X86VZeroUpper.cpp revision 226584
1226584Sdim//===-- X86VZeroUpper.cpp - AVX vzeroupper instruction inserter -----------===//
2226584Sdim//
3226584Sdim//                     The LLVM Compiler Infrastructure
4226584Sdim//
5226584Sdim// This file is distributed under the University of Illinois Open Source
6226584Sdim// License. See LICENSE.TXT for details.
7226584Sdim//
8226584Sdim//===----------------------------------------------------------------------===//
9226584Sdim//
10226584Sdim// This file defines the pass which inserts x86 AVX vzeroupper instructions
11226584Sdim// before calls to SSE encoded functions. This avoids transition latency
12226584Sdim// penalty when tranfering control between AVX encoded instructions and old
13226584Sdim// SSE encoding mode.
14226584Sdim//
15226584Sdim//===----------------------------------------------------------------------===//
16226584Sdim
17226584Sdim#define DEBUG_TYPE "x86-codegen"
18226584Sdim#include "X86.h"
19226584Sdim#include "X86InstrInfo.h"
20226584Sdim#include "llvm/ADT/Statistic.h"
21226584Sdim#include "llvm/CodeGen/MachineFunctionPass.h"
22226584Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
23226584Sdim#include "llvm/CodeGen/Passes.h"
24226584Sdim#include "llvm/GlobalValue.h"
25226584Sdim#include "llvm/Target/TargetInstrInfo.h"
26226584Sdimusing namespace llvm;
27226584Sdim
28226584SdimSTATISTIC(NumVZU, "Number of vzeroupper instructions inserted");
29226584Sdim
30226584Sdimnamespace {
31226584Sdim  struct VZeroUpperInserter : public MachineFunctionPass {
32226584Sdim    static char ID;
33226584Sdim    VZeroUpperInserter() : MachineFunctionPass(ID) {}
34226584Sdim
35226584Sdim    virtual bool runOnMachineFunction(MachineFunction &MF);
36226584Sdim
37226584Sdim    bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB);
38226584Sdim
39226584Sdim    virtual const char *getPassName() const { return "X86 vzeroupper inserter";}
40226584Sdim
41226584Sdim  private:
42226584Sdim    const TargetInstrInfo *TII; // Machine instruction info.
43226584Sdim    MachineBasicBlock *MBB;     // Current basic block
44226584Sdim  };
45226584Sdim  char VZeroUpperInserter::ID = 0;
46226584Sdim}
47226584Sdim
48226584SdimFunctionPass *llvm::createX86IssueVZeroUpperPass() {
49226584Sdim  return new VZeroUpperInserter();
50226584Sdim}
51226584Sdim
52226584Sdim/// runOnMachineFunction - Loop over all of the basic blocks, inserting
53226584Sdim/// vzero upper instructions before function calls.
54226584Sdimbool VZeroUpperInserter::runOnMachineFunction(MachineFunction &MF) {
55226584Sdim  TII = MF.getTarget().getInstrInfo();
56226584Sdim  bool Changed = false;
57226584Sdim
58226584Sdim  // Process any unreachable blocks in arbitrary order now.
59226584Sdim  for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB)
60226584Sdim    Changed |= processBasicBlock(MF, *BB);
61226584Sdim
62226584Sdim  return Changed;
63226584Sdim}
64226584Sdim
65226584Sdimstatic bool isCallToModuleFn(const MachineInstr *MI) {
66226584Sdim  assert(MI->getDesc().isCall() && "Isn't a call instruction");
67226584Sdim
68226584Sdim  for (int i = 0, e = MI->getNumOperands(); i != e; ++i) {
69226584Sdim    const MachineOperand &MO = MI->getOperand(i);
70226584Sdim
71226584Sdim    if (!MO.isGlobal())
72226584Sdim      continue;
73226584Sdim
74226584Sdim    const GlobalValue *GV = MO.getGlobal();
75226584Sdim    GlobalValue::LinkageTypes LT = GV->getLinkage();
76226584Sdim    if (GV->isInternalLinkage(LT) || GV->isPrivateLinkage(LT) ||
77226584Sdim        (GV->isExternalLinkage(LT) && !GV->isDeclaration()))
78226584Sdim      return true;
79226584Sdim
80226584Sdim    return false;
81226584Sdim  }
82226584Sdim  return false;
83226584Sdim}
84226584Sdim
85226584Sdim/// processBasicBlock - Loop over all of the instructions in the basic block,
86226584Sdim/// inserting vzero upper instructions before function calls.
87226584Sdimbool VZeroUpperInserter::processBasicBlock(MachineFunction &MF,
88226584Sdim                                           MachineBasicBlock &BB) {
89226584Sdim  bool Changed = false;
90226584Sdim  MBB = &BB;
91226584Sdim
92226584Sdim  for (MachineBasicBlock::iterator I = BB.begin(); I != BB.end(); ++I) {
93226584Sdim    MachineInstr *MI = I;
94226584Sdim    DebugLoc dl = I->getDebugLoc();
95226584Sdim
96226584Sdim    // Insert a vzeroupper instruction before each control transfer
97226584Sdim    // to functions outside this module
98226584Sdim    if (MI->getDesc().isCall() && !isCallToModuleFn(MI)) {
99226584Sdim      BuildMI(*MBB, I, dl, TII->get(X86::VZEROUPPER));
100226584Sdim      ++NumVZU;
101226584Sdim    }
102226584Sdim  }
103226584Sdim
104226584Sdim  return Changed;
105226584Sdim}
106