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; 33 VZeroUpperInserter() : MachineFunctionPass(ID) {} 34 35 virtual bool runOnMachineFunction(MachineFunction &MF); 36 37 bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB); 38 39 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 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. 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 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. 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