xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonConstPropagation.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- HexagonConstPropagation.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 #define DEBUG_TYPE "hcp"
10*0b57cec5SDimitry Andric 
11*0b57cec5SDimitry Andric #include "HexagonInstrInfo.h"
12*0b57cec5SDimitry Andric #include "HexagonRegisterInfo.h"
13*0b57cec5SDimitry Andric #include "HexagonSubtarget.h"
14*0b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h"
15*0b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
16*0b57cec5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
17*0b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h"
18*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
19*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
20*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
21*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
22*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
23*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
24*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
25*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
26*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
27*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
28*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
29*0b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
30*0b57cec5SDimitry Andric #include "llvm/IR/Type.h"
31*0b57cec5SDimitry Andric #include "llvm/Pass.h"
32*0b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
33*0b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
34*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
35*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
36*0b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
37*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
38*0b57cec5SDimitry Andric #include <cassert>
39*0b57cec5SDimitry Andric #include <cstdint>
40*0b57cec5SDimitry Andric #include <cstring>
41*0b57cec5SDimitry Andric #include <iterator>
42*0b57cec5SDimitry Andric #include <map>
43*0b57cec5SDimitry Andric #include <queue>
44*0b57cec5SDimitry Andric #include <set>
45*0b57cec5SDimitry Andric #include <utility>
46*0b57cec5SDimitry Andric #include <vector>
47*0b57cec5SDimitry Andric 
48*0b57cec5SDimitry Andric using namespace llvm;
49*0b57cec5SDimitry Andric 
50*0b57cec5SDimitry Andric namespace {
51*0b57cec5SDimitry Andric 
52*0b57cec5SDimitry Andric   // Properties of a value that are tracked by the propagation.
53*0b57cec5SDimitry Andric   // A property that is marked as present (i.e. bit is set) dentes that the
54*0b57cec5SDimitry Andric   // value is known (proven) to have this property. Not all combinations
55*0b57cec5SDimitry Andric   // of bits make sense, for example Zero and NonZero are mutually exclusive,
56*0b57cec5SDimitry Andric   // but on the other hand, Zero implies Finite. In this case, whenever
57*0b57cec5SDimitry Andric   // the Zero property is present, Finite should also be present.
58*0b57cec5SDimitry Andric   class ConstantProperties {
59*0b57cec5SDimitry Andric   public:
60*0b57cec5SDimitry Andric     enum {
61*0b57cec5SDimitry Andric       Unknown   = 0x0000,
62*0b57cec5SDimitry Andric       Zero      = 0x0001,
63*0b57cec5SDimitry Andric       NonZero   = 0x0002,
64*0b57cec5SDimitry Andric       Finite    = 0x0004,
65*0b57cec5SDimitry Andric       Infinity  = 0x0008,
66*0b57cec5SDimitry Andric       NaN       = 0x0010,
67*0b57cec5SDimitry Andric       SignedZero = 0x0020,
68*0b57cec5SDimitry Andric       NumericProperties = (Zero|NonZero|Finite|Infinity|NaN|SignedZero),
69*0b57cec5SDimitry Andric       PosOrZero       = 0x0100,
70*0b57cec5SDimitry Andric       NegOrZero       = 0x0200,
71*0b57cec5SDimitry Andric       SignProperties  = (PosOrZero|NegOrZero),
72*0b57cec5SDimitry Andric       Everything      = (NumericProperties|SignProperties)
73*0b57cec5SDimitry Andric     };
74*0b57cec5SDimitry Andric 
75*0b57cec5SDimitry Andric     // For a given constant, deduce the set of trackable properties that this
76*0b57cec5SDimitry Andric     // constant has.
77*0b57cec5SDimitry Andric     static uint32_t deduce(const Constant *C);
78*0b57cec5SDimitry Andric   };
79*0b57cec5SDimitry Andric 
80*0b57cec5SDimitry Andric   // A representation of a register as it can appear in a MachineOperand,
81*0b57cec5SDimitry Andric   // i.e. a pair register:subregister.
82*0b57cec5SDimitry Andric 
83*0b57cec5SDimitry Andric   // FIXME: Use TargetInstrInfo::RegSubRegPair. Also duplicated in
84*0b57cec5SDimitry Andric   // HexagonGenPredicate
85*0b57cec5SDimitry Andric   struct RegisterSubReg {
86*0b57cec5SDimitry Andric     unsigned Reg, SubReg;
87*0b57cec5SDimitry Andric 
88*0b57cec5SDimitry Andric     explicit RegisterSubReg(unsigned R, unsigned SR = 0) : Reg(R), SubReg(SR) {}
89*0b57cec5SDimitry Andric     explicit RegisterSubReg(const MachineOperand &MO)
90*0b57cec5SDimitry Andric       : Reg(MO.getReg()), SubReg(MO.getSubReg()) {}
91*0b57cec5SDimitry Andric 
92*0b57cec5SDimitry Andric     void print(const TargetRegisterInfo *TRI = nullptr) const {
93*0b57cec5SDimitry Andric       dbgs() << printReg(Reg, TRI, SubReg);
94*0b57cec5SDimitry Andric     }
95*0b57cec5SDimitry Andric 
96*0b57cec5SDimitry Andric     bool operator== (const RegisterSubReg &R) const {
97*0b57cec5SDimitry Andric       return (Reg == R.Reg) && (SubReg == R.SubReg);
98*0b57cec5SDimitry Andric     }
99*0b57cec5SDimitry Andric   };
100*0b57cec5SDimitry Andric 
101*0b57cec5SDimitry Andric   // Lattice cell, based on that was described in the W-Z paper on constant
102*0b57cec5SDimitry Andric   // propagation.
103*0b57cec5SDimitry Andric   // Latice cell will be allowed to hold multiple constant values. While
104*0b57cec5SDimitry Andric   // multiple values would normally indicate "bottom", we can still derive
105*0b57cec5SDimitry Andric   // some useful information from them. For example, comparison X > 0
106*0b57cec5SDimitry Andric   // could be folded if all the values in the cell associated with X are
107*0b57cec5SDimitry Andric   // positive.
108*0b57cec5SDimitry Andric   class LatticeCell {
109*0b57cec5SDimitry Andric   private:
110*0b57cec5SDimitry Andric     enum { Normal, Top, Bottom };
111*0b57cec5SDimitry Andric 
112*0b57cec5SDimitry Andric     static const unsigned MaxCellSize = 4;
113*0b57cec5SDimitry Andric 
114*0b57cec5SDimitry Andric     unsigned Kind:2;
115*0b57cec5SDimitry Andric     unsigned Size:3;
116*0b57cec5SDimitry Andric     unsigned IsSpecial:1;
117*0b57cec5SDimitry Andric     unsigned :0;
118*0b57cec5SDimitry Andric 
119*0b57cec5SDimitry Andric   public:
120*0b57cec5SDimitry Andric     union {
121*0b57cec5SDimitry Andric       uint32_t Properties;
122*0b57cec5SDimitry Andric       const Constant *Value;
123*0b57cec5SDimitry Andric       const Constant *Values[MaxCellSize];
124*0b57cec5SDimitry Andric     };
125*0b57cec5SDimitry Andric 
126*0b57cec5SDimitry Andric     LatticeCell() : Kind(Top), Size(0), IsSpecial(false) {
127*0b57cec5SDimitry Andric       for (unsigned i = 0; i < MaxCellSize; ++i)
128*0b57cec5SDimitry Andric         Values[i] = nullptr;
129*0b57cec5SDimitry Andric     }
130*0b57cec5SDimitry Andric 
131*0b57cec5SDimitry Andric     bool meet(const LatticeCell &L);
132*0b57cec5SDimitry Andric     bool add(const Constant *C);
133*0b57cec5SDimitry Andric     bool add(uint32_t Property);
134*0b57cec5SDimitry Andric     uint32_t properties() const;
135*0b57cec5SDimitry Andric     unsigned size() const { return Size; }
136*0b57cec5SDimitry Andric 
137*0b57cec5SDimitry Andric     LatticeCell &operator= (const LatticeCell &L) {
138*0b57cec5SDimitry Andric       if (this != &L) {
139*0b57cec5SDimitry Andric         // This memcpy also copies Properties (when L.Size == 0).
140*0b57cec5SDimitry Andric         uint32_t N = L.IsSpecial ? sizeof L.Properties
141*0b57cec5SDimitry Andric                                  : L.Size*sizeof(const Constant*);
142*0b57cec5SDimitry Andric         memcpy(Values, L.Values, N);
143*0b57cec5SDimitry Andric         Kind = L.Kind;
144*0b57cec5SDimitry Andric         Size = L.Size;
145*0b57cec5SDimitry Andric         IsSpecial = L.IsSpecial;
146*0b57cec5SDimitry Andric       }
147*0b57cec5SDimitry Andric       return *this;
148*0b57cec5SDimitry Andric     }
149*0b57cec5SDimitry Andric 
150*0b57cec5SDimitry Andric     bool isSingle() const { return size() == 1; }
151*0b57cec5SDimitry Andric     bool isProperty() const { return IsSpecial; }
152*0b57cec5SDimitry Andric     bool isTop() const { return Kind == Top; }
153*0b57cec5SDimitry Andric     bool isBottom() const { return Kind == Bottom; }
154*0b57cec5SDimitry Andric 
155*0b57cec5SDimitry Andric     bool setBottom() {
156*0b57cec5SDimitry Andric       bool Changed = (Kind != Bottom);
157*0b57cec5SDimitry Andric       Kind = Bottom;
158*0b57cec5SDimitry Andric       Size = 0;
159*0b57cec5SDimitry Andric       IsSpecial = false;
160*0b57cec5SDimitry Andric       return Changed;
161*0b57cec5SDimitry Andric     }
162*0b57cec5SDimitry Andric 
163*0b57cec5SDimitry Andric     void print(raw_ostream &os) const;
164*0b57cec5SDimitry Andric 
165*0b57cec5SDimitry Andric   private:
166*0b57cec5SDimitry Andric     void setProperty() {
167*0b57cec5SDimitry Andric       IsSpecial = true;
168*0b57cec5SDimitry Andric       Size = 0;
169*0b57cec5SDimitry Andric       Kind = Normal;
170*0b57cec5SDimitry Andric     }
171*0b57cec5SDimitry Andric 
172*0b57cec5SDimitry Andric     bool convertToProperty();
173*0b57cec5SDimitry Andric   };
174*0b57cec5SDimitry Andric 
175*0b57cec5SDimitry Andric #ifndef NDEBUG
176*0b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &os, const LatticeCell &L) {
177*0b57cec5SDimitry Andric     L.print(os);
178*0b57cec5SDimitry Andric     return os;
179*0b57cec5SDimitry Andric   }
180*0b57cec5SDimitry Andric #endif
181*0b57cec5SDimitry Andric 
182*0b57cec5SDimitry Andric   class MachineConstEvaluator;
183*0b57cec5SDimitry Andric 
184*0b57cec5SDimitry Andric   class MachineConstPropagator {
185*0b57cec5SDimitry Andric   public:
186*0b57cec5SDimitry Andric     MachineConstPropagator(MachineConstEvaluator &E) : MCE(E) {
187*0b57cec5SDimitry Andric       Bottom.setBottom();
188*0b57cec5SDimitry Andric     }
189*0b57cec5SDimitry Andric 
190*0b57cec5SDimitry Andric     // Mapping: vreg -> cell
191*0b57cec5SDimitry Andric     // The keys are registers _without_ subregisters. This won't allow
192*0b57cec5SDimitry Andric     // definitions in the form of "vreg:subreg = ...". Such definitions
193*0b57cec5SDimitry Andric     // would be questionable from the point of view of SSA, since the "vreg"
194*0b57cec5SDimitry Andric     // could not be initialized in its entirety (specifically, an instruction
195*0b57cec5SDimitry Andric     // defining the "other part" of "vreg" would also count as a definition
196*0b57cec5SDimitry Andric     // of "vreg", which would violate the SSA).
197*0b57cec5SDimitry Andric     // If a value of a pair vreg:subreg needs to be obtained, the cell for
198*0b57cec5SDimitry Andric     // "vreg" needs to be looked up, and then the value of subregister "subreg"
199*0b57cec5SDimitry Andric     // needs to be evaluated.
200*0b57cec5SDimitry Andric     class CellMap {
201*0b57cec5SDimitry Andric     public:
202*0b57cec5SDimitry Andric       CellMap() {
203*0b57cec5SDimitry Andric         assert(Top.isTop());
204*0b57cec5SDimitry Andric         Bottom.setBottom();
205*0b57cec5SDimitry Andric       }
206*0b57cec5SDimitry Andric 
207*0b57cec5SDimitry Andric       void clear() { Map.clear(); }
208*0b57cec5SDimitry Andric 
209*0b57cec5SDimitry Andric       bool has(unsigned R) const {
210*0b57cec5SDimitry Andric         // All non-virtual registers are considered "bottom".
211*0b57cec5SDimitry Andric         if (!TargetRegisterInfo::isVirtualRegister(R))
212*0b57cec5SDimitry Andric           return true;
213*0b57cec5SDimitry Andric         MapType::const_iterator F = Map.find(R);
214*0b57cec5SDimitry Andric         return F != Map.end();
215*0b57cec5SDimitry Andric       }
216*0b57cec5SDimitry Andric 
217*0b57cec5SDimitry Andric       const LatticeCell &get(unsigned R) const {
218*0b57cec5SDimitry Andric         if (!TargetRegisterInfo::isVirtualRegister(R))
219*0b57cec5SDimitry Andric           return Bottom;
220*0b57cec5SDimitry Andric         MapType::const_iterator F = Map.find(R);
221*0b57cec5SDimitry Andric         if (F != Map.end())
222*0b57cec5SDimitry Andric           return F->second;
223*0b57cec5SDimitry Andric         return Top;
224*0b57cec5SDimitry Andric       }
225*0b57cec5SDimitry Andric 
226*0b57cec5SDimitry Andric       // Invalidates any const references.
227*0b57cec5SDimitry Andric       void update(unsigned R, const LatticeCell &L) {
228*0b57cec5SDimitry Andric         Map[R] = L;
229*0b57cec5SDimitry Andric       }
230*0b57cec5SDimitry Andric 
231*0b57cec5SDimitry Andric       void print(raw_ostream &os, const TargetRegisterInfo &TRI) const;
232*0b57cec5SDimitry Andric 
233*0b57cec5SDimitry Andric     private:
234*0b57cec5SDimitry Andric       using MapType = std::map<unsigned, LatticeCell>;
235*0b57cec5SDimitry Andric 
236*0b57cec5SDimitry Andric       MapType Map;
237*0b57cec5SDimitry Andric       // To avoid creating "top" entries, return a const reference to
238*0b57cec5SDimitry Andric       // this cell in "get". Also, have a "Bottom" cell to return from
239*0b57cec5SDimitry Andric       // get when a value of a physical register is requested.
240*0b57cec5SDimitry Andric       LatticeCell Top, Bottom;
241*0b57cec5SDimitry Andric 
242*0b57cec5SDimitry Andric     public:
243*0b57cec5SDimitry Andric       using const_iterator = MapType::const_iterator;
244*0b57cec5SDimitry Andric 
245*0b57cec5SDimitry Andric       const_iterator begin() const { return Map.begin(); }
246*0b57cec5SDimitry Andric       const_iterator end() const { return Map.end(); }
247*0b57cec5SDimitry Andric     };
248*0b57cec5SDimitry Andric 
249*0b57cec5SDimitry Andric     bool run(MachineFunction &MF);
250*0b57cec5SDimitry Andric 
251*0b57cec5SDimitry Andric   private:
252*0b57cec5SDimitry Andric     void visitPHI(const MachineInstr &PN);
253*0b57cec5SDimitry Andric     void visitNonBranch(const MachineInstr &MI);
254*0b57cec5SDimitry Andric     void visitBranchesFrom(const MachineInstr &BrI);
255*0b57cec5SDimitry Andric     void visitUsesOf(unsigned R);
256*0b57cec5SDimitry Andric     bool computeBlockSuccessors(const MachineBasicBlock *MB,
257*0b57cec5SDimitry Andric           SetVector<const MachineBasicBlock*> &Targets);
258*0b57cec5SDimitry Andric     void removeCFGEdge(MachineBasicBlock *From, MachineBasicBlock *To);
259*0b57cec5SDimitry Andric 
260*0b57cec5SDimitry Andric     void propagate(MachineFunction &MF);
261*0b57cec5SDimitry Andric     bool rewrite(MachineFunction &MF);
262*0b57cec5SDimitry Andric 
263*0b57cec5SDimitry Andric     MachineRegisterInfo      *MRI;
264*0b57cec5SDimitry Andric     MachineConstEvaluator    &MCE;
265*0b57cec5SDimitry Andric 
266*0b57cec5SDimitry Andric     using CFGEdge = std::pair<unsigned, unsigned>;
267*0b57cec5SDimitry Andric     using SetOfCFGEdge = std::set<CFGEdge>;
268*0b57cec5SDimitry Andric     using SetOfInstr = std::set<const MachineInstr *>;
269*0b57cec5SDimitry Andric     using QueueOfCFGEdge = std::queue<CFGEdge>;
270*0b57cec5SDimitry Andric 
271*0b57cec5SDimitry Andric     LatticeCell     Bottom;
272*0b57cec5SDimitry Andric     CellMap         Cells;
273*0b57cec5SDimitry Andric     SetOfCFGEdge    EdgeExec;
274*0b57cec5SDimitry Andric     SetOfInstr      InstrExec;
275*0b57cec5SDimitry Andric     QueueOfCFGEdge  FlowQ;
276*0b57cec5SDimitry Andric   };
277*0b57cec5SDimitry Andric 
278*0b57cec5SDimitry Andric   // The "evaluator/rewriter" of machine instructions. This is an abstract
279*0b57cec5SDimitry Andric   // base class that provides the interface that the propagator will use,
280*0b57cec5SDimitry Andric   // as well as some helper functions that are target-independent.
281*0b57cec5SDimitry Andric   class MachineConstEvaluator {
282*0b57cec5SDimitry Andric   public:
283*0b57cec5SDimitry Andric     MachineConstEvaluator(MachineFunction &Fn)
284*0b57cec5SDimitry Andric       : TRI(*Fn.getSubtarget().getRegisterInfo()),
285*0b57cec5SDimitry Andric         MF(Fn), CX(Fn.getFunction().getContext()) {}
286*0b57cec5SDimitry Andric     virtual ~MachineConstEvaluator() = default;
287*0b57cec5SDimitry Andric 
288*0b57cec5SDimitry Andric     // The required interface:
289*0b57cec5SDimitry Andric     // - A set of three "evaluate" functions. Each returns "true" if the
290*0b57cec5SDimitry Andric     //       computation succeeded, "false" otherwise.
291*0b57cec5SDimitry Andric     //   (1) Given an instruction MI, and the map with input values "Inputs",
292*0b57cec5SDimitry Andric     //       compute the set of output values "Outputs". An example of when
293*0b57cec5SDimitry Andric     //       the computation can "fail" is if MI is not an instruction that
294*0b57cec5SDimitry Andric     //       is recognized by the evaluator.
295*0b57cec5SDimitry Andric     //   (2) Given a register R (as reg:subreg), compute the cell that
296*0b57cec5SDimitry Andric     //       corresponds to the "subreg" part of the given register.
297*0b57cec5SDimitry Andric     //   (3) Given a branch instruction BrI, compute the set of target blocks.
298*0b57cec5SDimitry Andric     //       If the branch can fall-through, add null (0) to the list of
299*0b57cec5SDimitry Andric     //       possible targets.
300*0b57cec5SDimitry Andric     // - A function "rewrite", that given the cell map after propagation,
301*0b57cec5SDimitry Andric     //   could rewrite instruction MI in a more beneficial form. Return
302*0b57cec5SDimitry Andric     //   "true" if a change has been made, "false" otherwise.
303*0b57cec5SDimitry Andric     using CellMap = MachineConstPropagator::CellMap;
304*0b57cec5SDimitry Andric     virtual bool evaluate(const MachineInstr &MI, const CellMap &Inputs,
305*0b57cec5SDimitry Andric                           CellMap &Outputs) = 0;
306*0b57cec5SDimitry Andric     virtual bool evaluate(const RegisterSubReg &R, const LatticeCell &SrcC,
307*0b57cec5SDimitry Andric                           LatticeCell &Result) = 0;
308*0b57cec5SDimitry Andric     virtual bool evaluate(const MachineInstr &BrI, const CellMap &Inputs,
309*0b57cec5SDimitry Andric                           SetVector<const MachineBasicBlock*> &Targets,
310*0b57cec5SDimitry Andric                           bool &CanFallThru) = 0;
311*0b57cec5SDimitry Andric     virtual bool rewrite(MachineInstr &MI, const CellMap &Inputs) = 0;
312*0b57cec5SDimitry Andric 
313*0b57cec5SDimitry Andric     const TargetRegisterInfo &TRI;
314*0b57cec5SDimitry Andric 
315*0b57cec5SDimitry Andric   protected:
316*0b57cec5SDimitry Andric     MachineFunction &MF;
317*0b57cec5SDimitry Andric     LLVMContext     &CX;
318*0b57cec5SDimitry Andric 
319*0b57cec5SDimitry Andric     struct Comparison {
320*0b57cec5SDimitry Andric       enum {
321*0b57cec5SDimitry Andric         Unk = 0x00,
322*0b57cec5SDimitry Andric         EQ  = 0x01,
323*0b57cec5SDimitry Andric         NE  = 0x02,
324*0b57cec5SDimitry Andric         L   = 0x04, // Less-than property.
325*0b57cec5SDimitry Andric         G   = 0x08, // Greater-than property.
326*0b57cec5SDimitry Andric         U   = 0x40, // Unsigned property.
327*0b57cec5SDimitry Andric         LTs = L,
328*0b57cec5SDimitry Andric         LEs = L | EQ,
329*0b57cec5SDimitry Andric         GTs = G,
330*0b57cec5SDimitry Andric         GEs = G | EQ,
331*0b57cec5SDimitry Andric         LTu = L      | U,
332*0b57cec5SDimitry Andric         LEu = L | EQ | U,
333*0b57cec5SDimitry Andric         GTu = G      | U,
334*0b57cec5SDimitry Andric         GEu = G | EQ | U
335*0b57cec5SDimitry Andric       };
336*0b57cec5SDimitry Andric 
337*0b57cec5SDimitry Andric       static uint32_t negate(uint32_t Cmp) {
338*0b57cec5SDimitry Andric         if (Cmp == EQ)
339*0b57cec5SDimitry Andric           return NE;
340*0b57cec5SDimitry Andric         if (Cmp == NE)
341*0b57cec5SDimitry Andric           return EQ;
342*0b57cec5SDimitry Andric         assert((Cmp & (L|G)) != (L|G));
343*0b57cec5SDimitry Andric         return Cmp ^ (L|G);
344*0b57cec5SDimitry Andric       }
345*0b57cec5SDimitry Andric     };
346*0b57cec5SDimitry Andric 
347*0b57cec5SDimitry Andric     // Helper functions.
348*0b57cec5SDimitry Andric 
349*0b57cec5SDimitry Andric     bool getCell(const RegisterSubReg &R, const CellMap &Inputs, LatticeCell &RC);
350*0b57cec5SDimitry Andric     bool constToInt(const Constant *C, APInt &Val) const;
351*0b57cec5SDimitry Andric     bool constToFloat(const Constant *C, APFloat &Val) const;
352*0b57cec5SDimitry Andric     const ConstantInt *intToConst(const APInt &Val) const;
353*0b57cec5SDimitry Andric 
354*0b57cec5SDimitry Andric     // Compares.
355*0b57cec5SDimitry Andric     bool evaluateCMPrr(uint32_t Cmp, const RegisterSubReg &R1, const RegisterSubReg &R2,
356*0b57cec5SDimitry Andric           const CellMap &Inputs, bool &Result);
357*0b57cec5SDimitry Andric     bool evaluateCMPri(uint32_t Cmp, const RegisterSubReg &R1, const APInt &A2,
358*0b57cec5SDimitry Andric           const CellMap &Inputs, bool &Result);
359*0b57cec5SDimitry Andric     bool evaluateCMPrp(uint32_t Cmp, const RegisterSubReg &R1, uint64_t Props2,
360*0b57cec5SDimitry Andric           const CellMap &Inputs, bool &Result);
361*0b57cec5SDimitry Andric     bool evaluateCMPii(uint32_t Cmp, const APInt &A1, const APInt &A2,
362*0b57cec5SDimitry Andric           bool &Result);
363*0b57cec5SDimitry Andric     bool evaluateCMPpi(uint32_t Cmp, uint32_t Props, const APInt &A2,
364*0b57cec5SDimitry Andric           bool &Result);
365*0b57cec5SDimitry Andric     bool evaluateCMPpp(uint32_t Cmp, uint32_t Props1, uint32_t Props2,
366*0b57cec5SDimitry Andric           bool &Result);
367*0b57cec5SDimitry Andric 
368*0b57cec5SDimitry Andric     bool evaluateCOPY(const RegisterSubReg &R1, const CellMap &Inputs,
369*0b57cec5SDimitry Andric           LatticeCell &Result);
370*0b57cec5SDimitry Andric 
371*0b57cec5SDimitry Andric     // Logical operations.
372*0b57cec5SDimitry Andric     bool evaluateANDrr(const RegisterSubReg &R1, const RegisterSubReg &R2,
373*0b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
374*0b57cec5SDimitry Andric     bool evaluateANDri(const RegisterSubReg &R1, const APInt &A2,
375*0b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
376*0b57cec5SDimitry Andric     bool evaluateANDii(const APInt &A1, const APInt &A2, APInt &Result);
377*0b57cec5SDimitry Andric     bool evaluateORrr(const RegisterSubReg &R1, const RegisterSubReg &R2,
378*0b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
379*0b57cec5SDimitry Andric     bool evaluateORri(const RegisterSubReg &R1, const APInt &A2,
380*0b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
381*0b57cec5SDimitry Andric     bool evaluateORii(const APInt &A1, const APInt &A2, APInt &Result);
382*0b57cec5SDimitry Andric     bool evaluateXORrr(const RegisterSubReg &R1, const RegisterSubReg &R2,
383*0b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
384*0b57cec5SDimitry Andric     bool evaluateXORri(const RegisterSubReg &R1, const APInt &A2,
385*0b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
386*0b57cec5SDimitry Andric     bool evaluateXORii(const APInt &A1, const APInt &A2, APInt &Result);
387*0b57cec5SDimitry Andric 
388*0b57cec5SDimitry Andric     // Extensions.
389*0b57cec5SDimitry Andric     bool evaluateZEXTr(const RegisterSubReg &R1, unsigned Width, unsigned Bits,
390*0b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
391*0b57cec5SDimitry Andric     bool evaluateZEXTi(const APInt &A1, unsigned Width, unsigned Bits,
392*0b57cec5SDimitry Andric           APInt &Result);
393*0b57cec5SDimitry Andric     bool evaluateSEXTr(const RegisterSubReg &R1, unsigned Width, unsigned Bits,
394*0b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
395*0b57cec5SDimitry Andric     bool evaluateSEXTi(const APInt &A1, unsigned Width, unsigned Bits,
396*0b57cec5SDimitry Andric           APInt &Result);
397*0b57cec5SDimitry Andric 
398*0b57cec5SDimitry Andric     // Leading/trailing bits.
399*0b57cec5SDimitry Andric     bool evaluateCLBr(const RegisterSubReg &R1, bool Zeros, bool Ones,
400*0b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
401*0b57cec5SDimitry Andric     bool evaluateCLBi(const APInt &A1, bool Zeros, bool Ones, APInt &Result);
402*0b57cec5SDimitry Andric     bool evaluateCTBr(const RegisterSubReg &R1, bool Zeros, bool Ones,
403*0b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
404*0b57cec5SDimitry Andric     bool evaluateCTBi(const APInt &A1, bool Zeros, bool Ones, APInt &Result);
405*0b57cec5SDimitry Andric 
406*0b57cec5SDimitry Andric     // Bitfield extract.
407*0b57cec5SDimitry Andric     bool evaluateEXTRACTr(const RegisterSubReg &R1, unsigned Width, unsigned Bits,
408*0b57cec5SDimitry Andric           unsigned Offset, bool Signed, const CellMap &Inputs,
409*0b57cec5SDimitry Andric           LatticeCell &Result);
410*0b57cec5SDimitry Andric     bool evaluateEXTRACTi(const APInt &A1, unsigned Bits, unsigned Offset,
411*0b57cec5SDimitry Andric           bool Signed, APInt &Result);
412*0b57cec5SDimitry Andric     // Vector operations.
413*0b57cec5SDimitry Andric     bool evaluateSplatr(const RegisterSubReg &R1, unsigned Bits, unsigned Count,
414*0b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
415*0b57cec5SDimitry Andric     bool evaluateSplati(const APInt &A1, unsigned Bits, unsigned Count,
416*0b57cec5SDimitry Andric           APInt &Result);
417*0b57cec5SDimitry Andric   };
418*0b57cec5SDimitry Andric 
419*0b57cec5SDimitry Andric } // end anonymous namespace
420*0b57cec5SDimitry Andric 
421*0b57cec5SDimitry Andric uint32_t ConstantProperties::deduce(const Constant *C) {
422*0b57cec5SDimitry Andric   if (isa<ConstantInt>(C)) {
423*0b57cec5SDimitry Andric     const ConstantInt *CI = cast<ConstantInt>(C);
424*0b57cec5SDimitry Andric     if (CI->isZero())
425*0b57cec5SDimitry Andric       return Zero | PosOrZero | NegOrZero | Finite;
426*0b57cec5SDimitry Andric     uint32_t Props = (NonZero | Finite);
427*0b57cec5SDimitry Andric     if (CI->isNegative())
428*0b57cec5SDimitry Andric       return Props | NegOrZero;
429*0b57cec5SDimitry Andric     return Props | PosOrZero;
430*0b57cec5SDimitry Andric   }
431*0b57cec5SDimitry Andric 
432*0b57cec5SDimitry Andric   if (isa<ConstantFP>(C)) {
433*0b57cec5SDimitry Andric     const ConstantFP *CF = cast<ConstantFP>(C);
434*0b57cec5SDimitry Andric     uint32_t Props = CF->isNegative() ? (NegOrZero|NonZero)
435*0b57cec5SDimitry Andric                                       : PosOrZero;
436*0b57cec5SDimitry Andric     if (CF->isZero())
437*0b57cec5SDimitry Andric       return (Props & ~NumericProperties) | (Zero|Finite);
438*0b57cec5SDimitry Andric     Props = (Props & ~NumericProperties) | NonZero;
439*0b57cec5SDimitry Andric     if (CF->isNaN())
440*0b57cec5SDimitry Andric       return (Props & ~NumericProperties) | NaN;
441*0b57cec5SDimitry Andric     const APFloat &Val = CF->getValueAPF();
442*0b57cec5SDimitry Andric     if (Val.isInfinity())
443*0b57cec5SDimitry Andric       return (Props & ~NumericProperties) | Infinity;
444*0b57cec5SDimitry Andric     Props |= Finite;
445*0b57cec5SDimitry Andric     return Props;
446*0b57cec5SDimitry Andric   }
447*0b57cec5SDimitry Andric 
448*0b57cec5SDimitry Andric   return Unknown;
449*0b57cec5SDimitry Andric }
450*0b57cec5SDimitry Andric 
451*0b57cec5SDimitry Andric // Convert a cell from a set of specific values to a cell that tracks
452*0b57cec5SDimitry Andric // properties.
453*0b57cec5SDimitry Andric bool LatticeCell::convertToProperty() {
454*0b57cec5SDimitry Andric   if (isProperty())
455*0b57cec5SDimitry Andric     return false;
456*0b57cec5SDimitry Andric   // Corner case: converting a fresh (top) cell to "special".
457*0b57cec5SDimitry Andric   // This can happen, when adding a property to a top cell.
458*0b57cec5SDimitry Andric   uint32_t Everything = ConstantProperties::Everything;
459*0b57cec5SDimitry Andric   uint32_t Ps = !isTop() ? properties()
460*0b57cec5SDimitry Andric                          : Everything;
461*0b57cec5SDimitry Andric   if (Ps != ConstantProperties::Unknown) {
462*0b57cec5SDimitry Andric     Properties = Ps;
463*0b57cec5SDimitry Andric     setProperty();
464*0b57cec5SDimitry Andric   } else {
465*0b57cec5SDimitry Andric     setBottom();
466*0b57cec5SDimitry Andric   }
467*0b57cec5SDimitry Andric   return true;
468*0b57cec5SDimitry Andric }
469*0b57cec5SDimitry Andric 
470*0b57cec5SDimitry Andric #ifndef NDEBUG
471*0b57cec5SDimitry Andric void LatticeCell::print(raw_ostream &os) const {
472*0b57cec5SDimitry Andric   if (isProperty()) {
473*0b57cec5SDimitry Andric     os << "{ ";
474*0b57cec5SDimitry Andric     uint32_t Ps = properties();
475*0b57cec5SDimitry Andric     if (Ps & ConstantProperties::Zero)
476*0b57cec5SDimitry Andric       os << "zero ";
477*0b57cec5SDimitry Andric     if (Ps & ConstantProperties::NonZero)
478*0b57cec5SDimitry Andric       os << "nonzero ";
479*0b57cec5SDimitry Andric     if (Ps & ConstantProperties::Finite)
480*0b57cec5SDimitry Andric       os << "finite ";
481*0b57cec5SDimitry Andric     if (Ps & ConstantProperties::Infinity)
482*0b57cec5SDimitry Andric       os << "infinity ";
483*0b57cec5SDimitry Andric     if (Ps & ConstantProperties::NaN)
484*0b57cec5SDimitry Andric       os << "nan ";
485*0b57cec5SDimitry Andric     if (Ps & ConstantProperties::PosOrZero)
486*0b57cec5SDimitry Andric       os << "poz ";
487*0b57cec5SDimitry Andric     if (Ps & ConstantProperties::NegOrZero)
488*0b57cec5SDimitry Andric       os << "nez ";
489*0b57cec5SDimitry Andric     os << '}';
490*0b57cec5SDimitry Andric     return;
491*0b57cec5SDimitry Andric   }
492*0b57cec5SDimitry Andric 
493*0b57cec5SDimitry Andric   os << "{ ";
494*0b57cec5SDimitry Andric   if (isBottom()) {
495*0b57cec5SDimitry Andric     os << "bottom";
496*0b57cec5SDimitry Andric   } else if (isTop()) {
497*0b57cec5SDimitry Andric     os << "top";
498*0b57cec5SDimitry Andric   } else {
499*0b57cec5SDimitry Andric     for (unsigned i = 0; i < size(); ++i) {
500*0b57cec5SDimitry Andric       const Constant *C = Values[i];
501*0b57cec5SDimitry Andric       if (i != 0)
502*0b57cec5SDimitry Andric         os << ", ";
503*0b57cec5SDimitry Andric       C->print(os);
504*0b57cec5SDimitry Andric     }
505*0b57cec5SDimitry Andric   }
506*0b57cec5SDimitry Andric   os << " }";
507*0b57cec5SDimitry Andric }
508*0b57cec5SDimitry Andric #endif
509*0b57cec5SDimitry Andric 
510*0b57cec5SDimitry Andric // "Meet" operation on two cells. This is the key of the propagation
511*0b57cec5SDimitry Andric // algorithm.
512*0b57cec5SDimitry Andric bool LatticeCell::meet(const LatticeCell &L) {
513*0b57cec5SDimitry Andric   bool Changed = false;
514*0b57cec5SDimitry Andric   if (L.isBottom())
515*0b57cec5SDimitry Andric     Changed = setBottom();
516*0b57cec5SDimitry Andric   if (isBottom() || L.isTop())
517*0b57cec5SDimitry Andric     return Changed;
518*0b57cec5SDimitry Andric   if (isTop()) {
519*0b57cec5SDimitry Andric     *this = L;
520*0b57cec5SDimitry Andric     // L can be neither Top nor Bottom, so *this must have changed.
521*0b57cec5SDimitry Andric     return true;
522*0b57cec5SDimitry Andric   }
523*0b57cec5SDimitry Andric 
524*0b57cec5SDimitry Andric   // Top/bottom cases covered. Need to integrate L's set into ours.
525*0b57cec5SDimitry Andric   if (L.isProperty())
526*0b57cec5SDimitry Andric     return add(L.properties());
527*0b57cec5SDimitry Andric   for (unsigned i = 0; i < L.size(); ++i) {
528*0b57cec5SDimitry Andric     const Constant *LC = L.Values[i];
529*0b57cec5SDimitry Andric     Changed |= add(LC);
530*0b57cec5SDimitry Andric   }
531*0b57cec5SDimitry Andric   return Changed;
532*0b57cec5SDimitry Andric }
533*0b57cec5SDimitry Andric 
534*0b57cec5SDimitry Andric // Add a new constant to the cell. This is actually where the cell update
535*0b57cec5SDimitry Andric // happens. If a cell has room for more constants, the new constant is added.
536*0b57cec5SDimitry Andric // Otherwise, the cell is converted to a "property" cell (i.e. a cell that
537*0b57cec5SDimitry Andric // will track properties of the associated values, and not the values
538*0b57cec5SDimitry Andric // themselves. Care is taken to handle special cases, like "bottom", etc.
539*0b57cec5SDimitry Andric bool LatticeCell::add(const Constant *LC) {
540*0b57cec5SDimitry Andric   assert(LC);
541*0b57cec5SDimitry Andric   if (isBottom())
542*0b57cec5SDimitry Andric     return false;
543*0b57cec5SDimitry Andric 
544*0b57cec5SDimitry Andric   if (!isProperty()) {
545*0b57cec5SDimitry Andric     // Cell is not special. Try to add the constant here first,
546*0b57cec5SDimitry Andric     // if there is room.
547*0b57cec5SDimitry Andric     unsigned Index = 0;
548*0b57cec5SDimitry Andric     while (Index < Size) {
549*0b57cec5SDimitry Andric       const Constant *C = Values[Index];
550*0b57cec5SDimitry Andric       // If the constant is already here, no change is needed.
551*0b57cec5SDimitry Andric       if (C == LC)
552*0b57cec5SDimitry Andric         return false;
553*0b57cec5SDimitry Andric       Index++;
554*0b57cec5SDimitry Andric     }
555*0b57cec5SDimitry Andric     if (Index < MaxCellSize) {
556*0b57cec5SDimitry Andric       Values[Index] = LC;
557*0b57cec5SDimitry Andric       Kind = Normal;
558*0b57cec5SDimitry Andric       Size++;
559*0b57cec5SDimitry Andric       return true;
560*0b57cec5SDimitry Andric     }
561*0b57cec5SDimitry Andric   }
562*0b57cec5SDimitry Andric 
563*0b57cec5SDimitry Andric   bool Changed = false;
564*0b57cec5SDimitry Andric 
565*0b57cec5SDimitry Andric   // This cell is special, or is not special, but is full. After this
566*0b57cec5SDimitry Andric   // it will be special.
567*0b57cec5SDimitry Andric   Changed = convertToProperty();
568*0b57cec5SDimitry Andric   uint32_t Ps = properties();
569*0b57cec5SDimitry Andric   uint32_t NewPs = Ps & ConstantProperties::deduce(LC);
570*0b57cec5SDimitry Andric   if (NewPs == ConstantProperties::Unknown) {
571*0b57cec5SDimitry Andric     setBottom();
572*0b57cec5SDimitry Andric     return true;
573*0b57cec5SDimitry Andric   }
574*0b57cec5SDimitry Andric   if (Ps != NewPs) {
575*0b57cec5SDimitry Andric     Properties = NewPs;
576*0b57cec5SDimitry Andric     Changed = true;
577*0b57cec5SDimitry Andric   }
578*0b57cec5SDimitry Andric   return Changed;
579*0b57cec5SDimitry Andric }
580*0b57cec5SDimitry Andric 
581*0b57cec5SDimitry Andric // Add a property to the cell. This will force the cell to become a property-
582*0b57cec5SDimitry Andric // tracking cell.
583*0b57cec5SDimitry Andric bool LatticeCell::add(uint32_t Property) {
584*0b57cec5SDimitry Andric   bool Changed = convertToProperty();
585*0b57cec5SDimitry Andric   uint32_t Ps = properties();
586*0b57cec5SDimitry Andric   if (Ps == (Ps & Property))
587*0b57cec5SDimitry Andric     return Changed;
588*0b57cec5SDimitry Andric   Properties = Property & Ps;
589*0b57cec5SDimitry Andric   return true;
590*0b57cec5SDimitry Andric }
591*0b57cec5SDimitry Andric 
592*0b57cec5SDimitry Andric // Return the properties of the values in the cell. This is valid for any
593*0b57cec5SDimitry Andric // cell, and does not alter the cell itself.
594*0b57cec5SDimitry Andric uint32_t LatticeCell::properties() const {
595*0b57cec5SDimitry Andric   if (isProperty())
596*0b57cec5SDimitry Andric     return Properties;
597*0b57cec5SDimitry Andric   assert(!isTop() && "Should not call this for a top cell");
598*0b57cec5SDimitry Andric   if (isBottom())
599*0b57cec5SDimitry Andric     return ConstantProperties::Unknown;
600*0b57cec5SDimitry Andric 
601*0b57cec5SDimitry Andric   assert(size() > 0 && "Empty cell");
602*0b57cec5SDimitry Andric   uint32_t Ps = ConstantProperties::deduce(Values[0]);
603*0b57cec5SDimitry Andric   for (unsigned i = 1; i < size(); ++i) {
604*0b57cec5SDimitry Andric     if (Ps == ConstantProperties::Unknown)
605*0b57cec5SDimitry Andric       break;
606*0b57cec5SDimitry Andric     Ps &= ConstantProperties::deduce(Values[i]);
607*0b57cec5SDimitry Andric   }
608*0b57cec5SDimitry Andric   return Ps;
609*0b57cec5SDimitry Andric }
610*0b57cec5SDimitry Andric 
611*0b57cec5SDimitry Andric #ifndef NDEBUG
612*0b57cec5SDimitry Andric void MachineConstPropagator::CellMap::print(raw_ostream &os,
613*0b57cec5SDimitry Andric       const TargetRegisterInfo &TRI) const {
614*0b57cec5SDimitry Andric   for (auto &I : Map)
615*0b57cec5SDimitry Andric     dbgs() << "  " << printReg(I.first, &TRI) << " -> " << I.second << '\n';
616*0b57cec5SDimitry Andric }
617*0b57cec5SDimitry Andric #endif
618*0b57cec5SDimitry Andric 
619*0b57cec5SDimitry Andric void MachineConstPropagator::visitPHI(const MachineInstr &PN) {
620*0b57cec5SDimitry Andric   const MachineBasicBlock *MB = PN.getParent();
621*0b57cec5SDimitry Andric   unsigned MBN = MB->getNumber();
622*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Visiting FI(" << printMBBReference(*MB) << "): " << PN);
623*0b57cec5SDimitry Andric 
624*0b57cec5SDimitry Andric   const MachineOperand &MD = PN.getOperand(0);
625*0b57cec5SDimitry Andric   RegisterSubReg DefR(MD);
626*0b57cec5SDimitry Andric   assert(TargetRegisterInfo::isVirtualRegister(DefR.Reg));
627*0b57cec5SDimitry Andric 
628*0b57cec5SDimitry Andric   bool Changed = false;
629*0b57cec5SDimitry Andric 
630*0b57cec5SDimitry Andric   // If the def has a sub-register, set the corresponding cell to "bottom".
631*0b57cec5SDimitry Andric   if (DefR.SubReg) {
632*0b57cec5SDimitry Andric Bottomize:
633*0b57cec5SDimitry Andric     const LatticeCell &T = Cells.get(DefR.Reg);
634*0b57cec5SDimitry Andric     Changed = !T.isBottom();
635*0b57cec5SDimitry Andric     Cells.update(DefR.Reg, Bottom);
636*0b57cec5SDimitry Andric     if (Changed)
637*0b57cec5SDimitry Andric       visitUsesOf(DefR.Reg);
638*0b57cec5SDimitry Andric     return;
639*0b57cec5SDimitry Andric   }
640*0b57cec5SDimitry Andric 
641*0b57cec5SDimitry Andric   LatticeCell DefC = Cells.get(DefR.Reg);
642*0b57cec5SDimitry Andric 
643*0b57cec5SDimitry Andric   for (unsigned i = 1, n = PN.getNumOperands(); i < n; i += 2) {
644*0b57cec5SDimitry Andric     const MachineBasicBlock *PB = PN.getOperand(i+1).getMBB();
645*0b57cec5SDimitry Andric     unsigned PBN = PB->getNumber();
646*0b57cec5SDimitry Andric     if (!EdgeExec.count(CFGEdge(PBN, MBN))) {
647*0b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "  edge " << printMBBReference(*PB) << "->"
648*0b57cec5SDimitry Andric                         << printMBBReference(*MB) << " not executable\n");
649*0b57cec5SDimitry Andric       continue;
650*0b57cec5SDimitry Andric     }
651*0b57cec5SDimitry Andric     const MachineOperand &SO = PN.getOperand(i);
652*0b57cec5SDimitry Andric     RegisterSubReg UseR(SO);
653*0b57cec5SDimitry Andric     // If the input is not a virtual register, we don't really know what
654*0b57cec5SDimitry Andric     // value it holds.
655*0b57cec5SDimitry Andric     if (!TargetRegisterInfo::isVirtualRegister(UseR.Reg))
656*0b57cec5SDimitry Andric       goto Bottomize;
657*0b57cec5SDimitry Andric     // If there is no cell for an input register, it means top.
658*0b57cec5SDimitry Andric     if (!Cells.has(UseR.Reg))
659*0b57cec5SDimitry Andric       continue;
660*0b57cec5SDimitry Andric 
661*0b57cec5SDimitry Andric     LatticeCell SrcC;
662*0b57cec5SDimitry Andric     bool Eval = MCE.evaluate(UseR, Cells.get(UseR.Reg), SrcC);
663*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "  edge from " << printMBBReference(*PB) << ": "
664*0b57cec5SDimitry Andric                       << printReg(UseR.Reg, &MCE.TRI, UseR.SubReg) << SrcC
665*0b57cec5SDimitry Andric                       << '\n');
666*0b57cec5SDimitry Andric     Changed |= Eval ? DefC.meet(SrcC)
667*0b57cec5SDimitry Andric                     : DefC.setBottom();
668*0b57cec5SDimitry Andric     Cells.update(DefR.Reg, DefC);
669*0b57cec5SDimitry Andric     if (DefC.isBottom())
670*0b57cec5SDimitry Andric       break;
671*0b57cec5SDimitry Andric   }
672*0b57cec5SDimitry Andric   if (Changed)
673*0b57cec5SDimitry Andric     visitUsesOf(DefR.Reg);
674*0b57cec5SDimitry Andric }
675*0b57cec5SDimitry Andric 
676*0b57cec5SDimitry Andric void MachineConstPropagator::visitNonBranch(const MachineInstr &MI) {
677*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Visiting MI(" << printMBBReference(*MI.getParent())
678*0b57cec5SDimitry Andric                     << "): " << MI);
679*0b57cec5SDimitry Andric   CellMap Outputs;
680*0b57cec5SDimitry Andric   bool Eval = MCE.evaluate(MI, Cells, Outputs);
681*0b57cec5SDimitry Andric   LLVM_DEBUG({
682*0b57cec5SDimitry Andric     if (Eval) {
683*0b57cec5SDimitry Andric       dbgs() << "  outputs:";
684*0b57cec5SDimitry Andric       for (auto &I : Outputs)
685*0b57cec5SDimitry Andric         dbgs() << ' ' << I.second;
686*0b57cec5SDimitry Andric       dbgs() << '\n';
687*0b57cec5SDimitry Andric     }
688*0b57cec5SDimitry Andric   });
689*0b57cec5SDimitry Andric 
690*0b57cec5SDimitry Andric   // Update outputs. If the value was not computed, set all the
691*0b57cec5SDimitry Andric   // def cells to bottom.
692*0b57cec5SDimitry Andric   for (const MachineOperand &MO : MI.operands()) {
693*0b57cec5SDimitry Andric     if (!MO.isReg() || !MO.isDef())
694*0b57cec5SDimitry Andric       continue;
695*0b57cec5SDimitry Andric     RegisterSubReg DefR(MO);
696*0b57cec5SDimitry Andric     // Only track virtual registers.
697*0b57cec5SDimitry Andric     if (!TargetRegisterInfo::isVirtualRegister(DefR.Reg))
698*0b57cec5SDimitry Andric       continue;
699*0b57cec5SDimitry Andric     bool Changed = false;
700*0b57cec5SDimitry Andric     // If the evaluation failed, set cells for all output registers to bottom.
701*0b57cec5SDimitry Andric     if (!Eval) {
702*0b57cec5SDimitry Andric       const LatticeCell &T = Cells.get(DefR.Reg);
703*0b57cec5SDimitry Andric       Changed = !T.isBottom();
704*0b57cec5SDimitry Andric       Cells.update(DefR.Reg, Bottom);
705*0b57cec5SDimitry Andric     } else {
706*0b57cec5SDimitry Andric       // Find the corresponding cell in the computed outputs.
707*0b57cec5SDimitry Andric       // If it's not there, go on to the next def.
708*0b57cec5SDimitry Andric       if (!Outputs.has(DefR.Reg))
709*0b57cec5SDimitry Andric         continue;
710*0b57cec5SDimitry Andric       LatticeCell RC = Cells.get(DefR.Reg);
711*0b57cec5SDimitry Andric       Changed = RC.meet(Outputs.get(DefR.Reg));
712*0b57cec5SDimitry Andric       Cells.update(DefR.Reg, RC);
713*0b57cec5SDimitry Andric     }
714*0b57cec5SDimitry Andric     if (Changed)
715*0b57cec5SDimitry Andric       visitUsesOf(DefR.Reg);
716*0b57cec5SDimitry Andric   }
717*0b57cec5SDimitry Andric }
718*0b57cec5SDimitry Andric 
719*0b57cec5SDimitry Andric // Starting at a given branch, visit remaining branches in the block.
720*0b57cec5SDimitry Andric // Traverse over the subsequent branches for as long as the preceding one
721*0b57cec5SDimitry Andric // can fall through. Add all the possible targets to the flow work queue,
722*0b57cec5SDimitry Andric // including the potential fall-through to the layout-successor block.
723*0b57cec5SDimitry Andric void MachineConstPropagator::visitBranchesFrom(const MachineInstr &BrI) {
724*0b57cec5SDimitry Andric   const MachineBasicBlock &B = *BrI.getParent();
725*0b57cec5SDimitry Andric   unsigned MBN = B.getNumber();
726*0b57cec5SDimitry Andric   MachineBasicBlock::const_iterator It = BrI.getIterator();
727*0b57cec5SDimitry Andric   MachineBasicBlock::const_iterator End = B.end();
728*0b57cec5SDimitry Andric 
729*0b57cec5SDimitry Andric   SetVector<const MachineBasicBlock*> Targets;
730*0b57cec5SDimitry Andric   bool EvalOk = true, FallsThru = true;
731*0b57cec5SDimitry Andric   while (It != End) {
732*0b57cec5SDimitry Andric     const MachineInstr &MI = *It;
733*0b57cec5SDimitry Andric     InstrExec.insert(&MI);
734*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Visiting " << (EvalOk ? "BR" : "br") << "("
735*0b57cec5SDimitry Andric                       << printMBBReference(B) << "): " << MI);
736*0b57cec5SDimitry Andric     // Do not evaluate subsequent branches if the evaluation of any of the
737*0b57cec5SDimitry Andric     // previous branches failed. Keep iterating over the branches only
738*0b57cec5SDimitry Andric     // to mark them as executable.
739*0b57cec5SDimitry Andric     EvalOk = EvalOk && MCE.evaluate(MI, Cells, Targets, FallsThru);
740*0b57cec5SDimitry Andric     if (!EvalOk)
741*0b57cec5SDimitry Andric       FallsThru = true;
742*0b57cec5SDimitry Andric     if (!FallsThru)
743*0b57cec5SDimitry Andric       break;
744*0b57cec5SDimitry Andric     ++It;
745*0b57cec5SDimitry Andric   }
746*0b57cec5SDimitry Andric 
747*0b57cec5SDimitry Andric   if (EvalOk) {
748*0b57cec5SDimitry Andric     // Need to add all CFG successors that lead to EH landing pads.
749*0b57cec5SDimitry Andric     // There won't be explicit branches to these blocks, but they must
750*0b57cec5SDimitry Andric     // be processed.
751*0b57cec5SDimitry Andric     for (const MachineBasicBlock *SB : B.successors()) {
752*0b57cec5SDimitry Andric       if (SB->isEHPad())
753*0b57cec5SDimitry Andric         Targets.insert(SB);
754*0b57cec5SDimitry Andric     }
755*0b57cec5SDimitry Andric     if (FallsThru) {
756*0b57cec5SDimitry Andric       const MachineFunction &MF = *B.getParent();
757*0b57cec5SDimitry Andric       MachineFunction::const_iterator BI = B.getIterator();
758*0b57cec5SDimitry Andric       MachineFunction::const_iterator Next = std::next(BI);
759*0b57cec5SDimitry Andric       if (Next != MF.end())
760*0b57cec5SDimitry Andric         Targets.insert(&*Next);
761*0b57cec5SDimitry Andric     }
762*0b57cec5SDimitry Andric   } else {
763*0b57cec5SDimitry Andric     // If the evaluation of the branches failed, make "Targets" to be the
764*0b57cec5SDimitry Andric     // set of all successors of the block from the CFG.
765*0b57cec5SDimitry Andric     // If the evaluation succeeded for all visited branches, then if the
766*0b57cec5SDimitry Andric     // last one set "FallsThru", then add an edge to the layout successor
767*0b57cec5SDimitry Andric     // to the targets.
768*0b57cec5SDimitry Andric     Targets.clear();
769*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "  failed to evaluate a branch...adding all CFG "
770*0b57cec5SDimitry Andric                          "successors\n");
771*0b57cec5SDimitry Andric     for (const MachineBasicBlock *SB : B.successors())
772*0b57cec5SDimitry Andric       Targets.insert(SB);
773*0b57cec5SDimitry Andric   }
774*0b57cec5SDimitry Andric 
775*0b57cec5SDimitry Andric   for (const MachineBasicBlock *TB : Targets) {
776*0b57cec5SDimitry Andric     unsigned TBN = TB->getNumber();
777*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "  pushing edge " << printMBBReference(B) << " -> "
778*0b57cec5SDimitry Andric                       << printMBBReference(*TB) << "\n");
779*0b57cec5SDimitry Andric     FlowQ.push(CFGEdge(MBN, TBN));
780*0b57cec5SDimitry Andric   }
781*0b57cec5SDimitry Andric }
782*0b57cec5SDimitry Andric 
783*0b57cec5SDimitry Andric void MachineConstPropagator::visitUsesOf(unsigned Reg) {
784*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Visiting uses of " << printReg(Reg, &MCE.TRI)
785*0b57cec5SDimitry Andric                     << Cells.get(Reg) << '\n');
786*0b57cec5SDimitry Andric   for (MachineInstr &MI : MRI->use_nodbg_instructions(Reg)) {
787*0b57cec5SDimitry Andric     // Do not process non-executable instructions. They can become exceutable
788*0b57cec5SDimitry Andric     // later (via a flow-edge in the work queue). In such case, the instruc-
789*0b57cec5SDimitry Andric     // tion will be visited at that time.
790*0b57cec5SDimitry Andric     if (!InstrExec.count(&MI))
791*0b57cec5SDimitry Andric       continue;
792*0b57cec5SDimitry Andric     if (MI.isPHI())
793*0b57cec5SDimitry Andric       visitPHI(MI);
794*0b57cec5SDimitry Andric     else if (!MI.isBranch())
795*0b57cec5SDimitry Andric       visitNonBranch(MI);
796*0b57cec5SDimitry Andric     else
797*0b57cec5SDimitry Andric       visitBranchesFrom(MI);
798*0b57cec5SDimitry Andric   }
799*0b57cec5SDimitry Andric }
800*0b57cec5SDimitry Andric 
801*0b57cec5SDimitry Andric bool MachineConstPropagator::computeBlockSuccessors(const MachineBasicBlock *MB,
802*0b57cec5SDimitry Andric       SetVector<const MachineBasicBlock*> &Targets) {
803*0b57cec5SDimitry Andric   MachineBasicBlock::const_iterator FirstBr = MB->end();
804*0b57cec5SDimitry Andric   for (const MachineInstr &MI : *MB) {
805*0b57cec5SDimitry Andric     if (MI.isDebugInstr())
806*0b57cec5SDimitry Andric       continue;
807*0b57cec5SDimitry Andric     if (MI.isBranch()) {
808*0b57cec5SDimitry Andric       FirstBr = MI.getIterator();
809*0b57cec5SDimitry Andric       break;
810*0b57cec5SDimitry Andric     }
811*0b57cec5SDimitry Andric   }
812*0b57cec5SDimitry Andric 
813*0b57cec5SDimitry Andric   Targets.clear();
814*0b57cec5SDimitry Andric   MachineBasicBlock::const_iterator End = MB->end();
815*0b57cec5SDimitry Andric 
816*0b57cec5SDimitry Andric   bool DoNext = true;
817*0b57cec5SDimitry Andric   for (MachineBasicBlock::const_iterator I = FirstBr; I != End; ++I) {
818*0b57cec5SDimitry Andric     const MachineInstr &MI = *I;
819*0b57cec5SDimitry Andric     // Can there be debug instructions between branches?
820*0b57cec5SDimitry Andric     if (MI.isDebugInstr())
821*0b57cec5SDimitry Andric       continue;
822*0b57cec5SDimitry Andric     if (!InstrExec.count(&MI))
823*0b57cec5SDimitry Andric       continue;
824*0b57cec5SDimitry Andric     bool Eval = MCE.evaluate(MI, Cells, Targets, DoNext);
825*0b57cec5SDimitry Andric     if (!Eval)
826*0b57cec5SDimitry Andric       return false;
827*0b57cec5SDimitry Andric     if (!DoNext)
828*0b57cec5SDimitry Andric       break;
829*0b57cec5SDimitry Andric   }
830*0b57cec5SDimitry Andric   // If the last branch could fall-through, add block's layout successor.
831*0b57cec5SDimitry Andric   if (DoNext) {
832*0b57cec5SDimitry Andric     MachineFunction::const_iterator BI = MB->getIterator();
833*0b57cec5SDimitry Andric     MachineFunction::const_iterator NextI = std::next(BI);
834*0b57cec5SDimitry Andric     if (NextI != MB->getParent()->end())
835*0b57cec5SDimitry Andric       Targets.insert(&*NextI);
836*0b57cec5SDimitry Andric   }
837*0b57cec5SDimitry Andric 
838*0b57cec5SDimitry Andric   // Add all the EH landing pads.
839*0b57cec5SDimitry Andric   for (const MachineBasicBlock *SB : MB->successors())
840*0b57cec5SDimitry Andric     if (SB->isEHPad())
841*0b57cec5SDimitry Andric       Targets.insert(SB);
842*0b57cec5SDimitry Andric 
843*0b57cec5SDimitry Andric   return true;
844*0b57cec5SDimitry Andric }
845*0b57cec5SDimitry Andric 
846*0b57cec5SDimitry Andric void MachineConstPropagator::removeCFGEdge(MachineBasicBlock *From,
847*0b57cec5SDimitry Andric       MachineBasicBlock *To) {
848*0b57cec5SDimitry Andric   // First, remove the CFG successor/predecessor information.
849*0b57cec5SDimitry Andric   From->removeSuccessor(To);
850*0b57cec5SDimitry Andric   // Remove all corresponding PHI operands in the To block.
851*0b57cec5SDimitry Andric   for (auto I = To->begin(), E = To->getFirstNonPHI(); I != E; ++I) {
852*0b57cec5SDimitry Andric     MachineInstr *PN = &*I;
853*0b57cec5SDimitry Andric     // reg0 = PHI reg1, bb2, reg3, bb4, ...
854*0b57cec5SDimitry Andric     int N = PN->getNumOperands()-2;
855*0b57cec5SDimitry Andric     while (N > 0) {
856*0b57cec5SDimitry Andric       if (PN->getOperand(N+1).getMBB() == From) {
857*0b57cec5SDimitry Andric         PN->RemoveOperand(N+1);
858*0b57cec5SDimitry Andric         PN->RemoveOperand(N);
859*0b57cec5SDimitry Andric       }
860*0b57cec5SDimitry Andric       N -= 2;
861*0b57cec5SDimitry Andric     }
862*0b57cec5SDimitry Andric   }
863*0b57cec5SDimitry Andric }
864*0b57cec5SDimitry Andric 
865*0b57cec5SDimitry Andric void MachineConstPropagator::propagate(MachineFunction &MF) {
866*0b57cec5SDimitry Andric   MachineBasicBlock *Entry = GraphTraits<MachineFunction*>::getEntryNode(&MF);
867*0b57cec5SDimitry Andric   unsigned EntryNum = Entry->getNumber();
868*0b57cec5SDimitry Andric 
869*0b57cec5SDimitry Andric   // Start with a fake edge, just to process the entry node.
870*0b57cec5SDimitry Andric   FlowQ.push(CFGEdge(EntryNum, EntryNum));
871*0b57cec5SDimitry Andric 
872*0b57cec5SDimitry Andric   while (!FlowQ.empty()) {
873*0b57cec5SDimitry Andric     CFGEdge Edge = FlowQ.front();
874*0b57cec5SDimitry Andric     FlowQ.pop();
875*0b57cec5SDimitry Andric 
876*0b57cec5SDimitry Andric     LLVM_DEBUG(
877*0b57cec5SDimitry Andric         dbgs() << "Picked edge "
878*0b57cec5SDimitry Andric                << printMBBReference(*MF.getBlockNumbered(Edge.first)) << "->"
879*0b57cec5SDimitry Andric                << printMBBReference(*MF.getBlockNumbered(Edge.second)) << '\n');
880*0b57cec5SDimitry Andric     if (Edge.first != EntryNum)
881*0b57cec5SDimitry Andric       if (EdgeExec.count(Edge))
882*0b57cec5SDimitry Andric         continue;
883*0b57cec5SDimitry Andric     EdgeExec.insert(Edge);
884*0b57cec5SDimitry Andric     MachineBasicBlock *SB = MF.getBlockNumbered(Edge.second);
885*0b57cec5SDimitry Andric 
886*0b57cec5SDimitry Andric     // Process the block in three stages:
887*0b57cec5SDimitry Andric     // - visit all PHI nodes,
888*0b57cec5SDimitry Andric     // - visit all non-branch instructions,
889*0b57cec5SDimitry Andric     // - visit block branches.
890*0b57cec5SDimitry Andric     MachineBasicBlock::const_iterator It = SB->begin(), End = SB->end();
891*0b57cec5SDimitry Andric 
892*0b57cec5SDimitry Andric     // Visit PHI nodes in the successor block.
893*0b57cec5SDimitry Andric     while (It != End && It->isPHI()) {
894*0b57cec5SDimitry Andric       InstrExec.insert(&*It);
895*0b57cec5SDimitry Andric       visitPHI(*It);
896*0b57cec5SDimitry Andric       ++It;
897*0b57cec5SDimitry Andric     }
898*0b57cec5SDimitry Andric 
899*0b57cec5SDimitry Andric     // If the successor block just became executable, visit all instructions.
900*0b57cec5SDimitry Andric     // To see if this is the first time we're visiting it, check the first
901*0b57cec5SDimitry Andric     // non-debug instruction to see if it is executable.
902*0b57cec5SDimitry Andric     while (It != End && It->isDebugInstr())
903*0b57cec5SDimitry Andric       ++It;
904*0b57cec5SDimitry Andric     assert(It == End || !It->isPHI());
905*0b57cec5SDimitry Andric     // If this block has been visited, go on to the next one.
906*0b57cec5SDimitry Andric     if (It != End && InstrExec.count(&*It))
907*0b57cec5SDimitry Andric       continue;
908*0b57cec5SDimitry Andric     // For now, scan all non-branch instructions. Branches require different
909*0b57cec5SDimitry Andric     // processing.
910*0b57cec5SDimitry Andric     while (It != End && !It->isBranch()) {
911*0b57cec5SDimitry Andric       if (!It->isDebugInstr()) {
912*0b57cec5SDimitry Andric         InstrExec.insert(&*It);
913*0b57cec5SDimitry Andric         visitNonBranch(*It);
914*0b57cec5SDimitry Andric       }
915*0b57cec5SDimitry Andric       ++It;
916*0b57cec5SDimitry Andric     }
917*0b57cec5SDimitry Andric 
918*0b57cec5SDimitry Andric     // Time to process the end of the block. This is different from
919*0b57cec5SDimitry Andric     // processing regular (non-branch) instructions, because there can
920*0b57cec5SDimitry Andric     // be multiple branches in a block, and they can cause the block to
921*0b57cec5SDimitry Andric     // terminate early.
922*0b57cec5SDimitry Andric     if (It != End) {
923*0b57cec5SDimitry Andric       visitBranchesFrom(*It);
924*0b57cec5SDimitry Andric     } else {
925*0b57cec5SDimitry Andric       // If the block didn't have a branch, add all successor edges to the
926*0b57cec5SDimitry Andric       // work queue. (There should really be only one successor in such case.)
927*0b57cec5SDimitry Andric       unsigned SBN = SB->getNumber();
928*0b57cec5SDimitry Andric       for (const MachineBasicBlock *SSB : SB->successors())
929*0b57cec5SDimitry Andric         FlowQ.push(CFGEdge(SBN, SSB->getNumber()));
930*0b57cec5SDimitry Andric     }
931*0b57cec5SDimitry Andric   } // while (FlowQ)
932*0b57cec5SDimitry Andric 
933*0b57cec5SDimitry Andric   LLVM_DEBUG({
934*0b57cec5SDimitry Andric     dbgs() << "Cells after propagation:\n";
935*0b57cec5SDimitry Andric     Cells.print(dbgs(), MCE.TRI);
936*0b57cec5SDimitry Andric     dbgs() << "Dead CFG edges:\n";
937*0b57cec5SDimitry Andric     for (const MachineBasicBlock &B : MF) {
938*0b57cec5SDimitry Andric       unsigned BN = B.getNumber();
939*0b57cec5SDimitry Andric       for (const MachineBasicBlock *SB : B.successors()) {
940*0b57cec5SDimitry Andric         unsigned SN = SB->getNumber();
941*0b57cec5SDimitry Andric         if (!EdgeExec.count(CFGEdge(BN, SN)))
942*0b57cec5SDimitry Andric           dbgs() << "  " << printMBBReference(B) << " -> "
943*0b57cec5SDimitry Andric                  << printMBBReference(*SB) << '\n';
944*0b57cec5SDimitry Andric       }
945*0b57cec5SDimitry Andric     }
946*0b57cec5SDimitry Andric   });
947*0b57cec5SDimitry Andric }
948*0b57cec5SDimitry Andric 
949*0b57cec5SDimitry Andric bool MachineConstPropagator::rewrite(MachineFunction &MF) {
950*0b57cec5SDimitry Andric   bool Changed = false;
951*0b57cec5SDimitry Andric   // Rewrite all instructions based on the collected cell information.
952*0b57cec5SDimitry Andric   //
953*0b57cec5SDimitry Andric   // Traverse the instructions in a post-order, so that rewriting an
954*0b57cec5SDimitry Andric   // instruction can make changes "downstream" in terms of control-flow
955*0b57cec5SDimitry Andric   // without affecting the rewriting process. (We should not change
956*0b57cec5SDimitry Andric   // instructions that have not yet been visited by the rewriter.)
957*0b57cec5SDimitry Andric   // The reason for this is that the rewriter can introduce new vregs,
958*0b57cec5SDimitry Andric   // and replace uses of old vregs (which had corresponding cells
959*0b57cec5SDimitry Andric   // computed during propagation) with these new vregs (which at this
960*0b57cec5SDimitry Andric   // point would not have any cells, and would appear to be "top").
961*0b57cec5SDimitry Andric   // If an attempt was made to evaluate an instruction with a fresh
962*0b57cec5SDimitry Andric   // "top" vreg, it would cause an error (abend) in the evaluator.
963*0b57cec5SDimitry Andric 
964*0b57cec5SDimitry Andric   // Collect the post-order-traversal block ordering. The subsequent
965*0b57cec5SDimitry Andric   // traversal/rewrite will update block successors, so it's safer
966*0b57cec5SDimitry Andric   // if the visiting order it computed ahead of time.
967*0b57cec5SDimitry Andric   std::vector<MachineBasicBlock*> POT;
968*0b57cec5SDimitry Andric   for (MachineBasicBlock *B : post_order(&MF))
969*0b57cec5SDimitry Andric     if (!B->empty())
970*0b57cec5SDimitry Andric       POT.push_back(B);
971*0b57cec5SDimitry Andric 
972*0b57cec5SDimitry Andric   for (MachineBasicBlock *B : POT) {
973*0b57cec5SDimitry Andric     // Walk the block backwards (which usually begin with the branches).
974*0b57cec5SDimitry Andric     // If any branch is rewritten, we may need to update the successor
975*0b57cec5SDimitry Andric     // information for this block. Unless the block's successors can be
976*0b57cec5SDimitry Andric     // precisely determined (which may not be the case for indirect
977*0b57cec5SDimitry Andric     // branches), we cannot modify any branch.
978*0b57cec5SDimitry Andric 
979*0b57cec5SDimitry Andric     // Compute the successor information.
980*0b57cec5SDimitry Andric     SetVector<const MachineBasicBlock*> Targets;
981*0b57cec5SDimitry Andric     bool HaveTargets = computeBlockSuccessors(B, Targets);
982*0b57cec5SDimitry Andric     // Rewrite the executable instructions. Skip branches if we don't
983*0b57cec5SDimitry Andric     // have block successor information.
984*0b57cec5SDimitry Andric     for (auto I = B->rbegin(), E = B->rend(); I != E; ++I) {
985*0b57cec5SDimitry Andric       MachineInstr &MI = *I;
986*0b57cec5SDimitry Andric       if (InstrExec.count(&MI)) {
987*0b57cec5SDimitry Andric         if (MI.isBranch() && !HaveTargets)
988*0b57cec5SDimitry Andric           continue;
989*0b57cec5SDimitry Andric         Changed |= MCE.rewrite(MI, Cells);
990*0b57cec5SDimitry Andric       }
991*0b57cec5SDimitry Andric     }
992*0b57cec5SDimitry Andric     // The rewriting could rewrite PHI nodes to non-PHI nodes, causing
993*0b57cec5SDimitry Andric     // regular instructions to appear in between PHI nodes. Bring all
994*0b57cec5SDimitry Andric     // the PHI nodes to the beginning of the block.
995*0b57cec5SDimitry Andric     for (auto I = B->begin(), E = B->end(); I != E; ++I) {
996*0b57cec5SDimitry Andric       if (I->isPHI())
997*0b57cec5SDimitry Andric         continue;
998*0b57cec5SDimitry Andric       // I is not PHI. Find the next PHI node P.
999*0b57cec5SDimitry Andric       auto P = I;
1000*0b57cec5SDimitry Andric       while (++P != E)
1001*0b57cec5SDimitry Andric         if (P->isPHI())
1002*0b57cec5SDimitry Andric           break;
1003*0b57cec5SDimitry Andric       // Not found.
1004*0b57cec5SDimitry Andric       if (P == E)
1005*0b57cec5SDimitry Andric         break;
1006*0b57cec5SDimitry Andric       // Splice P right before I.
1007*0b57cec5SDimitry Andric       B->splice(I, B, P);
1008*0b57cec5SDimitry Andric       // Reset I to point at the just spliced PHI node.
1009*0b57cec5SDimitry Andric       --I;
1010*0b57cec5SDimitry Andric     }
1011*0b57cec5SDimitry Andric     // Update the block successor information: remove unnecessary successors.
1012*0b57cec5SDimitry Andric     if (HaveTargets) {
1013*0b57cec5SDimitry Andric       SmallVector<MachineBasicBlock*,2> ToRemove;
1014*0b57cec5SDimitry Andric       for (MachineBasicBlock *SB : B->successors()) {
1015*0b57cec5SDimitry Andric         if (!Targets.count(SB))
1016*0b57cec5SDimitry Andric           ToRemove.push_back(const_cast<MachineBasicBlock*>(SB));
1017*0b57cec5SDimitry Andric         Targets.remove(SB);
1018*0b57cec5SDimitry Andric       }
1019*0b57cec5SDimitry Andric       for (unsigned i = 0, n = ToRemove.size(); i < n; ++i)
1020*0b57cec5SDimitry Andric         removeCFGEdge(B, ToRemove[i]);
1021*0b57cec5SDimitry Andric       // If there are any blocks left in the computed targets, it means that
1022*0b57cec5SDimitry Andric       // we think that the block could go somewhere, but the CFG does not.
1023*0b57cec5SDimitry Andric       // This could legitimately happen in blocks that have non-returning
1024*0b57cec5SDimitry Andric       // calls---we would think that the execution can continue, but the
1025*0b57cec5SDimitry Andric       // CFG will not have a successor edge.
1026*0b57cec5SDimitry Andric     }
1027*0b57cec5SDimitry Andric   }
1028*0b57cec5SDimitry Andric   // Need to do some final post-processing.
1029*0b57cec5SDimitry Andric   // If a branch was not executable, it will not get rewritten, but should
1030*0b57cec5SDimitry Andric   // be removed (or replaced with something equivalent to a A2_nop). We can't
1031*0b57cec5SDimitry Andric   // erase instructions during rewriting, so this needs to be delayed until
1032*0b57cec5SDimitry Andric   // now.
1033*0b57cec5SDimitry Andric   for (MachineBasicBlock &B : MF) {
1034*0b57cec5SDimitry Andric     MachineBasicBlock::iterator I = B.begin(), E = B.end();
1035*0b57cec5SDimitry Andric     while (I != E) {
1036*0b57cec5SDimitry Andric       auto Next = std::next(I);
1037*0b57cec5SDimitry Andric       if (I->isBranch() && !InstrExec.count(&*I))
1038*0b57cec5SDimitry Andric         B.erase(I);
1039*0b57cec5SDimitry Andric       I = Next;
1040*0b57cec5SDimitry Andric     }
1041*0b57cec5SDimitry Andric   }
1042*0b57cec5SDimitry Andric   return Changed;
1043*0b57cec5SDimitry Andric }
1044*0b57cec5SDimitry Andric 
1045*0b57cec5SDimitry Andric // This is the constant propagation algorithm as described by Wegman-Zadeck.
1046*0b57cec5SDimitry Andric // Most of the terminology comes from there.
1047*0b57cec5SDimitry Andric bool MachineConstPropagator::run(MachineFunction &MF) {
1048*0b57cec5SDimitry Andric   LLVM_DEBUG(MF.print(dbgs() << "Starting MachineConstPropagator\n", nullptr));
1049*0b57cec5SDimitry Andric 
1050*0b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
1051*0b57cec5SDimitry Andric 
1052*0b57cec5SDimitry Andric   Cells.clear();
1053*0b57cec5SDimitry Andric   EdgeExec.clear();
1054*0b57cec5SDimitry Andric   InstrExec.clear();
1055*0b57cec5SDimitry Andric   assert(FlowQ.empty());
1056*0b57cec5SDimitry Andric 
1057*0b57cec5SDimitry Andric   propagate(MF);
1058*0b57cec5SDimitry Andric   bool Changed = rewrite(MF);
1059*0b57cec5SDimitry Andric 
1060*0b57cec5SDimitry Andric   LLVM_DEBUG({
1061*0b57cec5SDimitry Andric     dbgs() << "End of MachineConstPropagator (Changed=" << Changed << ")\n";
1062*0b57cec5SDimitry Andric     if (Changed)
1063*0b57cec5SDimitry Andric       MF.print(dbgs(), nullptr);
1064*0b57cec5SDimitry Andric   });
1065*0b57cec5SDimitry Andric   return Changed;
1066*0b57cec5SDimitry Andric }
1067*0b57cec5SDimitry Andric 
1068*0b57cec5SDimitry Andric // --------------------------------------------------------------------
1069*0b57cec5SDimitry Andric // Machine const evaluator.
1070*0b57cec5SDimitry Andric 
1071*0b57cec5SDimitry Andric bool MachineConstEvaluator::getCell(const RegisterSubReg &R, const CellMap &Inputs,
1072*0b57cec5SDimitry Andric       LatticeCell &RC) {
1073*0b57cec5SDimitry Andric   if (!TargetRegisterInfo::isVirtualRegister(R.Reg))
1074*0b57cec5SDimitry Andric     return false;
1075*0b57cec5SDimitry Andric   const LatticeCell &L = Inputs.get(R.Reg);
1076*0b57cec5SDimitry Andric   if (!R.SubReg) {
1077*0b57cec5SDimitry Andric     RC = L;
1078*0b57cec5SDimitry Andric     return !RC.isBottom();
1079*0b57cec5SDimitry Andric   }
1080*0b57cec5SDimitry Andric   bool Eval = evaluate(R, L, RC);
1081*0b57cec5SDimitry Andric   return Eval && !RC.isBottom();
1082*0b57cec5SDimitry Andric }
1083*0b57cec5SDimitry Andric 
1084*0b57cec5SDimitry Andric bool MachineConstEvaluator::constToInt(const Constant *C,
1085*0b57cec5SDimitry Andric       APInt &Val) const {
1086*0b57cec5SDimitry Andric   const ConstantInt *CI = dyn_cast<ConstantInt>(C);
1087*0b57cec5SDimitry Andric   if (!CI)
1088*0b57cec5SDimitry Andric     return false;
1089*0b57cec5SDimitry Andric   Val = CI->getValue();
1090*0b57cec5SDimitry Andric   return true;
1091*0b57cec5SDimitry Andric }
1092*0b57cec5SDimitry Andric 
1093*0b57cec5SDimitry Andric const ConstantInt *MachineConstEvaluator::intToConst(const APInt &Val) const {
1094*0b57cec5SDimitry Andric   return ConstantInt::get(CX, Val);
1095*0b57cec5SDimitry Andric }
1096*0b57cec5SDimitry Andric 
1097*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPrr(uint32_t Cmp, const RegisterSubReg &R1,
1098*0b57cec5SDimitry Andric       const RegisterSubReg &R2, const CellMap &Inputs, bool &Result) {
1099*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
1100*0b57cec5SDimitry Andric   LatticeCell LS1, LS2;
1101*0b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1) || !getCell(R2, Inputs, LS2))
1102*0b57cec5SDimitry Andric     return false;
1103*0b57cec5SDimitry Andric 
1104*0b57cec5SDimitry Andric   bool IsProp1 = LS1.isProperty();
1105*0b57cec5SDimitry Andric   bool IsProp2 = LS2.isProperty();
1106*0b57cec5SDimitry Andric   if (IsProp1) {
1107*0b57cec5SDimitry Andric     uint32_t Prop1 = LS1.properties();
1108*0b57cec5SDimitry Andric     if (IsProp2)
1109*0b57cec5SDimitry Andric       return evaluateCMPpp(Cmp, Prop1, LS2.properties(), Result);
1110*0b57cec5SDimitry Andric     uint32_t NegCmp = Comparison::negate(Cmp);
1111*0b57cec5SDimitry Andric     return evaluateCMPrp(NegCmp, R2, Prop1, Inputs, Result);
1112*0b57cec5SDimitry Andric   }
1113*0b57cec5SDimitry Andric   if (IsProp2) {
1114*0b57cec5SDimitry Andric     uint32_t Prop2 = LS2.properties();
1115*0b57cec5SDimitry Andric     return evaluateCMPrp(Cmp, R1, Prop2, Inputs, Result);
1116*0b57cec5SDimitry Andric   }
1117*0b57cec5SDimitry Andric 
1118*0b57cec5SDimitry Andric   APInt A;
1119*0b57cec5SDimitry Andric   bool IsTrue = true, IsFalse = true;
1120*0b57cec5SDimitry Andric   for (unsigned i = 0; i < LS2.size(); ++i) {
1121*0b57cec5SDimitry Andric     bool Res;
1122*0b57cec5SDimitry Andric     bool Computed = constToInt(LS2.Values[i], A) &&
1123*0b57cec5SDimitry Andric                     evaluateCMPri(Cmp, R1, A, Inputs, Res);
1124*0b57cec5SDimitry Andric     if (!Computed)
1125*0b57cec5SDimitry Andric       return false;
1126*0b57cec5SDimitry Andric     IsTrue &= Res;
1127*0b57cec5SDimitry Andric     IsFalse &= !Res;
1128*0b57cec5SDimitry Andric   }
1129*0b57cec5SDimitry Andric   assert(!IsTrue || !IsFalse);
1130*0b57cec5SDimitry Andric   // The actual logical value of the comparison is same as IsTrue.
1131*0b57cec5SDimitry Andric   Result = IsTrue;
1132*0b57cec5SDimitry Andric   // Return true if the result was proven to be true or proven to be false.
1133*0b57cec5SDimitry Andric   return IsTrue || IsFalse;
1134*0b57cec5SDimitry Andric }
1135*0b57cec5SDimitry Andric 
1136*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPri(uint32_t Cmp, const RegisterSubReg &R1,
1137*0b57cec5SDimitry Andric       const APInt &A2, const CellMap &Inputs, bool &Result) {
1138*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
1139*0b57cec5SDimitry Andric   LatticeCell LS;
1140*0b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS))
1141*0b57cec5SDimitry Andric     return false;
1142*0b57cec5SDimitry Andric   if (LS.isProperty())
1143*0b57cec5SDimitry Andric     return evaluateCMPpi(Cmp, LS.properties(), A2, Result);
1144*0b57cec5SDimitry Andric 
1145*0b57cec5SDimitry Andric   APInt A;
1146*0b57cec5SDimitry Andric   bool IsTrue = true, IsFalse = true;
1147*0b57cec5SDimitry Andric   for (unsigned i = 0; i < LS.size(); ++i) {
1148*0b57cec5SDimitry Andric     bool Res;
1149*0b57cec5SDimitry Andric     bool Computed = constToInt(LS.Values[i], A) &&
1150*0b57cec5SDimitry Andric                     evaluateCMPii(Cmp, A, A2, Res);
1151*0b57cec5SDimitry Andric     if (!Computed)
1152*0b57cec5SDimitry Andric       return false;
1153*0b57cec5SDimitry Andric     IsTrue &= Res;
1154*0b57cec5SDimitry Andric     IsFalse &= !Res;
1155*0b57cec5SDimitry Andric   }
1156*0b57cec5SDimitry Andric   assert(!IsTrue || !IsFalse);
1157*0b57cec5SDimitry Andric   // The actual logical value of the comparison is same as IsTrue.
1158*0b57cec5SDimitry Andric   Result = IsTrue;
1159*0b57cec5SDimitry Andric   // Return true if the result was proven to be true or proven to be false.
1160*0b57cec5SDimitry Andric   return IsTrue || IsFalse;
1161*0b57cec5SDimitry Andric }
1162*0b57cec5SDimitry Andric 
1163*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPrp(uint32_t Cmp, const RegisterSubReg &R1,
1164*0b57cec5SDimitry Andric       uint64_t Props2, const CellMap &Inputs, bool &Result) {
1165*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
1166*0b57cec5SDimitry Andric   LatticeCell LS;
1167*0b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS))
1168*0b57cec5SDimitry Andric     return false;
1169*0b57cec5SDimitry Andric   if (LS.isProperty())
1170*0b57cec5SDimitry Andric     return evaluateCMPpp(Cmp, LS.properties(), Props2, Result);
1171*0b57cec5SDimitry Andric 
1172*0b57cec5SDimitry Andric   APInt A;
1173*0b57cec5SDimitry Andric   uint32_t NegCmp = Comparison::negate(Cmp);
1174*0b57cec5SDimitry Andric   bool IsTrue = true, IsFalse = true;
1175*0b57cec5SDimitry Andric   for (unsigned i = 0; i < LS.size(); ++i) {
1176*0b57cec5SDimitry Andric     bool Res;
1177*0b57cec5SDimitry Andric     bool Computed = constToInt(LS.Values[i], A) &&
1178*0b57cec5SDimitry Andric                     evaluateCMPpi(NegCmp, Props2, A, Res);
1179*0b57cec5SDimitry Andric     if (!Computed)
1180*0b57cec5SDimitry Andric       return false;
1181*0b57cec5SDimitry Andric     IsTrue &= Res;
1182*0b57cec5SDimitry Andric     IsFalse &= !Res;
1183*0b57cec5SDimitry Andric   }
1184*0b57cec5SDimitry Andric   assert(!IsTrue || !IsFalse);
1185*0b57cec5SDimitry Andric   Result = IsTrue;
1186*0b57cec5SDimitry Andric   return IsTrue || IsFalse;
1187*0b57cec5SDimitry Andric }
1188*0b57cec5SDimitry Andric 
1189*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPii(uint32_t Cmp, const APInt &A1,
1190*0b57cec5SDimitry Andric       const APInt &A2, bool &Result) {
1191*0b57cec5SDimitry Andric   // NE is a special kind of comparison (not composed of smaller properties).
1192*0b57cec5SDimitry Andric   if (Cmp == Comparison::NE) {
1193*0b57cec5SDimitry Andric     Result = !APInt::isSameValue(A1, A2);
1194*0b57cec5SDimitry Andric     return true;
1195*0b57cec5SDimitry Andric   }
1196*0b57cec5SDimitry Andric   if (Cmp == Comparison::EQ) {
1197*0b57cec5SDimitry Andric     Result = APInt::isSameValue(A1, A2);
1198*0b57cec5SDimitry Andric     return true;
1199*0b57cec5SDimitry Andric   }
1200*0b57cec5SDimitry Andric   if (Cmp & Comparison::EQ) {
1201*0b57cec5SDimitry Andric     if (APInt::isSameValue(A1, A2))
1202*0b57cec5SDimitry Andric       return (Result = true);
1203*0b57cec5SDimitry Andric   }
1204*0b57cec5SDimitry Andric   assert((Cmp & (Comparison::L | Comparison::G)) && "Malformed comparison");
1205*0b57cec5SDimitry Andric   Result = false;
1206*0b57cec5SDimitry Andric 
1207*0b57cec5SDimitry Andric   unsigned W1 = A1.getBitWidth();
1208*0b57cec5SDimitry Andric   unsigned W2 = A2.getBitWidth();
1209*0b57cec5SDimitry Andric   unsigned MaxW = (W1 >= W2) ? W1 : W2;
1210*0b57cec5SDimitry Andric   if (Cmp & Comparison::U) {
1211*0b57cec5SDimitry Andric     const APInt Zx1 = A1.zextOrSelf(MaxW);
1212*0b57cec5SDimitry Andric     const APInt Zx2 = A2.zextOrSelf(MaxW);
1213*0b57cec5SDimitry Andric     if (Cmp & Comparison::L)
1214*0b57cec5SDimitry Andric       Result = Zx1.ult(Zx2);
1215*0b57cec5SDimitry Andric     else if (Cmp & Comparison::G)
1216*0b57cec5SDimitry Andric       Result = Zx2.ult(Zx1);
1217*0b57cec5SDimitry Andric     return true;
1218*0b57cec5SDimitry Andric   }
1219*0b57cec5SDimitry Andric 
1220*0b57cec5SDimitry Andric   // Signed comparison.
1221*0b57cec5SDimitry Andric   const APInt Sx1 = A1.sextOrSelf(MaxW);
1222*0b57cec5SDimitry Andric   const APInt Sx2 = A2.sextOrSelf(MaxW);
1223*0b57cec5SDimitry Andric   if (Cmp & Comparison::L)
1224*0b57cec5SDimitry Andric     Result = Sx1.slt(Sx2);
1225*0b57cec5SDimitry Andric   else if (Cmp & Comparison::G)
1226*0b57cec5SDimitry Andric     Result = Sx2.slt(Sx1);
1227*0b57cec5SDimitry Andric   return true;
1228*0b57cec5SDimitry Andric }
1229*0b57cec5SDimitry Andric 
1230*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPpi(uint32_t Cmp, uint32_t Props,
1231*0b57cec5SDimitry Andric       const APInt &A2, bool &Result) {
1232*0b57cec5SDimitry Andric   if (Props == ConstantProperties::Unknown)
1233*0b57cec5SDimitry Andric     return false;
1234*0b57cec5SDimitry Andric 
1235*0b57cec5SDimitry Andric   // Should never see NaN here, but check for it for completeness.
1236*0b57cec5SDimitry Andric   if (Props & ConstantProperties::NaN)
1237*0b57cec5SDimitry Andric     return false;
1238*0b57cec5SDimitry Andric   // Infinity could theoretically be compared to a number, but the
1239*0b57cec5SDimitry Andric   // presence of infinity here would be very suspicious. If we don't
1240*0b57cec5SDimitry Andric   // know for sure that the number is finite, bail out.
1241*0b57cec5SDimitry Andric   if (!(Props & ConstantProperties::Finite))
1242*0b57cec5SDimitry Andric     return false;
1243*0b57cec5SDimitry Andric 
1244*0b57cec5SDimitry Andric   // Let X be a number that has properties Props.
1245*0b57cec5SDimitry Andric 
1246*0b57cec5SDimitry Andric   if (Cmp & Comparison::U) {
1247*0b57cec5SDimitry Andric     // In case of unsigned comparisons, we can only compare against 0.
1248*0b57cec5SDimitry Andric     if (A2 == 0) {
1249*0b57cec5SDimitry Andric       // Any x!=0 will be considered >0 in an unsigned comparison.
1250*0b57cec5SDimitry Andric       if (Props & ConstantProperties::Zero)
1251*0b57cec5SDimitry Andric         Result = (Cmp & Comparison::EQ);
1252*0b57cec5SDimitry Andric       else if (Props & ConstantProperties::NonZero)
1253*0b57cec5SDimitry Andric         Result = (Cmp & Comparison::G) || (Cmp == Comparison::NE);
1254*0b57cec5SDimitry Andric       else
1255*0b57cec5SDimitry Andric         return false;
1256*0b57cec5SDimitry Andric       return true;
1257*0b57cec5SDimitry Andric     }
1258*0b57cec5SDimitry Andric     // A2 is not zero. The only handled case is if X = 0.
1259*0b57cec5SDimitry Andric     if (Props & ConstantProperties::Zero) {
1260*0b57cec5SDimitry Andric       Result = (Cmp & Comparison::L) || (Cmp == Comparison::NE);
1261*0b57cec5SDimitry Andric       return true;
1262*0b57cec5SDimitry Andric     }
1263*0b57cec5SDimitry Andric     return false;
1264*0b57cec5SDimitry Andric   }
1265*0b57cec5SDimitry Andric 
1266*0b57cec5SDimitry Andric   // Signed comparisons are different.
1267*0b57cec5SDimitry Andric   if (Props & ConstantProperties::Zero) {
1268*0b57cec5SDimitry Andric     if (A2 == 0)
1269*0b57cec5SDimitry Andric       Result = (Cmp & Comparison::EQ);
1270*0b57cec5SDimitry Andric     else
1271*0b57cec5SDimitry Andric       Result = (Cmp == Comparison::NE) ||
1272*0b57cec5SDimitry Andric                ((Cmp & Comparison::L) && !A2.isNegative()) ||
1273*0b57cec5SDimitry Andric                ((Cmp & Comparison::G) &&  A2.isNegative());
1274*0b57cec5SDimitry Andric     return true;
1275*0b57cec5SDimitry Andric   }
1276*0b57cec5SDimitry Andric   if (Props & ConstantProperties::PosOrZero) {
1277*0b57cec5SDimitry Andric     // X >= 0 and !(A2 < 0) => cannot compare
1278*0b57cec5SDimitry Andric     if (!A2.isNegative())
1279*0b57cec5SDimitry Andric       return false;
1280*0b57cec5SDimitry Andric     // X >= 0 and A2 < 0
1281*0b57cec5SDimitry Andric     Result = (Cmp & Comparison::G) || (Cmp == Comparison::NE);
1282*0b57cec5SDimitry Andric     return true;
1283*0b57cec5SDimitry Andric   }
1284*0b57cec5SDimitry Andric   if (Props & ConstantProperties::NegOrZero) {
1285*0b57cec5SDimitry Andric     // X <= 0 and Src1 < 0 => cannot compare
1286*0b57cec5SDimitry Andric     if (A2 == 0 || A2.isNegative())
1287*0b57cec5SDimitry Andric       return false;
1288*0b57cec5SDimitry Andric     // X <= 0 and A2 > 0
1289*0b57cec5SDimitry Andric     Result = (Cmp & Comparison::L) || (Cmp == Comparison::NE);
1290*0b57cec5SDimitry Andric     return true;
1291*0b57cec5SDimitry Andric   }
1292*0b57cec5SDimitry Andric 
1293*0b57cec5SDimitry Andric   return false;
1294*0b57cec5SDimitry Andric }
1295*0b57cec5SDimitry Andric 
1296*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPpp(uint32_t Cmp, uint32_t Props1,
1297*0b57cec5SDimitry Andric       uint32_t Props2, bool &Result) {
1298*0b57cec5SDimitry Andric   using P = ConstantProperties;
1299*0b57cec5SDimitry Andric 
1300*0b57cec5SDimitry Andric   if ((Props1 & P::NaN) && (Props2 & P::NaN))
1301*0b57cec5SDimitry Andric     return false;
1302*0b57cec5SDimitry Andric   if (!(Props1 & P::Finite) || !(Props2 & P::Finite))
1303*0b57cec5SDimitry Andric     return false;
1304*0b57cec5SDimitry Andric 
1305*0b57cec5SDimitry Andric   bool Zero1 = (Props1 & P::Zero), Zero2 = (Props2 & P::Zero);
1306*0b57cec5SDimitry Andric   bool NonZero1 = (Props1 & P::NonZero), NonZero2 = (Props2 & P::NonZero);
1307*0b57cec5SDimitry Andric   if (Zero1 && Zero2) {
1308*0b57cec5SDimitry Andric     Result = (Cmp & Comparison::EQ);
1309*0b57cec5SDimitry Andric     return true;
1310*0b57cec5SDimitry Andric   }
1311*0b57cec5SDimitry Andric   if (Cmp == Comparison::NE) {
1312*0b57cec5SDimitry Andric     if ((Zero1 && NonZero2) || (NonZero1 && Zero2))
1313*0b57cec5SDimitry Andric       return (Result = true);
1314*0b57cec5SDimitry Andric     return false;
1315*0b57cec5SDimitry Andric   }
1316*0b57cec5SDimitry Andric 
1317*0b57cec5SDimitry Andric   if (Cmp & Comparison::U) {
1318*0b57cec5SDimitry Andric     // In unsigned comparisons, we can only compare against a known zero,
1319*0b57cec5SDimitry Andric     // or a known non-zero.
1320*0b57cec5SDimitry Andric     if (Zero1 && NonZero2) {
1321*0b57cec5SDimitry Andric       Result = (Cmp & Comparison::L);
1322*0b57cec5SDimitry Andric       return true;
1323*0b57cec5SDimitry Andric     }
1324*0b57cec5SDimitry Andric     if (NonZero1 && Zero2) {
1325*0b57cec5SDimitry Andric       Result = (Cmp & Comparison::G);
1326*0b57cec5SDimitry Andric       return true;
1327*0b57cec5SDimitry Andric     }
1328*0b57cec5SDimitry Andric     return false;
1329*0b57cec5SDimitry Andric   }
1330*0b57cec5SDimitry Andric 
1331*0b57cec5SDimitry Andric   // Signed comparison. The comparison is not NE.
1332*0b57cec5SDimitry Andric   bool Poz1 = (Props1 & P::PosOrZero), Poz2 = (Props2 & P::PosOrZero);
1333*0b57cec5SDimitry Andric   bool Nez1 = (Props1 & P::NegOrZero), Nez2 = (Props2 & P::NegOrZero);
1334*0b57cec5SDimitry Andric   if (Nez1 && Poz2) {
1335*0b57cec5SDimitry Andric     if (NonZero1 || NonZero2) {
1336*0b57cec5SDimitry Andric       Result = (Cmp & Comparison::L);
1337*0b57cec5SDimitry Andric       return true;
1338*0b57cec5SDimitry Andric     }
1339*0b57cec5SDimitry Andric     // Either (or both) could be zero. Can only say that X <= Y.
1340*0b57cec5SDimitry Andric     if ((Cmp & Comparison::EQ) && (Cmp & Comparison::L))
1341*0b57cec5SDimitry Andric       return (Result = true);
1342*0b57cec5SDimitry Andric   }
1343*0b57cec5SDimitry Andric   if (Poz1 && Nez2) {
1344*0b57cec5SDimitry Andric     if (NonZero1 || NonZero2) {
1345*0b57cec5SDimitry Andric       Result = (Cmp & Comparison::G);
1346*0b57cec5SDimitry Andric       return true;
1347*0b57cec5SDimitry Andric     }
1348*0b57cec5SDimitry Andric     // Either (or both) could be zero. Can only say that X >= Y.
1349*0b57cec5SDimitry Andric     if ((Cmp & Comparison::EQ) && (Cmp & Comparison::G))
1350*0b57cec5SDimitry Andric       return (Result = true);
1351*0b57cec5SDimitry Andric   }
1352*0b57cec5SDimitry Andric 
1353*0b57cec5SDimitry Andric   return false;
1354*0b57cec5SDimitry Andric }
1355*0b57cec5SDimitry Andric 
1356*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCOPY(const RegisterSubReg &R1,
1357*0b57cec5SDimitry Andric       const CellMap &Inputs, LatticeCell &Result) {
1358*0b57cec5SDimitry Andric   return getCell(R1, Inputs, Result);
1359*0b57cec5SDimitry Andric }
1360*0b57cec5SDimitry Andric 
1361*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateANDrr(const RegisterSubReg &R1,
1362*0b57cec5SDimitry Andric       const RegisterSubReg &R2, const CellMap &Inputs, LatticeCell &Result) {
1363*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
1364*0b57cec5SDimitry Andric   const LatticeCell &L1 = Inputs.get(R2.Reg);
1365*0b57cec5SDimitry Andric   const LatticeCell &L2 = Inputs.get(R2.Reg);
1366*0b57cec5SDimitry Andric   // If both sources are bottom, exit. Otherwise try to evaluate ANDri
1367*0b57cec5SDimitry Andric   // with the non-bottom argument passed as the immediate. This is to
1368*0b57cec5SDimitry Andric   // catch cases of ANDing with 0.
1369*0b57cec5SDimitry Andric   if (L2.isBottom()) {
1370*0b57cec5SDimitry Andric     if (L1.isBottom())
1371*0b57cec5SDimitry Andric       return false;
1372*0b57cec5SDimitry Andric     return evaluateANDrr(R2, R1, Inputs, Result);
1373*0b57cec5SDimitry Andric   }
1374*0b57cec5SDimitry Andric   LatticeCell LS2;
1375*0b57cec5SDimitry Andric   if (!evaluate(R2, L2, LS2))
1376*0b57cec5SDimitry Andric     return false;
1377*0b57cec5SDimitry Andric   if (LS2.isBottom() || LS2.isProperty())
1378*0b57cec5SDimitry Andric     return false;
1379*0b57cec5SDimitry Andric 
1380*0b57cec5SDimitry Andric   APInt A;
1381*0b57cec5SDimitry Andric   for (unsigned i = 0; i < LS2.size(); ++i) {
1382*0b57cec5SDimitry Andric     LatticeCell RC;
1383*0b57cec5SDimitry Andric     bool Eval = constToInt(LS2.Values[i], A) &&
1384*0b57cec5SDimitry Andric                 evaluateANDri(R1, A, Inputs, RC);
1385*0b57cec5SDimitry Andric     if (!Eval)
1386*0b57cec5SDimitry Andric       return false;
1387*0b57cec5SDimitry Andric     Result.meet(RC);
1388*0b57cec5SDimitry Andric   }
1389*0b57cec5SDimitry Andric   return !Result.isBottom();
1390*0b57cec5SDimitry Andric }
1391*0b57cec5SDimitry Andric 
1392*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateANDri(const RegisterSubReg &R1,
1393*0b57cec5SDimitry Andric       const APInt &A2, const CellMap &Inputs, LatticeCell &Result) {
1394*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
1395*0b57cec5SDimitry Andric   if (A2 == -1)
1396*0b57cec5SDimitry Andric     return getCell(R1, Inputs, Result);
1397*0b57cec5SDimitry Andric   if (A2 == 0) {
1398*0b57cec5SDimitry Andric     LatticeCell RC;
1399*0b57cec5SDimitry Andric     RC.add(intToConst(A2));
1400*0b57cec5SDimitry Andric     // Overwrite Result.
1401*0b57cec5SDimitry Andric     Result = RC;
1402*0b57cec5SDimitry Andric     return true;
1403*0b57cec5SDimitry Andric   }
1404*0b57cec5SDimitry Andric   LatticeCell LS1;
1405*0b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
1406*0b57cec5SDimitry Andric     return false;
1407*0b57cec5SDimitry Andric   if (LS1.isBottom() || LS1.isProperty())
1408*0b57cec5SDimitry Andric     return false;
1409*0b57cec5SDimitry Andric 
1410*0b57cec5SDimitry Andric   APInt A, ResA;
1411*0b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
1412*0b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
1413*0b57cec5SDimitry Andric                 evaluateANDii(A, A2, ResA);
1414*0b57cec5SDimitry Andric     if (!Eval)
1415*0b57cec5SDimitry Andric       return false;
1416*0b57cec5SDimitry Andric     const Constant *C = intToConst(ResA);
1417*0b57cec5SDimitry Andric     Result.add(C);
1418*0b57cec5SDimitry Andric   }
1419*0b57cec5SDimitry Andric   return !Result.isBottom();
1420*0b57cec5SDimitry Andric }
1421*0b57cec5SDimitry Andric 
1422*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateANDii(const APInt &A1,
1423*0b57cec5SDimitry Andric       const APInt &A2, APInt &Result) {
1424*0b57cec5SDimitry Andric   Result = A1 & A2;
1425*0b57cec5SDimitry Andric   return true;
1426*0b57cec5SDimitry Andric }
1427*0b57cec5SDimitry Andric 
1428*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateORrr(const RegisterSubReg &R1,
1429*0b57cec5SDimitry Andric       const RegisterSubReg &R2, const CellMap &Inputs, LatticeCell &Result) {
1430*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
1431*0b57cec5SDimitry Andric   const LatticeCell &L1 = Inputs.get(R2.Reg);
1432*0b57cec5SDimitry Andric   const LatticeCell &L2 = Inputs.get(R2.Reg);
1433*0b57cec5SDimitry Andric   // If both sources are bottom, exit. Otherwise try to evaluate ORri
1434*0b57cec5SDimitry Andric   // with the non-bottom argument passed as the immediate. This is to
1435*0b57cec5SDimitry Andric   // catch cases of ORing with -1.
1436*0b57cec5SDimitry Andric   if (L2.isBottom()) {
1437*0b57cec5SDimitry Andric     if (L1.isBottom())
1438*0b57cec5SDimitry Andric       return false;
1439*0b57cec5SDimitry Andric     return evaluateORrr(R2, R1, Inputs, Result);
1440*0b57cec5SDimitry Andric   }
1441*0b57cec5SDimitry Andric   LatticeCell LS2;
1442*0b57cec5SDimitry Andric   if (!evaluate(R2, L2, LS2))
1443*0b57cec5SDimitry Andric     return false;
1444*0b57cec5SDimitry Andric   if (LS2.isBottom() || LS2.isProperty())
1445*0b57cec5SDimitry Andric     return false;
1446*0b57cec5SDimitry Andric 
1447*0b57cec5SDimitry Andric   APInt A;
1448*0b57cec5SDimitry Andric   for (unsigned i = 0; i < LS2.size(); ++i) {
1449*0b57cec5SDimitry Andric     LatticeCell RC;
1450*0b57cec5SDimitry Andric     bool Eval = constToInt(LS2.Values[i], A) &&
1451*0b57cec5SDimitry Andric                 evaluateORri(R1, A, Inputs, RC);
1452*0b57cec5SDimitry Andric     if (!Eval)
1453*0b57cec5SDimitry Andric       return false;
1454*0b57cec5SDimitry Andric     Result.meet(RC);
1455*0b57cec5SDimitry Andric   }
1456*0b57cec5SDimitry Andric   return !Result.isBottom();
1457*0b57cec5SDimitry Andric }
1458*0b57cec5SDimitry Andric 
1459*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateORri(const RegisterSubReg &R1,
1460*0b57cec5SDimitry Andric       const APInt &A2, const CellMap &Inputs, LatticeCell &Result) {
1461*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
1462*0b57cec5SDimitry Andric   if (A2 == 0)
1463*0b57cec5SDimitry Andric     return getCell(R1, Inputs, Result);
1464*0b57cec5SDimitry Andric   if (A2 == -1) {
1465*0b57cec5SDimitry Andric     LatticeCell RC;
1466*0b57cec5SDimitry Andric     RC.add(intToConst(A2));
1467*0b57cec5SDimitry Andric     // Overwrite Result.
1468*0b57cec5SDimitry Andric     Result = RC;
1469*0b57cec5SDimitry Andric     return true;
1470*0b57cec5SDimitry Andric   }
1471*0b57cec5SDimitry Andric   LatticeCell LS1;
1472*0b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
1473*0b57cec5SDimitry Andric     return false;
1474*0b57cec5SDimitry Andric   if (LS1.isBottom() || LS1.isProperty())
1475*0b57cec5SDimitry Andric     return false;
1476*0b57cec5SDimitry Andric 
1477*0b57cec5SDimitry Andric   APInt A, ResA;
1478*0b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
1479*0b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
1480*0b57cec5SDimitry Andric                 evaluateORii(A, A2, ResA);
1481*0b57cec5SDimitry Andric     if (!Eval)
1482*0b57cec5SDimitry Andric       return false;
1483*0b57cec5SDimitry Andric     const Constant *C = intToConst(ResA);
1484*0b57cec5SDimitry Andric     Result.add(C);
1485*0b57cec5SDimitry Andric   }
1486*0b57cec5SDimitry Andric   return !Result.isBottom();
1487*0b57cec5SDimitry Andric }
1488*0b57cec5SDimitry Andric 
1489*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateORii(const APInt &A1,
1490*0b57cec5SDimitry Andric       const APInt &A2, APInt &Result) {
1491*0b57cec5SDimitry Andric   Result = A1 | A2;
1492*0b57cec5SDimitry Andric   return true;
1493*0b57cec5SDimitry Andric }
1494*0b57cec5SDimitry Andric 
1495*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateXORrr(const RegisterSubReg &R1,
1496*0b57cec5SDimitry Andric       const RegisterSubReg &R2, const CellMap &Inputs, LatticeCell &Result) {
1497*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
1498*0b57cec5SDimitry Andric   LatticeCell LS1, LS2;
1499*0b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1) || !getCell(R2, Inputs, LS2))
1500*0b57cec5SDimitry Andric     return false;
1501*0b57cec5SDimitry Andric   if (LS1.isProperty()) {
1502*0b57cec5SDimitry Andric     if (LS1.properties() & ConstantProperties::Zero)
1503*0b57cec5SDimitry Andric       return !(Result = LS2).isBottom();
1504*0b57cec5SDimitry Andric     return false;
1505*0b57cec5SDimitry Andric   }
1506*0b57cec5SDimitry Andric   if (LS2.isProperty()) {
1507*0b57cec5SDimitry Andric     if (LS2.properties() & ConstantProperties::Zero)
1508*0b57cec5SDimitry Andric       return !(Result = LS1).isBottom();
1509*0b57cec5SDimitry Andric     return false;
1510*0b57cec5SDimitry Andric   }
1511*0b57cec5SDimitry Andric 
1512*0b57cec5SDimitry Andric   APInt A;
1513*0b57cec5SDimitry Andric   for (unsigned i = 0; i < LS2.size(); ++i) {
1514*0b57cec5SDimitry Andric     LatticeCell RC;
1515*0b57cec5SDimitry Andric     bool Eval = constToInt(LS2.Values[i], A) &&
1516*0b57cec5SDimitry Andric                 evaluateXORri(R1, A, Inputs, RC);
1517*0b57cec5SDimitry Andric     if (!Eval)
1518*0b57cec5SDimitry Andric       return false;
1519*0b57cec5SDimitry Andric     Result.meet(RC);
1520*0b57cec5SDimitry Andric   }
1521*0b57cec5SDimitry Andric   return !Result.isBottom();
1522*0b57cec5SDimitry Andric }
1523*0b57cec5SDimitry Andric 
1524*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateXORri(const RegisterSubReg &R1,
1525*0b57cec5SDimitry Andric       const APInt &A2, const CellMap &Inputs, LatticeCell &Result) {
1526*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
1527*0b57cec5SDimitry Andric   LatticeCell LS1;
1528*0b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
1529*0b57cec5SDimitry Andric     return false;
1530*0b57cec5SDimitry Andric   if (LS1.isProperty()) {
1531*0b57cec5SDimitry Andric     if (LS1.properties() & ConstantProperties::Zero) {
1532*0b57cec5SDimitry Andric       const Constant *C = intToConst(A2);
1533*0b57cec5SDimitry Andric       Result.add(C);
1534*0b57cec5SDimitry Andric       return !Result.isBottom();
1535*0b57cec5SDimitry Andric     }
1536*0b57cec5SDimitry Andric     return false;
1537*0b57cec5SDimitry Andric   }
1538*0b57cec5SDimitry Andric 
1539*0b57cec5SDimitry Andric   APInt A, XA;
1540*0b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
1541*0b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
1542*0b57cec5SDimitry Andric                 evaluateXORii(A, A2, XA);
1543*0b57cec5SDimitry Andric     if (!Eval)
1544*0b57cec5SDimitry Andric       return false;
1545*0b57cec5SDimitry Andric     const Constant *C = intToConst(XA);
1546*0b57cec5SDimitry Andric     Result.add(C);
1547*0b57cec5SDimitry Andric   }
1548*0b57cec5SDimitry Andric   return !Result.isBottom();
1549*0b57cec5SDimitry Andric }
1550*0b57cec5SDimitry Andric 
1551*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateXORii(const APInt &A1,
1552*0b57cec5SDimitry Andric       const APInt &A2, APInt &Result) {
1553*0b57cec5SDimitry Andric   Result = A1 ^ A2;
1554*0b57cec5SDimitry Andric   return true;
1555*0b57cec5SDimitry Andric }
1556*0b57cec5SDimitry Andric 
1557*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateZEXTr(const RegisterSubReg &R1, unsigned Width,
1558*0b57cec5SDimitry Andric       unsigned Bits, const CellMap &Inputs, LatticeCell &Result) {
1559*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
1560*0b57cec5SDimitry Andric   LatticeCell LS1;
1561*0b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
1562*0b57cec5SDimitry Andric     return false;
1563*0b57cec5SDimitry Andric   if (LS1.isProperty())
1564*0b57cec5SDimitry Andric     return false;
1565*0b57cec5SDimitry Andric 
1566*0b57cec5SDimitry Andric   APInt A, XA;
1567*0b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
1568*0b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
1569*0b57cec5SDimitry Andric                 evaluateZEXTi(A, Width, Bits, XA);
1570*0b57cec5SDimitry Andric     if (!Eval)
1571*0b57cec5SDimitry Andric       return false;
1572*0b57cec5SDimitry Andric     const Constant *C = intToConst(XA);
1573*0b57cec5SDimitry Andric     Result.add(C);
1574*0b57cec5SDimitry Andric   }
1575*0b57cec5SDimitry Andric   return true;
1576*0b57cec5SDimitry Andric }
1577*0b57cec5SDimitry Andric 
1578*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateZEXTi(const APInt &A1, unsigned Width,
1579*0b57cec5SDimitry Andric       unsigned Bits, APInt &Result) {
1580*0b57cec5SDimitry Andric   unsigned BW = A1.getBitWidth();
1581*0b57cec5SDimitry Andric   (void)BW;
1582*0b57cec5SDimitry Andric   assert(Width >= Bits && BW >= Bits);
1583*0b57cec5SDimitry Andric   APInt Mask = APInt::getLowBitsSet(Width, Bits);
1584*0b57cec5SDimitry Andric   Result = A1.zextOrTrunc(Width) & Mask;
1585*0b57cec5SDimitry Andric   return true;
1586*0b57cec5SDimitry Andric }
1587*0b57cec5SDimitry Andric 
1588*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateSEXTr(const RegisterSubReg &R1, unsigned Width,
1589*0b57cec5SDimitry Andric       unsigned Bits, const CellMap &Inputs, LatticeCell &Result) {
1590*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
1591*0b57cec5SDimitry Andric   LatticeCell LS1;
1592*0b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
1593*0b57cec5SDimitry Andric     return false;
1594*0b57cec5SDimitry Andric   if (LS1.isBottom() || LS1.isProperty())
1595*0b57cec5SDimitry Andric     return false;
1596*0b57cec5SDimitry Andric 
1597*0b57cec5SDimitry Andric   APInt A, XA;
1598*0b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
1599*0b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
1600*0b57cec5SDimitry Andric                 evaluateSEXTi(A, Width, Bits, XA);
1601*0b57cec5SDimitry Andric     if (!Eval)
1602*0b57cec5SDimitry Andric       return false;
1603*0b57cec5SDimitry Andric     const Constant *C = intToConst(XA);
1604*0b57cec5SDimitry Andric     Result.add(C);
1605*0b57cec5SDimitry Andric   }
1606*0b57cec5SDimitry Andric   return true;
1607*0b57cec5SDimitry Andric }
1608*0b57cec5SDimitry Andric 
1609*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateSEXTi(const APInt &A1, unsigned Width,
1610*0b57cec5SDimitry Andric       unsigned Bits, APInt &Result) {
1611*0b57cec5SDimitry Andric   unsigned BW = A1.getBitWidth();
1612*0b57cec5SDimitry Andric   assert(Width >= Bits && BW >= Bits);
1613*0b57cec5SDimitry Andric   // Special case to make things faster for smaller source widths.
1614*0b57cec5SDimitry Andric   // Sign extension of 0 bits generates 0 as a result. This is consistent
1615*0b57cec5SDimitry Andric   // with what the HW does.
1616*0b57cec5SDimitry Andric   if (Bits == 0) {
1617*0b57cec5SDimitry Andric     Result = APInt(Width, 0);
1618*0b57cec5SDimitry Andric     return true;
1619*0b57cec5SDimitry Andric   }
1620*0b57cec5SDimitry Andric   // In C, shifts by 64 invoke undefined behavior: handle that case in APInt.
1621*0b57cec5SDimitry Andric   if (BW <= 64 && Bits != 0) {
1622*0b57cec5SDimitry Andric     int64_t V = A1.getSExtValue();
1623*0b57cec5SDimitry Andric     switch (Bits) {
1624*0b57cec5SDimitry Andric       case 8:
1625*0b57cec5SDimitry Andric         V = static_cast<int8_t>(V);
1626*0b57cec5SDimitry Andric         break;
1627*0b57cec5SDimitry Andric       case 16:
1628*0b57cec5SDimitry Andric         V = static_cast<int16_t>(V);
1629*0b57cec5SDimitry Andric         break;
1630*0b57cec5SDimitry Andric       case 32:
1631*0b57cec5SDimitry Andric         V = static_cast<int32_t>(V);
1632*0b57cec5SDimitry Andric         break;
1633*0b57cec5SDimitry Andric       default:
1634*0b57cec5SDimitry Andric         // Shift left to lose all bits except lower "Bits" bits, then shift
1635*0b57cec5SDimitry Andric         // the value back, replicating what was a sign bit after the first
1636*0b57cec5SDimitry Andric         // shift.
1637*0b57cec5SDimitry Andric         V = (V << (64-Bits)) >> (64-Bits);
1638*0b57cec5SDimitry Andric         break;
1639*0b57cec5SDimitry Andric     }
1640*0b57cec5SDimitry Andric     // V is a 64-bit sign-extended value. Convert it to APInt of desired
1641*0b57cec5SDimitry Andric     // width.
1642*0b57cec5SDimitry Andric     Result = APInt(Width, V, true);
1643*0b57cec5SDimitry Andric     return true;
1644*0b57cec5SDimitry Andric   }
1645*0b57cec5SDimitry Andric   // Slow case: the value doesn't fit in int64_t.
1646*0b57cec5SDimitry Andric   if (Bits < BW)
1647*0b57cec5SDimitry Andric     Result = A1.trunc(Bits).sext(Width);
1648*0b57cec5SDimitry Andric   else // Bits == BW
1649*0b57cec5SDimitry Andric     Result = A1.sext(Width);
1650*0b57cec5SDimitry Andric   return true;
1651*0b57cec5SDimitry Andric }
1652*0b57cec5SDimitry Andric 
1653*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCLBr(const RegisterSubReg &R1, bool Zeros,
1654*0b57cec5SDimitry Andric       bool Ones, const CellMap &Inputs, LatticeCell &Result) {
1655*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
1656*0b57cec5SDimitry Andric   LatticeCell LS1;
1657*0b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
1658*0b57cec5SDimitry Andric     return false;
1659*0b57cec5SDimitry Andric   if (LS1.isBottom() || LS1.isProperty())
1660*0b57cec5SDimitry Andric     return false;
1661*0b57cec5SDimitry Andric 
1662*0b57cec5SDimitry Andric   APInt A, CA;
1663*0b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
1664*0b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
1665*0b57cec5SDimitry Andric                 evaluateCLBi(A, Zeros, Ones, CA);
1666*0b57cec5SDimitry Andric     if (!Eval)
1667*0b57cec5SDimitry Andric       return false;
1668*0b57cec5SDimitry Andric     const Constant *C = intToConst(CA);
1669*0b57cec5SDimitry Andric     Result.add(C);
1670*0b57cec5SDimitry Andric   }
1671*0b57cec5SDimitry Andric   return true;
1672*0b57cec5SDimitry Andric }
1673*0b57cec5SDimitry Andric 
1674*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCLBi(const APInt &A1, bool Zeros,
1675*0b57cec5SDimitry Andric       bool Ones, APInt &Result) {
1676*0b57cec5SDimitry Andric   unsigned BW = A1.getBitWidth();
1677*0b57cec5SDimitry Andric   if (!Zeros && !Ones)
1678*0b57cec5SDimitry Andric     return false;
1679*0b57cec5SDimitry Andric   unsigned Count = 0;
1680*0b57cec5SDimitry Andric   if (Zeros && (Count == 0))
1681*0b57cec5SDimitry Andric     Count = A1.countLeadingZeros();
1682*0b57cec5SDimitry Andric   if (Ones && (Count == 0))
1683*0b57cec5SDimitry Andric     Count = A1.countLeadingOnes();
1684*0b57cec5SDimitry Andric   Result = APInt(BW, static_cast<uint64_t>(Count), false);
1685*0b57cec5SDimitry Andric   return true;
1686*0b57cec5SDimitry Andric }
1687*0b57cec5SDimitry Andric 
1688*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCTBr(const RegisterSubReg &R1, bool Zeros,
1689*0b57cec5SDimitry Andric       bool Ones, const CellMap &Inputs, LatticeCell &Result) {
1690*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
1691*0b57cec5SDimitry Andric   LatticeCell LS1;
1692*0b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
1693*0b57cec5SDimitry Andric     return false;
1694*0b57cec5SDimitry Andric   if (LS1.isBottom() || LS1.isProperty())
1695*0b57cec5SDimitry Andric     return false;
1696*0b57cec5SDimitry Andric 
1697*0b57cec5SDimitry Andric   APInt A, CA;
1698*0b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
1699*0b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
1700*0b57cec5SDimitry Andric                 evaluateCTBi(A, Zeros, Ones, CA);
1701*0b57cec5SDimitry Andric     if (!Eval)
1702*0b57cec5SDimitry Andric       return false;
1703*0b57cec5SDimitry Andric     const Constant *C = intToConst(CA);
1704*0b57cec5SDimitry Andric     Result.add(C);
1705*0b57cec5SDimitry Andric   }
1706*0b57cec5SDimitry Andric   return true;
1707*0b57cec5SDimitry Andric }
1708*0b57cec5SDimitry Andric 
1709*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCTBi(const APInt &A1, bool Zeros,
1710*0b57cec5SDimitry Andric       bool Ones, APInt &Result) {
1711*0b57cec5SDimitry Andric   unsigned BW = A1.getBitWidth();
1712*0b57cec5SDimitry Andric   if (!Zeros && !Ones)
1713*0b57cec5SDimitry Andric     return false;
1714*0b57cec5SDimitry Andric   unsigned Count = 0;
1715*0b57cec5SDimitry Andric   if (Zeros && (Count == 0))
1716*0b57cec5SDimitry Andric     Count = A1.countTrailingZeros();
1717*0b57cec5SDimitry Andric   if (Ones && (Count == 0))
1718*0b57cec5SDimitry Andric     Count = A1.countTrailingOnes();
1719*0b57cec5SDimitry Andric   Result = APInt(BW, static_cast<uint64_t>(Count), false);
1720*0b57cec5SDimitry Andric   return true;
1721*0b57cec5SDimitry Andric }
1722*0b57cec5SDimitry Andric 
1723*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateEXTRACTr(const RegisterSubReg &R1,
1724*0b57cec5SDimitry Andric       unsigned Width, unsigned Bits, unsigned Offset, bool Signed,
1725*0b57cec5SDimitry Andric       const CellMap &Inputs, LatticeCell &Result) {
1726*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
1727*0b57cec5SDimitry Andric   assert(Bits+Offset <= Width);
1728*0b57cec5SDimitry Andric   LatticeCell LS1;
1729*0b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
1730*0b57cec5SDimitry Andric     return false;
1731*0b57cec5SDimitry Andric   if (LS1.isBottom())
1732*0b57cec5SDimitry Andric     return false;
1733*0b57cec5SDimitry Andric   if (LS1.isProperty()) {
1734*0b57cec5SDimitry Andric     uint32_t Ps = LS1.properties();
1735*0b57cec5SDimitry Andric     if (Ps & ConstantProperties::Zero) {
1736*0b57cec5SDimitry Andric       const Constant *C = intToConst(APInt(Width, 0, false));
1737*0b57cec5SDimitry Andric       Result.add(C);
1738*0b57cec5SDimitry Andric       return true;
1739*0b57cec5SDimitry Andric     }
1740*0b57cec5SDimitry Andric     return false;
1741*0b57cec5SDimitry Andric   }
1742*0b57cec5SDimitry Andric 
1743*0b57cec5SDimitry Andric   APInt A, CA;
1744*0b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
1745*0b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
1746*0b57cec5SDimitry Andric                 evaluateEXTRACTi(A, Bits, Offset, Signed, CA);
1747*0b57cec5SDimitry Andric     if (!Eval)
1748*0b57cec5SDimitry Andric       return false;
1749*0b57cec5SDimitry Andric     const Constant *C = intToConst(CA);
1750*0b57cec5SDimitry Andric     Result.add(C);
1751*0b57cec5SDimitry Andric   }
1752*0b57cec5SDimitry Andric   return true;
1753*0b57cec5SDimitry Andric }
1754*0b57cec5SDimitry Andric 
1755*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateEXTRACTi(const APInt &A1, unsigned Bits,
1756*0b57cec5SDimitry Andric       unsigned Offset, bool Signed, APInt &Result) {
1757*0b57cec5SDimitry Andric   unsigned BW = A1.getBitWidth();
1758*0b57cec5SDimitry Andric   assert(Bits+Offset <= BW);
1759*0b57cec5SDimitry Andric   // Extracting 0 bits generates 0 as a result (as indicated by the HW people).
1760*0b57cec5SDimitry Andric   if (Bits == 0) {
1761*0b57cec5SDimitry Andric     Result = APInt(BW, 0);
1762*0b57cec5SDimitry Andric     return true;
1763*0b57cec5SDimitry Andric   }
1764*0b57cec5SDimitry Andric   if (BW <= 64) {
1765*0b57cec5SDimitry Andric     int64_t V = A1.getZExtValue();
1766*0b57cec5SDimitry Andric     V <<= (64-Bits-Offset);
1767*0b57cec5SDimitry Andric     if (Signed)
1768*0b57cec5SDimitry Andric       V >>= (64-Bits);
1769*0b57cec5SDimitry Andric     else
1770*0b57cec5SDimitry Andric       V = static_cast<uint64_t>(V) >> (64-Bits);
1771*0b57cec5SDimitry Andric     Result = APInt(BW, V, Signed);
1772*0b57cec5SDimitry Andric     return true;
1773*0b57cec5SDimitry Andric   }
1774*0b57cec5SDimitry Andric   if (Signed)
1775*0b57cec5SDimitry Andric     Result = A1.shl(BW-Bits-Offset).ashr(BW-Bits);
1776*0b57cec5SDimitry Andric   else
1777*0b57cec5SDimitry Andric     Result = A1.shl(BW-Bits-Offset).lshr(BW-Bits);
1778*0b57cec5SDimitry Andric   return true;
1779*0b57cec5SDimitry Andric }
1780*0b57cec5SDimitry Andric 
1781*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateSplatr(const RegisterSubReg &R1,
1782*0b57cec5SDimitry Andric       unsigned Bits, unsigned Count, const CellMap &Inputs,
1783*0b57cec5SDimitry Andric       LatticeCell &Result) {
1784*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
1785*0b57cec5SDimitry Andric   LatticeCell LS1;
1786*0b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
1787*0b57cec5SDimitry Andric     return false;
1788*0b57cec5SDimitry Andric   if (LS1.isBottom() || LS1.isProperty())
1789*0b57cec5SDimitry Andric     return false;
1790*0b57cec5SDimitry Andric 
1791*0b57cec5SDimitry Andric   APInt A, SA;
1792*0b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
1793*0b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
1794*0b57cec5SDimitry Andric                 evaluateSplati(A, Bits, Count, SA);
1795*0b57cec5SDimitry Andric     if (!Eval)
1796*0b57cec5SDimitry Andric       return false;
1797*0b57cec5SDimitry Andric     const Constant *C = intToConst(SA);
1798*0b57cec5SDimitry Andric     Result.add(C);
1799*0b57cec5SDimitry Andric   }
1800*0b57cec5SDimitry Andric   return true;
1801*0b57cec5SDimitry Andric }
1802*0b57cec5SDimitry Andric 
1803*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateSplati(const APInt &A1, unsigned Bits,
1804*0b57cec5SDimitry Andric       unsigned Count, APInt &Result) {
1805*0b57cec5SDimitry Andric   assert(Count > 0);
1806*0b57cec5SDimitry Andric   unsigned BW = A1.getBitWidth(), SW = Count*Bits;
1807*0b57cec5SDimitry Andric   APInt LoBits = (Bits < BW) ? A1.trunc(Bits) : A1.zextOrSelf(Bits);
1808*0b57cec5SDimitry Andric   if (Count > 1)
1809*0b57cec5SDimitry Andric     LoBits = LoBits.zext(SW);
1810*0b57cec5SDimitry Andric 
1811*0b57cec5SDimitry Andric   APInt Res(SW, 0, false);
1812*0b57cec5SDimitry Andric   for (unsigned i = 0; i < Count; ++i) {
1813*0b57cec5SDimitry Andric     Res <<= Bits;
1814*0b57cec5SDimitry Andric     Res |= LoBits;
1815*0b57cec5SDimitry Andric   }
1816*0b57cec5SDimitry Andric   Result = Res;
1817*0b57cec5SDimitry Andric   return true;
1818*0b57cec5SDimitry Andric }
1819*0b57cec5SDimitry Andric 
1820*0b57cec5SDimitry Andric // ----------------------------------------------------------------------
1821*0b57cec5SDimitry Andric // Hexagon-specific code.
1822*0b57cec5SDimitry Andric 
1823*0b57cec5SDimitry Andric namespace llvm {
1824*0b57cec5SDimitry Andric 
1825*0b57cec5SDimitry Andric   FunctionPass *createHexagonConstPropagationPass();
1826*0b57cec5SDimitry Andric   void initializeHexagonConstPropagationPass(PassRegistry &Registry);
1827*0b57cec5SDimitry Andric 
1828*0b57cec5SDimitry Andric } // end namespace llvm
1829*0b57cec5SDimitry Andric 
1830*0b57cec5SDimitry Andric namespace {
1831*0b57cec5SDimitry Andric 
1832*0b57cec5SDimitry Andric   class HexagonConstEvaluator : public MachineConstEvaluator {
1833*0b57cec5SDimitry Andric   public:
1834*0b57cec5SDimitry Andric     HexagonConstEvaluator(MachineFunction &Fn);
1835*0b57cec5SDimitry Andric 
1836*0b57cec5SDimitry Andric     bool evaluate(const MachineInstr &MI, const CellMap &Inputs,
1837*0b57cec5SDimitry Andric           CellMap &Outputs) override;
1838*0b57cec5SDimitry Andric     bool evaluate(const RegisterSubReg &R, const LatticeCell &SrcC,
1839*0b57cec5SDimitry Andric           LatticeCell &Result) override;
1840*0b57cec5SDimitry Andric     bool evaluate(const MachineInstr &BrI, const CellMap &Inputs,
1841*0b57cec5SDimitry Andric           SetVector<const MachineBasicBlock*> &Targets, bool &FallsThru)
1842*0b57cec5SDimitry Andric           override;
1843*0b57cec5SDimitry Andric     bool rewrite(MachineInstr &MI, const CellMap &Inputs) override;
1844*0b57cec5SDimitry Andric 
1845*0b57cec5SDimitry Andric   private:
1846*0b57cec5SDimitry Andric     unsigned getRegBitWidth(unsigned Reg) const;
1847*0b57cec5SDimitry Andric 
1848*0b57cec5SDimitry Andric     static uint32_t getCmp(unsigned Opc);
1849*0b57cec5SDimitry Andric     static APInt getCmpImm(unsigned Opc, unsigned OpX,
1850*0b57cec5SDimitry Andric           const MachineOperand &MO);
1851*0b57cec5SDimitry Andric     void replaceWithNop(MachineInstr &MI);
1852*0b57cec5SDimitry Andric 
1853*0b57cec5SDimitry Andric     bool evaluateHexRSEQ32(RegisterSubReg RL, RegisterSubReg RH, const CellMap &Inputs,
1854*0b57cec5SDimitry Andric           LatticeCell &Result);
1855*0b57cec5SDimitry Andric     bool evaluateHexCompare(const MachineInstr &MI, const CellMap &Inputs,
1856*0b57cec5SDimitry Andric           CellMap &Outputs);
1857*0b57cec5SDimitry Andric     // This is suitable to be called for compare-and-jump instructions.
1858*0b57cec5SDimitry Andric     bool evaluateHexCompare2(uint32_t Cmp, const MachineOperand &Src1,
1859*0b57cec5SDimitry Andric           const MachineOperand &Src2, const CellMap &Inputs, bool &Result);
1860*0b57cec5SDimitry Andric     bool evaluateHexLogical(const MachineInstr &MI, const CellMap &Inputs,
1861*0b57cec5SDimitry Andric           CellMap &Outputs);
1862*0b57cec5SDimitry Andric     bool evaluateHexCondMove(const MachineInstr &MI, const CellMap &Inputs,
1863*0b57cec5SDimitry Andric           CellMap &Outputs);
1864*0b57cec5SDimitry Andric     bool evaluateHexExt(const MachineInstr &MI, const CellMap &Inputs,
1865*0b57cec5SDimitry Andric           CellMap &Outputs);
1866*0b57cec5SDimitry Andric     bool evaluateHexVector1(const MachineInstr &MI, const CellMap &Inputs,
1867*0b57cec5SDimitry Andric           CellMap &Outputs);
1868*0b57cec5SDimitry Andric     bool evaluateHexVector2(const MachineInstr &MI, const CellMap &Inputs,
1869*0b57cec5SDimitry Andric           CellMap &Outputs);
1870*0b57cec5SDimitry Andric 
1871*0b57cec5SDimitry Andric     void replaceAllRegUsesWith(unsigned FromReg, unsigned ToReg);
1872*0b57cec5SDimitry Andric     bool rewriteHexBranch(MachineInstr &BrI, const CellMap &Inputs);
1873*0b57cec5SDimitry Andric     bool rewriteHexConstDefs(MachineInstr &MI, const CellMap &Inputs,
1874*0b57cec5SDimitry Andric           bool &AllDefs);
1875*0b57cec5SDimitry Andric     bool rewriteHexConstUses(MachineInstr &MI, const CellMap &Inputs);
1876*0b57cec5SDimitry Andric 
1877*0b57cec5SDimitry Andric     MachineRegisterInfo *MRI;
1878*0b57cec5SDimitry Andric     const HexagonInstrInfo &HII;
1879*0b57cec5SDimitry Andric     const HexagonRegisterInfo &HRI;
1880*0b57cec5SDimitry Andric   };
1881*0b57cec5SDimitry Andric 
1882*0b57cec5SDimitry Andric   class HexagonConstPropagation : public MachineFunctionPass {
1883*0b57cec5SDimitry Andric   public:
1884*0b57cec5SDimitry Andric     static char ID;
1885*0b57cec5SDimitry Andric 
1886*0b57cec5SDimitry Andric     HexagonConstPropagation() : MachineFunctionPass(ID) {}
1887*0b57cec5SDimitry Andric 
1888*0b57cec5SDimitry Andric     StringRef getPassName() const override {
1889*0b57cec5SDimitry Andric       return "Hexagon Constant Propagation";
1890*0b57cec5SDimitry Andric     }
1891*0b57cec5SDimitry Andric 
1892*0b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &MF) override {
1893*0b57cec5SDimitry Andric       const Function &F = MF.getFunction();
1894*0b57cec5SDimitry Andric       if (skipFunction(F))
1895*0b57cec5SDimitry Andric         return false;
1896*0b57cec5SDimitry Andric 
1897*0b57cec5SDimitry Andric       HexagonConstEvaluator HCE(MF);
1898*0b57cec5SDimitry Andric       return MachineConstPropagator(HCE).run(MF);
1899*0b57cec5SDimitry Andric     }
1900*0b57cec5SDimitry Andric   };
1901*0b57cec5SDimitry Andric 
1902*0b57cec5SDimitry Andric } // end anonymous namespace
1903*0b57cec5SDimitry Andric 
1904*0b57cec5SDimitry Andric char HexagonConstPropagation::ID = 0;
1905*0b57cec5SDimitry Andric 
1906*0b57cec5SDimitry Andric INITIALIZE_PASS(HexagonConstPropagation, "hexagon-constp",
1907*0b57cec5SDimitry Andric   "Hexagon Constant Propagation", false, false)
1908*0b57cec5SDimitry Andric 
1909*0b57cec5SDimitry Andric HexagonConstEvaluator::HexagonConstEvaluator(MachineFunction &Fn)
1910*0b57cec5SDimitry Andric   : MachineConstEvaluator(Fn),
1911*0b57cec5SDimitry Andric     HII(*Fn.getSubtarget<HexagonSubtarget>().getInstrInfo()),
1912*0b57cec5SDimitry Andric     HRI(*Fn.getSubtarget<HexagonSubtarget>().getRegisterInfo()) {
1913*0b57cec5SDimitry Andric   MRI = &Fn.getRegInfo();
1914*0b57cec5SDimitry Andric }
1915*0b57cec5SDimitry Andric 
1916*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluate(const MachineInstr &MI,
1917*0b57cec5SDimitry Andric       const CellMap &Inputs, CellMap &Outputs) {
1918*0b57cec5SDimitry Andric   if (MI.isCall())
1919*0b57cec5SDimitry Andric     return false;
1920*0b57cec5SDimitry Andric   if (MI.getNumOperands() == 0 || !MI.getOperand(0).isReg())
1921*0b57cec5SDimitry Andric     return false;
1922*0b57cec5SDimitry Andric   const MachineOperand &MD = MI.getOperand(0);
1923*0b57cec5SDimitry Andric   if (!MD.isDef())
1924*0b57cec5SDimitry Andric     return false;
1925*0b57cec5SDimitry Andric 
1926*0b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
1927*0b57cec5SDimitry Andric   RegisterSubReg DefR(MD);
1928*0b57cec5SDimitry Andric   assert(!DefR.SubReg);
1929*0b57cec5SDimitry Andric   if (!TargetRegisterInfo::isVirtualRegister(DefR.Reg))
1930*0b57cec5SDimitry Andric     return false;
1931*0b57cec5SDimitry Andric 
1932*0b57cec5SDimitry Andric   if (MI.isCopy()) {
1933*0b57cec5SDimitry Andric     LatticeCell RC;
1934*0b57cec5SDimitry Andric     RegisterSubReg SrcR(MI.getOperand(1));
1935*0b57cec5SDimitry Andric     bool Eval = evaluateCOPY(SrcR, Inputs, RC);
1936*0b57cec5SDimitry Andric     if (!Eval)
1937*0b57cec5SDimitry Andric       return false;
1938*0b57cec5SDimitry Andric     Outputs.update(DefR.Reg, RC);
1939*0b57cec5SDimitry Andric     return true;
1940*0b57cec5SDimitry Andric   }
1941*0b57cec5SDimitry Andric   if (MI.isRegSequence()) {
1942*0b57cec5SDimitry Andric     unsigned Sub1 = MI.getOperand(2).getImm();
1943*0b57cec5SDimitry Andric     unsigned Sub2 = MI.getOperand(4).getImm();
1944*0b57cec5SDimitry Andric     const TargetRegisterClass &DefRC = *MRI->getRegClass(DefR.Reg);
1945*0b57cec5SDimitry Andric     unsigned SubLo = HRI.getHexagonSubRegIndex(DefRC, Hexagon::ps_sub_lo);
1946*0b57cec5SDimitry Andric     unsigned SubHi = HRI.getHexagonSubRegIndex(DefRC, Hexagon::ps_sub_hi);
1947*0b57cec5SDimitry Andric     if (Sub1 != SubLo && Sub1 != SubHi)
1948*0b57cec5SDimitry Andric       return false;
1949*0b57cec5SDimitry Andric     if (Sub2 != SubLo && Sub2 != SubHi)
1950*0b57cec5SDimitry Andric       return false;
1951*0b57cec5SDimitry Andric     assert(Sub1 != Sub2);
1952*0b57cec5SDimitry Andric     bool LoIs1 = (Sub1 == SubLo);
1953*0b57cec5SDimitry Andric     const MachineOperand &OpLo = LoIs1 ? MI.getOperand(1) : MI.getOperand(3);
1954*0b57cec5SDimitry Andric     const MachineOperand &OpHi = LoIs1 ? MI.getOperand(3) : MI.getOperand(1);
1955*0b57cec5SDimitry Andric     LatticeCell RC;
1956*0b57cec5SDimitry Andric     RegisterSubReg SrcRL(OpLo), SrcRH(OpHi);
1957*0b57cec5SDimitry Andric     bool Eval = evaluateHexRSEQ32(SrcRL, SrcRH, Inputs, RC);
1958*0b57cec5SDimitry Andric     if (!Eval)
1959*0b57cec5SDimitry Andric       return false;
1960*0b57cec5SDimitry Andric     Outputs.update(DefR.Reg, RC);
1961*0b57cec5SDimitry Andric     return true;
1962*0b57cec5SDimitry Andric   }
1963*0b57cec5SDimitry Andric   if (MI.isCompare()) {
1964*0b57cec5SDimitry Andric     bool Eval = evaluateHexCompare(MI, Inputs, Outputs);
1965*0b57cec5SDimitry Andric     return Eval;
1966*0b57cec5SDimitry Andric   }
1967*0b57cec5SDimitry Andric 
1968*0b57cec5SDimitry Andric   switch (Opc) {
1969*0b57cec5SDimitry Andric     default:
1970*0b57cec5SDimitry Andric       return false;
1971*0b57cec5SDimitry Andric     case Hexagon::A2_tfrsi:
1972*0b57cec5SDimitry Andric     case Hexagon::A2_tfrpi:
1973*0b57cec5SDimitry Andric     case Hexagon::CONST32:
1974*0b57cec5SDimitry Andric     case Hexagon::CONST64:
1975*0b57cec5SDimitry Andric     {
1976*0b57cec5SDimitry Andric       const MachineOperand &VO = MI.getOperand(1);
1977*0b57cec5SDimitry Andric       // The operand of CONST32 can be a blockaddress, e.g.
1978*0b57cec5SDimitry Andric       //   %0 = CONST32 <blockaddress(@eat, %l)>
1979*0b57cec5SDimitry Andric       // Do this check for all instructions for safety.
1980*0b57cec5SDimitry Andric       if (!VO.isImm())
1981*0b57cec5SDimitry Andric         return false;
1982*0b57cec5SDimitry Andric       int64_t V = MI.getOperand(1).getImm();
1983*0b57cec5SDimitry Andric       unsigned W = getRegBitWidth(DefR.Reg);
1984*0b57cec5SDimitry Andric       if (W != 32 && W != 64)
1985*0b57cec5SDimitry Andric         return false;
1986*0b57cec5SDimitry Andric       IntegerType *Ty = (W == 32) ? Type::getInt32Ty(CX)
1987*0b57cec5SDimitry Andric                                   : Type::getInt64Ty(CX);
1988*0b57cec5SDimitry Andric       const ConstantInt *CI = ConstantInt::get(Ty, V, true);
1989*0b57cec5SDimitry Andric       LatticeCell RC = Outputs.get(DefR.Reg);
1990*0b57cec5SDimitry Andric       RC.add(CI);
1991*0b57cec5SDimitry Andric       Outputs.update(DefR.Reg, RC);
1992*0b57cec5SDimitry Andric       break;
1993*0b57cec5SDimitry Andric     }
1994*0b57cec5SDimitry Andric 
1995*0b57cec5SDimitry Andric     case Hexagon::PS_true:
1996*0b57cec5SDimitry Andric     case Hexagon::PS_false:
1997*0b57cec5SDimitry Andric     {
1998*0b57cec5SDimitry Andric       LatticeCell RC = Outputs.get(DefR.Reg);
1999*0b57cec5SDimitry Andric       bool NonZero = (Opc == Hexagon::PS_true);
2000*0b57cec5SDimitry Andric       uint32_t P = NonZero ? ConstantProperties::NonZero
2001*0b57cec5SDimitry Andric                            : ConstantProperties::Zero;
2002*0b57cec5SDimitry Andric       RC.add(P);
2003*0b57cec5SDimitry Andric       Outputs.update(DefR.Reg, RC);
2004*0b57cec5SDimitry Andric       break;
2005*0b57cec5SDimitry Andric     }
2006*0b57cec5SDimitry Andric 
2007*0b57cec5SDimitry Andric     case Hexagon::A2_and:
2008*0b57cec5SDimitry Andric     case Hexagon::A2_andir:
2009*0b57cec5SDimitry Andric     case Hexagon::A2_andp:
2010*0b57cec5SDimitry Andric     case Hexagon::A2_or:
2011*0b57cec5SDimitry Andric     case Hexagon::A2_orir:
2012*0b57cec5SDimitry Andric     case Hexagon::A2_orp:
2013*0b57cec5SDimitry Andric     case Hexagon::A2_xor:
2014*0b57cec5SDimitry Andric     case Hexagon::A2_xorp:
2015*0b57cec5SDimitry Andric     {
2016*0b57cec5SDimitry Andric       bool Eval = evaluateHexLogical(MI, Inputs, Outputs);
2017*0b57cec5SDimitry Andric       if (!Eval)
2018*0b57cec5SDimitry Andric         return false;
2019*0b57cec5SDimitry Andric       break;
2020*0b57cec5SDimitry Andric     }
2021*0b57cec5SDimitry Andric 
2022*0b57cec5SDimitry Andric     case Hexagon::A2_combineii:  // combine(#s8Ext, #s8)
2023*0b57cec5SDimitry Andric     case Hexagon::A4_combineii:  // combine(#s8, #u6Ext)
2024*0b57cec5SDimitry Andric     {
2025*0b57cec5SDimitry Andric       if (!MI.getOperand(1).isImm() || !MI.getOperand(2).isImm())
2026*0b57cec5SDimitry Andric         return false;
2027*0b57cec5SDimitry Andric       uint64_t Hi = MI.getOperand(1).getImm();
2028*0b57cec5SDimitry Andric       uint64_t Lo = MI.getOperand(2).getImm();
2029*0b57cec5SDimitry Andric       uint64_t Res = (Hi << 32) | (Lo & 0xFFFFFFFF);
2030*0b57cec5SDimitry Andric       IntegerType *Ty = Type::getInt64Ty(CX);
2031*0b57cec5SDimitry Andric       const ConstantInt *CI = ConstantInt::get(Ty, Res, false);
2032*0b57cec5SDimitry Andric       LatticeCell RC = Outputs.get(DefR.Reg);
2033*0b57cec5SDimitry Andric       RC.add(CI);
2034*0b57cec5SDimitry Andric       Outputs.update(DefR.Reg, RC);
2035*0b57cec5SDimitry Andric       break;
2036*0b57cec5SDimitry Andric     }
2037*0b57cec5SDimitry Andric 
2038*0b57cec5SDimitry Andric     case Hexagon::S2_setbit_i:
2039*0b57cec5SDimitry Andric     {
2040*0b57cec5SDimitry Andric       int64_t B = MI.getOperand(2).getImm();
2041*0b57cec5SDimitry Andric       assert(B >=0 && B < 32);
2042*0b57cec5SDimitry Andric       APInt A(32, (1ull << B), false);
2043*0b57cec5SDimitry Andric       RegisterSubReg R(MI.getOperand(1));
2044*0b57cec5SDimitry Andric       LatticeCell RC = Outputs.get(DefR.Reg);
2045*0b57cec5SDimitry Andric       bool Eval = evaluateORri(R, A, Inputs, RC);
2046*0b57cec5SDimitry Andric       if (!Eval)
2047*0b57cec5SDimitry Andric         return false;
2048*0b57cec5SDimitry Andric       Outputs.update(DefR.Reg, RC);
2049*0b57cec5SDimitry Andric       break;
2050*0b57cec5SDimitry Andric     }
2051*0b57cec5SDimitry Andric 
2052*0b57cec5SDimitry Andric     case Hexagon::C2_mux:
2053*0b57cec5SDimitry Andric     case Hexagon::C2_muxir:
2054*0b57cec5SDimitry Andric     case Hexagon::C2_muxri:
2055*0b57cec5SDimitry Andric     case Hexagon::C2_muxii:
2056*0b57cec5SDimitry Andric     {
2057*0b57cec5SDimitry Andric       bool Eval = evaluateHexCondMove(MI, Inputs, Outputs);
2058*0b57cec5SDimitry Andric       if (!Eval)
2059*0b57cec5SDimitry Andric         return false;
2060*0b57cec5SDimitry Andric       break;
2061*0b57cec5SDimitry Andric     }
2062*0b57cec5SDimitry Andric 
2063*0b57cec5SDimitry Andric     case Hexagon::A2_sxtb:
2064*0b57cec5SDimitry Andric     case Hexagon::A2_sxth:
2065*0b57cec5SDimitry Andric     case Hexagon::A2_sxtw:
2066*0b57cec5SDimitry Andric     case Hexagon::A2_zxtb:
2067*0b57cec5SDimitry Andric     case Hexagon::A2_zxth:
2068*0b57cec5SDimitry Andric     {
2069*0b57cec5SDimitry Andric       bool Eval = evaluateHexExt(MI, Inputs, Outputs);
2070*0b57cec5SDimitry Andric       if (!Eval)
2071*0b57cec5SDimitry Andric         return false;
2072*0b57cec5SDimitry Andric       break;
2073*0b57cec5SDimitry Andric     }
2074*0b57cec5SDimitry Andric 
2075*0b57cec5SDimitry Andric     case Hexagon::S2_ct0:
2076*0b57cec5SDimitry Andric     case Hexagon::S2_ct0p:
2077*0b57cec5SDimitry Andric     case Hexagon::S2_ct1:
2078*0b57cec5SDimitry Andric     case Hexagon::S2_ct1p:
2079*0b57cec5SDimitry Andric     {
2080*0b57cec5SDimitry Andric       using namespace Hexagon;
2081*0b57cec5SDimitry Andric 
2082*0b57cec5SDimitry Andric       bool Ones = (Opc == S2_ct1) || (Opc == S2_ct1p);
2083*0b57cec5SDimitry Andric       RegisterSubReg R1(MI.getOperand(1));
2084*0b57cec5SDimitry Andric       assert(Inputs.has(R1.Reg));
2085*0b57cec5SDimitry Andric       LatticeCell T;
2086*0b57cec5SDimitry Andric       bool Eval = evaluateCTBr(R1, !Ones, Ones, Inputs, T);
2087*0b57cec5SDimitry Andric       if (!Eval)
2088*0b57cec5SDimitry Andric         return false;
2089*0b57cec5SDimitry Andric       // All of these instructions return a 32-bit value. The evaluate
2090*0b57cec5SDimitry Andric       // will generate the same type as the operand, so truncate the
2091*0b57cec5SDimitry Andric       // result if necessary.
2092*0b57cec5SDimitry Andric       APInt C;
2093*0b57cec5SDimitry Andric       LatticeCell RC = Outputs.get(DefR.Reg);
2094*0b57cec5SDimitry Andric       for (unsigned i = 0; i < T.size(); ++i) {
2095*0b57cec5SDimitry Andric         const Constant *CI = T.Values[i];
2096*0b57cec5SDimitry Andric         if (constToInt(CI, C) && C.getBitWidth() > 32)
2097*0b57cec5SDimitry Andric           CI = intToConst(C.trunc(32));
2098*0b57cec5SDimitry Andric         RC.add(CI);
2099*0b57cec5SDimitry Andric       }
2100*0b57cec5SDimitry Andric       Outputs.update(DefR.Reg, RC);
2101*0b57cec5SDimitry Andric       break;
2102*0b57cec5SDimitry Andric     }
2103*0b57cec5SDimitry Andric 
2104*0b57cec5SDimitry Andric     case Hexagon::S2_cl0:
2105*0b57cec5SDimitry Andric     case Hexagon::S2_cl0p:
2106*0b57cec5SDimitry Andric     case Hexagon::S2_cl1:
2107*0b57cec5SDimitry Andric     case Hexagon::S2_cl1p:
2108*0b57cec5SDimitry Andric     case Hexagon::S2_clb:
2109*0b57cec5SDimitry Andric     case Hexagon::S2_clbp:
2110*0b57cec5SDimitry Andric     {
2111*0b57cec5SDimitry Andric       using namespace Hexagon;
2112*0b57cec5SDimitry Andric 
2113*0b57cec5SDimitry Andric       bool OnlyZeros = (Opc == S2_cl0) || (Opc == S2_cl0p);
2114*0b57cec5SDimitry Andric       bool OnlyOnes =  (Opc == S2_cl1) || (Opc == S2_cl1p);
2115*0b57cec5SDimitry Andric       RegisterSubReg R1(MI.getOperand(1));
2116*0b57cec5SDimitry Andric       assert(Inputs.has(R1.Reg));
2117*0b57cec5SDimitry Andric       LatticeCell T;
2118*0b57cec5SDimitry Andric       bool Eval = evaluateCLBr(R1, !OnlyOnes, !OnlyZeros, Inputs, T);
2119*0b57cec5SDimitry Andric       if (!Eval)
2120*0b57cec5SDimitry Andric         return false;
2121*0b57cec5SDimitry Andric       // All of these instructions return a 32-bit value. The evaluate
2122*0b57cec5SDimitry Andric       // will generate the same type as the operand, so truncate the
2123*0b57cec5SDimitry Andric       // result if necessary.
2124*0b57cec5SDimitry Andric       APInt C;
2125*0b57cec5SDimitry Andric       LatticeCell RC = Outputs.get(DefR.Reg);
2126*0b57cec5SDimitry Andric       for (unsigned i = 0; i < T.size(); ++i) {
2127*0b57cec5SDimitry Andric         const Constant *CI = T.Values[i];
2128*0b57cec5SDimitry Andric         if (constToInt(CI, C) && C.getBitWidth() > 32)
2129*0b57cec5SDimitry Andric           CI = intToConst(C.trunc(32));
2130*0b57cec5SDimitry Andric         RC.add(CI);
2131*0b57cec5SDimitry Andric       }
2132*0b57cec5SDimitry Andric       Outputs.update(DefR.Reg, RC);
2133*0b57cec5SDimitry Andric       break;
2134*0b57cec5SDimitry Andric     }
2135*0b57cec5SDimitry Andric 
2136*0b57cec5SDimitry Andric     case Hexagon::S4_extract:
2137*0b57cec5SDimitry Andric     case Hexagon::S4_extractp:
2138*0b57cec5SDimitry Andric     case Hexagon::S2_extractu:
2139*0b57cec5SDimitry Andric     case Hexagon::S2_extractup:
2140*0b57cec5SDimitry Andric     {
2141*0b57cec5SDimitry Andric       bool Signed = (Opc == Hexagon::S4_extract) ||
2142*0b57cec5SDimitry Andric                     (Opc == Hexagon::S4_extractp);
2143*0b57cec5SDimitry Andric       RegisterSubReg R1(MI.getOperand(1));
2144*0b57cec5SDimitry Andric       unsigned BW = getRegBitWidth(R1.Reg);
2145*0b57cec5SDimitry Andric       unsigned Bits = MI.getOperand(2).getImm();
2146*0b57cec5SDimitry Andric       unsigned Offset = MI.getOperand(3).getImm();
2147*0b57cec5SDimitry Andric       LatticeCell RC = Outputs.get(DefR.Reg);
2148*0b57cec5SDimitry Andric       if (Offset >= BW) {
2149*0b57cec5SDimitry Andric         APInt Zero(BW, 0, false);
2150*0b57cec5SDimitry Andric         RC.add(intToConst(Zero));
2151*0b57cec5SDimitry Andric         break;
2152*0b57cec5SDimitry Andric       }
2153*0b57cec5SDimitry Andric       if (Offset+Bits > BW) {
2154*0b57cec5SDimitry Andric         // If the requested bitfield extends beyond the most significant bit,
2155*0b57cec5SDimitry Andric         // the extra bits are treated as 0s. To emulate this behavior, reduce
2156*0b57cec5SDimitry Andric         // the number of requested bits, and make the extract unsigned.
2157*0b57cec5SDimitry Andric         Bits = BW-Offset;
2158*0b57cec5SDimitry Andric         Signed = false;
2159*0b57cec5SDimitry Andric       }
2160*0b57cec5SDimitry Andric       bool Eval = evaluateEXTRACTr(R1, BW, Bits, Offset, Signed, Inputs, RC);
2161*0b57cec5SDimitry Andric       if (!Eval)
2162*0b57cec5SDimitry Andric         return false;
2163*0b57cec5SDimitry Andric       Outputs.update(DefR.Reg, RC);
2164*0b57cec5SDimitry Andric       break;
2165*0b57cec5SDimitry Andric     }
2166*0b57cec5SDimitry Andric 
2167*0b57cec5SDimitry Andric     case Hexagon::S2_vsplatrb:
2168*0b57cec5SDimitry Andric     case Hexagon::S2_vsplatrh:
2169*0b57cec5SDimitry Andric     // vabsh, vabsh:sat
2170*0b57cec5SDimitry Andric     // vabsw, vabsw:sat
2171*0b57cec5SDimitry Andric     // vconj:sat
2172*0b57cec5SDimitry Andric     // vrndwh, vrndwh:sat
2173*0b57cec5SDimitry Andric     // vsathb, vsathub, vsatwuh
2174*0b57cec5SDimitry Andric     // vsxtbh, vsxthw
2175*0b57cec5SDimitry Andric     // vtrunehb, vtrunohb
2176*0b57cec5SDimitry Andric     // vzxtbh, vzxthw
2177*0b57cec5SDimitry Andric     {
2178*0b57cec5SDimitry Andric       bool Eval = evaluateHexVector1(MI, Inputs, Outputs);
2179*0b57cec5SDimitry Andric       if (!Eval)
2180*0b57cec5SDimitry Andric         return false;
2181*0b57cec5SDimitry Andric       break;
2182*0b57cec5SDimitry Andric     }
2183*0b57cec5SDimitry Andric 
2184*0b57cec5SDimitry Andric     // TODO:
2185*0b57cec5SDimitry Andric     // A2_vaddh
2186*0b57cec5SDimitry Andric     // A2_vaddhs
2187*0b57cec5SDimitry Andric     // A2_vaddw
2188*0b57cec5SDimitry Andric     // A2_vaddws
2189*0b57cec5SDimitry Andric   }
2190*0b57cec5SDimitry Andric 
2191*0b57cec5SDimitry Andric   return true;
2192*0b57cec5SDimitry Andric }
2193*0b57cec5SDimitry Andric 
2194*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluate(const RegisterSubReg &R,
2195*0b57cec5SDimitry Andric       const LatticeCell &Input, LatticeCell &Result) {
2196*0b57cec5SDimitry Andric   if (!R.SubReg) {
2197*0b57cec5SDimitry Andric     Result = Input;
2198*0b57cec5SDimitry Andric     return true;
2199*0b57cec5SDimitry Andric   }
2200*0b57cec5SDimitry Andric   const TargetRegisterClass *RC = MRI->getRegClass(R.Reg);
2201*0b57cec5SDimitry Andric   if (RC != &Hexagon::DoubleRegsRegClass)
2202*0b57cec5SDimitry Andric     return false;
2203*0b57cec5SDimitry Andric   if (R.SubReg != Hexagon::isub_lo && R.SubReg != Hexagon::isub_hi)
2204*0b57cec5SDimitry Andric     return false;
2205*0b57cec5SDimitry Andric 
2206*0b57cec5SDimitry Andric   assert(!Input.isTop());
2207*0b57cec5SDimitry Andric   if (Input.isBottom())
2208*0b57cec5SDimitry Andric     return false;
2209*0b57cec5SDimitry Andric 
2210*0b57cec5SDimitry Andric   using P = ConstantProperties;
2211*0b57cec5SDimitry Andric 
2212*0b57cec5SDimitry Andric   if (Input.isProperty()) {
2213*0b57cec5SDimitry Andric     uint32_t Ps = Input.properties();
2214*0b57cec5SDimitry Andric     if (Ps & (P::Zero|P::NaN)) {
2215*0b57cec5SDimitry Andric       uint32_t Ns = (Ps & (P::Zero|P::NaN|P::SignProperties));
2216*0b57cec5SDimitry Andric       Result.add(Ns);
2217*0b57cec5SDimitry Andric       return true;
2218*0b57cec5SDimitry Andric     }
2219*0b57cec5SDimitry Andric     if (R.SubReg == Hexagon::isub_hi) {
2220*0b57cec5SDimitry Andric       uint32_t Ns = (Ps & P::SignProperties);
2221*0b57cec5SDimitry Andric       Result.add(Ns);
2222*0b57cec5SDimitry Andric       return true;
2223*0b57cec5SDimitry Andric     }
2224*0b57cec5SDimitry Andric     return false;
2225*0b57cec5SDimitry Andric   }
2226*0b57cec5SDimitry Andric 
2227*0b57cec5SDimitry Andric   // The Input cell contains some known values. Pick the word corresponding
2228*0b57cec5SDimitry Andric   // to the subregister.
2229*0b57cec5SDimitry Andric   APInt A;
2230*0b57cec5SDimitry Andric   for (unsigned i = 0; i < Input.size(); ++i) {
2231*0b57cec5SDimitry Andric     const Constant *C = Input.Values[i];
2232*0b57cec5SDimitry Andric     if (!constToInt(C, A))
2233*0b57cec5SDimitry Andric       return false;
2234*0b57cec5SDimitry Andric     if (!A.isIntN(64))
2235*0b57cec5SDimitry Andric       return false;
2236*0b57cec5SDimitry Andric     uint64_t U = A.getZExtValue();
2237*0b57cec5SDimitry Andric     if (R.SubReg == Hexagon::isub_hi)
2238*0b57cec5SDimitry Andric       U >>= 32;
2239*0b57cec5SDimitry Andric     U &= 0xFFFFFFFFULL;
2240*0b57cec5SDimitry Andric     uint32_t U32 = Lo_32(U);
2241*0b57cec5SDimitry Andric     int32_t V32;
2242*0b57cec5SDimitry Andric     memcpy(&V32, &U32, sizeof V32);
2243*0b57cec5SDimitry Andric     IntegerType *Ty = Type::getInt32Ty(CX);
2244*0b57cec5SDimitry Andric     const ConstantInt *C32 = ConstantInt::get(Ty, static_cast<int64_t>(V32));
2245*0b57cec5SDimitry Andric     Result.add(C32);
2246*0b57cec5SDimitry Andric   }
2247*0b57cec5SDimitry Andric   return true;
2248*0b57cec5SDimitry Andric }
2249*0b57cec5SDimitry Andric 
2250*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluate(const MachineInstr &BrI,
2251*0b57cec5SDimitry Andric       const CellMap &Inputs, SetVector<const MachineBasicBlock*> &Targets,
2252*0b57cec5SDimitry Andric       bool &FallsThru) {
2253*0b57cec5SDimitry Andric   // We need to evaluate one branch at a time. TII::analyzeBranch checks
2254*0b57cec5SDimitry Andric   // all the branches in a basic block at once, so we cannot use it.
2255*0b57cec5SDimitry Andric   unsigned Opc = BrI.getOpcode();
2256*0b57cec5SDimitry Andric   bool SimpleBranch = false;
2257*0b57cec5SDimitry Andric   bool Negated = false;
2258*0b57cec5SDimitry Andric   switch (Opc) {
2259*0b57cec5SDimitry Andric     case Hexagon::J2_jumpf:
2260*0b57cec5SDimitry Andric     case Hexagon::J2_jumpfnew:
2261*0b57cec5SDimitry Andric     case Hexagon::J2_jumpfnewpt:
2262*0b57cec5SDimitry Andric       Negated = true;
2263*0b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
2264*0b57cec5SDimitry Andric     case Hexagon::J2_jumpt:
2265*0b57cec5SDimitry Andric     case Hexagon::J2_jumptnew:
2266*0b57cec5SDimitry Andric     case Hexagon::J2_jumptnewpt:
2267*0b57cec5SDimitry Andric       // Simple branch:  if([!]Pn) jump ...
2268*0b57cec5SDimitry Andric       // i.e. Op0 = predicate, Op1 = branch target.
2269*0b57cec5SDimitry Andric       SimpleBranch = true;
2270*0b57cec5SDimitry Andric       break;
2271*0b57cec5SDimitry Andric     case Hexagon::J2_jump:
2272*0b57cec5SDimitry Andric       Targets.insert(BrI.getOperand(0).getMBB());
2273*0b57cec5SDimitry Andric       FallsThru = false;
2274*0b57cec5SDimitry Andric       return true;
2275*0b57cec5SDimitry Andric     default:
2276*0b57cec5SDimitry Andric Undetermined:
2277*0b57cec5SDimitry Andric       // If the branch is of unknown type, assume that all successors are
2278*0b57cec5SDimitry Andric       // executable.
2279*0b57cec5SDimitry Andric       FallsThru = !BrI.isUnconditionalBranch();
2280*0b57cec5SDimitry Andric       return false;
2281*0b57cec5SDimitry Andric   }
2282*0b57cec5SDimitry Andric 
2283*0b57cec5SDimitry Andric   if (SimpleBranch) {
2284*0b57cec5SDimitry Andric     const MachineOperand &MD = BrI.getOperand(0);
2285*0b57cec5SDimitry Andric     RegisterSubReg PR(MD);
2286*0b57cec5SDimitry Andric     // If the condition operand has a subregister, this is not something
2287*0b57cec5SDimitry Andric     // we currently recognize.
2288*0b57cec5SDimitry Andric     if (PR.SubReg)
2289*0b57cec5SDimitry Andric       goto Undetermined;
2290*0b57cec5SDimitry Andric     assert(Inputs.has(PR.Reg));
2291*0b57cec5SDimitry Andric     const LatticeCell &PredC = Inputs.get(PR.Reg);
2292*0b57cec5SDimitry Andric     if (PredC.isBottom())
2293*0b57cec5SDimitry Andric       goto Undetermined;
2294*0b57cec5SDimitry Andric 
2295*0b57cec5SDimitry Andric     uint32_t Props = PredC.properties();
2296*0b57cec5SDimitry Andric     bool CTrue = false, CFalse = false;
2297*0b57cec5SDimitry Andric     if (Props & ConstantProperties::Zero)
2298*0b57cec5SDimitry Andric       CFalse = true;
2299*0b57cec5SDimitry Andric     else if (Props & ConstantProperties::NonZero)
2300*0b57cec5SDimitry Andric       CTrue = true;
2301*0b57cec5SDimitry Andric     // If the condition is not known to be either, bail out.
2302*0b57cec5SDimitry Andric     if (!CTrue && !CFalse)
2303*0b57cec5SDimitry Andric       goto Undetermined;
2304*0b57cec5SDimitry Andric 
2305*0b57cec5SDimitry Andric     const MachineBasicBlock *BranchTarget = BrI.getOperand(1).getMBB();
2306*0b57cec5SDimitry Andric 
2307*0b57cec5SDimitry Andric     FallsThru = false;
2308*0b57cec5SDimitry Andric     if ((!Negated && CTrue) || (Negated && CFalse))
2309*0b57cec5SDimitry Andric       Targets.insert(BranchTarget);
2310*0b57cec5SDimitry Andric     else if ((!Negated && CFalse) || (Negated && CTrue))
2311*0b57cec5SDimitry Andric       FallsThru = true;
2312*0b57cec5SDimitry Andric     else
2313*0b57cec5SDimitry Andric       goto Undetermined;
2314*0b57cec5SDimitry Andric   }
2315*0b57cec5SDimitry Andric 
2316*0b57cec5SDimitry Andric   return true;
2317*0b57cec5SDimitry Andric }
2318*0b57cec5SDimitry Andric 
2319*0b57cec5SDimitry Andric bool HexagonConstEvaluator::rewrite(MachineInstr &MI, const CellMap &Inputs) {
2320*0b57cec5SDimitry Andric   if (MI.isBranch())
2321*0b57cec5SDimitry Andric     return rewriteHexBranch(MI, Inputs);
2322*0b57cec5SDimitry Andric 
2323*0b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
2324*0b57cec5SDimitry Andric   switch (Opc) {
2325*0b57cec5SDimitry Andric     default:
2326*0b57cec5SDimitry Andric       break;
2327*0b57cec5SDimitry Andric     case Hexagon::A2_tfrsi:
2328*0b57cec5SDimitry Andric     case Hexagon::A2_tfrpi:
2329*0b57cec5SDimitry Andric     case Hexagon::CONST32:
2330*0b57cec5SDimitry Andric     case Hexagon::CONST64:
2331*0b57cec5SDimitry Andric     case Hexagon::PS_true:
2332*0b57cec5SDimitry Andric     case Hexagon::PS_false:
2333*0b57cec5SDimitry Andric       return false;
2334*0b57cec5SDimitry Andric   }
2335*0b57cec5SDimitry Andric 
2336*0b57cec5SDimitry Andric   unsigned NumOp = MI.getNumOperands();
2337*0b57cec5SDimitry Andric   if (NumOp == 0)
2338*0b57cec5SDimitry Andric     return false;
2339*0b57cec5SDimitry Andric 
2340*0b57cec5SDimitry Andric   bool AllDefs, Changed;
2341*0b57cec5SDimitry Andric   Changed = rewriteHexConstDefs(MI, Inputs, AllDefs);
2342*0b57cec5SDimitry Andric   // If not all defs have been rewritten (i.e. the instruction defines
2343*0b57cec5SDimitry Andric   // a register that is not compile-time constant), then try to rewrite
2344*0b57cec5SDimitry Andric   // register operands that are known to be constant with immediates.
2345*0b57cec5SDimitry Andric   if (!AllDefs)
2346*0b57cec5SDimitry Andric     Changed |= rewriteHexConstUses(MI, Inputs);
2347*0b57cec5SDimitry Andric 
2348*0b57cec5SDimitry Andric   return Changed;
2349*0b57cec5SDimitry Andric }
2350*0b57cec5SDimitry Andric 
2351*0b57cec5SDimitry Andric unsigned HexagonConstEvaluator::getRegBitWidth(unsigned Reg) const {
2352*0b57cec5SDimitry Andric   const TargetRegisterClass *RC = MRI->getRegClass(Reg);
2353*0b57cec5SDimitry Andric   if (Hexagon::IntRegsRegClass.hasSubClassEq(RC))
2354*0b57cec5SDimitry Andric     return 32;
2355*0b57cec5SDimitry Andric   if (Hexagon::DoubleRegsRegClass.hasSubClassEq(RC))
2356*0b57cec5SDimitry Andric     return 64;
2357*0b57cec5SDimitry Andric   if (Hexagon::PredRegsRegClass.hasSubClassEq(RC))
2358*0b57cec5SDimitry Andric     return 8;
2359*0b57cec5SDimitry Andric   llvm_unreachable("Invalid register");
2360*0b57cec5SDimitry Andric   return 0;
2361*0b57cec5SDimitry Andric }
2362*0b57cec5SDimitry Andric 
2363*0b57cec5SDimitry Andric uint32_t HexagonConstEvaluator::getCmp(unsigned Opc) {
2364*0b57cec5SDimitry Andric   switch (Opc) {
2365*0b57cec5SDimitry Andric     case Hexagon::C2_cmpeq:
2366*0b57cec5SDimitry Andric     case Hexagon::C2_cmpeqp:
2367*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbeq:
2368*0b57cec5SDimitry Andric     case Hexagon::A4_cmpheq:
2369*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbeqi:
2370*0b57cec5SDimitry Andric     case Hexagon::A4_cmpheqi:
2371*0b57cec5SDimitry Andric     case Hexagon::C2_cmpeqi:
2372*0b57cec5SDimitry Andric     case Hexagon::J4_cmpeqn1_t_jumpnv_nt:
2373*0b57cec5SDimitry Andric     case Hexagon::J4_cmpeqn1_t_jumpnv_t:
2374*0b57cec5SDimitry Andric     case Hexagon::J4_cmpeqi_t_jumpnv_nt:
2375*0b57cec5SDimitry Andric     case Hexagon::J4_cmpeqi_t_jumpnv_t:
2376*0b57cec5SDimitry Andric     case Hexagon::J4_cmpeq_t_jumpnv_nt:
2377*0b57cec5SDimitry Andric     case Hexagon::J4_cmpeq_t_jumpnv_t:
2378*0b57cec5SDimitry Andric       return Comparison::EQ;
2379*0b57cec5SDimitry Andric 
2380*0b57cec5SDimitry Andric     case Hexagon::C4_cmpneq:
2381*0b57cec5SDimitry Andric     case Hexagon::C4_cmpneqi:
2382*0b57cec5SDimitry Andric     case Hexagon::J4_cmpeqn1_f_jumpnv_nt:
2383*0b57cec5SDimitry Andric     case Hexagon::J4_cmpeqn1_f_jumpnv_t:
2384*0b57cec5SDimitry Andric     case Hexagon::J4_cmpeqi_f_jumpnv_nt:
2385*0b57cec5SDimitry Andric     case Hexagon::J4_cmpeqi_f_jumpnv_t:
2386*0b57cec5SDimitry Andric     case Hexagon::J4_cmpeq_f_jumpnv_nt:
2387*0b57cec5SDimitry Andric     case Hexagon::J4_cmpeq_f_jumpnv_t:
2388*0b57cec5SDimitry Andric       return Comparison::NE;
2389*0b57cec5SDimitry Andric 
2390*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgt:
2391*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgtp:
2392*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbgt:
2393*0b57cec5SDimitry Andric     case Hexagon::A4_cmphgt:
2394*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbgti:
2395*0b57cec5SDimitry Andric     case Hexagon::A4_cmphgti:
2396*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgti:
2397*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgtn1_t_jumpnv_nt:
2398*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgtn1_t_jumpnv_t:
2399*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgti_t_jumpnv_nt:
2400*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgti_t_jumpnv_t:
2401*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgt_t_jumpnv_nt:
2402*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgt_t_jumpnv_t:
2403*0b57cec5SDimitry Andric       return Comparison::GTs;
2404*0b57cec5SDimitry Andric 
2405*0b57cec5SDimitry Andric     case Hexagon::C4_cmplte:
2406*0b57cec5SDimitry Andric     case Hexagon::C4_cmpltei:
2407*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgtn1_f_jumpnv_nt:
2408*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgtn1_f_jumpnv_t:
2409*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgti_f_jumpnv_nt:
2410*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgti_f_jumpnv_t:
2411*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgt_f_jumpnv_nt:
2412*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgt_f_jumpnv_t:
2413*0b57cec5SDimitry Andric       return Comparison::LEs;
2414*0b57cec5SDimitry Andric 
2415*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgtu:
2416*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgtup:
2417*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbgtu:
2418*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbgtui:
2419*0b57cec5SDimitry Andric     case Hexagon::A4_cmphgtu:
2420*0b57cec5SDimitry Andric     case Hexagon::A4_cmphgtui:
2421*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgtui:
2422*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgtui_t_jumpnv_nt:
2423*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgtui_t_jumpnv_t:
2424*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgtu_t_jumpnv_nt:
2425*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgtu_t_jumpnv_t:
2426*0b57cec5SDimitry Andric       return Comparison::GTu;
2427*0b57cec5SDimitry Andric 
2428*0b57cec5SDimitry Andric     case Hexagon::J4_cmpltu_f_jumpnv_nt:
2429*0b57cec5SDimitry Andric     case Hexagon::J4_cmpltu_f_jumpnv_t:
2430*0b57cec5SDimitry Andric       return Comparison::GEu;
2431*0b57cec5SDimitry Andric 
2432*0b57cec5SDimitry Andric     case Hexagon::J4_cmpltu_t_jumpnv_nt:
2433*0b57cec5SDimitry Andric     case Hexagon::J4_cmpltu_t_jumpnv_t:
2434*0b57cec5SDimitry Andric       return Comparison::LTu;
2435*0b57cec5SDimitry Andric 
2436*0b57cec5SDimitry Andric     case Hexagon::J4_cmplt_f_jumpnv_nt:
2437*0b57cec5SDimitry Andric     case Hexagon::J4_cmplt_f_jumpnv_t:
2438*0b57cec5SDimitry Andric       return Comparison::GEs;
2439*0b57cec5SDimitry Andric 
2440*0b57cec5SDimitry Andric     case Hexagon::C4_cmplteu:
2441*0b57cec5SDimitry Andric     case Hexagon::C4_cmplteui:
2442*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgtui_f_jumpnv_nt:
2443*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgtui_f_jumpnv_t:
2444*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgtu_f_jumpnv_nt:
2445*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgtu_f_jumpnv_t:
2446*0b57cec5SDimitry Andric       return Comparison::LEu;
2447*0b57cec5SDimitry Andric 
2448*0b57cec5SDimitry Andric     case Hexagon::J4_cmplt_t_jumpnv_nt:
2449*0b57cec5SDimitry Andric     case Hexagon::J4_cmplt_t_jumpnv_t:
2450*0b57cec5SDimitry Andric       return Comparison::LTs;
2451*0b57cec5SDimitry Andric 
2452*0b57cec5SDimitry Andric     default:
2453*0b57cec5SDimitry Andric       break;
2454*0b57cec5SDimitry Andric   }
2455*0b57cec5SDimitry Andric   return Comparison::Unk;
2456*0b57cec5SDimitry Andric }
2457*0b57cec5SDimitry Andric 
2458*0b57cec5SDimitry Andric APInt HexagonConstEvaluator::getCmpImm(unsigned Opc, unsigned OpX,
2459*0b57cec5SDimitry Andric       const MachineOperand &MO) {
2460*0b57cec5SDimitry Andric   bool Signed = false;
2461*0b57cec5SDimitry Andric   switch (Opc) {
2462*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbgtui:   // u7
2463*0b57cec5SDimitry Andric     case Hexagon::A4_cmphgtui:   // u7
2464*0b57cec5SDimitry Andric       break;
2465*0b57cec5SDimitry Andric     case Hexagon::A4_cmpheqi:    // s8
2466*0b57cec5SDimitry Andric     case Hexagon::C4_cmpneqi:   // s8
2467*0b57cec5SDimitry Andric       Signed = true;
2468*0b57cec5SDimitry Andric       break;
2469*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbeqi:    // u8
2470*0b57cec5SDimitry Andric       break;
2471*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgtui:      // u9
2472*0b57cec5SDimitry Andric     case Hexagon::C4_cmplteui:  // u9
2473*0b57cec5SDimitry Andric       break;
2474*0b57cec5SDimitry Andric     case Hexagon::C2_cmpeqi:       // s10
2475*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgti:       // s10
2476*0b57cec5SDimitry Andric     case Hexagon::C4_cmpltei:   // s10
2477*0b57cec5SDimitry Andric       Signed = true;
2478*0b57cec5SDimitry Andric       break;
2479*0b57cec5SDimitry Andric     case Hexagon::J4_cmpeqi_f_jumpnv_nt:   // u5
2480*0b57cec5SDimitry Andric     case Hexagon::J4_cmpeqi_f_jumpnv_t:    // u5
2481*0b57cec5SDimitry Andric     case Hexagon::J4_cmpeqi_t_jumpnv_nt:   // u5
2482*0b57cec5SDimitry Andric     case Hexagon::J4_cmpeqi_t_jumpnv_t:    // u5
2483*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgti_f_jumpnv_nt:   // u5
2484*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgti_f_jumpnv_t:    // u5
2485*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgti_t_jumpnv_nt:   // u5
2486*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgti_t_jumpnv_t:    // u5
2487*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgtui_f_jumpnv_nt:  // u5
2488*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgtui_f_jumpnv_t:   // u5
2489*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgtui_t_jumpnv_nt:  // u5
2490*0b57cec5SDimitry Andric     case Hexagon::J4_cmpgtui_t_jumpnv_t:   // u5
2491*0b57cec5SDimitry Andric       break;
2492*0b57cec5SDimitry Andric     default:
2493*0b57cec5SDimitry Andric       llvm_unreachable("Unhandled instruction");
2494*0b57cec5SDimitry Andric       break;
2495*0b57cec5SDimitry Andric   }
2496*0b57cec5SDimitry Andric 
2497*0b57cec5SDimitry Andric   uint64_t Val = MO.getImm();
2498*0b57cec5SDimitry Andric   return APInt(32, Val, Signed);
2499*0b57cec5SDimitry Andric }
2500*0b57cec5SDimitry Andric 
2501*0b57cec5SDimitry Andric void HexagonConstEvaluator::replaceWithNop(MachineInstr &MI) {
2502*0b57cec5SDimitry Andric   MI.setDesc(HII.get(Hexagon::A2_nop));
2503*0b57cec5SDimitry Andric   while (MI.getNumOperands() > 0)
2504*0b57cec5SDimitry Andric     MI.RemoveOperand(0);
2505*0b57cec5SDimitry Andric }
2506*0b57cec5SDimitry Andric 
2507*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexRSEQ32(RegisterSubReg RL, RegisterSubReg RH,
2508*0b57cec5SDimitry Andric       const CellMap &Inputs, LatticeCell &Result) {
2509*0b57cec5SDimitry Andric   assert(Inputs.has(RL.Reg) && Inputs.has(RH.Reg));
2510*0b57cec5SDimitry Andric   LatticeCell LSL, LSH;
2511*0b57cec5SDimitry Andric   if (!getCell(RL, Inputs, LSL) || !getCell(RH, Inputs, LSH))
2512*0b57cec5SDimitry Andric     return false;
2513*0b57cec5SDimitry Andric   if (LSL.isProperty() || LSH.isProperty())
2514*0b57cec5SDimitry Andric     return false;
2515*0b57cec5SDimitry Andric 
2516*0b57cec5SDimitry Andric   unsigned LN = LSL.size(), HN = LSH.size();
2517*0b57cec5SDimitry Andric   SmallVector<APInt,4> LoVs(LN), HiVs(HN);
2518*0b57cec5SDimitry Andric   for (unsigned i = 0; i < LN; ++i) {
2519*0b57cec5SDimitry Andric     bool Eval = constToInt(LSL.Values[i], LoVs[i]);
2520*0b57cec5SDimitry Andric     if (!Eval)
2521*0b57cec5SDimitry Andric       return false;
2522*0b57cec5SDimitry Andric     assert(LoVs[i].getBitWidth() == 32);
2523*0b57cec5SDimitry Andric   }
2524*0b57cec5SDimitry Andric   for (unsigned i = 0; i < HN; ++i) {
2525*0b57cec5SDimitry Andric     bool Eval = constToInt(LSH.Values[i], HiVs[i]);
2526*0b57cec5SDimitry Andric     if (!Eval)
2527*0b57cec5SDimitry Andric       return false;
2528*0b57cec5SDimitry Andric     assert(HiVs[i].getBitWidth() == 32);
2529*0b57cec5SDimitry Andric   }
2530*0b57cec5SDimitry Andric 
2531*0b57cec5SDimitry Andric   for (unsigned i = 0; i < HiVs.size(); ++i) {
2532*0b57cec5SDimitry Andric     APInt HV = HiVs[i].zextOrSelf(64) << 32;
2533*0b57cec5SDimitry Andric     for (unsigned j = 0; j < LoVs.size(); ++j) {
2534*0b57cec5SDimitry Andric       APInt LV = LoVs[j].zextOrSelf(64);
2535*0b57cec5SDimitry Andric       const Constant *C = intToConst(HV | LV);
2536*0b57cec5SDimitry Andric       Result.add(C);
2537*0b57cec5SDimitry Andric       if (Result.isBottom())
2538*0b57cec5SDimitry Andric         return false;
2539*0b57cec5SDimitry Andric     }
2540*0b57cec5SDimitry Andric   }
2541*0b57cec5SDimitry Andric   return !Result.isBottom();
2542*0b57cec5SDimitry Andric }
2543*0b57cec5SDimitry Andric 
2544*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexCompare(const MachineInstr &MI,
2545*0b57cec5SDimitry Andric       const CellMap &Inputs, CellMap &Outputs) {
2546*0b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
2547*0b57cec5SDimitry Andric   bool Classic = false;
2548*0b57cec5SDimitry Andric   switch (Opc) {
2549*0b57cec5SDimitry Andric     case Hexagon::C2_cmpeq:
2550*0b57cec5SDimitry Andric     case Hexagon::C2_cmpeqp:
2551*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgt:
2552*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgtp:
2553*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgtu:
2554*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgtup:
2555*0b57cec5SDimitry Andric     case Hexagon::C2_cmpeqi:
2556*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgti:
2557*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgtui:
2558*0b57cec5SDimitry Andric       // Classic compare:  Dst0 = CMP Src1, Src2
2559*0b57cec5SDimitry Andric       Classic = true;
2560*0b57cec5SDimitry Andric       break;
2561*0b57cec5SDimitry Andric     default:
2562*0b57cec5SDimitry Andric       // Not handling other compare instructions now.
2563*0b57cec5SDimitry Andric       return false;
2564*0b57cec5SDimitry Andric   }
2565*0b57cec5SDimitry Andric 
2566*0b57cec5SDimitry Andric   if (Classic) {
2567*0b57cec5SDimitry Andric     const MachineOperand &Src1 = MI.getOperand(1);
2568*0b57cec5SDimitry Andric     const MachineOperand &Src2 = MI.getOperand(2);
2569*0b57cec5SDimitry Andric 
2570*0b57cec5SDimitry Andric     bool Result;
2571*0b57cec5SDimitry Andric     unsigned Opc = MI.getOpcode();
2572*0b57cec5SDimitry Andric     bool Computed = evaluateHexCompare2(Opc, Src1, Src2, Inputs, Result);
2573*0b57cec5SDimitry Andric     if (Computed) {
2574*0b57cec5SDimitry Andric       // Only create a zero/non-zero cell. At this time there isn't really
2575*0b57cec5SDimitry Andric       // much need for specific values.
2576*0b57cec5SDimitry Andric       RegisterSubReg DefR(MI.getOperand(0));
2577*0b57cec5SDimitry Andric       LatticeCell L = Outputs.get(DefR.Reg);
2578*0b57cec5SDimitry Andric       uint32_t P = Result ? ConstantProperties::NonZero
2579*0b57cec5SDimitry Andric                           : ConstantProperties::Zero;
2580*0b57cec5SDimitry Andric       L.add(P);
2581*0b57cec5SDimitry Andric       Outputs.update(DefR.Reg, L);
2582*0b57cec5SDimitry Andric       return true;
2583*0b57cec5SDimitry Andric     }
2584*0b57cec5SDimitry Andric   }
2585*0b57cec5SDimitry Andric 
2586*0b57cec5SDimitry Andric   return false;
2587*0b57cec5SDimitry Andric }
2588*0b57cec5SDimitry Andric 
2589*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexCompare2(unsigned Opc,
2590*0b57cec5SDimitry Andric       const MachineOperand &Src1, const MachineOperand &Src2,
2591*0b57cec5SDimitry Andric       const CellMap &Inputs, bool &Result) {
2592*0b57cec5SDimitry Andric   uint32_t Cmp = getCmp(Opc);
2593*0b57cec5SDimitry Andric   bool Reg1 = Src1.isReg(), Reg2 = Src2.isReg();
2594*0b57cec5SDimitry Andric   bool Imm1 = Src1.isImm(), Imm2 = Src2.isImm();
2595*0b57cec5SDimitry Andric   if (Reg1) {
2596*0b57cec5SDimitry Andric     RegisterSubReg R1(Src1);
2597*0b57cec5SDimitry Andric     if (Reg2) {
2598*0b57cec5SDimitry Andric       RegisterSubReg R2(Src2);
2599*0b57cec5SDimitry Andric       return evaluateCMPrr(Cmp, R1, R2, Inputs, Result);
2600*0b57cec5SDimitry Andric     } else if (Imm2) {
2601*0b57cec5SDimitry Andric       APInt A2 = getCmpImm(Opc, 2, Src2);
2602*0b57cec5SDimitry Andric       return evaluateCMPri(Cmp, R1, A2, Inputs, Result);
2603*0b57cec5SDimitry Andric     }
2604*0b57cec5SDimitry Andric   } else if (Imm1) {
2605*0b57cec5SDimitry Andric     APInt A1 = getCmpImm(Opc, 1, Src1);
2606*0b57cec5SDimitry Andric     if (Reg2) {
2607*0b57cec5SDimitry Andric       RegisterSubReg R2(Src2);
2608*0b57cec5SDimitry Andric       uint32_t NegCmp = Comparison::negate(Cmp);
2609*0b57cec5SDimitry Andric       return evaluateCMPri(NegCmp, R2, A1, Inputs, Result);
2610*0b57cec5SDimitry Andric     } else if (Imm2) {
2611*0b57cec5SDimitry Andric       APInt A2 = getCmpImm(Opc, 2, Src2);
2612*0b57cec5SDimitry Andric       return evaluateCMPii(Cmp, A1, A2, Result);
2613*0b57cec5SDimitry Andric     }
2614*0b57cec5SDimitry Andric   }
2615*0b57cec5SDimitry Andric   // Unknown kind of comparison.
2616*0b57cec5SDimitry Andric   return false;
2617*0b57cec5SDimitry Andric }
2618*0b57cec5SDimitry Andric 
2619*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexLogical(const MachineInstr &MI,
2620*0b57cec5SDimitry Andric       const CellMap &Inputs, CellMap &Outputs) {
2621*0b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
2622*0b57cec5SDimitry Andric   if (MI.getNumOperands() != 3)
2623*0b57cec5SDimitry Andric     return false;
2624*0b57cec5SDimitry Andric   const MachineOperand &Src1 = MI.getOperand(1);
2625*0b57cec5SDimitry Andric   const MachineOperand &Src2 = MI.getOperand(2);
2626*0b57cec5SDimitry Andric   RegisterSubReg R1(Src1);
2627*0b57cec5SDimitry Andric   bool Eval = false;
2628*0b57cec5SDimitry Andric   LatticeCell RC;
2629*0b57cec5SDimitry Andric   switch (Opc) {
2630*0b57cec5SDimitry Andric     default:
2631*0b57cec5SDimitry Andric       return false;
2632*0b57cec5SDimitry Andric     case Hexagon::A2_and:
2633*0b57cec5SDimitry Andric     case Hexagon::A2_andp:
2634*0b57cec5SDimitry Andric       Eval = evaluateANDrr(R1, RegisterSubReg(Src2), Inputs, RC);
2635*0b57cec5SDimitry Andric       break;
2636*0b57cec5SDimitry Andric     case Hexagon::A2_andir: {
2637*0b57cec5SDimitry Andric       if (!Src2.isImm())
2638*0b57cec5SDimitry Andric         return false;
2639*0b57cec5SDimitry Andric       APInt A(32, Src2.getImm(), true);
2640*0b57cec5SDimitry Andric       Eval = evaluateANDri(R1, A, Inputs, RC);
2641*0b57cec5SDimitry Andric       break;
2642*0b57cec5SDimitry Andric     }
2643*0b57cec5SDimitry Andric     case Hexagon::A2_or:
2644*0b57cec5SDimitry Andric     case Hexagon::A2_orp:
2645*0b57cec5SDimitry Andric       Eval = evaluateORrr(R1, RegisterSubReg(Src2), Inputs, RC);
2646*0b57cec5SDimitry Andric       break;
2647*0b57cec5SDimitry Andric     case Hexagon::A2_orir: {
2648*0b57cec5SDimitry Andric       if (!Src2.isImm())
2649*0b57cec5SDimitry Andric         return false;
2650*0b57cec5SDimitry Andric       APInt A(32, Src2.getImm(), true);
2651*0b57cec5SDimitry Andric       Eval = evaluateORri(R1, A, Inputs, RC);
2652*0b57cec5SDimitry Andric       break;
2653*0b57cec5SDimitry Andric     }
2654*0b57cec5SDimitry Andric     case Hexagon::A2_xor:
2655*0b57cec5SDimitry Andric     case Hexagon::A2_xorp:
2656*0b57cec5SDimitry Andric       Eval = evaluateXORrr(R1, RegisterSubReg(Src2), Inputs, RC);
2657*0b57cec5SDimitry Andric       break;
2658*0b57cec5SDimitry Andric   }
2659*0b57cec5SDimitry Andric   if (Eval) {
2660*0b57cec5SDimitry Andric     RegisterSubReg DefR(MI.getOperand(0));
2661*0b57cec5SDimitry Andric     Outputs.update(DefR.Reg, RC);
2662*0b57cec5SDimitry Andric   }
2663*0b57cec5SDimitry Andric   return Eval;
2664*0b57cec5SDimitry Andric }
2665*0b57cec5SDimitry Andric 
2666*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexCondMove(const MachineInstr &MI,
2667*0b57cec5SDimitry Andric       const CellMap &Inputs, CellMap &Outputs) {
2668*0b57cec5SDimitry Andric   // Dst0 = Cond1 ? Src2 : Src3
2669*0b57cec5SDimitry Andric   RegisterSubReg CR(MI.getOperand(1));
2670*0b57cec5SDimitry Andric   assert(Inputs.has(CR.Reg));
2671*0b57cec5SDimitry Andric   LatticeCell LS;
2672*0b57cec5SDimitry Andric   if (!getCell(CR, Inputs, LS))
2673*0b57cec5SDimitry Andric     return false;
2674*0b57cec5SDimitry Andric   uint32_t Ps = LS.properties();
2675*0b57cec5SDimitry Andric   unsigned TakeOp;
2676*0b57cec5SDimitry Andric   if (Ps & ConstantProperties::Zero)
2677*0b57cec5SDimitry Andric     TakeOp = 3;
2678*0b57cec5SDimitry Andric   else if (Ps & ConstantProperties::NonZero)
2679*0b57cec5SDimitry Andric     TakeOp = 2;
2680*0b57cec5SDimitry Andric   else
2681*0b57cec5SDimitry Andric     return false;
2682*0b57cec5SDimitry Andric 
2683*0b57cec5SDimitry Andric   const MachineOperand &ValOp = MI.getOperand(TakeOp);
2684*0b57cec5SDimitry Andric   RegisterSubReg DefR(MI.getOperand(0));
2685*0b57cec5SDimitry Andric   LatticeCell RC = Outputs.get(DefR.Reg);
2686*0b57cec5SDimitry Andric 
2687*0b57cec5SDimitry Andric   if (ValOp.isImm()) {
2688*0b57cec5SDimitry Andric     int64_t V = ValOp.getImm();
2689*0b57cec5SDimitry Andric     unsigned W = getRegBitWidth(DefR.Reg);
2690*0b57cec5SDimitry Andric     APInt A(W, V, true);
2691*0b57cec5SDimitry Andric     const Constant *C = intToConst(A);
2692*0b57cec5SDimitry Andric     RC.add(C);
2693*0b57cec5SDimitry Andric     Outputs.update(DefR.Reg, RC);
2694*0b57cec5SDimitry Andric     return true;
2695*0b57cec5SDimitry Andric   }
2696*0b57cec5SDimitry Andric   if (ValOp.isReg()) {
2697*0b57cec5SDimitry Andric     RegisterSubReg R(ValOp);
2698*0b57cec5SDimitry Andric     const LatticeCell &LR = Inputs.get(R.Reg);
2699*0b57cec5SDimitry Andric     LatticeCell LSR;
2700*0b57cec5SDimitry Andric     if (!evaluate(R, LR, LSR))
2701*0b57cec5SDimitry Andric       return false;
2702*0b57cec5SDimitry Andric     RC.meet(LSR);
2703*0b57cec5SDimitry Andric     Outputs.update(DefR.Reg, RC);
2704*0b57cec5SDimitry Andric     return true;
2705*0b57cec5SDimitry Andric   }
2706*0b57cec5SDimitry Andric   return false;
2707*0b57cec5SDimitry Andric }
2708*0b57cec5SDimitry Andric 
2709*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexExt(const MachineInstr &MI,
2710*0b57cec5SDimitry Andric       const CellMap &Inputs, CellMap &Outputs) {
2711*0b57cec5SDimitry Andric   // Dst0 = ext R1
2712*0b57cec5SDimitry Andric   RegisterSubReg R1(MI.getOperand(1));
2713*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
2714*0b57cec5SDimitry Andric 
2715*0b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
2716*0b57cec5SDimitry Andric   unsigned Bits;
2717*0b57cec5SDimitry Andric   switch (Opc) {
2718*0b57cec5SDimitry Andric     case Hexagon::A2_sxtb:
2719*0b57cec5SDimitry Andric     case Hexagon::A2_zxtb:
2720*0b57cec5SDimitry Andric       Bits = 8;
2721*0b57cec5SDimitry Andric       break;
2722*0b57cec5SDimitry Andric     case Hexagon::A2_sxth:
2723*0b57cec5SDimitry Andric     case Hexagon::A2_zxth:
2724*0b57cec5SDimitry Andric       Bits = 16;
2725*0b57cec5SDimitry Andric       break;
2726*0b57cec5SDimitry Andric     case Hexagon::A2_sxtw:
2727*0b57cec5SDimitry Andric       Bits = 32;
2728*0b57cec5SDimitry Andric       break;
2729*0b57cec5SDimitry Andric     default:
2730*0b57cec5SDimitry Andric       llvm_unreachable("Unhandled extension opcode");
2731*0b57cec5SDimitry Andric   }
2732*0b57cec5SDimitry Andric 
2733*0b57cec5SDimitry Andric   bool Signed = false;
2734*0b57cec5SDimitry Andric   switch (Opc) {
2735*0b57cec5SDimitry Andric     case Hexagon::A2_sxtb:
2736*0b57cec5SDimitry Andric     case Hexagon::A2_sxth:
2737*0b57cec5SDimitry Andric     case Hexagon::A2_sxtw:
2738*0b57cec5SDimitry Andric       Signed = true;
2739*0b57cec5SDimitry Andric       break;
2740*0b57cec5SDimitry Andric   }
2741*0b57cec5SDimitry Andric 
2742*0b57cec5SDimitry Andric   RegisterSubReg DefR(MI.getOperand(0));
2743*0b57cec5SDimitry Andric   unsigned BW = getRegBitWidth(DefR.Reg);
2744*0b57cec5SDimitry Andric   LatticeCell RC = Outputs.get(DefR.Reg);
2745*0b57cec5SDimitry Andric   bool Eval = Signed ? evaluateSEXTr(R1, BW, Bits, Inputs, RC)
2746*0b57cec5SDimitry Andric                      : evaluateZEXTr(R1, BW, Bits, Inputs, RC);
2747*0b57cec5SDimitry Andric   if (!Eval)
2748*0b57cec5SDimitry Andric     return false;
2749*0b57cec5SDimitry Andric   Outputs.update(DefR.Reg, RC);
2750*0b57cec5SDimitry Andric   return true;
2751*0b57cec5SDimitry Andric }
2752*0b57cec5SDimitry Andric 
2753*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexVector1(const MachineInstr &MI,
2754*0b57cec5SDimitry Andric       const CellMap &Inputs, CellMap &Outputs) {
2755*0b57cec5SDimitry Andric   // DefR = op R1
2756*0b57cec5SDimitry Andric   RegisterSubReg DefR(MI.getOperand(0));
2757*0b57cec5SDimitry Andric   RegisterSubReg R1(MI.getOperand(1));
2758*0b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
2759*0b57cec5SDimitry Andric   LatticeCell RC = Outputs.get(DefR.Reg);
2760*0b57cec5SDimitry Andric   bool Eval;
2761*0b57cec5SDimitry Andric 
2762*0b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
2763*0b57cec5SDimitry Andric   switch (Opc) {
2764*0b57cec5SDimitry Andric     case Hexagon::S2_vsplatrb:
2765*0b57cec5SDimitry Andric       // Rd = 4 times Rs:0..7
2766*0b57cec5SDimitry Andric       Eval = evaluateSplatr(R1, 8, 4, Inputs, RC);
2767*0b57cec5SDimitry Andric       break;
2768*0b57cec5SDimitry Andric     case Hexagon::S2_vsplatrh:
2769*0b57cec5SDimitry Andric       // Rdd = 4 times Rs:0..15
2770*0b57cec5SDimitry Andric       Eval = evaluateSplatr(R1, 16, 4, Inputs, RC);
2771*0b57cec5SDimitry Andric       break;
2772*0b57cec5SDimitry Andric     default:
2773*0b57cec5SDimitry Andric       return false;
2774*0b57cec5SDimitry Andric   }
2775*0b57cec5SDimitry Andric 
2776*0b57cec5SDimitry Andric   if (!Eval)
2777*0b57cec5SDimitry Andric     return false;
2778*0b57cec5SDimitry Andric   Outputs.update(DefR.Reg, RC);
2779*0b57cec5SDimitry Andric   return true;
2780*0b57cec5SDimitry Andric }
2781*0b57cec5SDimitry Andric 
2782*0b57cec5SDimitry Andric bool HexagonConstEvaluator::rewriteHexConstDefs(MachineInstr &MI,
2783*0b57cec5SDimitry Andric       const CellMap &Inputs, bool &AllDefs) {
2784*0b57cec5SDimitry Andric   AllDefs = false;
2785*0b57cec5SDimitry Andric 
2786*0b57cec5SDimitry Andric   // Some diagnostics.
2787*0b57cec5SDimitry Andric   // LLVM_DEBUG({...}) gets confused with all this code as an argument.
2788*0b57cec5SDimitry Andric #ifndef NDEBUG
2789*0b57cec5SDimitry Andric   bool Debugging = DebugFlag && isCurrentDebugType(DEBUG_TYPE);
2790*0b57cec5SDimitry Andric   if (Debugging) {
2791*0b57cec5SDimitry Andric     bool Const = true, HasUse = false;
2792*0b57cec5SDimitry Andric     for (const MachineOperand &MO : MI.operands()) {
2793*0b57cec5SDimitry Andric       if (!MO.isReg() || !MO.isUse() || MO.isImplicit())
2794*0b57cec5SDimitry Andric         continue;
2795*0b57cec5SDimitry Andric       RegisterSubReg R(MO);
2796*0b57cec5SDimitry Andric       if (!TargetRegisterInfo::isVirtualRegister(R.Reg))
2797*0b57cec5SDimitry Andric         continue;
2798*0b57cec5SDimitry Andric       HasUse = true;
2799*0b57cec5SDimitry Andric       // PHIs can legitimately have "top" cells after propagation.
2800*0b57cec5SDimitry Andric       if (!MI.isPHI() && !Inputs.has(R.Reg)) {
2801*0b57cec5SDimitry Andric         dbgs() << "Top " << printReg(R.Reg, &HRI, R.SubReg)
2802*0b57cec5SDimitry Andric                << " in MI: " << MI;
2803*0b57cec5SDimitry Andric         continue;
2804*0b57cec5SDimitry Andric       }
2805*0b57cec5SDimitry Andric       const LatticeCell &L = Inputs.get(R.Reg);
2806*0b57cec5SDimitry Andric       Const &= L.isSingle();
2807*0b57cec5SDimitry Andric       if (!Const)
2808*0b57cec5SDimitry Andric         break;
2809*0b57cec5SDimitry Andric     }
2810*0b57cec5SDimitry Andric     if (HasUse && Const) {
2811*0b57cec5SDimitry Andric       if (!MI.isCopy()) {
2812*0b57cec5SDimitry Andric         dbgs() << "CONST: " << MI;
2813*0b57cec5SDimitry Andric         for (const MachineOperand &MO : MI.operands()) {
2814*0b57cec5SDimitry Andric           if (!MO.isReg() || !MO.isUse() || MO.isImplicit())
2815*0b57cec5SDimitry Andric             continue;
2816*0b57cec5SDimitry Andric           unsigned R = MO.getReg();
2817*0b57cec5SDimitry Andric           dbgs() << printReg(R, &TRI) << ": " << Inputs.get(R) << "\n";
2818*0b57cec5SDimitry Andric         }
2819*0b57cec5SDimitry Andric       }
2820*0b57cec5SDimitry Andric     }
2821*0b57cec5SDimitry Andric   }
2822*0b57cec5SDimitry Andric #endif
2823*0b57cec5SDimitry Andric 
2824*0b57cec5SDimitry Andric   // Avoid generating TFRIs for register transfers---this will keep the
2825*0b57cec5SDimitry Andric   // coalescing opportunities.
2826*0b57cec5SDimitry Andric   if (MI.isCopy())
2827*0b57cec5SDimitry Andric     return false;
2828*0b57cec5SDimitry Andric 
2829*0b57cec5SDimitry Andric   // Collect all virtual register-def operands.
2830*0b57cec5SDimitry Andric   SmallVector<unsigned,2> DefRegs;
2831*0b57cec5SDimitry Andric   for (const MachineOperand &MO : MI.operands()) {
2832*0b57cec5SDimitry Andric     if (!MO.isReg() || !MO.isDef())
2833*0b57cec5SDimitry Andric       continue;
2834*0b57cec5SDimitry Andric     unsigned R = MO.getReg();
2835*0b57cec5SDimitry Andric     if (!TargetRegisterInfo::isVirtualRegister(R))
2836*0b57cec5SDimitry Andric       continue;
2837*0b57cec5SDimitry Andric     assert(!MO.getSubReg());
2838*0b57cec5SDimitry Andric     assert(Inputs.has(R));
2839*0b57cec5SDimitry Andric     DefRegs.push_back(R);
2840*0b57cec5SDimitry Andric   }
2841*0b57cec5SDimitry Andric 
2842*0b57cec5SDimitry Andric   MachineBasicBlock &B = *MI.getParent();
2843*0b57cec5SDimitry Andric   const DebugLoc &DL = MI.getDebugLoc();
2844*0b57cec5SDimitry Andric   unsigned ChangedNum = 0;
2845*0b57cec5SDimitry Andric #ifndef NDEBUG
2846*0b57cec5SDimitry Andric   SmallVector<const MachineInstr*,4> NewInstrs;
2847*0b57cec5SDimitry Andric #endif
2848*0b57cec5SDimitry Andric 
2849*0b57cec5SDimitry Andric   // For each defined register, if it is a constant, create an instruction
2850*0b57cec5SDimitry Andric   //   NewR = const
2851*0b57cec5SDimitry Andric   // and replace all uses of the defined register with NewR.
2852*0b57cec5SDimitry Andric   for (unsigned i = 0, n = DefRegs.size(); i < n; ++i) {
2853*0b57cec5SDimitry Andric     unsigned R = DefRegs[i];
2854*0b57cec5SDimitry Andric     const LatticeCell &L = Inputs.get(R);
2855*0b57cec5SDimitry Andric     if (L.isBottom())
2856*0b57cec5SDimitry Andric       continue;
2857*0b57cec5SDimitry Andric     const TargetRegisterClass *RC = MRI->getRegClass(R);
2858*0b57cec5SDimitry Andric     MachineBasicBlock::iterator At = MI.getIterator();
2859*0b57cec5SDimitry Andric 
2860*0b57cec5SDimitry Andric     if (!L.isSingle()) {
2861*0b57cec5SDimitry Andric       // If this a zero/non-zero cell, we can fold a definition
2862*0b57cec5SDimitry Andric       // of a predicate register.
2863*0b57cec5SDimitry Andric       using P = ConstantProperties;
2864*0b57cec5SDimitry Andric 
2865*0b57cec5SDimitry Andric       uint64_t Ps = L.properties();
2866*0b57cec5SDimitry Andric       if (!(Ps & (P::Zero|P::NonZero)))
2867*0b57cec5SDimitry Andric         continue;
2868*0b57cec5SDimitry Andric       const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
2869*0b57cec5SDimitry Andric       if (RC != PredRC)
2870*0b57cec5SDimitry Andric         continue;
2871*0b57cec5SDimitry Andric       const MCInstrDesc *NewD = (Ps & P::Zero) ?
2872*0b57cec5SDimitry Andric         &HII.get(Hexagon::PS_false) :
2873*0b57cec5SDimitry Andric         &HII.get(Hexagon::PS_true);
2874*0b57cec5SDimitry Andric       unsigned NewR = MRI->createVirtualRegister(PredRC);
2875*0b57cec5SDimitry Andric       const MachineInstrBuilder &MIB = BuildMI(B, At, DL, *NewD, NewR);
2876*0b57cec5SDimitry Andric       (void)MIB;
2877*0b57cec5SDimitry Andric #ifndef NDEBUG
2878*0b57cec5SDimitry Andric       NewInstrs.push_back(&*MIB);
2879*0b57cec5SDimitry Andric #endif
2880*0b57cec5SDimitry Andric       replaceAllRegUsesWith(R, NewR);
2881*0b57cec5SDimitry Andric     } else {
2882*0b57cec5SDimitry Andric       // This cell has a single value.
2883*0b57cec5SDimitry Andric       APInt A;
2884*0b57cec5SDimitry Andric       if (!constToInt(L.Value, A) || !A.isSignedIntN(64))
2885*0b57cec5SDimitry Andric         continue;
2886*0b57cec5SDimitry Andric       const TargetRegisterClass *NewRC;
2887*0b57cec5SDimitry Andric       const MCInstrDesc *NewD;
2888*0b57cec5SDimitry Andric 
2889*0b57cec5SDimitry Andric       unsigned W = getRegBitWidth(R);
2890*0b57cec5SDimitry Andric       int64_t V = A.getSExtValue();
2891*0b57cec5SDimitry Andric       assert(W == 32 || W == 64);
2892*0b57cec5SDimitry Andric       if (W == 32)
2893*0b57cec5SDimitry Andric         NewRC = &Hexagon::IntRegsRegClass;
2894*0b57cec5SDimitry Andric       else
2895*0b57cec5SDimitry Andric         NewRC = &Hexagon::DoubleRegsRegClass;
2896*0b57cec5SDimitry Andric       unsigned NewR = MRI->createVirtualRegister(NewRC);
2897*0b57cec5SDimitry Andric       const MachineInstr *NewMI;
2898*0b57cec5SDimitry Andric 
2899*0b57cec5SDimitry Andric       if (W == 32) {
2900*0b57cec5SDimitry Andric         NewD = &HII.get(Hexagon::A2_tfrsi);
2901*0b57cec5SDimitry Andric         NewMI = BuildMI(B, At, DL, *NewD, NewR)
2902*0b57cec5SDimitry Andric                   .addImm(V);
2903*0b57cec5SDimitry Andric       } else {
2904*0b57cec5SDimitry Andric         if (A.isSignedIntN(8)) {
2905*0b57cec5SDimitry Andric           NewD = &HII.get(Hexagon::A2_tfrpi);
2906*0b57cec5SDimitry Andric           NewMI = BuildMI(B, At, DL, *NewD, NewR)
2907*0b57cec5SDimitry Andric                     .addImm(V);
2908*0b57cec5SDimitry Andric         } else {
2909*0b57cec5SDimitry Andric           int32_t Hi = V >> 32;
2910*0b57cec5SDimitry Andric           int32_t Lo = V & 0xFFFFFFFFLL;
2911*0b57cec5SDimitry Andric           if (isInt<8>(Hi) && isInt<8>(Lo)) {
2912*0b57cec5SDimitry Andric             NewD = &HII.get(Hexagon::A2_combineii);
2913*0b57cec5SDimitry Andric             NewMI = BuildMI(B, At, DL, *NewD, NewR)
2914*0b57cec5SDimitry Andric                       .addImm(Hi)
2915*0b57cec5SDimitry Andric                       .addImm(Lo);
2916*0b57cec5SDimitry Andric           } else {
2917*0b57cec5SDimitry Andric             NewD = &HII.get(Hexagon::CONST64);
2918*0b57cec5SDimitry Andric             NewMI = BuildMI(B, At, DL, *NewD, NewR)
2919*0b57cec5SDimitry Andric                       .addImm(V);
2920*0b57cec5SDimitry Andric           }
2921*0b57cec5SDimitry Andric         }
2922*0b57cec5SDimitry Andric       }
2923*0b57cec5SDimitry Andric       (void)NewMI;
2924*0b57cec5SDimitry Andric #ifndef NDEBUG
2925*0b57cec5SDimitry Andric       NewInstrs.push_back(NewMI);
2926*0b57cec5SDimitry Andric #endif
2927*0b57cec5SDimitry Andric       replaceAllRegUsesWith(R, NewR);
2928*0b57cec5SDimitry Andric     }
2929*0b57cec5SDimitry Andric     ChangedNum++;
2930*0b57cec5SDimitry Andric   }
2931*0b57cec5SDimitry Andric 
2932*0b57cec5SDimitry Andric   LLVM_DEBUG({
2933*0b57cec5SDimitry Andric     if (!NewInstrs.empty()) {
2934*0b57cec5SDimitry Andric       MachineFunction &MF = *MI.getParent()->getParent();
2935*0b57cec5SDimitry Andric       dbgs() << "In function: " << MF.getName() << "\n";
2936*0b57cec5SDimitry Andric       dbgs() << "Rewrite: for " << MI << "  created " << *NewInstrs[0];
2937*0b57cec5SDimitry Andric       for (unsigned i = 1; i < NewInstrs.size(); ++i)
2938*0b57cec5SDimitry Andric         dbgs() << "          " << *NewInstrs[i];
2939*0b57cec5SDimitry Andric     }
2940*0b57cec5SDimitry Andric   });
2941*0b57cec5SDimitry Andric 
2942*0b57cec5SDimitry Andric   AllDefs = (ChangedNum == DefRegs.size());
2943*0b57cec5SDimitry Andric   return ChangedNum > 0;
2944*0b57cec5SDimitry Andric }
2945*0b57cec5SDimitry Andric 
2946*0b57cec5SDimitry Andric bool HexagonConstEvaluator::rewriteHexConstUses(MachineInstr &MI,
2947*0b57cec5SDimitry Andric       const CellMap &Inputs) {
2948*0b57cec5SDimitry Andric   bool Changed = false;
2949*0b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
2950*0b57cec5SDimitry Andric   MachineBasicBlock &B = *MI.getParent();
2951*0b57cec5SDimitry Andric   const DebugLoc &DL = MI.getDebugLoc();
2952*0b57cec5SDimitry Andric   MachineBasicBlock::iterator At = MI.getIterator();
2953*0b57cec5SDimitry Andric   MachineInstr *NewMI = nullptr;
2954*0b57cec5SDimitry Andric 
2955*0b57cec5SDimitry Andric   switch (Opc) {
2956*0b57cec5SDimitry Andric     case Hexagon::M2_maci:
2957*0b57cec5SDimitry Andric     // Convert DefR += mpyi(R2, R3)
2958*0b57cec5SDimitry Andric     //   to   DefR += mpyi(R, #imm),
2959*0b57cec5SDimitry Andric     //   or   DefR -= mpyi(R, #imm).
2960*0b57cec5SDimitry Andric     {
2961*0b57cec5SDimitry Andric       RegisterSubReg DefR(MI.getOperand(0));
2962*0b57cec5SDimitry Andric       assert(!DefR.SubReg);
2963*0b57cec5SDimitry Andric       RegisterSubReg R2(MI.getOperand(2));
2964*0b57cec5SDimitry Andric       RegisterSubReg R3(MI.getOperand(3));
2965*0b57cec5SDimitry Andric       assert(Inputs.has(R2.Reg) && Inputs.has(R3.Reg));
2966*0b57cec5SDimitry Andric       LatticeCell LS2, LS3;
2967*0b57cec5SDimitry Andric       // It is enough to get one of the input cells, since we will only try
2968*0b57cec5SDimitry Andric       // to replace one argument---whichever happens to be a single constant.
2969*0b57cec5SDimitry Andric       bool HasC2 = getCell(R2, Inputs, LS2), HasC3 = getCell(R3, Inputs, LS3);
2970*0b57cec5SDimitry Andric       if (!HasC2 && !HasC3)
2971*0b57cec5SDimitry Andric         return false;
2972*0b57cec5SDimitry Andric       bool Zero = ((HasC2 && (LS2.properties() & ConstantProperties::Zero)) ||
2973*0b57cec5SDimitry Andric                    (HasC3 && (LS3.properties() & ConstantProperties::Zero)));
2974*0b57cec5SDimitry Andric       // If one of the operands is zero, eliminate the multiplication.
2975*0b57cec5SDimitry Andric       if (Zero) {
2976*0b57cec5SDimitry Andric         // DefR == R1 (tied operands).
2977*0b57cec5SDimitry Andric         MachineOperand &Acc = MI.getOperand(1);
2978*0b57cec5SDimitry Andric         RegisterSubReg R1(Acc);
2979*0b57cec5SDimitry Andric         unsigned NewR = R1.Reg;
2980*0b57cec5SDimitry Andric         if (R1.SubReg) {
2981*0b57cec5SDimitry Andric           // Generate COPY. FIXME: Replace with the register:subregister.
2982*0b57cec5SDimitry Andric           const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg);
2983*0b57cec5SDimitry Andric           NewR = MRI->createVirtualRegister(RC);
2984*0b57cec5SDimitry Andric           NewMI = BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR)
2985*0b57cec5SDimitry Andric                     .addReg(R1.Reg, getRegState(Acc), R1.SubReg);
2986*0b57cec5SDimitry Andric         }
2987*0b57cec5SDimitry Andric         replaceAllRegUsesWith(DefR.Reg, NewR);
2988*0b57cec5SDimitry Andric         MRI->clearKillFlags(NewR);
2989*0b57cec5SDimitry Andric         Changed = true;
2990*0b57cec5SDimitry Andric         break;
2991*0b57cec5SDimitry Andric       }
2992*0b57cec5SDimitry Andric 
2993*0b57cec5SDimitry Andric       bool Swap = false;
2994*0b57cec5SDimitry Andric       if (!LS3.isSingle()) {
2995*0b57cec5SDimitry Andric         if (!LS2.isSingle())
2996*0b57cec5SDimitry Andric           return false;
2997*0b57cec5SDimitry Andric         Swap = true;
2998*0b57cec5SDimitry Andric       }
2999*0b57cec5SDimitry Andric       const LatticeCell &LI = Swap ? LS2 : LS3;
3000*0b57cec5SDimitry Andric       const MachineOperand &OpR2 = Swap ? MI.getOperand(3)
3001*0b57cec5SDimitry Andric                                         : MI.getOperand(2);
3002*0b57cec5SDimitry Andric       // LI is single here.
3003*0b57cec5SDimitry Andric       APInt A;
3004*0b57cec5SDimitry Andric       if (!constToInt(LI.Value, A) || !A.isSignedIntN(8))
3005*0b57cec5SDimitry Andric         return false;
3006*0b57cec5SDimitry Andric       int64_t V = A.getSExtValue();
3007*0b57cec5SDimitry Andric       const MCInstrDesc &D = (V >= 0) ? HII.get(Hexagon::M2_macsip)
3008*0b57cec5SDimitry Andric                                       : HII.get(Hexagon::M2_macsin);
3009*0b57cec5SDimitry Andric       if (V < 0)
3010*0b57cec5SDimitry Andric         V = -V;
3011*0b57cec5SDimitry Andric       const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg);
3012*0b57cec5SDimitry Andric       unsigned NewR = MRI->createVirtualRegister(RC);
3013*0b57cec5SDimitry Andric       const MachineOperand &Src1 = MI.getOperand(1);
3014*0b57cec5SDimitry Andric       NewMI = BuildMI(B, At, DL, D, NewR)
3015*0b57cec5SDimitry Andric                 .addReg(Src1.getReg(), getRegState(Src1), Src1.getSubReg())
3016*0b57cec5SDimitry Andric                 .addReg(OpR2.getReg(), getRegState(OpR2), OpR2.getSubReg())
3017*0b57cec5SDimitry Andric                 .addImm(V);
3018*0b57cec5SDimitry Andric       replaceAllRegUsesWith(DefR.Reg, NewR);
3019*0b57cec5SDimitry Andric       Changed = true;
3020*0b57cec5SDimitry Andric       break;
3021*0b57cec5SDimitry Andric     }
3022*0b57cec5SDimitry Andric 
3023*0b57cec5SDimitry Andric     case Hexagon::A2_and:
3024*0b57cec5SDimitry Andric     {
3025*0b57cec5SDimitry Andric       RegisterSubReg R1(MI.getOperand(1));
3026*0b57cec5SDimitry Andric       RegisterSubReg R2(MI.getOperand(2));
3027*0b57cec5SDimitry Andric       assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
3028*0b57cec5SDimitry Andric       LatticeCell LS1, LS2;
3029*0b57cec5SDimitry Andric       unsigned CopyOf = 0;
3030*0b57cec5SDimitry Andric       // Check if any of the operands is -1 (i.e. all bits set).
3031*0b57cec5SDimitry Andric       if (getCell(R1, Inputs, LS1) && LS1.isSingle()) {
3032*0b57cec5SDimitry Andric         APInt M1;
3033*0b57cec5SDimitry Andric         if (constToInt(LS1.Value, M1) && !~M1)
3034*0b57cec5SDimitry Andric           CopyOf = 2;
3035*0b57cec5SDimitry Andric       }
3036*0b57cec5SDimitry Andric       else if (getCell(R2, Inputs, LS2) && LS2.isSingle()) {
3037*0b57cec5SDimitry Andric         APInt M1;
3038*0b57cec5SDimitry Andric         if (constToInt(LS2.Value, M1) && !~M1)
3039*0b57cec5SDimitry Andric           CopyOf = 1;
3040*0b57cec5SDimitry Andric       }
3041*0b57cec5SDimitry Andric       if (!CopyOf)
3042*0b57cec5SDimitry Andric         return false;
3043*0b57cec5SDimitry Andric       MachineOperand &SO = MI.getOperand(CopyOf);
3044*0b57cec5SDimitry Andric       RegisterSubReg SR(SO);
3045*0b57cec5SDimitry Andric       RegisterSubReg DefR(MI.getOperand(0));
3046*0b57cec5SDimitry Andric       unsigned NewR = SR.Reg;
3047*0b57cec5SDimitry Andric       if (SR.SubReg) {
3048*0b57cec5SDimitry Andric         const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg);
3049*0b57cec5SDimitry Andric         NewR = MRI->createVirtualRegister(RC);
3050*0b57cec5SDimitry Andric         NewMI = BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR)
3051*0b57cec5SDimitry Andric                   .addReg(SR.Reg, getRegState(SO), SR.SubReg);
3052*0b57cec5SDimitry Andric       }
3053*0b57cec5SDimitry Andric       replaceAllRegUsesWith(DefR.Reg, NewR);
3054*0b57cec5SDimitry Andric       MRI->clearKillFlags(NewR);
3055*0b57cec5SDimitry Andric       Changed = true;
3056*0b57cec5SDimitry Andric     }
3057*0b57cec5SDimitry Andric     break;
3058*0b57cec5SDimitry Andric 
3059*0b57cec5SDimitry Andric     case Hexagon::A2_or:
3060*0b57cec5SDimitry Andric     {
3061*0b57cec5SDimitry Andric       RegisterSubReg R1(MI.getOperand(1));
3062*0b57cec5SDimitry Andric       RegisterSubReg R2(MI.getOperand(2));
3063*0b57cec5SDimitry Andric       assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
3064*0b57cec5SDimitry Andric       LatticeCell LS1, LS2;
3065*0b57cec5SDimitry Andric       unsigned CopyOf = 0;
3066*0b57cec5SDimitry Andric 
3067*0b57cec5SDimitry Andric       using P = ConstantProperties;
3068*0b57cec5SDimitry Andric 
3069*0b57cec5SDimitry Andric       if (getCell(R1, Inputs, LS1) && (LS1.properties() & P::Zero))
3070*0b57cec5SDimitry Andric         CopyOf = 2;
3071*0b57cec5SDimitry Andric       else if (getCell(R2, Inputs, LS2) && (LS2.properties() & P::Zero))
3072*0b57cec5SDimitry Andric         CopyOf = 1;
3073*0b57cec5SDimitry Andric       if (!CopyOf)
3074*0b57cec5SDimitry Andric         return false;
3075*0b57cec5SDimitry Andric       MachineOperand &SO = MI.getOperand(CopyOf);
3076*0b57cec5SDimitry Andric       RegisterSubReg SR(SO);
3077*0b57cec5SDimitry Andric       RegisterSubReg DefR(MI.getOperand(0));
3078*0b57cec5SDimitry Andric       unsigned NewR = SR.Reg;
3079*0b57cec5SDimitry Andric       if (SR.SubReg) {
3080*0b57cec5SDimitry Andric         const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg);
3081*0b57cec5SDimitry Andric         NewR = MRI->createVirtualRegister(RC);
3082*0b57cec5SDimitry Andric         NewMI = BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR)
3083*0b57cec5SDimitry Andric                   .addReg(SR.Reg, getRegState(SO), SR.SubReg);
3084*0b57cec5SDimitry Andric       }
3085*0b57cec5SDimitry Andric       replaceAllRegUsesWith(DefR.Reg, NewR);
3086*0b57cec5SDimitry Andric       MRI->clearKillFlags(NewR);
3087*0b57cec5SDimitry Andric       Changed = true;
3088*0b57cec5SDimitry Andric     }
3089*0b57cec5SDimitry Andric     break;
3090*0b57cec5SDimitry Andric   }
3091*0b57cec5SDimitry Andric 
3092*0b57cec5SDimitry Andric   if (NewMI) {
3093*0b57cec5SDimitry Andric     // clear all the kill flags of this new instruction.
3094*0b57cec5SDimitry Andric     for (MachineOperand &MO : NewMI->operands())
3095*0b57cec5SDimitry Andric       if (MO.isReg() && MO.isUse())
3096*0b57cec5SDimitry Andric         MO.setIsKill(false);
3097*0b57cec5SDimitry Andric   }
3098*0b57cec5SDimitry Andric 
3099*0b57cec5SDimitry Andric   LLVM_DEBUG({
3100*0b57cec5SDimitry Andric     if (NewMI) {
3101*0b57cec5SDimitry Andric       dbgs() << "Rewrite: for " << MI;
3102*0b57cec5SDimitry Andric       if (NewMI != &MI)
3103*0b57cec5SDimitry Andric         dbgs() << "  created " << *NewMI;
3104*0b57cec5SDimitry Andric       else
3105*0b57cec5SDimitry Andric         dbgs() << "  modified the instruction itself and created:" << *NewMI;
3106*0b57cec5SDimitry Andric     }
3107*0b57cec5SDimitry Andric   });
3108*0b57cec5SDimitry Andric 
3109*0b57cec5SDimitry Andric   return Changed;
3110*0b57cec5SDimitry Andric }
3111*0b57cec5SDimitry Andric 
3112*0b57cec5SDimitry Andric void HexagonConstEvaluator::replaceAllRegUsesWith(unsigned FromReg,
3113*0b57cec5SDimitry Andric       unsigned ToReg) {
3114*0b57cec5SDimitry Andric   assert(TargetRegisterInfo::isVirtualRegister(FromReg));
3115*0b57cec5SDimitry Andric   assert(TargetRegisterInfo::isVirtualRegister(ToReg));
3116*0b57cec5SDimitry Andric   for (auto I = MRI->use_begin(FromReg), E = MRI->use_end(); I != E;) {
3117*0b57cec5SDimitry Andric     MachineOperand &O = *I;
3118*0b57cec5SDimitry Andric     ++I;
3119*0b57cec5SDimitry Andric     O.setReg(ToReg);
3120*0b57cec5SDimitry Andric   }
3121*0b57cec5SDimitry Andric }
3122*0b57cec5SDimitry Andric 
3123*0b57cec5SDimitry Andric bool HexagonConstEvaluator::rewriteHexBranch(MachineInstr &BrI,
3124*0b57cec5SDimitry Andric       const CellMap &Inputs) {
3125*0b57cec5SDimitry Andric   MachineBasicBlock &B = *BrI.getParent();
3126*0b57cec5SDimitry Andric   unsigned NumOp = BrI.getNumOperands();
3127*0b57cec5SDimitry Andric   if (!NumOp)
3128*0b57cec5SDimitry Andric     return false;
3129*0b57cec5SDimitry Andric 
3130*0b57cec5SDimitry Andric   bool FallsThru;
3131*0b57cec5SDimitry Andric   SetVector<const MachineBasicBlock*> Targets;
3132*0b57cec5SDimitry Andric   bool Eval = evaluate(BrI, Inputs, Targets, FallsThru);
3133*0b57cec5SDimitry Andric   unsigned NumTargets = Targets.size();
3134*0b57cec5SDimitry Andric   if (!Eval || NumTargets > 1 || (NumTargets == 1 && FallsThru))
3135*0b57cec5SDimitry Andric     return false;
3136*0b57cec5SDimitry Andric   if (BrI.getOpcode() == Hexagon::J2_jump)
3137*0b57cec5SDimitry Andric     return false;
3138*0b57cec5SDimitry Andric 
3139*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Rewrite(" << printMBBReference(B) << "):" << BrI);
3140*0b57cec5SDimitry Andric   bool Rewritten = false;
3141*0b57cec5SDimitry Andric   if (NumTargets > 0) {
3142*0b57cec5SDimitry Andric     assert(!FallsThru && "This should have been checked before");
3143*0b57cec5SDimitry Andric     // MIB.addMBB needs non-const pointer.
3144*0b57cec5SDimitry Andric     MachineBasicBlock *TargetB = const_cast<MachineBasicBlock*>(Targets[0]);
3145*0b57cec5SDimitry Andric     bool Moot = B.isLayoutSuccessor(TargetB);
3146*0b57cec5SDimitry Andric     if (!Moot) {
3147*0b57cec5SDimitry Andric       // If we build a branch here, we must make sure that it won't be
3148*0b57cec5SDimitry Andric       // erased as "non-executable". We can't mark any new instructions
3149*0b57cec5SDimitry Andric       // as executable here, so we need to overwrite the BrI, which we
3150*0b57cec5SDimitry Andric       // know is executable.
3151*0b57cec5SDimitry Andric       const MCInstrDesc &JD = HII.get(Hexagon::J2_jump);
3152*0b57cec5SDimitry Andric       auto NI = BuildMI(B, BrI.getIterator(), BrI.getDebugLoc(), JD)
3153*0b57cec5SDimitry Andric                   .addMBB(TargetB);
3154*0b57cec5SDimitry Andric       BrI.setDesc(JD);
3155*0b57cec5SDimitry Andric       while (BrI.getNumOperands() > 0)
3156*0b57cec5SDimitry Andric         BrI.RemoveOperand(0);
3157*0b57cec5SDimitry Andric       // This ensures that all implicit operands (e.g. implicit-def %r31, etc)
3158*0b57cec5SDimitry Andric       // are present in the rewritten branch.
3159*0b57cec5SDimitry Andric       for (auto &Op : NI->operands())
3160*0b57cec5SDimitry Andric         BrI.addOperand(Op);
3161*0b57cec5SDimitry Andric       NI->eraseFromParent();
3162*0b57cec5SDimitry Andric       Rewritten = true;
3163*0b57cec5SDimitry Andric     }
3164*0b57cec5SDimitry Andric   }
3165*0b57cec5SDimitry Andric 
3166*0b57cec5SDimitry Andric   // Do not erase instructions. A newly created instruction could get
3167*0b57cec5SDimitry Andric   // the same address as an instruction marked as executable during the
3168*0b57cec5SDimitry Andric   // propagation.
3169*0b57cec5SDimitry Andric   if (!Rewritten)
3170*0b57cec5SDimitry Andric     replaceWithNop(BrI);
3171*0b57cec5SDimitry Andric   return true;
3172*0b57cec5SDimitry Andric }
3173*0b57cec5SDimitry Andric 
3174*0b57cec5SDimitry Andric FunctionPass *llvm::createHexagonConstPropagationPass() {
3175*0b57cec5SDimitry Andric   return new HexagonConstPropagation();
3176*0b57cec5SDimitry Andric }
3177