37 #define DEBUG_TYPE "x86-optimize-LEAs"
41 cl::desc(
"X86: Disable LEA optimizations."),
44 STATISTIC(NumSubstLEAs,
"Number of LEA instruction substitutions");
45 STATISTIC(NumRedundantLEAs,
"Number of redundant LEA instructions removed");
71 Operands[3] = Segment;
76 for (
int i = 0;
i < 4; ++
i)
101 return MemOpKey(PtrInfo::getEmptyKey(), PtrInfo::getEmptyKey(),
102 PtrInfo::getEmptyKey(), PtrInfo::getEmptyKey(),
103 PtrInfo::getEmptyKey());
107 return MemOpKey(PtrInfo::getTombstoneKey(), PtrInfo::getTombstoneKey(),
108 PtrInfo::getTombstoneKey(), PtrInfo::getTombstoneKey(),
109 PtrInfo::getTombstoneKey());
115 assert(Val.Disp != PtrInfo::getEmptyKey() &&
"Cannot hash the empty key");
116 assert(Val.Disp != PtrInfo::getTombstoneKey() &&
117 "Cannot hash the tombstone key");
120 *Val.Operands[2], *Val.Operands[3]);
126 switch (Val.Disp->getType()) {
152 return (
unsigned)
Hash;
155 static bool isEqual(
const MemOpKey &LHS,
const MemOpKey &RHS) {
158 if (RHS.Disp == PtrInfo::getEmptyKey())
159 return LHS.Disp == PtrInfo::getEmptyKey();
160 if (RHS.Disp == PtrInfo::getTombstoneKey())
161 return LHS.Disp == PtrInfo::getTombstoneKey();
171 "The instruction must be a LEA, a load or a store");
196 "Address displacement operand is not valid");
213 return Opcode == X86::LEA16r || Opcode == X86::LEA32r ||
214 Opcode == X86::LEA64r || Opcode == X86::LEA64_32r;
222 StringRef getPassName()
const override {
return "X86 LEA Optimize"; }
242 int64_t &AddrDispShift,
int &Dist);
247 int64_t getAddrDispShift(
const MachineInstr &MI1,
unsigned N1,
255 int64_t &AddrDispShift)
const;
263 bool removeRedundantAddrCalc(MemOpMap &LEAs);
266 bool removeRedundantLEAs(MemOpMap &LEAs);
281 int OptimizeLEAPass::calcInstrDist(
const MachineInstr &First,
286 "Instructions are in different basic blocks");
287 assert(InstrPos.find(&First) != InstrPos.end() &&
288 InstrPos.find(&Last) != InstrPos.end() &&
289 "Instructions' positions are undefined");
291 return InstrPos[&Last] - InstrPos[&First];
306 int64_t &AddrDispShift,
int &Dist) {
315 for (
auto DefMI : List) {
317 int64_t AddrDispShiftTemp = getAddrDispShift(MI, MemOpNo, *DefMI, 1);
329 MRI->getRegClass(DefMI->getOperand(0).getReg()))
336 int DistTemp = calcInstrDist(*DefMI, MI);
338 "The distance between two different instructions cannot be zero");
339 if (DistTemp > 0 || BestLEA ==
nullptr) {
342 if (BestLEA !=
nullptr && !
isInt<8>(AddrDispShiftTemp) &&
347 AddrDispShift = AddrDispShiftTemp;
356 return BestLEA !=
nullptr;
362 int64_t OptimizeLEAPass::getAddrDispShift(
const MachineInstr &MI1,
unsigned N1,
369 "Address displacement operands are not compatible");
386 bool OptimizeLEAPass::isReplaceable(
const MachineInstr &First,
388 int64_t &AddrDispShift)
const {
390 "The function works only with LEA instructions");
393 AddrDispShift = getAddrDispShift(Last, 1, First, 1);
444 for (
auto &MI : MBB) {
450 InstrPos[&
MI] = Pos += 2;
453 LEAs[
getMemOpKey(MI, 1)].push_back(const_cast<MachineInstr *>(&MI));
460 bool OptimizeLEAPass::removeRedundantAddrCalc(MemOpMap &LEAs) {
461 bool Changed =
false;
467 for (
auto I = MBB->begin(),
E = MBB->end();
I !=
E;) {
486 int64_t AddrDispShift;
488 if (!chooseBestLEA(LEAs[
getMemOpKey(MI, MemOpNo)], MI, DefMI, AddrDispShift,
501 InstrPos[DefMI] = InstrPos[&
MI] - 1;
504 assert(((InstrPos[DefMI] == 1 &&
508 "Instruction positioning is broken");
515 DEBUG(
dbgs() <<
"OptimizeLEAs: Candidate to replace: "; MI.
dump(););
536 bool OptimizeLEAPass::removeRedundantLEAs(MemOpMap &LEAs) {
537 bool Changed =
false;
540 for (
auto &
E : LEAs) {
541 auto &List =
E.second;
544 auto I1 = List.begin();
545 while (I1 != List.end()) {
547 auto I2 = std::next(I1);
548 while (I2 != List.end()) {
550 int64_t AddrDispShift;
554 assert(calcInstrDist(First, Last) > 0 &&
555 "LEAs must be in occurrence order in the list");
558 if (!isReplaceable(First, Last, AddrDispShift)) {
585 else if (!Op.
isJTI())
593 DEBUG(
dbgs() <<
"OptimizeLEAs: Remove redundant LEA: "; Last.
dump(););
598 "The LEA's def register must have no uses");
614 bool Changed =
false;
624 for (
auto &MBB : MF) {
636 Changed |= removeRedundantLEAs(LEAs);
640 if (MF.getFunction()->optForSize())
641 Changed |= removeRedundantAddrCalc(LEAs);
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
const GlobalValue * getGlobal() const
FunctionPass * createX86OptimizeLEAs()
Return a pass that removes redundant LEA instructions and redundant address recalculations.
STATISTIC(NumFunctions,"Total number of functions")
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...
MachineBasicBlock * getMBB() const
static unsigned getHashValue(const MemOpKey &Val)
Describe properties that are true of each instruction in the target description file.
MachineInstrBuilder MachineInstrBuilder &DefMI const MCInstrDesc & Desc
Address of indexed Jump Table for switch.
constexpr bool isInt< 8 >(int64_t x)
bool isBlockAddress() const
isBlockAddress - Tests if this is a MO_BlockAddress operand.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
MachineBasicBlock reference.
const char * getSymbolName() const
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
AddrSegmentReg - The operand # of the segment in the memory operand.
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
Name of external global symbol.
unsigned getNumOperands() const
Access to explicit operands of the instruction.
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
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/...
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
void ChangeToImmediate(int64_t ImmVal)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value...
const MachineBasicBlock * getParent() const
static bool isEqual(const MemOpKey &LHS, const MemOpKey &RHS)
Address of a global value.
initializer< Ty > init(const Ty &Val)
unsigned const MachineRegisterInfo * MRI
static MemOpKey getEmptyKey()
const MachineOperand & getOperand(unsigned i) const
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
Address of a basic block.
void setImm(int64_t immVal)
FunctionPass class - This class is used to implement most global optimizations.
int64_t getOffset() const
Return the offset from the symbol in this operand.
unsigned getOperandBias(const MCInstrDesc &Desc)
getOperandBias - compute any additional adjustment needed to the offset to the start of the memory op...
void setOffset(int64_t Offset)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static bool isValidDispOp(const MachineOperand &MO)
constexpr bool isInt< 32 >(int64_t x)
static bool isLEA(const MachineInstr &MI)
Returns true if the instruction is LEA.
MachineOperand class - Representation of each machine instruction operand.
DenseMapInfo< const MachineOperand * > PtrInfo
bool isMBB() const
isMBB - Tests if this is a MO_MachineBasicBlock operand.
void dump(const TargetInstrInfo *TII=nullptr) const
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))
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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
void setReg(unsigned Reg)
Change the register this operand corresponds to.
MCSymbol * getMCSymbol() const
MachineInstr * removeFromParent()
Unlink 'this' from the containing basic block, and return it without deleting it. ...
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static MemOpKey getMemOpKey(const MachineInstr &MI, unsigned N)
Returns a hash table key based on memory operands of MI.
static const Function * getParent(const Value *V)
std::string Hash(const Unit &U)
StringRef - Represent a constant reference to a string, i.e.
const BlockAddress * getBlockAddress() const
Address of indexed Constant in Constant Pool.
bool operator==(uint64_t V1, const APInt &V2)
bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
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()