xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonConstExtenders.cpp (revision 480093f4440d54b30b3025afeac24b48f2ba7a2e)
10b57cec5SDimitry Andric //===- HexagonConstExtenders.cpp ------------------------------------------===//
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 #include "HexagonInstrInfo.h"
100b57cec5SDimitry Andric #include "HexagonRegisterInfo.h"
110b57cec5SDimitry Andric #include "HexagonSubtarget.h"
120b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
130b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
140b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
150b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
178bcb0991SDimitry Andric #include "llvm/CodeGen/Register.h"
18*480093f4SDimitry Andric #include "llvm/InitializePasses.h"
198bcb0991SDimitry Andric #include "llvm/Pass.h"
200b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
210b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
220b57cec5SDimitry Andric #include <map>
230b57cec5SDimitry Andric #include <set>
240b57cec5SDimitry Andric #include <utility>
250b57cec5SDimitry Andric #include <vector>
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric #define DEBUG_TYPE "hexagon-cext-opt"
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric using namespace llvm;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric static cl::opt<unsigned> CountThreshold("hexagon-cext-threshold",
320b57cec5SDimitry Andric   cl::init(3), cl::Hidden, cl::ZeroOrMore,
330b57cec5SDimitry Andric   cl::desc("Minimum number of extenders to trigger replacement"));
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric static cl::opt<unsigned> ReplaceLimit("hexagon-cext-limit", cl::init(0),
360b57cec5SDimitry Andric   cl::Hidden, cl::ZeroOrMore, cl::desc("Maximum number of replacements"));
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric namespace llvm {
390b57cec5SDimitry Andric   void initializeHexagonConstExtendersPass(PassRegistry&);
400b57cec5SDimitry Andric   FunctionPass *createHexagonConstExtenders();
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric static int32_t adjustUp(int32_t V, uint8_t A, uint8_t O) {
440b57cec5SDimitry Andric   assert(isPowerOf2_32(A));
450b57cec5SDimitry Andric   int32_t U = (V & -A) + O;
460b57cec5SDimitry Andric   return U >= V ? U : U+A;
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric static int32_t adjustDown(int32_t V, uint8_t A, uint8_t O) {
500b57cec5SDimitry Andric   assert(isPowerOf2_32(A));
510b57cec5SDimitry Andric   int32_t U = (V & -A) + O;
520b57cec5SDimitry Andric   return U <= V ? U : U-A;
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric namespace {
560b57cec5SDimitry Andric   struct OffsetRange {
570b57cec5SDimitry Andric     // The range of values between Min and Max that are of form Align*N+Offset,
580b57cec5SDimitry Andric     // for some integer N. Min and Max are required to be of that form as well,
590b57cec5SDimitry Andric     // except in the case of an empty range.
600b57cec5SDimitry Andric     int32_t Min = INT_MIN, Max = INT_MAX;
610b57cec5SDimitry Andric     uint8_t Align = 1;
620b57cec5SDimitry Andric     uint8_t Offset = 0;
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric     OffsetRange() = default;
650b57cec5SDimitry Andric     OffsetRange(int32_t L, int32_t H, uint8_t A, uint8_t O = 0)
660b57cec5SDimitry Andric       : Min(L), Max(H), Align(A), Offset(O) {}
670b57cec5SDimitry Andric     OffsetRange &intersect(OffsetRange A) {
680b57cec5SDimitry Andric       if (Align < A.Align)
690b57cec5SDimitry Andric         std::swap(*this, A);
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric       // Align >= A.Align.
720b57cec5SDimitry Andric       if (Offset >= A.Offset && (Offset - A.Offset) % A.Align == 0) {
730b57cec5SDimitry Andric         Min = adjustUp(std::max(Min, A.Min), Align, Offset);
740b57cec5SDimitry Andric         Max = adjustDown(std::min(Max, A.Max), Align, Offset);
750b57cec5SDimitry Andric       } else {
760b57cec5SDimitry Andric         // Make an empty range.
770b57cec5SDimitry Andric         Min = 0;
780b57cec5SDimitry Andric         Max = -1;
790b57cec5SDimitry Andric       }
800b57cec5SDimitry Andric       // Canonicalize empty ranges.
810b57cec5SDimitry Andric       if (Min > Max)
820b57cec5SDimitry Andric         std::tie(Min, Max, Align) = std::make_tuple(0, -1, 1);
830b57cec5SDimitry Andric       return *this;
840b57cec5SDimitry Andric     }
850b57cec5SDimitry Andric     OffsetRange &shift(int32_t S) {
860b57cec5SDimitry Andric       Min += S;
870b57cec5SDimitry Andric       Max += S;
880b57cec5SDimitry Andric       Offset = (Offset+S) % Align;
890b57cec5SDimitry Andric       return *this;
900b57cec5SDimitry Andric     }
910b57cec5SDimitry Andric     OffsetRange &extendBy(int32_t D) {
920b57cec5SDimitry Andric       // If D < 0, extend Min, otherwise extend Max.
930b57cec5SDimitry Andric       assert(D % Align == 0);
940b57cec5SDimitry Andric       if (D < 0)
950b57cec5SDimitry Andric         Min = (INT_MIN-D < Min) ? Min+D : INT_MIN;
960b57cec5SDimitry Andric       else
970b57cec5SDimitry Andric         Max = (INT_MAX-D > Max) ? Max+D : INT_MAX;
980b57cec5SDimitry Andric       return *this;
990b57cec5SDimitry Andric     }
1000b57cec5SDimitry Andric     bool empty() const {
1010b57cec5SDimitry Andric       return Min > Max;
1020b57cec5SDimitry Andric     }
1030b57cec5SDimitry Andric     bool contains(int32_t V) const {
1040b57cec5SDimitry Andric       return Min <= V && V <= Max && (V-Offset) % Align == 0;
1050b57cec5SDimitry Andric     }
1060b57cec5SDimitry Andric     bool operator==(const OffsetRange &R) const {
1070b57cec5SDimitry Andric       return Min == R.Min && Max == R.Max && Align == R.Align;
1080b57cec5SDimitry Andric     }
1090b57cec5SDimitry Andric     bool operator!=(const OffsetRange &R) const {
1100b57cec5SDimitry Andric       return !operator==(R);
1110b57cec5SDimitry Andric     }
1120b57cec5SDimitry Andric     bool operator<(const OffsetRange &R) const {
1130b57cec5SDimitry Andric       if (Min != R.Min)
1140b57cec5SDimitry Andric         return Min < R.Min;
1150b57cec5SDimitry Andric       if (Max != R.Max)
1160b57cec5SDimitry Andric         return Max < R.Max;
1170b57cec5SDimitry Andric       return Align < R.Align;
1180b57cec5SDimitry Andric     }
1190b57cec5SDimitry Andric     static OffsetRange zero() { return {0, 0, 1}; }
1200b57cec5SDimitry Andric   };
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   struct RangeTree {
1230b57cec5SDimitry Andric     struct Node {
1240b57cec5SDimitry Andric       Node(const OffsetRange &R) : MaxEnd(R.Max), Range(R) {}
1250b57cec5SDimitry Andric       unsigned Height = 1;
1260b57cec5SDimitry Andric       unsigned Count = 1;
1270b57cec5SDimitry Andric       int32_t MaxEnd;
1280b57cec5SDimitry Andric       const OffsetRange &Range;
1290b57cec5SDimitry Andric       Node *Left = nullptr, *Right = nullptr;
1300b57cec5SDimitry Andric     };
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric     Node *Root = nullptr;
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric     void add(const OffsetRange &R) {
1350b57cec5SDimitry Andric       Root = add(Root, R);
1360b57cec5SDimitry Andric     }
1370b57cec5SDimitry Andric     void erase(const Node *N) {
1380b57cec5SDimitry Andric       Root = remove(Root, N);
1390b57cec5SDimitry Andric       delete N;
1400b57cec5SDimitry Andric     }
1410b57cec5SDimitry Andric     void order(SmallVectorImpl<Node*> &Seq) const {
1420b57cec5SDimitry Andric       order(Root, Seq);
1430b57cec5SDimitry Andric     }
1440b57cec5SDimitry Andric     SmallVector<Node*,8> nodesWith(int32_t P, bool CheckAlign = true) {
1450b57cec5SDimitry Andric       SmallVector<Node*,8> Nodes;
1460b57cec5SDimitry Andric       nodesWith(Root, P, CheckAlign, Nodes);
1470b57cec5SDimitry Andric       return Nodes;
1480b57cec5SDimitry Andric     }
1490b57cec5SDimitry Andric     void dump() const;
1500b57cec5SDimitry Andric     ~RangeTree() {
1510b57cec5SDimitry Andric       SmallVector<Node*,8> Nodes;
1520b57cec5SDimitry Andric       order(Nodes);
1530b57cec5SDimitry Andric       for (Node *N : Nodes)
1540b57cec5SDimitry Andric         delete N;
1550b57cec5SDimitry Andric     }
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric   private:
1580b57cec5SDimitry Andric     void dump(const Node *N) const;
1590b57cec5SDimitry Andric     void order(Node *N, SmallVectorImpl<Node*> &Seq) const;
1600b57cec5SDimitry Andric     void nodesWith(Node *N, int32_t P, bool CheckA,
1610b57cec5SDimitry Andric                    SmallVectorImpl<Node*> &Seq) const;
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric     Node *add(Node *N, const OffsetRange &R);
1640b57cec5SDimitry Andric     Node *remove(Node *N, const Node *D);
1650b57cec5SDimitry Andric     Node *rotateLeft(Node *Lower, Node *Higher);
1660b57cec5SDimitry Andric     Node *rotateRight(Node *Lower, Node *Higher);
1670b57cec5SDimitry Andric     unsigned height(Node *N) {
1680b57cec5SDimitry Andric       return N != nullptr ? N->Height : 0;
1690b57cec5SDimitry Andric     }
1700b57cec5SDimitry Andric     Node *update(Node *N) {
1710b57cec5SDimitry Andric       assert(N != nullptr);
1720b57cec5SDimitry Andric       N->Height = 1 + std::max(height(N->Left), height(N->Right));
1730b57cec5SDimitry Andric       if (N->Left)
1740b57cec5SDimitry Andric         N->MaxEnd = std::max(N->MaxEnd, N->Left->MaxEnd);
1750b57cec5SDimitry Andric       if (N->Right)
1760b57cec5SDimitry Andric         N->MaxEnd = std::max(N->MaxEnd, N->Right->MaxEnd);
1770b57cec5SDimitry Andric       return N;
1780b57cec5SDimitry Andric     }
1790b57cec5SDimitry Andric     Node *rebalance(Node *N) {
1800b57cec5SDimitry Andric       assert(N != nullptr);
1810b57cec5SDimitry Andric       int32_t Balance = height(N->Right) - height(N->Left);
1820b57cec5SDimitry Andric       if (Balance < -1)
1830b57cec5SDimitry Andric         return rotateRight(N->Left, N);
1840b57cec5SDimitry Andric       if (Balance > 1)
1850b57cec5SDimitry Andric         return rotateLeft(N->Right, N);
1860b57cec5SDimitry Andric       return N;
1870b57cec5SDimitry Andric     }
1880b57cec5SDimitry Andric   };
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   struct Loc {
1910b57cec5SDimitry Andric     MachineBasicBlock *Block = nullptr;
1920b57cec5SDimitry Andric     MachineBasicBlock::iterator At;
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric     Loc(MachineBasicBlock *B, MachineBasicBlock::iterator It)
1950b57cec5SDimitry Andric       : Block(B), At(It) {
1960b57cec5SDimitry Andric       if (B->end() == It) {
1970b57cec5SDimitry Andric         Pos = -1;
1980b57cec5SDimitry Andric       } else {
1990b57cec5SDimitry Andric         assert(It->getParent() == B);
2000b57cec5SDimitry Andric         Pos = std::distance(B->begin(), It);
2010b57cec5SDimitry Andric       }
2020b57cec5SDimitry Andric     }
2030b57cec5SDimitry Andric     bool operator<(Loc A) const {
2040b57cec5SDimitry Andric       if (Block != A.Block)
2050b57cec5SDimitry Andric         return Block->getNumber() < A.Block->getNumber();
2060b57cec5SDimitry Andric       if (A.Pos == -1)
2070b57cec5SDimitry Andric         return Pos != A.Pos;
2080b57cec5SDimitry Andric       return Pos != -1 && Pos < A.Pos;
2090b57cec5SDimitry Andric     }
2100b57cec5SDimitry Andric   private:
2110b57cec5SDimitry Andric     int Pos = 0;
2120b57cec5SDimitry Andric   };
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   struct HexagonConstExtenders : public MachineFunctionPass {
2150b57cec5SDimitry Andric     static char ID;
2160b57cec5SDimitry Andric     HexagonConstExtenders() : MachineFunctionPass(ID) {}
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric     void getAnalysisUsage(AnalysisUsage &AU) const override {
2190b57cec5SDimitry Andric       AU.addRequired<MachineDominatorTree>();
2200b57cec5SDimitry Andric       AU.addPreserved<MachineDominatorTree>();
2210b57cec5SDimitry Andric       MachineFunctionPass::getAnalysisUsage(AU);
2220b57cec5SDimitry Andric     }
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric     StringRef getPassName() const override {
2250b57cec5SDimitry Andric       return "Hexagon constant-extender optimization";
2260b57cec5SDimitry Andric     }
2270b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &MF) override;
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   private:
2300b57cec5SDimitry Andric     struct Register {
2310b57cec5SDimitry Andric       Register() = default;
2320b57cec5SDimitry Andric       Register(unsigned R, unsigned S) : Reg(R), Sub(S) {}
2330b57cec5SDimitry Andric       Register(const MachineOperand &Op)
2340b57cec5SDimitry Andric         : Reg(Op.getReg()), Sub(Op.getSubReg()) {}
2350b57cec5SDimitry Andric       Register &operator=(const MachineOperand &Op) {
2360b57cec5SDimitry Andric         if (Op.isReg()) {
2370b57cec5SDimitry Andric           Reg = Op.getReg();
2380b57cec5SDimitry Andric           Sub = Op.getSubReg();
2390b57cec5SDimitry Andric         } else if (Op.isFI()) {
2408bcb0991SDimitry Andric           Reg = llvm::Register::index2StackSlot(Op.getIndex());
2410b57cec5SDimitry Andric         }
2420b57cec5SDimitry Andric         return *this;
2430b57cec5SDimitry Andric       }
2440b57cec5SDimitry Andric       bool isVReg() const {
2458bcb0991SDimitry Andric         return Reg != 0 && !llvm::Register::isStackSlot(Reg) &&
2468bcb0991SDimitry Andric                llvm::Register::isVirtualRegister(Reg);
2470b57cec5SDimitry Andric       }
2480b57cec5SDimitry Andric       bool isSlot() const {
2498bcb0991SDimitry Andric         return Reg != 0 && llvm::Register::isStackSlot(Reg);
2500b57cec5SDimitry Andric       }
2510b57cec5SDimitry Andric       operator MachineOperand() const {
2520b57cec5SDimitry Andric         if (isVReg())
2530b57cec5SDimitry Andric           return MachineOperand::CreateReg(Reg, /*Def*/false, /*Imp*/false,
2540b57cec5SDimitry Andric                           /*Kill*/false, /*Dead*/false, /*Undef*/false,
2550b57cec5SDimitry Andric                           /*EarlyClobber*/false, Sub);
2568bcb0991SDimitry Andric         if (llvm::Register::isStackSlot(Reg)) {
2578bcb0991SDimitry Andric           int FI = llvm::Register::stackSlot2Index(Reg);
2580b57cec5SDimitry Andric           return MachineOperand::CreateFI(FI);
2590b57cec5SDimitry Andric         }
2600b57cec5SDimitry Andric         llvm_unreachable("Cannot create MachineOperand");
2610b57cec5SDimitry Andric       }
2620b57cec5SDimitry Andric       bool operator==(Register R) const { return Reg == R.Reg && Sub == R.Sub; }
2630b57cec5SDimitry Andric       bool operator!=(Register R) const { return !operator==(R); }
2640b57cec5SDimitry Andric       bool operator<(Register R) const {
2650b57cec5SDimitry Andric         // For std::map.
2660b57cec5SDimitry Andric         return Reg < R.Reg || (Reg == R.Reg && Sub < R.Sub);
2670b57cec5SDimitry Andric       }
2680b57cec5SDimitry Andric       unsigned Reg = 0, Sub = 0;
2690b57cec5SDimitry Andric     };
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric     struct ExtExpr {
2720b57cec5SDimitry Andric       // A subexpression in which the extender is used. In general, this
2730b57cec5SDimitry Andric       // represents an expression where adding D to the extender will be
2740b57cec5SDimitry Andric       // equivalent to adding D to the expression as a whole. In other
2750b57cec5SDimitry Andric       // words, expr(add(##V,D) = add(expr(##V),D).
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric       // The original motivation for this are the io/ur addressing modes,
2780b57cec5SDimitry Andric       // where the offset is extended. Consider the io example:
2790b57cec5SDimitry Andric       // In memw(Rs+##V), the ##V could be replaced by a register Rt to
2800b57cec5SDimitry Andric       // form the rr mode: memw(Rt+Rs<<0). In such case, however, the
2810b57cec5SDimitry Andric       // register Rt must have exactly the value of ##V. If there was
2820b57cec5SDimitry Andric       // another instruction memw(Rs+##V+4), it would need a different Rt.
2830b57cec5SDimitry Andric       // Now, if Rt was initialized as "##V+Rs<<0", both of these
2840b57cec5SDimitry Andric       // instructions could use the same Rt, just with different offsets.
2850b57cec5SDimitry Andric       // Here it's clear that "initializer+4" should be the same as if
2860b57cec5SDimitry Andric       // the offset 4 was added to the ##V in the initializer.
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric       // The only kinds of expressions that support the requirement of
2890b57cec5SDimitry Andric       // commuting with addition are addition and subtraction from ##V.
2900b57cec5SDimitry Andric       // Include shifting the Rs to account for the ur addressing mode:
2910b57cec5SDimitry Andric       //   ##Val + Rs << S
2920b57cec5SDimitry Andric       //   ##Val - Rs
2930b57cec5SDimitry Andric       Register Rs;
2940b57cec5SDimitry Andric       unsigned S = 0;
2950b57cec5SDimitry Andric       bool Neg = false;
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric       ExtExpr() = default;
2980b57cec5SDimitry Andric       ExtExpr(Register RS, bool NG, unsigned SH) : Rs(RS), S(SH), Neg(NG) {}
2990b57cec5SDimitry Andric       // Expression is trivial if it does not modify the extender.
3000b57cec5SDimitry Andric       bool trivial() const {
3010b57cec5SDimitry Andric         return Rs.Reg == 0;
3020b57cec5SDimitry Andric       }
3030b57cec5SDimitry Andric       bool operator==(const ExtExpr &Ex) const {
3040b57cec5SDimitry Andric         return Rs == Ex.Rs && S == Ex.S && Neg == Ex.Neg;
3050b57cec5SDimitry Andric       }
3060b57cec5SDimitry Andric       bool operator!=(const ExtExpr &Ex) const {
3070b57cec5SDimitry Andric         return !operator==(Ex);
3080b57cec5SDimitry Andric       }
3090b57cec5SDimitry Andric       bool operator<(const ExtExpr &Ex) const {
3100b57cec5SDimitry Andric         if (Rs != Ex.Rs)
3110b57cec5SDimitry Andric           return Rs < Ex.Rs;
3120b57cec5SDimitry Andric         if (S != Ex.S)
3130b57cec5SDimitry Andric           return S < Ex.S;
3140b57cec5SDimitry Andric         return !Neg && Ex.Neg;
3150b57cec5SDimitry Andric       }
3160b57cec5SDimitry Andric     };
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric     struct ExtDesc {
3190b57cec5SDimitry Andric       MachineInstr *UseMI = nullptr;
3200b57cec5SDimitry Andric       unsigned OpNum = -1u;
3210b57cec5SDimitry Andric       // The subexpression in which the extender is used (e.g. address
3220b57cec5SDimitry Andric       // computation).
3230b57cec5SDimitry Andric       ExtExpr Expr;
3240b57cec5SDimitry Andric       // Optional register that is assigned the value of Expr.
3250b57cec5SDimitry Andric       Register Rd;
3260b57cec5SDimitry Andric       // Def means that the output of the instruction may differ from the
3270b57cec5SDimitry Andric       // original by a constant c, and that the difference can be corrected
3280b57cec5SDimitry Andric       // by adding/subtracting c in all users of the defined register.
3290b57cec5SDimitry Andric       bool IsDef = false;
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric       MachineOperand &getOp() {
3320b57cec5SDimitry Andric         return UseMI->getOperand(OpNum);
3330b57cec5SDimitry Andric       }
3340b57cec5SDimitry Andric       const MachineOperand &getOp() const {
3350b57cec5SDimitry Andric         return UseMI->getOperand(OpNum);
3360b57cec5SDimitry Andric       }
3370b57cec5SDimitry Andric     };
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric     struct ExtRoot {
3400b57cec5SDimitry Andric       union {
3410b57cec5SDimitry Andric         const ConstantFP *CFP;  // MO_FPImmediate
3420b57cec5SDimitry Andric         const char *SymbolName; // MO_ExternalSymbol
3430b57cec5SDimitry Andric         const GlobalValue *GV;  // MO_GlobalAddress
3440b57cec5SDimitry Andric         const BlockAddress *BA; // MO_BlockAddress
3450b57cec5SDimitry Andric         int64_t ImmVal;         // MO_Immediate, MO_TargetIndex,
3460b57cec5SDimitry Andric                                 // and MO_ConstantPoolIndex
3470b57cec5SDimitry Andric       } V;
3480b57cec5SDimitry Andric       unsigned Kind;            // Same as in MachineOperand.
3490b57cec5SDimitry Andric       unsigned char TF;         // TargetFlags.
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric       ExtRoot(const MachineOperand &Op);
3520b57cec5SDimitry Andric       bool operator==(const ExtRoot &ER) const {
3530b57cec5SDimitry Andric         return Kind == ER.Kind && V.ImmVal == ER.V.ImmVal;
3540b57cec5SDimitry Andric       }
3550b57cec5SDimitry Andric       bool operator!=(const ExtRoot &ER) const {
3560b57cec5SDimitry Andric         return !operator==(ER);
3570b57cec5SDimitry Andric       }
3580b57cec5SDimitry Andric       bool operator<(const ExtRoot &ER) const;
3590b57cec5SDimitry Andric     };
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric     struct ExtValue : public ExtRoot {
3620b57cec5SDimitry Andric       int32_t Offset;
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric       ExtValue(const MachineOperand &Op);
3650b57cec5SDimitry Andric       ExtValue(const ExtDesc &ED) : ExtValue(ED.getOp()) {}
3660b57cec5SDimitry Andric       ExtValue(const ExtRoot &ER, int32_t Off) : ExtRoot(ER), Offset(Off) {}
3670b57cec5SDimitry Andric       bool operator<(const ExtValue &EV) const;
3680b57cec5SDimitry Andric       bool operator==(const ExtValue &EV) const {
3690b57cec5SDimitry Andric         return ExtRoot(*this) == ExtRoot(EV) && Offset == EV.Offset;
3700b57cec5SDimitry Andric       }
3710b57cec5SDimitry Andric       bool operator!=(const ExtValue &EV) const {
3720b57cec5SDimitry Andric         return !operator==(EV);
3730b57cec5SDimitry Andric       }
3740b57cec5SDimitry Andric       explicit operator MachineOperand() const;
3750b57cec5SDimitry Andric     };
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric     using IndexList = SetVector<unsigned>;
3780b57cec5SDimitry Andric     using ExtenderInit = std::pair<ExtValue, ExtExpr>;
3790b57cec5SDimitry Andric     using AssignmentMap = std::map<ExtenderInit, IndexList>;
3800b57cec5SDimitry Andric     using LocDefList = std::vector<std::pair<Loc, IndexList>>;
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric     const HexagonInstrInfo *HII = nullptr;
3830b57cec5SDimitry Andric     const HexagonRegisterInfo *HRI = nullptr;
3840b57cec5SDimitry Andric     MachineDominatorTree *MDT = nullptr;
3850b57cec5SDimitry Andric     MachineRegisterInfo *MRI = nullptr;
3860b57cec5SDimitry Andric     std::vector<ExtDesc> Extenders;
3870b57cec5SDimitry Andric     std::vector<unsigned> NewRegs;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric     bool isStoreImmediate(unsigned Opc) const;
3900b57cec5SDimitry Andric     bool isRegOffOpcode(unsigned ExtOpc) const ;
3910b57cec5SDimitry Andric     unsigned getRegOffOpcode(unsigned ExtOpc) const;
3920b57cec5SDimitry Andric     unsigned getDirectRegReplacement(unsigned ExtOpc) const;
3930b57cec5SDimitry Andric     OffsetRange getOffsetRange(Register R, const MachineInstr &MI) const;
3940b57cec5SDimitry Andric     OffsetRange getOffsetRange(const ExtDesc &ED) const;
3950b57cec5SDimitry Andric     OffsetRange getOffsetRange(Register Rd) const;
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric     void recordExtender(MachineInstr &MI, unsigned OpNum);
3980b57cec5SDimitry Andric     void collectInstr(MachineInstr &MI);
3990b57cec5SDimitry Andric     void collect(MachineFunction &MF);
4000b57cec5SDimitry Andric     void assignInits(const ExtRoot &ER, unsigned Begin, unsigned End,
4010b57cec5SDimitry Andric                      AssignmentMap &IMap);
4020b57cec5SDimitry Andric     void calculatePlacement(const ExtenderInit &ExtI, const IndexList &Refs,
4030b57cec5SDimitry Andric                             LocDefList &Defs);
4040b57cec5SDimitry Andric     Register insertInitializer(Loc DefL, const ExtenderInit &ExtI);
4050b57cec5SDimitry Andric     bool replaceInstrExact(const ExtDesc &ED, Register ExtR);
4060b57cec5SDimitry Andric     bool replaceInstrExpr(const ExtDesc &ED, const ExtenderInit &ExtI,
4070b57cec5SDimitry Andric                           Register ExtR, int32_t &Diff);
4080b57cec5SDimitry Andric     bool replaceInstr(unsigned Idx, Register ExtR, const ExtenderInit &ExtI);
4090b57cec5SDimitry Andric     bool replaceExtenders(const AssignmentMap &IMap);
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric     unsigned getOperandIndex(const MachineInstr &MI,
4120b57cec5SDimitry Andric                              const MachineOperand &Op) const;
4130b57cec5SDimitry Andric     const MachineOperand &getPredicateOp(const MachineInstr &MI) const;
4140b57cec5SDimitry Andric     const MachineOperand &getLoadResultOp(const MachineInstr &MI) const;
4150b57cec5SDimitry Andric     const MachineOperand &getStoredValueOp(const MachineInstr &MI) const;
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric     friend struct PrintRegister;
4180b57cec5SDimitry Andric     friend struct PrintExpr;
4190b57cec5SDimitry Andric     friend struct PrintInit;
4200b57cec5SDimitry Andric     friend struct PrintIMap;
4210b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS,
4220b57cec5SDimitry Andric                                     const struct PrintRegister &P);
4230b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS, const struct PrintExpr &P);
4240b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS, const struct PrintInit &P);
4250b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS, const ExtDesc &ED);
4260b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS, const ExtRoot &ER);
4270b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS, const ExtValue &EV);
4280b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS, const OffsetRange &OR);
4290b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS, const struct PrintIMap &P);
4300b57cec5SDimitry Andric   };
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric   using HCE = HexagonConstExtenders;
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
4350b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const OffsetRange &OR) {
4360b57cec5SDimitry Andric     if (OR.Min > OR.Max)
4370b57cec5SDimitry Andric       OS << '!';
4380b57cec5SDimitry Andric     OS << '[' << OR.Min << ',' << OR.Max << "]a" << unsigned(OR.Align)
4390b57cec5SDimitry Andric        << '+' << unsigned(OR.Offset);
4400b57cec5SDimitry Andric     return OS;
4410b57cec5SDimitry Andric   }
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric   struct PrintRegister {
4440b57cec5SDimitry Andric     PrintRegister(HCE::Register R, const HexagonRegisterInfo &I)
4450b57cec5SDimitry Andric       : Rs(R), HRI(I) {}
4460b57cec5SDimitry Andric     HCE::Register Rs;
4470b57cec5SDimitry Andric     const HexagonRegisterInfo &HRI;
4480b57cec5SDimitry Andric   };
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
4510b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const PrintRegister &P) {
4520b57cec5SDimitry Andric     if (P.Rs.Reg != 0)
4530b57cec5SDimitry Andric       OS << printReg(P.Rs.Reg, &P.HRI, P.Rs.Sub);
4540b57cec5SDimitry Andric     else
4550b57cec5SDimitry Andric       OS << "noreg";
4560b57cec5SDimitry Andric     return OS;
4570b57cec5SDimitry Andric   }
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric   struct PrintExpr {
4600b57cec5SDimitry Andric     PrintExpr(const HCE::ExtExpr &E, const HexagonRegisterInfo &I)
4610b57cec5SDimitry Andric       : Ex(E), HRI(I) {}
4620b57cec5SDimitry Andric     const HCE::ExtExpr &Ex;
4630b57cec5SDimitry Andric     const HexagonRegisterInfo &HRI;
4640b57cec5SDimitry Andric   };
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
4670b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const PrintExpr &P) {
4680b57cec5SDimitry Andric     OS << "## " << (P.Ex.Neg ? "- " : "+ ");
4690b57cec5SDimitry Andric     if (P.Ex.Rs.Reg != 0)
4700b57cec5SDimitry Andric       OS << printReg(P.Ex.Rs.Reg, &P.HRI, P.Ex.Rs.Sub);
4710b57cec5SDimitry Andric     else
4720b57cec5SDimitry Andric       OS << "__";
4730b57cec5SDimitry Andric     OS << " << " << P.Ex.S;
4740b57cec5SDimitry Andric     return OS;
4750b57cec5SDimitry Andric   }
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   struct PrintInit {
4780b57cec5SDimitry Andric     PrintInit(const HCE::ExtenderInit &EI, const HexagonRegisterInfo &I)
4790b57cec5SDimitry Andric       : ExtI(EI), HRI(I) {}
4800b57cec5SDimitry Andric     const HCE::ExtenderInit &ExtI;
4810b57cec5SDimitry Andric     const HexagonRegisterInfo &HRI;
4820b57cec5SDimitry Andric   };
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
4850b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const PrintInit &P) {
4860b57cec5SDimitry Andric     OS << '[' << P.ExtI.first << ", "
4870b57cec5SDimitry Andric        << PrintExpr(P.ExtI.second, P.HRI) << ']';
4880b57cec5SDimitry Andric     return OS;
4890b57cec5SDimitry Andric   }
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
4920b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const HCE::ExtDesc &ED) {
4930b57cec5SDimitry Andric     assert(ED.OpNum != -1u);
4940b57cec5SDimitry Andric     const MachineBasicBlock &MBB = *ED.getOp().getParent()->getParent();
4950b57cec5SDimitry Andric     const MachineFunction &MF = *MBB.getParent();
4960b57cec5SDimitry Andric     const auto &HRI = *MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
4970b57cec5SDimitry Andric     OS << "bb#" << MBB.getNumber() << ": ";
4980b57cec5SDimitry Andric     if (ED.Rd.Reg != 0)
4990b57cec5SDimitry Andric       OS << printReg(ED.Rd.Reg, &HRI, ED.Rd.Sub);
5000b57cec5SDimitry Andric     else
5010b57cec5SDimitry Andric       OS << "__";
5020b57cec5SDimitry Andric     OS << " = " << PrintExpr(ED.Expr, HRI);
5030b57cec5SDimitry Andric     if (ED.IsDef)
5040b57cec5SDimitry Andric       OS << ", def";
5050b57cec5SDimitry Andric     return OS;
5060b57cec5SDimitry Andric   }
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
5090b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const HCE::ExtRoot &ER) {
5100b57cec5SDimitry Andric     switch (ER.Kind) {
5110b57cec5SDimitry Andric       case MachineOperand::MO_Immediate:
5120b57cec5SDimitry Andric         OS << "imm:" << ER.V.ImmVal;
5130b57cec5SDimitry Andric         break;
5140b57cec5SDimitry Andric       case MachineOperand::MO_FPImmediate:
5150b57cec5SDimitry Andric         OS << "fpi:" << *ER.V.CFP;
5160b57cec5SDimitry Andric         break;
5170b57cec5SDimitry Andric       case MachineOperand::MO_ExternalSymbol:
5180b57cec5SDimitry Andric         OS << "sym:" << *ER.V.SymbolName;
5190b57cec5SDimitry Andric         break;
5200b57cec5SDimitry Andric       case MachineOperand::MO_GlobalAddress:
5210b57cec5SDimitry Andric         OS << "gad:" << ER.V.GV->getName();
5220b57cec5SDimitry Andric         break;
5230b57cec5SDimitry Andric       case MachineOperand::MO_BlockAddress:
5240b57cec5SDimitry Andric         OS << "blk:" << *ER.V.BA;
5250b57cec5SDimitry Andric         break;
5260b57cec5SDimitry Andric       case MachineOperand::MO_TargetIndex:
5270b57cec5SDimitry Andric         OS << "tgi:" << ER.V.ImmVal;
5280b57cec5SDimitry Andric         break;
5290b57cec5SDimitry Andric       case MachineOperand::MO_ConstantPoolIndex:
5300b57cec5SDimitry Andric         OS << "cpi:" << ER.V.ImmVal;
5310b57cec5SDimitry Andric         break;
5320b57cec5SDimitry Andric       case MachineOperand::MO_JumpTableIndex:
5330b57cec5SDimitry Andric         OS << "jti:" << ER.V.ImmVal;
5340b57cec5SDimitry Andric         break;
5350b57cec5SDimitry Andric       default:
5360b57cec5SDimitry Andric         OS << "???:" << ER.V.ImmVal;
5370b57cec5SDimitry Andric         break;
5380b57cec5SDimitry Andric     }
5390b57cec5SDimitry Andric     return OS;
5400b57cec5SDimitry Andric   }
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
5430b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const HCE::ExtValue &EV) {
5440b57cec5SDimitry Andric     OS << HCE::ExtRoot(EV) << "  off:" << EV.Offset;
5450b57cec5SDimitry Andric     return OS;
5460b57cec5SDimitry Andric   }
5470b57cec5SDimitry Andric 
5480b57cec5SDimitry Andric   struct PrintIMap {
5490b57cec5SDimitry Andric     PrintIMap(const HCE::AssignmentMap &M, const HexagonRegisterInfo &I)
5500b57cec5SDimitry Andric       : IMap(M), HRI(I) {}
5510b57cec5SDimitry Andric     const HCE::AssignmentMap &IMap;
5520b57cec5SDimitry Andric     const HexagonRegisterInfo &HRI;
5530b57cec5SDimitry Andric   };
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
5560b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const PrintIMap &P) {
5570b57cec5SDimitry Andric     OS << "{\n";
558*480093f4SDimitry Andric     for (const std::pair<const HCE::ExtenderInit, HCE::IndexList> &Q : P.IMap) {
5590b57cec5SDimitry Andric       OS << "  " << PrintInit(Q.first, P.HRI) << " -> {";
5600b57cec5SDimitry Andric       for (unsigned I : Q.second)
5610b57cec5SDimitry Andric         OS << ' ' << I;
5620b57cec5SDimitry Andric       OS << " }\n";
5630b57cec5SDimitry Andric     }
5640b57cec5SDimitry Andric     OS << "}\n";
5650b57cec5SDimitry Andric     return OS;
5660b57cec5SDimitry Andric   }
5670b57cec5SDimitry Andric }
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(HexagonConstExtenders, "hexagon-cext-opt",
5700b57cec5SDimitry Andric       "Hexagon constant-extender optimization", false, false)
5710b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
5720b57cec5SDimitry Andric INITIALIZE_PASS_END(HexagonConstExtenders, "hexagon-cext-opt",
5730b57cec5SDimitry Andric       "Hexagon constant-extender optimization", false, false)
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric static unsigned ReplaceCounter = 0;
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric char HCE::ID = 0;
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric #ifndef NDEBUG
5800b57cec5SDimitry Andric LLVM_DUMP_METHOD void RangeTree::dump() const {
5810b57cec5SDimitry Andric   dbgs() << "Root: " << Root << '\n';
5820b57cec5SDimitry Andric   if (Root)
5830b57cec5SDimitry Andric     dump(Root);
5840b57cec5SDimitry Andric }
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric LLVM_DUMP_METHOD void RangeTree::dump(const Node *N) const {
5870b57cec5SDimitry Andric   dbgs() << "Node: " << N << '\n';
5880b57cec5SDimitry Andric   dbgs() << "  Height: " << N->Height << '\n';
5890b57cec5SDimitry Andric   dbgs() << "  Count: " << N->Count << '\n';
5900b57cec5SDimitry Andric   dbgs() << "  MaxEnd: " << N->MaxEnd << '\n';
5910b57cec5SDimitry Andric   dbgs() << "  Range: " << N->Range << '\n';
5920b57cec5SDimitry Andric   dbgs() << "  Left: " << N->Left << '\n';
5930b57cec5SDimitry Andric   dbgs() << "  Right: " << N->Right << "\n\n";
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   if (N->Left)
5960b57cec5SDimitry Andric     dump(N->Left);
5970b57cec5SDimitry Andric   if (N->Right)
5980b57cec5SDimitry Andric     dump(N->Right);
5990b57cec5SDimitry Andric }
6000b57cec5SDimitry Andric #endif
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric void RangeTree::order(Node *N, SmallVectorImpl<Node*> &Seq) const {
6030b57cec5SDimitry Andric   if (N == nullptr)
6040b57cec5SDimitry Andric     return;
6050b57cec5SDimitry Andric   order(N->Left, Seq);
6060b57cec5SDimitry Andric   Seq.push_back(N);
6070b57cec5SDimitry Andric   order(N->Right, Seq);
6080b57cec5SDimitry Andric }
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric void RangeTree::nodesWith(Node *N, int32_t P, bool CheckA,
6110b57cec5SDimitry Andric       SmallVectorImpl<Node*> &Seq) const {
6120b57cec5SDimitry Andric   if (N == nullptr || N->MaxEnd < P)
6130b57cec5SDimitry Andric     return;
6140b57cec5SDimitry Andric   nodesWith(N->Left, P, CheckA, Seq);
6150b57cec5SDimitry Andric   if (N->Range.Min <= P) {
6160b57cec5SDimitry Andric     if ((CheckA && N->Range.contains(P)) || (!CheckA && P <= N->Range.Max))
6170b57cec5SDimitry Andric       Seq.push_back(N);
6180b57cec5SDimitry Andric     nodesWith(N->Right, P, CheckA, Seq);
6190b57cec5SDimitry Andric   }
6200b57cec5SDimitry Andric }
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric RangeTree::Node *RangeTree::add(Node *N, const OffsetRange &R) {
6230b57cec5SDimitry Andric   if (N == nullptr)
6240b57cec5SDimitry Andric     return new Node(R);
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric   if (N->Range == R) {
6270b57cec5SDimitry Andric     N->Count++;
6280b57cec5SDimitry Andric     return N;
6290b57cec5SDimitry Andric   }
6300b57cec5SDimitry Andric 
6310b57cec5SDimitry Andric   if (R < N->Range)
6320b57cec5SDimitry Andric     N->Left = add(N->Left, R);
6330b57cec5SDimitry Andric   else
6340b57cec5SDimitry Andric     N->Right = add(N->Right, R);
6350b57cec5SDimitry Andric   return rebalance(update(N));
6360b57cec5SDimitry Andric }
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric RangeTree::Node *RangeTree::remove(Node *N, const Node *D) {
6390b57cec5SDimitry Andric   assert(N != nullptr);
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric   if (N != D) {
6420b57cec5SDimitry Andric     assert(N->Range != D->Range && "N and D should not be equal");
6430b57cec5SDimitry Andric     if (D->Range < N->Range)
6440b57cec5SDimitry Andric       N->Left = remove(N->Left, D);
6450b57cec5SDimitry Andric     else
6460b57cec5SDimitry Andric       N->Right = remove(N->Right, D);
6470b57cec5SDimitry Andric     return rebalance(update(N));
6480b57cec5SDimitry Andric   }
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric   // We got to the node we need to remove. If any of its children are
6510b57cec5SDimitry Andric   // missing, simply replace it with the other child.
6520b57cec5SDimitry Andric   if (N->Left == nullptr || N->Right == nullptr)
6530b57cec5SDimitry Andric     return (N->Left == nullptr) ? N->Right : N->Left;
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric   // Find the rightmost child of N->Left, remove it and plug it in place
6560b57cec5SDimitry Andric   // of N.
6570b57cec5SDimitry Andric   Node *M = N->Left;
6580b57cec5SDimitry Andric   while (M->Right)
6590b57cec5SDimitry Andric     M = M->Right;
6600b57cec5SDimitry Andric   M->Left = remove(N->Left, M);
6610b57cec5SDimitry Andric   M->Right = N->Right;
6620b57cec5SDimitry Andric   return rebalance(update(M));
6630b57cec5SDimitry Andric }
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric RangeTree::Node *RangeTree::rotateLeft(Node *Lower, Node *Higher) {
6660b57cec5SDimitry Andric   assert(Higher->Right == Lower);
6670b57cec5SDimitry Andric   // The Lower node is on the right from Higher. Make sure that Lower's
6680b57cec5SDimitry Andric   // balance is greater to the right. Otherwise the rotation will create
6690b57cec5SDimitry Andric   // an unbalanced tree again.
6700b57cec5SDimitry Andric   if (height(Lower->Left) > height(Lower->Right))
6710b57cec5SDimitry Andric     Lower = rotateRight(Lower->Left, Lower);
6720b57cec5SDimitry Andric   assert(height(Lower->Left) <= height(Lower->Right));
6730b57cec5SDimitry Andric   Higher->Right = Lower->Left;
6740b57cec5SDimitry Andric   update(Higher);
6750b57cec5SDimitry Andric   Lower->Left = Higher;
6760b57cec5SDimitry Andric   update(Lower);
6770b57cec5SDimitry Andric   return Lower;
6780b57cec5SDimitry Andric }
6790b57cec5SDimitry Andric 
6800b57cec5SDimitry Andric RangeTree::Node *RangeTree::rotateRight(Node *Lower, Node *Higher) {
6810b57cec5SDimitry Andric   assert(Higher->Left == Lower);
6820b57cec5SDimitry Andric   // The Lower node is on the left from Higher. Make sure that Lower's
6830b57cec5SDimitry Andric   // balance is greater to the left. Otherwise the rotation will create
6840b57cec5SDimitry Andric   // an unbalanced tree again.
6850b57cec5SDimitry Andric   if (height(Lower->Left) < height(Lower->Right))
6860b57cec5SDimitry Andric     Lower = rotateLeft(Lower->Right, Lower);
6870b57cec5SDimitry Andric   assert(height(Lower->Left) >= height(Lower->Right));
6880b57cec5SDimitry Andric   Higher->Left = Lower->Right;
6890b57cec5SDimitry Andric   update(Higher);
6900b57cec5SDimitry Andric   Lower->Right = Higher;
6910b57cec5SDimitry Andric   update(Lower);
6920b57cec5SDimitry Andric   return Lower;
6930b57cec5SDimitry Andric }
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric 
6960b57cec5SDimitry Andric HCE::ExtRoot::ExtRoot(const MachineOperand &Op) {
6970b57cec5SDimitry Andric   // Always store ImmVal, since it's the field used for comparisons.
6980b57cec5SDimitry Andric   V.ImmVal = 0;
6990b57cec5SDimitry Andric   if (Op.isImm())
7000b57cec5SDimitry Andric     ; // Keep 0. Do not use Op.getImm() for value here (treat 0 as the root).
7010b57cec5SDimitry Andric   else if (Op.isFPImm())
7020b57cec5SDimitry Andric     V.CFP = Op.getFPImm();
7030b57cec5SDimitry Andric   else if (Op.isSymbol())
7040b57cec5SDimitry Andric     V.SymbolName = Op.getSymbolName();
7050b57cec5SDimitry Andric   else if (Op.isGlobal())
7060b57cec5SDimitry Andric     V.GV = Op.getGlobal();
7070b57cec5SDimitry Andric   else if (Op.isBlockAddress())
7080b57cec5SDimitry Andric     V.BA = Op.getBlockAddress();
7090b57cec5SDimitry Andric   else if (Op.isCPI() || Op.isTargetIndex() || Op.isJTI())
7100b57cec5SDimitry Andric     V.ImmVal = Op.getIndex();
7110b57cec5SDimitry Andric   else
7120b57cec5SDimitry Andric     llvm_unreachable("Unexpected operand type");
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric   Kind = Op.getType();
7150b57cec5SDimitry Andric   TF = Op.getTargetFlags();
7160b57cec5SDimitry Andric }
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric bool HCE::ExtRoot::operator< (const HCE::ExtRoot &ER) const {
7190b57cec5SDimitry Andric   if (Kind != ER.Kind)
7200b57cec5SDimitry Andric     return Kind < ER.Kind;
7210b57cec5SDimitry Andric   switch (Kind) {
7220b57cec5SDimitry Andric     case MachineOperand::MO_Immediate:
7230b57cec5SDimitry Andric     case MachineOperand::MO_TargetIndex:
7240b57cec5SDimitry Andric     case MachineOperand::MO_ConstantPoolIndex:
7250b57cec5SDimitry Andric     case MachineOperand::MO_JumpTableIndex:
7260b57cec5SDimitry Andric       return V.ImmVal < ER.V.ImmVal;
7270b57cec5SDimitry Andric     case MachineOperand::MO_FPImmediate: {
7280b57cec5SDimitry Andric       const APFloat &ThisF = V.CFP->getValueAPF();
7290b57cec5SDimitry Andric       const APFloat &OtherF = ER.V.CFP->getValueAPF();
7300b57cec5SDimitry Andric       return ThisF.bitcastToAPInt().ult(OtherF.bitcastToAPInt());
7310b57cec5SDimitry Andric     }
7320b57cec5SDimitry Andric     case MachineOperand::MO_ExternalSymbol:
7330b57cec5SDimitry Andric       return StringRef(V.SymbolName) < StringRef(ER.V.SymbolName);
7340b57cec5SDimitry Andric     case MachineOperand::MO_GlobalAddress:
7350b57cec5SDimitry Andric       // Do not use GUIDs, since they depend on the source path. Moving the
7360b57cec5SDimitry Andric       // source file to a different directory could cause different GUID
7370b57cec5SDimitry Andric       // values for a pair of given symbols. These symbols could then compare
7380b57cec5SDimitry Andric       // "less" in one directory, but "greater" in another.
7390b57cec5SDimitry Andric       assert(!V.GV->getName().empty() && !ER.V.GV->getName().empty());
7400b57cec5SDimitry Andric       return V.GV->getName() < ER.V.GV->getName();
7410b57cec5SDimitry Andric     case MachineOperand::MO_BlockAddress: {
7420b57cec5SDimitry Andric       const BasicBlock *ThisB = V.BA->getBasicBlock();
7430b57cec5SDimitry Andric       const BasicBlock *OtherB = ER.V.BA->getBasicBlock();
7440b57cec5SDimitry Andric       assert(ThisB->getParent() == OtherB->getParent());
7450b57cec5SDimitry Andric       const Function &F = *ThisB->getParent();
7460b57cec5SDimitry Andric       return std::distance(F.begin(), ThisB->getIterator()) <
7470b57cec5SDimitry Andric              std::distance(F.begin(), OtherB->getIterator());
7480b57cec5SDimitry Andric     }
7490b57cec5SDimitry Andric   }
7500b57cec5SDimitry Andric   return V.ImmVal < ER.V.ImmVal;
7510b57cec5SDimitry Andric }
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric HCE::ExtValue::ExtValue(const MachineOperand &Op) : ExtRoot(Op) {
7540b57cec5SDimitry Andric   if (Op.isImm())
7550b57cec5SDimitry Andric     Offset = Op.getImm();
7560b57cec5SDimitry Andric   else if (Op.isFPImm() || Op.isJTI())
7570b57cec5SDimitry Andric     Offset = 0;
7580b57cec5SDimitry Andric   else if (Op.isSymbol() || Op.isGlobal() || Op.isBlockAddress() ||
7590b57cec5SDimitry Andric            Op.isCPI() || Op.isTargetIndex())
7600b57cec5SDimitry Andric     Offset = Op.getOffset();
7610b57cec5SDimitry Andric   else
7620b57cec5SDimitry Andric     llvm_unreachable("Unexpected operand type");
7630b57cec5SDimitry Andric }
7640b57cec5SDimitry Andric 
7650b57cec5SDimitry Andric bool HCE::ExtValue::operator< (const HCE::ExtValue &EV) const {
7660b57cec5SDimitry Andric   const ExtRoot &ER = *this;
7670b57cec5SDimitry Andric   if (!(ER == ExtRoot(EV)))
7680b57cec5SDimitry Andric     return ER < EV;
7690b57cec5SDimitry Andric   return Offset < EV.Offset;
7700b57cec5SDimitry Andric }
7710b57cec5SDimitry Andric 
7720b57cec5SDimitry Andric HCE::ExtValue::operator MachineOperand() const {
7730b57cec5SDimitry Andric   switch (Kind) {
7740b57cec5SDimitry Andric     case MachineOperand::MO_Immediate:
7750b57cec5SDimitry Andric       return MachineOperand::CreateImm(V.ImmVal + Offset);
7760b57cec5SDimitry Andric     case MachineOperand::MO_FPImmediate:
7770b57cec5SDimitry Andric       assert(Offset == 0);
7780b57cec5SDimitry Andric       return MachineOperand::CreateFPImm(V.CFP);
7790b57cec5SDimitry Andric     case MachineOperand::MO_ExternalSymbol:
7800b57cec5SDimitry Andric       assert(Offset == 0);
7810b57cec5SDimitry Andric       return MachineOperand::CreateES(V.SymbolName, TF);
7820b57cec5SDimitry Andric     case MachineOperand::MO_GlobalAddress:
7830b57cec5SDimitry Andric       return MachineOperand::CreateGA(V.GV, Offset, TF);
7840b57cec5SDimitry Andric     case MachineOperand::MO_BlockAddress:
7850b57cec5SDimitry Andric       return MachineOperand::CreateBA(V.BA, Offset, TF);
7860b57cec5SDimitry Andric     case MachineOperand::MO_TargetIndex:
7870b57cec5SDimitry Andric       return MachineOperand::CreateTargetIndex(V.ImmVal, Offset, TF);
7880b57cec5SDimitry Andric     case MachineOperand::MO_ConstantPoolIndex:
7890b57cec5SDimitry Andric       return MachineOperand::CreateCPI(V.ImmVal, Offset, TF);
7900b57cec5SDimitry Andric     case MachineOperand::MO_JumpTableIndex:
7910b57cec5SDimitry Andric       assert(Offset == 0);
7920b57cec5SDimitry Andric       return MachineOperand::CreateJTI(V.ImmVal, TF);
7930b57cec5SDimitry Andric     default:
7940b57cec5SDimitry Andric       llvm_unreachable("Unhandled kind");
7950b57cec5SDimitry Andric  }
7960b57cec5SDimitry Andric }
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric bool HCE::isStoreImmediate(unsigned Opc) const {
7990b57cec5SDimitry Andric   switch (Opc) {
8000b57cec5SDimitry Andric     case Hexagon::S4_storeirbt_io:
8010b57cec5SDimitry Andric     case Hexagon::S4_storeirbf_io:
8020b57cec5SDimitry Andric     case Hexagon::S4_storeirht_io:
8030b57cec5SDimitry Andric     case Hexagon::S4_storeirhf_io:
8040b57cec5SDimitry Andric     case Hexagon::S4_storeirit_io:
8050b57cec5SDimitry Andric     case Hexagon::S4_storeirif_io:
8060b57cec5SDimitry Andric     case Hexagon::S4_storeirb_io:
8070b57cec5SDimitry Andric     case Hexagon::S4_storeirh_io:
8080b57cec5SDimitry Andric     case Hexagon::S4_storeiri_io:
8090b57cec5SDimitry Andric       return true;
8100b57cec5SDimitry Andric     default:
8110b57cec5SDimitry Andric       break;
8120b57cec5SDimitry Andric   }
8130b57cec5SDimitry Andric   return false;
8140b57cec5SDimitry Andric }
8150b57cec5SDimitry Andric 
8160b57cec5SDimitry Andric bool HCE::isRegOffOpcode(unsigned Opc) const {
8170b57cec5SDimitry Andric   switch (Opc) {
8180b57cec5SDimitry Andric     case Hexagon::L2_loadrub_io:
8190b57cec5SDimitry Andric     case Hexagon::L2_loadrb_io:
8200b57cec5SDimitry Andric     case Hexagon::L2_loadruh_io:
8210b57cec5SDimitry Andric     case Hexagon::L2_loadrh_io:
8220b57cec5SDimitry Andric     case Hexagon::L2_loadri_io:
8230b57cec5SDimitry Andric     case Hexagon::L2_loadrd_io:
8240b57cec5SDimitry Andric     case Hexagon::L2_loadbzw2_io:
8250b57cec5SDimitry Andric     case Hexagon::L2_loadbzw4_io:
8260b57cec5SDimitry Andric     case Hexagon::L2_loadbsw2_io:
8270b57cec5SDimitry Andric     case Hexagon::L2_loadbsw4_io:
8280b57cec5SDimitry Andric     case Hexagon::L2_loadalignh_io:
8290b57cec5SDimitry Andric     case Hexagon::L2_loadalignb_io:
8300b57cec5SDimitry Andric     case Hexagon::L2_ploadrubt_io:
8310b57cec5SDimitry Andric     case Hexagon::L2_ploadrubf_io:
8320b57cec5SDimitry Andric     case Hexagon::L2_ploadrbt_io:
8330b57cec5SDimitry Andric     case Hexagon::L2_ploadrbf_io:
8340b57cec5SDimitry Andric     case Hexagon::L2_ploadruht_io:
8350b57cec5SDimitry Andric     case Hexagon::L2_ploadruhf_io:
8360b57cec5SDimitry Andric     case Hexagon::L2_ploadrht_io:
8370b57cec5SDimitry Andric     case Hexagon::L2_ploadrhf_io:
8380b57cec5SDimitry Andric     case Hexagon::L2_ploadrit_io:
8390b57cec5SDimitry Andric     case Hexagon::L2_ploadrif_io:
8400b57cec5SDimitry Andric     case Hexagon::L2_ploadrdt_io:
8410b57cec5SDimitry Andric     case Hexagon::L2_ploadrdf_io:
8420b57cec5SDimitry Andric     case Hexagon::S2_storerb_io:
8430b57cec5SDimitry Andric     case Hexagon::S2_storerh_io:
8440b57cec5SDimitry Andric     case Hexagon::S2_storerf_io:
8450b57cec5SDimitry Andric     case Hexagon::S2_storeri_io:
8460b57cec5SDimitry Andric     case Hexagon::S2_storerd_io:
8470b57cec5SDimitry Andric     case Hexagon::S2_pstorerbt_io:
8480b57cec5SDimitry Andric     case Hexagon::S2_pstorerbf_io:
8490b57cec5SDimitry Andric     case Hexagon::S2_pstorerht_io:
8500b57cec5SDimitry Andric     case Hexagon::S2_pstorerhf_io:
8510b57cec5SDimitry Andric     case Hexagon::S2_pstorerft_io:
8520b57cec5SDimitry Andric     case Hexagon::S2_pstorerff_io:
8530b57cec5SDimitry Andric     case Hexagon::S2_pstorerit_io:
8540b57cec5SDimitry Andric     case Hexagon::S2_pstorerif_io:
8550b57cec5SDimitry Andric     case Hexagon::S2_pstorerdt_io:
8560b57cec5SDimitry Andric     case Hexagon::S2_pstorerdf_io:
8570b57cec5SDimitry Andric     case Hexagon::A2_addi:
8580b57cec5SDimitry Andric       return true;
8590b57cec5SDimitry Andric     default:
8600b57cec5SDimitry Andric       break;
8610b57cec5SDimitry Andric   }
8620b57cec5SDimitry Andric   return false;
8630b57cec5SDimitry Andric }
8640b57cec5SDimitry Andric 
8650b57cec5SDimitry Andric unsigned HCE::getRegOffOpcode(unsigned ExtOpc) const {
8660b57cec5SDimitry Andric   // If there exists an instruction that takes a register and offset,
8670b57cec5SDimitry Andric   // that corresponds to the ExtOpc, return it, otherwise return 0.
8680b57cec5SDimitry Andric   using namespace Hexagon;
8690b57cec5SDimitry Andric   switch (ExtOpc) {
8700b57cec5SDimitry Andric     case A2_tfrsi:    return A2_addi;
8710b57cec5SDimitry Andric     default:
8720b57cec5SDimitry Andric       break;
8730b57cec5SDimitry Andric   }
8740b57cec5SDimitry Andric   const MCInstrDesc &D = HII->get(ExtOpc);
8750b57cec5SDimitry Andric   if (D.mayLoad() || D.mayStore()) {
8760b57cec5SDimitry Andric     uint64_t F = D.TSFlags;
8770b57cec5SDimitry Andric     unsigned AM = (F >> HexagonII::AddrModePos) & HexagonII::AddrModeMask;
8780b57cec5SDimitry Andric     switch (AM) {
8790b57cec5SDimitry Andric       case HexagonII::Absolute:
8800b57cec5SDimitry Andric       case HexagonII::AbsoluteSet:
8810b57cec5SDimitry Andric       case HexagonII::BaseLongOffset:
8820b57cec5SDimitry Andric         switch (ExtOpc) {
8830b57cec5SDimitry Andric           case PS_loadrubabs:
8840b57cec5SDimitry Andric           case L4_loadrub_ap:
8850b57cec5SDimitry Andric           case L4_loadrub_ur:     return L2_loadrub_io;
8860b57cec5SDimitry Andric           case PS_loadrbabs:
8870b57cec5SDimitry Andric           case L4_loadrb_ap:
8880b57cec5SDimitry Andric           case L4_loadrb_ur:      return L2_loadrb_io;
8890b57cec5SDimitry Andric           case PS_loadruhabs:
8900b57cec5SDimitry Andric           case L4_loadruh_ap:
8910b57cec5SDimitry Andric           case L4_loadruh_ur:     return L2_loadruh_io;
8920b57cec5SDimitry Andric           case PS_loadrhabs:
8930b57cec5SDimitry Andric           case L4_loadrh_ap:
8940b57cec5SDimitry Andric           case L4_loadrh_ur:      return L2_loadrh_io;
8950b57cec5SDimitry Andric           case PS_loadriabs:
8960b57cec5SDimitry Andric           case L4_loadri_ap:
8970b57cec5SDimitry Andric           case L4_loadri_ur:      return L2_loadri_io;
8980b57cec5SDimitry Andric           case PS_loadrdabs:
8990b57cec5SDimitry Andric           case L4_loadrd_ap:
9000b57cec5SDimitry Andric           case L4_loadrd_ur:      return L2_loadrd_io;
9010b57cec5SDimitry Andric           case L4_loadbzw2_ap:
9020b57cec5SDimitry Andric           case L4_loadbzw2_ur:    return L2_loadbzw2_io;
9030b57cec5SDimitry Andric           case L4_loadbzw4_ap:
9040b57cec5SDimitry Andric           case L4_loadbzw4_ur:    return L2_loadbzw4_io;
9050b57cec5SDimitry Andric           case L4_loadbsw2_ap:
9060b57cec5SDimitry Andric           case L4_loadbsw2_ur:    return L2_loadbsw2_io;
9070b57cec5SDimitry Andric           case L4_loadbsw4_ap:
9080b57cec5SDimitry Andric           case L4_loadbsw4_ur:    return L2_loadbsw4_io;
9090b57cec5SDimitry Andric           case L4_loadalignh_ap:
9100b57cec5SDimitry Andric           case L4_loadalignh_ur:  return L2_loadalignh_io;
9110b57cec5SDimitry Andric           case L4_loadalignb_ap:
9120b57cec5SDimitry Andric           case L4_loadalignb_ur:  return L2_loadalignb_io;
9130b57cec5SDimitry Andric           case L4_ploadrubt_abs:  return L2_ploadrubt_io;
9140b57cec5SDimitry Andric           case L4_ploadrubf_abs:  return L2_ploadrubf_io;
9150b57cec5SDimitry Andric           case L4_ploadrbt_abs:   return L2_ploadrbt_io;
9160b57cec5SDimitry Andric           case L4_ploadrbf_abs:   return L2_ploadrbf_io;
9170b57cec5SDimitry Andric           case L4_ploadruht_abs:  return L2_ploadruht_io;
9180b57cec5SDimitry Andric           case L4_ploadruhf_abs:  return L2_ploadruhf_io;
9190b57cec5SDimitry Andric           case L4_ploadrht_abs:   return L2_ploadrht_io;
9200b57cec5SDimitry Andric           case L4_ploadrhf_abs:   return L2_ploadrhf_io;
9210b57cec5SDimitry Andric           case L4_ploadrit_abs:   return L2_ploadrit_io;
9220b57cec5SDimitry Andric           case L4_ploadrif_abs:   return L2_ploadrif_io;
9230b57cec5SDimitry Andric           case L4_ploadrdt_abs:   return L2_ploadrdt_io;
9240b57cec5SDimitry Andric           case L4_ploadrdf_abs:   return L2_ploadrdf_io;
9250b57cec5SDimitry Andric           case PS_storerbabs:
9260b57cec5SDimitry Andric           case S4_storerb_ap:
9270b57cec5SDimitry Andric           case S4_storerb_ur:     return S2_storerb_io;
9280b57cec5SDimitry Andric           case PS_storerhabs:
9290b57cec5SDimitry Andric           case S4_storerh_ap:
9300b57cec5SDimitry Andric           case S4_storerh_ur:     return S2_storerh_io;
9310b57cec5SDimitry Andric           case PS_storerfabs:
9320b57cec5SDimitry Andric           case S4_storerf_ap:
9330b57cec5SDimitry Andric           case S4_storerf_ur:     return S2_storerf_io;
9340b57cec5SDimitry Andric           case PS_storeriabs:
9350b57cec5SDimitry Andric           case S4_storeri_ap:
9360b57cec5SDimitry Andric           case S4_storeri_ur:     return S2_storeri_io;
9370b57cec5SDimitry Andric           case PS_storerdabs:
9380b57cec5SDimitry Andric           case S4_storerd_ap:
9390b57cec5SDimitry Andric           case S4_storerd_ur:     return S2_storerd_io;
9400b57cec5SDimitry Andric           case S4_pstorerbt_abs:  return S2_pstorerbt_io;
9410b57cec5SDimitry Andric           case S4_pstorerbf_abs:  return S2_pstorerbf_io;
9420b57cec5SDimitry Andric           case S4_pstorerht_abs:  return S2_pstorerht_io;
9430b57cec5SDimitry Andric           case S4_pstorerhf_abs:  return S2_pstorerhf_io;
9440b57cec5SDimitry Andric           case S4_pstorerft_abs:  return S2_pstorerft_io;
9450b57cec5SDimitry Andric           case S4_pstorerff_abs:  return S2_pstorerff_io;
9460b57cec5SDimitry Andric           case S4_pstorerit_abs:  return S2_pstorerit_io;
9470b57cec5SDimitry Andric           case S4_pstorerif_abs:  return S2_pstorerif_io;
9480b57cec5SDimitry Andric           case S4_pstorerdt_abs:  return S2_pstorerdt_io;
9490b57cec5SDimitry Andric           case S4_pstorerdf_abs:  return S2_pstorerdf_io;
9500b57cec5SDimitry Andric           default:
9510b57cec5SDimitry Andric             break;
9520b57cec5SDimitry Andric         }
9530b57cec5SDimitry Andric         break;
9540b57cec5SDimitry Andric       case HexagonII::BaseImmOffset:
9550b57cec5SDimitry Andric         if (!isStoreImmediate(ExtOpc))
9560b57cec5SDimitry Andric           return ExtOpc;
9570b57cec5SDimitry Andric         break;
9580b57cec5SDimitry Andric       default:
9590b57cec5SDimitry Andric         break;
9600b57cec5SDimitry Andric     }
9610b57cec5SDimitry Andric   }
9620b57cec5SDimitry Andric   return 0;
9630b57cec5SDimitry Andric }
9640b57cec5SDimitry Andric 
9650b57cec5SDimitry Andric unsigned HCE::getDirectRegReplacement(unsigned ExtOpc) const {
9660b57cec5SDimitry Andric   switch (ExtOpc) {
9670b57cec5SDimitry Andric     case Hexagon::A2_addi:          return Hexagon::A2_add;
9680b57cec5SDimitry Andric     case Hexagon::A2_andir:         return Hexagon::A2_and;
9690b57cec5SDimitry Andric     case Hexagon::A2_combineii:     return Hexagon::A4_combineri;
9700b57cec5SDimitry Andric     case Hexagon::A2_orir:          return Hexagon::A2_or;
9710b57cec5SDimitry Andric     case Hexagon::A2_paddif:        return Hexagon::A2_paddf;
9720b57cec5SDimitry Andric     case Hexagon::A2_paddit:        return Hexagon::A2_paddt;
9730b57cec5SDimitry Andric     case Hexagon::A2_subri:         return Hexagon::A2_sub;
9740b57cec5SDimitry Andric     case Hexagon::A2_tfrsi:         return TargetOpcode::COPY;
9750b57cec5SDimitry Andric     case Hexagon::A4_cmpbeqi:       return Hexagon::A4_cmpbeq;
9760b57cec5SDimitry Andric     case Hexagon::A4_cmpbgti:       return Hexagon::A4_cmpbgt;
9770b57cec5SDimitry Andric     case Hexagon::A4_cmpbgtui:      return Hexagon::A4_cmpbgtu;
9780b57cec5SDimitry Andric     case Hexagon::A4_cmpheqi:       return Hexagon::A4_cmpheq;
9790b57cec5SDimitry Andric     case Hexagon::A4_cmphgti:       return Hexagon::A4_cmphgt;
9800b57cec5SDimitry Andric     case Hexagon::A4_cmphgtui:      return Hexagon::A4_cmphgtu;
9810b57cec5SDimitry Andric     case Hexagon::A4_combineii:     return Hexagon::A4_combineir;
9820b57cec5SDimitry Andric     case Hexagon::A4_combineir:     return TargetOpcode::REG_SEQUENCE;
9830b57cec5SDimitry Andric     case Hexagon::A4_combineri:     return TargetOpcode::REG_SEQUENCE;
9840b57cec5SDimitry Andric     case Hexagon::A4_rcmpeqi:       return Hexagon::A4_rcmpeq;
9850b57cec5SDimitry Andric     case Hexagon::A4_rcmpneqi:      return Hexagon::A4_rcmpneq;
9860b57cec5SDimitry Andric     case Hexagon::C2_cmoveif:       return Hexagon::A2_tfrpf;
9870b57cec5SDimitry Andric     case Hexagon::C2_cmoveit:       return Hexagon::A2_tfrpt;
9880b57cec5SDimitry Andric     case Hexagon::C2_cmpeqi:        return Hexagon::C2_cmpeq;
9890b57cec5SDimitry Andric     case Hexagon::C2_cmpgti:        return Hexagon::C2_cmpgt;
9900b57cec5SDimitry Andric     case Hexagon::C2_cmpgtui:       return Hexagon::C2_cmpgtu;
9910b57cec5SDimitry Andric     case Hexagon::C2_muxii:         return Hexagon::C2_muxir;
9920b57cec5SDimitry Andric     case Hexagon::C2_muxir:         return Hexagon::C2_mux;
9930b57cec5SDimitry Andric     case Hexagon::C2_muxri:         return Hexagon::C2_mux;
9940b57cec5SDimitry Andric     case Hexagon::C4_cmpltei:       return Hexagon::C4_cmplte;
9950b57cec5SDimitry Andric     case Hexagon::C4_cmplteui:      return Hexagon::C4_cmplteu;
9960b57cec5SDimitry Andric     case Hexagon::C4_cmpneqi:       return Hexagon::C4_cmpneq;
9970b57cec5SDimitry Andric     case Hexagon::M2_accii:         return Hexagon::M2_acci;        // T -> T
9980b57cec5SDimitry Andric     /* No M2_macsin */
9990b57cec5SDimitry Andric     case Hexagon::M2_macsip:        return Hexagon::M2_maci;        // T -> T
10000b57cec5SDimitry Andric     case Hexagon::M2_mpysin:        return Hexagon::M2_mpyi;
10010b57cec5SDimitry Andric     case Hexagon::M2_mpysip:        return Hexagon::M2_mpyi;
10020b57cec5SDimitry Andric     case Hexagon::M2_mpysmi:        return Hexagon::M2_mpyi;
10030b57cec5SDimitry Andric     case Hexagon::M2_naccii:        return Hexagon::M2_nacci;       // T -> T
10040b57cec5SDimitry Andric     case Hexagon::M4_mpyri_addi:    return Hexagon::M4_mpyri_addr;
10050b57cec5SDimitry Andric     case Hexagon::M4_mpyri_addr:    return Hexagon::M4_mpyrr_addr;  // _ -> T
10060b57cec5SDimitry Andric     case Hexagon::M4_mpyrr_addi:    return Hexagon::M4_mpyrr_addr;  // _ -> T
10070b57cec5SDimitry Andric     case Hexagon::S4_addaddi:       return Hexagon::M2_acci;        // _ -> T
10080b57cec5SDimitry Andric     case Hexagon::S4_addi_asl_ri:   return Hexagon::S2_asl_i_r_acc; // T -> T
10090b57cec5SDimitry Andric     case Hexagon::S4_addi_lsr_ri:   return Hexagon::S2_lsr_i_r_acc; // T -> T
10100b57cec5SDimitry Andric     case Hexagon::S4_andi_asl_ri:   return Hexagon::S2_asl_i_r_and; // T -> T
10110b57cec5SDimitry Andric     case Hexagon::S4_andi_lsr_ri:   return Hexagon::S2_lsr_i_r_and; // T -> T
10120b57cec5SDimitry Andric     case Hexagon::S4_ori_asl_ri:    return Hexagon::S2_asl_i_r_or;  // T -> T
10130b57cec5SDimitry Andric     case Hexagon::S4_ori_lsr_ri:    return Hexagon::S2_lsr_i_r_or;  // T -> T
10140b57cec5SDimitry Andric     case Hexagon::S4_subaddi:       return Hexagon::M2_subacc;      // _ -> T
10150b57cec5SDimitry Andric     case Hexagon::S4_subi_asl_ri:   return Hexagon::S2_asl_i_r_nac; // T -> T
10160b57cec5SDimitry Andric     case Hexagon::S4_subi_lsr_ri:   return Hexagon::S2_lsr_i_r_nac; // T -> T
10170b57cec5SDimitry Andric 
10180b57cec5SDimitry Andric     // Store-immediates:
10190b57cec5SDimitry Andric     case Hexagon::S4_storeirbf_io:  return Hexagon::S2_pstorerbf_io;
10200b57cec5SDimitry Andric     case Hexagon::S4_storeirb_io:   return Hexagon::S2_storerb_io;
10210b57cec5SDimitry Andric     case Hexagon::S4_storeirbt_io:  return Hexagon::S2_pstorerbt_io;
10220b57cec5SDimitry Andric     case Hexagon::S4_storeirhf_io:  return Hexagon::S2_pstorerhf_io;
10230b57cec5SDimitry Andric     case Hexagon::S4_storeirh_io:   return Hexagon::S2_storerh_io;
10240b57cec5SDimitry Andric     case Hexagon::S4_storeirht_io:  return Hexagon::S2_pstorerht_io;
10250b57cec5SDimitry Andric     case Hexagon::S4_storeirif_io:  return Hexagon::S2_pstorerif_io;
10260b57cec5SDimitry Andric     case Hexagon::S4_storeiri_io:   return Hexagon::S2_storeri_io;
10270b57cec5SDimitry Andric     case Hexagon::S4_storeirit_io:  return Hexagon::S2_pstorerit_io;
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric     default:
10300b57cec5SDimitry Andric       break;
10310b57cec5SDimitry Andric   }
10320b57cec5SDimitry Andric   return 0;
10330b57cec5SDimitry Andric }
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric // Return the allowable deviation from the current value of Rb (i.e. the
10360b57cec5SDimitry Andric // range of values that can be added to the current value) which the
10370b57cec5SDimitry Andric // instruction MI can accommodate.
10380b57cec5SDimitry Andric // The instruction MI is a user of register Rb, which is defined via an
10390b57cec5SDimitry Andric // extender. It may be possible for MI to be tweaked to work for a register
10400b57cec5SDimitry Andric // defined with a slightly different value. For example
10410b57cec5SDimitry Andric //   ... = L2_loadrub_io Rb, 1
10420b57cec5SDimitry Andric // can be modifed to be
10430b57cec5SDimitry Andric //   ... = L2_loadrub_io Rb', 0
10440b57cec5SDimitry Andric // if Rb' = Rb+1.
10450b57cec5SDimitry Andric // The range for Rb would be [Min+1, Max+1], where [Min, Max] is a range
10460b57cec5SDimitry Andric // for L2_loadrub with offset 0. That means that Rb could be replaced with
10470b57cec5SDimitry Andric // Rc, where Rc-Rb belongs to [Min+1, Max+1].
10480b57cec5SDimitry Andric OffsetRange HCE::getOffsetRange(Register Rb, const MachineInstr &MI) const {
10490b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
10500b57cec5SDimitry Andric   // Instructions that are constant-extended may be replaced with something
10510b57cec5SDimitry Andric   // else that no longer offers the same range as the original.
10520b57cec5SDimitry Andric   if (!isRegOffOpcode(Opc) || HII->isConstExtended(MI))
10530b57cec5SDimitry Andric     return OffsetRange::zero();
10540b57cec5SDimitry Andric 
10550b57cec5SDimitry Andric   if (Opc == Hexagon::A2_addi) {
10560b57cec5SDimitry Andric     const MachineOperand &Op1 = MI.getOperand(1), &Op2 = MI.getOperand(2);
10570b57cec5SDimitry Andric     if (Rb != Register(Op1) || !Op2.isImm())
10580b57cec5SDimitry Andric       return OffsetRange::zero();
10590b57cec5SDimitry Andric     OffsetRange R = { -(1<<15)+1, (1<<15)-1, 1 };
10600b57cec5SDimitry Andric     return R.shift(Op2.getImm());
10610b57cec5SDimitry Andric   }
10620b57cec5SDimitry Andric 
10630b57cec5SDimitry Andric   // HII::getBaseAndOffsetPosition returns the increment position as "offset".
10640b57cec5SDimitry Andric   if (HII->isPostIncrement(MI))
10650b57cec5SDimitry Andric     return OffsetRange::zero();
10660b57cec5SDimitry Andric 
10670b57cec5SDimitry Andric   const MCInstrDesc &D = HII->get(Opc);
10680b57cec5SDimitry Andric   assert(D.mayLoad() || D.mayStore());
10690b57cec5SDimitry Andric 
10700b57cec5SDimitry Andric   unsigned BaseP, OffP;
10710b57cec5SDimitry Andric   if (!HII->getBaseAndOffsetPosition(MI, BaseP, OffP) ||
10720b57cec5SDimitry Andric       Rb != Register(MI.getOperand(BaseP)) ||
10730b57cec5SDimitry Andric       !MI.getOperand(OffP).isImm())
10740b57cec5SDimitry Andric     return OffsetRange::zero();
10750b57cec5SDimitry Andric 
10760b57cec5SDimitry Andric   uint64_t F = (D.TSFlags >> HexagonII::MemAccessSizePos) &
10770b57cec5SDimitry Andric                   HexagonII::MemAccesSizeMask;
10780b57cec5SDimitry Andric   uint8_t A = HexagonII::getMemAccessSizeInBytes(HexagonII::MemAccessSize(F));
10790b57cec5SDimitry Andric   unsigned L = Log2_32(A);
10800b57cec5SDimitry Andric   unsigned S = 10+L;  // sint11_L
10810b57cec5SDimitry Andric   int32_t Min = -alignDown((1<<S)-1, A);
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric   // The range will be shifted by Off. To prefer non-negative offsets,
10840b57cec5SDimitry Andric   // adjust Max accordingly.
10850b57cec5SDimitry Andric   int32_t Off = MI.getOperand(OffP).getImm();
10860b57cec5SDimitry Andric   int32_t Max = Off >= 0 ? 0 : -Off;
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric   OffsetRange R = { Min, Max, A };
10890b57cec5SDimitry Andric   return R.shift(Off);
10900b57cec5SDimitry Andric }
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric // Return the allowable deviation from the current value of the extender ED,
10930b57cec5SDimitry Andric // for which the instruction corresponding to ED can be modified without
10940b57cec5SDimitry Andric // using an extender.
10950b57cec5SDimitry Andric // The instruction uses the extender directly. It will be replaced with
10960b57cec5SDimitry Andric // another instruction, say MJ, where the extender will be replaced with a
10970b57cec5SDimitry Andric // register. MJ can allow some variability with respect to the value of
10980b57cec5SDimitry Andric // that register, as is the case with indexed memory instructions.
10990b57cec5SDimitry Andric OffsetRange HCE::getOffsetRange(const ExtDesc &ED) const {
11000b57cec5SDimitry Andric   // The only way that there can be a non-zero range available is if
11010b57cec5SDimitry Andric   // the instruction using ED will be converted to an indexed memory
11020b57cec5SDimitry Andric   // instruction.
11030b57cec5SDimitry Andric   unsigned IdxOpc = getRegOffOpcode(ED.UseMI->getOpcode());
11040b57cec5SDimitry Andric   switch (IdxOpc) {
11050b57cec5SDimitry Andric     case 0:
11060b57cec5SDimitry Andric       return OffsetRange::zero();
11070b57cec5SDimitry Andric     case Hexagon::A2_addi:    // s16
11080b57cec5SDimitry Andric       return { -32767, 32767, 1 };
11090b57cec5SDimitry Andric     case Hexagon::A2_subri:   // s10
11100b57cec5SDimitry Andric       return { -511, 511, 1 };
11110b57cec5SDimitry Andric   }
11120b57cec5SDimitry Andric 
11130b57cec5SDimitry Andric   if (!ED.UseMI->mayLoad() && !ED.UseMI->mayStore())
11140b57cec5SDimitry Andric     return OffsetRange::zero();
11150b57cec5SDimitry Andric   const MCInstrDesc &D = HII->get(IdxOpc);
11160b57cec5SDimitry Andric   uint64_t F = (D.TSFlags >> HexagonII::MemAccessSizePos) &
11170b57cec5SDimitry Andric                   HexagonII::MemAccesSizeMask;
11180b57cec5SDimitry Andric   uint8_t A = HexagonII::getMemAccessSizeInBytes(HexagonII::MemAccessSize(F));
11190b57cec5SDimitry Andric   unsigned L = Log2_32(A);
11200b57cec5SDimitry Andric   unsigned S = 10+L;  // sint11_L
11210b57cec5SDimitry Andric   int32_t Min = -alignDown((1<<S)-1, A);
11220b57cec5SDimitry Andric   int32_t Max = 0;  // Force non-negative offsets.
11230b57cec5SDimitry Andric   return { Min, Max, A };
11240b57cec5SDimitry Andric }
11250b57cec5SDimitry Andric 
11260b57cec5SDimitry Andric // Get the allowable deviation from the current value of Rd by checking
11270b57cec5SDimitry Andric // all uses of Rd.
11280b57cec5SDimitry Andric OffsetRange HCE::getOffsetRange(Register Rd) const {
11290b57cec5SDimitry Andric   OffsetRange Range;
11300b57cec5SDimitry Andric   for (const MachineOperand &Op : MRI->use_operands(Rd.Reg)) {
11310b57cec5SDimitry Andric     // Make sure that the register being used by this operand is identical
11320b57cec5SDimitry Andric     // to the register that was defined: using a different subregister
11330b57cec5SDimitry Andric     // precludes any non-trivial range.
11340b57cec5SDimitry Andric     if (Rd != Register(Op))
11350b57cec5SDimitry Andric       return OffsetRange::zero();
11360b57cec5SDimitry Andric     Range.intersect(getOffsetRange(Rd, *Op.getParent()));
11370b57cec5SDimitry Andric   }
11380b57cec5SDimitry Andric   return Range;
11390b57cec5SDimitry Andric }
11400b57cec5SDimitry Andric 
11410b57cec5SDimitry Andric void HCE::recordExtender(MachineInstr &MI, unsigned OpNum) {
11420b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
11430b57cec5SDimitry Andric   ExtDesc ED;
11440b57cec5SDimitry Andric   ED.OpNum = OpNum;
11450b57cec5SDimitry Andric 
11460b57cec5SDimitry Andric   bool IsLoad = MI.mayLoad();
11470b57cec5SDimitry Andric   bool IsStore = MI.mayStore();
11480b57cec5SDimitry Andric 
11490b57cec5SDimitry Andric   // Fixed stack slots have negative indexes, and they cannot be used
11500b57cec5SDimitry Andric   // with TRI::stackSlot2Index and TRI::index2StackSlot. This is somewhat
11510b57cec5SDimitry Andric   // unfortunate, but should not be a frequent thing.
11520b57cec5SDimitry Andric   for (MachineOperand &Op : MI.operands())
11530b57cec5SDimitry Andric     if (Op.isFI() && Op.getIndex() < 0)
11540b57cec5SDimitry Andric       return;
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric   if (IsLoad || IsStore) {
11570b57cec5SDimitry Andric     unsigned AM = HII->getAddrMode(MI);
11580b57cec5SDimitry Andric     switch (AM) {
11590b57cec5SDimitry Andric       // (Re: ##Off + Rb<<S) = Rd: ##Val
11600b57cec5SDimitry Andric       case HexagonII::Absolute:       // (__: ## + __<<_)
11610b57cec5SDimitry Andric         break;
11620b57cec5SDimitry Andric       case HexagonII::AbsoluteSet:    // (Rd: ## + __<<_)
11630b57cec5SDimitry Andric         ED.Rd = MI.getOperand(OpNum-1);
11640b57cec5SDimitry Andric         ED.IsDef = true;
11650b57cec5SDimitry Andric         break;
11660b57cec5SDimitry Andric       case HexagonII::BaseImmOffset:  // (__: ## + Rs<<0)
11670b57cec5SDimitry Andric         // Store-immediates are treated as non-memory operations, since
11680b57cec5SDimitry Andric         // it's the value being stored that is extended (as opposed to
11690b57cec5SDimitry Andric         // a part of the address).
11700b57cec5SDimitry Andric         if (!isStoreImmediate(Opc))
11710b57cec5SDimitry Andric           ED.Expr.Rs = MI.getOperand(OpNum-1);
11720b57cec5SDimitry Andric         break;
11730b57cec5SDimitry Andric       case HexagonII::BaseLongOffset: // (__: ## + Rs<<S)
11740b57cec5SDimitry Andric         ED.Expr.Rs = MI.getOperand(OpNum-2);
11750b57cec5SDimitry Andric         ED.Expr.S = MI.getOperand(OpNum-1).getImm();
11760b57cec5SDimitry Andric         break;
11770b57cec5SDimitry Andric       default:
11780b57cec5SDimitry Andric         llvm_unreachable("Unhandled memory instruction");
11790b57cec5SDimitry Andric     }
11800b57cec5SDimitry Andric   } else {
11810b57cec5SDimitry Andric     switch (Opc) {
11820b57cec5SDimitry Andric       case Hexagon::A2_tfrsi:         // (Rd: ## + __<<_)
11830b57cec5SDimitry Andric         ED.Rd = MI.getOperand(0);
11840b57cec5SDimitry Andric         ED.IsDef = true;
11850b57cec5SDimitry Andric         break;
11860b57cec5SDimitry Andric       case Hexagon::A2_combineii:     // (Rd: ## + __<<_)
11870b57cec5SDimitry Andric       case Hexagon::A4_combineir:
11880b57cec5SDimitry Andric         ED.Rd = { MI.getOperand(0).getReg(), Hexagon::isub_hi };
11890b57cec5SDimitry Andric         ED.IsDef = true;
11900b57cec5SDimitry Andric         break;
11910b57cec5SDimitry Andric       case Hexagon::A4_combineri:     // (Rd: ## + __<<_)
11920b57cec5SDimitry Andric         ED.Rd = { MI.getOperand(0).getReg(), Hexagon::isub_lo };
11930b57cec5SDimitry Andric         ED.IsDef = true;
11940b57cec5SDimitry Andric         break;
11950b57cec5SDimitry Andric       case Hexagon::A2_addi:          // (Rd: ## + Rs<<0)
11960b57cec5SDimitry Andric         ED.Rd = MI.getOperand(0);
11970b57cec5SDimitry Andric         ED.Expr.Rs = MI.getOperand(OpNum-1);
11980b57cec5SDimitry Andric         break;
11990b57cec5SDimitry Andric       case Hexagon::M2_accii:         // (__: ## + Rs<<0)
12000b57cec5SDimitry Andric       case Hexagon::M2_naccii:
12010b57cec5SDimitry Andric       case Hexagon::S4_addaddi:
12020b57cec5SDimitry Andric         ED.Expr.Rs = MI.getOperand(OpNum-1);
12030b57cec5SDimitry Andric         break;
12040b57cec5SDimitry Andric       case Hexagon::A2_subri:         // (Rd: ## - Rs<<0)
12050b57cec5SDimitry Andric         ED.Rd = MI.getOperand(0);
12060b57cec5SDimitry Andric         ED.Expr.Rs = MI.getOperand(OpNum+1);
12070b57cec5SDimitry Andric         ED.Expr.Neg = true;
12080b57cec5SDimitry Andric         break;
12090b57cec5SDimitry Andric       case Hexagon::S4_subaddi:       // (__: ## - Rs<<0)
12100b57cec5SDimitry Andric         ED.Expr.Rs = MI.getOperand(OpNum+1);
12110b57cec5SDimitry Andric         ED.Expr.Neg = true;
12120b57cec5SDimitry Andric         break;
12130b57cec5SDimitry Andric       default:                        // (__: ## + __<<_)
12140b57cec5SDimitry Andric         break;
12150b57cec5SDimitry Andric     }
12160b57cec5SDimitry Andric   }
12170b57cec5SDimitry Andric 
12180b57cec5SDimitry Andric   ED.UseMI = &MI;
12190b57cec5SDimitry Andric 
12200b57cec5SDimitry Andric   // Ignore unnamed globals.
12210b57cec5SDimitry Andric   ExtRoot ER(ED.getOp());
12220b57cec5SDimitry Andric   if (ER.Kind == MachineOperand::MO_GlobalAddress)
12230b57cec5SDimitry Andric     if (ER.V.GV->getName().empty())
12240b57cec5SDimitry Andric       return;
12250b57cec5SDimitry Andric   Extenders.push_back(ED);
12260b57cec5SDimitry Andric }
12270b57cec5SDimitry Andric 
12280b57cec5SDimitry Andric void HCE::collectInstr(MachineInstr &MI) {
12290b57cec5SDimitry Andric   if (!HII->isConstExtended(MI))
12300b57cec5SDimitry Andric     return;
12310b57cec5SDimitry Andric 
12320b57cec5SDimitry Andric   // Skip some non-convertible instructions.
12330b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
12340b57cec5SDimitry Andric   switch (Opc) {
12350b57cec5SDimitry Andric     case Hexagon::M2_macsin:  // There is no Rx -= mpyi(Rs,Rt).
12360b57cec5SDimitry Andric     case Hexagon::C4_addipc:
12370b57cec5SDimitry Andric     case Hexagon::S4_or_andi:
12380b57cec5SDimitry Andric     case Hexagon::S4_or_andix:
12390b57cec5SDimitry Andric     case Hexagon::S4_or_ori:
12400b57cec5SDimitry Andric       return;
12410b57cec5SDimitry Andric   }
12420b57cec5SDimitry Andric   recordExtender(MI, HII->getCExtOpNum(MI));
12430b57cec5SDimitry Andric }
12440b57cec5SDimitry Andric 
12450b57cec5SDimitry Andric void HCE::collect(MachineFunction &MF) {
12460b57cec5SDimitry Andric   Extenders.clear();
12470b57cec5SDimitry Andric   for (MachineBasicBlock &MBB : MF) {
12480b57cec5SDimitry Andric     // Skip unreachable blocks.
12490b57cec5SDimitry Andric     if (MBB.getNumber() == -1)
12500b57cec5SDimitry Andric       continue;
12510b57cec5SDimitry Andric     for (MachineInstr &MI : MBB)
12520b57cec5SDimitry Andric       collectInstr(MI);
12530b57cec5SDimitry Andric   }
12540b57cec5SDimitry Andric }
12550b57cec5SDimitry Andric 
12560b57cec5SDimitry Andric void HCE::assignInits(const ExtRoot &ER, unsigned Begin, unsigned End,
12570b57cec5SDimitry Andric       AssignmentMap &IMap) {
12580b57cec5SDimitry Andric   // Sanity check: make sure that all extenders in the range [Begin..End)
12590b57cec5SDimitry Andric   // share the same root ER.
12600b57cec5SDimitry Andric   for (unsigned I = Begin; I != End; ++I)
12610b57cec5SDimitry Andric     assert(ER == ExtRoot(Extenders[I].getOp()));
12620b57cec5SDimitry Andric 
12630b57cec5SDimitry Andric   // Construct the list of ranges, such that for each P in Ranges[I],
12640b57cec5SDimitry Andric   // a register Reg = ER+P can be used in place of Extender[I]. If the
12650b57cec5SDimitry Andric   // instruction allows, uses in the form of Reg+Off are considered
12660b57cec5SDimitry Andric   // (here, Off = required_value - P).
12670b57cec5SDimitry Andric   std::vector<OffsetRange> Ranges(End-Begin);
12680b57cec5SDimitry Andric 
12690b57cec5SDimitry Andric   // For each extender that is a def, visit all uses of the defined register,
12700b57cec5SDimitry Andric   // and produce an offset range that works for all uses. The def doesn't
12710b57cec5SDimitry Andric   // have to be checked, because it can become dead if all uses can be updated
12720b57cec5SDimitry Andric   // to use a different reg/offset.
12730b57cec5SDimitry Andric   for (unsigned I = Begin; I != End; ++I) {
12740b57cec5SDimitry Andric     const ExtDesc &ED = Extenders[I];
12750b57cec5SDimitry Andric     if (!ED.IsDef)
12760b57cec5SDimitry Andric       continue;
12770b57cec5SDimitry Andric     ExtValue EV(ED);
12780b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << " =" << I << ". " << EV << "  " << ED << '\n');
12790b57cec5SDimitry Andric     assert(ED.Rd.Reg != 0);
12800b57cec5SDimitry Andric     Ranges[I-Begin] = getOffsetRange(ED.Rd).shift(EV.Offset);
12810b57cec5SDimitry Andric     // A2_tfrsi is a special case: it will be replaced with A2_addi, which
12820b57cec5SDimitry Andric     // has a 16-bit signed offset. This means that A2_tfrsi not only has a
12830b57cec5SDimitry Andric     // range coming from its uses, but also from the fact that its replacement
12840b57cec5SDimitry Andric     // has a range as well.
12850b57cec5SDimitry Andric     if (ED.UseMI->getOpcode() == Hexagon::A2_tfrsi) {
12860b57cec5SDimitry Andric       int32_t D = alignDown(32767, Ranges[I-Begin].Align); // XXX hardcoded
12870b57cec5SDimitry Andric       Ranges[I-Begin].extendBy(-D).extendBy(D);
12880b57cec5SDimitry Andric     }
12890b57cec5SDimitry Andric   }
12900b57cec5SDimitry Andric 
12910b57cec5SDimitry Andric   // Visit all non-def extenders. For each one, determine the offset range
12920b57cec5SDimitry Andric   // available for it.
12930b57cec5SDimitry Andric   for (unsigned I = Begin; I != End; ++I) {
12940b57cec5SDimitry Andric     const ExtDesc &ED = Extenders[I];
12950b57cec5SDimitry Andric     if (ED.IsDef)
12960b57cec5SDimitry Andric       continue;
12970b57cec5SDimitry Andric     ExtValue EV(ED);
12980b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "  " << I << ". " << EV << "  " << ED << '\n');
12990b57cec5SDimitry Andric     OffsetRange Dev = getOffsetRange(ED);
13000b57cec5SDimitry Andric     Ranges[I-Begin].intersect(Dev.shift(EV.Offset));
13010b57cec5SDimitry Andric   }
13020b57cec5SDimitry Andric 
13030b57cec5SDimitry Andric   // Here for each I there is a corresponding Range[I]. Construct the
13040b57cec5SDimitry Andric   // inverse map, that to each range will assign the set of indexes in
13050b57cec5SDimitry Andric   // [Begin..End) that this range corresponds to.
13060b57cec5SDimitry Andric   std::map<OffsetRange, IndexList> RangeMap;
13070b57cec5SDimitry Andric   for (unsigned I = Begin; I != End; ++I)
13080b57cec5SDimitry Andric     RangeMap[Ranges[I-Begin]].insert(I);
13090b57cec5SDimitry Andric 
13100b57cec5SDimitry Andric   LLVM_DEBUG({
13110b57cec5SDimitry Andric     dbgs() << "Ranges\n";
13120b57cec5SDimitry Andric     for (unsigned I = Begin; I != End; ++I)
13130b57cec5SDimitry Andric       dbgs() << "  " << I << ". " << Ranges[I-Begin] << '\n';
13140b57cec5SDimitry Andric     dbgs() << "RangeMap\n";
13150b57cec5SDimitry Andric     for (auto &P : RangeMap) {
13160b57cec5SDimitry Andric       dbgs() << "  " << P.first << " ->";
13170b57cec5SDimitry Andric       for (unsigned I : P.second)
13180b57cec5SDimitry Andric         dbgs() << ' ' << I;
13190b57cec5SDimitry Andric       dbgs() << '\n';
13200b57cec5SDimitry Andric     }
13210b57cec5SDimitry Andric   });
13220b57cec5SDimitry Andric 
13230b57cec5SDimitry Andric   // Select the definition points, and generate the assignment between
13240b57cec5SDimitry Andric   // these points and the uses.
13250b57cec5SDimitry Andric 
13260b57cec5SDimitry Andric   // For each candidate offset, keep a pair CandData consisting of
13270b57cec5SDimitry Andric   // the total number of ranges containing that candidate, and the
13280b57cec5SDimitry Andric   // vector of corresponding RangeTree nodes.
13290b57cec5SDimitry Andric   using CandData = std::pair<unsigned, SmallVector<RangeTree::Node*,8>>;
13300b57cec5SDimitry Andric   std::map<int32_t, CandData> CandMap;
13310b57cec5SDimitry Andric 
13320b57cec5SDimitry Andric   RangeTree Tree;
13330b57cec5SDimitry Andric   for (const OffsetRange &R : Ranges)
13340b57cec5SDimitry Andric     Tree.add(R);
13350b57cec5SDimitry Andric   SmallVector<RangeTree::Node*,8> Nodes;
13360b57cec5SDimitry Andric   Tree.order(Nodes);
13370b57cec5SDimitry Andric 
13380b57cec5SDimitry Andric   auto MaxAlign = [](const SmallVectorImpl<RangeTree::Node*> &Nodes,
13390b57cec5SDimitry Andric                      uint8_t Align, uint8_t Offset) {
13400b57cec5SDimitry Andric     for (RangeTree::Node *N : Nodes) {
13410b57cec5SDimitry Andric       if (N->Range.Align <= Align || N->Range.Offset < Offset)
13420b57cec5SDimitry Andric         continue;
13430b57cec5SDimitry Andric       if ((N->Range.Offset - Offset) % Align != 0)
13440b57cec5SDimitry Andric         continue;
13450b57cec5SDimitry Andric       Align = N->Range.Align;
13460b57cec5SDimitry Andric       Offset = N->Range.Offset;
13470b57cec5SDimitry Andric     }
13480b57cec5SDimitry Andric     return std::make_pair(Align, Offset);
13490b57cec5SDimitry Andric   };
13500b57cec5SDimitry Andric 
13510b57cec5SDimitry Andric   // Construct the set of all potential definition points from the endpoints
13520b57cec5SDimitry Andric   // of the ranges. If a given endpoint also belongs to a different range,
13530b57cec5SDimitry Andric   // but with a higher alignment, also consider the more-highly-aligned
13540b57cec5SDimitry Andric   // value of this endpoint.
13550b57cec5SDimitry Andric   std::set<int32_t> CandSet;
13560b57cec5SDimitry Andric   for (RangeTree::Node *N : Nodes) {
13570b57cec5SDimitry Andric     const OffsetRange &R = N->Range;
13580b57cec5SDimitry Andric     auto P0 = MaxAlign(Tree.nodesWith(R.Min, false), R.Align, R.Offset);
13590b57cec5SDimitry Andric     CandSet.insert(R.Min);
13600b57cec5SDimitry Andric     if (R.Align < P0.first)
13610b57cec5SDimitry Andric       CandSet.insert(adjustUp(R.Min, P0.first, P0.second));
13620b57cec5SDimitry Andric     auto P1 = MaxAlign(Tree.nodesWith(R.Max, false), R.Align, R.Offset);
13630b57cec5SDimitry Andric     CandSet.insert(R.Max);
13640b57cec5SDimitry Andric     if (R.Align < P1.first)
13650b57cec5SDimitry Andric       CandSet.insert(adjustDown(R.Max, P1.first, P1.second));
13660b57cec5SDimitry Andric   }
13670b57cec5SDimitry Andric 
13680b57cec5SDimitry Andric   // Build the assignment map: candidate C -> { list of extender indexes }.
13690b57cec5SDimitry Andric   // This has to be done iteratively:
13700b57cec5SDimitry Andric   // - pick the candidate that covers the maximum number of extenders,
13710b57cec5SDimitry Andric   // - add the candidate to the map,
13720b57cec5SDimitry Andric   // - remove the extenders from the pool.
13730b57cec5SDimitry Andric   while (true) {
13740b57cec5SDimitry Andric     using CMap = std::map<int32_t,unsigned>;
13750b57cec5SDimitry Andric     CMap Counts;
13760b57cec5SDimitry Andric     for (auto It = CandSet.begin(), Et = CandSet.end(); It != Et; ) {
13770b57cec5SDimitry Andric       auto &&V = Tree.nodesWith(*It);
13780b57cec5SDimitry Andric       unsigned N = std::accumulate(V.begin(), V.end(), 0u,
13790b57cec5SDimitry Andric                     [](unsigned Acc, const RangeTree::Node *N) {
13800b57cec5SDimitry Andric                       return Acc + N->Count;
13810b57cec5SDimitry Andric                     });
13820b57cec5SDimitry Andric       if (N != 0)
13830b57cec5SDimitry Andric         Counts.insert({*It, N});
13840b57cec5SDimitry Andric       It = (N != 0) ? std::next(It) : CandSet.erase(It);
13850b57cec5SDimitry Andric     }
13860b57cec5SDimitry Andric     if (Counts.empty())
13870b57cec5SDimitry Andric       break;
13880b57cec5SDimitry Andric 
13890b57cec5SDimitry Andric     // Find the best candidate with respect to the number of extenders covered.
13900b57cec5SDimitry Andric     auto BestIt = std::max_element(Counts.begin(), Counts.end(),
13910b57cec5SDimitry Andric                     [](const CMap::value_type &A, const CMap::value_type &B) {
13920b57cec5SDimitry Andric                       return A.second < B.second ||
13930b57cec5SDimitry Andric                              (A.second == B.second && A < B);
13940b57cec5SDimitry Andric                     });
13950b57cec5SDimitry Andric     int32_t Best = BestIt->first;
13960b57cec5SDimitry Andric     ExtValue BestV(ER, Best);
13970b57cec5SDimitry Andric     for (RangeTree::Node *N : Tree.nodesWith(Best)) {
13980b57cec5SDimitry Andric       for (unsigned I : RangeMap[N->Range])
13990b57cec5SDimitry Andric         IMap[{BestV,Extenders[I].Expr}].insert(I);
14000b57cec5SDimitry Andric       Tree.erase(N);
14010b57cec5SDimitry Andric     }
14020b57cec5SDimitry Andric   }
14030b57cec5SDimitry Andric 
14040b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "IMap (before fixup) = " << PrintIMap(IMap, *HRI));
14050b57cec5SDimitry Andric 
14060b57cec5SDimitry Andric   // There is some ambiguity in what initializer should be used, if the
14070b57cec5SDimitry Andric   // descriptor's subexpression is non-trivial: it can be the entire
14080b57cec5SDimitry Andric   // subexpression (which is what has been done so far), or it can be
14090b57cec5SDimitry Andric   // the extender's value itself, if all corresponding extenders have the
14100b57cec5SDimitry Andric   // exact value of the initializer (i.e. require offset of 0).
14110b57cec5SDimitry Andric 
14120b57cec5SDimitry Andric   // To reduce the number of initializers, merge such special cases.
14130b57cec5SDimitry Andric   for (std::pair<const ExtenderInit,IndexList> &P : IMap) {
14140b57cec5SDimitry Andric     // Skip trivial initializers.
14150b57cec5SDimitry Andric     if (P.first.second.trivial())
14160b57cec5SDimitry Andric       continue;
14170b57cec5SDimitry Andric     // If the corresponding trivial initializer does not exist, skip this
14180b57cec5SDimitry Andric     // entry.
14190b57cec5SDimitry Andric     const ExtValue &EV = P.first.first;
14200b57cec5SDimitry Andric     AssignmentMap::iterator F = IMap.find({EV, ExtExpr()});
14210b57cec5SDimitry Andric     if (F == IMap.end())
14220b57cec5SDimitry Andric       continue;
14230b57cec5SDimitry Andric 
14240b57cec5SDimitry Andric     // Finally, check if all extenders have the same value as the initializer.
14250b57cec5SDimitry Andric     // Make sure that extenders that are a part of a stack address are not
14260b57cec5SDimitry Andric     // merged with those that aren't. Stack addresses need an offset field
14270b57cec5SDimitry Andric     // (to be used by frame index elimination), while non-stack expressions
14280b57cec5SDimitry Andric     // can be replaced with forms (such as rr) that do not have such a field.
14290b57cec5SDimitry Andric     // Example:
14300b57cec5SDimitry Andric     //
14310b57cec5SDimitry Andric     // Collected 3 extenders
14320b57cec5SDimitry Andric     //  =2. imm:0  off:32968  bb#2: %7 = ## + __ << 0, def
14330b57cec5SDimitry Andric     //   0. imm:0  off:267  bb#0: __ = ## + SS#1 << 0
14340b57cec5SDimitry Andric     //   1. imm:0  off:267  bb#1: __ = ## + SS#1 << 0
14350b57cec5SDimitry Andric     // Ranges
14360b57cec5SDimitry Andric     //   0. [-756,267]a1+0
14370b57cec5SDimitry Andric     //   1. [-756,267]a1+0
14380b57cec5SDimitry Andric     //   2. [201,65735]a1+0
14390b57cec5SDimitry Andric     // RangeMap
14400b57cec5SDimitry Andric     //   [-756,267]a1+0 -> 0 1
14410b57cec5SDimitry Andric     //   [201,65735]a1+0 -> 2
14420b57cec5SDimitry Andric     // IMap (before fixup) = {
14430b57cec5SDimitry Andric     //   [imm:0  off:267, ## + __ << 0] -> { 2 }
14440b57cec5SDimitry Andric     //   [imm:0  off:267, ## + SS#1 << 0] -> { 0 1 }
14450b57cec5SDimitry Andric     // }
14460b57cec5SDimitry Andric     // IMap (after fixup) = {
14470b57cec5SDimitry Andric     //   [imm:0  off:267, ## + __ << 0] -> { 2 0 1 }
14480b57cec5SDimitry Andric     //   [imm:0  off:267, ## + SS#1 << 0] -> { }
14490b57cec5SDimitry Andric     // }
14500b57cec5SDimitry Andric     // Inserted def in bb#0 for initializer: [imm:0  off:267, ## + __ << 0]
14510b57cec5SDimitry Andric     //   %12:intregs = A2_tfrsi 267
14520b57cec5SDimitry Andric     //
14530b57cec5SDimitry Andric     // The result was
14540b57cec5SDimitry Andric     //   %12:intregs = A2_tfrsi 267
14550b57cec5SDimitry Andric     //   S4_pstorerbt_rr %3, %12, %stack.1, 0, killed %4
14560b57cec5SDimitry Andric     // Which became
14570b57cec5SDimitry Andric     //   r0 = #267
14580b57cec5SDimitry Andric     //   if (p0.new) memb(r0+r29<<#4) = r2
14590b57cec5SDimitry Andric 
14600b57cec5SDimitry Andric     bool IsStack = any_of(F->second, [this](unsigned I) {
14610b57cec5SDimitry Andric                       return Extenders[I].Expr.Rs.isSlot();
14620b57cec5SDimitry Andric                    });
14630b57cec5SDimitry Andric     auto SameValue = [&EV,this,IsStack](unsigned I) {
14640b57cec5SDimitry Andric       const ExtDesc &ED = Extenders[I];
14650b57cec5SDimitry Andric       return ED.Expr.Rs.isSlot() == IsStack &&
14660b57cec5SDimitry Andric              ExtValue(ED).Offset == EV.Offset;
14670b57cec5SDimitry Andric     };
14680b57cec5SDimitry Andric     if (all_of(P.second, SameValue)) {
14690b57cec5SDimitry Andric       F->second.insert(P.second.begin(), P.second.end());
14700b57cec5SDimitry Andric       P.second.clear();
14710b57cec5SDimitry Andric     }
14720b57cec5SDimitry Andric   }
14730b57cec5SDimitry Andric 
14740b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "IMap (after fixup) = " << PrintIMap(IMap, *HRI));
14750b57cec5SDimitry Andric }
14760b57cec5SDimitry Andric 
14770b57cec5SDimitry Andric void HCE::calculatePlacement(const ExtenderInit &ExtI, const IndexList &Refs,
14780b57cec5SDimitry Andric       LocDefList &Defs) {
14790b57cec5SDimitry Andric   if (Refs.empty())
14800b57cec5SDimitry Andric     return;
14810b57cec5SDimitry Andric 
14820b57cec5SDimitry Andric   // The placement calculation is somewhat simple right now: it finds a
14830b57cec5SDimitry Andric   // single location for the def that dominates all refs. Since this may
14840b57cec5SDimitry Andric   // place the def far from the uses, producing several locations for
14850b57cec5SDimitry Andric   // defs that collectively dominate all refs could be better.
14860b57cec5SDimitry Andric   // For now only do the single one.
14870b57cec5SDimitry Andric   DenseSet<MachineBasicBlock*> Blocks;
14880b57cec5SDimitry Andric   DenseSet<MachineInstr*> RefMIs;
14890b57cec5SDimitry Andric   const ExtDesc &ED0 = Extenders[Refs[0]];
14900b57cec5SDimitry Andric   MachineBasicBlock *DomB = ED0.UseMI->getParent();
14910b57cec5SDimitry Andric   RefMIs.insert(ED0.UseMI);
14920b57cec5SDimitry Andric   Blocks.insert(DomB);
14930b57cec5SDimitry Andric   for (unsigned i = 1, e = Refs.size(); i != e; ++i) {
14940b57cec5SDimitry Andric     const ExtDesc &ED = Extenders[Refs[i]];
14950b57cec5SDimitry Andric     MachineBasicBlock *MBB = ED.UseMI->getParent();
14960b57cec5SDimitry Andric     RefMIs.insert(ED.UseMI);
14970b57cec5SDimitry Andric     DomB = MDT->findNearestCommonDominator(DomB, MBB);
14980b57cec5SDimitry Andric     Blocks.insert(MBB);
14990b57cec5SDimitry Andric   }
15000b57cec5SDimitry Andric 
15010b57cec5SDimitry Andric #ifndef NDEBUG
15020b57cec5SDimitry Andric   // The block DomB should be dominated by the def of each register used
15030b57cec5SDimitry Andric   // in the initializer.
15040b57cec5SDimitry Andric   Register Rs = ExtI.second.Rs;  // Only one reg allowed now.
15050b57cec5SDimitry Andric   const MachineInstr *DefI = Rs.isVReg() ? MRI->getVRegDef(Rs.Reg) : nullptr;
15060b57cec5SDimitry Andric 
15070b57cec5SDimitry Andric   // This should be guaranteed given that the entire expression is used
15080b57cec5SDimitry Andric   // at each instruction in Refs. Add an assertion just in case.
15090b57cec5SDimitry Andric   assert(!DefI || MDT->dominates(DefI->getParent(), DomB));
15100b57cec5SDimitry Andric #endif
15110b57cec5SDimitry Andric 
15120b57cec5SDimitry Andric   MachineBasicBlock::iterator It;
15130b57cec5SDimitry Andric   if (Blocks.count(DomB)) {
15140b57cec5SDimitry Andric     // Try to find the latest possible location for the def.
15150b57cec5SDimitry Andric     MachineBasicBlock::iterator End = DomB->end();
15160b57cec5SDimitry Andric     for (It = DomB->begin(); It != End; ++It)
15170b57cec5SDimitry Andric       if (RefMIs.count(&*It))
15180b57cec5SDimitry Andric         break;
15190b57cec5SDimitry Andric     assert(It != End && "Should have found a ref in DomB");
15200b57cec5SDimitry Andric   } else {
15210b57cec5SDimitry Andric     // DomB does not contain any refs.
15220b57cec5SDimitry Andric     It = DomB->getFirstTerminator();
15230b57cec5SDimitry Andric   }
15240b57cec5SDimitry Andric   Loc DefLoc(DomB, It);
15250b57cec5SDimitry Andric   Defs.emplace_back(DefLoc, Refs);
15260b57cec5SDimitry Andric }
15270b57cec5SDimitry Andric 
15280b57cec5SDimitry Andric HCE::Register HCE::insertInitializer(Loc DefL, const ExtenderInit &ExtI) {
15298bcb0991SDimitry Andric   llvm::Register DefR = MRI->createVirtualRegister(&Hexagon::IntRegsRegClass);
15300b57cec5SDimitry Andric   MachineBasicBlock &MBB = *DefL.Block;
15310b57cec5SDimitry Andric   MachineBasicBlock::iterator At = DefL.At;
15320b57cec5SDimitry Andric   DebugLoc dl = DefL.Block->findDebugLoc(DefL.At);
15330b57cec5SDimitry Andric   const ExtValue &EV = ExtI.first;
15340b57cec5SDimitry Andric   MachineOperand ExtOp(EV);
15350b57cec5SDimitry Andric 
15360b57cec5SDimitry Andric   const ExtExpr &Ex = ExtI.second;
15370b57cec5SDimitry Andric   const MachineInstr *InitI = nullptr;
15380b57cec5SDimitry Andric 
15390b57cec5SDimitry Andric   if (Ex.Rs.isSlot()) {
15400b57cec5SDimitry Andric     assert(Ex.S == 0 && "Cannot have a shift of a stack slot");
15410b57cec5SDimitry Andric     assert(!Ex.Neg && "Cannot subtract a stack slot");
15420b57cec5SDimitry Andric     // DefR = PS_fi Rb,##EV
15430b57cec5SDimitry Andric     InitI = BuildMI(MBB, At, dl, HII->get(Hexagon::PS_fi), DefR)
15440b57cec5SDimitry Andric               .add(MachineOperand(Ex.Rs))
15450b57cec5SDimitry Andric               .add(ExtOp);
15460b57cec5SDimitry Andric   } else {
15470b57cec5SDimitry Andric     assert((Ex.Rs.Reg == 0 || Ex.Rs.isVReg()) && "Expecting virtual register");
15480b57cec5SDimitry Andric     if (Ex.trivial()) {
15490b57cec5SDimitry Andric       // DefR = ##EV
15500b57cec5SDimitry Andric       InitI = BuildMI(MBB, At, dl, HII->get(Hexagon::A2_tfrsi), DefR)
15510b57cec5SDimitry Andric                 .add(ExtOp);
15520b57cec5SDimitry Andric     } else if (Ex.S == 0) {
15530b57cec5SDimitry Andric       if (Ex.Neg) {
15540b57cec5SDimitry Andric         // DefR = sub(##EV,Rb)
15550b57cec5SDimitry Andric         InitI = BuildMI(MBB, At, dl, HII->get(Hexagon::A2_subri), DefR)
15560b57cec5SDimitry Andric                   .add(ExtOp)
15570b57cec5SDimitry Andric                   .add(MachineOperand(Ex.Rs));
15580b57cec5SDimitry Andric       } else {
15590b57cec5SDimitry Andric         // DefR = add(Rb,##EV)
15600b57cec5SDimitry Andric         InitI = BuildMI(MBB, At, dl, HII->get(Hexagon::A2_addi), DefR)
15610b57cec5SDimitry Andric                   .add(MachineOperand(Ex.Rs))
15620b57cec5SDimitry Andric                   .add(ExtOp);
15630b57cec5SDimitry Andric       }
15640b57cec5SDimitry Andric     } else {
15650b57cec5SDimitry Andric       unsigned NewOpc = Ex.Neg ? Hexagon::S4_subi_asl_ri
15660b57cec5SDimitry Andric                                : Hexagon::S4_addi_asl_ri;
15670b57cec5SDimitry Andric       // DefR = add(##EV,asl(Rb,S))
15680b57cec5SDimitry Andric       InitI = BuildMI(MBB, At, dl, HII->get(NewOpc), DefR)
15690b57cec5SDimitry Andric                 .add(ExtOp)
15700b57cec5SDimitry Andric                 .add(MachineOperand(Ex.Rs))
15710b57cec5SDimitry Andric                 .addImm(Ex.S);
15720b57cec5SDimitry Andric     }
15730b57cec5SDimitry Andric   }
15740b57cec5SDimitry Andric 
15750b57cec5SDimitry Andric   assert(InitI);
15760b57cec5SDimitry Andric   (void)InitI;
15770b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Inserted def in bb#" << MBB.getNumber()
15780b57cec5SDimitry Andric                     << " for initializer: " << PrintInit(ExtI, *HRI) << "\n  "
15790b57cec5SDimitry Andric                     << *InitI);
15800b57cec5SDimitry Andric   return { DefR, 0 };
15810b57cec5SDimitry Andric }
15820b57cec5SDimitry Andric 
15830b57cec5SDimitry Andric // Replace the extender at index Idx with the register ExtR.
15840b57cec5SDimitry Andric bool HCE::replaceInstrExact(const ExtDesc &ED, Register ExtR) {
15850b57cec5SDimitry Andric   MachineInstr &MI = *ED.UseMI;
15860b57cec5SDimitry Andric   MachineBasicBlock &MBB = *MI.getParent();
15870b57cec5SDimitry Andric   MachineBasicBlock::iterator At = MI.getIterator();
15880b57cec5SDimitry Andric   DebugLoc dl = MI.getDebugLoc();
15890b57cec5SDimitry Andric   unsigned ExtOpc = MI.getOpcode();
15900b57cec5SDimitry Andric 
15910b57cec5SDimitry Andric   // With a few exceptions, direct replacement amounts to creating an
15920b57cec5SDimitry Andric   // instruction with a corresponding register opcode, with all operands
15930b57cec5SDimitry Andric   // the same, except for the register used in place of the extender.
15940b57cec5SDimitry Andric   unsigned RegOpc = getDirectRegReplacement(ExtOpc);
15950b57cec5SDimitry Andric 
15960b57cec5SDimitry Andric   if (RegOpc == TargetOpcode::REG_SEQUENCE) {
15970b57cec5SDimitry Andric     if (ExtOpc == Hexagon::A4_combineri)
15980b57cec5SDimitry Andric       BuildMI(MBB, At, dl, HII->get(RegOpc))
15990b57cec5SDimitry Andric         .add(MI.getOperand(0))
16000b57cec5SDimitry Andric         .add(MI.getOperand(1))
16010b57cec5SDimitry Andric         .addImm(Hexagon::isub_hi)
16020b57cec5SDimitry Andric         .add(MachineOperand(ExtR))
16030b57cec5SDimitry Andric         .addImm(Hexagon::isub_lo);
16040b57cec5SDimitry Andric     else if (ExtOpc == Hexagon::A4_combineir)
16050b57cec5SDimitry Andric       BuildMI(MBB, At, dl, HII->get(RegOpc))
16060b57cec5SDimitry Andric         .add(MI.getOperand(0))
16070b57cec5SDimitry Andric         .add(MachineOperand(ExtR))
16080b57cec5SDimitry Andric         .addImm(Hexagon::isub_hi)
16090b57cec5SDimitry Andric         .add(MI.getOperand(2))
16100b57cec5SDimitry Andric         .addImm(Hexagon::isub_lo);
16110b57cec5SDimitry Andric     else
16120b57cec5SDimitry Andric       llvm_unreachable("Unexpected opcode became REG_SEQUENCE");
16130b57cec5SDimitry Andric     MBB.erase(MI);
16140b57cec5SDimitry Andric     return true;
16150b57cec5SDimitry Andric   }
16160b57cec5SDimitry Andric   if (ExtOpc == Hexagon::C2_cmpgei || ExtOpc == Hexagon::C2_cmpgeui) {
16170b57cec5SDimitry Andric     unsigned NewOpc = ExtOpc == Hexagon::C2_cmpgei ? Hexagon::C2_cmplt
16180b57cec5SDimitry Andric                                                    : Hexagon::C2_cmpltu;
16190b57cec5SDimitry Andric     BuildMI(MBB, At, dl, HII->get(NewOpc))
16200b57cec5SDimitry Andric       .add(MI.getOperand(0))
16210b57cec5SDimitry Andric       .add(MachineOperand(ExtR))
16220b57cec5SDimitry Andric       .add(MI.getOperand(1));
16230b57cec5SDimitry Andric     MBB.erase(MI);
16240b57cec5SDimitry Andric     return true;
16250b57cec5SDimitry Andric   }
16260b57cec5SDimitry Andric 
16270b57cec5SDimitry Andric   if (RegOpc != 0) {
16280b57cec5SDimitry Andric     MachineInstrBuilder MIB = BuildMI(MBB, At, dl, HII->get(RegOpc));
16290b57cec5SDimitry Andric     unsigned RegN = ED.OpNum;
16300b57cec5SDimitry Andric     // Copy all operands except the one that has the extender.
16310b57cec5SDimitry Andric     for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
16320b57cec5SDimitry Andric       if (i != RegN)
16330b57cec5SDimitry Andric         MIB.add(MI.getOperand(i));
16340b57cec5SDimitry Andric       else
16350b57cec5SDimitry Andric         MIB.add(MachineOperand(ExtR));
16360b57cec5SDimitry Andric     }
16370b57cec5SDimitry Andric     MIB.cloneMemRefs(MI);
16380b57cec5SDimitry Andric     MBB.erase(MI);
16390b57cec5SDimitry Andric     return true;
16400b57cec5SDimitry Andric   }
16410b57cec5SDimitry Andric 
1642*480093f4SDimitry Andric   if (MI.mayLoadOrStore() && !isStoreImmediate(ExtOpc)) {
16430b57cec5SDimitry Andric     // For memory instructions, there is an asymmetry in the addressing
16440b57cec5SDimitry Andric     // modes. Addressing modes allowing extenders can be replaced with
16450b57cec5SDimitry Andric     // addressing modes that use registers, but the order of operands
16460b57cec5SDimitry Andric     // (or even their number) may be different.
16470b57cec5SDimitry Andric     // Replacements:
16480b57cec5SDimitry Andric     //   BaseImmOffset (io)  -> BaseRegOffset (rr)
16490b57cec5SDimitry Andric     //   BaseLongOffset (ur) -> BaseRegOffset (rr)
16500b57cec5SDimitry Andric     unsigned RegOpc, Shift;
16510b57cec5SDimitry Andric     unsigned AM = HII->getAddrMode(MI);
16520b57cec5SDimitry Andric     if (AM == HexagonII::BaseImmOffset) {
16530b57cec5SDimitry Andric       RegOpc = HII->changeAddrMode_io_rr(ExtOpc);
16540b57cec5SDimitry Andric       Shift = 0;
16550b57cec5SDimitry Andric     } else if (AM == HexagonII::BaseLongOffset) {
16560b57cec5SDimitry Andric       // Loads:  Rd = L4_loadri_ur Rs, S, ##
16570b57cec5SDimitry Andric       // Stores: S4_storeri_ur Rs, S, ##, Rt
16580b57cec5SDimitry Andric       RegOpc = HII->changeAddrMode_ur_rr(ExtOpc);
16590b57cec5SDimitry Andric       Shift = MI.getOperand(MI.mayLoad() ? 2 : 1).getImm();
16600b57cec5SDimitry Andric     } else {
16610b57cec5SDimitry Andric       llvm_unreachable("Unexpected addressing mode");
16620b57cec5SDimitry Andric     }
16630b57cec5SDimitry Andric #ifndef NDEBUG
16640b57cec5SDimitry Andric     if (RegOpc == -1u) {
16650b57cec5SDimitry Andric       dbgs() << "\nExtOpc: " << HII->getName(ExtOpc) << " has no rr version\n";
16660b57cec5SDimitry Andric       llvm_unreachable("No corresponding rr instruction");
16670b57cec5SDimitry Andric     }
16680b57cec5SDimitry Andric #endif
16690b57cec5SDimitry Andric 
16700b57cec5SDimitry Andric     unsigned BaseP, OffP;
16710b57cec5SDimitry Andric     HII->getBaseAndOffsetPosition(MI, BaseP, OffP);
16720b57cec5SDimitry Andric 
16730b57cec5SDimitry Andric     // Build an rr instruction: (RegOff + RegBase<<0)
16740b57cec5SDimitry Andric     MachineInstrBuilder MIB = BuildMI(MBB, At, dl, HII->get(RegOpc));
16750b57cec5SDimitry Andric     // First, add the def for loads.
16760b57cec5SDimitry Andric     if (MI.mayLoad())
16770b57cec5SDimitry Andric       MIB.add(getLoadResultOp(MI));
16780b57cec5SDimitry Andric     // Handle possible predication.
16790b57cec5SDimitry Andric     if (HII->isPredicated(MI))
16800b57cec5SDimitry Andric       MIB.add(getPredicateOp(MI));
16810b57cec5SDimitry Andric     // Build the address.
16820b57cec5SDimitry Andric     MIB.add(MachineOperand(ExtR));      // RegOff
16830b57cec5SDimitry Andric     MIB.add(MI.getOperand(BaseP));      // RegBase
16840b57cec5SDimitry Andric     MIB.addImm(Shift);                  // << Shift
16850b57cec5SDimitry Andric     // Add the stored value for stores.
16860b57cec5SDimitry Andric     if (MI.mayStore())
16870b57cec5SDimitry Andric       MIB.add(getStoredValueOp(MI));
16880b57cec5SDimitry Andric     MIB.cloneMemRefs(MI);
16890b57cec5SDimitry Andric     MBB.erase(MI);
16900b57cec5SDimitry Andric     return true;
16910b57cec5SDimitry Andric   }
16920b57cec5SDimitry Andric 
16930b57cec5SDimitry Andric #ifndef NDEBUG
16940b57cec5SDimitry Andric   dbgs() << '\n' << MI;
16950b57cec5SDimitry Andric #endif
16960b57cec5SDimitry Andric   llvm_unreachable("Unhandled exact replacement");
16970b57cec5SDimitry Andric   return false;
16980b57cec5SDimitry Andric }
16990b57cec5SDimitry Andric 
17000b57cec5SDimitry Andric // Replace the extender ED with a form corresponding to the initializer ExtI.
17010b57cec5SDimitry Andric bool HCE::replaceInstrExpr(const ExtDesc &ED, const ExtenderInit &ExtI,
17020b57cec5SDimitry Andric       Register ExtR, int32_t &Diff) {
17030b57cec5SDimitry Andric   MachineInstr &MI = *ED.UseMI;
17040b57cec5SDimitry Andric   MachineBasicBlock &MBB = *MI.getParent();
17050b57cec5SDimitry Andric   MachineBasicBlock::iterator At = MI.getIterator();
17060b57cec5SDimitry Andric   DebugLoc dl = MI.getDebugLoc();
17070b57cec5SDimitry Andric   unsigned ExtOpc = MI.getOpcode();
17080b57cec5SDimitry Andric 
17090b57cec5SDimitry Andric   if (ExtOpc == Hexagon::A2_tfrsi) {
17100b57cec5SDimitry Andric     // A2_tfrsi is a special case: it's replaced with A2_addi, which introduces
17110b57cec5SDimitry Andric     // another range. One range is the one that's common to all tfrsi's uses,
17120b57cec5SDimitry Andric     // this one is the range of immediates in A2_addi. When calculating ranges,
17130b57cec5SDimitry Andric     // the addi's 16-bit argument was included, so now we need to make it such
17140b57cec5SDimitry Andric     // that the produced value is in the range for the uses alone.
17150b57cec5SDimitry Andric     // Most of the time, simply adding Diff will make the addi produce exact
17160b57cec5SDimitry Andric     // result, but if Diff is outside of the 16-bit range, some adjustment
17170b57cec5SDimitry Andric     // will be needed.
17180b57cec5SDimitry Andric     unsigned IdxOpc = getRegOffOpcode(ExtOpc);
17190b57cec5SDimitry Andric     assert(IdxOpc == Hexagon::A2_addi);
17200b57cec5SDimitry Andric 
17210b57cec5SDimitry Andric     // Clamp Diff to the 16 bit range.
17220b57cec5SDimitry Andric     int32_t D = isInt<16>(Diff) ? Diff : (Diff > 0 ? 32767 : -32768);
17230b57cec5SDimitry Andric     if (Diff > 32767) {
17240b57cec5SDimitry Andric       // Split Diff into two values: one that is close to min/max int16,
17250b57cec5SDimitry Andric       // and the other being the rest, and such that both have the same
17260b57cec5SDimitry Andric       // "alignment" as Diff.
17270b57cec5SDimitry Andric       uint32_t UD = Diff;
17280b57cec5SDimitry Andric       OffsetRange R = getOffsetRange(MI.getOperand(0));
17290b57cec5SDimitry Andric       uint32_t A = std::min<uint32_t>(R.Align, 1u << countTrailingZeros(UD));
17300b57cec5SDimitry Andric       D &= ~(A-1);
17310b57cec5SDimitry Andric     }
17320b57cec5SDimitry Andric     BuildMI(MBB, At, dl, HII->get(IdxOpc))
17330b57cec5SDimitry Andric       .add(MI.getOperand(0))
17340b57cec5SDimitry Andric       .add(MachineOperand(ExtR))
17350b57cec5SDimitry Andric       .addImm(D);
17360b57cec5SDimitry Andric     Diff -= D;
17370b57cec5SDimitry Andric #ifndef NDEBUG
17380b57cec5SDimitry Andric     // Make sure the output is within allowable range for uses.
17390b57cec5SDimitry Andric     // "Diff" is a difference in the "opposite direction", i.e. Ext - DefV,
17400b57cec5SDimitry Andric     // not DefV - Ext, as the getOffsetRange would calculate.
17410b57cec5SDimitry Andric     OffsetRange Uses = getOffsetRange(MI.getOperand(0));
17420b57cec5SDimitry Andric     if (!Uses.contains(-Diff))
17430b57cec5SDimitry Andric       dbgs() << "Diff: " << -Diff << " out of range " << Uses
17440b57cec5SDimitry Andric              << " for " << MI;
17450b57cec5SDimitry Andric     assert(Uses.contains(-Diff));
17460b57cec5SDimitry Andric #endif
17470b57cec5SDimitry Andric     MBB.erase(MI);
17480b57cec5SDimitry Andric     return true;
17490b57cec5SDimitry Andric   }
17500b57cec5SDimitry Andric 
17510b57cec5SDimitry Andric   const ExtValue &EV = ExtI.first; (void)EV;
17520b57cec5SDimitry Andric   const ExtExpr &Ex = ExtI.second; (void)Ex;
17530b57cec5SDimitry Andric 
17540b57cec5SDimitry Andric   if (ExtOpc == Hexagon::A2_addi || ExtOpc == Hexagon::A2_subri) {
17550b57cec5SDimitry Andric     // If addi/subri are replaced with the exactly matching initializer,
17560b57cec5SDimitry Andric     // they amount to COPY.
17570b57cec5SDimitry Andric     // Check that the initializer is an exact match (for simplicity).
17580b57cec5SDimitry Andric #ifndef NDEBUG
17590b57cec5SDimitry Andric     bool IsAddi = ExtOpc == Hexagon::A2_addi;
17600b57cec5SDimitry Andric     const MachineOperand &RegOp = MI.getOperand(IsAddi ? 1 : 2);
17610b57cec5SDimitry Andric     const MachineOperand &ImmOp = MI.getOperand(IsAddi ? 2 : 1);
17620b57cec5SDimitry Andric     assert(Ex.Rs == RegOp && EV == ImmOp && Ex.Neg != IsAddi &&
17630b57cec5SDimitry Andric            "Initializer mismatch");
17640b57cec5SDimitry Andric #endif
17650b57cec5SDimitry Andric     BuildMI(MBB, At, dl, HII->get(TargetOpcode::COPY))
17660b57cec5SDimitry Andric       .add(MI.getOperand(0))
17670b57cec5SDimitry Andric       .add(MachineOperand(ExtR));
17680b57cec5SDimitry Andric     Diff = 0;
17690b57cec5SDimitry Andric     MBB.erase(MI);
17700b57cec5SDimitry Andric     return true;
17710b57cec5SDimitry Andric   }
17720b57cec5SDimitry Andric   if (ExtOpc == Hexagon::M2_accii || ExtOpc == Hexagon::M2_naccii ||
17730b57cec5SDimitry Andric       ExtOpc == Hexagon::S4_addaddi || ExtOpc == Hexagon::S4_subaddi) {
17740b57cec5SDimitry Andric     // M2_accii:    add(Rt,add(Rs,V)) (tied)
17750b57cec5SDimitry Andric     // M2_naccii:   sub(Rt,add(Rs,V))
17760b57cec5SDimitry Andric     // S4_addaddi:  add(Rt,add(Rs,V))
17770b57cec5SDimitry Andric     // S4_subaddi:  add(Rt,sub(V,Rs))
17780b57cec5SDimitry Andric     // Check that Rs and V match the initializer expression. The Rs+V is the
17790b57cec5SDimitry Andric     // combination that is considered "subexpression" for V, although Rx+V
17800b57cec5SDimitry Andric     // would also be valid.
17810b57cec5SDimitry Andric #ifndef NDEBUG
17820b57cec5SDimitry Andric     bool IsSub = ExtOpc == Hexagon::S4_subaddi;
17830b57cec5SDimitry Andric     Register Rs = MI.getOperand(IsSub ? 3 : 2);
17840b57cec5SDimitry Andric     ExtValue V = MI.getOperand(IsSub ? 2 : 3);
17850b57cec5SDimitry Andric     assert(EV == V && Rs == Ex.Rs && IsSub == Ex.Neg && "Initializer mismatch");
17860b57cec5SDimitry Andric #endif
17870b57cec5SDimitry Andric     unsigned NewOpc = ExtOpc == Hexagon::M2_naccii ? Hexagon::A2_sub
17880b57cec5SDimitry Andric                                                    : Hexagon::A2_add;
17890b57cec5SDimitry Andric     BuildMI(MBB, At, dl, HII->get(NewOpc))
17900b57cec5SDimitry Andric       .add(MI.getOperand(0))
17910b57cec5SDimitry Andric       .add(MI.getOperand(1))
17920b57cec5SDimitry Andric       .add(MachineOperand(ExtR));
17930b57cec5SDimitry Andric     MBB.erase(MI);
17940b57cec5SDimitry Andric     return true;
17950b57cec5SDimitry Andric   }
17960b57cec5SDimitry Andric 
1797*480093f4SDimitry Andric   if (MI.mayLoadOrStore()) {
17980b57cec5SDimitry Andric     unsigned IdxOpc = getRegOffOpcode(ExtOpc);
17990b57cec5SDimitry Andric     assert(IdxOpc && "Expecting indexed opcode");
18000b57cec5SDimitry Andric     MachineInstrBuilder MIB = BuildMI(MBB, At, dl, HII->get(IdxOpc));
18010b57cec5SDimitry Andric     // Construct the new indexed instruction.
18020b57cec5SDimitry Andric     // First, add the def for loads.
18030b57cec5SDimitry Andric     if (MI.mayLoad())
18040b57cec5SDimitry Andric       MIB.add(getLoadResultOp(MI));
18050b57cec5SDimitry Andric     // Handle possible predication.
18060b57cec5SDimitry Andric     if (HII->isPredicated(MI))
18070b57cec5SDimitry Andric       MIB.add(getPredicateOp(MI));
18080b57cec5SDimitry Andric     // Build the address.
18090b57cec5SDimitry Andric     MIB.add(MachineOperand(ExtR));
18100b57cec5SDimitry Andric     MIB.addImm(Diff);
18110b57cec5SDimitry Andric     // Add the stored value for stores.
18120b57cec5SDimitry Andric     if (MI.mayStore())
18130b57cec5SDimitry Andric       MIB.add(getStoredValueOp(MI));
18140b57cec5SDimitry Andric     MIB.cloneMemRefs(MI);
18150b57cec5SDimitry Andric     MBB.erase(MI);
18160b57cec5SDimitry Andric     return true;
18170b57cec5SDimitry Andric   }
18180b57cec5SDimitry Andric 
18190b57cec5SDimitry Andric #ifndef NDEBUG
18200b57cec5SDimitry Andric   dbgs() << '\n' << PrintInit(ExtI, *HRI) << "  " << MI;
18210b57cec5SDimitry Andric #endif
18220b57cec5SDimitry Andric   llvm_unreachable("Unhandled expr replacement");
18230b57cec5SDimitry Andric   return false;
18240b57cec5SDimitry Andric }
18250b57cec5SDimitry Andric 
18260b57cec5SDimitry Andric bool HCE::replaceInstr(unsigned Idx, Register ExtR, const ExtenderInit &ExtI) {
18270b57cec5SDimitry Andric   if (ReplaceLimit.getNumOccurrences()) {
18280b57cec5SDimitry Andric     if (ReplaceLimit <= ReplaceCounter)
18290b57cec5SDimitry Andric       return false;
18300b57cec5SDimitry Andric     ++ReplaceCounter;
18310b57cec5SDimitry Andric   }
18320b57cec5SDimitry Andric   const ExtDesc &ED = Extenders[Idx];
18330b57cec5SDimitry Andric   assert((!ED.IsDef || ED.Rd.Reg != 0) && "Missing Rd for def");
18340b57cec5SDimitry Andric   const ExtValue &DefV = ExtI.first;
18350b57cec5SDimitry Andric   assert(ExtRoot(ExtValue(ED)) == ExtRoot(DefV) && "Extender root mismatch");
18360b57cec5SDimitry Andric   const ExtExpr &DefEx = ExtI.second;
18370b57cec5SDimitry Andric 
18380b57cec5SDimitry Andric   ExtValue EV(ED);
18390b57cec5SDimitry Andric   int32_t Diff = EV.Offset - DefV.Offset;
18400b57cec5SDimitry Andric   const MachineInstr &MI = *ED.UseMI;
18410b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << __func__ << " Idx:" << Idx << " ExtR:"
18420b57cec5SDimitry Andric                     << PrintRegister(ExtR, *HRI) << " Diff:" << Diff << '\n');
18430b57cec5SDimitry Andric 
18440b57cec5SDimitry Andric   // These two addressing modes must be converted into indexed forms
18450b57cec5SDimitry Andric   // regardless of what the initializer looks like.
18460b57cec5SDimitry Andric   bool IsAbs = false, IsAbsSet = false;
1847*480093f4SDimitry Andric   if (MI.mayLoadOrStore()) {
18480b57cec5SDimitry Andric     unsigned AM = HII->getAddrMode(MI);
18490b57cec5SDimitry Andric     IsAbs = AM == HexagonII::Absolute;
18500b57cec5SDimitry Andric     IsAbsSet = AM == HexagonII::AbsoluteSet;
18510b57cec5SDimitry Andric   }
18520b57cec5SDimitry Andric 
18530b57cec5SDimitry Andric   // If it's a def, remember all operands that need to be updated.
18540b57cec5SDimitry Andric   // If ED is a def, and Diff is not 0, then all uses of the register Rd
18550b57cec5SDimitry Andric   // defined by ED must be in the form (Rd, imm), i.e. the immediate offset
18560b57cec5SDimitry Andric   // must follow the Rd in the operand list.
18570b57cec5SDimitry Andric   std::vector<std::pair<MachineInstr*,unsigned>> RegOps;
18580b57cec5SDimitry Andric   if (ED.IsDef && Diff != 0) {
18590b57cec5SDimitry Andric     for (MachineOperand &Op : MRI->use_operands(ED.Rd.Reg)) {
18600b57cec5SDimitry Andric       MachineInstr &UI = *Op.getParent();
18610b57cec5SDimitry Andric       RegOps.push_back({&UI, getOperandIndex(UI, Op)});
18620b57cec5SDimitry Andric     }
18630b57cec5SDimitry Andric   }
18640b57cec5SDimitry Andric 
18650b57cec5SDimitry Andric   // Replace the instruction.
18660b57cec5SDimitry Andric   bool Replaced = false;
18670b57cec5SDimitry Andric   if (Diff == 0 && DefEx.trivial() && !IsAbs && !IsAbsSet)
18680b57cec5SDimitry Andric     Replaced = replaceInstrExact(ED, ExtR);
18690b57cec5SDimitry Andric   else
18700b57cec5SDimitry Andric     Replaced = replaceInstrExpr(ED, ExtI, ExtR, Diff);
18710b57cec5SDimitry Andric 
18720b57cec5SDimitry Andric   if (Diff != 0 && Replaced && ED.IsDef) {
18730b57cec5SDimitry Andric     // Update offsets of the def's uses.
18740b57cec5SDimitry Andric     for (std::pair<MachineInstr*,unsigned> P : RegOps) {
18750b57cec5SDimitry Andric       unsigned J = P.second;
18760b57cec5SDimitry Andric       assert(P.first->getNumOperands() > J+1 &&
18770b57cec5SDimitry Andric              P.first->getOperand(J+1).isImm());
18780b57cec5SDimitry Andric       MachineOperand &ImmOp = P.first->getOperand(J+1);
18790b57cec5SDimitry Andric       ImmOp.setImm(ImmOp.getImm() + Diff);
18800b57cec5SDimitry Andric     }
18810b57cec5SDimitry Andric     // If it was an absolute-set instruction, the "set" part has been removed.
18820b57cec5SDimitry Andric     // ExtR will now be the register with the extended value, and since all
18830b57cec5SDimitry Andric     // users of Rd have been updated, all that needs to be done is to replace
18840b57cec5SDimitry Andric     // Rd with ExtR.
18850b57cec5SDimitry Andric     if (IsAbsSet) {
18860b57cec5SDimitry Andric       assert(ED.Rd.Sub == 0 && ExtR.Sub == 0);
18870b57cec5SDimitry Andric       MRI->replaceRegWith(ED.Rd.Reg, ExtR.Reg);
18880b57cec5SDimitry Andric     }
18890b57cec5SDimitry Andric   }
18900b57cec5SDimitry Andric 
18910b57cec5SDimitry Andric   return Replaced;
18920b57cec5SDimitry Andric }
18930b57cec5SDimitry Andric 
18940b57cec5SDimitry Andric bool HCE::replaceExtenders(const AssignmentMap &IMap) {
18950b57cec5SDimitry Andric   LocDefList Defs;
18960b57cec5SDimitry Andric   bool Changed = false;
18970b57cec5SDimitry Andric 
1898*480093f4SDimitry Andric   for (const std::pair<const ExtenderInit, IndexList> &P : IMap) {
18990b57cec5SDimitry Andric     const IndexList &Idxs = P.second;
19000b57cec5SDimitry Andric     if (Idxs.size() < CountThreshold)
19010b57cec5SDimitry Andric       continue;
19020b57cec5SDimitry Andric 
19030b57cec5SDimitry Andric     Defs.clear();
19040b57cec5SDimitry Andric     calculatePlacement(P.first, Idxs, Defs);
19050b57cec5SDimitry Andric     for (const std::pair<Loc,IndexList> &Q : Defs) {
19060b57cec5SDimitry Andric       Register DefR = insertInitializer(Q.first, P.first);
19070b57cec5SDimitry Andric       NewRegs.push_back(DefR.Reg);
19080b57cec5SDimitry Andric       for (unsigned I : Q.second)
19090b57cec5SDimitry Andric         Changed |= replaceInstr(I, DefR, P.first);
19100b57cec5SDimitry Andric     }
19110b57cec5SDimitry Andric   }
19120b57cec5SDimitry Andric   return Changed;
19130b57cec5SDimitry Andric }
19140b57cec5SDimitry Andric 
19150b57cec5SDimitry Andric unsigned HCE::getOperandIndex(const MachineInstr &MI,
19160b57cec5SDimitry Andric       const MachineOperand &Op) const {
19170b57cec5SDimitry Andric   for (unsigned i = 0, n = MI.getNumOperands(); i != n; ++i)
19180b57cec5SDimitry Andric     if (&MI.getOperand(i) == &Op)
19190b57cec5SDimitry Andric       return i;
19200b57cec5SDimitry Andric   llvm_unreachable("Not an operand of MI");
19210b57cec5SDimitry Andric }
19220b57cec5SDimitry Andric 
19230b57cec5SDimitry Andric const MachineOperand &HCE::getPredicateOp(const MachineInstr &MI) const {
19240b57cec5SDimitry Andric   assert(HII->isPredicated(MI));
19250b57cec5SDimitry Andric   for (const MachineOperand &Op : MI.operands()) {
19260b57cec5SDimitry Andric     if (!Op.isReg() || !Op.isUse() ||
19270b57cec5SDimitry Andric         MRI->getRegClass(Op.getReg()) != &Hexagon::PredRegsRegClass)
19280b57cec5SDimitry Andric       continue;
19290b57cec5SDimitry Andric     assert(Op.getSubReg() == 0 && "Predicate register with a subregister");
19300b57cec5SDimitry Andric     return Op;
19310b57cec5SDimitry Andric   }
19320b57cec5SDimitry Andric   llvm_unreachable("Predicate operand not found");
19330b57cec5SDimitry Andric }
19340b57cec5SDimitry Andric 
19350b57cec5SDimitry Andric const MachineOperand &HCE::getLoadResultOp(const MachineInstr &MI) const {
19360b57cec5SDimitry Andric   assert(MI.mayLoad());
19370b57cec5SDimitry Andric   return MI.getOperand(0);
19380b57cec5SDimitry Andric }
19390b57cec5SDimitry Andric 
19400b57cec5SDimitry Andric const MachineOperand &HCE::getStoredValueOp(const MachineInstr &MI) const {
19410b57cec5SDimitry Andric   assert(MI.mayStore());
19420b57cec5SDimitry Andric   return MI.getOperand(MI.getNumExplicitOperands()-1);
19430b57cec5SDimitry Andric }
19440b57cec5SDimitry Andric 
19450b57cec5SDimitry Andric bool HCE::runOnMachineFunction(MachineFunction &MF) {
19460b57cec5SDimitry Andric   if (skipFunction(MF.getFunction()))
19470b57cec5SDimitry Andric     return false;
19480b57cec5SDimitry Andric   if (MF.getFunction().hasPersonalityFn()) {
19490b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << getPassName() << ": skipping " << MF.getName()
19500b57cec5SDimitry Andric                       << " due to exception handling\n");
19510b57cec5SDimitry Andric     return false;
19520b57cec5SDimitry Andric   }
19530b57cec5SDimitry Andric   LLVM_DEBUG(MF.print(dbgs() << "Before " << getPassName() << '\n', nullptr));
19540b57cec5SDimitry Andric 
19550b57cec5SDimitry Andric   HII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
19560b57cec5SDimitry Andric   HRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
19570b57cec5SDimitry Andric   MDT = &getAnalysis<MachineDominatorTree>();
19580b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
19590b57cec5SDimitry Andric   AssignmentMap IMap;
19600b57cec5SDimitry Andric 
19610b57cec5SDimitry Andric   collect(MF);
19620b57cec5SDimitry Andric   llvm::sort(Extenders, [this](const ExtDesc &A, const ExtDesc &B) {
19630b57cec5SDimitry Andric     ExtValue VA(A), VB(B);
19640b57cec5SDimitry Andric     if (VA != VB)
19650b57cec5SDimitry Andric       return VA < VB;
19660b57cec5SDimitry Andric     const MachineInstr *MA = A.UseMI;
19670b57cec5SDimitry Andric     const MachineInstr *MB = B.UseMI;
19680b57cec5SDimitry Andric     if (MA == MB) {
19690b57cec5SDimitry Andric       // If it's the same instruction, compare operand numbers.
19700b57cec5SDimitry Andric       return A.OpNum < B.OpNum;
19710b57cec5SDimitry Andric     }
19720b57cec5SDimitry Andric 
19730b57cec5SDimitry Andric     const MachineBasicBlock *BA = MA->getParent();
19740b57cec5SDimitry Andric     const MachineBasicBlock *BB = MB->getParent();
19750b57cec5SDimitry Andric     assert(BA->getNumber() != -1 && BB->getNumber() != -1);
19760b57cec5SDimitry Andric     if (BA != BB)
19770b57cec5SDimitry Andric       return BA->getNumber() < BB->getNumber();
19780b57cec5SDimitry Andric     return MDT->dominates(MA, MB);
19790b57cec5SDimitry Andric   });
19800b57cec5SDimitry Andric 
19810b57cec5SDimitry Andric   bool Changed = false;
19820b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Collected " << Extenders.size() << " extenders\n");
19830b57cec5SDimitry Andric   for (unsigned I = 0, E = Extenders.size(); I != E; ) {
19840b57cec5SDimitry Andric     unsigned B = I;
19850b57cec5SDimitry Andric     const ExtRoot &T = Extenders[B].getOp();
19860b57cec5SDimitry Andric     while (I != E && ExtRoot(Extenders[I].getOp()) == T)
19870b57cec5SDimitry Andric       ++I;
19880b57cec5SDimitry Andric 
19890b57cec5SDimitry Andric     IMap.clear();
19900b57cec5SDimitry Andric     assignInits(T, B, I, IMap);
19910b57cec5SDimitry Andric     Changed |= replaceExtenders(IMap);
19920b57cec5SDimitry Andric   }
19930b57cec5SDimitry Andric 
19940b57cec5SDimitry Andric   LLVM_DEBUG({
19950b57cec5SDimitry Andric     if (Changed)
19960b57cec5SDimitry Andric       MF.print(dbgs() << "After " << getPassName() << '\n', nullptr);
19970b57cec5SDimitry Andric     else
19980b57cec5SDimitry Andric       dbgs() << "No changes\n";
19990b57cec5SDimitry Andric   });
20000b57cec5SDimitry Andric   return Changed;
20010b57cec5SDimitry Andric }
20020b57cec5SDimitry Andric 
20030b57cec5SDimitry Andric FunctionPass *llvm::createHexagonConstExtenders() {
20040b57cec5SDimitry Andric   return new HexagonConstExtenders();
20050b57cec5SDimitry Andric }
2006