30#define FIXUPLEA_DESC "X86 LEA Fixup"
31#define FIXUPLEA_NAME "x86-fixup-leas"
33#define DEBUG_TYPE FIXUPLEA_NAME
35STATISTIC(NumLEAs,
"Number of LEA instructions created");
39 enum RegUsageState { RU_NotUsed, RU_Write, RU_Read };
47 MachineBasicBlock &
MBB);
54 MachineBasicBlock &
MBB);
59 MachineBasicBlock &
MBB);
74 MachineBasicBlock &
MBB,
bool OptIncDec);
79 MachineBasicBlock &
MBB,
bool OptIncDec,
80 bool UseLEAForSP)
const;
94 MachineBasicBlock &
MBB)
const;
103 bool &AluDestRef, MachineOperand **KilledBase,
104 MachineOperand **KilledIndex)
const;
115 MachineBasicBlock &
MBB);
120 MachineInstr *postRAConvertToLEA(MachineBasicBlock &
MBB,
124 FixupLEAsImpl(ProfileSummaryInfo *PSI, MachineBlockFrequencyInfo *MBFI)
125 : PSI(PSI), MBFI(MBFI) {}
130 bool runOnMachineFunction(MachineFunction &MF);
133 TargetSchedModel TSM;
134 const X86InstrInfo *TII =
nullptr;
135 const X86RegisterInfo *TRI =
nullptr;
136 ProfileSummaryInfo *PSI;
137 MachineBlockFrequencyInfo *MBFI;
144 StringRef getPassName()
const override {
return FIXUPLEA_DESC; }
146 FixupLEAsLegacy() : MachineFunctionPass(ID) {}
148 bool runOnMachineFunction(MachineFunction &MF)
override;
151 MachineFunctionProperties getRequiredProperties()
const override {
152 return MachineFunctionProperties().setNoVRegs();
155 void getAnalysisUsage(AnalysisUsage &AU)
const override {
157 AU.
addRequired<LazyMachineBlockFrequencyInfoPass>();
163char FixupLEAsLegacy::ID = 0;
171 switch (
MI.getOpcode()) {
174 const MachineOperand &Src = MI.getOperand(1);
175 const MachineOperand &Dest = MI.getOperand(0);
176 MachineInstr *NewMI =
177 BuildMI(MBB, MBBI, MI.getDebugLoc(),
178 TII->get(MI.getOpcode() == X86::MOV32rr ? X86::LEA32r
190 if (!
MI.isConvertibleTo3Addr())
193 switch (
MI.getOpcode()) {
198 case X86::ADD64ri32_DB:
200 case X86::ADD32ri_DB:
201 if (!MI.getOperand(2).isImm()) {
214 case X86::ADD64rr_DB:
216 case X86::ADD32rr_DB:
220 return TII->convertToThreeAddress(
MI,
nullptr,
nullptr);
224 return new FixupLEAsLegacy();
228 return Opcode == X86::LEA32r || Opcode == X86::LEA64r ||
229 Opcode == X86::LEA64_32r;
234 bool IsSlowLEA =
ST.slowLEA();
235 bool IsSlow3OpsLEA =
ST.slow3OpsLEA();
236 bool LEAUsesAG =
ST.leaUsesAG();
239 bool UseLEAForSP =
ST.useLeaForSP();
242 TII =
ST.getInstrInfo();
243 TRI =
ST.getRegisterInfo();
246 for (MachineBasicBlock &
MBB : MF) {
248 bool OptIncDecPerBB =
251 if (!
isLEA(
I->getOpcode()))
254 if (optTwoAddrLEA(
I,
MBB, OptIncDecPerBB, UseLEAForSP))
258 processInstructionForSlowLEA(
I,
MBB);
259 else if (IsSlow3OpsLEA)
260 processInstrForSlow3OpLEA(
I,
MBB, OptIncDecPerBB);
267 processInstruction(
I,
MBB);
276FixupLEAsImpl::RegUsageState
278 RegUsageState
RegUsage = RU_NotUsed;
279 MachineInstr &
MI = *
I;
281 for (
const MachineOperand &MO :
MI.operands()) {
282 if (MO.isReg() && MO.getReg() ==
p.getReg()) {
297 if (
I ==
MBB.begin()) {
298 if (
MBB.isPredecessor(&
MBB)) {
310 int InstrDistance = 1;
312 static const int INSTR_DISTANCE_THRESHOLD = 5;
317 while (Found &&
I != CurInst) {
318 if (CurInst->isCall() || CurInst->isInlineAsm())
320 if (InstrDistance > INSTR_DISTANCE_THRESHOLD)
322 if (usesRegister(p, CurInst) == RU_Write) {
325 InstrDistance += TSM.computeInstrLatency(&*CurInst);
332 return Reg == X86::EBP ||
Reg == X86::RBP ||
333 Reg == X86::R13D ||
Reg == X86::R13;
343 Index.getReg().isValid();
384 return X86::ADD64ri32;
394 return IsINC ? X86::INC32r : X86::DEC32r;
396 return IsINC ? X86::INC64r : X86::DEC64r;
402 MachineBasicBlock &
MBB)
const {
403 const int InstrDistanceThreshold = 5;
404 int InstrDistance = 1;
407 unsigned LEAOpcode =
I->getOpcode();
410 Register DestReg =
I->getOperand(0).getReg();
412 while (CurInst !=
MBB.
end()) {
413 if (CurInst->isCall() || CurInst->isInlineAsm())
415 if (InstrDistance > InstrDistanceThreshold)
419 for (
unsigned I = 0,
E = CurInst->getNumOperands();
I !=
E; ++
I) {
420 MachineOperand &Opnd = CurInst->getOperand(
I);
422 if (Opnd.
getReg() == DestReg) {
426 unsigned AluOpcode = CurInst->getOpcode();
427 if (AluOpcode != AddOpcode && AluOpcode != SubOpcode)
430 MachineOperand &Opnd2 = CurInst->getOperand(3 -
I);
431 MachineOperand AluDest = CurInst->getOperand(0);
438 if (!CurInst->registerDefIsDead(X86::EFLAGS,
TRI))
443 if (
TRI->regsOverlap(DestReg, Opnd.
getReg()))
456 bool &BaseIndexDef,
bool &AluDestRef,
457 MachineOperand **KilledBase,
458 MachineOperand **KilledIndex)
const {
459 BaseIndexDef = AluDestRef =
false;
460 *KilledBase = *KilledIndex =
nullptr;
463 Register AluDestReg = AluI->getOperand(0).getReg();
466 for (MachineOperand &Opnd : CurInst.operands()) {
470 if (
TRI->regsOverlap(
Reg, AluDestReg))
472 if (
TRI->regsOverlap(
Reg, BaseReg)) {
478 if (
TRI->regsOverlap(
Reg, IndexReg)) {
482 *KilledIndex = &Opnd;
489 MachineBasicBlock &
MBB)
const {
496 bool BaseIndexDef, AluDestRef;
497 MachineOperand *KilledBase, *KilledIndex;
498 checkRegUsage(
I, AluI, BaseIndexDef, AluDestRef, &KilledBase, &KilledIndex);
505 KilledBase = KilledIndex =
nullptr;
509 Register AluDestReg = AluI->getOperand(0).getReg();
512 if (
I->getOpcode() == X86::LEA64_32r) {
513 BaseReg =
TRI->getSubReg(BaseReg, X86::sub_32bit);
514 IndexReg =
TRI->getSubReg(IndexReg, X86::sub_32bit);
516 if (AluDestReg == IndexReg) {
517 if (BaseReg == IndexReg)
522 if (BaseReg == IndexReg)
523 KilledBase =
nullptr;
526 MachineInstr *NewMI1, *NewMI2;
527 unsigned NewOpcode = AluI->getOpcode();
528 NewMI1 =
BuildMI(
MBB, InsertPos, AluI->getDebugLoc(),
TII->get(NewOpcode),
533 NewMI2 =
BuildMI(
MBB, InsertPos, AluI->getDebugLoc(),
TII->get(NewOpcode),
553 MachineBasicBlock &
MBB,
bool OptIncDec,
554 bool UseLEAForSP)
const {
555 MachineInstr &
MI = *
I;
573 if (UseLEAForSP && (DestReg == X86::ESP || DestReg == X86::RSP))
577 if (
MI.getOpcode() == X86::LEA64_32r) {
579 BaseReg =
TRI->getSubReg(BaseReg, X86::sub_32bit);
581 IndexReg =
TRI->getSubReg(IndexReg, X86::sub_32bit);
584 MachineInstr *NewMI =
nullptr;
590 (DestReg == BaseReg || DestReg == IndexReg)) {
592 if (DestReg != BaseReg)
595 if (
MI.getOpcode() == X86::LEA64_32r) {
605 }
else if (DestReg == BaseReg && !IndexReg) {
613 if (OptIncDec && (Disp.
getImm() == 1 || Disp.
getImm() == -1)) {
614 bool IsINC = Disp.
getImm() == 1;
617 if (
MI.getOpcode() == X86::LEA64_32r) {
627 if (
MI.getOpcode() == X86::LEA64_32r) {
642 return optLEAALU(
I,
MBB);
653 MachineBasicBlock &
MBB) {
655 MachineInstr &
MI = *
I;
656 const MCInstrDesc &
Desc =
MI.getDesc();
658 if (AddrOffset >= 0) {
661 if (
p.isReg() &&
p.getReg() != X86::ESP) {
662 seekLEAFixup(p,
I,
MBB);
665 if (
q.isReg() &&
q.getReg() != X86::ESP) {
666 seekLEAFixup(q,
I,
MBB);
671void FixupLEAsImpl::seekLEAFixup(MachineOperand &p,
673 MachineBasicBlock &
MBB) {
676 MachineInstr *NewMI = postRAConvertToLEA(
MBB, MBI);
679 LLVM_DEBUG(
dbgs() <<
"FixLEA: Candidate to replace:"; MBI->dump(););
686 processInstruction(J,
MBB);
692 MachineBasicBlock &
MBB) {
693 MachineInstr &
MI = *
I;
694 const unsigned Opcode =
MI.getOpcode();
696 const MachineOperand &Dst =
MI.getOperand(0);
710 if ((!SrcR1 || SrcR1 != DstR) && (!SrcR2 || SrcR2 != DstR))
716 MachineInstr *NewMI =
nullptr;
718 if (SrcR1 && SrcR2) {
720 const MachineOperand &Src = SrcR1 == DstR ?
Index :
Base;
726 if (
Offset.getImm() != 0) {
727 const MCInstrDesc &ADDri =
729 const MachineOperand &SrcR = SrcR1 == DstR ?
Base :
Index;
743 MachineBasicBlock &
MBB,
745 MachineInstr &
MI = *
I;
746 const unsigned LEAOpcode =
MI.getOpcode();
748 const MachineOperand &Dest =
MI.getOperand(0);
765 if (
MI.getOpcode() == X86::LEA64_32r) {
767 BaseReg =
TRI->getSubReg(BaseReg, X86::sub_32bit);
769 IndexReg =
TRI->getSubReg(IndexReg, X86::sub_32bit);
772 bool IsScale1 = Scale.
getImm() == 1;
778 if (IsInefficientBase && DestReg == BaseReg && !IsScale1)
784 MachineInstr *NewMI =
nullptr;
785 bool BaseOrIndexIsDst = DestReg ==
BaseReg || DestReg == IndexReg;
792 if (IsScale1 && BaseReg == IndexReg &&
807 }
else if (IsScale1 && BaseOrIndexIsDst) {
814 if (DestReg != BaseReg)
817 if (
MI.getOpcode() == X86::LEA64_32r) {
829 }
else if (!IsInefficientBase || (!IsInefficientIndex && IsScale1)) {
836 .
add(IsInefficientBase ? Index :
Base)
838 .
add(IsInefficientBase ?
Base : Index)
849 if (OptIncDec &&
Offset.isImm() &&
872 assert(DestReg != BaseReg &&
"DestReg == BaseReg should be handled already!");
873 assert(IsInefficientBase &&
"efficient base should be handled already!");
876 if (LEAOpcode == X86::LEA64_32r)
919bool FixupLEAsLegacy::runOnMachineFunction(MachineFunction &MF) {
923 auto *PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
924 auto *MBFI = (PSI && PSI->hasProfileSummary())
925 ? &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI()
927 FixupLEAsImpl PassImpl(PSI, MBFI);
928 return PassImpl.runOnMachineFunction(MF);
935 .getCachedResult<ProfileSummaryAnalysis>(
942 FixupLEAsImpl PassImpl(PSI, MBFI);
943 bool Changed = PassImpl.runOnMachineFunction(MF);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
===- LazyMachineBlockFrequencyInfo.h - Lazy Block Frequency -*- C++ -*–===//
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static unsigned getINCDECFromLEA(unsigned LEAOpcode, bool IsINC)
static bool isLEA(unsigned Opcode)
static bool hasLEAOffset(const MachineOperand &Offset)
static bool isInefficientLEAReg(Register Reg)
static bool hasInefficientLEABaseReg(const MachineOperand &Base, const MachineOperand &Index)
Returns true if this LEA uses base and index registers, and the base register is known to be ineffici...
static unsigned getADDriFromLEA(unsigned LEAOpcode, const MachineOperand &Offset)
static bool getPreviousInstr(MachineBasicBlock::iterator &I, MachineBasicBlock &MBB)
getPreviousInstr - Given a reference to an instruction in a basic block, return a reference to the pr...
static unsigned getADDrrFromLEA(unsigned LEAOpcode)
static unsigned getSUBrrFromLEA(unsigned LEAOpcode)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
Represents analyses that only rely on functions' control flow.
FunctionPass class - This class is used to implement most global optimizations.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
Module * getParent()
Get the module that this global value is contained inside of...
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
Emit instructions to copy a pair of physical registers.
LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineInstrBundleIterator< MachineInstr > iterator
@ LQR_Dead
Register is known to be fully dead.
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
void substituteDebugValuesForInst(const MachineInstr &Old, MachineInstr &New, unsigned MaxOperand=UINT_MAX)
Create substitutions for any tracked values in Old, to point at New.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
LLVM_ABI void dump() const
LLVM_ABI bool addRegisterDead(Register Reg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI defined a register without a use.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
void setIsKill(bool Val=true)
Register getReg() const
getReg - Returns the register number.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Analysis providing profile information.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
LLVM_ABI void init(const TargetSubtargetInfo *TSInfo, bool EnableSModel=true, bool EnableSItins=true)
Initialize the machine model for instruction scheduling.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
int getMemoryOperandNo(uint64_t TSFlags)
unsigned getOperandBias(const MCInstrDesc &Desc)
Compute whether all of the def operands are repeated in the uses and therefore should be skipped.
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
OuterAnalysisManagerProxy< ModuleAnalysisManager, MachineFunction > ModuleAnalysisManagerMachineFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI bool shouldOptimizeForSize(const MachineFunction *MF, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo *BFI, PGSOQueryType QueryType=PGSOQueryType::Other)
Returns true if machine function MF is suggested to be size-optimized based on the profile.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionPass * createX86FixupLEAsLegacyPass()
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.