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