55#define DEBUG_TYPE "x86-optimize-leas"
57STATISTIC(NumSubstLEAs,
"Number of LEA instruction substitutions");
58STATISTIC(NumRedundantLEAs,
"Number of redundant LEA instructions removed");
90 for (
int i = 0; i < 4; ++i)
102 const MachineOperand *Operands[4];
105 const MachineOperand *Disp;
118 *Val.Operands[2], *Val.Operands[3]);
150 return (
unsigned)Hash;
153 static bool isEqual(
const MemOpKey &LHS,
const MemOpKey &RHS) {
164 "The instruction must be a LEA, a load or a store");
187 "Address displacement operand is not valid");
203 unsigned Opcode =
MI.getOpcode();
204 return Opcode == X86::LEA16r || Opcode == X86::LEA32r ||
205 Opcode == X86::LEA64r || Opcode == X86::LEA64_32r;
210class X86OptimizeLEAsImpl {
212 bool runOnMachineFunction(
MachineFunction &MF, ProfileSummaryInfo *PSI,
213 MachineBlockFrequencyInfo *MBFI);
216 using MemOpMap = DenseMap<MemOpKey, SmallVector<MachineInstr *, 16>>;
220 int calcInstrDist(
const MachineInstr &
First,
const MachineInstr &
Last);
226 bool chooseBestLEA(
const SmallVectorImpl<MachineInstr *> &
List,
227 const MachineInstr &
MI, MachineInstr *&BestLEA,
228 int64_t &AddrDispShift,
int &Dist);
233 int64_t getAddrDispShift(
const MachineInstr &MI1,
unsigned N1,
234 const MachineInstr &MI2,
unsigned N2)
const;
240 bool isReplaceable(
const MachineInstr &
First,
const MachineInstr &
Last,
241 int64_t &AddrDispShift)
const;
246 void findLEAs(
const MachineBasicBlock &
MBB, MemOpMap &LEAs);
249 bool removeRedundantAddrCalc(MemOpMap &LEAs);
254 MachineInstr *replaceDebugValue(MachineInstr &
MI,
Register OldReg,
255 Register NewReg, int64_t AddrDispShift);
258 bool removeRedundantLEAs(MemOpMap &LEAs);
260 DenseMap<const MachineInstr *, unsigned> InstrPos;
262 MachineRegisterInfo *MRI =
nullptr;
263 const X86InstrInfo *TII =
nullptr;
264 const X86RegisterInfo *TRI =
nullptr;
269 X86OptimizeLEAsLegacy() : MachineFunctionPass(ID) {}
271 StringRef getPassName()
const override {
return "X86 LEA Optimize"; }
280 void getAnalysisUsage(AnalysisUsage &AU)
const override {
282 AU.
addRequired<LazyMachineBlockFrequencyInfoPass>();
290char X86OptimizeLEAsLegacy::ID = 0;
293 return new X86OptimizeLEAsLegacy();
303 "Instructions are in different basic blocks");
305 "Instructions' positions are undefined");
307 return InstrPos[&
Last] - InstrPos[&
First];
319bool X86OptimizeLEAsImpl::chooseBestLEA(
321 MachineInstr *&BestLEA, int64_t &AddrDispShift,
int &Dist) {
322 const MCInstrDesc &
Desc =
MI.getDesc();
324 assert(MemOpNo >= 0 &&
"Expected a memory operand");
331 int64_t AddrDispShiftTemp = getAddrDispShift(
MI, MemOpNo, *
DefMI, 1);
350 int DistTemp = calcInstrDist(*
DefMI,
MI);
352 "The distance between two different instructions cannot be zero");
353 if (DistTemp > 0 || BestLEA ==
nullptr) {
356 if (BestLEA !=
nullptr && !
isInt<8>(AddrDispShiftTemp) &&
361 AddrDispShift = AddrDispShiftTemp;
370 return BestLEA !=
nullptr;
376int64_t X86OptimizeLEAsImpl::getAddrDispShift(
const MachineInstr &MI1,
378 const MachineInstr &MI2,
384 "Address displacement operands are not compatible");
401bool X86OptimizeLEAsImpl::isReplaceable(
const MachineInstr &
First,
402 const MachineInstr &
Last,
403 int64_t &AddrDispShift)
const {
405 "The function works only with LEA instructions");
416 AddrDispShift = getAddrDispShift(
Last, 1,
First, 1);
422 MachineInstr &
MI = *MO.getParent();
439 for (
unsigned i = 0; i <
MI.getNumOperands(); i++)
454void X86OptimizeLEAsImpl::findLEAs(
const MachineBasicBlock &
MBB,
457 for (
auto &
MI :
MBB) {
463 InstrPos[&
MI] = Pos += 2;
473bool X86OptimizeLEAsImpl::removeRedundantAddrCalc(MemOpMap &LEAs) {
477 MachineBasicBlock *
MBB = (*LEAs.begin()->second.begin())->
getParent();
482 if (!
MI.mayLoadOrStore())
494 if (Insns == LEAs.end())
499 int64_t AddrDispShift;
501 if (!chooseBestLEA(Insns->second,
MI,
DefMI, AddrDispShift, Dist))
513 InstrPos[
DefMI] = InstrPos[&
MI] - 1;
520 "Instruction positioning is broken");
534 .ChangeToRegister(X86::NoRegister,
false);
535 MI.getOperand(MemOpNo +
X86::AddrDisp).ChangeToImmediate(AddrDispShift);
537 .ChangeToRegister(X86::NoRegister,
false);
547MachineInstr *X86OptimizeLEAsImpl::replaceDebugValue(MachineInstr &
MI,
550 int64_t AddrDispShift) {
551 const DIExpression *Expr =
MI.getDebugExpression();
552 if (AddrDispShift != 0) {
553 if (
MI.isNonListDebugValue()) {
561 for (MachineOperand &
Op :
MI.getDebugOperandsForReg(OldReg)) {
562 unsigned OpIdx =
MI.getDebugOperandIndex(&
Op);
571 bool IsIndirect =
MI.isIndirectDebugValue();
572 const MDNode *Var =
MI.getDebugVariable();
573 unsigned Opcode =
MI.isNonListDebugValue() ? TargetOpcode::DBG_VALUE
574 : TargetOpcode::DBG_VALUE_LIST;
576 assert(
MI.getDebugOffset().getImm() == 0 &&
577 "DBG_VALUE with nonzero offset");
578 SmallVector<MachineOperand, 4> NewOps;
581 auto replaceOldReg = [OldReg, NewReg](
const MachineOperand &
Op) {
582 if (
Op.isReg() &&
Op.getReg() == OldReg)
584 false,
false,
false,
false,
false,
588 for (
const MachineOperand &
Op :
MI.debug_operands())
595bool X86OptimizeLEAsImpl::removeRedundantLEAs(MemOpMap &LEAs) {
599 for (
auto &
E : LEAs) {
600 auto &
List =
E.second;
604 while (I1 !=
List.end()) {
606 auto I2 = std::next(I1);
607 while (I2 !=
List.end()) {
608 MachineInstr &
Last = **I2;
609 int64_t AddrDispShift;
614 "LEAs must be in occurrence order in the list");
617 if (!isReplaceable(
First,
Last, AddrDispShift)) {
632 MachineOperand &MO = *MRI->
use_begin(LastVReg);
635 if (
MI.isDebugValue()) {
639 replaceDebugValue(
MI, LastVReg, FirstVReg, AddrDispShift);
645 assert(MemOpNo >= 0 &&
"Expected a memory operand");
653 Op.setImm(
Op.getImm() + AddrDispShift);
654 else if (!
Op.isJTI())
655 Op.setOffset(
Op.getOffset() + AddrDispShift);
668 "The LEA's def register must have no uses");
669 Last.eraseFromParent();
683bool X86OptimizeLEAsImpl::runOnMachineFunction(
685 MachineBlockFrequencyInfo *MBFI) {
689 if (
ST.getCLOpts().disable_x86_lea_opt)
693 TII =
ST.getInstrInfo();
694 TRI =
ST.getRegisterInfo();
697 for (
auto &
MBB : MF) {
709 Changed |= removeRedundantLEAs(LEAs);
714 Changed |= removeRedundantAddrCalc(LEAs);
723 ProfileSummaryInfo *PSI =
724 &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
725 MachineBlockFrequencyInfo *MBFI =
727 ? &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI()
729 X86OptimizeLEAsImpl PassImpl;
730 return PassImpl.runOnMachineFunction(MF, PSI, MBFI);
738 .getCachedResult<ProfileSummaryAnalysis>(
744 X86OptimizeLEAsImpl PassImpl;
745 bool Changed = PassImpl.runOnMachineFunction(MF, PSI, MBFI);
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines DenseMapInfo traits for DenseMap.
This file defines the DenseMap class.
const HexagonInstrInfo * TII
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
===- LazyMachineBlockFrequencyInfo.h - Lazy Block Frequency -*- C++ -*–===//
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
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 bool isLEA(unsigned Opcode)
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.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Represents analyses that only rely on functions' control flow.
static LLVM_ABI void appendOffset(SmallVectorImpl< uint64_t > &Ops, int64_t Offset)
Append Ops with operations to apply the Offset.
static LLVM_ABI 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 LLVM_ABI 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 ...
FunctionPass class - This class is used to implement most global optimizations.
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineInstrBundleIterator< MachineInstr > iterator
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
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.
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.
LLVM_ABI 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.
LLVM_ABI 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.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this 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.
LLVM_ABI 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.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
use_iterator use_begin(Register RegNo) const
bool use_empty(Register RegNo) const
use_empty - Return true if there are no instructions using the specified register.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Analysis providing profile information.
bool hasProfileSummary() const
Returns true if profile summary is available.
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)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
An opaque object representing a hash code.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
int getMemoryOperandIdx(const MCInstrDesc &Desc)
This is an optimization pass for GlobalISel generic memory operations.
OuterAnalysisManagerProxy< ModuleAnalysisManager, MachineFunction > ModuleAnalysisManagerMachineFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
FunctionPass * createX86OptimizeLEAsLegacyPass()
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI 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...
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
DWARFExpression::Operation Op
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
static unsigned getHashValue(const MemOpKey &Val)
DenseMapInfo< const MachineOperand * > PtrInfo
static bool isEqual(const MemOpKey &LHS, const MemOpKey &RHS)
An information struct used to provide DenseMap with the various necessary components for a given valu...