xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonConstExtenders.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- HexagonConstExtenders.cpp ------------------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "HexagonInstrInfo.h"
10*0b57cec5SDimitry Andric #include "HexagonRegisterInfo.h"
11*0b57cec5SDimitry Andric #include "HexagonSubtarget.h"
12*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
13*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
14*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
15*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
16*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
17*0b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
18*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
19*0b57cec5SDimitry Andric #include "llvm/Pass.h"
20*0b57cec5SDimitry Andric #include <map>
21*0b57cec5SDimitry Andric #include <set>
22*0b57cec5SDimitry Andric #include <utility>
23*0b57cec5SDimitry Andric #include <vector>
24*0b57cec5SDimitry Andric 
25*0b57cec5SDimitry Andric #define DEBUG_TYPE "hexagon-cext-opt"
26*0b57cec5SDimitry Andric 
27*0b57cec5SDimitry Andric using namespace llvm;
28*0b57cec5SDimitry Andric 
29*0b57cec5SDimitry Andric static cl::opt<unsigned> CountThreshold("hexagon-cext-threshold",
30*0b57cec5SDimitry Andric   cl::init(3), cl::Hidden, cl::ZeroOrMore,
31*0b57cec5SDimitry Andric   cl::desc("Minimum number of extenders to trigger replacement"));
32*0b57cec5SDimitry Andric 
33*0b57cec5SDimitry Andric static cl::opt<unsigned> ReplaceLimit("hexagon-cext-limit", cl::init(0),
34*0b57cec5SDimitry Andric   cl::Hidden, cl::ZeroOrMore, cl::desc("Maximum number of replacements"));
35*0b57cec5SDimitry Andric 
36*0b57cec5SDimitry Andric namespace llvm {
37*0b57cec5SDimitry Andric   void initializeHexagonConstExtendersPass(PassRegistry&);
38*0b57cec5SDimitry Andric   FunctionPass *createHexagonConstExtenders();
39*0b57cec5SDimitry Andric }
40*0b57cec5SDimitry Andric 
41*0b57cec5SDimitry Andric static int32_t adjustUp(int32_t V, uint8_t A, uint8_t O) {
42*0b57cec5SDimitry Andric   assert(isPowerOf2_32(A));
43*0b57cec5SDimitry Andric   int32_t U = (V & -A) + O;
44*0b57cec5SDimitry Andric   return U >= V ? U : U+A;
45*0b57cec5SDimitry Andric }
46*0b57cec5SDimitry Andric 
47*0b57cec5SDimitry Andric static int32_t adjustDown(int32_t V, uint8_t A, uint8_t O) {
48*0b57cec5SDimitry Andric   assert(isPowerOf2_32(A));
49*0b57cec5SDimitry Andric   int32_t U = (V & -A) + O;
50*0b57cec5SDimitry Andric   return U <= V ? U : U-A;
51*0b57cec5SDimitry Andric }
52*0b57cec5SDimitry Andric 
53*0b57cec5SDimitry Andric namespace {
54*0b57cec5SDimitry Andric   struct OffsetRange {
55*0b57cec5SDimitry Andric     // The range of values between Min and Max that are of form Align*N+Offset,
56*0b57cec5SDimitry Andric     // for some integer N. Min and Max are required to be of that form as well,
57*0b57cec5SDimitry Andric     // except in the case of an empty range.
58*0b57cec5SDimitry Andric     int32_t Min = INT_MIN, Max = INT_MAX;
59*0b57cec5SDimitry Andric     uint8_t Align = 1;
60*0b57cec5SDimitry Andric     uint8_t Offset = 0;
61*0b57cec5SDimitry Andric 
62*0b57cec5SDimitry Andric     OffsetRange() = default;
63*0b57cec5SDimitry Andric     OffsetRange(int32_t L, int32_t H, uint8_t A, uint8_t O = 0)
64*0b57cec5SDimitry Andric       : Min(L), Max(H), Align(A), Offset(O) {}
65*0b57cec5SDimitry Andric     OffsetRange &intersect(OffsetRange A) {
66*0b57cec5SDimitry Andric       if (Align < A.Align)
67*0b57cec5SDimitry Andric         std::swap(*this, A);
68*0b57cec5SDimitry Andric 
69*0b57cec5SDimitry Andric       // Align >= A.Align.
70*0b57cec5SDimitry Andric       if (Offset >= A.Offset && (Offset - A.Offset) % A.Align == 0) {
71*0b57cec5SDimitry Andric         Min = adjustUp(std::max(Min, A.Min), Align, Offset);
72*0b57cec5SDimitry Andric         Max = adjustDown(std::min(Max, A.Max), Align, Offset);
73*0b57cec5SDimitry Andric       } else {
74*0b57cec5SDimitry Andric         // Make an empty range.
75*0b57cec5SDimitry Andric         Min = 0;
76*0b57cec5SDimitry Andric         Max = -1;
77*0b57cec5SDimitry Andric       }
78*0b57cec5SDimitry Andric       // Canonicalize empty ranges.
79*0b57cec5SDimitry Andric       if (Min > Max)
80*0b57cec5SDimitry Andric         std::tie(Min, Max, Align) = std::make_tuple(0, -1, 1);
81*0b57cec5SDimitry Andric       return *this;
82*0b57cec5SDimitry Andric     }
83*0b57cec5SDimitry Andric     OffsetRange &shift(int32_t S) {
84*0b57cec5SDimitry Andric       Min += S;
85*0b57cec5SDimitry Andric       Max += S;
86*0b57cec5SDimitry Andric       Offset = (Offset+S) % Align;
87*0b57cec5SDimitry Andric       return *this;
88*0b57cec5SDimitry Andric     }
89*0b57cec5SDimitry Andric     OffsetRange &extendBy(int32_t D) {
90*0b57cec5SDimitry Andric       // If D < 0, extend Min, otherwise extend Max.
91*0b57cec5SDimitry Andric       assert(D % Align == 0);
92*0b57cec5SDimitry Andric       if (D < 0)
93*0b57cec5SDimitry Andric         Min = (INT_MIN-D < Min) ? Min+D : INT_MIN;
94*0b57cec5SDimitry Andric       else
95*0b57cec5SDimitry Andric         Max = (INT_MAX-D > Max) ? Max+D : INT_MAX;
96*0b57cec5SDimitry Andric       return *this;
97*0b57cec5SDimitry Andric     }
98*0b57cec5SDimitry Andric     bool empty() const {
99*0b57cec5SDimitry Andric       return Min > Max;
100*0b57cec5SDimitry Andric     }
101*0b57cec5SDimitry Andric     bool contains(int32_t V) const {
102*0b57cec5SDimitry Andric       return Min <= V && V <= Max && (V-Offset) % Align == 0;
103*0b57cec5SDimitry Andric     }
104*0b57cec5SDimitry Andric     bool operator==(const OffsetRange &R) const {
105*0b57cec5SDimitry Andric       return Min == R.Min && Max == R.Max && Align == R.Align;
106*0b57cec5SDimitry Andric     }
107*0b57cec5SDimitry Andric     bool operator!=(const OffsetRange &R) const {
108*0b57cec5SDimitry Andric       return !operator==(R);
109*0b57cec5SDimitry Andric     }
110*0b57cec5SDimitry Andric     bool operator<(const OffsetRange &R) const {
111*0b57cec5SDimitry Andric       if (Min != R.Min)
112*0b57cec5SDimitry Andric         return Min < R.Min;
113*0b57cec5SDimitry Andric       if (Max != R.Max)
114*0b57cec5SDimitry Andric         return Max < R.Max;
115*0b57cec5SDimitry Andric       return Align < R.Align;
116*0b57cec5SDimitry Andric     }
117*0b57cec5SDimitry Andric     static OffsetRange zero() { return {0, 0, 1}; }
118*0b57cec5SDimitry Andric   };
119*0b57cec5SDimitry Andric 
120*0b57cec5SDimitry Andric   struct RangeTree {
121*0b57cec5SDimitry Andric     struct Node {
122*0b57cec5SDimitry Andric       Node(const OffsetRange &R) : MaxEnd(R.Max), Range(R) {}
123*0b57cec5SDimitry Andric       unsigned Height = 1;
124*0b57cec5SDimitry Andric       unsigned Count = 1;
125*0b57cec5SDimitry Andric       int32_t MaxEnd;
126*0b57cec5SDimitry Andric       const OffsetRange &Range;
127*0b57cec5SDimitry Andric       Node *Left = nullptr, *Right = nullptr;
128*0b57cec5SDimitry Andric     };
129*0b57cec5SDimitry Andric 
130*0b57cec5SDimitry Andric     Node *Root = nullptr;
131*0b57cec5SDimitry Andric 
132*0b57cec5SDimitry Andric     void add(const OffsetRange &R) {
133*0b57cec5SDimitry Andric       Root = add(Root, R);
134*0b57cec5SDimitry Andric     }
135*0b57cec5SDimitry Andric     void erase(const Node *N) {
136*0b57cec5SDimitry Andric       Root = remove(Root, N);
137*0b57cec5SDimitry Andric       delete N;
138*0b57cec5SDimitry Andric     }
139*0b57cec5SDimitry Andric     void order(SmallVectorImpl<Node*> &Seq) const {
140*0b57cec5SDimitry Andric       order(Root, Seq);
141*0b57cec5SDimitry Andric     }
142*0b57cec5SDimitry Andric     SmallVector<Node*,8> nodesWith(int32_t P, bool CheckAlign = true) {
143*0b57cec5SDimitry Andric       SmallVector<Node*,8> Nodes;
144*0b57cec5SDimitry Andric       nodesWith(Root, P, CheckAlign, Nodes);
145*0b57cec5SDimitry Andric       return Nodes;
146*0b57cec5SDimitry Andric     }
147*0b57cec5SDimitry Andric     void dump() const;
148*0b57cec5SDimitry Andric     ~RangeTree() {
149*0b57cec5SDimitry Andric       SmallVector<Node*,8> Nodes;
150*0b57cec5SDimitry Andric       order(Nodes);
151*0b57cec5SDimitry Andric       for (Node *N : Nodes)
152*0b57cec5SDimitry Andric         delete N;
153*0b57cec5SDimitry Andric     }
154*0b57cec5SDimitry Andric 
155*0b57cec5SDimitry Andric   private:
156*0b57cec5SDimitry Andric     void dump(const Node *N) const;
157*0b57cec5SDimitry Andric     void order(Node *N, SmallVectorImpl<Node*> &Seq) const;
158*0b57cec5SDimitry Andric     void nodesWith(Node *N, int32_t P, bool CheckA,
159*0b57cec5SDimitry Andric                    SmallVectorImpl<Node*> &Seq) const;
160*0b57cec5SDimitry Andric 
161*0b57cec5SDimitry Andric     Node *add(Node *N, const OffsetRange &R);
162*0b57cec5SDimitry Andric     Node *remove(Node *N, const Node *D);
163*0b57cec5SDimitry Andric     Node *rotateLeft(Node *Lower, Node *Higher);
164*0b57cec5SDimitry Andric     Node *rotateRight(Node *Lower, Node *Higher);
165*0b57cec5SDimitry Andric     unsigned height(Node *N) {
166*0b57cec5SDimitry Andric       return N != nullptr ? N->Height : 0;
167*0b57cec5SDimitry Andric     }
168*0b57cec5SDimitry Andric     Node *update(Node *N) {
169*0b57cec5SDimitry Andric       assert(N != nullptr);
170*0b57cec5SDimitry Andric       N->Height = 1 + std::max(height(N->Left), height(N->Right));
171*0b57cec5SDimitry Andric       if (N->Left)
172*0b57cec5SDimitry Andric         N->MaxEnd = std::max(N->MaxEnd, N->Left->MaxEnd);
173*0b57cec5SDimitry Andric       if (N->Right)
174*0b57cec5SDimitry Andric         N->MaxEnd = std::max(N->MaxEnd, N->Right->MaxEnd);
175*0b57cec5SDimitry Andric       return N;
176*0b57cec5SDimitry Andric     }
177*0b57cec5SDimitry Andric     Node *rebalance(Node *N) {
178*0b57cec5SDimitry Andric       assert(N != nullptr);
179*0b57cec5SDimitry Andric       int32_t Balance = height(N->Right) - height(N->Left);
180*0b57cec5SDimitry Andric       if (Balance < -1)
181*0b57cec5SDimitry Andric         return rotateRight(N->Left, N);
182*0b57cec5SDimitry Andric       if (Balance > 1)
183*0b57cec5SDimitry Andric         return rotateLeft(N->Right, N);
184*0b57cec5SDimitry Andric       return N;
185*0b57cec5SDimitry Andric     }
186*0b57cec5SDimitry Andric   };
187*0b57cec5SDimitry Andric 
188*0b57cec5SDimitry Andric   struct Loc {
189*0b57cec5SDimitry Andric     MachineBasicBlock *Block = nullptr;
190*0b57cec5SDimitry Andric     MachineBasicBlock::iterator At;
191*0b57cec5SDimitry Andric 
192*0b57cec5SDimitry Andric     Loc(MachineBasicBlock *B, MachineBasicBlock::iterator It)
193*0b57cec5SDimitry Andric       : Block(B), At(It) {
194*0b57cec5SDimitry Andric       if (B->end() == It) {
195*0b57cec5SDimitry Andric         Pos = -1;
196*0b57cec5SDimitry Andric       } else {
197*0b57cec5SDimitry Andric         assert(It->getParent() == B);
198*0b57cec5SDimitry Andric         Pos = std::distance(B->begin(), It);
199*0b57cec5SDimitry Andric       }
200*0b57cec5SDimitry Andric     }
201*0b57cec5SDimitry Andric     bool operator<(Loc A) const {
202*0b57cec5SDimitry Andric       if (Block != A.Block)
203*0b57cec5SDimitry Andric         return Block->getNumber() < A.Block->getNumber();
204*0b57cec5SDimitry Andric       if (A.Pos == -1)
205*0b57cec5SDimitry Andric         return Pos != A.Pos;
206*0b57cec5SDimitry Andric       return Pos != -1 && Pos < A.Pos;
207*0b57cec5SDimitry Andric     }
208*0b57cec5SDimitry Andric   private:
209*0b57cec5SDimitry Andric     int Pos = 0;
210*0b57cec5SDimitry Andric   };
211*0b57cec5SDimitry Andric 
212*0b57cec5SDimitry Andric   struct HexagonConstExtenders : public MachineFunctionPass {
213*0b57cec5SDimitry Andric     static char ID;
214*0b57cec5SDimitry Andric     HexagonConstExtenders() : MachineFunctionPass(ID) {}
215*0b57cec5SDimitry Andric 
216*0b57cec5SDimitry Andric     void getAnalysisUsage(AnalysisUsage &AU) const override {
217*0b57cec5SDimitry Andric       AU.addRequired<MachineDominatorTree>();
218*0b57cec5SDimitry Andric       AU.addPreserved<MachineDominatorTree>();
219*0b57cec5SDimitry Andric       MachineFunctionPass::getAnalysisUsage(AU);
220*0b57cec5SDimitry Andric     }
221*0b57cec5SDimitry Andric 
222*0b57cec5SDimitry Andric     StringRef getPassName() const override {
223*0b57cec5SDimitry Andric       return "Hexagon constant-extender optimization";
224*0b57cec5SDimitry Andric     }
225*0b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &MF) override;
226*0b57cec5SDimitry Andric 
227*0b57cec5SDimitry Andric   private:
228*0b57cec5SDimitry Andric     struct Register {
229*0b57cec5SDimitry Andric       Register() = default;
230*0b57cec5SDimitry Andric       Register(unsigned R, unsigned S) : Reg(R), Sub(S) {}
231*0b57cec5SDimitry Andric       Register(const MachineOperand &Op)
232*0b57cec5SDimitry Andric         : Reg(Op.getReg()), Sub(Op.getSubReg()) {}
233*0b57cec5SDimitry Andric       Register &operator=(const MachineOperand &Op) {
234*0b57cec5SDimitry Andric         if (Op.isReg()) {
235*0b57cec5SDimitry Andric           Reg = Op.getReg();
236*0b57cec5SDimitry Andric           Sub = Op.getSubReg();
237*0b57cec5SDimitry Andric         } else if (Op.isFI()) {
238*0b57cec5SDimitry Andric           Reg = TargetRegisterInfo::index2StackSlot(Op.getIndex());
239*0b57cec5SDimitry Andric         }
240*0b57cec5SDimitry Andric         return *this;
241*0b57cec5SDimitry Andric       }
242*0b57cec5SDimitry Andric       bool isVReg() const {
243*0b57cec5SDimitry Andric         return Reg != 0 && !TargetRegisterInfo::isStackSlot(Reg) &&
244*0b57cec5SDimitry Andric                TargetRegisterInfo::isVirtualRegister(Reg);
245*0b57cec5SDimitry Andric       }
246*0b57cec5SDimitry Andric       bool isSlot() const {
247*0b57cec5SDimitry Andric         return Reg != 0 && TargetRegisterInfo::isStackSlot(Reg);
248*0b57cec5SDimitry Andric       }
249*0b57cec5SDimitry Andric       operator MachineOperand() const {
250*0b57cec5SDimitry Andric         if (isVReg())
251*0b57cec5SDimitry Andric           return MachineOperand::CreateReg(Reg, /*Def*/false, /*Imp*/false,
252*0b57cec5SDimitry Andric                           /*Kill*/false, /*Dead*/false, /*Undef*/false,
253*0b57cec5SDimitry Andric                           /*EarlyClobber*/false, Sub);
254*0b57cec5SDimitry Andric         if (TargetRegisterInfo::isStackSlot(Reg)) {
255*0b57cec5SDimitry Andric           int FI = TargetRegisterInfo::stackSlot2Index(Reg);
256*0b57cec5SDimitry Andric           return MachineOperand::CreateFI(FI);
257*0b57cec5SDimitry Andric         }
258*0b57cec5SDimitry Andric         llvm_unreachable("Cannot create MachineOperand");
259*0b57cec5SDimitry Andric       }
260*0b57cec5SDimitry Andric       bool operator==(Register R) const { return Reg == R.Reg && Sub == R.Sub; }
261*0b57cec5SDimitry Andric       bool operator!=(Register R) const { return !operator==(R); }
262*0b57cec5SDimitry Andric       bool operator<(Register R) const {
263*0b57cec5SDimitry Andric         // For std::map.
264*0b57cec5SDimitry Andric         return Reg < R.Reg || (Reg == R.Reg && Sub < R.Sub);
265*0b57cec5SDimitry Andric       }
266*0b57cec5SDimitry Andric       unsigned Reg = 0, Sub = 0;
267*0b57cec5SDimitry Andric     };
268*0b57cec5SDimitry Andric 
269*0b57cec5SDimitry Andric     struct ExtExpr {
270*0b57cec5SDimitry Andric       // A subexpression in which the extender is used. In general, this
271*0b57cec5SDimitry Andric       // represents an expression where adding D to the extender will be
272*0b57cec5SDimitry Andric       // equivalent to adding D to the expression as a whole. In other
273*0b57cec5SDimitry Andric       // words, expr(add(##V,D) = add(expr(##V),D).
274*0b57cec5SDimitry Andric 
275*0b57cec5SDimitry Andric       // The original motivation for this are the io/ur addressing modes,
276*0b57cec5SDimitry Andric       // where the offset is extended. Consider the io example:
277*0b57cec5SDimitry Andric       // In memw(Rs+##V), the ##V could be replaced by a register Rt to
278*0b57cec5SDimitry Andric       // form the rr mode: memw(Rt+Rs<<0). In such case, however, the
279*0b57cec5SDimitry Andric       // register Rt must have exactly the value of ##V. If there was
280*0b57cec5SDimitry Andric       // another instruction memw(Rs+##V+4), it would need a different Rt.
281*0b57cec5SDimitry Andric       // Now, if Rt was initialized as "##V+Rs<<0", both of these
282*0b57cec5SDimitry Andric       // instructions could use the same Rt, just with different offsets.
283*0b57cec5SDimitry Andric       // Here it's clear that "initializer+4" should be the same as if
284*0b57cec5SDimitry Andric       // the offset 4 was added to the ##V in the initializer.
285*0b57cec5SDimitry Andric 
286*0b57cec5SDimitry Andric       // The only kinds of expressions that support the requirement of
287*0b57cec5SDimitry Andric       // commuting with addition are addition and subtraction from ##V.
288*0b57cec5SDimitry Andric       // Include shifting the Rs to account for the ur addressing mode:
289*0b57cec5SDimitry Andric       //   ##Val + Rs << S
290*0b57cec5SDimitry Andric       //   ##Val - Rs
291*0b57cec5SDimitry Andric       Register Rs;
292*0b57cec5SDimitry Andric       unsigned S = 0;
293*0b57cec5SDimitry Andric       bool Neg = false;
294*0b57cec5SDimitry Andric 
295*0b57cec5SDimitry Andric       ExtExpr() = default;
296*0b57cec5SDimitry Andric       ExtExpr(Register RS, bool NG, unsigned SH) : Rs(RS), S(SH), Neg(NG) {}
297*0b57cec5SDimitry Andric       // Expression is trivial if it does not modify the extender.
298*0b57cec5SDimitry Andric       bool trivial() const {
299*0b57cec5SDimitry Andric         return Rs.Reg == 0;
300*0b57cec5SDimitry Andric       }
301*0b57cec5SDimitry Andric       bool operator==(const ExtExpr &Ex) const {
302*0b57cec5SDimitry Andric         return Rs == Ex.Rs && S == Ex.S && Neg == Ex.Neg;
303*0b57cec5SDimitry Andric       }
304*0b57cec5SDimitry Andric       bool operator!=(const ExtExpr &Ex) const {
305*0b57cec5SDimitry Andric         return !operator==(Ex);
306*0b57cec5SDimitry Andric       }
307*0b57cec5SDimitry Andric       bool operator<(const ExtExpr &Ex) const {
308*0b57cec5SDimitry Andric         if (Rs != Ex.Rs)
309*0b57cec5SDimitry Andric           return Rs < Ex.Rs;
310*0b57cec5SDimitry Andric         if (S != Ex.S)
311*0b57cec5SDimitry Andric           return S < Ex.S;
312*0b57cec5SDimitry Andric         return !Neg && Ex.Neg;
313*0b57cec5SDimitry Andric       }
314*0b57cec5SDimitry Andric     };
315*0b57cec5SDimitry Andric 
316*0b57cec5SDimitry Andric     struct ExtDesc {
317*0b57cec5SDimitry Andric       MachineInstr *UseMI = nullptr;
318*0b57cec5SDimitry Andric       unsigned OpNum = -1u;
319*0b57cec5SDimitry Andric       // The subexpression in which the extender is used (e.g. address
320*0b57cec5SDimitry Andric       // computation).
321*0b57cec5SDimitry Andric       ExtExpr Expr;
322*0b57cec5SDimitry Andric       // Optional register that is assigned the value of Expr.
323*0b57cec5SDimitry Andric       Register Rd;
324*0b57cec5SDimitry Andric       // Def means that the output of the instruction may differ from the
325*0b57cec5SDimitry Andric       // original by a constant c, and that the difference can be corrected
326*0b57cec5SDimitry Andric       // by adding/subtracting c in all users of the defined register.
327*0b57cec5SDimitry Andric       bool IsDef = false;
328*0b57cec5SDimitry Andric 
329*0b57cec5SDimitry Andric       MachineOperand &getOp() {
330*0b57cec5SDimitry Andric         return UseMI->getOperand(OpNum);
331*0b57cec5SDimitry Andric       }
332*0b57cec5SDimitry Andric       const MachineOperand &getOp() const {
333*0b57cec5SDimitry Andric         return UseMI->getOperand(OpNum);
334*0b57cec5SDimitry Andric       }
335*0b57cec5SDimitry Andric     };
336*0b57cec5SDimitry Andric 
337*0b57cec5SDimitry Andric     struct ExtRoot {
338*0b57cec5SDimitry Andric       union {
339*0b57cec5SDimitry Andric         const ConstantFP *CFP;  // MO_FPImmediate
340*0b57cec5SDimitry Andric         const char *SymbolName; // MO_ExternalSymbol
341*0b57cec5SDimitry Andric         const GlobalValue *GV;  // MO_GlobalAddress
342*0b57cec5SDimitry Andric         const BlockAddress *BA; // MO_BlockAddress
343*0b57cec5SDimitry Andric         int64_t ImmVal;         // MO_Immediate, MO_TargetIndex,
344*0b57cec5SDimitry Andric                                 // and MO_ConstantPoolIndex
345*0b57cec5SDimitry Andric       } V;
346*0b57cec5SDimitry Andric       unsigned Kind;            // Same as in MachineOperand.
347*0b57cec5SDimitry Andric       unsigned char TF;         // TargetFlags.
348*0b57cec5SDimitry Andric 
349*0b57cec5SDimitry Andric       ExtRoot(const MachineOperand &Op);
350*0b57cec5SDimitry Andric       bool operator==(const ExtRoot &ER) const {
351*0b57cec5SDimitry Andric         return Kind == ER.Kind && V.ImmVal == ER.V.ImmVal;
352*0b57cec5SDimitry Andric       }
353*0b57cec5SDimitry Andric       bool operator!=(const ExtRoot &ER) const {
354*0b57cec5SDimitry Andric         return !operator==(ER);
355*0b57cec5SDimitry Andric       }
356*0b57cec5SDimitry Andric       bool operator<(const ExtRoot &ER) const;
357*0b57cec5SDimitry Andric     };
358*0b57cec5SDimitry Andric 
359*0b57cec5SDimitry Andric     struct ExtValue : public ExtRoot {
360*0b57cec5SDimitry Andric       int32_t Offset;
361*0b57cec5SDimitry Andric 
362*0b57cec5SDimitry Andric       ExtValue(const MachineOperand &Op);
363*0b57cec5SDimitry Andric       ExtValue(const ExtDesc &ED) : ExtValue(ED.getOp()) {}
364*0b57cec5SDimitry Andric       ExtValue(const ExtRoot &ER, int32_t Off) : ExtRoot(ER), Offset(Off) {}
365*0b57cec5SDimitry Andric       bool operator<(const ExtValue &EV) const;
366*0b57cec5SDimitry Andric       bool operator==(const ExtValue &EV) const {
367*0b57cec5SDimitry Andric         return ExtRoot(*this) == ExtRoot(EV) && Offset == EV.Offset;
368*0b57cec5SDimitry Andric       }
369*0b57cec5SDimitry Andric       bool operator!=(const ExtValue &EV) const {
370*0b57cec5SDimitry Andric         return !operator==(EV);
371*0b57cec5SDimitry Andric       }
372*0b57cec5SDimitry Andric       explicit operator MachineOperand() const;
373*0b57cec5SDimitry Andric     };
374*0b57cec5SDimitry Andric 
375*0b57cec5SDimitry Andric     using IndexList = SetVector<unsigned>;
376*0b57cec5SDimitry Andric     using ExtenderInit = std::pair<ExtValue, ExtExpr>;
377*0b57cec5SDimitry Andric     using AssignmentMap = std::map<ExtenderInit, IndexList>;
378*0b57cec5SDimitry Andric     using LocDefList = std::vector<std::pair<Loc, IndexList>>;
379*0b57cec5SDimitry Andric 
380*0b57cec5SDimitry Andric     const HexagonInstrInfo *HII = nullptr;
381*0b57cec5SDimitry Andric     const HexagonRegisterInfo *HRI = nullptr;
382*0b57cec5SDimitry Andric     MachineDominatorTree *MDT = nullptr;
383*0b57cec5SDimitry Andric     MachineRegisterInfo *MRI = nullptr;
384*0b57cec5SDimitry Andric     std::vector<ExtDesc> Extenders;
385*0b57cec5SDimitry Andric     std::vector<unsigned> NewRegs;
386*0b57cec5SDimitry Andric 
387*0b57cec5SDimitry Andric     bool isStoreImmediate(unsigned Opc) const;
388*0b57cec5SDimitry Andric     bool isRegOffOpcode(unsigned ExtOpc) const ;
389*0b57cec5SDimitry Andric     unsigned getRegOffOpcode(unsigned ExtOpc) const;
390*0b57cec5SDimitry Andric     unsigned getDirectRegReplacement(unsigned ExtOpc) const;
391*0b57cec5SDimitry Andric     OffsetRange getOffsetRange(Register R, const MachineInstr &MI) const;
392*0b57cec5SDimitry Andric     OffsetRange getOffsetRange(const ExtDesc &ED) const;
393*0b57cec5SDimitry Andric     OffsetRange getOffsetRange(Register Rd) const;
394*0b57cec5SDimitry Andric 
395*0b57cec5SDimitry Andric     void recordExtender(MachineInstr &MI, unsigned OpNum);
396*0b57cec5SDimitry Andric     void collectInstr(MachineInstr &MI);
397*0b57cec5SDimitry Andric     void collect(MachineFunction &MF);
398*0b57cec5SDimitry Andric     void assignInits(const ExtRoot &ER, unsigned Begin, unsigned End,
399*0b57cec5SDimitry Andric                      AssignmentMap &IMap);
400*0b57cec5SDimitry Andric     void calculatePlacement(const ExtenderInit &ExtI, const IndexList &Refs,
401*0b57cec5SDimitry Andric                             LocDefList &Defs);
402*0b57cec5SDimitry Andric     Register insertInitializer(Loc DefL, const ExtenderInit &ExtI);
403*0b57cec5SDimitry Andric     bool replaceInstrExact(const ExtDesc &ED, Register ExtR);
404*0b57cec5SDimitry Andric     bool replaceInstrExpr(const ExtDesc &ED, const ExtenderInit &ExtI,
405*0b57cec5SDimitry Andric                           Register ExtR, int32_t &Diff);
406*0b57cec5SDimitry Andric     bool replaceInstr(unsigned Idx, Register ExtR, const ExtenderInit &ExtI);
407*0b57cec5SDimitry Andric     bool replaceExtenders(const AssignmentMap &IMap);
408*0b57cec5SDimitry Andric 
409*0b57cec5SDimitry Andric     unsigned getOperandIndex(const MachineInstr &MI,
410*0b57cec5SDimitry Andric                              const MachineOperand &Op) const;
411*0b57cec5SDimitry Andric     const MachineOperand &getPredicateOp(const MachineInstr &MI) const;
412*0b57cec5SDimitry Andric     const MachineOperand &getLoadResultOp(const MachineInstr &MI) const;
413*0b57cec5SDimitry Andric     const MachineOperand &getStoredValueOp(const MachineInstr &MI) const;
414*0b57cec5SDimitry Andric 
415*0b57cec5SDimitry Andric     friend struct PrintRegister;
416*0b57cec5SDimitry Andric     friend struct PrintExpr;
417*0b57cec5SDimitry Andric     friend struct PrintInit;
418*0b57cec5SDimitry Andric     friend struct PrintIMap;
419*0b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS,
420*0b57cec5SDimitry Andric                                     const struct PrintRegister &P);
421*0b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS, const struct PrintExpr &P);
422*0b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS, const struct PrintInit &P);
423*0b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS, const ExtDesc &ED);
424*0b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS, const ExtRoot &ER);
425*0b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS, const ExtValue &EV);
426*0b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS, const OffsetRange &OR);
427*0b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS, const struct PrintIMap &P);
428*0b57cec5SDimitry Andric   };
429*0b57cec5SDimitry Andric 
430*0b57cec5SDimitry Andric   using HCE = HexagonConstExtenders;
431*0b57cec5SDimitry Andric 
432*0b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
433*0b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const OffsetRange &OR) {
434*0b57cec5SDimitry Andric     if (OR.Min > OR.Max)
435*0b57cec5SDimitry Andric       OS << '!';
436*0b57cec5SDimitry Andric     OS << '[' << OR.Min << ',' << OR.Max << "]a" << unsigned(OR.Align)
437*0b57cec5SDimitry Andric        << '+' << unsigned(OR.Offset);
438*0b57cec5SDimitry Andric     return OS;
439*0b57cec5SDimitry Andric   }
440*0b57cec5SDimitry Andric 
441*0b57cec5SDimitry Andric   struct PrintRegister {
442*0b57cec5SDimitry Andric     PrintRegister(HCE::Register R, const HexagonRegisterInfo &I)
443*0b57cec5SDimitry Andric       : Rs(R), HRI(I) {}
444*0b57cec5SDimitry Andric     HCE::Register Rs;
445*0b57cec5SDimitry Andric     const HexagonRegisterInfo &HRI;
446*0b57cec5SDimitry Andric   };
447*0b57cec5SDimitry Andric 
448*0b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
449*0b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const PrintRegister &P) {
450*0b57cec5SDimitry Andric     if (P.Rs.Reg != 0)
451*0b57cec5SDimitry Andric       OS << printReg(P.Rs.Reg, &P.HRI, P.Rs.Sub);
452*0b57cec5SDimitry Andric     else
453*0b57cec5SDimitry Andric       OS << "noreg";
454*0b57cec5SDimitry Andric     return OS;
455*0b57cec5SDimitry Andric   }
456*0b57cec5SDimitry Andric 
457*0b57cec5SDimitry Andric   struct PrintExpr {
458*0b57cec5SDimitry Andric     PrintExpr(const HCE::ExtExpr &E, const HexagonRegisterInfo &I)
459*0b57cec5SDimitry Andric       : Ex(E), HRI(I) {}
460*0b57cec5SDimitry Andric     const HCE::ExtExpr &Ex;
461*0b57cec5SDimitry Andric     const HexagonRegisterInfo &HRI;
462*0b57cec5SDimitry Andric   };
463*0b57cec5SDimitry Andric 
464*0b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
465*0b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const PrintExpr &P) {
466*0b57cec5SDimitry Andric     OS << "## " << (P.Ex.Neg ? "- " : "+ ");
467*0b57cec5SDimitry Andric     if (P.Ex.Rs.Reg != 0)
468*0b57cec5SDimitry Andric       OS << printReg(P.Ex.Rs.Reg, &P.HRI, P.Ex.Rs.Sub);
469*0b57cec5SDimitry Andric     else
470*0b57cec5SDimitry Andric       OS << "__";
471*0b57cec5SDimitry Andric     OS << " << " << P.Ex.S;
472*0b57cec5SDimitry Andric     return OS;
473*0b57cec5SDimitry Andric   }
474*0b57cec5SDimitry Andric 
475*0b57cec5SDimitry Andric   struct PrintInit {
476*0b57cec5SDimitry Andric     PrintInit(const HCE::ExtenderInit &EI, const HexagonRegisterInfo &I)
477*0b57cec5SDimitry Andric       : ExtI(EI), HRI(I) {}
478*0b57cec5SDimitry Andric     const HCE::ExtenderInit &ExtI;
479*0b57cec5SDimitry Andric     const HexagonRegisterInfo &HRI;
480*0b57cec5SDimitry Andric   };
481*0b57cec5SDimitry Andric 
482*0b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
483*0b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const PrintInit &P) {
484*0b57cec5SDimitry Andric     OS << '[' << P.ExtI.first << ", "
485*0b57cec5SDimitry Andric        << PrintExpr(P.ExtI.second, P.HRI) << ']';
486*0b57cec5SDimitry Andric     return OS;
487*0b57cec5SDimitry Andric   }
488*0b57cec5SDimitry Andric 
489*0b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
490*0b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const HCE::ExtDesc &ED) {
491*0b57cec5SDimitry Andric     assert(ED.OpNum != -1u);
492*0b57cec5SDimitry Andric     const MachineBasicBlock &MBB = *ED.getOp().getParent()->getParent();
493*0b57cec5SDimitry Andric     const MachineFunction &MF = *MBB.getParent();
494*0b57cec5SDimitry Andric     const auto &HRI = *MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
495*0b57cec5SDimitry Andric     OS << "bb#" << MBB.getNumber() << ": ";
496*0b57cec5SDimitry Andric     if (ED.Rd.Reg != 0)
497*0b57cec5SDimitry Andric       OS << printReg(ED.Rd.Reg, &HRI, ED.Rd.Sub);
498*0b57cec5SDimitry Andric     else
499*0b57cec5SDimitry Andric       OS << "__";
500*0b57cec5SDimitry Andric     OS << " = " << PrintExpr(ED.Expr, HRI);
501*0b57cec5SDimitry Andric     if (ED.IsDef)
502*0b57cec5SDimitry Andric       OS << ", def";
503*0b57cec5SDimitry Andric     return OS;
504*0b57cec5SDimitry Andric   }
505*0b57cec5SDimitry Andric 
506*0b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
507*0b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const HCE::ExtRoot &ER) {
508*0b57cec5SDimitry Andric     switch (ER.Kind) {
509*0b57cec5SDimitry Andric       case MachineOperand::MO_Immediate:
510*0b57cec5SDimitry Andric         OS << "imm:" << ER.V.ImmVal;
511*0b57cec5SDimitry Andric         break;
512*0b57cec5SDimitry Andric       case MachineOperand::MO_FPImmediate:
513*0b57cec5SDimitry Andric         OS << "fpi:" << *ER.V.CFP;
514*0b57cec5SDimitry Andric         break;
515*0b57cec5SDimitry Andric       case MachineOperand::MO_ExternalSymbol:
516*0b57cec5SDimitry Andric         OS << "sym:" << *ER.V.SymbolName;
517*0b57cec5SDimitry Andric         break;
518*0b57cec5SDimitry Andric       case MachineOperand::MO_GlobalAddress:
519*0b57cec5SDimitry Andric         OS << "gad:" << ER.V.GV->getName();
520*0b57cec5SDimitry Andric         break;
521*0b57cec5SDimitry Andric       case MachineOperand::MO_BlockAddress:
522*0b57cec5SDimitry Andric         OS << "blk:" << *ER.V.BA;
523*0b57cec5SDimitry Andric         break;
524*0b57cec5SDimitry Andric       case MachineOperand::MO_TargetIndex:
525*0b57cec5SDimitry Andric         OS << "tgi:" << ER.V.ImmVal;
526*0b57cec5SDimitry Andric         break;
527*0b57cec5SDimitry Andric       case MachineOperand::MO_ConstantPoolIndex:
528*0b57cec5SDimitry Andric         OS << "cpi:" << ER.V.ImmVal;
529*0b57cec5SDimitry Andric         break;
530*0b57cec5SDimitry Andric       case MachineOperand::MO_JumpTableIndex:
531*0b57cec5SDimitry Andric         OS << "jti:" << ER.V.ImmVal;
532*0b57cec5SDimitry Andric         break;
533*0b57cec5SDimitry Andric       default:
534*0b57cec5SDimitry Andric         OS << "???:" << ER.V.ImmVal;
535*0b57cec5SDimitry Andric         break;
536*0b57cec5SDimitry Andric     }
537*0b57cec5SDimitry Andric     return OS;
538*0b57cec5SDimitry Andric   }
539*0b57cec5SDimitry Andric 
540*0b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
541*0b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const HCE::ExtValue &EV) {
542*0b57cec5SDimitry Andric     OS << HCE::ExtRoot(EV) << "  off:" << EV.Offset;
543*0b57cec5SDimitry Andric     return OS;
544*0b57cec5SDimitry Andric   }
545*0b57cec5SDimitry Andric 
546*0b57cec5SDimitry Andric   struct PrintIMap {
547*0b57cec5SDimitry Andric     PrintIMap(const HCE::AssignmentMap &M, const HexagonRegisterInfo &I)
548*0b57cec5SDimitry Andric       : IMap(M), HRI(I) {}
549*0b57cec5SDimitry Andric     const HCE::AssignmentMap &IMap;
550*0b57cec5SDimitry Andric     const HexagonRegisterInfo &HRI;
551*0b57cec5SDimitry Andric   };
552*0b57cec5SDimitry Andric 
553*0b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
554*0b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const PrintIMap &P) {
555*0b57cec5SDimitry Andric     OS << "{\n";
556*0b57cec5SDimitry Andric     for (const std::pair<HCE::ExtenderInit,HCE::IndexList> &Q : P.IMap) {
557*0b57cec5SDimitry Andric       OS << "  " << PrintInit(Q.first, P.HRI) << " -> {";
558*0b57cec5SDimitry Andric       for (unsigned I : Q.second)
559*0b57cec5SDimitry Andric         OS << ' ' << I;
560*0b57cec5SDimitry Andric       OS << " }\n";
561*0b57cec5SDimitry Andric     }
562*0b57cec5SDimitry Andric     OS << "}\n";
563*0b57cec5SDimitry Andric     return OS;
564*0b57cec5SDimitry Andric   }
565*0b57cec5SDimitry Andric }
566*0b57cec5SDimitry Andric 
567*0b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(HexagonConstExtenders, "hexagon-cext-opt",
568*0b57cec5SDimitry Andric       "Hexagon constant-extender optimization", false, false)
569*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
570*0b57cec5SDimitry Andric INITIALIZE_PASS_END(HexagonConstExtenders, "hexagon-cext-opt",
571*0b57cec5SDimitry Andric       "Hexagon constant-extender optimization", false, false)
572*0b57cec5SDimitry Andric 
573*0b57cec5SDimitry Andric static unsigned ReplaceCounter = 0;
574*0b57cec5SDimitry Andric 
575*0b57cec5SDimitry Andric char HCE::ID = 0;
576*0b57cec5SDimitry Andric 
577*0b57cec5SDimitry Andric #ifndef NDEBUG
578*0b57cec5SDimitry Andric LLVM_DUMP_METHOD void RangeTree::dump() const {
579*0b57cec5SDimitry Andric   dbgs() << "Root: " << Root << '\n';
580*0b57cec5SDimitry Andric   if (Root)
581*0b57cec5SDimitry Andric     dump(Root);
582*0b57cec5SDimitry Andric }
583*0b57cec5SDimitry Andric 
584*0b57cec5SDimitry Andric LLVM_DUMP_METHOD void RangeTree::dump(const Node *N) const {
585*0b57cec5SDimitry Andric   dbgs() << "Node: " << N << '\n';
586*0b57cec5SDimitry Andric   dbgs() << "  Height: " << N->Height << '\n';
587*0b57cec5SDimitry Andric   dbgs() << "  Count: " << N->Count << '\n';
588*0b57cec5SDimitry Andric   dbgs() << "  MaxEnd: " << N->MaxEnd << '\n';
589*0b57cec5SDimitry Andric   dbgs() << "  Range: " << N->Range << '\n';
590*0b57cec5SDimitry Andric   dbgs() << "  Left: " << N->Left << '\n';
591*0b57cec5SDimitry Andric   dbgs() << "  Right: " << N->Right << "\n\n";
592*0b57cec5SDimitry Andric 
593*0b57cec5SDimitry Andric   if (N->Left)
594*0b57cec5SDimitry Andric     dump(N->Left);
595*0b57cec5SDimitry Andric   if (N->Right)
596*0b57cec5SDimitry Andric     dump(N->Right);
597*0b57cec5SDimitry Andric }
598*0b57cec5SDimitry Andric #endif
599*0b57cec5SDimitry Andric 
600*0b57cec5SDimitry Andric void RangeTree::order(Node *N, SmallVectorImpl<Node*> &Seq) const {
601*0b57cec5SDimitry Andric   if (N == nullptr)
602*0b57cec5SDimitry Andric     return;
603*0b57cec5SDimitry Andric   order(N->Left, Seq);
604*0b57cec5SDimitry Andric   Seq.push_back(N);
605*0b57cec5SDimitry Andric   order(N->Right, Seq);
606*0b57cec5SDimitry Andric }
607*0b57cec5SDimitry Andric 
608*0b57cec5SDimitry Andric void RangeTree::nodesWith(Node *N, int32_t P, bool CheckA,
609*0b57cec5SDimitry Andric       SmallVectorImpl<Node*> &Seq) const {
610*0b57cec5SDimitry Andric   if (N == nullptr || N->MaxEnd < P)
611*0b57cec5SDimitry Andric     return;
612*0b57cec5SDimitry Andric   nodesWith(N->Left, P, CheckA, Seq);
613*0b57cec5SDimitry Andric   if (N->Range.Min <= P) {
614*0b57cec5SDimitry Andric     if ((CheckA && N->Range.contains(P)) || (!CheckA && P <= N->Range.Max))
615*0b57cec5SDimitry Andric       Seq.push_back(N);
616*0b57cec5SDimitry Andric     nodesWith(N->Right, P, CheckA, Seq);
617*0b57cec5SDimitry Andric   }
618*0b57cec5SDimitry Andric }
619*0b57cec5SDimitry Andric 
620*0b57cec5SDimitry Andric RangeTree::Node *RangeTree::add(Node *N, const OffsetRange &R) {
621*0b57cec5SDimitry Andric   if (N == nullptr)
622*0b57cec5SDimitry Andric     return new Node(R);
623*0b57cec5SDimitry Andric 
624*0b57cec5SDimitry Andric   if (N->Range == R) {
625*0b57cec5SDimitry Andric     N->Count++;
626*0b57cec5SDimitry Andric     return N;
627*0b57cec5SDimitry Andric   }
628*0b57cec5SDimitry Andric 
629*0b57cec5SDimitry Andric   if (R < N->Range)
630*0b57cec5SDimitry Andric     N->Left = add(N->Left, R);
631*0b57cec5SDimitry Andric   else
632*0b57cec5SDimitry Andric     N->Right = add(N->Right, R);
633*0b57cec5SDimitry Andric   return rebalance(update(N));
634*0b57cec5SDimitry Andric }
635*0b57cec5SDimitry Andric 
636*0b57cec5SDimitry Andric RangeTree::Node *RangeTree::remove(Node *N, const Node *D) {
637*0b57cec5SDimitry Andric   assert(N != nullptr);
638*0b57cec5SDimitry Andric 
639*0b57cec5SDimitry Andric   if (N != D) {
640*0b57cec5SDimitry Andric     assert(N->Range != D->Range && "N and D should not be equal");
641*0b57cec5SDimitry Andric     if (D->Range < N->Range)
642*0b57cec5SDimitry Andric       N->Left = remove(N->Left, D);
643*0b57cec5SDimitry Andric     else
644*0b57cec5SDimitry Andric       N->Right = remove(N->Right, D);
645*0b57cec5SDimitry Andric     return rebalance(update(N));
646*0b57cec5SDimitry Andric   }
647*0b57cec5SDimitry Andric 
648*0b57cec5SDimitry Andric   // We got to the node we need to remove. If any of its children are
649*0b57cec5SDimitry Andric   // missing, simply replace it with the other child.
650*0b57cec5SDimitry Andric   if (N->Left == nullptr || N->Right == nullptr)
651*0b57cec5SDimitry Andric     return (N->Left == nullptr) ? N->Right : N->Left;
652*0b57cec5SDimitry Andric 
653*0b57cec5SDimitry Andric   // Find the rightmost child of N->Left, remove it and plug it in place
654*0b57cec5SDimitry Andric   // of N.
655*0b57cec5SDimitry Andric   Node *M = N->Left;
656*0b57cec5SDimitry Andric   while (M->Right)
657*0b57cec5SDimitry Andric     M = M->Right;
658*0b57cec5SDimitry Andric   M->Left = remove(N->Left, M);
659*0b57cec5SDimitry Andric   M->Right = N->Right;
660*0b57cec5SDimitry Andric   return rebalance(update(M));
661*0b57cec5SDimitry Andric }
662*0b57cec5SDimitry Andric 
663*0b57cec5SDimitry Andric RangeTree::Node *RangeTree::rotateLeft(Node *Lower, Node *Higher) {
664*0b57cec5SDimitry Andric   assert(Higher->Right == Lower);
665*0b57cec5SDimitry Andric   // The Lower node is on the right from Higher. Make sure that Lower's
666*0b57cec5SDimitry Andric   // balance is greater to the right. Otherwise the rotation will create
667*0b57cec5SDimitry Andric   // an unbalanced tree again.
668*0b57cec5SDimitry Andric   if (height(Lower->Left) > height(Lower->Right))
669*0b57cec5SDimitry Andric     Lower = rotateRight(Lower->Left, Lower);
670*0b57cec5SDimitry Andric   assert(height(Lower->Left) <= height(Lower->Right));
671*0b57cec5SDimitry Andric   Higher->Right = Lower->Left;
672*0b57cec5SDimitry Andric   update(Higher);
673*0b57cec5SDimitry Andric   Lower->Left = Higher;
674*0b57cec5SDimitry Andric   update(Lower);
675*0b57cec5SDimitry Andric   return Lower;
676*0b57cec5SDimitry Andric }
677*0b57cec5SDimitry Andric 
678*0b57cec5SDimitry Andric RangeTree::Node *RangeTree::rotateRight(Node *Lower, Node *Higher) {
679*0b57cec5SDimitry Andric   assert(Higher->Left == Lower);
680*0b57cec5SDimitry Andric   // The Lower node is on the left from Higher. Make sure that Lower's
681*0b57cec5SDimitry Andric   // balance is greater to the left. Otherwise the rotation will create
682*0b57cec5SDimitry Andric   // an unbalanced tree again.
683*0b57cec5SDimitry Andric   if (height(Lower->Left) < height(Lower->Right))
684*0b57cec5SDimitry Andric     Lower = rotateLeft(Lower->Right, Lower);
685*0b57cec5SDimitry Andric   assert(height(Lower->Left) >= height(Lower->Right));
686*0b57cec5SDimitry Andric   Higher->Left = Lower->Right;
687*0b57cec5SDimitry Andric   update(Higher);
688*0b57cec5SDimitry Andric   Lower->Right = Higher;
689*0b57cec5SDimitry Andric   update(Lower);
690*0b57cec5SDimitry Andric   return Lower;
691*0b57cec5SDimitry Andric }
692*0b57cec5SDimitry Andric 
693*0b57cec5SDimitry Andric 
694*0b57cec5SDimitry Andric HCE::ExtRoot::ExtRoot(const MachineOperand &Op) {
695*0b57cec5SDimitry Andric   // Always store ImmVal, since it's the field used for comparisons.
696*0b57cec5SDimitry Andric   V.ImmVal = 0;
697*0b57cec5SDimitry Andric   if (Op.isImm())
698*0b57cec5SDimitry Andric     ; // Keep 0. Do not use Op.getImm() for value here (treat 0 as the root).
699*0b57cec5SDimitry Andric   else if (Op.isFPImm())
700*0b57cec5SDimitry Andric     V.CFP = Op.getFPImm();
701*0b57cec5SDimitry Andric   else if (Op.isSymbol())
702*0b57cec5SDimitry Andric     V.SymbolName = Op.getSymbolName();
703*0b57cec5SDimitry Andric   else if (Op.isGlobal())
704*0b57cec5SDimitry Andric     V.GV = Op.getGlobal();
705*0b57cec5SDimitry Andric   else if (Op.isBlockAddress())
706*0b57cec5SDimitry Andric     V.BA = Op.getBlockAddress();
707*0b57cec5SDimitry Andric   else if (Op.isCPI() || Op.isTargetIndex() || Op.isJTI())
708*0b57cec5SDimitry Andric     V.ImmVal = Op.getIndex();
709*0b57cec5SDimitry Andric   else
710*0b57cec5SDimitry Andric     llvm_unreachable("Unexpected operand type");
711*0b57cec5SDimitry Andric 
712*0b57cec5SDimitry Andric   Kind = Op.getType();
713*0b57cec5SDimitry Andric   TF = Op.getTargetFlags();
714*0b57cec5SDimitry Andric }
715*0b57cec5SDimitry Andric 
716*0b57cec5SDimitry Andric bool HCE::ExtRoot::operator< (const HCE::ExtRoot &ER) const {
717*0b57cec5SDimitry Andric   if (Kind != ER.Kind)
718*0b57cec5SDimitry Andric     return Kind < ER.Kind;
719*0b57cec5SDimitry Andric   switch (Kind) {
720*0b57cec5SDimitry Andric     case MachineOperand::MO_Immediate:
721*0b57cec5SDimitry Andric     case MachineOperand::MO_TargetIndex:
722*0b57cec5SDimitry Andric     case MachineOperand::MO_ConstantPoolIndex:
723*0b57cec5SDimitry Andric     case MachineOperand::MO_JumpTableIndex:
724*0b57cec5SDimitry Andric       return V.ImmVal < ER.V.ImmVal;
725*0b57cec5SDimitry Andric     case MachineOperand::MO_FPImmediate: {
726*0b57cec5SDimitry Andric       const APFloat &ThisF = V.CFP->getValueAPF();
727*0b57cec5SDimitry Andric       const APFloat &OtherF = ER.V.CFP->getValueAPF();
728*0b57cec5SDimitry Andric       return ThisF.bitcastToAPInt().ult(OtherF.bitcastToAPInt());
729*0b57cec5SDimitry Andric     }
730*0b57cec5SDimitry Andric     case MachineOperand::MO_ExternalSymbol:
731*0b57cec5SDimitry Andric       return StringRef(V.SymbolName) < StringRef(ER.V.SymbolName);
732*0b57cec5SDimitry Andric     case MachineOperand::MO_GlobalAddress:
733*0b57cec5SDimitry Andric       // Do not use GUIDs, since they depend on the source path. Moving the
734*0b57cec5SDimitry Andric       // source file to a different directory could cause different GUID
735*0b57cec5SDimitry Andric       // values for a pair of given symbols. These symbols could then compare
736*0b57cec5SDimitry Andric       // "less" in one directory, but "greater" in another.
737*0b57cec5SDimitry Andric       assert(!V.GV->getName().empty() && !ER.V.GV->getName().empty());
738*0b57cec5SDimitry Andric       return V.GV->getName() < ER.V.GV->getName();
739*0b57cec5SDimitry Andric     case MachineOperand::MO_BlockAddress: {
740*0b57cec5SDimitry Andric       const BasicBlock *ThisB = V.BA->getBasicBlock();
741*0b57cec5SDimitry Andric       const BasicBlock *OtherB = ER.V.BA->getBasicBlock();
742*0b57cec5SDimitry Andric       assert(ThisB->getParent() == OtherB->getParent());
743*0b57cec5SDimitry Andric       const Function &F = *ThisB->getParent();
744*0b57cec5SDimitry Andric       return std::distance(F.begin(), ThisB->getIterator()) <
745*0b57cec5SDimitry Andric              std::distance(F.begin(), OtherB->getIterator());
746*0b57cec5SDimitry Andric     }
747*0b57cec5SDimitry Andric   }
748*0b57cec5SDimitry Andric   return V.ImmVal < ER.V.ImmVal;
749*0b57cec5SDimitry Andric }
750*0b57cec5SDimitry Andric 
751*0b57cec5SDimitry Andric HCE::ExtValue::ExtValue(const MachineOperand &Op) : ExtRoot(Op) {
752*0b57cec5SDimitry Andric   if (Op.isImm())
753*0b57cec5SDimitry Andric     Offset = Op.getImm();
754*0b57cec5SDimitry Andric   else if (Op.isFPImm() || Op.isJTI())
755*0b57cec5SDimitry Andric     Offset = 0;
756*0b57cec5SDimitry Andric   else if (Op.isSymbol() || Op.isGlobal() || Op.isBlockAddress() ||
757*0b57cec5SDimitry Andric            Op.isCPI() || Op.isTargetIndex())
758*0b57cec5SDimitry Andric     Offset = Op.getOffset();
759*0b57cec5SDimitry Andric   else
760*0b57cec5SDimitry Andric     llvm_unreachable("Unexpected operand type");
761*0b57cec5SDimitry Andric }
762*0b57cec5SDimitry Andric 
763*0b57cec5SDimitry Andric bool HCE::ExtValue::operator< (const HCE::ExtValue &EV) const {
764*0b57cec5SDimitry Andric   const ExtRoot &ER = *this;
765*0b57cec5SDimitry Andric   if (!(ER == ExtRoot(EV)))
766*0b57cec5SDimitry Andric     return ER < EV;
767*0b57cec5SDimitry Andric   return Offset < EV.Offset;
768*0b57cec5SDimitry Andric }
769*0b57cec5SDimitry Andric 
770*0b57cec5SDimitry Andric HCE::ExtValue::operator MachineOperand() const {
771*0b57cec5SDimitry Andric   switch (Kind) {
772*0b57cec5SDimitry Andric     case MachineOperand::MO_Immediate:
773*0b57cec5SDimitry Andric       return MachineOperand::CreateImm(V.ImmVal + Offset);
774*0b57cec5SDimitry Andric     case MachineOperand::MO_FPImmediate:
775*0b57cec5SDimitry Andric       assert(Offset == 0);
776*0b57cec5SDimitry Andric       return MachineOperand::CreateFPImm(V.CFP);
777*0b57cec5SDimitry Andric     case MachineOperand::MO_ExternalSymbol:
778*0b57cec5SDimitry Andric       assert(Offset == 0);
779*0b57cec5SDimitry Andric       return MachineOperand::CreateES(V.SymbolName, TF);
780*0b57cec5SDimitry Andric     case MachineOperand::MO_GlobalAddress:
781*0b57cec5SDimitry Andric       return MachineOperand::CreateGA(V.GV, Offset, TF);
782*0b57cec5SDimitry Andric     case MachineOperand::MO_BlockAddress:
783*0b57cec5SDimitry Andric       return MachineOperand::CreateBA(V.BA, Offset, TF);
784*0b57cec5SDimitry Andric     case MachineOperand::MO_TargetIndex:
785*0b57cec5SDimitry Andric       return MachineOperand::CreateTargetIndex(V.ImmVal, Offset, TF);
786*0b57cec5SDimitry Andric     case MachineOperand::MO_ConstantPoolIndex:
787*0b57cec5SDimitry Andric       return MachineOperand::CreateCPI(V.ImmVal, Offset, TF);
788*0b57cec5SDimitry Andric     case MachineOperand::MO_JumpTableIndex:
789*0b57cec5SDimitry Andric       assert(Offset == 0);
790*0b57cec5SDimitry Andric       return MachineOperand::CreateJTI(V.ImmVal, TF);
791*0b57cec5SDimitry Andric     default:
792*0b57cec5SDimitry Andric       llvm_unreachable("Unhandled kind");
793*0b57cec5SDimitry Andric  }
794*0b57cec5SDimitry Andric }
795*0b57cec5SDimitry Andric 
796*0b57cec5SDimitry Andric bool HCE::isStoreImmediate(unsigned Opc) const {
797*0b57cec5SDimitry Andric   switch (Opc) {
798*0b57cec5SDimitry Andric     case Hexagon::S4_storeirbt_io:
799*0b57cec5SDimitry Andric     case Hexagon::S4_storeirbf_io:
800*0b57cec5SDimitry Andric     case Hexagon::S4_storeirht_io:
801*0b57cec5SDimitry Andric     case Hexagon::S4_storeirhf_io:
802*0b57cec5SDimitry Andric     case Hexagon::S4_storeirit_io:
803*0b57cec5SDimitry Andric     case Hexagon::S4_storeirif_io:
804*0b57cec5SDimitry Andric     case Hexagon::S4_storeirb_io:
805*0b57cec5SDimitry Andric     case Hexagon::S4_storeirh_io:
806*0b57cec5SDimitry Andric     case Hexagon::S4_storeiri_io:
807*0b57cec5SDimitry Andric       return true;
808*0b57cec5SDimitry Andric     default:
809*0b57cec5SDimitry Andric       break;
810*0b57cec5SDimitry Andric   }
811*0b57cec5SDimitry Andric   return false;
812*0b57cec5SDimitry Andric }
813*0b57cec5SDimitry Andric 
814*0b57cec5SDimitry Andric bool HCE::isRegOffOpcode(unsigned Opc) const {
815*0b57cec5SDimitry Andric   switch (Opc) {
816*0b57cec5SDimitry Andric     case Hexagon::L2_loadrub_io:
817*0b57cec5SDimitry Andric     case Hexagon::L2_loadrb_io:
818*0b57cec5SDimitry Andric     case Hexagon::L2_loadruh_io:
819*0b57cec5SDimitry Andric     case Hexagon::L2_loadrh_io:
820*0b57cec5SDimitry Andric     case Hexagon::L2_loadri_io:
821*0b57cec5SDimitry Andric     case Hexagon::L2_loadrd_io:
822*0b57cec5SDimitry Andric     case Hexagon::L2_loadbzw2_io:
823*0b57cec5SDimitry Andric     case Hexagon::L2_loadbzw4_io:
824*0b57cec5SDimitry Andric     case Hexagon::L2_loadbsw2_io:
825*0b57cec5SDimitry Andric     case Hexagon::L2_loadbsw4_io:
826*0b57cec5SDimitry Andric     case Hexagon::L2_loadalignh_io:
827*0b57cec5SDimitry Andric     case Hexagon::L2_loadalignb_io:
828*0b57cec5SDimitry Andric     case Hexagon::L2_ploadrubt_io:
829*0b57cec5SDimitry Andric     case Hexagon::L2_ploadrubf_io:
830*0b57cec5SDimitry Andric     case Hexagon::L2_ploadrbt_io:
831*0b57cec5SDimitry Andric     case Hexagon::L2_ploadrbf_io:
832*0b57cec5SDimitry Andric     case Hexagon::L2_ploadruht_io:
833*0b57cec5SDimitry Andric     case Hexagon::L2_ploadruhf_io:
834*0b57cec5SDimitry Andric     case Hexagon::L2_ploadrht_io:
835*0b57cec5SDimitry Andric     case Hexagon::L2_ploadrhf_io:
836*0b57cec5SDimitry Andric     case Hexagon::L2_ploadrit_io:
837*0b57cec5SDimitry Andric     case Hexagon::L2_ploadrif_io:
838*0b57cec5SDimitry Andric     case Hexagon::L2_ploadrdt_io:
839*0b57cec5SDimitry Andric     case Hexagon::L2_ploadrdf_io:
840*0b57cec5SDimitry Andric     case Hexagon::S2_storerb_io:
841*0b57cec5SDimitry Andric     case Hexagon::S2_storerh_io:
842*0b57cec5SDimitry Andric     case Hexagon::S2_storerf_io:
843*0b57cec5SDimitry Andric     case Hexagon::S2_storeri_io:
844*0b57cec5SDimitry Andric     case Hexagon::S2_storerd_io:
845*0b57cec5SDimitry Andric     case Hexagon::S2_pstorerbt_io:
846*0b57cec5SDimitry Andric     case Hexagon::S2_pstorerbf_io:
847*0b57cec5SDimitry Andric     case Hexagon::S2_pstorerht_io:
848*0b57cec5SDimitry Andric     case Hexagon::S2_pstorerhf_io:
849*0b57cec5SDimitry Andric     case Hexagon::S2_pstorerft_io:
850*0b57cec5SDimitry Andric     case Hexagon::S2_pstorerff_io:
851*0b57cec5SDimitry Andric     case Hexagon::S2_pstorerit_io:
852*0b57cec5SDimitry Andric     case Hexagon::S2_pstorerif_io:
853*0b57cec5SDimitry Andric     case Hexagon::S2_pstorerdt_io:
854*0b57cec5SDimitry Andric     case Hexagon::S2_pstorerdf_io:
855*0b57cec5SDimitry Andric     case Hexagon::A2_addi:
856*0b57cec5SDimitry Andric       return true;
857*0b57cec5SDimitry Andric     default:
858*0b57cec5SDimitry Andric       break;
859*0b57cec5SDimitry Andric   }
860*0b57cec5SDimitry Andric   return false;
861*0b57cec5SDimitry Andric }
862*0b57cec5SDimitry Andric 
863*0b57cec5SDimitry Andric unsigned HCE::getRegOffOpcode(unsigned ExtOpc) const {
864*0b57cec5SDimitry Andric   // If there exists an instruction that takes a register and offset,
865*0b57cec5SDimitry Andric   // that corresponds to the ExtOpc, return it, otherwise return 0.
866*0b57cec5SDimitry Andric   using namespace Hexagon;
867*0b57cec5SDimitry Andric   switch (ExtOpc) {
868*0b57cec5SDimitry Andric     case A2_tfrsi:    return A2_addi;
869*0b57cec5SDimitry Andric     default:
870*0b57cec5SDimitry Andric       break;
871*0b57cec5SDimitry Andric   }
872*0b57cec5SDimitry Andric   const MCInstrDesc &D = HII->get(ExtOpc);
873*0b57cec5SDimitry Andric   if (D.mayLoad() || D.mayStore()) {
874*0b57cec5SDimitry Andric     uint64_t F = D.TSFlags;
875*0b57cec5SDimitry Andric     unsigned AM = (F >> HexagonII::AddrModePos) & HexagonII::AddrModeMask;
876*0b57cec5SDimitry Andric     switch (AM) {
877*0b57cec5SDimitry Andric       case HexagonII::Absolute:
878*0b57cec5SDimitry Andric       case HexagonII::AbsoluteSet:
879*0b57cec5SDimitry Andric       case HexagonII::BaseLongOffset:
880*0b57cec5SDimitry Andric         switch (ExtOpc) {
881*0b57cec5SDimitry Andric           case PS_loadrubabs:
882*0b57cec5SDimitry Andric           case L4_loadrub_ap:
883*0b57cec5SDimitry Andric           case L4_loadrub_ur:     return L2_loadrub_io;
884*0b57cec5SDimitry Andric           case PS_loadrbabs:
885*0b57cec5SDimitry Andric           case L4_loadrb_ap:
886*0b57cec5SDimitry Andric           case L4_loadrb_ur:      return L2_loadrb_io;
887*0b57cec5SDimitry Andric           case PS_loadruhabs:
888*0b57cec5SDimitry Andric           case L4_loadruh_ap:
889*0b57cec5SDimitry Andric           case L4_loadruh_ur:     return L2_loadruh_io;
890*0b57cec5SDimitry Andric           case PS_loadrhabs:
891*0b57cec5SDimitry Andric           case L4_loadrh_ap:
892*0b57cec5SDimitry Andric           case L4_loadrh_ur:      return L2_loadrh_io;
893*0b57cec5SDimitry Andric           case PS_loadriabs:
894*0b57cec5SDimitry Andric           case L4_loadri_ap:
895*0b57cec5SDimitry Andric           case L4_loadri_ur:      return L2_loadri_io;
896*0b57cec5SDimitry Andric           case PS_loadrdabs:
897*0b57cec5SDimitry Andric           case L4_loadrd_ap:
898*0b57cec5SDimitry Andric           case L4_loadrd_ur:      return L2_loadrd_io;
899*0b57cec5SDimitry Andric           case L4_loadbzw2_ap:
900*0b57cec5SDimitry Andric           case L4_loadbzw2_ur:    return L2_loadbzw2_io;
901*0b57cec5SDimitry Andric           case L4_loadbzw4_ap:
902*0b57cec5SDimitry Andric           case L4_loadbzw4_ur:    return L2_loadbzw4_io;
903*0b57cec5SDimitry Andric           case L4_loadbsw2_ap:
904*0b57cec5SDimitry Andric           case L4_loadbsw2_ur:    return L2_loadbsw2_io;
905*0b57cec5SDimitry Andric           case L4_loadbsw4_ap:
906*0b57cec5SDimitry Andric           case L4_loadbsw4_ur:    return L2_loadbsw4_io;
907*0b57cec5SDimitry Andric           case L4_loadalignh_ap:
908*0b57cec5SDimitry Andric           case L4_loadalignh_ur:  return L2_loadalignh_io;
909*0b57cec5SDimitry Andric           case L4_loadalignb_ap:
910*0b57cec5SDimitry Andric           case L4_loadalignb_ur:  return L2_loadalignb_io;
911*0b57cec5SDimitry Andric           case L4_ploadrubt_abs:  return L2_ploadrubt_io;
912*0b57cec5SDimitry Andric           case L4_ploadrubf_abs:  return L2_ploadrubf_io;
913*0b57cec5SDimitry Andric           case L4_ploadrbt_abs:   return L2_ploadrbt_io;
914*0b57cec5SDimitry Andric           case L4_ploadrbf_abs:   return L2_ploadrbf_io;
915*0b57cec5SDimitry Andric           case L4_ploadruht_abs:  return L2_ploadruht_io;
916*0b57cec5SDimitry Andric           case L4_ploadruhf_abs:  return L2_ploadruhf_io;
917*0b57cec5SDimitry Andric           case L4_ploadrht_abs:   return L2_ploadrht_io;
918*0b57cec5SDimitry Andric           case L4_ploadrhf_abs:   return L2_ploadrhf_io;
919*0b57cec5SDimitry Andric           case L4_ploadrit_abs:   return L2_ploadrit_io;
920*0b57cec5SDimitry Andric           case L4_ploadrif_abs:   return L2_ploadrif_io;
921*0b57cec5SDimitry Andric           case L4_ploadrdt_abs:   return L2_ploadrdt_io;
922*0b57cec5SDimitry Andric           case L4_ploadrdf_abs:   return L2_ploadrdf_io;
923*0b57cec5SDimitry Andric           case PS_storerbabs:
924*0b57cec5SDimitry Andric           case S4_storerb_ap:
925*0b57cec5SDimitry Andric           case S4_storerb_ur:     return S2_storerb_io;
926*0b57cec5SDimitry Andric           case PS_storerhabs:
927*0b57cec5SDimitry Andric           case S4_storerh_ap:
928*0b57cec5SDimitry Andric           case S4_storerh_ur:     return S2_storerh_io;
929*0b57cec5SDimitry Andric           case PS_storerfabs:
930*0b57cec5SDimitry Andric           case S4_storerf_ap:
931*0b57cec5SDimitry Andric           case S4_storerf_ur:     return S2_storerf_io;
932*0b57cec5SDimitry Andric           case PS_storeriabs:
933*0b57cec5SDimitry Andric           case S4_storeri_ap:
934*0b57cec5SDimitry Andric           case S4_storeri_ur:     return S2_storeri_io;
935*0b57cec5SDimitry Andric           case PS_storerdabs:
936*0b57cec5SDimitry Andric           case S4_storerd_ap:
937*0b57cec5SDimitry Andric           case S4_storerd_ur:     return S2_storerd_io;
938*0b57cec5SDimitry Andric           case S4_pstorerbt_abs:  return S2_pstorerbt_io;
939*0b57cec5SDimitry Andric           case S4_pstorerbf_abs:  return S2_pstorerbf_io;
940*0b57cec5SDimitry Andric           case S4_pstorerht_abs:  return S2_pstorerht_io;
941*0b57cec5SDimitry Andric           case S4_pstorerhf_abs:  return S2_pstorerhf_io;
942*0b57cec5SDimitry Andric           case S4_pstorerft_abs:  return S2_pstorerft_io;
943*0b57cec5SDimitry Andric           case S4_pstorerff_abs:  return S2_pstorerff_io;
944*0b57cec5SDimitry Andric           case S4_pstorerit_abs:  return S2_pstorerit_io;
945*0b57cec5SDimitry Andric           case S4_pstorerif_abs:  return S2_pstorerif_io;
946*0b57cec5SDimitry Andric           case S4_pstorerdt_abs:  return S2_pstorerdt_io;
947*0b57cec5SDimitry Andric           case S4_pstorerdf_abs:  return S2_pstorerdf_io;
948*0b57cec5SDimitry Andric           default:
949*0b57cec5SDimitry Andric             break;
950*0b57cec5SDimitry Andric         }
951*0b57cec5SDimitry Andric         break;
952*0b57cec5SDimitry Andric       case HexagonII::BaseImmOffset:
953*0b57cec5SDimitry Andric         if (!isStoreImmediate(ExtOpc))
954*0b57cec5SDimitry Andric           return ExtOpc;
955*0b57cec5SDimitry Andric         break;
956*0b57cec5SDimitry Andric       default:
957*0b57cec5SDimitry Andric         break;
958*0b57cec5SDimitry Andric     }
959*0b57cec5SDimitry Andric   }
960*0b57cec5SDimitry Andric   return 0;
961*0b57cec5SDimitry Andric }
962*0b57cec5SDimitry Andric 
963*0b57cec5SDimitry Andric unsigned HCE::getDirectRegReplacement(unsigned ExtOpc) const {
964*0b57cec5SDimitry Andric   switch (ExtOpc) {
965*0b57cec5SDimitry Andric     case Hexagon::A2_addi:          return Hexagon::A2_add;
966*0b57cec5SDimitry Andric     case Hexagon::A2_andir:         return Hexagon::A2_and;
967*0b57cec5SDimitry Andric     case Hexagon::A2_combineii:     return Hexagon::A4_combineri;
968*0b57cec5SDimitry Andric     case Hexagon::A2_orir:          return Hexagon::A2_or;
969*0b57cec5SDimitry Andric     case Hexagon::A2_paddif:        return Hexagon::A2_paddf;
970*0b57cec5SDimitry Andric     case Hexagon::A2_paddit:        return Hexagon::A2_paddt;
971*0b57cec5SDimitry Andric     case Hexagon::A2_subri:         return Hexagon::A2_sub;
972*0b57cec5SDimitry Andric     case Hexagon::A2_tfrsi:         return TargetOpcode::COPY;
973*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbeqi:       return Hexagon::A4_cmpbeq;
974*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbgti:       return Hexagon::A4_cmpbgt;
975*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbgtui:      return Hexagon::A4_cmpbgtu;
976*0b57cec5SDimitry Andric     case Hexagon::A4_cmpheqi:       return Hexagon::A4_cmpheq;
977*0b57cec5SDimitry Andric     case Hexagon::A4_cmphgti:       return Hexagon::A4_cmphgt;
978*0b57cec5SDimitry Andric     case Hexagon::A4_cmphgtui:      return Hexagon::A4_cmphgtu;
979*0b57cec5SDimitry Andric     case Hexagon::A4_combineii:     return Hexagon::A4_combineir;
980*0b57cec5SDimitry Andric     case Hexagon::A4_combineir:     return TargetOpcode::REG_SEQUENCE;
981*0b57cec5SDimitry Andric     case Hexagon::A4_combineri:     return TargetOpcode::REG_SEQUENCE;
982*0b57cec5SDimitry Andric     case Hexagon::A4_rcmpeqi:       return Hexagon::A4_rcmpeq;
983*0b57cec5SDimitry Andric     case Hexagon::A4_rcmpneqi:      return Hexagon::A4_rcmpneq;
984*0b57cec5SDimitry Andric     case Hexagon::C2_cmoveif:       return Hexagon::A2_tfrpf;
985*0b57cec5SDimitry Andric     case Hexagon::C2_cmoveit:       return Hexagon::A2_tfrpt;
986*0b57cec5SDimitry Andric     case Hexagon::C2_cmpeqi:        return Hexagon::C2_cmpeq;
987*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgti:        return Hexagon::C2_cmpgt;
988*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgtui:       return Hexagon::C2_cmpgtu;
989*0b57cec5SDimitry Andric     case Hexagon::C2_muxii:         return Hexagon::C2_muxir;
990*0b57cec5SDimitry Andric     case Hexagon::C2_muxir:         return Hexagon::C2_mux;
991*0b57cec5SDimitry Andric     case Hexagon::C2_muxri:         return Hexagon::C2_mux;
992*0b57cec5SDimitry Andric     case Hexagon::C4_cmpltei:       return Hexagon::C4_cmplte;
993*0b57cec5SDimitry Andric     case Hexagon::C4_cmplteui:      return Hexagon::C4_cmplteu;
994*0b57cec5SDimitry Andric     case Hexagon::C4_cmpneqi:       return Hexagon::C4_cmpneq;
995*0b57cec5SDimitry Andric     case Hexagon::M2_accii:         return Hexagon::M2_acci;        // T -> T
996*0b57cec5SDimitry Andric     /* No M2_macsin */
997*0b57cec5SDimitry Andric     case Hexagon::M2_macsip:        return Hexagon::M2_maci;        // T -> T
998*0b57cec5SDimitry Andric     case Hexagon::M2_mpysin:        return Hexagon::M2_mpyi;
999*0b57cec5SDimitry Andric     case Hexagon::M2_mpysip:        return Hexagon::M2_mpyi;
1000*0b57cec5SDimitry Andric     case Hexagon::M2_mpysmi:        return Hexagon::M2_mpyi;
1001*0b57cec5SDimitry Andric     case Hexagon::M2_naccii:        return Hexagon::M2_nacci;       // T -> T
1002*0b57cec5SDimitry Andric     case Hexagon::M4_mpyri_addi:    return Hexagon::M4_mpyri_addr;
1003*0b57cec5SDimitry Andric     case Hexagon::M4_mpyri_addr:    return Hexagon::M4_mpyrr_addr;  // _ -> T
1004*0b57cec5SDimitry Andric     case Hexagon::M4_mpyrr_addi:    return Hexagon::M4_mpyrr_addr;  // _ -> T
1005*0b57cec5SDimitry Andric     case Hexagon::S4_addaddi:       return Hexagon::M2_acci;        // _ -> T
1006*0b57cec5SDimitry Andric     case Hexagon::S4_addi_asl_ri:   return Hexagon::S2_asl_i_r_acc; // T -> T
1007*0b57cec5SDimitry Andric     case Hexagon::S4_addi_lsr_ri:   return Hexagon::S2_lsr_i_r_acc; // T -> T
1008*0b57cec5SDimitry Andric     case Hexagon::S4_andi_asl_ri:   return Hexagon::S2_asl_i_r_and; // T -> T
1009*0b57cec5SDimitry Andric     case Hexagon::S4_andi_lsr_ri:   return Hexagon::S2_lsr_i_r_and; // T -> T
1010*0b57cec5SDimitry Andric     case Hexagon::S4_ori_asl_ri:    return Hexagon::S2_asl_i_r_or;  // T -> T
1011*0b57cec5SDimitry Andric     case Hexagon::S4_ori_lsr_ri:    return Hexagon::S2_lsr_i_r_or;  // T -> T
1012*0b57cec5SDimitry Andric     case Hexagon::S4_subaddi:       return Hexagon::M2_subacc;      // _ -> T
1013*0b57cec5SDimitry Andric     case Hexagon::S4_subi_asl_ri:   return Hexagon::S2_asl_i_r_nac; // T -> T
1014*0b57cec5SDimitry Andric     case Hexagon::S4_subi_lsr_ri:   return Hexagon::S2_lsr_i_r_nac; // T -> T
1015*0b57cec5SDimitry Andric 
1016*0b57cec5SDimitry Andric     // Store-immediates:
1017*0b57cec5SDimitry Andric     case Hexagon::S4_storeirbf_io:  return Hexagon::S2_pstorerbf_io;
1018*0b57cec5SDimitry Andric     case Hexagon::S4_storeirb_io:   return Hexagon::S2_storerb_io;
1019*0b57cec5SDimitry Andric     case Hexagon::S4_storeirbt_io:  return Hexagon::S2_pstorerbt_io;
1020*0b57cec5SDimitry Andric     case Hexagon::S4_storeirhf_io:  return Hexagon::S2_pstorerhf_io;
1021*0b57cec5SDimitry Andric     case Hexagon::S4_storeirh_io:   return Hexagon::S2_storerh_io;
1022*0b57cec5SDimitry Andric     case Hexagon::S4_storeirht_io:  return Hexagon::S2_pstorerht_io;
1023*0b57cec5SDimitry Andric     case Hexagon::S4_storeirif_io:  return Hexagon::S2_pstorerif_io;
1024*0b57cec5SDimitry Andric     case Hexagon::S4_storeiri_io:   return Hexagon::S2_storeri_io;
1025*0b57cec5SDimitry Andric     case Hexagon::S4_storeirit_io:  return Hexagon::S2_pstorerit_io;
1026*0b57cec5SDimitry Andric 
1027*0b57cec5SDimitry Andric     default:
1028*0b57cec5SDimitry Andric       break;
1029*0b57cec5SDimitry Andric   }
1030*0b57cec5SDimitry Andric   return 0;
1031*0b57cec5SDimitry Andric }
1032*0b57cec5SDimitry Andric 
1033*0b57cec5SDimitry Andric // Return the allowable deviation from the current value of Rb (i.e. the
1034*0b57cec5SDimitry Andric // range of values that can be added to the current value) which the
1035*0b57cec5SDimitry Andric // instruction MI can accommodate.
1036*0b57cec5SDimitry Andric // The instruction MI is a user of register Rb, which is defined via an
1037*0b57cec5SDimitry Andric // extender. It may be possible for MI to be tweaked to work for a register
1038*0b57cec5SDimitry Andric // defined with a slightly different value. For example
1039*0b57cec5SDimitry Andric //   ... = L2_loadrub_io Rb, 1
1040*0b57cec5SDimitry Andric // can be modifed to be
1041*0b57cec5SDimitry Andric //   ... = L2_loadrub_io Rb', 0
1042*0b57cec5SDimitry Andric // if Rb' = Rb+1.
1043*0b57cec5SDimitry Andric // The range for Rb would be [Min+1, Max+1], where [Min, Max] is a range
1044*0b57cec5SDimitry Andric // for L2_loadrub with offset 0. That means that Rb could be replaced with
1045*0b57cec5SDimitry Andric // Rc, where Rc-Rb belongs to [Min+1, Max+1].
1046*0b57cec5SDimitry Andric OffsetRange HCE::getOffsetRange(Register Rb, const MachineInstr &MI) const {
1047*0b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
1048*0b57cec5SDimitry Andric   // Instructions that are constant-extended may be replaced with something
1049*0b57cec5SDimitry Andric   // else that no longer offers the same range as the original.
1050*0b57cec5SDimitry Andric   if (!isRegOffOpcode(Opc) || HII->isConstExtended(MI))
1051*0b57cec5SDimitry Andric     return OffsetRange::zero();
1052*0b57cec5SDimitry Andric 
1053*0b57cec5SDimitry Andric   if (Opc == Hexagon::A2_addi) {
1054*0b57cec5SDimitry Andric     const MachineOperand &Op1 = MI.getOperand(1), &Op2 = MI.getOperand(2);
1055*0b57cec5SDimitry Andric     if (Rb != Register(Op1) || !Op2.isImm())
1056*0b57cec5SDimitry Andric       return OffsetRange::zero();
1057*0b57cec5SDimitry Andric     OffsetRange R = { -(1<<15)+1, (1<<15)-1, 1 };
1058*0b57cec5SDimitry Andric     return R.shift(Op2.getImm());
1059*0b57cec5SDimitry Andric   }
1060*0b57cec5SDimitry Andric 
1061*0b57cec5SDimitry Andric   // HII::getBaseAndOffsetPosition returns the increment position as "offset".
1062*0b57cec5SDimitry Andric   if (HII->isPostIncrement(MI))
1063*0b57cec5SDimitry Andric     return OffsetRange::zero();
1064*0b57cec5SDimitry Andric 
1065*0b57cec5SDimitry Andric   const MCInstrDesc &D = HII->get(Opc);
1066*0b57cec5SDimitry Andric   assert(D.mayLoad() || D.mayStore());
1067*0b57cec5SDimitry Andric 
1068*0b57cec5SDimitry Andric   unsigned BaseP, OffP;
1069*0b57cec5SDimitry Andric   if (!HII->getBaseAndOffsetPosition(MI, BaseP, OffP) ||
1070*0b57cec5SDimitry Andric       Rb != Register(MI.getOperand(BaseP)) ||
1071*0b57cec5SDimitry Andric       !MI.getOperand(OffP).isImm())
1072*0b57cec5SDimitry Andric     return OffsetRange::zero();
1073*0b57cec5SDimitry Andric 
1074*0b57cec5SDimitry Andric   uint64_t F = (D.TSFlags >> HexagonII::MemAccessSizePos) &
1075*0b57cec5SDimitry Andric                   HexagonII::MemAccesSizeMask;
1076*0b57cec5SDimitry Andric   uint8_t A = HexagonII::getMemAccessSizeInBytes(HexagonII::MemAccessSize(F));
1077*0b57cec5SDimitry Andric   unsigned L = Log2_32(A);
1078*0b57cec5SDimitry Andric   unsigned S = 10+L;  // sint11_L
1079*0b57cec5SDimitry Andric   int32_t Min = -alignDown((1<<S)-1, A);
1080*0b57cec5SDimitry Andric 
1081*0b57cec5SDimitry Andric   // The range will be shifted by Off. To prefer non-negative offsets,
1082*0b57cec5SDimitry Andric   // adjust Max accordingly.
1083*0b57cec5SDimitry Andric   int32_t Off = MI.getOperand(OffP).getImm();
1084*0b57cec5SDimitry Andric   int32_t Max = Off >= 0 ? 0 : -Off;
1085*0b57cec5SDimitry Andric 
1086*0b57cec5SDimitry Andric   OffsetRange R = { Min, Max, A };
1087*0b57cec5SDimitry Andric   return R.shift(Off);
1088*0b57cec5SDimitry Andric }
1089*0b57cec5SDimitry Andric 
1090*0b57cec5SDimitry Andric // Return the allowable deviation from the current value of the extender ED,
1091*0b57cec5SDimitry Andric // for which the instruction corresponding to ED can be modified without
1092*0b57cec5SDimitry Andric // using an extender.
1093*0b57cec5SDimitry Andric // The instruction uses the extender directly. It will be replaced with
1094*0b57cec5SDimitry Andric // another instruction, say MJ, where the extender will be replaced with a
1095*0b57cec5SDimitry Andric // register. MJ can allow some variability with respect to the value of
1096*0b57cec5SDimitry Andric // that register, as is the case with indexed memory instructions.
1097*0b57cec5SDimitry Andric OffsetRange HCE::getOffsetRange(const ExtDesc &ED) const {
1098*0b57cec5SDimitry Andric   // The only way that there can be a non-zero range available is if
1099*0b57cec5SDimitry Andric   // the instruction using ED will be converted to an indexed memory
1100*0b57cec5SDimitry Andric   // instruction.
1101*0b57cec5SDimitry Andric   unsigned IdxOpc = getRegOffOpcode(ED.UseMI->getOpcode());
1102*0b57cec5SDimitry Andric   switch (IdxOpc) {
1103*0b57cec5SDimitry Andric     case 0:
1104*0b57cec5SDimitry Andric       return OffsetRange::zero();
1105*0b57cec5SDimitry Andric     case Hexagon::A2_addi:    // s16
1106*0b57cec5SDimitry Andric       return { -32767, 32767, 1 };
1107*0b57cec5SDimitry Andric     case Hexagon::A2_subri:   // s10
1108*0b57cec5SDimitry Andric       return { -511, 511, 1 };
1109*0b57cec5SDimitry Andric   }
1110*0b57cec5SDimitry Andric 
1111*0b57cec5SDimitry Andric   if (!ED.UseMI->mayLoad() && !ED.UseMI->mayStore())
1112*0b57cec5SDimitry Andric     return OffsetRange::zero();
1113*0b57cec5SDimitry Andric   const MCInstrDesc &D = HII->get(IdxOpc);
1114*0b57cec5SDimitry Andric   uint64_t F = (D.TSFlags >> HexagonII::MemAccessSizePos) &
1115*0b57cec5SDimitry Andric                   HexagonII::MemAccesSizeMask;
1116*0b57cec5SDimitry Andric   uint8_t A = HexagonII::getMemAccessSizeInBytes(HexagonII::MemAccessSize(F));
1117*0b57cec5SDimitry Andric   unsigned L = Log2_32(A);
1118*0b57cec5SDimitry Andric   unsigned S = 10+L;  // sint11_L
1119*0b57cec5SDimitry Andric   int32_t Min = -alignDown((1<<S)-1, A);
1120*0b57cec5SDimitry Andric   int32_t Max = 0;  // Force non-negative offsets.
1121*0b57cec5SDimitry Andric   return { Min, Max, A };
1122*0b57cec5SDimitry Andric }
1123*0b57cec5SDimitry Andric 
1124*0b57cec5SDimitry Andric // Get the allowable deviation from the current value of Rd by checking
1125*0b57cec5SDimitry Andric // all uses of Rd.
1126*0b57cec5SDimitry Andric OffsetRange HCE::getOffsetRange(Register Rd) const {
1127*0b57cec5SDimitry Andric   OffsetRange Range;
1128*0b57cec5SDimitry Andric   for (const MachineOperand &Op : MRI->use_operands(Rd.Reg)) {
1129*0b57cec5SDimitry Andric     // Make sure that the register being used by this operand is identical
1130*0b57cec5SDimitry Andric     // to the register that was defined: using a different subregister
1131*0b57cec5SDimitry Andric     // precludes any non-trivial range.
1132*0b57cec5SDimitry Andric     if (Rd != Register(Op))
1133*0b57cec5SDimitry Andric       return OffsetRange::zero();
1134*0b57cec5SDimitry Andric     Range.intersect(getOffsetRange(Rd, *Op.getParent()));
1135*0b57cec5SDimitry Andric   }
1136*0b57cec5SDimitry Andric   return Range;
1137*0b57cec5SDimitry Andric }
1138*0b57cec5SDimitry Andric 
1139*0b57cec5SDimitry Andric void HCE::recordExtender(MachineInstr &MI, unsigned OpNum) {
1140*0b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
1141*0b57cec5SDimitry Andric   ExtDesc ED;
1142*0b57cec5SDimitry Andric   ED.OpNum = OpNum;
1143*0b57cec5SDimitry Andric 
1144*0b57cec5SDimitry Andric   bool IsLoad = MI.mayLoad();
1145*0b57cec5SDimitry Andric   bool IsStore = MI.mayStore();
1146*0b57cec5SDimitry Andric 
1147*0b57cec5SDimitry Andric   // Fixed stack slots have negative indexes, and they cannot be used
1148*0b57cec5SDimitry Andric   // with TRI::stackSlot2Index and TRI::index2StackSlot. This is somewhat
1149*0b57cec5SDimitry Andric   // unfortunate, but should not be a frequent thing.
1150*0b57cec5SDimitry Andric   for (MachineOperand &Op : MI.operands())
1151*0b57cec5SDimitry Andric     if (Op.isFI() && Op.getIndex() < 0)
1152*0b57cec5SDimitry Andric       return;
1153*0b57cec5SDimitry Andric 
1154*0b57cec5SDimitry Andric   if (IsLoad || IsStore) {
1155*0b57cec5SDimitry Andric     unsigned AM = HII->getAddrMode(MI);
1156*0b57cec5SDimitry Andric     switch (AM) {
1157*0b57cec5SDimitry Andric       // (Re: ##Off + Rb<<S) = Rd: ##Val
1158*0b57cec5SDimitry Andric       case HexagonII::Absolute:       // (__: ## + __<<_)
1159*0b57cec5SDimitry Andric         break;
1160*0b57cec5SDimitry Andric       case HexagonII::AbsoluteSet:    // (Rd: ## + __<<_)
1161*0b57cec5SDimitry Andric         ED.Rd = MI.getOperand(OpNum-1);
1162*0b57cec5SDimitry Andric         ED.IsDef = true;
1163*0b57cec5SDimitry Andric         break;
1164*0b57cec5SDimitry Andric       case HexagonII::BaseImmOffset:  // (__: ## + Rs<<0)
1165*0b57cec5SDimitry Andric         // Store-immediates are treated as non-memory operations, since
1166*0b57cec5SDimitry Andric         // it's the value being stored that is extended (as opposed to
1167*0b57cec5SDimitry Andric         // a part of the address).
1168*0b57cec5SDimitry Andric         if (!isStoreImmediate(Opc))
1169*0b57cec5SDimitry Andric           ED.Expr.Rs = MI.getOperand(OpNum-1);
1170*0b57cec5SDimitry Andric         break;
1171*0b57cec5SDimitry Andric       case HexagonII::BaseLongOffset: // (__: ## + Rs<<S)
1172*0b57cec5SDimitry Andric         ED.Expr.Rs = MI.getOperand(OpNum-2);
1173*0b57cec5SDimitry Andric         ED.Expr.S = MI.getOperand(OpNum-1).getImm();
1174*0b57cec5SDimitry Andric         break;
1175*0b57cec5SDimitry Andric       default:
1176*0b57cec5SDimitry Andric         llvm_unreachable("Unhandled memory instruction");
1177*0b57cec5SDimitry Andric     }
1178*0b57cec5SDimitry Andric   } else {
1179*0b57cec5SDimitry Andric     switch (Opc) {
1180*0b57cec5SDimitry Andric       case Hexagon::A2_tfrsi:         // (Rd: ## + __<<_)
1181*0b57cec5SDimitry Andric         ED.Rd = MI.getOperand(0);
1182*0b57cec5SDimitry Andric         ED.IsDef = true;
1183*0b57cec5SDimitry Andric         break;
1184*0b57cec5SDimitry Andric       case Hexagon::A2_combineii:     // (Rd: ## + __<<_)
1185*0b57cec5SDimitry Andric       case Hexagon::A4_combineir:
1186*0b57cec5SDimitry Andric         ED.Rd = { MI.getOperand(0).getReg(), Hexagon::isub_hi };
1187*0b57cec5SDimitry Andric         ED.IsDef = true;
1188*0b57cec5SDimitry Andric         break;
1189*0b57cec5SDimitry Andric       case Hexagon::A4_combineri:     // (Rd: ## + __<<_)
1190*0b57cec5SDimitry Andric         ED.Rd = { MI.getOperand(0).getReg(), Hexagon::isub_lo };
1191*0b57cec5SDimitry Andric         ED.IsDef = true;
1192*0b57cec5SDimitry Andric         break;
1193*0b57cec5SDimitry Andric       case Hexagon::A2_addi:          // (Rd: ## + Rs<<0)
1194*0b57cec5SDimitry Andric         ED.Rd = MI.getOperand(0);
1195*0b57cec5SDimitry Andric         ED.Expr.Rs = MI.getOperand(OpNum-1);
1196*0b57cec5SDimitry Andric         break;
1197*0b57cec5SDimitry Andric       case Hexagon::M2_accii:         // (__: ## + Rs<<0)
1198*0b57cec5SDimitry Andric       case Hexagon::M2_naccii:
1199*0b57cec5SDimitry Andric       case Hexagon::S4_addaddi:
1200*0b57cec5SDimitry Andric         ED.Expr.Rs = MI.getOperand(OpNum-1);
1201*0b57cec5SDimitry Andric         break;
1202*0b57cec5SDimitry Andric       case Hexagon::A2_subri:         // (Rd: ## - Rs<<0)
1203*0b57cec5SDimitry Andric         ED.Rd = MI.getOperand(0);
1204*0b57cec5SDimitry Andric         ED.Expr.Rs = MI.getOperand(OpNum+1);
1205*0b57cec5SDimitry Andric         ED.Expr.Neg = true;
1206*0b57cec5SDimitry Andric         break;
1207*0b57cec5SDimitry Andric       case Hexagon::S4_subaddi:       // (__: ## - Rs<<0)
1208*0b57cec5SDimitry Andric         ED.Expr.Rs = MI.getOperand(OpNum+1);
1209*0b57cec5SDimitry Andric         ED.Expr.Neg = true;
1210*0b57cec5SDimitry Andric         break;
1211*0b57cec5SDimitry Andric       default:                        // (__: ## + __<<_)
1212*0b57cec5SDimitry Andric         break;
1213*0b57cec5SDimitry Andric     }
1214*0b57cec5SDimitry Andric   }
1215*0b57cec5SDimitry Andric 
1216*0b57cec5SDimitry Andric   ED.UseMI = &MI;
1217*0b57cec5SDimitry Andric 
1218*0b57cec5SDimitry Andric   // Ignore unnamed globals.
1219*0b57cec5SDimitry Andric   ExtRoot ER(ED.getOp());
1220*0b57cec5SDimitry Andric   if (ER.Kind == MachineOperand::MO_GlobalAddress)
1221*0b57cec5SDimitry Andric     if (ER.V.GV->getName().empty())
1222*0b57cec5SDimitry Andric       return;
1223*0b57cec5SDimitry Andric   Extenders.push_back(ED);
1224*0b57cec5SDimitry Andric }
1225*0b57cec5SDimitry Andric 
1226*0b57cec5SDimitry Andric void HCE::collectInstr(MachineInstr &MI) {
1227*0b57cec5SDimitry Andric   if (!HII->isConstExtended(MI))
1228*0b57cec5SDimitry Andric     return;
1229*0b57cec5SDimitry Andric 
1230*0b57cec5SDimitry Andric   // Skip some non-convertible instructions.
1231*0b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
1232*0b57cec5SDimitry Andric   switch (Opc) {
1233*0b57cec5SDimitry Andric     case Hexagon::M2_macsin:  // There is no Rx -= mpyi(Rs,Rt).
1234*0b57cec5SDimitry Andric     case Hexagon::C4_addipc:
1235*0b57cec5SDimitry Andric     case Hexagon::S4_or_andi:
1236*0b57cec5SDimitry Andric     case Hexagon::S4_or_andix:
1237*0b57cec5SDimitry Andric     case Hexagon::S4_or_ori:
1238*0b57cec5SDimitry Andric       return;
1239*0b57cec5SDimitry Andric   }
1240*0b57cec5SDimitry Andric   recordExtender(MI, HII->getCExtOpNum(MI));
1241*0b57cec5SDimitry Andric }
1242*0b57cec5SDimitry Andric 
1243*0b57cec5SDimitry Andric void HCE::collect(MachineFunction &MF) {
1244*0b57cec5SDimitry Andric   Extenders.clear();
1245*0b57cec5SDimitry Andric   for (MachineBasicBlock &MBB : MF) {
1246*0b57cec5SDimitry Andric     // Skip unreachable blocks.
1247*0b57cec5SDimitry Andric     if (MBB.getNumber() == -1)
1248*0b57cec5SDimitry Andric       continue;
1249*0b57cec5SDimitry Andric     for (MachineInstr &MI : MBB)
1250*0b57cec5SDimitry Andric       collectInstr(MI);
1251*0b57cec5SDimitry Andric   }
1252*0b57cec5SDimitry Andric }
1253*0b57cec5SDimitry Andric 
1254*0b57cec5SDimitry Andric void HCE::assignInits(const ExtRoot &ER, unsigned Begin, unsigned End,
1255*0b57cec5SDimitry Andric       AssignmentMap &IMap) {
1256*0b57cec5SDimitry Andric   // Sanity check: make sure that all extenders in the range [Begin..End)
1257*0b57cec5SDimitry Andric   // share the same root ER.
1258*0b57cec5SDimitry Andric   for (unsigned I = Begin; I != End; ++I)
1259*0b57cec5SDimitry Andric     assert(ER == ExtRoot(Extenders[I].getOp()));
1260*0b57cec5SDimitry Andric 
1261*0b57cec5SDimitry Andric   // Construct the list of ranges, such that for each P in Ranges[I],
1262*0b57cec5SDimitry Andric   // a register Reg = ER+P can be used in place of Extender[I]. If the
1263*0b57cec5SDimitry Andric   // instruction allows, uses in the form of Reg+Off are considered
1264*0b57cec5SDimitry Andric   // (here, Off = required_value - P).
1265*0b57cec5SDimitry Andric   std::vector<OffsetRange> Ranges(End-Begin);
1266*0b57cec5SDimitry Andric 
1267*0b57cec5SDimitry Andric   // For each extender that is a def, visit all uses of the defined register,
1268*0b57cec5SDimitry Andric   // and produce an offset range that works for all uses. The def doesn't
1269*0b57cec5SDimitry Andric   // have to be checked, because it can become dead if all uses can be updated
1270*0b57cec5SDimitry Andric   // to use a different reg/offset.
1271*0b57cec5SDimitry Andric   for (unsigned I = Begin; I != End; ++I) {
1272*0b57cec5SDimitry Andric     const ExtDesc &ED = Extenders[I];
1273*0b57cec5SDimitry Andric     if (!ED.IsDef)
1274*0b57cec5SDimitry Andric       continue;
1275*0b57cec5SDimitry Andric     ExtValue EV(ED);
1276*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << " =" << I << ". " << EV << "  " << ED << '\n');
1277*0b57cec5SDimitry Andric     assert(ED.Rd.Reg != 0);
1278*0b57cec5SDimitry Andric     Ranges[I-Begin] = getOffsetRange(ED.Rd).shift(EV.Offset);
1279*0b57cec5SDimitry Andric     // A2_tfrsi is a special case: it will be replaced with A2_addi, which
1280*0b57cec5SDimitry Andric     // has a 16-bit signed offset. This means that A2_tfrsi not only has a
1281*0b57cec5SDimitry Andric     // range coming from its uses, but also from the fact that its replacement
1282*0b57cec5SDimitry Andric     // has a range as well.
1283*0b57cec5SDimitry Andric     if (ED.UseMI->getOpcode() == Hexagon::A2_tfrsi) {
1284*0b57cec5SDimitry Andric       int32_t D = alignDown(32767, Ranges[I-Begin].Align); // XXX hardcoded
1285*0b57cec5SDimitry Andric       Ranges[I-Begin].extendBy(-D).extendBy(D);
1286*0b57cec5SDimitry Andric     }
1287*0b57cec5SDimitry Andric   }
1288*0b57cec5SDimitry Andric 
1289*0b57cec5SDimitry Andric   // Visit all non-def extenders. For each one, determine the offset range
1290*0b57cec5SDimitry Andric   // available for it.
1291*0b57cec5SDimitry Andric   for (unsigned I = Begin; I != End; ++I) {
1292*0b57cec5SDimitry Andric     const ExtDesc &ED = Extenders[I];
1293*0b57cec5SDimitry Andric     if (ED.IsDef)
1294*0b57cec5SDimitry Andric       continue;
1295*0b57cec5SDimitry Andric     ExtValue EV(ED);
1296*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "  " << I << ". " << EV << "  " << ED << '\n');
1297*0b57cec5SDimitry Andric     OffsetRange Dev = getOffsetRange(ED);
1298*0b57cec5SDimitry Andric     Ranges[I-Begin].intersect(Dev.shift(EV.Offset));
1299*0b57cec5SDimitry Andric   }
1300*0b57cec5SDimitry Andric 
1301*0b57cec5SDimitry Andric   // Here for each I there is a corresponding Range[I]. Construct the
1302*0b57cec5SDimitry Andric   // inverse map, that to each range will assign the set of indexes in
1303*0b57cec5SDimitry Andric   // [Begin..End) that this range corresponds to.
1304*0b57cec5SDimitry Andric   std::map<OffsetRange, IndexList> RangeMap;
1305*0b57cec5SDimitry Andric   for (unsigned I = Begin; I != End; ++I)
1306*0b57cec5SDimitry Andric     RangeMap[Ranges[I-Begin]].insert(I);
1307*0b57cec5SDimitry Andric 
1308*0b57cec5SDimitry Andric   LLVM_DEBUG({
1309*0b57cec5SDimitry Andric     dbgs() << "Ranges\n";
1310*0b57cec5SDimitry Andric     for (unsigned I = Begin; I != End; ++I)
1311*0b57cec5SDimitry Andric       dbgs() << "  " << I << ". " << Ranges[I-Begin] << '\n';
1312*0b57cec5SDimitry Andric     dbgs() << "RangeMap\n";
1313*0b57cec5SDimitry Andric     for (auto &P : RangeMap) {
1314*0b57cec5SDimitry Andric       dbgs() << "  " << P.first << " ->";
1315*0b57cec5SDimitry Andric       for (unsigned I : P.second)
1316*0b57cec5SDimitry Andric         dbgs() << ' ' << I;
1317*0b57cec5SDimitry Andric       dbgs() << '\n';
1318*0b57cec5SDimitry Andric     }
1319*0b57cec5SDimitry Andric   });
1320*0b57cec5SDimitry Andric 
1321*0b57cec5SDimitry Andric   // Select the definition points, and generate the assignment between
1322*0b57cec5SDimitry Andric   // these points and the uses.
1323*0b57cec5SDimitry Andric 
1324*0b57cec5SDimitry Andric   // For each candidate offset, keep a pair CandData consisting of
1325*0b57cec5SDimitry Andric   // the total number of ranges containing that candidate, and the
1326*0b57cec5SDimitry Andric   // vector of corresponding RangeTree nodes.
1327*0b57cec5SDimitry Andric   using CandData = std::pair<unsigned, SmallVector<RangeTree::Node*,8>>;
1328*0b57cec5SDimitry Andric   std::map<int32_t, CandData> CandMap;
1329*0b57cec5SDimitry Andric 
1330*0b57cec5SDimitry Andric   RangeTree Tree;
1331*0b57cec5SDimitry Andric   for (const OffsetRange &R : Ranges)
1332*0b57cec5SDimitry Andric     Tree.add(R);
1333*0b57cec5SDimitry Andric   SmallVector<RangeTree::Node*,8> Nodes;
1334*0b57cec5SDimitry Andric   Tree.order(Nodes);
1335*0b57cec5SDimitry Andric 
1336*0b57cec5SDimitry Andric   auto MaxAlign = [](const SmallVectorImpl<RangeTree::Node*> &Nodes,
1337*0b57cec5SDimitry Andric                      uint8_t Align, uint8_t Offset) {
1338*0b57cec5SDimitry Andric     for (RangeTree::Node *N : Nodes) {
1339*0b57cec5SDimitry Andric       if (N->Range.Align <= Align || N->Range.Offset < Offset)
1340*0b57cec5SDimitry Andric         continue;
1341*0b57cec5SDimitry Andric       if ((N->Range.Offset - Offset) % Align != 0)
1342*0b57cec5SDimitry Andric         continue;
1343*0b57cec5SDimitry Andric       Align = N->Range.Align;
1344*0b57cec5SDimitry Andric       Offset = N->Range.Offset;
1345*0b57cec5SDimitry Andric     }
1346*0b57cec5SDimitry Andric     return std::make_pair(Align, Offset);
1347*0b57cec5SDimitry Andric   };
1348*0b57cec5SDimitry Andric 
1349*0b57cec5SDimitry Andric   // Construct the set of all potential definition points from the endpoints
1350*0b57cec5SDimitry Andric   // of the ranges. If a given endpoint also belongs to a different range,
1351*0b57cec5SDimitry Andric   // but with a higher alignment, also consider the more-highly-aligned
1352*0b57cec5SDimitry Andric   // value of this endpoint.
1353*0b57cec5SDimitry Andric   std::set<int32_t> CandSet;
1354*0b57cec5SDimitry Andric   for (RangeTree::Node *N : Nodes) {
1355*0b57cec5SDimitry Andric     const OffsetRange &R = N->Range;
1356*0b57cec5SDimitry Andric     auto P0 = MaxAlign(Tree.nodesWith(R.Min, false), R.Align, R.Offset);
1357*0b57cec5SDimitry Andric     CandSet.insert(R.Min);
1358*0b57cec5SDimitry Andric     if (R.Align < P0.first)
1359*0b57cec5SDimitry Andric       CandSet.insert(adjustUp(R.Min, P0.first, P0.second));
1360*0b57cec5SDimitry Andric     auto P1 = MaxAlign(Tree.nodesWith(R.Max, false), R.Align, R.Offset);
1361*0b57cec5SDimitry Andric     CandSet.insert(R.Max);
1362*0b57cec5SDimitry Andric     if (R.Align < P1.first)
1363*0b57cec5SDimitry Andric       CandSet.insert(adjustDown(R.Max, P1.first, P1.second));
1364*0b57cec5SDimitry Andric   }
1365*0b57cec5SDimitry Andric 
1366*0b57cec5SDimitry Andric   // Build the assignment map: candidate C -> { list of extender indexes }.
1367*0b57cec5SDimitry Andric   // This has to be done iteratively:
1368*0b57cec5SDimitry Andric   // - pick the candidate that covers the maximum number of extenders,
1369*0b57cec5SDimitry Andric   // - add the candidate to the map,
1370*0b57cec5SDimitry Andric   // - remove the extenders from the pool.
1371*0b57cec5SDimitry Andric   while (true) {
1372*0b57cec5SDimitry Andric     using CMap = std::map<int32_t,unsigned>;
1373*0b57cec5SDimitry Andric     CMap Counts;
1374*0b57cec5SDimitry Andric     for (auto It = CandSet.begin(), Et = CandSet.end(); It != Et; ) {
1375*0b57cec5SDimitry Andric       auto &&V = Tree.nodesWith(*It);
1376*0b57cec5SDimitry Andric       unsigned N = std::accumulate(V.begin(), V.end(), 0u,
1377*0b57cec5SDimitry Andric                     [](unsigned Acc, const RangeTree::Node *N) {
1378*0b57cec5SDimitry Andric                       return Acc + N->Count;
1379*0b57cec5SDimitry Andric                     });
1380*0b57cec5SDimitry Andric       if (N != 0)
1381*0b57cec5SDimitry Andric         Counts.insert({*It, N});
1382*0b57cec5SDimitry Andric       It = (N != 0) ? std::next(It) : CandSet.erase(It);
1383*0b57cec5SDimitry Andric     }
1384*0b57cec5SDimitry Andric     if (Counts.empty())
1385*0b57cec5SDimitry Andric       break;
1386*0b57cec5SDimitry Andric 
1387*0b57cec5SDimitry Andric     // Find the best candidate with respect to the number of extenders covered.
1388*0b57cec5SDimitry Andric     auto BestIt = std::max_element(Counts.begin(), Counts.end(),
1389*0b57cec5SDimitry Andric                     [](const CMap::value_type &A, const CMap::value_type &B) {
1390*0b57cec5SDimitry Andric                       return A.second < B.second ||
1391*0b57cec5SDimitry Andric                              (A.second == B.second && A < B);
1392*0b57cec5SDimitry Andric                     });
1393*0b57cec5SDimitry Andric     int32_t Best = BestIt->first;
1394*0b57cec5SDimitry Andric     ExtValue BestV(ER, Best);
1395*0b57cec5SDimitry Andric     for (RangeTree::Node *N : Tree.nodesWith(Best)) {
1396*0b57cec5SDimitry Andric       for (unsigned I : RangeMap[N->Range])
1397*0b57cec5SDimitry Andric         IMap[{BestV,Extenders[I].Expr}].insert(I);
1398*0b57cec5SDimitry Andric       Tree.erase(N);
1399*0b57cec5SDimitry Andric     }
1400*0b57cec5SDimitry Andric   }
1401*0b57cec5SDimitry Andric 
1402*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "IMap (before fixup) = " << PrintIMap(IMap, *HRI));
1403*0b57cec5SDimitry Andric 
1404*0b57cec5SDimitry Andric   // There is some ambiguity in what initializer should be used, if the
1405*0b57cec5SDimitry Andric   // descriptor's subexpression is non-trivial: it can be the entire
1406*0b57cec5SDimitry Andric   // subexpression (which is what has been done so far), or it can be
1407*0b57cec5SDimitry Andric   // the extender's value itself, if all corresponding extenders have the
1408*0b57cec5SDimitry Andric   // exact value of the initializer (i.e. require offset of 0).
1409*0b57cec5SDimitry Andric 
1410*0b57cec5SDimitry Andric   // To reduce the number of initializers, merge such special cases.
1411*0b57cec5SDimitry Andric   for (std::pair<const ExtenderInit,IndexList> &P : IMap) {
1412*0b57cec5SDimitry Andric     // Skip trivial initializers.
1413*0b57cec5SDimitry Andric     if (P.first.second.trivial())
1414*0b57cec5SDimitry Andric       continue;
1415*0b57cec5SDimitry Andric     // If the corresponding trivial initializer does not exist, skip this
1416*0b57cec5SDimitry Andric     // entry.
1417*0b57cec5SDimitry Andric     const ExtValue &EV = P.first.first;
1418*0b57cec5SDimitry Andric     AssignmentMap::iterator F = IMap.find({EV, ExtExpr()});
1419*0b57cec5SDimitry Andric     if (F == IMap.end())
1420*0b57cec5SDimitry Andric       continue;
1421*0b57cec5SDimitry Andric 
1422*0b57cec5SDimitry Andric     // Finally, check if all extenders have the same value as the initializer.
1423*0b57cec5SDimitry Andric     // Make sure that extenders that are a part of a stack address are not
1424*0b57cec5SDimitry Andric     // merged with those that aren't. Stack addresses need an offset field
1425*0b57cec5SDimitry Andric     // (to be used by frame index elimination), while non-stack expressions
1426*0b57cec5SDimitry Andric     // can be replaced with forms (such as rr) that do not have such a field.
1427*0b57cec5SDimitry Andric     // Example:
1428*0b57cec5SDimitry Andric     //
1429*0b57cec5SDimitry Andric     // Collected 3 extenders
1430*0b57cec5SDimitry Andric     //  =2. imm:0  off:32968  bb#2: %7 = ## + __ << 0, def
1431*0b57cec5SDimitry Andric     //   0. imm:0  off:267  bb#0: __ = ## + SS#1 << 0
1432*0b57cec5SDimitry Andric     //   1. imm:0  off:267  bb#1: __ = ## + SS#1 << 0
1433*0b57cec5SDimitry Andric     // Ranges
1434*0b57cec5SDimitry Andric     //   0. [-756,267]a1+0
1435*0b57cec5SDimitry Andric     //   1. [-756,267]a1+0
1436*0b57cec5SDimitry Andric     //   2. [201,65735]a1+0
1437*0b57cec5SDimitry Andric     // RangeMap
1438*0b57cec5SDimitry Andric     //   [-756,267]a1+0 -> 0 1
1439*0b57cec5SDimitry Andric     //   [201,65735]a1+0 -> 2
1440*0b57cec5SDimitry Andric     // IMap (before fixup) = {
1441*0b57cec5SDimitry Andric     //   [imm:0  off:267, ## + __ << 0] -> { 2 }
1442*0b57cec5SDimitry Andric     //   [imm:0  off:267, ## + SS#1 << 0] -> { 0 1 }
1443*0b57cec5SDimitry Andric     // }
1444*0b57cec5SDimitry Andric     // IMap (after fixup) = {
1445*0b57cec5SDimitry Andric     //   [imm:0  off:267, ## + __ << 0] -> { 2 0 1 }
1446*0b57cec5SDimitry Andric     //   [imm:0  off:267, ## + SS#1 << 0] -> { }
1447*0b57cec5SDimitry Andric     // }
1448*0b57cec5SDimitry Andric     // Inserted def in bb#0 for initializer: [imm:0  off:267, ## + __ << 0]
1449*0b57cec5SDimitry Andric     //   %12:intregs = A2_tfrsi 267
1450*0b57cec5SDimitry Andric     //
1451*0b57cec5SDimitry Andric     // The result was
1452*0b57cec5SDimitry Andric     //   %12:intregs = A2_tfrsi 267
1453*0b57cec5SDimitry Andric     //   S4_pstorerbt_rr %3, %12, %stack.1, 0, killed %4
1454*0b57cec5SDimitry Andric     // Which became
1455*0b57cec5SDimitry Andric     //   r0 = #267
1456*0b57cec5SDimitry Andric     //   if (p0.new) memb(r0+r29<<#4) = r2
1457*0b57cec5SDimitry Andric 
1458*0b57cec5SDimitry Andric     bool IsStack = any_of(F->second, [this](unsigned I) {
1459*0b57cec5SDimitry Andric                       return Extenders[I].Expr.Rs.isSlot();
1460*0b57cec5SDimitry Andric                    });
1461*0b57cec5SDimitry Andric     auto SameValue = [&EV,this,IsStack](unsigned I) {
1462*0b57cec5SDimitry Andric       const ExtDesc &ED = Extenders[I];
1463*0b57cec5SDimitry Andric       return ED.Expr.Rs.isSlot() == IsStack &&
1464*0b57cec5SDimitry Andric              ExtValue(ED).Offset == EV.Offset;
1465*0b57cec5SDimitry Andric     };
1466*0b57cec5SDimitry Andric     if (all_of(P.second, SameValue)) {
1467*0b57cec5SDimitry Andric       F->second.insert(P.second.begin(), P.second.end());
1468*0b57cec5SDimitry Andric       P.second.clear();
1469*0b57cec5SDimitry Andric     }
1470*0b57cec5SDimitry Andric   }
1471*0b57cec5SDimitry Andric 
1472*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "IMap (after fixup) = " << PrintIMap(IMap, *HRI));
1473*0b57cec5SDimitry Andric }
1474*0b57cec5SDimitry Andric 
1475*0b57cec5SDimitry Andric void HCE::calculatePlacement(const ExtenderInit &ExtI, const IndexList &Refs,
1476*0b57cec5SDimitry Andric       LocDefList &Defs) {
1477*0b57cec5SDimitry Andric   if (Refs.empty())
1478*0b57cec5SDimitry Andric     return;
1479*0b57cec5SDimitry Andric 
1480*0b57cec5SDimitry Andric   // The placement calculation is somewhat simple right now: it finds a
1481*0b57cec5SDimitry Andric   // single location for the def that dominates all refs. Since this may
1482*0b57cec5SDimitry Andric   // place the def far from the uses, producing several locations for
1483*0b57cec5SDimitry Andric   // defs that collectively dominate all refs could be better.
1484*0b57cec5SDimitry Andric   // For now only do the single one.
1485*0b57cec5SDimitry Andric   DenseSet<MachineBasicBlock*> Blocks;
1486*0b57cec5SDimitry Andric   DenseSet<MachineInstr*> RefMIs;
1487*0b57cec5SDimitry Andric   const ExtDesc &ED0 = Extenders[Refs[0]];
1488*0b57cec5SDimitry Andric   MachineBasicBlock *DomB = ED0.UseMI->getParent();
1489*0b57cec5SDimitry Andric   RefMIs.insert(ED0.UseMI);
1490*0b57cec5SDimitry Andric   Blocks.insert(DomB);
1491*0b57cec5SDimitry Andric   for (unsigned i = 1, e = Refs.size(); i != e; ++i) {
1492*0b57cec5SDimitry Andric     const ExtDesc &ED = Extenders[Refs[i]];
1493*0b57cec5SDimitry Andric     MachineBasicBlock *MBB = ED.UseMI->getParent();
1494*0b57cec5SDimitry Andric     RefMIs.insert(ED.UseMI);
1495*0b57cec5SDimitry Andric     DomB = MDT->findNearestCommonDominator(DomB, MBB);
1496*0b57cec5SDimitry Andric     Blocks.insert(MBB);
1497*0b57cec5SDimitry Andric   }
1498*0b57cec5SDimitry Andric 
1499*0b57cec5SDimitry Andric #ifndef NDEBUG
1500*0b57cec5SDimitry Andric   // The block DomB should be dominated by the def of each register used
1501*0b57cec5SDimitry Andric   // in the initializer.
1502*0b57cec5SDimitry Andric   Register Rs = ExtI.second.Rs;  // Only one reg allowed now.
1503*0b57cec5SDimitry Andric   const MachineInstr *DefI = Rs.isVReg() ? MRI->getVRegDef(Rs.Reg) : nullptr;
1504*0b57cec5SDimitry Andric 
1505*0b57cec5SDimitry Andric   // This should be guaranteed given that the entire expression is used
1506*0b57cec5SDimitry Andric   // at each instruction in Refs. Add an assertion just in case.
1507*0b57cec5SDimitry Andric   assert(!DefI || MDT->dominates(DefI->getParent(), DomB));
1508*0b57cec5SDimitry Andric #endif
1509*0b57cec5SDimitry Andric 
1510*0b57cec5SDimitry Andric   MachineBasicBlock::iterator It;
1511*0b57cec5SDimitry Andric   if (Blocks.count(DomB)) {
1512*0b57cec5SDimitry Andric     // Try to find the latest possible location for the def.
1513*0b57cec5SDimitry Andric     MachineBasicBlock::iterator End = DomB->end();
1514*0b57cec5SDimitry Andric     for (It = DomB->begin(); It != End; ++It)
1515*0b57cec5SDimitry Andric       if (RefMIs.count(&*It))
1516*0b57cec5SDimitry Andric         break;
1517*0b57cec5SDimitry Andric     assert(It != End && "Should have found a ref in DomB");
1518*0b57cec5SDimitry Andric   } else {
1519*0b57cec5SDimitry Andric     // DomB does not contain any refs.
1520*0b57cec5SDimitry Andric     It = DomB->getFirstTerminator();
1521*0b57cec5SDimitry Andric   }
1522*0b57cec5SDimitry Andric   Loc DefLoc(DomB, It);
1523*0b57cec5SDimitry Andric   Defs.emplace_back(DefLoc, Refs);
1524*0b57cec5SDimitry Andric }
1525*0b57cec5SDimitry Andric 
1526*0b57cec5SDimitry Andric HCE::Register HCE::insertInitializer(Loc DefL, const ExtenderInit &ExtI) {
1527*0b57cec5SDimitry Andric   unsigned DefR = MRI->createVirtualRegister(&Hexagon::IntRegsRegClass);
1528*0b57cec5SDimitry Andric   MachineBasicBlock &MBB = *DefL.Block;
1529*0b57cec5SDimitry Andric   MachineBasicBlock::iterator At = DefL.At;
1530*0b57cec5SDimitry Andric   DebugLoc dl = DefL.Block->findDebugLoc(DefL.At);
1531*0b57cec5SDimitry Andric   const ExtValue &EV = ExtI.first;
1532*0b57cec5SDimitry Andric   MachineOperand ExtOp(EV);
1533*0b57cec5SDimitry Andric 
1534*0b57cec5SDimitry Andric   const ExtExpr &Ex = ExtI.second;
1535*0b57cec5SDimitry Andric   const MachineInstr *InitI = nullptr;
1536*0b57cec5SDimitry Andric 
1537*0b57cec5SDimitry Andric   if (Ex.Rs.isSlot()) {
1538*0b57cec5SDimitry Andric     assert(Ex.S == 0 && "Cannot have a shift of a stack slot");
1539*0b57cec5SDimitry Andric     assert(!Ex.Neg && "Cannot subtract a stack slot");
1540*0b57cec5SDimitry Andric     // DefR = PS_fi Rb,##EV
1541*0b57cec5SDimitry Andric     InitI = BuildMI(MBB, At, dl, HII->get(Hexagon::PS_fi), DefR)
1542*0b57cec5SDimitry Andric               .add(MachineOperand(Ex.Rs))
1543*0b57cec5SDimitry Andric               .add(ExtOp);
1544*0b57cec5SDimitry Andric   } else {
1545*0b57cec5SDimitry Andric     assert((Ex.Rs.Reg == 0 || Ex.Rs.isVReg()) && "Expecting virtual register");
1546*0b57cec5SDimitry Andric     if (Ex.trivial()) {
1547*0b57cec5SDimitry Andric       // DefR = ##EV
1548*0b57cec5SDimitry Andric       InitI = BuildMI(MBB, At, dl, HII->get(Hexagon::A2_tfrsi), DefR)
1549*0b57cec5SDimitry Andric                 .add(ExtOp);
1550*0b57cec5SDimitry Andric     } else if (Ex.S == 0) {
1551*0b57cec5SDimitry Andric       if (Ex.Neg) {
1552*0b57cec5SDimitry Andric         // DefR = sub(##EV,Rb)
1553*0b57cec5SDimitry Andric         InitI = BuildMI(MBB, At, dl, HII->get(Hexagon::A2_subri), DefR)
1554*0b57cec5SDimitry Andric                   .add(ExtOp)
1555*0b57cec5SDimitry Andric                   .add(MachineOperand(Ex.Rs));
1556*0b57cec5SDimitry Andric       } else {
1557*0b57cec5SDimitry Andric         // DefR = add(Rb,##EV)
1558*0b57cec5SDimitry Andric         InitI = BuildMI(MBB, At, dl, HII->get(Hexagon::A2_addi), DefR)
1559*0b57cec5SDimitry Andric                   .add(MachineOperand(Ex.Rs))
1560*0b57cec5SDimitry Andric                   .add(ExtOp);
1561*0b57cec5SDimitry Andric       }
1562*0b57cec5SDimitry Andric     } else {
1563*0b57cec5SDimitry Andric       unsigned NewOpc = Ex.Neg ? Hexagon::S4_subi_asl_ri
1564*0b57cec5SDimitry Andric                                : Hexagon::S4_addi_asl_ri;
1565*0b57cec5SDimitry Andric       // DefR = add(##EV,asl(Rb,S))
1566*0b57cec5SDimitry Andric       InitI = BuildMI(MBB, At, dl, HII->get(NewOpc), DefR)
1567*0b57cec5SDimitry Andric                 .add(ExtOp)
1568*0b57cec5SDimitry Andric                 .add(MachineOperand(Ex.Rs))
1569*0b57cec5SDimitry Andric                 .addImm(Ex.S);
1570*0b57cec5SDimitry Andric     }
1571*0b57cec5SDimitry Andric   }
1572*0b57cec5SDimitry Andric 
1573*0b57cec5SDimitry Andric   assert(InitI);
1574*0b57cec5SDimitry Andric   (void)InitI;
1575*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Inserted def in bb#" << MBB.getNumber()
1576*0b57cec5SDimitry Andric                     << " for initializer: " << PrintInit(ExtI, *HRI) << "\n  "
1577*0b57cec5SDimitry Andric                     << *InitI);
1578*0b57cec5SDimitry Andric   return { DefR, 0 };
1579*0b57cec5SDimitry Andric }
1580*0b57cec5SDimitry Andric 
1581*0b57cec5SDimitry Andric // Replace the extender at index Idx with the register ExtR.
1582*0b57cec5SDimitry Andric bool HCE::replaceInstrExact(const ExtDesc &ED, Register ExtR) {
1583*0b57cec5SDimitry Andric   MachineInstr &MI = *ED.UseMI;
1584*0b57cec5SDimitry Andric   MachineBasicBlock &MBB = *MI.getParent();
1585*0b57cec5SDimitry Andric   MachineBasicBlock::iterator At = MI.getIterator();
1586*0b57cec5SDimitry Andric   DebugLoc dl = MI.getDebugLoc();
1587*0b57cec5SDimitry Andric   unsigned ExtOpc = MI.getOpcode();
1588*0b57cec5SDimitry Andric 
1589*0b57cec5SDimitry Andric   // With a few exceptions, direct replacement amounts to creating an
1590*0b57cec5SDimitry Andric   // instruction with a corresponding register opcode, with all operands
1591*0b57cec5SDimitry Andric   // the same, except for the register used in place of the extender.
1592*0b57cec5SDimitry Andric   unsigned RegOpc = getDirectRegReplacement(ExtOpc);
1593*0b57cec5SDimitry Andric 
1594*0b57cec5SDimitry Andric   if (RegOpc == TargetOpcode::REG_SEQUENCE) {
1595*0b57cec5SDimitry Andric     if (ExtOpc == Hexagon::A4_combineri)
1596*0b57cec5SDimitry Andric       BuildMI(MBB, At, dl, HII->get(RegOpc))
1597*0b57cec5SDimitry Andric         .add(MI.getOperand(0))
1598*0b57cec5SDimitry Andric         .add(MI.getOperand(1))
1599*0b57cec5SDimitry Andric         .addImm(Hexagon::isub_hi)
1600*0b57cec5SDimitry Andric         .add(MachineOperand(ExtR))
1601*0b57cec5SDimitry Andric         .addImm(Hexagon::isub_lo);
1602*0b57cec5SDimitry Andric     else if (ExtOpc == Hexagon::A4_combineir)
1603*0b57cec5SDimitry Andric       BuildMI(MBB, At, dl, HII->get(RegOpc))
1604*0b57cec5SDimitry Andric         .add(MI.getOperand(0))
1605*0b57cec5SDimitry Andric         .add(MachineOperand(ExtR))
1606*0b57cec5SDimitry Andric         .addImm(Hexagon::isub_hi)
1607*0b57cec5SDimitry Andric         .add(MI.getOperand(2))
1608*0b57cec5SDimitry Andric         .addImm(Hexagon::isub_lo);
1609*0b57cec5SDimitry Andric     else
1610*0b57cec5SDimitry Andric       llvm_unreachable("Unexpected opcode became REG_SEQUENCE");
1611*0b57cec5SDimitry Andric     MBB.erase(MI);
1612*0b57cec5SDimitry Andric     return true;
1613*0b57cec5SDimitry Andric   }
1614*0b57cec5SDimitry Andric   if (ExtOpc == Hexagon::C2_cmpgei || ExtOpc == Hexagon::C2_cmpgeui) {
1615*0b57cec5SDimitry Andric     unsigned NewOpc = ExtOpc == Hexagon::C2_cmpgei ? Hexagon::C2_cmplt
1616*0b57cec5SDimitry Andric                                                    : Hexagon::C2_cmpltu;
1617*0b57cec5SDimitry Andric     BuildMI(MBB, At, dl, HII->get(NewOpc))
1618*0b57cec5SDimitry Andric       .add(MI.getOperand(0))
1619*0b57cec5SDimitry Andric       .add(MachineOperand(ExtR))
1620*0b57cec5SDimitry Andric       .add(MI.getOperand(1));
1621*0b57cec5SDimitry Andric     MBB.erase(MI);
1622*0b57cec5SDimitry Andric     return true;
1623*0b57cec5SDimitry Andric   }
1624*0b57cec5SDimitry Andric 
1625*0b57cec5SDimitry Andric   if (RegOpc != 0) {
1626*0b57cec5SDimitry Andric     MachineInstrBuilder MIB = BuildMI(MBB, At, dl, HII->get(RegOpc));
1627*0b57cec5SDimitry Andric     unsigned RegN = ED.OpNum;
1628*0b57cec5SDimitry Andric     // Copy all operands except the one that has the extender.
1629*0b57cec5SDimitry Andric     for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
1630*0b57cec5SDimitry Andric       if (i != RegN)
1631*0b57cec5SDimitry Andric         MIB.add(MI.getOperand(i));
1632*0b57cec5SDimitry Andric       else
1633*0b57cec5SDimitry Andric         MIB.add(MachineOperand(ExtR));
1634*0b57cec5SDimitry Andric     }
1635*0b57cec5SDimitry Andric     MIB.cloneMemRefs(MI);
1636*0b57cec5SDimitry Andric     MBB.erase(MI);
1637*0b57cec5SDimitry Andric     return true;
1638*0b57cec5SDimitry Andric   }
1639*0b57cec5SDimitry Andric 
1640*0b57cec5SDimitry Andric   if ((MI.mayLoad() || MI.mayStore()) && !isStoreImmediate(ExtOpc)) {
1641*0b57cec5SDimitry Andric     // For memory instructions, there is an asymmetry in the addressing
1642*0b57cec5SDimitry Andric     // modes. Addressing modes allowing extenders can be replaced with
1643*0b57cec5SDimitry Andric     // addressing modes that use registers, but the order of operands
1644*0b57cec5SDimitry Andric     // (or even their number) may be different.
1645*0b57cec5SDimitry Andric     // Replacements:
1646*0b57cec5SDimitry Andric     //   BaseImmOffset (io)  -> BaseRegOffset (rr)
1647*0b57cec5SDimitry Andric     //   BaseLongOffset (ur) -> BaseRegOffset (rr)
1648*0b57cec5SDimitry Andric     unsigned RegOpc, Shift;
1649*0b57cec5SDimitry Andric     unsigned AM = HII->getAddrMode(MI);
1650*0b57cec5SDimitry Andric     if (AM == HexagonII::BaseImmOffset) {
1651*0b57cec5SDimitry Andric       RegOpc = HII->changeAddrMode_io_rr(ExtOpc);
1652*0b57cec5SDimitry Andric       Shift = 0;
1653*0b57cec5SDimitry Andric     } else if (AM == HexagonII::BaseLongOffset) {
1654*0b57cec5SDimitry Andric       // Loads:  Rd = L4_loadri_ur Rs, S, ##
1655*0b57cec5SDimitry Andric       // Stores: S4_storeri_ur Rs, S, ##, Rt
1656*0b57cec5SDimitry Andric       RegOpc = HII->changeAddrMode_ur_rr(ExtOpc);
1657*0b57cec5SDimitry Andric       Shift = MI.getOperand(MI.mayLoad() ? 2 : 1).getImm();
1658*0b57cec5SDimitry Andric     } else {
1659*0b57cec5SDimitry Andric       llvm_unreachable("Unexpected addressing mode");
1660*0b57cec5SDimitry Andric     }
1661*0b57cec5SDimitry Andric #ifndef NDEBUG
1662*0b57cec5SDimitry Andric     if (RegOpc == -1u) {
1663*0b57cec5SDimitry Andric       dbgs() << "\nExtOpc: " << HII->getName(ExtOpc) << " has no rr version\n";
1664*0b57cec5SDimitry Andric       llvm_unreachable("No corresponding rr instruction");
1665*0b57cec5SDimitry Andric     }
1666*0b57cec5SDimitry Andric #endif
1667*0b57cec5SDimitry Andric 
1668*0b57cec5SDimitry Andric     unsigned BaseP, OffP;
1669*0b57cec5SDimitry Andric     HII->getBaseAndOffsetPosition(MI, BaseP, OffP);
1670*0b57cec5SDimitry Andric 
1671*0b57cec5SDimitry Andric     // Build an rr instruction: (RegOff + RegBase<<0)
1672*0b57cec5SDimitry Andric     MachineInstrBuilder MIB = BuildMI(MBB, At, dl, HII->get(RegOpc));
1673*0b57cec5SDimitry Andric     // First, add the def for loads.
1674*0b57cec5SDimitry Andric     if (MI.mayLoad())
1675*0b57cec5SDimitry Andric       MIB.add(getLoadResultOp(MI));
1676*0b57cec5SDimitry Andric     // Handle possible predication.
1677*0b57cec5SDimitry Andric     if (HII->isPredicated(MI))
1678*0b57cec5SDimitry Andric       MIB.add(getPredicateOp(MI));
1679*0b57cec5SDimitry Andric     // Build the address.
1680*0b57cec5SDimitry Andric     MIB.add(MachineOperand(ExtR));      // RegOff
1681*0b57cec5SDimitry Andric     MIB.add(MI.getOperand(BaseP));      // RegBase
1682*0b57cec5SDimitry Andric     MIB.addImm(Shift);                  // << Shift
1683*0b57cec5SDimitry Andric     // Add the stored value for stores.
1684*0b57cec5SDimitry Andric     if (MI.mayStore())
1685*0b57cec5SDimitry Andric       MIB.add(getStoredValueOp(MI));
1686*0b57cec5SDimitry Andric     MIB.cloneMemRefs(MI);
1687*0b57cec5SDimitry Andric     MBB.erase(MI);
1688*0b57cec5SDimitry Andric     return true;
1689*0b57cec5SDimitry Andric   }
1690*0b57cec5SDimitry Andric 
1691*0b57cec5SDimitry Andric #ifndef NDEBUG
1692*0b57cec5SDimitry Andric   dbgs() << '\n' << MI;
1693*0b57cec5SDimitry Andric #endif
1694*0b57cec5SDimitry Andric   llvm_unreachable("Unhandled exact replacement");
1695*0b57cec5SDimitry Andric   return false;
1696*0b57cec5SDimitry Andric }
1697*0b57cec5SDimitry Andric 
1698*0b57cec5SDimitry Andric // Replace the extender ED with a form corresponding to the initializer ExtI.
1699*0b57cec5SDimitry Andric bool HCE::replaceInstrExpr(const ExtDesc &ED, const ExtenderInit &ExtI,
1700*0b57cec5SDimitry Andric       Register ExtR, int32_t &Diff) {
1701*0b57cec5SDimitry Andric   MachineInstr &MI = *ED.UseMI;
1702*0b57cec5SDimitry Andric   MachineBasicBlock &MBB = *MI.getParent();
1703*0b57cec5SDimitry Andric   MachineBasicBlock::iterator At = MI.getIterator();
1704*0b57cec5SDimitry Andric   DebugLoc dl = MI.getDebugLoc();
1705*0b57cec5SDimitry Andric   unsigned ExtOpc = MI.getOpcode();
1706*0b57cec5SDimitry Andric 
1707*0b57cec5SDimitry Andric   if (ExtOpc == Hexagon::A2_tfrsi) {
1708*0b57cec5SDimitry Andric     // A2_tfrsi is a special case: it's replaced with A2_addi, which introduces
1709*0b57cec5SDimitry Andric     // another range. One range is the one that's common to all tfrsi's uses,
1710*0b57cec5SDimitry Andric     // this one is the range of immediates in A2_addi. When calculating ranges,
1711*0b57cec5SDimitry Andric     // the addi's 16-bit argument was included, so now we need to make it such
1712*0b57cec5SDimitry Andric     // that the produced value is in the range for the uses alone.
1713*0b57cec5SDimitry Andric     // Most of the time, simply adding Diff will make the addi produce exact
1714*0b57cec5SDimitry Andric     // result, but if Diff is outside of the 16-bit range, some adjustment
1715*0b57cec5SDimitry Andric     // will be needed.
1716*0b57cec5SDimitry Andric     unsigned IdxOpc = getRegOffOpcode(ExtOpc);
1717*0b57cec5SDimitry Andric     assert(IdxOpc == Hexagon::A2_addi);
1718*0b57cec5SDimitry Andric 
1719*0b57cec5SDimitry Andric     // Clamp Diff to the 16 bit range.
1720*0b57cec5SDimitry Andric     int32_t D = isInt<16>(Diff) ? Diff : (Diff > 0 ? 32767 : -32768);
1721*0b57cec5SDimitry Andric     if (Diff > 32767) {
1722*0b57cec5SDimitry Andric       // Split Diff into two values: one that is close to min/max int16,
1723*0b57cec5SDimitry Andric       // and the other being the rest, and such that both have the same
1724*0b57cec5SDimitry Andric       // "alignment" as Diff.
1725*0b57cec5SDimitry Andric       uint32_t UD = Diff;
1726*0b57cec5SDimitry Andric       OffsetRange R = getOffsetRange(MI.getOperand(0));
1727*0b57cec5SDimitry Andric       uint32_t A = std::min<uint32_t>(R.Align, 1u << countTrailingZeros(UD));
1728*0b57cec5SDimitry Andric       D &= ~(A-1);
1729*0b57cec5SDimitry Andric     }
1730*0b57cec5SDimitry Andric     BuildMI(MBB, At, dl, HII->get(IdxOpc))
1731*0b57cec5SDimitry Andric       .add(MI.getOperand(0))
1732*0b57cec5SDimitry Andric       .add(MachineOperand(ExtR))
1733*0b57cec5SDimitry Andric       .addImm(D);
1734*0b57cec5SDimitry Andric     Diff -= D;
1735*0b57cec5SDimitry Andric #ifndef NDEBUG
1736*0b57cec5SDimitry Andric     // Make sure the output is within allowable range for uses.
1737*0b57cec5SDimitry Andric     // "Diff" is a difference in the "opposite direction", i.e. Ext - DefV,
1738*0b57cec5SDimitry Andric     // not DefV - Ext, as the getOffsetRange would calculate.
1739*0b57cec5SDimitry Andric     OffsetRange Uses = getOffsetRange(MI.getOperand(0));
1740*0b57cec5SDimitry Andric     if (!Uses.contains(-Diff))
1741*0b57cec5SDimitry Andric       dbgs() << "Diff: " << -Diff << " out of range " << Uses
1742*0b57cec5SDimitry Andric              << " for " << MI;
1743*0b57cec5SDimitry Andric     assert(Uses.contains(-Diff));
1744*0b57cec5SDimitry Andric #endif
1745*0b57cec5SDimitry Andric     MBB.erase(MI);
1746*0b57cec5SDimitry Andric     return true;
1747*0b57cec5SDimitry Andric   }
1748*0b57cec5SDimitry Andric 
1749*0b57cec5SDimitry Andric   const ExtValue &EV = ExtI.first; (void)EV;
1750*0b57cec5SDimitry Andric   const ExtExpr &Ex = ExtI.second; (void)Ex;
1751*0b57cec5SDimitry Andric 
1752*0b57cec5SDimitry Andric   if (ExtOpc == Hexagon::A2_addi || ExtOpc == Hexagon::A2_subri) {
1753*0b57cec5SDimitry Andric     // If addi/subri are replaced with the exactly matching initializer,
1754*0b57cec5SDimitry Andric     // they amount to COPY.
1755*0b57cec5SDimitry Andric     // Check that the initializer is an exact match (for simplicity).
1756*0b57cec5SDimitry Andric #ifndef NDEBUG
1757*0b57cec5SDimitry Andric     bool IsAddi = ExtOpc == Hexagon::A2_addi;
1758*0b57cec5SDimitry Andric     const MachineOperand &RegOp = MI.getOperand(IsAddi ? 1 : 2);
1759*0b57cec5SDimitry Andric     const MachineOperand &ImmOp = MI.getOperand(IsAddi ? 2 : 1);
1760*0b57cec5SDimitry Andric     assert(Ex.Rs == RegOp && EV == ImmOp && Ex.Neg != IsAddi &&
1761*0b57cec5SDimitry Andric            "Initializer mismatch");
1762*0b57cec5SDimitry Andric #endif
1763*0b57cec5SDimitry Andric     BuildMI(MBB, At, dl, HII->get(TargetOpcode::COPY))
1764*0b57cec5SDimitry Andric       .add(MI.getOperand(0))
1765*0b57cec5SDimitry Andric       .add(MachineOperand(ExtR));
1766*0b57cec5SDimitry Andric     Diff = 0;
1767*0b57cec5SDimitry Andric     MBB.erase(MI);
1768*0b57cec5SDimitry Andric     return true;
1769*0b57cec5SDimitry Andric   }
1770*0b57cec5SDimitry Andric   if (ExtOpc == Hexagon::M2_accii || ExtOpc == Hexagon::M2_naccii ||
1771*0b57cec5SDimitry Andric       ExtOpc == Hexagon::S4_addaddi || ExtOpc == Hexagon::S4_subaddi) {
1772*0b57cec5SDimitry Andric     // M2_accii:    add(Rt,add(Rs,V)) (tied)
1773*0b57cec5SDimitry Andric     // M2_naccii:   sub(Rt,add(Rs,V))
1774*0b57cec5SDimitry Andric     // S4_addaddi:  add(Rt,add(Rs,V))
1775*0b57cec5SDimitry Andric     // S4_subaddi:  add(Rt,sub(V,Rs))
1776*0b57cec5SDimitry Andric     // Check that Rs and V match the initializer expression. The Rs+V is the
1777*0b57cec5SDimitry Andric     // combination that is considered "subexpression" for V, although Rx+V
1778*0b57cec5SDimitry Andric     // would also be valid.
1779*0b57cec5SDimitry Andric #ifndef NDEBUG
1780*0b57cec5SDimitry Andric     bool IsSub = ExtOpc == Hexagon::S4_subaddi;
1781*0b57cec5SDimitry Andric     Register Rs = MI.getOperand(IsSub ? 3 : 2);
1782*0b57cec5SDimitry Andric     ExtValue V = MI.getOperand(IsSub ? 2 : 3);
1783*0b57cec5SDimitry Andric     assert(EV == V && Rs == Ex.Rs && IsSub == Ex.Neg && "Initializer mismatch");
1784*0b57cec5SDimitry Andric #endif
1785*0b57cec5SDimitry Andric     unsigned NewOpc = ExtOpc == Hexagon::M2_naccii ? Hexagon::A2_sub
1786*0b57cec5SDimitry Andric                                                    : Hexagon::A2_add;
1787*0b57cec5SDimitry Andric     BuildMI(MBB, At, dl, HII->get(NewOpc))
1788*0b57cec5SDimitry Andric       .add(MI.getOperand(0))
1789*0b57cec5SDimitry Andric       .add(MI.getOperand(1))
1790*0b57cec5SDimitry Andric       .add(MachineOperand(ExtR));
1791*0b57cec5SDimitry Andric     MBB.erase(MI);
1792*0b57cec5SDimitry Andric     return true;
1793*0b57cec5SDimitry Andric   }
1794*0b57cec5SDimitry Andric 
1795*0b57cec5SDimitry Andric   if (MI.mayLoad() || MI.mayStore()) {
1796*0b57cec5SDimitry Andric     unsigned IdxOpc = getRegOffOpcode(ExtOpc);
1797*0b57cec5SDimitry Andric     assert(IdxOpc && "Expecting indexed opcode");
1798*0b57cec5SDimitry Andric     MachineInstrBuilder MIB = BuildMI(MBB, At, dl, HII->get(IdxOpc));
1799*0b57cec5SDimitry Andric     // Construct the new indexed instruction.
1800*0b57cec5SDimitry Andric     // First, add the def for loads.
1801*0b57cec5SDimitry Andric     if (MI.mayLoad())
1802*0b57cec5SDimitry Andric       MIB.add(getLoadResultOp(MI));
1803*0b57cec5SDimitry Andric     // Handle possible predication.
1804*0b57cec5SDimitry Andric     if (HII->isPredicated(MI))
1805*0b57cec5SDimitry Andric       MIB.add(getPredicateOp(MI));
1806*0b57cec5SDimitry Andric     // Build the address.
1807*0b57cec5SDimitry Andric     MIB.add(MachineOperand(ExtR));
1808*0b57cec5SDimitry Andric     MIB.addImm(Diff);
1809*0b57cec5SDimitry Andric     // Add the stored value for stores.
1810*0b57cec5SDimitry Andric     if (MI.mayStore())
1811*0b57cec5SDimitry Andric       MIB.add(getStoredValueOp(MI));
1812*0b57cec5SDimitry Andric     MIB.cloneMemRefs(MI);
1813*0b57cec5SDimitry Andric     MBB.erase(MI);
1814*0b57cec5SDimitry Andric     return true;
1815*0b57cec5SDimitry Andric   }
1816*0b57cec5SDimitry Andric 
1817*0b57cec5SDimitry Andric #ifndef NDEBUG
1818*0b57cec5SDimitry Andric   dbgs() << '\n' << PrintInit(ExtI, *HRI) << "  " << MI;
1819*0b57cec5SDimitry Andric #endif
1820*0b57cec5SDimitry Andric   llvm_unreachable("Unhandled expr replacement");
1821*0b57cec5SDimitry Andric   return false;
1822*0b57cec5SDimitry Andric }
1823*0b57cec5SDimitry Andric 
1824*0b57cec5SDimitry Andric bool HCE::replaceInstr(unsigned Idx, Register ExtR, const ExtenderInit &ExtI) {
1825*0b57cec5SDimitry Andric   if (ReplaceLimit.getNumOccurrences()) {
1826*0b57cec5SDimitry Andric     if (ReplaceLimit <= ReplaceCounter)
1827*0b57cec5SDimitry Andric       return false;
1828*0b57cec5SDimitry Andric     ++ReplaceCounter;
1829*0b57cec5SDimitry Andric   }
1830*0b57cec5SDimitry Andric   const ExtDesc &ED = Extenders[Idx];
1831*0b57cec5SDimitry Andric   assert((!ED.IsDef || ED.Rd.Reg != 0) && "Missing Rd for def");
1832*0b57cec5SDimitry Andric   const ExtValue &DefV = ExtI.first;
1833*0b57cec5SDimitry Andric   assert(ExtRoot(ExtValue(ED)) == ExtRoot(DefV) && "Extender root mismatch");
1834*0b57cec5SDimitry Andric   const ExtExpr &DefEx = ExtI.second;
1835*0b57cec5SDimitry Andric 
1836*0b57cec5SDimitry Andric   ExtValue EV(ED);
1837*0b57cec5SDimitry Andric   int32_t Diff = EV.Offset - DefV.Offset;
1838*0b57cec5SDimitry Andric   const MachineInstr &MI = *ED.UseMI;
1839*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << __func__ << " Idx:" << Idx << " ExtR:"
1840*0b57cec5SDimitry Andric                     << PrintRegister(ExtR, *HRI) << " Diff:" << Diff << '\n');
1841*0b57cec5SDimitry Andric 
1842*0b57cec5SDimitry Andric   // These two addressing modes must be converted into indexed forms
1843*0b57cec5SDimitry Andric   // regardless of what the initializer looks like.
1844*0b57cec5SDimitry Andric   bool IsAbs = false, IsAbsSet = false;
1845*0b57cec5SDimitry Andric   if (MI.mayLoad() || MI.mayStore()) {
1846*0b57cec5SDimitry Andric     unsigned AM = HII->getAddrMode(MI);
1847*0b57cec5SDimitry Andric     IsAbs = AM == HexagonII::Absolute;
1848*0b57cec5SDimitry Andric     IsAbsSet = AM == HexagonII::AbsoluteSet;
1849*0b57cec5SDimitry Andric   }
1850*0b57cec5SDimitry Andric 
1851*0b57cec5SDimitry Andric   // If it's a def, remember all operands that need to be updated.
1852*0b57cec5SDimitry Andric   // If ED is a def, and Diff is not 0, then all uses of the register Rd
1853*0b57cec5SDimitry Andric   // defined by ED must be in the form (Rd, imm), i.e. the immediate offset
1854*0b57cec5SDimitry Andric   // must follow the Rd in the operand list.
1855*0b57cec5SDimitry Andric   std::vector<std::pair<MachineInstr*,unsigned>> RegOps;
1856*0b57cec5SDimitry Andric   if (ED.IsDef && Diff != 0) {
1857*0b57cec5SDimitry Andric     for (MachineOperand &Op : MRI->use_operands(ED.Rd.Reg)) {
1858*0b57cec5SDimitry Andric       MachineInstr &UI = *Op.getParent();
1859*0b57cec5SDimitry Andric       RegOps.push_back({&UI, getOperandIndex(UI, Op)});
1860*0b57cec5SDimitry Andric     }
1861*0b57cec5SDimitry Andric   }
1862*0b57cec5SDimitry Andric 
1863*0b57cec5SDimitry Andric   // Replace the instruction.
1864*0b57cec5SDimitry Andric   bool Replaced = false;
1865*0b57cec5SDimitry Andric   if (Diff == 0 && DefEx.trivial() && !IsAbs && !IsAbsSet)
1866*0b57cec5SDimitry Andric     Replaced = replaceInstrExact(ED, ExtR);
1867*0b57cec5SDimitry Andric   else
1868*0b57cec5SDimitry Andric     Replaced = replaceInstrExpr(ED, ExtI, ExtR, Diff);
1869*0b57cec5SDimitry Andric 
1870*0b57cec5SDimitry Andric   if (Diff != 0 && Replaced && ED.IsDef) {
1871*0b57cec5SDimitry Andric     // Update offsets of the def's uses.
1872*0b57cec5SDimitry Andric     for (std::pair<MachineInstr*,unsigned> P : RegOps) {
1873*0b57cec5SDimitry Andric       unsigned J = P.second;
1874*0b57cec5SDimitry Andric       assert(P.first->getNumOperands() > J+1 &&
1875*0b57cec5SDimitry Andric              P.first->getOperand(J+1).isImm());
1876*0b57cec5SDimitry Andric       MachineOperand &ImmOp = P.first->getOperand(J+1);
1877*0b57cec5SDimitry Andric       ImmOp.setImm(ImmOp.getImm() + Diff);
1878*0b57cec5SDimitry Andric     }
1879*0b57cec5SDimitry Andric     // If it was an absolute-set instruction, the "set" part has been removed.
1880*0b57cec5SDimitry Andric     // ExtR will now be the register with the extended value, and since all
1881*0b57cec5SDimitry Andric     // users of Rd have been updated, all that needs to be done is to replace
1882*0b57cec5SDimitry Andric     // Rd with ExtR.
1883*0b57cec5SDimitry Andric     if (IsAbsSet) {
1884*0b57cec5SDimitry Andric       assert(ED.Rd.Sub == 0 && ExtR.Sub == 0);
1885*0b57cec5SDimitry Andric       MRI->replaceRegWith(ED.Rd.Reg, ExtR.Reg);
1886*0b57cec5SDimitry Andric     }
1887*0b57cec5SDimitry Andric   }
1888*0b57cec5SDimitry Andric 
1889*0b57cec5SDimitry Andric   return Replaced;
1890*0b57cec5SDimitry Andric }
1891*0b57cec5SDimitry Andric 
1892*0b57cec5SDimitry Andric bool HCE::replaceExtenders(const AssignmentMap &IMap) {
1893*0b57cec5SDimitry Andric   LocDefList Defs;
1894*0b57cec5SDimitry Andric   bool Changed = false;
1895*0b57cec5SDimitry Andric 
1896*0b57cec5SDimitry Andric   for (const std::pair<ExtenderInit,IndexList> &P : IMap) {
1897*0b57cec5SDimitry Andric     const IndexList &Idxs = P.second;
1898*0b57cec5SDimitry Andric     if (Idxs.size() < CountThreshold)
1899*0b57cec5SDimitry Andric       continue;
1900*0b57cec5SDimitry Andric 
1901*0b57cec5SDimitry Andric     Defs.clear();
1902*0b57cec5SDimitry Andric     calculatePlacement(P.first, Idxs, Defs);
1903*0b57cec5SDimitry Andric     for (const std::pair<Loc,IndexList> &Q : Defs) {
1904*0b57cec5SDimitry Andric       Register DefR = insertInitializer(Q.first, P.first);
1905*0b57cec5SDimitry Andric       NewRegs.push_back(DefR.Reg);
1906*0b57cec5SDimitry Andric       for (unsigned I : Q.second)
1907*0b57cec5SDimitry Andric         Changed |= replaceInstr(I, DefR, P.first);
1908*0b57cec5SDimitry Andric     }
1909*0b57cec5SDimitry Andric   }
1910*0b57cec5SDimitry Andric   return Changed;
1911*0b57cec5SDimitry Andric }
1912*0b57cec5SDimitry Andric 
1913*0b57cec5SDimitry Andric unsigned HCE::getOperandIndex(const MachineInstr &MI,
1914*0b57cec5SDimitry Andric       const MachineOperand &Op) const {
1915*0b57cec5SDimitry Andric   for (unsigned i = 0, n = MI.getNumOperands(); i != n; ++i)
1916*0b57cec5SDimitry Andric     if (&MI.getOperand(i) == &Op)
1917*0b57cec5SDimitry Andric       return i;
1918*0b57cec5SDimitry Andric   llvm_unreachable("Not an operand of MI");
1919*0b57cec5SDimitry Andric }
1920*0b57cec5SDimitry Andric 
1921*0b57cec5SDimitry Andric const MachineOperand &HCE::getPredicateOp(const MachineInstr &MI) const {
1922*0b57cec5SDimitry Andric   assert(HII->isPredicated(MI));
1923*0b57cec5SDimitry Andric   for (const MachineOperand &Op : MI.operands()) {
1924*0b57cec5SDimitry Andric     if (!Op.isReg() || !Op.isUse() ||
1925*0b57cec5SDimitry Andric         MRI->getRegClass(Op.getReg()) != &Hexagon::PredRegsRegClass)
1926*0b57cec5SDimitry Andric       continue;
1927*0b57cec5SDimitry Andric     assert(Op.getSubReg() == 0 && "Predicate register with a subregister");
1928*0b57cec5SDimitry Andric     return Op;
1929*0b57cec5SDimitry Andric   }
1930*0b57cec5SDimitry Andric   llvm_unreachable("Predicate operand not found");
1931*0b57cec5SDimitry Andric }
1932*0b57cec5SDimitry Andric 
1933*0b57cec5SDimitry Andric const MachineOperand &HCE::getLoadResultOp(const MachineInstr &MI) const {
1934*0b57cec5SDimitry Andric   assert(MI.mayLoad());
1935*0b57cec5SDimitry Andric   return MI.getOperand(0);
1936*0b57cec5SDimitry Andric }
1937*0b57cec5SDimitry Andric 
1938*0b57cec5SDimitry Andric const MachineOperand &HCE::getStoredValueOp(const MachineInstr &MI) const {
1939*0b57cec5SDimitry Andric   assert(MI.mayStore());
1940*0b57cec5SDimitry Andric   return MI.getOperand(MI.getNumExplicitOperands()-1);
1941*0b57cec5SDimitry Andric }
1942*0b57cec5SDimitry Andric 
1943*0b57cec5SDimitry Andric bool HCE::runOnMachineFunction(MachineFunction &MF) {
1944*0b57cec5SDimitry Andric   if (skipFunction(MF.getFunction()))
1945*0b57cec5SDimitry Andric     return false;
1946*0b57cec5SDimitry Andric   if (MF.getFunction().hasPersonalityFn()) {
1947*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << getPassName() << ": skipping " << MF.getName()
1948*0b57cec5SDimitry Andric                       << " due to exception handling\n");
1949*0b57cec5SDimitry Andric     return false;
1950*0b57cec5SDimitry Andric   }
1951*0b57cec5SDimitry Andric   LLVM_DEBUG(MF.print(dbgs() << "Before " << getPassName() << '\n', nullptr));
1952*0b57cec5SDimitry Andric 
1953*0b57cec5SDimitry Andric   HII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
1954*0b57cec5SDimitry Andric   HRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
1955*0b57cec5SDimitry Andric   MDT = &getAnalysis<MachineDominatorTree>();
1956*0b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
1957*0b57cec5SDimitry Andric   AssignmentMap IMap;
1958*0b57cec5SDimitry Andric 
1959*0b57cec5SDimitry Andric   collect(MF);
1960*0b57cec5SDimitry Andric   llvm::sort(Extenders, [this](const ExtDesc &A, const ExtDesc &B) {
1961*0b57cec5SDimitry Andric     ExtValue VA(A), VB(B);
1962*0b57cec5SDimitry Andric     if (VA != VB)
1963*0b57cec5SDimitry Andric       return VA < VB;
1964*0b57cec5SDimitry Andric     const MachineInstr *MA = A.UseMI;
1965*0b57cec5SDimitry Andric     const MachineInstr *MB = B.UseMI;
1966*0b57cec5SDimitry Andric     if (MA == MB) {
1967*0b57cec5SDimitry Andric       // If it's the same instruction, compare operand numbers.
1968*0b57cec5SDimitry Andric       return A.OpNum < B.OpNum;
1969*0b57cec5SDimitry Andric     }
1970*0b57cec5SDimitry Andric 
1971*0b57cec5SDimitry Andric     const MachineBasicBlock *BA = MA->getParent();
1972*0b57cec5SDimitry Andric     const MachineBasicBlock *BB = MB->getParent();
1973*0b57cec5SDimitry Andric     assert(BA->getNumber() != -1 && BB->getNumber() != -1);
1974*0b57cec5SDimitry Andric     if (BA != BB)
1975*0b57cec5SDimitry Andric       return BA->getNumber() < BB->getNumber();
1976*0b57cec5SDimitry Andric     return MDT->dominates(MA, MB);
1977*0b57cec5SDimitry Andric   });
1978*0b57cec5SDimitry Andric 
1979*0b57cec5SDimitry Andric   bool Changed = false;
1980*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Collected " << Extenders.size() << " extenders\n");
1981*0b57cec5SDimitry Andric   for (unsigned I = 0, E = Extenders.size(); I != E; ) {
1982*0b57cec5SDimitry Andric     unsigned B = I;
1983*0b57cec5SDimitry Andric     const ExtRoot &T = Extenders[B].getOp();
1984*0b57cec5SDimitry Andric     while (I != E && ExtRoot(Extenders[I].getOp()) == T)
1985*0b57cec5SDimitry Andric       ++I;
1986*0b57cec5SDimitry Andric 
1987*0b57cec5SDimitry Andric     IMap.clear();
1988*0b57cec5SDimitry Andric     assignInits(T, B, I, IMap);
1989*0b57cec5SDimitry Andric     Changed |= replaceExtenders(IMap);
1990*0b57cec5SDimitry Andric   }
1991*0b57cec5SDimitry Andric 
1992*0b57cec5SDimitry Andric   LLVM_DEBUG({
1993*0b57cec5SDimitry Andric     if (Changed)
1994*0b57cec5SDimitry Andric       MF.print(dbgs() << "After " << getPassName() << '\n', nullptr);
1995*0b57cec5SDimitry Andric     else
1996*0b57cec5SDimitry Andric       dbgs() << "No changes\n";
1997*0b57cec5SDimitry Andric   });
1998*0b57cec5SDimitry Andric   return Changed;
1999*0b57cec5SDimitry Andric }
2000*0b57cec5SDimitry Andric 
2001*0b57cec5SDimitry Andric FunctionPass *llvm::createHexagonConstExtenders() {
2002*0b57cec5SDimitry Andric   return new HexagonConstExtenders();
2003*0b57cec5SDimitry Andric }
2004