Home | History | Annotate | Download | only in X86
      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