X86VZeroUpper.cpp revision 3bde6fe0df05558b89e7edfe48ac05da59beb81a
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"
26using namespace llvm;
27
28STATISTIC(NumVZU, "Number of vzeroupper instructions inserted");
29
30namespace {
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
48FunctionPass *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.
54bool 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
65bool 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.
87bool 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