30 #define DEBUG_TYPE "x86-vzeroupper"
32 STATISTIC(NumVZU,
"Number of vzeroupper instructions inserted");
41 const char *getPassName()
const override {
return "X86 vzeroupper inserter";}
50 typedef enum { PASS_THROUGH, EXITS_CLEAN, EXITS_DIRTY } BlockExitState;
51 static const char* getBlockExitStateName(BlockExitState
ST);
72 BlockState() : ExitState(PASS_THROUGH), AddedToDirtySuccessors(
false) {}
73 BlockExitState ExitState;
74 bool AddedToDirtySuccessors;
80 BlockStateMap BlockStates;
81 DirtySuccessorsWorkList DirtySuccessors;
92 return new VZeroUpperInserter();
95 const char* VZeroUpperInserter::getBlockExitStateName(BlockExitState
ST) {
97 case PASS_THROUGH:
return "Pass-through";
98 case EXITS_DIRTY:
return "Exits-dirty";
99 case EXITS_CLEAN:
return "Exits-clean";
105 return (Reg >= X86::YMM0 && Reg <= X86::YMM15);
118 for (
unsigned reg = X86::YMM0; reg <= X86::YMM15; ++reg) {
143 assert(MI->
isCall() &&
"Can only be called on call instructions.");
148 for (
unsigned reg = X86::YMM0; reg <= X86::YMM15; ++reg) {
160 BuildMI(MBB, I, dl,
TII->get(X86::VZEROUPPER));
162 EverMadeChange =
true;
167 if (!BlockStates[MBB.
getNumber()].AddedToDirtySuccessors) {
168 DirtySuccessors.push_back(&MBB);
169 BlockStates[MBB.
getNumber()].AddedToDirtySuccessors =
true;
179 BlockExitState CurState = PASS_THROUGH;
180 BlockStates[MBB.
getNumber()].FirstUnguardedCall = MBB.
end();
187 if (!isControlFlow && CurState == EXITS_DIRTY)
193 CurState = EXITS_DIRTY;
218 if (CurState == EXITS_DIRTY) {
222 insertVZeroUpper(I, MBB);
223 CurState = EXITS_CLEAN;
224 }
else if (CurState == PASS_THROUGH) {
230 BlockStates[MBB.
getNumber()].FirstUnguardedCall =
I;
231 CurState = EXITS_CLEAN;
236 << getBlockExitStateName(CurState) <<
'\n');
238 if (CurState == EXITS_DIRTY)
242 addDirtySuccessor(**SI);
244 BlockStates[MBB.
getNumber()].ExitState = CurState;
255 EverMadeChange =
false;
262 bool YMMUsed = FnHasLiveInYmm;
277 assert(BlockStates.empty() && DirtySuccessors.empty() &&
278 "X86VZeroUpper state should be clear");
285 processBasicBlock(MBB);
290 addDirtySuccessor(MF.front());
295 while (!DirtySuccessors.empty()) {
297 DirtySuccessors.pop_back();
298 BlockState &BBState = BlockStates[MBB.
getNumber()];
302 if (BBState.FirstUnguardedCall != MBB.
end())
303 insertVZeroUpper(BBState.FirstUnguardedCall, MBB);
308 if (BBState.ExitState == PASS_THROUGH) {
310 <<
" was Pass-through, is now Dirty-out.\n");
314 addDirtySuccessor(**SI);
319 return EverMadeChange;
STATISTIC(NumFunctions,"Total number of functions")
livein_iterator livein_end() const
int getNumber() const
getNumber - MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a M...
const X86InstrInfo * getInstrInfo() const override
FunctionPass * createX86IssueVZeroUpperPass()
createX86IssueVZeroUpperPass - This pass inserts AVX vzeroupper instructions before each call to avoi...
const MCPhysReg * iterator
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
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
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.
unsigned getNumOperands() const
Access to explicit operands of the instruction.
static bool hasYmmReg(MachineInstr *MI)
TargetInstrInfo - Interface to description of machine instruction set.
bundle_iterator< MachineInstr, instr_iterator > iterator
static bool checkFnHasLiveInYmm(MachineRegisterInfo &MRI)
bool isReturn(QueryType Type=AnyInBundle) const
const MachineOperand & getOperand(unsigned i) const
FunctionPass class - This class is used to implement most global optimizations.
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
BuildMI - Builder interface.
succ_iterator succ_begin()
bool isRegMask() const
isRegMask - Tests if this is a MO_RegisterMask operand.
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)
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.
Representation of each machine instruction.
static bool callClobbersAnyYmmReg(MachineInstr *MI)
clobbersAnyYmmReg() - Check if any YMM register will be clobbered by this 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
unsigned getReg() const
getReg - Returns the register number.
static bool clobbersAllYmmRegs(const MachineOperand &MO)
bool reg_nodbg_empty(unsigned RegNo) const
reg_nodbg_empty - Return true if the only instructions using or defining Reg are Debug instructions...