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