1 //===-- X86VZeroUpper.cpp - AVX vzeroupper instruction inserter -----------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the pass which inserts x86 AVX vzeroupper instructions
11 // before calls to SSE encoded functions. This avoids transition latency
12 // penalty when tranfering control between AVX encoded instructions and old
13 // SSE encoding mode.
14 //
15 //===----------------------------------------------------------------------===//
16
17 #define DEBUG_TYPE "x86-codegen"
18 #include "X86.h"
19 #include "X86InstrInfo.h"
20 #include "llvm/ADT/Statistic.h"
21 #include "llvm/CodeGen/MachineFunctionPass.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/Passes.h"
24 #include "llvm/GlobalValue.h"
25 #include "llvm/Target/TargetInstrInfo.h"
26 using namespace llvm;
27
28 STATISTIC(NumVZU, "Number of vzeroupper instructions inserted");
29
30 namespace {
31 struct VZeroUpperInserter : public MachineFunctionPass {
32 static char ID;
VZeroUpperInserter__anonf1d3c4110111::VZeroUpperInserter33 VZeroUpperInserter() : MachineFunctionPass(ID) {}
34
35 virtual bool runOnMachineFunction(MachineFunction &MF);
36
37 bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB);
38
getPassName__anonf1d3c4110111::VZeroUpperInserter39 virtual const char *getPassName() const { return "X86 vzeroupper inserter";}
40
41 private:
42 const TargetInstrInfo *TII; // Machine instruction info.
43 MachineBasicBlock *MBB; // Current basic block
44 };
45 char VZeroUpperInserter::ID = 0;
46 }
47
createX86IssueVZeroUpperPass()48 FunctionPass *llvm::createX86IssueVZeroUpperPass() {
49 return new VZeroUpperInserter();
50 }
51
52 /// runOnMachineFunction - Loop over all of the basic blocks, inserting
53 /// vzero upper instructions before function calls.
runOnMachineFunction(MachineFunction & MF)54 bool VZeroUpperInserter::runOnMachineFunction(MachineFunction &MF) {
55 TII = MF.getTarget().getInstrInfo();
56 bool Changed = false;
57
58 // Process any unreachable blocks in arbitrary order now.
59 for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB)
60 Changed |= processBasicBlock(MF, *BB);
61
62 return Changed;
63 }
64
isCallToModuleFn(const MachineInstr * MI)65 static bool isCallToModuleFn(const MachineInstr *MI) {
66 assert(MI->getDesc().isCall() && "Isn't a call instruction");
67
68 for (int i = 0, e = MI->getNumOperands(); i != e; ++i) {
69 const MachineOperand &MO = MI->getOperand(i);
70
71 if (!MO.isGlobal())
72 continue;
73
74 const GlobalValue *GV = MO.getGlobal();
75 GlobalValue::LinkageTypes LT = GV->getLinkage();
76 if (GV->isInternalLinkage(LT) || GV->isPrivateLinkage(LT) ||
77 (GV->isExternalLinkage(LT) && !GV->isDeclaration()))
78 return true;
79
80 return false;
81 }
82 return false;
83 }
84
85 /// processBasicBlock - Loop over all of the instructions in the basic block,
86 /// inserting vzero upper instructions before function calls.
processBasicBlock(MachineFunction & MF,MachineBasicBlock & BB)87 bool VZeroUpperInserter::processBasicBlock(MachineFunction &MF,
88 MachineBasicBlock &BB) {
89 bool Changed = false;
90 MBB = &BB;
91
92 for (MachineBasicBlock::iterator I = BB.begin(); I != BB.end(); ++I) {
93 MachineInstr *MI = I;
94 DebugLoc dl = I->getDebugLoc();
95
96 // Insert a vzeroupper instruction before each control transfer
97 // to functions outside this module
98 if (MI->getDesc().isCall() && !isCallToModuleFn(MI)) {
99 BuildMI(*MBB, I, dl, TII->get(X86::VZEROUPPER));
100 ++NumVZU;
101 }
102 }
103
104 return Changed;
105 }
106