llvm-6502/lib/Target/X86/X86VZeroUpper.cpp
Bruno Cardoso Lopes 3bde6fe0df Introduce a pass to insert vzeroupper instructions to avoid AVX to
SSE transition penalty. The pass is enabled through the "x86-use-vzeroupper"
llc command line option. This is only the first step (very naive and
conservative one) to sketch out the idea, but proper DFA is coming next
to allow smarter decisions. Comments and ideas now and in further commits
will be very appreciated.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@138317 91177308-0d34-0410-b5e6-96231b3b80d8
2011-08-23 01:14:17 +00:00

106 lines
3.3 KiB
C++

//===-- X86VZeroUpper.cpp - AVX vzeroupper instruction inserter -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the pass which inserts x86 AVX vzeroupper instructions
// before calls to SSE encoded functions. This avoids transition latency
// penalty when tranfering control between AVX encoded instructions and old
// SSE encoding mode.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "x86-codegen"
#include "X86.h"
#include "X86InstrInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/GlobalValue.h"
#include "llvm/Target/TargetInstrInfo.h"
using namespace llvm;
STATISTIC(NumVZU, "Number of vzeroupper instructions inserted");
namespace {
struct VZeroUpperInserter : public MachineFunctionPass {
static char ID;
VZeroUpperInserter() : MachineFunctionPass(ID) {}
virtual bool runOnMachineFunction(MachineFunction &MF);
bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB);
virtual const char *getPassName() const { return "X86 vzeroupper inserter";}
private:
const TargetInstrInfo *TII; // Machine instruction info.
MachineBasicBlock *MBB; // Current basic block
};
char VZeroUpperInserter::ID = 0;
}
FunctionPass *llvm::createX86IssueVZeroUpperPass() {
return new VZeroUpperInserter();
}
/// runOnMachineFunction - Loop over all of the basic blocks, inserting
/// vzero upper instructions before function calls.
bool VZeroUpperInserter::runOnMachineFunction(MachineFunction &MF) {
TII = MF.getTarget().getInstrInfo();
bool Changed = false;
// Process any unreachable blocks in arbitrary order now.
for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB)
Changed |= processBasicBlock(MF, *BB);
return Changed;
}
bool isCallToModuleFn(const MachineInstr *MI) {
assert(MI->getDesc().isCall() && "Isn't a call instruction");
for (int i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
if (!MO.isGlobal())
continue;
const GlobalValue *GV = MO.getGlobal();
GlobalValue::LinkageTypes LT = GV->getLinkage();
if (GV->isInternalLinkage(LT) || GV->isPrivateLinkage(LT) ||
(GV->isExternalLinkage(LT) && !GV->isDeclaration()))
return true;
return false;
}
return false;
}
/// processBasicBlock - Loop over all of the instructions in the basic block,
/// inserting vzero upper instructions before function calls.
bool VZeroUpperInserter::processBasicBlock(MachineFunction &MF,
MachineBasicBlock &BB) {
bool Changed = false;
MBB = &BB;
for (MachineBasicBlock::iterator I = BB.begin(); I != BB.end(); ++I) {
MachineInstr *MI = I;
DebugLoc dl = I->getDebugLoc();
// Insert a vzeroupper instruction before each control transfer
// to functions outside this module
if (MI->getDesc().isCall() && !isCallToModuleFn(MI)) {
BuildMI(*MBB, I, dl, TII->get(X86::VZEROUPPER));
++NumVZU;
}
}
return Changed;
}