53 #define DEBUG_TYPE "x86-optimize-LEAs" 57 cl::desc(
"X86: Disable LEA optimizations."),
60 STATISTIC(NumSubstLEAs,
"Number of LEA instruction substitutions");
61 STATISTIC(NumRedundantLEAs,
"Number of redundant LEA instructions removed");
88 Operands[3] = Segment;
93 for (
int i = 0; i < 4; ++i)
120 return MemOpKey(PtrInfo::getEmptyKey(), PtrInfo::getEmptyKey(),
121 PtrInfo::getEmptyKey(), PtrInfo::getEmptyKey(),
122 PtrInfo::getEmptyKey());
126 return MemOpKey(PtrInfo::getTombstoneKey(), PtrInfo::getTombstoneKey(),
127 PtrInfo::getTombstoneKey(), PtrInfo::getTombstoneKey(),
128 PtrInfo::getTombstoneKey());
134 assert(Val.Disp != PtrInfo::getEmptyKey() &&
"Cannot hash the empty key");
135 assert(Val.Disp != PtrInfo::getTombstoneKey() &&
136 "Cannot hash the tombstone key");
139 *Val.Operands[2], *Val.Operands[3]);
145 switch (Val.Disp->getType()) {
171 return (
unsigned)Hash;
174 static bool isEqual(
const MemOpKey &LHS,
const MemOpKey &RHS) {
177 if (RHS.Disp == PtrInfo::getEmptyKey())
178 return LHS.Disp == PtrInfo::getEmptyKey();
179 if (RHS.Disp == PtrInfo::getTombstoneKey())
180 return LHS.Disp == PtrInfo::getTombstoneKey();
191 "The instruction must be a LEA, a load or a store");
216 "Address displacement operand is not valid");
233 return Opcode == X86::LEA16r || Opcode == X86::LEA32r ||
234 Opcode == X86::LEA64r || Opcode == X86::LEA64_32r;
243 StringRef getPassName()
const override {
return "X86 LEA Optimize"; }
263 int64_t &AddrDispShift,
int &Dist);
268 int64_t getAddrDispShift(
const MachineInstr &MI1,
unsigned N1,
276 int64_t &AddrDispShift)
const;
284 bool removeRedundantAddrCalc(MemOpMap &LEAs);
290 int64_t AddrDispShift);
293 bool removeRedundantLEAs(MemOpMap &LEAs);
310 int OptimizeLEAPass::calcInstrDist(
const MachineInstr &First,
315 "Instructions are in different basic blocks");
316 assert(InstrPos.find(&First) != InstrPos.end() &&
317 InstrPos.find(&Last) != InstrPos.end() &&
318 "Instructions' positions are undefined");
320 return InstrPos[&Last] - InstrPos[&First];
335 int64_t &AddrDispShift,
int &Dist) {
344 for (
auto DefMI : List) {
346 int64_t AddrDispShiftTemp = getAddrDispShift(MI, MemOpNo, *
DefMI, 1);
365 int DistTemp = calcInstrDist(*
DefMI, MI);
367 "The distance between two different instructions cannot be zero");
368 if (DistTemp > 0 || BestLEA ==
nullptr) {
371 if (BestLEA !=
nullptr && !
isInt<8>(AddrDispShiftTemp) &&
376 AddrDispShift = AddrDispShiftTemp;
385 return BestLEA !=
nullptr;
391 int64_t OptimizeLEAPass::getAddrDispShift(
const MachineInstr &MI1,
unsigned N1,
398 "Address displacement operands are not compatible");
415 bool OptimizeLEAPass::isReplaceable(
const MachineInstr &First,
417 int64_t &AddrDispShift)
const {
419 "The function works only with LEA instructions");
430 AddrDispShift = getAddrDispShift(Last, 1, First, 1);
473 for (
auto &MI : MBB) {
479 InstrPos[&
MI] = Pos += 2;
482 LEAs[
getMemOpKey(MI, 1)].push_back(const_cast<MachineInstr *>(&MI));
489 bool OptimizeLEAPass::removeRedundantAddrCalc(MemOpMap &LEAs) {
490 bool Changed =
false;
496 for (
auto I = MBB->begin(),
E = MBB->end();
I !=
E;) {
515 if (Insns == LEAs.end())
520 int64_t AddrDispShift;
522 if (!chooseBestLEA(Insns->second, MI, DefMI, AddrDispShift, Dist))
534 InstrPos[
DefMI] = InstrPos[&
MI] - 1;
537 assert(((InstrPos[DefMI] == 1 &&
541 "Instruction positioning is broken");
570 int64_t AddrDispShift) {
573 if (AddrDispShift != 0)
585 return BuildMI(*MBB, MBB->
erase(&MI), DL,
TII->get(TargetOpcode::DBG_VALUE),
586 IsIndirect, VReg, Var, Expr);
590 bool OptimizeLEAPass::removeRedundantLEAs(MemOpMap &LEAs) {
591 bool Changed =
false;
594 for (
auto &
E : LEAs) {
595 auto &List =
E.second;
598 auto I1 = List.
begin();
599 while (I1 != List.
end()) {
601 auto I2 = std::next(I1);
602 while (I2 != List.
end()) {
604 int64_t AddrDispShift;
608 assert(calcInstrDist(First, Last) > 0 &&
609 "LEAs must be in occurrence order in the list");
612 if (!isReplaceable(First, Last, AddrDispShift)) {
622 for (
auto UI =
MRI->use_begin(LastVReg), UE =
MRI->use_end();
631 replaceDebugValue(MI, FirstVReg, AddrDispShift);
648 else if (!Op.
isJTI())
653 MRI->clearKillFlags(FirstVReg);
662 "The LEA's def register must have no uses");
678 bool Changed =
false;
688 for (
auto &MBB : MF) {
700 Changed |= removeRedundantLEAs(LEAs);
704 if (MF.getFunction().optForSize())
705 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.
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")
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
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.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
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.
AddrSegmentReg - The operand # of the segment in the memory operand.
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()