Go to the documentation of this file.
55 #define DEBUG_TYPE "x86-optimize-LEAs"
59 cl::desc(
"X86: Disable LEA optimizations."),
62 STATISTIC(NumSubstLEAs,
"Number of LEA instruction substitutions");
63 STATISTIC(NumRedundantLEAs,
"Number of redundant LEA instructions removed");
95 for (
int i = 0;
i < 4; ++
i)
122 return MemOpKey(PtrInfo::getEmptyKey(), PtrInfo::getEmptyKey(),
123 PtrInfo::getEmptyKey(), PtrInfo::getEmptyKey(),
124 PtrInfo::getEmptyKey());
128 return MemOpKey(PtrInfo::getTombstoneKey(), PtrInfo::getTombstoneKey(),
129 PtrInfo::getTombstoneKey(), PtrInfo::getTombstoneKey(),
130 PtrInfo::getTombstoneKey());
136 assert(Val.Disp != PtrInfo::getEmptyKey() &&
"Cannot hash the empty key");
137 assert(Val.Disp != PtrInfo::getTombstoneKey() &&
138 "Cannot hash the tombstone key");
141 *Val.Operands[2], *Val.Operands[3]);
147 switch (Val.Disp->getType()) {
173 return (
unsigned)Hash;
179 if (
RHS.Disp == PtrInfo::getEmptyKey())
180 return LHS.Disp == PtrInfo::getEmptyKey();
181 if (
RHS.Disp == PtrInfo::getTombstoneKey())
182 return LHS.Disp == PtrInfo::getTombstoneKey();
193 "The instruction must be a LEA, a load or a store");
217 "Address displacement operand is not valid");
233 unsigned Opcode =
MI.getOpcode();
234 return Opcode == X86::LEA16r || Opcode == X86::LEA32r ||
235 Opcode == X86::LEA64r || Opcode == X86::LEA64_32r;
244 StringRef getPassName()
const override {
return "X86 LEA Optimize"; }
272 int64_t &AddrDispShift,
int &Dist);
277 int64_t getAddrDispShift(
const MachineInstr &MI1,
unsigned N1,
285 int64_t &AddrDispShift)
const;
293 bool removeRedundantAddrCalc(MemOpMap &LEAs);
299 unsigned NewReg, int64_t AddrDispShift);
302 bool removeRedundantLEAs(MemOpMap &LEAs);
324 "Instructions are in different basic blocks");
326 InstrPos.find(&Last) != InstrPos.end() &&
327 "Instructions' positions are undefined");
329 return InstrPos[&Last] - InstrPos[&
First];
341 bool X86OptimizeLEAPass::chooseBestLEA(
343 MachineInstr *&BestLEA, int64_t &AddrDispShift,
int &Dist) {
352 for (
auto DefMI : List) {
354 int64_t AddrDispShiftTemp = getAddrDispShift(
MI, MemOpNo, *
DefMI, 1);
373 int DistTemp = calcInstrDist(*
DefMI,
MI);
375 "The distance between two different instructions cannot be zero");
376 if (DistTemp > 0 || BestLEA ==
nullptr) {
379 if (BestLEA !=
nullptr && !
isInt<8>(AddrDispShiftTemp) &&
384 AddrDispShift = AddrDispShiftTemp;
393 return BestLEA !=
nullptr;
399 int64_t X86OptimizeLEAPass::getAddrDispShift(
const MachineInstr &MI1,
407 "Address displacement operands are not compatible");
424 bool X86OptimizeLEAPass::isReplaceable(
const MachineInstr &First,
426 int64_t &AddrDispShift)
const {
428 "The function works only with LEA instructions");
439 AddrDispShift = getAddrDispShift(Last, 1, First, 1);
465 for (
unsigned i = 0;
i <
MI.getNumOperands();
i++)
483 for (
auto &
MI :
MBB) {
489 InstrPos[&
MI] = Pos += 2;
499 bool X86OptimizeLEAPass::removeRedundantAddrCalc(MemOpMap &LEAs) {
500 bool Changed =
false;
508 if (!
MI.mayLoadOrStore())
523 if (Insns == LEAs.end())
528 int64_t AddrDispShift;
530 if (!chooseBestLEA(Insns->second,
MI,
DefMI, AddrDispShift, Dist))
542 InstrPos[
DefMI] = InstrPos[&
MI] - 1;
549 "Instruction positioning is broken");
563 .ChangeToRegister(X86::NoRegister,
false);
564 MI.getOperand(MemOpNo +
X86::AddrDisp).ChangeToImmediate(AddrDispShift);
566 .ChangeToRegister(X86::NoRegister,
false);
579 int64_t AddrDispShift) {
581 if (AddrDispShift != 0) {
582 if (
MI.isNonListDebugValue()) {
591 unsigned OpIdx =
MI.getDebugOperandIndex(&
Op);
600 bool IsIndirect =
MI.isIndirectDebugValue();
601 const MDNode *Var =
MI.getDebugVariable();
602 unsigned Opcode =
MI.isNonListDebugValue() ? TargetOpcode::DBG_VALUE
603 : TargetOpcode::DBG_VALUE_LIST;
605 assert(
MI.getDebugOffset().getImm() == 0 &&
606 "DBG_VALUE with nonzero offset");
611 if (
Op.isReg() &&
Op.getReg() == OldReg)
613 false,
false,
false,
false,
false,
618 NewOps.push_back(replaceOldReg(
Op));
624 bool X86OptimizeLEAPass::removeRedundantLEAs(MemOpMap &LEAs) {
625 bool Changed =
false;
628 for (
auto &
E : LEAs) {
629 auto &
List =
E.second;
633 while (
I1 !=
List.end()) {
635 auto I2 = std::next(
I1);
636 while (I2 !=
List.end()) {
638 int64_t AddrDispShift;
642 assert(calcInstrDist(First, Last) > 0 &&
643 "LEAs must be in occurrence order in the list");
646 if (!isReplaceable(First, Last, AddrDispShift)) {
660 if (
MI.isDebugValue()) {
664 replaceDebugValue(
MI, LastVReg, FirstVReg, AddrDispShift);
675 MO.setReg(FirstVReg);
680 Op.setImm(
Op.getImm() + AddrDispShift);
681 else if (!
Op.isJTI())
682 Op.setOffset(
Op.getOffset() + AddrDispShift);
695 "The LEA's def register must have no uses");
696 Last.eraseFromParent();
711 bool Changed =
false;
720 &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
721 auto *MBFI = (PSI && PSI->hasProfileSummary()) ?
722 &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI() :
726 for (
auto &
MBB : MF) {
738 Changed |= removeRedundantLEAs(LEAs);
742 bool OptForSize = MF.getFunction().hasOptSize() ||
745 Changed |= removeRedundantAddrCalc(LEAs);
static DIExpression * prepend(const DIExpression *Expr, uint8_t Flags, int64_t Offset=0)
Prepend DIExpr with a deref and offset operation and optionally turn it into a stack value or/and an ...
static MemOpKey getEmptyKey()
@ MO_BlockAddress
Address of a basic block.
@ MO_Immediate
Immediate operand.
This is an optimization pass for GlobalISel generic memory operations.
int getMemoryOperandNo(uint64_t TSFlags)
The function returns the MCInst operand # for the first field of the memory operand.
bool isBlockAddress() const
isBlockAddress - Tests if this is a MO_BlockAddress operand.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const GlobalValue * getGlobal() const
@ AddrSegmentReg
AddrSegmentReg - The operand # of the segment in the memory operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
const BlockAddress * getBlockAddress() const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
iterator_range< use_iterator > use_operands(Register Reg) const
int64_t getOffset() const
Return the offset from the symbol in this operand.
unsigned const TargetRegisterInfo * TRI
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
MCSymbol * getMCSymbol() const
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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/...
static MemOpKey getTombstoneKey()
An information struct used to provide DenseMap with the various necessary components for a given valu...
static DIExpression * appendOpsToArg(const DIExpression *Expr, ArrayRef< uint64_t > Ops, unsigned ArgNo, bool StackValue=false)
Create a copy of Expr by appending the given list of Ops to each instance of the operand DW_OP_LLVM_a...
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
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.
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
@ MO_GlobalAddress
Address of a global value.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static bool isLEA(const MachineInstr &MI)
Returns true if the instruction is LEA.
const MachineOperand & getOperand(unsigned i) const
Clang compiles this i1 i64 store i64 i64 store i64 i64 store i64 i64 store i64 align Which gets codegen d xmm0 movaps rbp movaps rbp movaps rbp movaps rbp rbp rbp rbp rbp It would be better to have movq s of instead of the movaps s LLVM produces ret int
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
Represent the analysis usage information of a pass.
MachineInstr * removeFromParent()
Unlink 'this' from the containing basic block, and return it without deleting it.
bool isMBB() const
isMBB - Tests if this is a MO_MachineBasicBlock operand.
const HexagonInstrInfo * TII
Describe properties that are true of each instruction in the target description file.
into llvm powi allowing the code generator to produce balanced multiplication trees First
MachineOperand class - Representation of each machine instruction operand.
STATISTIC(NumFunctions, "Total number of functions")
bool use_empty(Register RegNo) const
use_empty - Return true if there are no instructions using the specified register.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
mir Rename Register Operands
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
constexpr bool isInt< 8 >(int64_t x)
void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
===- LazyMachineBlockFrequencyInfo.h - Lazy Block Frequency -*- C++ -*–===//
unsigned getOperandBias(const MCInstrDesc &Desc)
Compute whether all of the def operands are repeated in the uses and therefore should be skipped.
constexpr bool isInt< 32 >(int64_t x)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Representation of each machine instruction.
@ MO_MCSymbol
MCSymbol reference (for debug/eh info)
initializer< Ty > init(const Ty &Val)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
static MemOpKey getMemOpKey(const MachineInstr &MI, unsigned N)
Returns a hash table key based on memory operands of MI.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool operator==(uint64_t V1, const APInt &V2)
Register getReg() const
getReg - Returns the register number.
INITIALIZE_PASS(X86OptimizeLEAPass, DEBUG_TYPE, "X86 optimize LEA pass", false, false) int X86OptimizeLEAPass
This is an alternative analysis pass to MachineBlockFrequencyInfo.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
MachineBasicBlock * getMBB() const
StringRef - Represent a constant reference to a string, i.e.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static const Function * getParent(const Value *V)
static bool isIdenticalOp(const MachineOperand &MO1, const MachineOperand &MO2)
Returns true if two machine operands are identical and they are not physical registers.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
unsigned const MachineRegisterInfo * MRI
Wrapper class representing virtual and physical registers.
static bool isValidDispOp(const MachineOperand &MO)
static unsigned getHashValue(const MemOpKey &Val)
static void appendOffset(SmallVectorImpl< uint64_t > &Ops, int64_t Offset)
Append Ops with operations to apply the Offset.
Function & getFunction()
Return the LLVM function that this machine code represents.
static bool isEqual(const MemOpKey &LHS, const MemOpKey &RHS)
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
@ MO_ExternalSymbol
Name of external global symbol.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
static cl::opt< bool > DisableX86LEAOpt("disable-x86-lea-opt", cl::Hidden, cl::desc("X86: Disable LEA optimizations."), cl::init(false))
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
const char * getSymbolName() const
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
MachineInstrBuilder MachineInstrBuilder & DefMI
FunctionPass class - This class is used to implement most global optimizations.
FunctionPass * createX86OptimizeLEAs()
Return a pass that removes redundant LEA instructions and redundant address recalculations.
AnalysisUsage & addRequired()
Optional< std::vector< StOtherPiece > > Other
bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
An opaque object representing a hash code.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.