52 #define DEBUG_TYPE "x86-optimize-LEAs" 56 cl::desc(
"X86: Disable LEA optimizations."),
59 STATISTIC(NumSubstLEAs,
"Number of LEA instruction substitutions");
60 STATISTIC(NumRedundantLEAs,
"Number of redundant LEA instructions removed");
87 Operands[3] = Segment;
92 for (
int i = 0; i < 4; ++i)
119 return MemOpKey(PtrInfo::getEmptyKey(), PtrInfo::getEmptyKey(),
120 PtrInfo::getEmptyKey(), PtrInfo::getEmptyKey(),
121 PtrInfo::getEmptyKey());
125 return MemOpKey(PtrInfo::getTombstoneKey(), PtrInfo::getTombstoneKey(),
126 PtrInfo::getTombstoneKey(), PtrInfo::getTombstoneKey(),
127 PtrInfo::getTombstoneKey());
133 assert(Val.Disp != PtrInfo::getEmptyKey() &&
"Cannot hash the empty key");
134 assert(Val.Disp != PtrInfo::getTombstoneKey() &&
135 "Cannot hash the tombstone key");
138 *Val.Operands[2], *Val.Operands[3]);
144 switch (Val.Disp->getType()) {
170 return (
unsigned)Hash;
173 static bool isEqual(
const MemOpKey &LHS,
const MemOpKey &RHS) {
176 if (RHS.Disp == PtrInfo::getEmptyKey())
177 return LHS.Disp == PtrInfo::getEmptyKey();
178 if (RHS.Disp == PtrInfo::getTombstoneKey())
179 return LHS.Disp == PtrInfo::getTombstoneKey();
190 "The instruction must be a LEA, a load or a store");
215 "Address displacement operand is not valid");
232 return Opcode == X86::LEA16r || Opcode == X86::LEA32r ||
233 Opcode == X86::LEA64r || Opcode == X86::LEA64_32r;
242 StringRef getPassName()
const override {
return "X86 LEA Optimize"; }
262 int64_t &AddrDispShift,
int &Dist);
267 int64_t getAddrDispShift(
const MachineInstr &MI1,
unsigned N1,
275 int64_t &AddrDispShift)
const;
283 bool removeRedundantAddrCalc(MemOpMap &LEAs);
289 int64_t AddrDispShift);
292 bool removeRedundantLEAs(MemOpMap &LEAs);
309 int OptimizeLEAPass::calcInstrDist(
const MachineInstr &First,
314 "Instructions are in different basic blocks");
315 assert(InstrPos.find(&First) != InstrPos.end() &&
316 InstrPos.find(&Last) != InstrPos.end() &&
317 "Instructions' positions are undefined");
319 return InstrPos[&Last] - InstrPos[&First];
334 int64_t &AddrDispShift,
int &Dist) {
343 for (
auto DefMI : List) {
345 int64_t AddrDispShiftTemp = getAddrDispShift(MI, MemOpNo, *
DefMI, 1);
364 int DistTemp = calcInstrDist(*
DefMI, MI);
366 "The distance between two different instructions cannot be zero");
367 if (DistTemp > 0 || BestLEA ==
nullptr) {
370 if (BestLEA !=
nullptr && !
isInt<8>(AddrDispShiftTemp) &&
375 AddrDispShift = AddrDispShiftTemp;
384 return BestLEA !=
nullptr;
390 int64_t OptimizeLEAPass::getAddrDispShift(
const MachineInstr &MI1,
unsigned N1,
397 "Address displacement operands are not compatible");
414 bool OptimizeLEAPass::isReplaceable(
const MachineInstr &First,
416 int64_t &AddrDispShift)
const {
418 "The function works only with LEA instructions");
429 AddrDispShift = getAddrDispShift(Last, 1, First, 1);
472 for (
auto &MI : MBB) {
478 InstrPos[&
MI] = Pos += 2;
481 LEAs[
getMemOpKey(MI, 1)].push_back(const_cast<MachineInstr *>(&MI));
488 bool OptimizeLEAPass::removeRedundantAddrCalc(MemOpMap &LEAs) {
489 bool Changed =
false;
495 for (
auto I = MBB->begin(),
E = MBB->end();
I !=
E;) {
514 if (Insns == LEAs.end())
519 int64_t AddrDispShift;
521 if (!chooseBestLEA(Insns->second, MI, DefMI, AddrDispShift, Dist))
533 InstrPos[
DefMI] = InstrPos[&
MI] - 1;
536 assert(((InstrPos[DefMI] == 1 &&
540 "Instruction positioning is broken");
569 int64_t AddrDispShift) {
572 if (AddrDispShift != 0)
584 return BuildMI(*MBB, MBB->
erase(&MI), DL,
TII->get(TargetOpcode::DBG_VALUE),
585 IsIndirect, VReg, Var, Expr);
589 bool OptimizeLEAPass::removeRedundantLEAs(MemOpMap &LEAs) {
590 bool Changed =
false;
593 for (
auto &
E : LEAs) {
594 auto &List =
E.second;
597 auto I1 = List.
begin();
598 while (I1 != List.
end()) {
600 auto I2 = std::next(I1);
601 while (I2 != List.
end()) {
603 int64_t AddrDispShift;
607 assert(calcInstrDist(First, Last) > 0 &&
608 "LEAs must be in occurrence order in the list");
611 if (!isReplaceable(First, Last, AddrDispShift)) {
621 for (
auto UI =
MRI->use_begin(LastVReg), UE =
MRI->use_end();
630 replaceDebugValue(MI, FirstVReg, AddrDispShift);
647 else if (!Op.
isJTI())
652 MRI->clearKillFlags(FirstVReg);
661 "The LEA's def register must have no uses");
677 bool Changed =
false;
687 for (
auto &MBB : MF) {
699 Changed |= removeRedundantLEAs(LEAs);
703 if (MF.getFunction().optForSize())
704 Changed |= removeRedundantAddrCalc(LEAs);
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
FunctionPass * createX86OptimizeLEAs()
Return a pass that removes redundant LEA instructions and redundant address recalculations.
MachineBasicBlock * getMBB() const
This class represents lattice values for constants.
void ChangeToRegister(unsigned Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
ChangeToRegister - Replace this operand with a new register operand of the specified value...
static unsigned getHashValue(const MemOpKey &Val)
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.
Address of indexed Jump Table for switch.
constexpr bool isInt< 8 >(int64_t x)
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
MachineBasicBlock reference.
STATISTIC(NumFunctions, "Total number of functions")
unsigned const TargetRegisterInfo * TRI
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
static DIExpression * prepend(const DIExpression *Expr, bool DerefBefore, int64_t Offset=0, bool DerefAfter=false, bool StackValue=false)
Prepend DIExpr with a deref and offset operation and optionally turn it into a stack value...
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
unsigned getNumOperands() const
Retuns the total number of operands.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
Name of external global symbol.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const char * getSymbolName() const
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
static bool isSimilarDispOp(const MachineOperand &MO1, const MachineOperand &MO2)
Returns true if two address displacement operands are of the same type and use the same symbol/index/...
void ChangeToImmediate(int64_t ImmVal)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value...
bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
static bool isEqual(const MemOpKey &LHS, const MemOpKey &RHS)
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
AddrSegmentReg - The operand # of the segment in the memory operand.
Address of a global value.
initializer< Ty > init(const Ty &Val)
unsigned const MachineRegisterInfo * MRI
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")
static MemOpKey getEmptyKey()
const GlobalValue * getGlobal() const
Address of a basic block.
void setImm(int64_t immVal)
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...
void setOffset(int64_t Offset)
iterator erase(const_iterator CI)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const DIExpression * getDebugExpression() const
Return the complex address expression referenced by this DBG_VALUE instruction.
static bool isValidDispOp(const MachineOperand &MO)
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
constexpr bool isInt< 32 >(int64_t x)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
static bool isLEA(const MachineInstr &MI)
Returns true if the instruction is LEA.
bool isDebugValue() const
MachineOperand class - Representation of each machine instruction operand.
MachineInstrBuilder MachineInstrBuilder & DefMI
bool isBlockAddress() const
isBlockAddress - Tests if this is a MO_BlockAddress 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.
MCSymbol reference (for debug/eh info)
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
An opaque object representing a hash code.
static cl::opt< bool > DisableX86LEAOpt("disable-x86-lea-opt", cl::Hidden, cl::desc("X86: Disable LEA optimizations."), cl::init(false))
const MachineBasicBlock * getParent() const
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 isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
int64_t getOffset() const
Return the offset from the symbol in this operand.
const BlockAddress * getBlockAddress() const
void setReg(unsigned Reg)
Change the register this operand corresponds to.
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
MachineInstr * removeFromParent()
Unlink 'this' from the containing basic block, and return it without deleting it. ...
bool isReg() const
isReg - Tests if this is a MO_Register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MCSymbol * getMCSymbol() const
static MemOpKey getMemOpKey(const MachineInstr &MI, unsigned N)
Returns a hash table key based on memory operands of MI.
const DILocalVariable * getDebugVariable() const
Return the debug variable referenced by this DBG_VALUE instruction.
static const Function * getParent(const Value *V)
StringRef - Represent a constant reference to a string, i.e.
bool isMBB() const
isMBB - Tests if this is a MO_MachineBasicBlock operand.
Address of indexed Constant in Constant Pool.
bool operator==(uint64_t V1, const APInt &V2)
const MachineOperand & getOperand(unsigned i) const
bool isIndirectDebugValue() const
A DBG_VALUE is indirect iff the first operand is a register and the second operand is an immediate...
static bool isIdenticalOp(const MachineOperand &MO1, const MachineOperand &MO2)
Returns true if two machine operands are identical and they are not physical registers.
int getMemoryOperandNo(uint64_t TSFlags)
getMemoryOperandNo - The function returns the MCInst operand # for the first field of the memory oper...
static MemOpKey getTombstoneKey()