xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/X86OptimizeLEAs.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===- X86OptimizeLEAs.cpp - optimize usage of LEA instructions -----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the pass that performs some optimizations with LEA
100b57cec5SDimitry Andric // instructions in order to improve performance and code size.
110b57cec5SDimitry Andric // Currently, it does two things:
120b57cec5SDimitry Andric // 1) If there are two LEA instructions calculating addresses which only differ
130b57cec5SDimitry Andric //    by displacement inside a basic block, one of them is removed.
140b57cec5SDimitry Andric // 2) Address calculations in load and store instructions are replaced by
150b57cec5SDimitry Andric //    existing LEA def registers where possible.
160b57cec5SDimitry Andric //
170b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #include "MCTargetDesc/X86BaseInfo.h"
200b57cec5SDimitry Andric #include "X86.h"
210b57cec5SDimitry Andric #include "X86InstrInfo.h"
220b57cec5SDimitry Andric #include "X86Subtarget.h"
230b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
240b57cec5SDimitry Andric #include "llvm/ADT/DenseMapInfo.h"
250b57cec5SDimitry Andric #include "llvm/ADT/Hashing.h"
260b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
270b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
28480093f4SDimitry Andric #include "llvm/Analysis/ProfileSummaryInfo.h"
29480093f4SDimitry Andric #include "llvm/CodeGen/LazyMachineBlockFrequencyInfo.h"
300b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
320b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
330b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
340b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
350b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
360b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
37480093f4SDimitry Andric #include "llvm/CodeGen/MachineSizeOpts.h"
380b57cec5SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h"
390b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
400b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
410b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h"
420b57cec5SDimitry Andric #include "llvm/IR/Function.h"
430b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h"
440b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
450b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
460b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
470b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
480b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
490b57cec5SDimitry Andric #include <cassert>
500b57cec5SDimitry Andric #include <cstdint>
510b57cec5SDimitry Andric #include <iterator>
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric using namespace llvm;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric #define DEBUG_TYPE "x86-optimize-LEAs"
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric static cl::opt<bool>
580b57cec5SDimitry Andric     DisableX86LEAOpt("disable-x86-lea-opt", cl::Hidden,
590b57cec5SDimitry Andric                      cl::desc("X86: Disable LEA optimizations."),
600b57cec5SDimitry Andric                      cl::init(false));
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric STATISTIC(NumSubstLEAs, "Number of LEA instruction substitutions");
630b57cec5SDimitry Andric STATISTIC(NumRedundantLEAs, "Number of redundant LEA instructions removed");
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric /// Returns true if two machine operands are identical and they are not
660b57cec5SDimitry Andric /// physical registers.
670b57cec5SDimitry Andric static inline bool isIdenticalOp(const MachineOperand &MO1,
680b57cec5SDimitry Andric                                  const MachineOperand &MO2);
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric /// Returns true if two address displacement operands are of the same
710b57cec5SDimitry Andric /// type and use the same symbol/index/address regardless of the offset.
720b57cec5SDimitry Andric static bool isSimilarDispOp(const MachineOperand &MO1,
730b57cec5SDimitry Andric                             const MachineOperand &MO2);
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric /// Returns true if the instruction is LEA.
760b57cec5SDimitry Andric static inline bool isLEA(const MachineInstr &MI);
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric namespace {
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric /// A key based on instruction's memory operands.
810b57cec5SDimitry Andric class MemOpKey {
820b57cec5SDimitry Andric public:
MemOpKey(const MachineOperand * Base,const MachineOperand * Scale,const MachineOperand * Index,const MachineOperand * Segment,const MachineOperand * Disp)830b57cec5SDimitry Andric   MemOpKey(const MachineOperand *Base, const MachineOperand *Scale,
840b57cec5SDimitry Andric            const MachineOperand *Index, const MachineOperand *Segment,
850b57cec5SDimitry Andric            const MachineOperand *Disp)
860b57cec5SDimitry Andric       : Disp(Disp) {
870b57cec5SDimitry Andric     Operands[0] = Base;
880b57cec5SDimitry Andric     Operands[1] = Scale;
890b57cec5SDimitry Andric     Operands[2] = Index;
900b57cec5SDimitry Andric     Operands[3] = Segment;
910b57cec5SDimitry Andric   }
920b57cec5SDimitry Andric 
operator ==(const MemOpKey & Other) const930b57cec5SDimitry Andric   bool operator==(const MemOpKey &Other) const {
940b57cec5SDimitry Andric     // Addresses' bases, scales, indices and segments must be identical.
950b57cec5SDimitry Andric     for (int i = 0; i < 4; ++i)
960b57cec5SDimitry Andric       if (!isIdenticalOp(*Operands[i], *Other.Operands[i]))
970b57cec5SDimitry Andric         return false;
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric     // Addresses' displacements don't have to be exactly the same. It only
1000b57cec5SDimitry Andric     // matters that they use the same symbol/index/address. Immediates' or
1010b57cec5SDimitry Andric     // offsets' differences will be taken care of during instruction
1020b57cec5SDimitry Andric     // substitution.
1030b57cec5SDimitry Andric     return isSimilarDispOp(*Disp, *Other.Disp);
1040b57cec5SDimitry Andric   }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   // Address' base, scale, index and segment operands.
1070b57cec5SDimitry Andric   const MachineOperand *Operands[4];
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   // Address' displacement operand.
1100b57cec5SDimitry Andric   const MachineOperand *Disp;
1110b57cec5SDimitry Andric };
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric } // end anonymous namespace
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric namespace llvm {
1160b57cec5SDimitry Andric 
117fe6060f1SDimitry Andric /// Provide DenseMapInfo for MemOpKey.
1180b57cec5SDimitry Andric template <> struct DenseMapInfo<MemOpKey> {
1190b57cec5SDimitry Andric   using PtrInfo = DenseMapInfo<const MachineOperand *>;
1200b57cec5SDimitry Andric 
getEmptyKeyllvm::DenseMapInfo1210b57cec5SDimitry Andric   static inline MemOpKey getEmptyKey() {
1220b57cec5SDimitry Andric     return MemOpKey(PtrInfo::getEmptyKey(), PtrInfo::getEmptyKey(),
1230b57cec5SDimitry Andric                     PtrInfo::getEmptyKey(), PtrInfo::getEmptyKey(),
1240b57cec5SDimitry Andric                     PtrInfo::getEmptyKey());
1250b57cec5SDimitry Andric   }
1260b57cec5SDimitry Andric 
getTombstoneKeyllvm::DenseMapInfo1270b57cec5SDimitry Andric   static inline MemOpKey getTombstoneKey() {
1280b57cec5SDimitry Andric     return MemOpKey(PtrInfo::getTombstoneKey(), PtrInfo::getTombstoneKey(),
1290b57cec5SDimitry Andric                     PtrInfo::getTombstoneKey(), PtrInfo::getTombstoneKey(),
1300b57cec5SDimitry Andric                     PtrInfo::getTombstoneKey());
1310b57cec5SDimitry Andric   }
1320b57cec5SDimitry Andric 
getHashValuellvm::DenseMapInfo1330b57cec5SDimitry Andric   static unsigned getHashValue(const MemOpKey &Val) {
1340b57cec5SDimitry Andric     // Checking any field of MemOpKey is enough to determine if the key is
1350b57cec5SDimitry Andric     // empty or tombstone.
1360b57cec5SDimitry Andric     assert(Val.Disp != PtrInfo::getEmptyKey() && "Cannot hash the empty key");
1370b57cec5SDimitry Andric     assert(Val.Disp != PtrInfo::getTombstoneKey() &&
1380b57cec5SDimitry Andric            "Cannot hash the tombstone key");
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric     hash_code Hash = hash_combine(*Val.Operands[0], *Val.Operands[1],
1410b57cec5SDimitry Andric                                   *Val.Operands[2], *Val.Operands[3]);
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric     // If the address displacement is an immediate, it should not affect the
1440b57cec5SDimitry Andric     // hash so that memory operands which differ only be immediate displacement
1450b57cec5SDimitry Andric     // would have the same hash. If the address displacement is something else,
1460b57cec5SDimitry Andric     // we should reflect symbol/index/address in the hash.
1470b57cec5SDimitry Andric     switch (Val.Disp->getType()) {
1480b57cec5SDimitry Andric     case MachineOperand::MO_Immediate:
1490b57cec5SDimitry Andric       break;
1500b57cec5SDimitry Andric     case MachineOperand::MO_ConstantPoolIndex:
1510b57cec5SDimitry Andric     case MachineOperand::MO_JumpTableIndex:
1520b57cec5SDimitry Andric       Hash = hash_combine(Hash, Val.Disp->getIndex());
1530b57cec5SDimitry Andric       break;
1540b57cec5SDimitry Andric     case MachineOperand::MO_ExternalSymbol:
1550b57cec5SDimitry Andric       Hash = hash_combine(Hash, Val.Disp->getSymbolName());
1560b57cec5SDimitry Andric       break;
1570b57cec5SDimitry Andric     case MachineOperand::MO_GlobalAddress:
1580b57cec5SDimitry Andric       Hash = hash_combine(Hash, Val.Disp->getGlobal());
1590b57cec5SDimitry Andric       break;
1600b57cec5SDimitry Andric     case MachineOperand::MO_BlockAddress:
1610b57cec5SDimitry Andric       Hash = hash_combine(Hash, Val.Disp->getBlockAddress());
1620b57cec5SDimitry Andric       break;
1630b57cec5SDimitry Andric     case MachineOperand::MO_MCSymbol:
1640b57cec5SDimitry Andric       Hash = hash_combine(Hash, Val.Disp->getMCSymbol());
1650b57cec5SDimitry Andric       break;
1660b57cec5SDimitry Andric     case MachineOperand::MO_MachineBasicBlock:
1670b57cec5SDimitry Andric       Hash = hash_combine(Hash, Val.Disp->getMBB());
1680b57cec5SDimitry Andric       break;
1690b57cec5SDimitry Andric     default:
1700b57cec5SDimitry Andric       llvm_unreachable("Invalid address displacement operand");
1710b57cec5SDimitry Andric     }
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric     return (unsigned)Hash;
1740b57cec5SDimitry Andric   }
1750b57cec5SDimitry Andric 
isEqualllvm::DenseMapInfo1760b57cec5SDimitry Andric   static bool isEqual(const MemOpKey &LHS, const MemOpKey &RHS) {
1770b57cec5SDimitry Andric     // Checking any field of MemOpKey is enough to determine if the key is
1780b57cec5SDimitry Andric     // empty or tombstone.
1790b57cec5SDimitry Andric     if (RHS.Disp == PtrInfo::getEmptyKey())
1800b57cec5SDimitry Andric       return LHS.Disp == PtrInfo::getEmptyKey();
1810b57cec5SDimitry Andric     if (RHS.Disp == PtrInfo::getTombstoneKey())
1820b57cec5SDimitry Andric       return LHS.Disp == PtrInfo::getTombstoneKey();
1830b57cec5SDimitry Andric     return LHS == RHS;
1840b57cec5SDimitry Andric   }
1850b57cec5SDimitry Andric };
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric } // end namespace llvm
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric /// Returns a hash table key based on memory operands of \p MI. The
1900b57cec5SDimitry Andric /// number of the first memory operand of \p MI is specified through \p N.
getMemOpKey(const MachineInstr & MI,unsigned N)1910b57cec5SDimitry Andric static inline MemOpKey getMemOpKey(const MachineInstr &MI, unsigned N) {
1920b57cec5SDimitry Andric   assert((isLEA(MI) || MI.mayLoadOrStore()) &&
1930b57cec5SDimitry Andric          "The instruction must be a LEA, a load or a store");
1940b57cec5SDimitry Andric   return MemOpKey(&MI.getOperand(N + X86::AddrBaseReg),
1950b57cec5SDimitry Andric                   &MI.getOperand(N + X86::AddrScaleAmt),
1960b57cec5SDimitry Andric                   &MI.getOperand(N + X86::AddrIndexReg),
1970b57cec5SDimitry Andric                   &MI.getOperand(N + X86::AddrSegmentReg),
1980b57cec5SDimitry Andric                   &MI.getOperand(N + X86::AddrDisp));
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric 
isIdenticalOp(const MachineOperand & MO1,const MachineOperand & MO2)2010b57cec5SDimitry Andric static inline bool isIdenticalOp(const MachineOperand &MO1,
2020b57cec5SDimitry Andric                                  const MachineOperand &MO2) {
203bdd1243dSDimitry Andric   return MO1.isIdenticalTo(MO2) && (!MO1.isReg() || !MO1.getReg().isPhysical());
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric #ifndef NDEBUG
isValidDispOp(const MachineOperand & MO)2070b57cec5SDimitry Andric static bool isValidDispOp(const MachineOperand &MO) {
2080b57cec5SDimitry Andric   return MO.isImm() || MO.isCPI() || MO.isJTI() || MO.isSymbol() ||
2090b57cec5SDimitry Andric          MO.isGlobal() || MO.isBlockAddress() || MO.isMCSymbol() || MO.isMBB();
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric #endif
2120b57cec5SDimitry Andric 
isSimilarDispOp(const MachineOperand & MO1,const MachineOperand & MO2)2130b57cec5SDimitry Andric static bool isSimilarDispOp(const MachineOperand &MO1,
2140b57cec5SDimitry Andric                             const MachineOperand &MO2) {
2150b57cec5SDimitry Andric   assert(isValidDispOp(MO1) && isValidDispOp(MO2) &&
2160b57cec5SDimitry Andric          "Address displacement operand is not valid");
2170b57cec5SDimitry Andric   return (MO1.isImm() && MO2.isImm()) ||
2180b57cec5SDimitry Andric          (MO1.isCPI() && MO2.isCPI() && MO1.getIndex() == MO2.getIndex()) ||
2190b57cec5SDimitry Andric          (MO1.isJTI() && MO2.isJTI() && MO1.getIndex() == MO2.getIndex()) ||
2200b57cec5SDimitry Andric          (MO1.isSymbol() && MO2.isSymbol() &&
2210b57cec5SDimitry Andric           MO1.getSymbolName() == MO2.getSymbolName()) ||
2220b57cec5SDimitry Andric          (MO1.isGlobal() && MO2.isGlobal() &&
2230b57cec5SDimitry Andric           MO1.getGlobal() == MO2.getGlobal()) ||
2240b57cec5SDimitry Andric          (MO1.isBlockAddress() && MO2.isBlockAddress() &&
2250b57cec5SDimitry Andric           MO1.getBlockAddress() == MO2.getBlockAddress()) ||
2260b57cec5SDimitry Andric          (MO1.isMCSymbol() && MO2.isMCSymbol() &&
2270b57cec5SDimitry Andric           MO1.getMCSymbol() == MO2.getMCSymbol()) ||
2280b57cec5SDimitry Andric          (MO1.isMBB() && MO2.isMBB() && MO1.getMBB() == MO2.getMBB());
2290b57cec5SDimitry Andric }
2300b57cec5SDimitry Andric 
isLEA(const MachineInstr & MI)2310b57cec5SDimitry Andric static inline bool isLEA(const MachineInstr &MI) {
2320b57cec5SDimitry Andric   unsigned Opcode = MI.getOpcode();
2330b57cec5SDimitry Andric   return Opcode == X86::LEA16r || Opcode == X86::LEA32r ||
2340b57cec5SDimitry Andric          Opcode == X86::LEA64r || Opcode == X86::LEA64_32r;
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric namespace {
2380b57cec5SDimitry Andric 
2398bcb0991SDimitry Andric class X86OptimizeLEAPass : public MachineFunctionPass {
2400b57cec5SDimitry Andric public:
X86OptimizeLEAPass()2418bcb0991SDimitry Andric   X86OptimizeLEAPass() : MachineFunctionPass(ID) {}
2420b57cec5SDimitry Andric 
getPassName() const2430b57cec5SDimitry Andric   StringRef getPassName() const override { return "X86 LEA Optimize"; }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric   /// Loop over all of the basic blocks, replacing address
2460b57cec5SDimitry Andric   /// calculations in load and store instructions, if it's already
2470b57cec5SDimitry Andric   /// been calculated by LEA. Also, remove redundant LEAs.
2480b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
2490b57cec5SDimitry Andric 
2508bcb0991SDimitry Andric   static char ID;
2518bcb0991SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const252480093f4SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
253480093f4SDimitry Andric     AU.addRequired<ProfileSummaryInfoWrapperPass>();
254480093f4SDimitry Andric     AU.addRequired<LazyMachineBlockFrequencyInfoPass>();
255480093f4SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
256480093f4SDimitry Andric   }
257480093f4SDimitry Andric 
2580b57cec5SDimitry Andric private:
2590b57cec5SDimitry Andric   using MemOpMap = DenseMap<MemOpKey, SmallVector<MachineInstr *, 16>>;
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   /// Returns a distance between two instructions inside one basic block.
2620b57cec5SDimitry Andric   /// Negative result means, that instructions occur in reverse order.
2630b57cec5SDimitry Andric   int calcInstrDist(const MachineInstr &First, const MachineInstr &Last);
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric   /// Choose the best \p LEA instruction from the \p List to replace
2660b57cec5SDimitry Andric   /// address calculation in \p MI instruction. Return the address displacement
2670b57cec5SDimitry Andric   /// and the distance between \p MI and the chosen \p BestLEA in
2680b57cec5SDimitry Andric   /// \p AddrDispShift and \p Dist.
2690b57cec5SDimitry Andric   bool chooseBestLEA(const SmallVectorImpl<MachineInstr *> &List,
2700b57cec5SDimitry Andric                      const MachineInstr &MI, MachineInstr *&BestLEA,
2710b57cec5SDimitry Andric                      int64_t &AddrDispShift, int &Dist);
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric   /// Returns the difference between addresses' displacements of \p MI1
2740b57cec5SDimitry Andric   /// and \p MI2. The numbers of the first memory operands for the instructions
2750b57cec5SDimitry Andric   /// are specified through \p N1 and \p N2.
2760b57cec5SDimitry Andric   int64_t getAddrDispShift(const MachineInstr &MI1, unsigned N1,
2770b57cec5SDimitry Andric                            const MachineInstr &MI2, unsigned N2) const;
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   /// Returns true if the \p Last LEA instruction can be replaced by the
2800b57cec5SDimitry Andric   /// \p First. The difference between displacements of the addresses calculated
2810b57cec5SDimitry Andric   /// by these LEAs is returned in \p AddrDispShift. It'll be used for proper
2820b57cec5SDimitry Andric   /// replacement of the \p Last LEA's uses with the \p First's def register.
2830b57cec5SDimitry Andric   bool isReplaceable(const MachineInstr &First, const MachineInstr &Last,
2840b57cec5SDimitry Andric                      int64_t &AddrDispShift) const;
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   /// Find all LEA instructions in the basic block. Also, assign position
2870b57cec5SDimitry Andric   /// numbers to all instructions in the basic block to speed up calculation of
2880b57cec5SDimitry Andric   /// distance between them.
2890b57cec5SDimitry Andric   void findLEAs(const MachineBasicBlock &MBB, MemOpMap &LEAs);
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric   /// Removes redundant address calculations.
2920b57cec5SDimitry Andric   bool removeRedundantAddrCalc(MemOpMap &LEAs);
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric   /// Replace debug value MI with a new debug value instruction using register
2950b57cec5SDimitry Andric   /// VReg with an appropriate offset and DIExpression to incorporate the
2960b57cec5SDimitry Andric   /// address displacement AddrDispShift. Return new debug value instruction.
297fe6060f1SDimitry Andric   MachineInstr *replaceDebugValue(MachineInstr &MI, unsigned OldReg,
298fe6060f1SDimitry Andric                                   unsigned NewReg, int64_t AddrDispShift);
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric   /// Removes LEAs which calculate similar addresses.
3010b57cec5SDimitry Andric   bool removeRedundantLEAs(MemOpMap &LEAs);
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric   DenseMap<const MachineInstr *, unsigned> InstrPos;
3040b57cec5SDimitry Andric 
305480093f4SDimitry Andric   MachineRegisterInfo *MRI = nullptr;
306480093f4SDimitry Andric   const X86InstrInfo *TII = nullptr;
307480093f4SDimitry Andric   const X86RegisterInfo *TRI = nullptr;
3080b57cec5SDimitry Andric };
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric } // end anonymous namespace
3110b57cec5SDimitry Andric 
3128bcb0991SDimitry Andric char X86OptimizeLEAPass::ID = 0;
3130b57cec5SDimitry Andric 
createX86OptimizeLEAs()3148bcb0991SDimitry Andric FunctionPass *llvm::createX86OptimizeLEAs() { return new X86OptimizeLEAPass(); }
3158bcb0991SDimitry Andric INITIALIZE_PASS(X86OptimizeLEAPass, DEBUG_TYPE, "X86 optimize LEA pass", false,
3168bcb0991SDimitry Andric                 false)
3170b57cec5SDimitry Andric 
calcInstrDist(const MachineInstr & First,const MachineInstr & Last)3188bcb0991SDimitry Andric int X86OptimizeLEAPass::calcInstrDist(const MachineInstr &First,
3190b57cec5SDimitry Andric                                       const MachineInstr &Last) {
3200b57cec5SDimitry Andric   // Both instructions must be in the same basic block and they must be
3210b57cec5SDimitry Andric   // presented in InstrPos.
3220b57cec5SDimitry Andric   assert(Last.getParent() == First.getParent() &&
3230b57cec5SDimitry Andric          "Instructions are in different basic blocks");
324*06c3fb27SDimitry Andric   assert(InstrPos.contains(&First) && InstrPos.contains(&Last) &&
3250b57cec5SDimitry Andric          "Instructions' positions are undefined");
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric   return InstrPos[&Last] - InstrPos[&First];
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric // Find the best LEA instruction in the List to replace address recalculation in
3310b57cec5SDimitry Andric // MI. Such LEA must meet these requirements:
3320b57cec5SDimitry Andric // 1) The address calculated by the LEA differs only by the displacement from
3330b57cec5SDimitry Andric //    the address used in MI.
3340b57cec5SDimitry Andric // 2) The register class of the definition of the LEA is compatible with the
3350b57cec5SDimitry Andric //    register class of the address base register of MI.
3360b57cec5SDimitry Andric // 3) Displacement of the new memory operand should fit in 1 byte if possible.
3370b57cec5SDimitry Andric // 4) The LEA should be as close to MI as possible, and prior to it if
3380b57cec5SDimitry Andric //    possible.
chooseBestLEA(const SmallVectorImpl<MachineInstr * > & List,const MachineInstr & MI,MachineInstr * & BestLEA,int64_t & AddrDispShift,int & Dist)3398bcb0991SDimitry Andric bool X86OptimizeLEAPass::chooseBestLEA(
3408bcb0991SDimitry Andric     const SmallVectorImpl<MachineInstr *> &List, const MachineInstr &MI,
3418bcb0991SDimitry Andric     MachineInstr *&BestLEA, int64_t &AddrDispShift, int &Dist) {
3420b57cec5SDimitry Andric   const MachineFunction *MF = MI.getParent()->getParent();
3430b57cec5SDimitry Andric   const MCInstrDesc &Desc = MI.getDesc();
3440b57cec5SDimitry Andric   int MemOpNo = X86II::getMemoryOperandNo(Desc.TSFlags) +
3450b57cec5SDimitry Andric                 X86II::getOperandBias(Desc);
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   BestLEA = nullptr;
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   // Loop over all LEA instructions.
350bdd1243dSDimitry Andric   for (auto *DefMI : List) {
3510b57cec5SDimitry Andric     // Get new address displacement.
3520b57cec5SDimitry Andric     int64_t AddrDispShiftTemp = getAddrDispShift(MI, MemOpNo, *DefMI, 1);
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric     // Make sure address displacement fits 4 bytes.
3550b57cec5SDimitry Andric     if (!isInt<32>(AddrDispShiftTemp))
3560b57cec5SDimitry Andric       continue;
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric     // Check that LEA def register can be used as MI address base. Some
3590b57cec5SDimitry Andric     // instructions can use a limited set of registers as address base, for
3600b57cec5SDimitry Andric     // example MOV8mr_NOREX. We could constrain the register class of the LEA
3610b57cec5SDimitry Andric     // def to suit MI, however since this case is very rare and hard to
3620b57cec5SDimitry Andric     // reproduce in a test it's just more reliable to skip the LEA.
3630b57cec5SDimitry Andric     if (TII->getRegClass(Desc, MemOpNo + X86::AddrBaseReg, TRI, *MF) !=
3640b57cec5SDimitry Andric         MRI->getRegClass(DefMI->getOperand(0).getReg()))
3650b57cec5SDimitry Andric       continue;
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric     // Choose the closest LEA instruction from the list, prior to MI if
3680b57cec5SDimitry Andric     // possible. Note that we took into account resulting address displacement
3690b57cec5SDimitry Andric     // as well. Also note that the list is sorted by the order in which the LEAs
3700b57cec5SDimitry Andric     // occur, so the break condition is pretty simple.
3710b57cec5SDimitry Andric     int DistTemp = calcInstrDist(*DefMI, MI);
3720b57cec5SDimitry Andric     assert(DistTemp != 0 &&
3730b57cec5SDimitry Andric            "The distance between two different instructions cannot be zero");
3740b57cec5SDimitry Andric     if (DistTemp > 0 || BestLEA == nullptr) {
3750b57cec5SDimitry Andric       // Do not update return LEA, if the current one provides a displacement
3760b57cec5SDimitry Andric       // which fits in 1 byte, while the new candidate does not.
3770b57cec5SDimitry Andric       if (BestLEA != nullptr && !isInt<8>(AddrDispShiftTemp) &&
3780b57cec5SDimitry Andric           isInt<8>(AddrDispShift))
3790b57cec5SDimitry Andric         continue;
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric       BestLEA = DefMI;
3820b57cec5SDimitry Andric       AddrDispShift = AddrDispShiftTemp;
3830b57cec5SDimitry Andric       Dist = DistTemp;
3840b57cec5SDimitry Andric     }
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric     // FIXME: Maybe we should not always stop at the first LEA after MI.
3870b57cec5SDimitry Andric     if (DistTemp < 0)
3880b57cec5SDimitry Andric       break;
3890b57cec5SDimitry Andric   }
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric   return BestLEA != nullptr;
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric // Get the difference between the addresses' displacements of the two
3950b57cec5SDimitry Andric // instructions \p MI1 and \p MI2. The numbers of the first memory operands are
3960b57cec5SDimitry Andric // passed through \p N1 and \p N2.
getAddrDispShift(const MachineInstr & MI1,unsigned N1,const MachineInstr & MI2,unsigned N2) const3978bcb0991SDimitry Andric int64_t X86OptimizeLEAPass::getAddrDispShift(const MachineInstr &MI1,
3988bcb0991SDimitry Andric                                              unsigned N1,
3990b57cec5SDimitry Andric                                              const MachineInstr &MI2,
4000b57cec5SDimitry Andric                                              unsigned N2) const {
4010b57cec5SDimitry Andric   const MachineOperand &Op1 = MI1.getOperand(N1 + X86::AddrDisp);
4020b57cec5SDimitry Andric   const MachineOperand &Op2 = MI2.getOperand(N2 + X86::AddrDisp);
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   assert(isSimilarDispOp(Op1, Op2) &&
4050b57cec5SDimitry Andric          "Address displacement operands are not compatible");
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric   // After the assert above we can be sure that both operands are of the same
4080b57cec5SDimitry Andric   // valid type and use the same symbol/index/address, thus displacement shift
4090b57cec5SDimitry Andric   // calculation is rather simple.
4100b57cec5SDimitry Andric   if (Op1.isJTI())
4110b57cec5SDimitry Andric     return 0;
4120b57cec5SDimitry Andric   return Op1.isImm() ? Op1.getImm() - Op2.getImm()
4130b57cec5SDimitry Andric                      : Op1.getOffset() - Op2.getOffset();
4140b57cec5SDimitry Andric }
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric // Check that the Last LEA can be replaced by the First LEA. To be so,
4170b57cec5SDimitry Andric // these requirements must be met:
4180b57cec5SDimitry Andric // 1) Addresses calculated by LEAs differ only by displacement.
4190b57cec5SDimitry Andric // 2) Def registers of LEAs belong to the same class.
4200b57cec5SDimitry Andric // 3) All uses of the Last LEA def register are replaceable, thus the
4210b57cec5SDimitry Andric //    register is used only as address base.
isReplaceable(const MachineInstr & First,const MachineInstr & Last,int64_t & AddrDispShift) const4228bcb0991SDimitry Andric bool X86OptimizeLEAPass::isReplaceable(const MachineInstr &First,
4230b57cec5SDimitry Andric                                        const MachineInstr &Last,
4240b57cec5SDimitry Andric                                        int64_t &AddrDispShift) const {
4250b57cec5SDimitry Andric   assert(isLEA(First) && isLEA(Last) &&
4260b57cec5SDimitry Andric          "The function works only with LEA instructions");
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric   // Make sure that LEA def registers belong to the same class. There may be
4290b57cec5SDimitry Andric   // instructions (like MOV8mr_NOREX) which allow a limited set of registers to
4300b57cec5SDimitry Andric   // be used as their operands, so we must be sure that replacing one LEA
4310b57cec5SDimitry Andric   // with another won't lead to putting a wrong register in the instruction.
4320b57cec5SDimitry Andric   if (MRI->getRegClass(First.getOperand(0).getReg()) !=
4330b57cec5SDimitry Andric       MRI->getRegClass(Last.getOperand(0).getReg()))
4340b57cec5SDimitry Andric     return false;
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric   // Get new address displacement.
4370b57cec5SDimitry Andric   AddrDispShift = getAddrDispShift(Last, 1, First, 1);
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   // Loop over all uses of the Last LEA to check that its def register is
4400b57cec5SDimitry Andric   // used only as address base for memory accesses. If so, it can be
4410b57cec5SDimitry Andric   // replaced, otherwise - no.
4420b57cec5SDimitry Andric   for (auto &MO : MRI->use_nodbg_operands(Last.getOperand(0).getReg())) {
4430b57cec5SDimitry Andric     MachineInstr &MI = *MO.getParent();
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric     // Get the number of the first memory operand.
4460b57cec5SDimitry Andric     const MCInstrDesc &Desc = MI.getDesc();
4470b57cec5SDimitry Andric     int MemOpNo = X86II::getMemoryOperandNo(Desc.TSFlags);
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric     // If the use instruction has no memory operand - the LEA is not
4500b57cec5SDimitry Andric     // replaceable.
4510b57cec5SDimitry Andric     if (MemOpNo < 0)
4520b57cec5SDimitry Andric       return false;
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric     MemOpNo += X86II::getOperandBias(Desc);
4550b57cec5SDimitry Andric 
4560b57cec5SDimitry Andric     // If the address base of the use instruction is not the LEA def register -
4570b57cec5SDimitry Andric     // the LEA is not replaceable.
4580b57cec5SDimitry Andric     if (!isIdenticalOp(MI.getOperand(MemOpNo + X86::AddrBaseReg), MO))
4590b57cec5SDimitry Andric       return false;
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric     // If the LEA def register is used as any other operand of the use
4620b57cec5SDimitry Andric     // instruction - the LEA is not replaceable.
4630b57cec5SDimitry Andric     for (unsigned i = 0; i < MI.getNumOperands(); i++)
4640b57cec5SDimitry Andric       if (i != (unsigned)(MemOpNo + X86::AddrBaseReg) &&
4650b57cec5SDimitry Andric           isIdenticalOp(MI.getOperand(i), MO))
4660b57cec5SDimitry Andric         return false;
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric     // Check that the new address displacement will fit 4 bytes.
4690b57cec5SDimitry Andric     if (MI.getOperand(MemOpNo + X86::AddrDisp).isImm() &&
4700b57cec5SDimitry Andric         !isInt<32>(MI.getOperand(MemOpNo + X86::AddrDisp).getImm() +
4710b57cec5SDimitry Andric                    AddrDispShift))
4720b57cec5SDimitry Andric       return false;
4730b57cec5SDimitry Andric   }
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric   return true;
4760b57cec5SDimitry Andric }
4770b57cec5SDimitry Andric 
findLEAs(const MachineBasicBlock & MBB,MemOpMap & LEAs)4788bcb0991SDimitry Andric void X86OptimizeLEAPass::findLEAs(const MachineBasicBlock &MBB,
4798bcb0991SDimitry Andric                                   MemOpMap &LEAs) {
4800b57cec5SDimitry Andric   unsigned Pos = 0;
4810b57cec5SDimitry Andric   for (auto &MI : MBB) {
4820b57cec5SDimitry Andric     // Assign the position number to the instruction. Note that we are going to
4830b57cec5SDimitry Andric     // move some instructions during the optimization however there will never
4840b57cec5SDimitry Andric     // be a need to move two instructions before any selected instruction. So to
4850b57cec5SDimitry Andric     // avoid multiple positions' updates during moves we just increase position
4860b57cec5SDimitry Andric     // counter by two leaving a free space for instructions which will be moved.
4870b57cec5SDimitry Andric     InstrPos[&MI] = Pos += 2;
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric     if (isLEA(MI))
4900b57cec5SDimitry Andric       LEAs[getMemOpKey(MI, 1)].push_back(const_cast<MachineInstr *>(&MI));
4910b57cec5SDimitry Andric   }
4920b57cec5SDimitry Andric }
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric // Try to find load and store instructions which recalculate addresses already
4950b57cec5SDimitry Andric // calculated by some LEA and replace their memory operands with its def
4960b57cec5SDimitry Andric // register.
removeRedundantAddrCalc(MemOpMap & LEAs)4978bcb0991SDimitry Andric bool X86OptimizeLEAPass::removeRedundantAddrCalc(MemOpMap &LEAs) {
4980b57cec5SDimitry Andric   bool Changed = false;
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric   assert(!LEAs.empty());
5010b57cec5SDimitry Andric   MachineBasicBlock *MBB = (*LEAs.begin()->second.begin())->getParent();
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric   // Process all instructions in basic block.
504349cc55cSDimitry Andric   for (MachineInstr &MI : llvm::make_early_inc_range(*MBB)) {
5050b57cec5SDimitry Andric     // Instruction must be load or store.
5060b57cec5SDimitry Andric     if (!MI.mayLoadOrStore())
5070b57cec5SDimitry Andric       continue;
5080b57cec5SDimitry Andric 
5090b57cec5SDimitry Andric     // Get the number of the first memory operand.
5100b57cec5SDimitry Andric     const MCInstrDesc &Desc = MI.getDesc();
5110b57cec5SDimitry Andric     int MemOpNo = X86II::getMemoryOperandNo(Desc.TSFlags);
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric     // If instruction has no memory operand - skip it.
5140b57cec5SDimitry Andric     if (MemOpNo < 0)
5150b57cec5SDimitry Andric       continue;
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric     MemOpNo += X86II::getOperandBias(Desc);
5180b57cec5SDimitry Andric 
5190b57cec5SDimitry Andric     // Do not call chooseBestLEA if there was no matching LEA
5200b57cec5SDimitry Andric     auto Insns = LEAs.find(getMemOpKey(MI, MemOpNo));
5210b57cec5SDimitry Andric     if (Insns == LEAs.end())
5220b57cec5SDimitry Andric       continue;
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric     // Get the best LEA instruction to replace address calculation.
5250b57cec5SDimitry Andric     MachineInstr *DefMI;
5260b57cec5SDimitry Andric     int64_t AddrDispShift;
5270b57cec5SDimitry Andric     int Dist;
5280b57cec5SDimitry Andric     if (!chooseBestLEA(Insns->second, MI, DefMI, AddrDispShift, Dist))
5290b57cec5SDimitry Andric       continue;
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric     // If LEA occurs before current instruction, we can freely replace
5320b57cec5SDimitry Andric     // the instruction. If LEA occurs after, we can lift LEA above the
5330b57cec5SDimitry Andric     // instruction and this way to be able to replace it. Since LEA and the
5340b57cec5SDimitry Andric     // instruction have similar memory operands (thus, the same def
5350b57cec5SDimitry Andric     // instructions for these operands), we can always do that, without
5360b57cec5SDimitry Andric     // worries of using registers before their defs.
5370b57cec5SDimitry Andric     if (Dist < 0) {
5380b57cec5SDimitry Andric       DefMI->removeFromParent();
5390b57cec5SDimitry Andric       MBB->insert(MachineBasicBlock::iterator(&MI), DefMI);
5400b57cec5SDimitry Andric       InstrPos[DefMI] = InstrPos[&MI] - 1;
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric       // Make sure the instructions' position numbers are sane.
5430b57cec5SDimitry Andric       assert(((InstrPos[DefMI] == 1 &&
5440b57cec5SDimitry Andric                MachineBasicBlock::iterator(DefMI) == MBB->begin()) ||
5450b57cec5SDimitry Andric               InstrPos[DefMI] >
5460b57cec5SDimitry Andric                   InstrPos[&*std::prev(MachineBasicBlock::iterator(DefMI))]) &&
5470b57cec5SDimitry Andric              "Instruction positioning is broken");
5480b57cec5SDimitry Andric     }
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric     // Since we can possibly extend register lifetime, clear kill flags.
5510b57cec5SDimitry Andric     MRI->clearKillFlags(DefMI->getOperand(0).getReg());
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric     ++NumSubstLEAs;
5540b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "OptimizeLEAs: Candidate to replace: "; MI.dump(););
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric     // Change instruction operands.
5570b57cec5SDimitry Andric     MI.getOperand(MemOpNo + X86::AddrBaseReg)
5580b57cec5SDimitry Andric         .ChangeToRegister(DefMI->getOperand(0).getReg(), false);
5590b57cec5SDimitry Andric     MI.getOperand(MemOpNo + X86::AddrScaleAmt).ChangeToImmediate(1);
5600b57cec5SDimitry Andric     MI.getOperand(MemOpNo + X86::AddrIndexReg)
5610b57cec5SDimitry Andric         .ChangeToRegister(X86::NoRegister, false);
5620b57cec5SDimitry Andric     MI.getOperand(MemOpNo + X86::AddrDisp).ChangeToImmediate(AddrDispShift);
5630b57cec5SDimitry Andric     MI.getOperand(MemOpNo + X86::AddrSegmentReg)
5640b57cec5SDimitry Andric         .ChangeToRegister(X86::NoRegister, false);
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "OptimizeLEAs: Replaced by: "; MI.dump(););
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric     Changed = true;
5690b57cec5SDimitry Andric   }
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric   return Changed;
5720b57cec5SDimitry Andric }
5730b57cec5SDimitry Andric 
replaceDebugValue(MachineInstr & MI,unsigned OldReg,unsigned NewReg,int64_t AddrDispShift)5748bcb0991SDimitry Andric MachineInstr *X86OptimizeLEAPass::replaceDebugValue(MachineInstr &MI,
575fe6060f1SDimitry Andric                                                     unsigned OldReg,
576fe6060f1SDimitry Andric                                                     unsigned NewReg,
5770b57cec5SDimitry Andric                                                     int64_t AddrDispShift) {
5785ffd83dbSDimitry Andric   const DIExpression *Expr = MI.getDebugExpression();
579fe6060f1SDimitry Andric   if (AddrDispShift != 0) {
580fe6060f1SDimitry Andric     if (MI.isNonListDebugValue()) {
581fe6060f1SDimitry Andric       Expr =
582fe6060f1SDimitry Andric           DIExpression::prepend(Expr, DIExpression::StackValue, AddrDispShift);
583fe6060f1SDimitry Andric     } else {
584fe6060f1SDimitry Andric       // Update the Expression, appending an offset of `AddrDispShift` to the
585fe6060f1SDimitry Andric       // Op corresponding to `OldReg`.
586fe6060f1SDimitry Andric       SmallVector<uint64_t, 3> Ops;
587fe6060f1SDimitry Andric       DIExpression::appendOffset(Ops, AddrDispShift);
588fe6060f1SDimitry Andric       for (MachineOperand &Op : MI.getDebugOperandsForReg(OldReg)) {
589fe6060f1SDimitry Andric         unsigned OpIdx = MI.getDebugOperandIndex(&Op);
590fe6060f1SDimitry Andric         Expr = DIExpression::appendOpsToArg(Expr, Ops, OpIdx);
591fe6060f1SDimitry Andric       }
592fe6060f1SDimitry Andric     }
593fe6060f1SDimitry Andric   }
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   // Replace DBG_VALUE instruction with modified version.
5960b57cec5SDimitry Andric   MachineBasicBlock *MBB = MI.getParent();
5970b57cec5SDimitry Andric   DebugLoc DL = MI.getDebugLoc();
5980b57cec5SDimitry Andric   bool IsIndirect = MI.isIndirectDebugValue();
5990b57cec5SDimitry Andric   const MDNode *Var = MI.getDebugVariable();
600fe6060f1SDimitry Andric   unsigned Opcode = MI.isNonListDebugValue() ? TargetOpcode::DBG_VALUE
601fe6060f1SDimitry Andric                                              : TargetOpcode::DBG_VALUE_LIST;
6020b57cec5SDimitry Andric   if (IsIndirect)
603fe6060f1SDimitry Andric     assert(MI.getDebugOffset().getImm() == 0 &&
604fe6060f1SDimitry Andric            "DBG_VALUE with nonzero offset");
605fe6060f1SDimitry Andric   SmallVector<MachineOperand, 4> NewOps;
606fe6060f1SDimitry Andric   // If we encounter an operand using the old register, replace it with an
607fe6060f1SDimitry Andric   // operand that uses the new register; otherwise keep the old operand.
608fe6060f1SDimitry Andric   auto replaceOldReg = [OldReg, NewReg](const MachineOperand &Op) {
609fe6060f1SDimitry Andric     if (Op.isReg() && Op.getReg() == OldReg)
610fe6060f1SDimitry Andric       return MachineOperand::CreateReg(NewReg, false, false, false, false,
61104eeddc0SDimitry Andric                                        false, false, false, false, false,
612fe6060f1SDimitry Andric                                        /*IsRenamable*/ true);
613fe6060f1SDimitry Andric     return Op;
614fe6060f1SDimitry Andric   };
615fe6060f1SDimitry Andric   for (const MachineOperand &Op : MI.debug_operands())
616fe6060f1SDimitry Andric     NewOps.push_back(replaceOldReg(Op));
617fe6060f1SDimitry Andric   return BuildMI(*MBB, MBB->erase(&MI), DL, TII->get(Opcode), IsIndirect,
618fe6060f1SDimitry Andric                  NewOps, Var, Expr);
6190b57cec5SDimitry Andric }
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric // Try to find similar LEAs in the list and replace one with another.
removeRedundantLEAs(MemOpMap & LEAs)6228bcb0991SDimitry Andric bool X86OptimizeLEAPass::removeRedundantLEAs(MemOpMap &LEAs) {
6230b57cec5SDimitry Andric   bool Changed = false;
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric   // Loop over all entries in the table.
6260b57cec5SDimitry Andric   for (auto &E : LEAs) {
6270b57cec5SDimitry Andric     auto &List = E.second;
6280b57cec5SDimitry Andric 
6290b57cec5SDimitry Andric     // Loop over all LEA pairs.
6300b57cec5SDimitry Andric     auto I1 = List.begin();
6310b57cec5SDimitry Andric     while (I1 != List.end()) {
6320b57cec5SDimitry Andric       MachineInstr &First = **I1;
6330b57cec5SDimitry Andric       auto I2 = std::next(I1);
6340b57cec5SDimitry Andric       while (I2 != List.end()) {
6350b57cec5SDimitry Andric         MachineInstr &Last = **I2;
6360b57cec5SDimitry Andric         int64_t AddrDispShift;
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric         // LEAs should be in occurrence order in the list, so we can freely
6390b57cec5SDimitry Andric         // replace later LEAs with earlier ones.
6400b57cec5SDimitry Andric         assert(calcInstrDist(First, Last) > 0 &&
6410b57cec5SDimitry Andric                "LEAs must be in occurrence order in the list");
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric         // Check that the Last LEA instruction can be replaced by the First.
6440b57cec5SDimitry Andric         if (!isReplaceable(First, Last, AddrDispShift)) {
6450b57cec5SDimitry Andric           ++I2;
6460b57cec5SDimitry Andric           continue;
6470b57cec5SDimitry Andric         }
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric         // Loop over all uses of the Last LEA and update their operands. Note
6500b57cec5SDimitry Andric         // that the correctness of this has already been checked in the
6510b57cec5SDimitry Andric         // isReplaceable function.
6528bcb0991SDimitry Andric         Register FirstVReg = First.getOperand(0).getReg();
6538bcb0991SDimitry Andric         Register LastVReg = Last.getOperand(0).getReg();
654bdd1243dSDimitry Andric         // We use MRI->use_empty here instead of the combination of
655bdd1243dSDimitry Andric         // llvm::make_early_inc_range and MRI->use_operands because we could
656bdd1243dSDimitry Andric         // replace two or more uses in a debug instruction in one iteration, and
657bdd1243dSDimitry Andric         // that would deeply confuse llvm::make_early_inc_range.
658bdd1243dSDimitry Andric         while (!MRI->use_empty(LastVReg)) {
659bdd1243dSDimitry Andric           MachineOperand &MO = *MRI->use_begin(LastVReg);
6600b57cec5SDimitry Andric           MachineInstr &MI = *MO.getParent();
6610b57cec5SDimitry Andric 
6620b57cec5SDimitry Andric           if (MI.isDebugValue()) {
6630b57cec5SDimitry Andric             // Replace DBG_VALUE instruction with modified version using the
6640b57cec5SDimitry Andric             // register from the replacing LEA and the address displacement
6650b57cec5SDimitry Andric             // between the LEA instructions.
666fe6060f1SDimitry Andric             replaceDebugValue(MI, LastVReg, FirstVReg, AddrDispShift);
6670b57cec5SDimitry Andric             continue;
6680b57cec5SDimitry Andric           }
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric           // Get the number of the first memory operand.
6710b57cec5SDimitry Andric           const MCInstrDesc &Desc = MI.getDesc();
6720b57cec5SDimitry Andric           int MemOpNo =
6730b57cec5SDimitry Andric               X86II::getMemoryOperandNo(Desc.TSFlags) +
6740b57cec5SDimitry Andric               X86II::getOperandBias(Desc);
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric           // Update address base.
6770b57cec5SDimitry Andric           MO.setReg(FirstVReg);
6780b57cec5SDimitry Andric 
6790b57cec5SDimitry Andric           // Update address disp.
6800b57cec5SDimitry Andric           MachineOperand &Op = MI.getOperand(MemOpNo + X86::AddrDisp);
6810b57cec5SDimitry Andric           if (Op.isImm())
6820b57cec5SDimitry Andric             Op.setImm(Op.getImm() + AddrDispShift);
6830b57cec5SDimitry Andric           else if (!Op.isJTI())
6840b57cec5SDimitry Andric             Op.setOffset(Op.getOffset() + AddrDispShift);
6850b57cec5SDimitry Andric         }
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric         // Since we can possibly extend register lifetime, clear kill flags.
6880b57cec5SDimitry Andric         MRI->clearKillFlags(FirstVReg);
6890b57cec5SDimitry Andric 
6900b57cec5SDimitry Andric         ++NumRedundantLEAs;
6910b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "OptimizeLEAs: Remove redundant LEA: ";
6920b57cec5SDimitry Andric                    Last.dump(););
6930b57cec5SDimitry Andric 
6940b57cec5SDimitry Andric         // By this moment, all of the Last LEA's uses must be replaced. So we
6950b57cec5SDimitry Andric         // can freely remove it.
6960b57cec5SDimitry Andric         assert(MRI->use_empty(LastVReg) &&
6970b57cec5SDimitry Andric                "The LEA's def register must have no uses");
6980b57cec5SDimitry Andric         Last.eraseFromParent();
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric         // Erase removed LEA from the list.
7010b57cec5SDimitry Andric         I2 = List.erase(I2);
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric         Changed = true;
7040b57cec5SDimitry Andric       }
7050b57cec5SDimitry Andric       ++I1;
7060b57cec5SDimitry Andric     }
7070b57cec5SDimitry Andric   }
7080b57cec5SDimitry Andric 
7090b57cec5SDimitry Andric   return Changed;
7100b57cec5SDimitry Andric }
7110b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)7128bcb0991SDimitry Andric bool X86OptimizeLEAPass::runOnMachineFunction(MachineFunction &MF) {
7130b57cec5SDimitry Andric   bool Changed = false;
7140b57cec5SDimitry Andric 
7150b57cec5SDimitry Andric   if (DisableX86LEAOpt || skipFunction(MF.getFunction()))
7160b57cec5SDimitry Andric     return false;
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
7190b57cec5SDimitry Andric   TII = MF.getSubtarget<X86Subtarget>().getInstrInfo();
7200b57cec5SDimitry Andric   TRI = MF.getSubtarget<X86Subtarget>().getRegisterInfo();
721480093f4SDimitry Andric   auto *PSI =
722480093f4SDimitry Andric       &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
723480093f4SDimitry Andric   auto *MBFI = (PSI && PSI->hasProfileSummary()) ?
724480093f4SDimitry Andric                &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI() :
725480093f4SDimitry Andric                nullptr;
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric   // Process all basic blocks.
7280b57cec5SDimitry Andric   for (auto &MBB : MF) {
7290b57cec5SDimitry Andric     MemOpMap LEAs;
7300b57cec5SDimitry Andric     InstrPos.clear();
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric     // Find all LEA instructions in basic block.
7330b57cec5SDimitry Andric     findLEAs(MBB, LEAs);
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric     // If current basic block has no LEAs, move on to the next one.
7360b57cec5SDimitry Andric     if (LEAs.empty())
7370b57cec5SDimitry Andric       continue;
7380b57cec5SDimitry Andric 
7390b57cec5SDimitry Andric     // Remove redundant LEA instructions.
7400b57cec5SDimitry Andric     Changed |= removeRedundantLEAs(LEAs);
7410b57cec5SDimitry Andric 
7420b57cec5SDimitry Andric     // Remove redundant address calculations. Do it only for -Os/-Oz since only
7430b57cec5SDimitry Andric     // a code size gain is expected from this part of the pass.
744480093f4SDimitry Andric     bool OptForSize = MF.getFunction().hasOptSize() ||
745480093f4SDimitry Andric                       llvm::shouldOptimizeForSize(&MBB, PSI, MBFI);
746480093f4SDimitry Andric     if (OptForSize)
7470b57cec5SDimitry Andric       Changed |= removeRedundantAddrCalc(LEAs);
7480b57cec5SDimitry Andric   }
7490b57cec5SDimitry Andric 
7500b57cec5SDimitry Andric   return Changed;
7510b57cec5SDimitry Andric }
752