30 #define DEBUG_TYPE "x86-vzeroupper"
32 STATISTIC(NumVZU,
"Number of vzeroupper instructions inserted");
45 StringRef getPassName()
const override {
return "X86 vzeroupper inserter"; }
54 typedef enum { PASS_THROUGH, EXITS_CLEAN, EXITS_DIRTY } BlockExitState;
55 static const char* getBlockExitStateName(BlockExitState
ST);
76 BlockState() : ExitState(PASS_THROUGH), AddedToDirtySuccessors(
false) {}
77 BlockExitState ExitState;
78 bool AddedToDirtySuccessors;
84 BlockStateMap BlockStates;
85 DirtySuccessorsWorkList DirtySuccessors;
97 return new VZeroUpperInserter();
100 const char* VZeroUpperInserter::getBlockExitStateName(BlockExitState
ST) {
102 case PASS_THROUGH:
return "Pass-through";
103 case EXITS_DIRTY:
return "Exits-dirty";
104 case EXITS_CLEAN:
return "Exits-clean";
110 return (Reg >= X86::YMM0 && Reg <= X86::YMM15);
123 for (
unsigned reg = X86::YMM0; reg <= X86::YMM15; ++reg) {
146 assert(MI.
isCall() &&
"Can only be called on call instructions.");
150 for (
unsigned reg = X86::YMM0; reg <= X86::YMM15; ++reg) {
151 if (MO.clobbersPhysReg(reg))
162 BuildMI(MBB, I, dl,
TII->get(X86::VZEROUPPER));
164 EverMadeChange =
true;
169 if (!BlockStates[MBB.
getNumber()].AddedToDirtySuccessors) {
170 DirtySuccessors.push_back(&MBB);
171 BlockStates[MBB.
getNumber()].AddedToDirtySuccessors =
true;
181 BlockExitState CurState = PASS_THROUGH;
182 BlockStates[MBB.
getNumber()].FirstUnguardedCall = MBB.
end();
187 bool IsReturnFromX86INTR = IsX86INTR &&
MI.isReturn();
188 bool IsControlFlow =
MI.isCall() ||
MI.isReturn();
191 if (
MI.getOpcode() == X86::VZEROALL ||
MI.getOpcode() == X86::VZEROUPPER) {
192 CurState = EXITS_CLEAN;
197 if ((!IsControlFlow || IsReturnFromX86INTR) && CurState == EXITS_DIRTY)
203 CurState = EXITS_DIRTY;
209 if (!IsControlFlow || IsReturnFromX86INTR)
227 if (CurState == EXITS_DIRTY) {
231 insertVZeroUpper(
MI, MBB);
232 CurState = EXITS_CLEAN;
233 }
else if (CurState == PASS_THROUGH) {
239 BlockStates[MBB.getNumber()].FirstUnguardedCall =
MI;
240 CurState = EXITS_CLEAN;
244 DEBUG(
dbgs() <<
"MBB #" << MBB.getNumber() <<
" exit state: "
245 << getBlockExitStateName(CurState) <<
'\n');
247 if (CurState == EXITS_DIRTY)
251 addDirtySuccessor(**SI);
253 BlockStates[MBB.getNumber()].ExitState = CurState;
264 EverMadeChange =
false;
272 bool YMMUsed = FnHasLiveInYmm;
287 assert(BlockStates.empty() && DirtySuccessors.empty() &&
288 "X86VZeroUpper state should be clear");
295 processBasicBlock(MBB);
300 addDirtySuccessor(MF.front());
305 while (!DirtySuccessors.empty()) {
307 DirtySuccessors.pop_back();
308 BlockState &BBState = BlockStates[MBB.
getNumber()];
312 if (BBState.FirstUnguardedCall != MBB.
end())
313 insertVZeroUpper(BBState.FirstUnguardedCall, MBB);
318 if (BBState.ExitState == PASS_THROUGH) {
320 <<
" was Pass-through, is now Dirty-out.\n");
322 addDirtySuccessor(*Succ);
327 return EverMadeChange;
STATISTIC(NumFunctions,"Total number of functions")
livein_iterator livein_end() const
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
const X86InstrInfo * getInstrInfo() const override
bool hasFastPartialYMMWrite() const
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
FunctionPass * createX86IssueVZeroUpperPass()
This pass inserts AVX vzeroupper instructions before each call to avoid transition penalty between fu...
const MCPhysReg * iterator
iterator_range< mop_iterator > operands()
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
iterator_range< succ_iterator > successors()
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
X86_INTR - x86 hardware interrupt context.
std::vector< MachineBasicBlock * >::iterator succ_iterator
iterator begin() const
begin/end - Return all of the registers in this class.
Reg
All possible values of the reg field in the ModR/M byte.
Function Alias Analysis false
static bool hasYmmReg(MachineInstr &MI)
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
TargetInstrInfo - Interface to description of machine instruction set.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static bool checkFnHasLiveInYmm(MachineRegisterInfo &MRI)
unsigned const MachineRegisterInfo * MRI
FunctionPass class - This class is used to implement most global optimizations.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
livein_iterator livein_begin() const
static bool isYmmReg(unsigned Reg)
static bool callClobbersAnyYmmReg(MachineInstr &MI)
Check if any YMM register will be clobbered by this instruction.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static bool clobbersPhysReg(const uint32_t *RegMask, unsigned PhysReg)
clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
MachineFunctionProperties & set(Property P)
Representation of each machine instruction.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
bool isCall(QueryType Type=AnyInBundle) const
std::vector< std::pair< unsigned, unsigned > >::const_iterator livein_iterator
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool clobbersAllYmmRegs(const MachineOperand &MO)
StringRef - Represent a constant reference to a string, i.e.
bool reg_nodbg_empty(unsigned RegNo) const
reg_nodbg_empty - Return true if the only instructions using or defining Reg are Debug instructions...
Properties which a MachineFunction may have at a given point in time.