28 #define FIXUPLEA_DESC "X86 LEA Fixup" 29 #define FIXUPLEA_NAME "x86-fixup-LEAs" 31 #define DEBUG_TYPE FIXUPLEA_NAME 33 STATISTIC(NumLEAs,
"Number of LEA instructions created");
37 enum RegUsageState { RU_NotUsed, RU_Write, RU_Read };
43 bool IsSlowLEA,
bool IsSlow3OpsLEA);
154 MFI->insert(MBBI, NewMI);
159 case X86::ADD64ri32_DB:
160 case X86::ADD64ri8_DB:
163 case X86::ADD32ri_DB:
164 case X86::ADD32ri8_DB:
167 case X86::ADD16ri_DB:
168 case X86::ADD16ri8_DB:
176 case X86::ADD16rr_DB:
184 return TII->convertToThreeAddress(MFI, MI,
nullptr);
199 OptLEA = ST.
LEAusesAG() || IsSlowLEA || IsSlow3OpsLEA;
201 if (!OptLEA && !OptIncDec)
210 processBasicBlock(Func,
I, IsSlowLEA, IsSlow3OpsLEA);
216 FixupLEAPass::RegUsageState
218 RegUsageState
RegUsage = RU_NotUsed;
238 if (I == MFI->begin()) {
239 if (MFI->isPredecessor(&*MFI)) {
252 int InstrDistance = 1;
254 static const int INSTR_DISTANCE_THRESHOLD = 5;
259 while (Found && I != CurInst) {
260 if (CurInst->isCall() || CurInst->isInlineAsm())
262 if (InstrDistance > INSTR_DISTANCE_THRESHOLD)
264 if (usesRegister(p, CurInst) == RU_Write) {
267 InstrDistance += TSM.computeInstrLatency(&*CurInst);
273 static inline bool isLEA(
const int Opcode) {
274 return Opcode == X86::LEA16r || Opcode == X86::LEA32r ||
275 Opcode == X86::LEA64r || Opcode == X86::LEA64_32r;
279 return Reg == X86::EBP || Reg == X86::RBP ||
280 Reg == X86::R13D || Reg == X86::R13;
284 return Op.
isReg() && Op.
getReg() != X86::NoRegister;
321 return IsInt8 ? X86::ADD16ri8 : X86::ADD16ri;
324 return IsInt8 ? X86::ADD32ri8 : X86::ADD32ri;
326 return IsInt8 ? X86::ADD64ri8 : X86::ADD64ri32;
337 return SrcReg == DstReg &&
356 NewOpcode = isINC ? X86::INC16r : X86::DEC16r;
360 NewOpcode = isINC ? X86::INC32r : X86::DEC32r;
363 NewOpcode = isINC ? X86::INC64r : X86::DEC64r;
384 if (AddrOffset >= 0) {
388 seekLEAFixup(p, I, MFI);
392 seekLEAFixup(q, I, MFI);
405 LLVM_DEBUG(
dbgs() <<
"FixLEA: Candidate to replace:"; MBI->dump(););
411 processInstruction(J, MFI);
431 !
TII->isSafeToClobberEFLAGS(*MFI, I))
433 const unsigned DstR = Dst.
getReg();
434 const unsigned SrcR1 = Base.
getReg();
435 const unsigned SrcR2 = Index.
getReg();
436 if ((SrcR1 == 0 || SrcR1 != DstR) && (SrcR2 == 0 || SrcR2 != DstR))
440 LLVM_DEBUG(
dbgs() <<
"FixLEA: Candidate to replace:"; I->dump(););
444 if (SrcR1 != 0 && SrcR2 != 0) {
452 if (Offset.
getImm() != 0) {
468 FixupLEAPass::processInstrForSlow3OpLEA(
MachineInstr &MI,
472 if (!
isLEA(LEAOpcode))
482 if (!(
TII->isThreeOperandsLEA(MI) ||
484 !
TII->isSafeToClobberEFLAGS(*MFI, MI) ||
485 Segment.
getReg() != X86::NoRegister)
488 unsigned int DstR = Dst.
getReg();
489 unsigned int BaseR = Base.
getReg();
490 unsigned int IndexR = Index.
getReg();
493 bool IsScale1 = Scale.
getImm() == 1;
499 if (IsInefficientBase && SSDstR == BaseR && !IsScale1)
501 if (LEAOpcode == X86::LEA64_32r && IsInefficientBase &&
502 (IsInefficientIndex || !IsScale1))
516 if (IsScale1 && (DstR == BaseR || DstR == IndexR)) {
532 if (!IsInefficientBase || (!IsInefficientIndex && IsScale1)) {
535 .add(IsInefficientBase ? Index : Base)
537 .add(IsInefficientBase ? Base : Index)
549 assert(SSDstR != BaseR &&
"SSDstR == BaseR should be handled already!");
550 assert(IsInefficientBase &&
"efficient base should be handled already!");
554 bool BIK = Base.
isKill() && BaseR != IndexR;
581 bool IsSlowLEA,
bool IsSlow3OpsLEA) {
584 if (fixupIncDec(I, MFI))
589 processInstructionForSlowLEA(I, MFI);
594 if (
auto *NewMI = processInstrForSlow3OpLEA(*I, MFI)) {
601 processInstruction(I, MFI);
const MachineInstrBuilder & add(const MachineOperand &MO) const
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static bool isRegOperand(const MachineOperand &Op)
This class represents lattice values for constants.
static bool isLEASimpleIncOrDec(MachineInstr &LEA)
isLEASimpleIncOrDec - Does this LEA have one these forms: lea reg, 1(reg) lea reg, -1(reg)
const X86InstrInfo * getInstrInfo() const override
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Describe properties that are true of each instruction in the target description file.
unsigned getReg() const
getReg - Returns the register number.
static bool getPreviousInstr(MachineBasicBlock::iterator &I, MachineFunction::iterator MFI)
getPreviousInstr - Given a reference to an instruction in a basic block, return a reference to the pr...
constexpr bool isInt< 8 >(int64_t x)
STATISTIC(NumFunctions, "Total number of functions")
static bool isLEA(const int Opcode)
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
static int getADDrrFromLEA(int LEAOpcode)
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...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Provide an instruction scheduling machine model to CodeGen passes.
const HexagonInstrInfo * TII
unsigned getNumOperands() const
Retuns the total number of operands.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
FunctionPass * createX86FixupLEAs()
Return a pass that selectively replaces certain instructions (like add, sub, inc, dec...
static int getADDriFromLEA(int LEAOpcode, const MachineOperand &Offset)
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
MachineInstrBundleIterator< MachineInstr > iterator
static bool isInefficientLEAReg(unsigned int Reg)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
void initializeFixupLEAPassPass(PassRegistry &)
FunctionPass class - This class is used to implement most global optimizations.
unsigned getOperandBias(const MCInstrDesc &Desc)
getOperandBias - compute whether all of the def operands are repeated in the uses and therefore shoul...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Iterator for intrusive lists based on ilist_node.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperand class - Representation of each machine instruction operand.
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
unsigned getX86SubSuperRegister(unsigned, unsigned, bool High=false)
Returns the sub or super register of a specific X86 register.
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const override
Emit instructions to copy a pair of physical registers.
MachineFunctionProperties & set(Property P)
Representation of each machine instruction.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
static bool hasLEAOffset(const MachineOperand &Offset)
bool optForMinSize() const
Optimize this function for minimum size (-Oz).
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringRef - Represent a constant reference to a string, i.e.
AddrSegmentReg - The operand # of the segment in the memory operand.
const MachineOperand & getOperand(unsigned i) const
Properties which a MachineFunction may have at a given point in time.
int getMemoryOperandNo(uint64_t TSFlags)
getMemoryOperandNo - The function returns the MCInst operand # for the first field of the memory oper...