55#define DEBUG_TYPE "x86-optimize-LEAs"
59 cl::desc(
"X86: Disable LEA optimizations."),
62STATISTIC(NumSubstLEAs,
"Number of LEA instruction substitutions");
63STATISTIC(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;
176 static bool isEqual(
const MemOpKey &LHS,
const MemOpKey &RHS) {
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");
216 "Address displacement operand is not valid");
232 unsigned Opcode =
MI.getOpcode();
233 return Opcode == X86::LEA16r || Opcode == X86::LEA32r ||
234 Opcode == X86::LEA64r || Opcode == X86::LEA64_32r;
271 int64_t &AddrDispShift,
int &Dist);
276 int64_t getAddrDispShift(
const MachineInstr &MI1,
unsigned N1,
284 int64_t &AddrDispShift)
const;
292 bool removeRedundantAddrCalc(MemOpMap &LEAs);
298 unsigned NewReg, int64_t AddrDispShift);
301 bool removeRedundantLEAs(MemOpMap &LEAs);
312char X86OptimizeLEAPass::ID = 0;
323 "Instructions are in different basic blocks");
325 "Instructions' positions are undefined");
327 return InstrPos[&
Last] - InstrPos[&
First];
339bool X86OptimizeLEAPass::chooseBestLEA(
341 MachineInstr *&BestLEA, int64_t &AddrDispShift,
int &Dist) {
350 for (
auto *
DefMI : List) {
352 int64_t AddrDispShiftTemp = getAddrDispShift(
MI, MemOpNo, *
DefMI, 1);
355 if (!isInt<32>(AddrDispShiftTemp))
371 int DistTemp = calcInstrDist(*
DefMI,
MI);
373 "The distance between two different instructions cannot be zero");
374 if (DistTemp > 0 || BestLEA ==
nullptr) {
377 if (BestLEA !=
nullptr && !isInt<8>(AddrDispShiftTemp) &&
378 isInt<8>(AddrDispShift))
382 AddrDispShift = AddrDispShiftTemp;
391 return BestLEA !=
nullptr;
397int64_t X86OptimizeLEAPass::getAddrDispShift(
const MachineInstr &MI1,
405 "Address displacement operands are not compatible");
424 int64_t &AddrDispShift)
const {
426 "The function works only with LEA instructions");
432 if (
MRI->getRegClass(
First.getOperand(0).getReg()) !=
433 MRI->getRegClass(
Last.getOperand(0).getReg()))
437 AddrDispShift = getAddrDispShift(
Last, 1,
First, 1);
442 for (
auto &MO :
MRI->use_nodbg_operands(
Last.getOperand(0).getReg())) {
463 for (
unsigned i = 0; i <
MI.getNumOperands(); i++)
481 for (
auto &
MI :
MBB) {
487 InstrPos[&
MI] = Pos += 2;
497bool X86OptimizeLEAPass::removeRedundantAddrCalc(MemOpMap &LEAs) {
498 bool Changed =
false;
506 if (!
MI.mayLoadOrStore())
521 if (Insns == LEAs.end())
526 int64_t AddrDispShift;
528 if (!chooseBestLEA(Insns->second,
MI,
DefMI, AddrDispShift, Dist))
540 InstrPos[
DefMI] = InstrPos[&
MI] - 1;
547 "Instruction positioning is broken");
561 .ChangeToRegister(X86::NoRegister,
false);
562 MI.getOperand(MemOpNo +
X86::AddrDisp).ChangeToImmediate(AddrDispShift);
564 .ChangeToRegister(X86::NoRegister,
false);
577 int64_t AddrDispShift) {
579 if (AddrDispShift != 0) {
580 if (
MI.isNonListDebugValue()) {
589 unsigned OpIdx =
MI.getDebugOperandIndex(&
Op);
598 bool IsIndirect =
MI.isIndirectDebugValue();
599 const MDNode *Var =
MI.getDebugVariable();
600 unsigned Opcode =
MI.isNonListDebugValue() ? TargetOpcode::DBG_VALUE
601 : TargetOpcode::DBG_VALUE_LIST;
603 assert(
MI.getDebugOffset().getImm() == 0 &&
604 "DBG_VALUE with nonzero offset");
609 if (
Op.isReg() &&
Op.getReg() == OldReg)
611 false,
false,
false,
false,
false,
622bool X86OptimizeLEAPass::removeRedundantLEAs(MemOpMap &LEAs) {
623 bool Changed =
false;
626 for (
auto &E : LEAs) {
627 auto &
List = E.second;
631 while (I1 !=
List.end()) {
633 auto I2 = std::next(I1);
634 while (I2 !=
List.end()) {
636 int64_t AddrDispShift;
641 "LEAs must be in occurrence order in the list");
644 if (!isReplaceable(
First,
Last, AddrDispShift)) {
658 while (!
MRI->use_empty(LastVReg)) {
662 if (
MI.isDebugValue()) {
666 replaceDebugValue(
MI, LastVReg, FirstVReg, AddrDispShift);
682 Op.setImm(
Op.getImm() + AddrDispShift);
683 else if (!
Op.isJTI())
684 Op.setOffset(
Op.getOffset() + AddrDispShift);
688 MRI->clearKillFlags(FirstVReg);
697 "The LEA's def register must have no uses");
698 Last.eraseFromParent();
713 bool Changed =
false;
722 &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
723 auto *MBFI = (PSI && PSI->hasProfileSummary()) ?
724 &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI() :
728 for (
auto &
MBB : MF) {
740 Changed |= removeRedundantLEAs(LEAs);
745 Changed |= removeRedundantAddrCalc(LEAs);
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder MachineInstrBuilder & DefMI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const Function * getParent(const Value *V)
This file defines DenseMapInfo traits for DenseMap.
This file defines the DenseMap class.
std::optional< std::vector< StOtherPiece > > Other
const HexagonInstrInfo * TII
===- LazyMachineBlockFrequencyInfo.h - Lazy Block Frequency -*- C++ -*–===//
mir Rename Register Operands
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static cl::opt< bool > DisableX86LEAOpt("disable-x86-lea-opt", cl::Hidden, cl::desc("X86: Disable LEA optimizations."), cl::init(false))
static bool isLEA(const MachineInstr &MI)
Returns true if the instruction is LEA.
static bool isValidDispOp(const MachineOperand &MO)
static MemOpKey getMemOpKey(const MachineInstr &MI, unsigned N)
Returns a hash table key based on memory operands of MI.
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 bool isIdenticalOp(const MachineOperand &MO1, const MachineOperand &MO2)
Returns true if two machine operands are identical and they are not physical registers.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
static void appendOffset(SmallVectorImpl< uint64_t > &Ops, int64_t Offset)
Append Ops with operations to apply the Offset.
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...
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 ...
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
This is an alternative analysis pass to MachineBlockFrequencyInfo.
Describe properties that are true of each instruction in the target description file.
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
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...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
MachineInstr * removeFromParent()
Unlink 'this' from the containing basic block, and return it without deleting it.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
const BlockAddress * getBlockAddress() const
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
const char * getSymbolName() const
bool isBlockAddress() const
isBlockAddress - Tests if this is a MO_BlockAddress operand.
Register getReg() const
getReg - Returns the register number.
bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
MCSymbol * getMCSymbol() const
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_MCSymbol
MCSymbol reference (for debug/eh info)
@ MO_GlobalAddress
Address of a global value.
@ MO_BlockAddress
Address of a basic block.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_ExternalSymbol
Name of external global symbol.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
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)
int64_t getOffset() const
Return the offset from the symbol in this operand.
bool isMBB() const
isMBB - Tests if this is a MO_MachineBasicBlock operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
An opaque object representing a hash code.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
int getMemoryOperandNo(uint64_t TSFlags)
unsigned getOperandBias(const MCInstrDesc &Desc)
Compute whether all of the def operands are repeated in the uses and therefore should be skipped.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
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< 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...
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
DWARFExpression::Operation Op
FunctionPass * createX86OptimizeLEAs()
Return a pass that removes redundant LEA instructions and redundant address recalculations.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Description of the encoding of one expression Op.
static unsigned getHashValue(const MemOpKey &Val)
static MemOpKey getEmptyKey()
static bool isEqual(const MemOpKey &LHS, const MemOpKey &RHS)
static MemOpKey getTombstoneKey()
An information struct used to provide DenseMap with the various necessary components for a given valu...