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 };
80 bool UseLEAForSP)
const;
138 MachineFunctionProperties::Property::NoVRegs);
154char FixupLEAPass::ID = 0;
162 switch (
MI.getOpcode()) {
169 TII->get(
MI.getOpcode() == X86::MOV32rr ? X86::LEA32r
181 if (!
MI.isConvertibleTo3Addr())
184 switch (
MI.getOpcode()) {
190 case X86::ADD64ri32_DB:
191 case X86::ADD64ri8_DB:
194 case X86::ADD32ri_DB:
195 case X86::ADD32ri8_DB:
196 if (!
MI.getOperand(2).isImm()) {
209 case X86::ADD64rr_DB:
211 case X86::ADD32rr_DB:
215 return TII->convertToThreeAddress(
MI,
nullptr,
nullptr);
221 return Opcode == X86::LEA32r || Opcode == X86::LEA64r ||
222 Opcode == X86::LEA64_32r;
230 bool IsSlowLEA =
ST.slowLEA();
231 bool IsSlow3OpsLEA =
ST.slow3OpsLEA();
232 bool LEAUsesAG =
ST.leaUsesAG();
235 bool UseLEAForSP =
ST.useLeaForSP();
238 TII =
ST.getInstrInfo();
239 TRI =
ST.getRegisterInfo();
240 auto *PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
241 auto *MBFI = (PSI && PSI->hasProfileSummary())
242 ? &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI()
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);
276FixupLEAPass::RegUsageState
278 RegUsageState
RegUsage = RU_NotUsed;
282 if (MO.isReg() && MO.getReg() ==
p.getReg()) {
311 int InstrDistance = 1;
313 static const int INSTR_DISTANCE_THRESHOLD = 5;
318 while (Found &&
I != CurInst) {
319 if (CurInst->isCall() || CurInst->isInlineAsm())
321 if (InstrDistance > INSTR_DISTANCE_THRESHOLD)
323 if (usesRegister(p, CurInst) == RU_Write) {
326 InstrDistance += TSM.computeInstrLatency(&*CurInst);
333 return Reg == X86::EBP || Reg == X86::RBP ||
334 Reg == X86::R13D || Reg == X86::R13;
344 Index.getReg() != X86::NoRegister;
377 bool IsInt8 =
Offset.isImm() && isInt<8>(
Offset.getImm());
383 return IsInt8 ? X86::ADD32ri8 : X86::ADD32ri;
385 return IsInt8 ? X86::ADD64ri8 : X86::ADD64ri32;
395 return IsINC ? X86::INC32r : X86::DEC32r;
397 return IsINC ? X86::INC64r : X86::DEC64r;
404 const int InstrDistanceThreshold = 5;
405 int InstrDistance = 1;
408 unsigned LEAOpcode =
I->getOpcode();
411 Register DestReg =
I->getOperand(0).getReg();
413 while (CurInst !=
MBB.
end()) {
414 if (CurInst->isCall() || CurInst->isInlineAsm())
416 if (InstrDistance > InstrDistanceThreshold)
420 for (
unsigned I = 0,
E = CurInst->getNumOperands();
I !=
E; ++
I) {
423 if (Opnd.
getReg() == DestReg) {
427 unsigned AluOpcode = CurInst->getOpcode();
428 if (AluOpcode != AddOpcode && AluOpcode != SubOpcode)
439 if (!CurInst->registerDefIsDead(X86::EFLAGS,
TRI))
444 if (
TRI->regsOverlap(DestReg, Opnd.
getReg()))
457 bool &BaseIndexDef,
bool &AluDestRef,
460 BaseIndexDef = AluDestRef =
false;
461 *KilledBase = *KilledIndex =
nullptr;
464 Register AluDestReg = AluI->getOperand(0).getReg();
467 while (CurInst != AluI) {
468 for (
unsigned I = 0,
E = CurInst->getNumOperands();
I !=
E; ++
I) {
473 if (
TRI->regsOverlap(Reg, AluDestReg))
475 if (
TRI->regsOverlap(Reg, BaseReg)) {
481 if (
TRI->regsOverlap(Reg, IndexReg)) {
485 *KilledIndex = &Opnd;
500 bool BaseIndexDef, AluDestRef;
502 checkRegUsage(
I, AluI, BaseIndexDef, AluDestRef, &KilledBase, &KilledIndex);
509 KilledBase = KilledIndex =
nullptr;
513 Register AluDestReg = AluI->getOperand(0).getReg();
516 if (
I->getOpcode() == X86::LEA64_32r) {
517 BaseReg =
TRI->getSubReg(BaseReg, X86::sub_32bit);
518 IndexReg =
TRI->getSubReg(IndexReg, X86::sub_32bit);
520 if (AluDestReg == IndexReg) {
521 if (BaseReg == IndexReg)
526 if (BaseReg == IndexReg)
527 KilledBase =
nullptr;
531 unsigned NewOpcode = AluI->getOpcode();
532 NewMI1 =
BuildMI(
MBB, InsertPos, AluI->getDebugLoc(),
TII->get(NewOpcode),
537 NewMI2 =
BuildMI(
MBB, InsertPos, AluI->getDebugLoc(),
TII->get(NewOpcode),
558 bool UseLEAForSP)
const {
577 if (UseLEAForSP && (DestReg == X86::ESP || DestReg == X86::RSP))
581 if (
MI.getOpcode() == X86::LEA64_32r) {
583 BaseReg =
TRI->getSubReg(BaseReg, X86::sub_32bit);
585 IndexReg =
TRI->getSubReg(IndexReg, X86::sub_32bit);
593 if (BaseReg != 0 && IndexReg != 0 && Disp.
getImm() == 0 &&
594 (DestReg == BaseReg || DestReg == IndexReg)) {
596 if (DestReg != BaseReg)
599 if (
MI.getOpcode() == X86::LEA64_32r) {
609 }
else if (DestReg == BaseReg && IndexReg == 0) {
617 if (OptIncDec && (Disp.
getImm() == 1 || Disp.
getImm() == -1)) {
618 bool IsINC = Disp.
getImm() == 1;
621 if (
MI.getOpcode() == X86::LEA64_32r) {
631 if (
MI.getOpcode() == X86::LEA64_32r) {
641 }
else if (BaseReg != 0 && IndexReg != 0 && Disp.
getImm() == 0) {
646 return optLEAALU(
I,
MBB);
662 if (AddrOffset >= 0) {
665 if (
p.isReg() &&
p.getReg() != X86::ESP) {
666 seekLEAFixup(p,
I,
MBB);
669 if (
q.isReg() &&
q.getReg() != X86::ESP) {
670 seekLEAFixup(q,
I,
MBB);
683 LLVM_DEBUG(
dbgs() <<
"FixLEA: Candidate to replace:"; MBI->dump(););
690 processInstruction(J,
MBB);
698 const unsigned Opcode =
MI.getOpcode();
714 if ((SrcR1 == 0 || SrcR1 != DstR) && (SrcR2 == 0 || SrcR2 != DstR))
722 if (SrcR1 != 0 && SrcR2 != 0) {
730 if (
Offset.getImm() != 0) {
750 const unsigned LEAOpcode =
MI.getOpcode();
762 Segment.
getReg() != X86::NoRegister)
769 if (
MI.getOpcode() == X86::LEA64_32r) {
771 BaseReg =
TRI->getSubReg(BaseReg, X86::sub_32bit);
773 IndexReg =
TRI->getSubReg(IndexReg, X86::sub_32bit);
776 bool IsScale1 = Scale.
getImm() == 1;
782 if (IsInefficientBase && DestReg == BaseReg && !IsScale1)
789 bool BaseOrIndexIsDst = DestReg == BaseReg || DestReg == IndexReg;
796 if (IsScale1 && BaseReg == IndexReg &&
811 }
else if (IsScale1 && BaseOrIndexIsDst) {
818 if (DestReg != BaseReg)
821 if (
MI.getOpcode() == X86::LEA64_32r) {
833 }
else if (!IsInefficientBase || (!IsInefficientIndex && IsScale1)) {
853 if (OptIncDec &&
Offset.isImm() &&
876 assert(DestReg != BaseReg &&
"DestReg == BaseReg should be handled already!");
877 assert(IsInefficientBase &&
"efficient base should be handled already!");
880 if (LEAOpcode == X86::LEA64_32r)
885 bool BIK =
Base.isKill() && BaseReg != IndexReg;
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
===- LazyMachineBlockFrequencyInfo.h - Lazy Block Frequency -*- C++ -*–===//
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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 hasInefficientLEABaseReg(const MachineOperand &Base, const MachineOperand &Index)
Returns true if this LEA uses base an index registers, and the base register is known to be inefficie...
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 bool isInefficientLEAReg(unsigned Reg)
static unsigned getSUBrrFromLEA(unsigned LEAOpcode)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
FunctionPass class - This class is used to implement most global optimizations.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc) const override
Emit instructions to copy a pair of physical registers.
This is an alternative analysis pass to MachineBlockFrequencyInfo.
Describe properties that are true of each instruction in the target description file.
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.
bool isPredecessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a predecessor of this block.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
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.
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
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.
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.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
Wrapper class representing virtual and physical registers.
StringRef - Represent a constant reference to a string, i.e.
Provide an instruction scheduling machine model to CodeGen passes.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
Reg
All possible values of the reg field in the ModR/M byte.
int getMemoryOperandNo(uint64_t TSFlags)
The function returns the MCInst operand # for the first field of the memory operand.
unsigned getOperandBias(const MCInstrDesc &Desc)
Compute whether all of the def operands are repeated in the uses and therefore should be skipped.
@ AddrSegmentReg
AddrSegmentReg - The operand # of the segment in the memory operand.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
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.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createX86FixupLEAs()
Return a pass that selectively replaces certain instructions (like add, sub, inc, dec,...
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.