xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonConstPropagation.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
10b57cec5SDimitry Andric //===- HexagonConstPropagation.cpp ----------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #define DEBUG_TYPE "hcp"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "HexagonInstrInfo.h"
120b57cec5SDimitry Andric #include "HexagonRegisterInfo.h"
130b57cec5SDimitry Andric #include "HexagonSubtarget.h"
140b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h"
150b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
160b57cec5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
170b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h"
180b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
190b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
290b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
300b57cec5SDimitry Andric #include "llvm/IR/Type.h"
310b57cec5SDimitry Andric #include "llvm/Pass.h"
320b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
330b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
340b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
350b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
360b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
370b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
380b57cec5SDimitry Andric #include <cassert>
390b57cec5SDimitry Andric #include <cstdint>
400b57cec5SDimitry Andric #include <cstring>
410b57cec5SDimitry Andric #include <iterator>
420b57cec5SDimitry Andric #include <map>
430b57cec5SDimitry Andric #include <queue>
440b57cec5SDimitry Andric #include <set>
450b57cec5SDimitry Andric #include <utility>
460b57cec5SDimitry Andric #include <vector>
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric using namespace llvm;
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric namespace {
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   // Properties of a value that are tracked by the propagation.
530b57cec5SDimitry Andric   // A property that is marked as present (i.e. bit is set) dentes that the
540b57cec5SDimitry Andric   // value is known (proven) to have this property. Not all combinations
550b57cec5SDimitry Andric   // of bits make sense, for example Zero and NonZero are mutually exclusive,
560b57cec5SDimitry Andric   // but on the other hand, Zero implies Finite. In this case, whenever
570b57cec5SDimitry Andric   // the Zero property is present, Finite should also be present.
580b57cec5SDimitry Andric   class ConstantProperties {
590b57cec5SDimitry Andric   public:
600b57cec5SDimitry Andric     enum {
610b57cec5SDimitry Andric       Unknown   = 0x0000,
620b57cec5SDimitry Andric       Zero      = 0x0001,
630b57cec5SDimitry Andric       NonZero   = 0x0002,
640b57cec5SDimitry Andric       Finite    = 0x0004,
650b57cec5SDimitry Andric       Infinity  = 0x0008,
660b57cec5SDimitry Andric       NaN       = 0x0010,
670b57cec5SDimitry Andric       SignedZero = 0x0020,
680b57cec5SDimitry Andric       NumericProperties = (Zero|NonZero|Finite|Infinity|NaN|SignedZero),
690b57cec5SDimitry Andric       PosOrZero       = 0x0100,
700b57cec5SDimitry Andric       NegOrZero       = 0x0200,
710b57cec5SDimitry Andric       SignProperties  = (PosOrZero|NegOrZero),
720b57cec5SDimitry Andric       Everything      = (NumericProperties|SignProperties)
730b57cec5SDimitry Andric     };
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric     // For a given constant, deduce the set of trackable properties that this
760b57cec5SDimitry Andric     // constant has.
770b57cec5SDimitry Andric     static uint32_t deduce(const Constant *C);
780b57cec5SDimitry Andric   };
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   // A representation of a register as it can appear in a MachineOperand,
810b57cec5SDimitry Andric   // i.e. a pair register:subregister.
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   // FIXME: Use TargetInstrInfo::RegSubRegPair. Also duplicated in
840b57cec5SDimitry Andric   // HexagonGenPredicate
850b57cec5SDimitry Andric   struct RegisterSubReg {
860b57cec5SDimitry Andric     unsigned Reg, SubReg;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric     explicit RegisterSubReg(unsigned R, unsigned SR = 0) : Reg(R), SubReg(SR) {}
890b57cec5SDimitry Andric     explicit RegisterSubReg(const MachineOperand &MO)
900b57cec5SDimitry Andric       : Reg(MO.getReg()), SubReg(MO.getSubReg()) {}
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric     void print(const TargetRegisterInfo *TRI = nullptr) const {
930b57cec5SDimitry Andric       dbgs() << printReg(Reg, TRI, SubReg);
940b57cec5SDimitry Andric     }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric     bool operator== (const RegisterSubReg &R) const {
970b57cec5SDimitry Andric       return (Reg == R.Reg) && (SubReg == R.SubReg);
980b57cec5SDimitry Andric     }
990b57cec5SDimitry Andric   };
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   // Lattice cell, based on that was described in the W-Z paper on constant
1020b57cec5SDimitry Andric   // propagation.
1030b57cec5SDimitry Andric   // Latice cell will be allowed to hold multiple constant values. While
1040b57cec5SDimitry Andric   // multiple values would normally indicate "bottom", we can still derive
1050b57cec5SDimitry Andric   // some useful information from them. For example, comparison X > 0
1060b57cec5SDimitry Andric   // could be folded if all the values in the cell associated with X are
1070b57cec5SDimitry Andric   // positive.
1080b57cec5SDimitry Andric   class LatticeCell {
1090b57cec5SDimitry Andric   private:
1100b57cec5SDimitry Andric     enum { Normal, Top, Bottom };
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric     static const unsigned MaxCellSize = 4;
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric     unsigned Kind:2;
1150b57cec5SDimitry Andric     unsigned Size:3;
1160b57cec5SDimitry Andric     unsigned IsSpecial:1;
1170b57cec5SDimitry Andric     unsigned :0;
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   public:
1200b57cec5SDimitry Andric     union {
1210b57cec5SDimitry Andric       uint32_t Properties;
1220b57cec5SDimitry Andric       const Constant *Value;
1230b57cec5SDimitry Andric       const Constant *Values[MaxCellSize];
1240b57cec5SDimitry Andric     };
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric     LatticeCell() : Kind(Top), Size(0), IsSpecial(false) {
1270b57cec5SDimitry Andric       for (unsigned i = 0; i < MaxCellSize; ++i)
1280b57cec5SDimitry Andric         Values[i] = nullptr;
1290b57cec5SDimitry Andric     }
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric     bool meet(const LatticeCell &L);
1320b57cec5SDimitry Andric     bool add(const Constant *C);
1330b57cec5SDimitry Andric     bool add(uint32_t Property);
1340b57cec5SDimitry Andric     uint32_t properties() const;
1350b57cec5SDimitry Andric     unsigned size() const { return Size; }
1360b57cec5SDimitry Andric 
137480093f4SDimitry Andric     LatticeCell(const LatticeCell &L) {
138480093f4SDimitry Andric       // This memcpy also copies Properties (when L.Size == 0).
139480093f4SDimitry Andric       uint32_t N =
140480093f4SDimitry Andric           L.IsSpecial ? sizeof L.Properties : L.Size * sizeof(const Constant *);
141480093f4SDimitry Andric       memcpy(Values, L.Values, N);
142480093f4SDimitry Andric       Kind = L.Kind;
143480093f4SDimitry Andric       Size = L.Size;
144480093f4SDimitry Andric       IsSpecial = L.IsSpecial;
145480093f4SDimitry Andric     }
146480093f4SDimitry Andric 
1470b57cec5SDimitry Andric     LatticeCell &operator=(const LatticeCell &L) {
1480b57cec5SDimitry Andric       if (this != &L) {
1490b57cec5SDimitry Andric         // This memcpy also copies Properties (when L.Size == 0).
1500b57cec5SDimitry Andric         uint32_t N = L.IsSpecial ? sizeof L.Properties
1510b57cec5SDimitry Andric                                  : L.Size * sizeof(const Constant *);
1520b57cec5SDimitry Andric         memcpy(Values, L.Values, N);
1530b57cec5SDimitry Andric         Kind = L.Kind;
1540b57cec5SDimitry Andric         Size = L.Size;
1550b57cec5SDimitry Andric         IsSpecial = L.IsSpecial;
1560b57cec5SDimitry Andric       }
1570b57cec5SDimitry Andric       return *this;
1580b57cec5SDimitry Andric     }
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric     bool isSingle() const { return size() == 1; }
1610b57cec5SDimitry Andric     bool isProperty() const { return IsSpecial; }
1620b57cec5SDimitry Andric     bool isTop() const { return Kind == Top; }
1630b57cec5SDimitry Andric     bool isBottom() const { return Kind == Bottom; }
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric     bool setBottom() {
1660b57cec5SDimitry Andric       bool Changed = (Kind != Bottom);
1670b57cec5SDimitry Andric       Kind = Bottom;
1680b57cec5SDimitry Andric       Size = 0;
1690b57cec5SDimitry Andric       IsSpecial = false;
1700b57cec5SDimitry Andric       return Changed;
1710b57cec5SDimitry Andric     }
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric     void print(raw_ostream &os) const;
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   private:
1760b57cec5SDimitry Andric     void setProperty() {
1770b57cec5SDimitry Andric       IsSpecial = true;
1780b57cec5SDimitry Andric       Size = 0;
1790b57cec5SDimitry Andric       Kind = Normal;
1800b57cec5SDimitry Andric     }
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric     bool convertToProperty();
1830b57cec5SDimitry Andric   };
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric #ifndef NDEBUG
1860b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &os, const LatticeCell &L) {
1870b57cec5SDimitry Andric     L.print(os);
1880b57cec5SDimitry Andric     return os;
1890b57cec5SDimitry Andric   }
1900b57cec5SDimitry Andric #endif
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric   class MachineConstEvaluator;
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   class MachineConstPropagator {
1950b57cec5SDimitry Andric   public:
1960b57cec5SDimitry Andric     MachineConstPropagator(MachineConstEvaluator &E) : MCE(E) {
1970b57cec5SDimitry Andric       Bottom.setBottom();
1980b57cec5SDimitry Andric     }
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric     // Mapping: vreg -> cell
2010b57cec5SDimitry Andric     // The keys are registers _without_ subregisters. This won't allow
2020b57cec5SDimitry Andric     // definitions in the form of "vreg:subreg = ...". Such definitions
2030b57cec5SDimitry Andric     // would be questionable from the point of view of SSA, since the "vreg"
2040b57cec5SDimitry Andric     // could not be initialized in its entirety (specifically, an instruction
2050b57cec5SDimitry Andric     // defining the "other part" of "vreg" would also count as a definition
2060b57cec5SDimitry Andric     // of "vreg", which would violate the SSA).
2070b57cec5SDimitry Andric     // If a value of a pair vreg:subreg needs to be obtained, the cell for
2080b57cec5SDimitry Andric     // "vreg" needs to be looked up, and then the value of subregister "subreg"
2090b57cec5SDimitry Andric     // needs to be evaluated.
2100b57cec5SDimitry Andric     class CellMap {
2110b57cec5SDimitry Andric     public:
2120b57cec5SDimitry Andric       CellMap() {
2130b57cec5SDimitry Andric         assert(Top.isTop());
2140b57cec5SDimitry Andric         Bottom.setBottom();
2150b57cec5SDimitry Andric       }
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric       void clear() { Map.clear(); }
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric       bool has(unsigned R) const {
2200b57cec5SDimitry Andric         // All non-virtual registers are considered "bottom".
2218bcb0991SDimitry Andric         if (!Register::isVirtualRegister(R))
2220b57cec5SDimitry Andric           return true;
2230b57cec5SDimitry Andric         MapType::const_iterator F = Map.find(R);
2240b57cec5SDimitry Andric         return F != Map.end();
2250b57cec5SDimitry Andric       }
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric       const LatticeCell &get(unsigned R) const {
2288bcb0991SDimitry Andric         if (!Register::isVirtualRegister(R))
2290b57cec5SDimitry Andric           return Bottom;
2300b57cec5SDimitry Andric         MapType::const_iterator F = Map.find(R);
2310b57cec5SDimitry Andric         if (F != Map.end())
2320b57cec5SDimitry Andric           return F->second;
2330b57cec5SDimitry Andric         return Top;
2340b57cec5SDimitry Andric       }
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric       // Invalidates any const references.
2370b57cec5SDimitry Andric       void update(unsigned R, const LatticeCell &L) {
2380b57cec5SDimitry Andric         Map[R] = L;
2390b57cec5SDimitry Andric       }
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric       void print(raw_ostream &os, const TargetRegisterInfo &TRI) const;
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric     private:
2440b57cec5SDimitry Andric       using MapType = std::map<unsigned, LatticeCell>;
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric       MapType Map;
2470b57cec5SDimitry Andric       // To avoid creating "top" entries, return a const reference to
2480b57cec5SDimitry Andric       // this cell in "get". Also, have a "Bottom" cell to return from
2490b57cec5SDimitry Andric       // get when a value of a physical register is requested.
2500b57cec5SDimitry Andric       LatticeCell Top, Bottom;
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric     public:
2530b57cec5SDimitry Andric       using const_iterator = MapType::const_iterator;
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric       const_iterator begin() const { return Map.begin(); }
2560b57cec5SDimitry Andric       const_iterator end() const { return Map.end(); }
2570b57cec5SDimitry Andric     };
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric     bool run(MachineFunction &MF);
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   private:
2620b57cec5SDimitry Andric     void visitPHI(const MachineInstr &PN);
2630b57cec5SDimitry Andric     void visitNonBranch(const MachineInstr &MI);
2640b57cec5SDimitry Andric     void visitBranchesFrom(const MachineInstr &BrI);
2650b57cec5SDimitry Andric     void visitUsesOf(unsigned R);
2660b57cec5SDimitry Andric     bool computeBlockSuccessors(const MachineBasicBlock *MB,
2670b57cec5SDimitry Andric           SetVector<const MachineBasicBlock*> &Targets);
2680b57cec5SDimitry Andric     void removeCFGEdge(MachineBasicBlock *From, MachineBasicBlock *To);
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric     void propagate(MachineFunction &MF);
2710b57cec5SDimitry Andric     bool rewrite(MachineFunction &MF);
2720b57cec5SDimitry Andric 
273480093f4SDimitry Andric     MachineRegisterInfo      *MRI = nullptr;
2740b57cec5SDimitry Andric     MachineConstEvaluator    &MCE;
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric     using CFGEdge = std::pair<unsigned, unsigned>;
2770b57cec5SDimitry Andric     using SetOfCFGEdge = std::set<CFGEdge>;
2780b57cec5SDimitry Andric     using SetOfInstr = std::set<const MachineInstr *>;
2790b57cec5SDimitry Andric     using QueueOfCFGEdge = std::queue<CFGEdge>;
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric     LatticeCell     Bottom;
2820b57cec5SDimitry Andric     CellMap         Cells;
2830b57cec5SDimitry Andric     SetOfCFGEdge    EdgeExec;
2840b57cec5SDimitry Andric     SetOfInstr      InstrExec;
2850b57cec5SDimitry Andric     QueueOfCFGEdge  FlowQ;
2860b57cec5SDimitry Andric   };
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   // The "evaluator/rewriter" of machine instructions. This is an abstract
2890b57cec5SDimitry Andric   // base class that provides the interface that the propagator will use,
2900b57cec5SDimitry Andric   // as well as some helper functions that are target-independent.
2910b57cec5SDimitry Andric   class MachineConstEvaluator {
2920b57cec5SDimitry Andric   public:
2930b57cec5SDimitry Andric     MachineConstEvaluator(MachineFunction &Fn)
2940b57cec5SDimitry Andric       : TRI(*Fn.getSubtarget().getRegisterInfo()),
2950b57cec5SDimitry Andric         MF(Fn), CX(Fn.getFunction().getContext()) {}
2960b57cec5SDimitry Andric     virtual ~MachineConstEvaluator() = default;
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric     // The required interface:
2990b57cec5SDimitry Andric     // - A set of three "evaluate" functions. Each returns "true" if the
3000b57cec5SDimitry Andric     //       computation succeeded, "false" otherwise.
3010b57cec5SDimitry Andric     //   (1) Given an instruction MI, and the map with input values "Inputs",
3020b57cec5SDimitry Andric     //       compute the set of output values "Outputs". An example of when
3030b57cec5SDimitry Andric     //       the computation can "fail" is if MI is not an instruction that
3040b57cec5SDimitry Andric     //       is recognized by the evaluator.
3050b57cec5SDimitry Andric     //   (2) Given a register R (as reg:subreg), compute the cell that
3060b57cec5SDimitry Andric     //       corresponds to the "subreg" part of the given register.
3070b57cec5SDimitry Andric     //   (3) Given a branch instruction BrI, compute the set of target blocks.
3080b57cec5SDimitry Andric     //       If the branch can fall-through, add null (0) to the list of
3090b57cec5SDimitry Andric     //       possible targets.
3100b57cec5SDimitry Andric     // - A function "rewrite", that given the cell map after propagation,
3110b57cec5SDimitry Andric     //   could rewrite instruction MI in a more beneficial form. Return
3120b57cec5SDimitry Andric     //   "true" if a change has been made, "false" otherwise.
3130b57cec5SDimitry Andric     using CellMap = MachineConstPropagator::CellMap;
3140b57cec5SDimitry Andric     virtual bool evaluate(const MachineInstr &MI, const CellMap &Inputs,
3150b57cec5SDimitry Andric                           CellMap &Outputs) = 0;
3160b57cec5SDimitry Andric     virtual bool evaluate(const RegisterSubReg &R, const LatticeCell &SrcC,
3170b57cec5SDimitry Andric                           LatticeCell &Result) = 0;
3180b57cec5SDimitry Andric     virtual bool evaluate(const MachineInstr &BrI, const CellMap &Inputs,
3190b57cec5SDimitry Andric                           SetVector<const MachineBasicBlock*> &Targets,
3200b57cec5SDimitry Andric                           bool &CanFallThru) = 0;
3210b57cec5SDimitry Andric     virtual bool rewrite(MachineInstr &MI, const CellMap &Inputs) = 0;
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric     const TargetRegisterInfo &TRI;
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric   protected:
3260b57cec5SDimitry Andric     MachineFunction &MF;
3270b57cec5SDimitry Andric     LLVMContext     &CX;
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric     struct Comparison {
3300b57cec5SDimitry Andric       enum {
3310b57cec5SDimitry Andric         Unk = 0x00,
3320b57cec5SDimitry Andric         EQ  = 0x01,
3330b57cec5SDimitry Andric         NE  = 0x02,
3340b57cec5SDimitry Andric         L   = 0x04, // Less-than property.
3350b57cec5SDimitry Andric         G   = 0x08, // Greater-than property.
3360b57cec5SDimitry Andric         U   = 0x40, // Unsigned property.
3370b57cec5SDimitry Andric         LTs = L,
3380b57cec5SDimitry Andric         LEs = L | EQ,
3390b57cec5SDimitry Andric         GTs = G,
3400b57cec5SDimitry Andric         GEs = G | EQ,
3410b57cec5SDimitry Andric         LTu = L      | U,
3420b57cec5SDimitry Andric         LEu = L | EQ | U,
3430b57cec5SDimitry Andric         GTu = G      | U,
3440b57cec5SDimitry Andric         GEu = G | EQ | U
3450b57cec5SDimitry Andric       };
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric       static uint32_t negate(uint32_t Cmp) {
3480b57cec5SDimitry Andric         if (Cmp == EQ)
3490b57cec5SDimitry Andric           return NE;
3500b57cec5SDimitry Andric         if (Cmp == NE)
3510b57cec5SDimitry Andric           return EQ;
3520b57cec5SDimitry Andric         assert((Cmp & (L|G)) != (L|G));
3530b57cec5SDimitry Andric         return Cmp ^ (L|G);
3540b57cec5SDimitry Andric       }
3550b57cec5SDimitry Andric     };
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric     // Helper functions.
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric     bool getCell(const RegisterSubReg &R, const CellMap &Inputs, LatticeCell &RC);
3600b57cec5SDimitry Andric     bool constToInt(const Constant *C, APInt &Val) const;
3610b57cec5SDimitry Andric     bool constToFloat(const Constant *C, APFloat &Val) const;
3620b57cec5SDimitry Andric     const ConstantInt *intToConst(const APInt &Val) const;
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric     // Compares.
3650b57cec5SDimitry Andric     bool evaluateCMPrr(uint32_t Cmp, const RegisterSubReg &R1, const RegisterSubReg &R2,
3660b57cec5SDimitry Andric           const CellMap &Inputs, bool &Result);
3670b57cec5SDimitry Andric     bool evaluateCMPri(uint32_t Cmp, const RegisterSubReg &R1, const APInt &A2,
3680b57cec5SDimitry Andric           const CellMap &Inputs, bool &Result);
3690b57cec5SDimitry Andric     bool evaluateCMPrp(uint32_t Cmp, const RegisterSubReg &R1, uint64_t Props2,
3700b57cec5SDimitry Andric           const CellMap &Inputs, bool &Result);
3710b57cec5SDimitry Andric     bool evaluateCMPii(uint32_t Cmp, const APInt &A1, const APInt &A2,
3720b57cec5SDimitry Andric           bool &Result);
3730b57cec5SDimitry Andric     bool evaluateCMPpi(uint32_t Cmp, uint32_t Props, const APInt &A2,
3740b57cec5SDimitry Andric           bool &Result);
3750b57cec5SDimitry Andric     bool evaluateCMPpp(uint32_t Cmp, uint32_t Props1, uint32_t Props2,
3760b57cec5SDimitry Andric           bool &Result);
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric     bool evaluateCOPY(const RegisterSubReg &R1, const CellMap &Inputs,
3790b57cec5SDimitry Andric           LatticeCell &Result);
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric     // Logical operations.
3820b57cec5SDimitry Andric     bool evaluateANDrr(const RegisterSubReg &R1, const RegisterSubReg &R2,
3830b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
3840b57cec5SDimitry Andric     bool evaluateANDri(const RegisterSubReg &R1, const APInt &A2,
3850b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
3860b57cec5SDimitry Andric     bool evaluateANDii(const APInt &A1, const APInt &A2, APInt &Result);
3870b57cec5SDimitry Andric     bool evaluateORrr(const RegisterSubReg &R1, const RegisterSubReg &R2,
3880b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
3890b57cec5SDimitry Andric     bool evaluateORri(const RegisterSubReg &R1, const APInt &A2,
3900b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
3910b57cec5SDimitry Andric     bool evaluateORii(const APInt &A1, const APInt &A2, APInt &Result);
3920b57cec5SDimitry Andric     bool evaluateXORrr(const RegisterSubReg &R1, const RegisterSubReg &R2,
3930b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
3940b57cec5SDimitry Andric     bool evaluateXORri(const RegisterSubReg &R1, const APInt &A2,
3950b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
3960b57cec5SDimitry Andric     bool evaluateXORii(const APInt &A1, const APInt &A2, APInt &Result);
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric     // Extensions.
3990b57cec5SDimitry Andric     bool evaluateZEXTr(const RegisterSubReg &R1, unsigned Width, unsigned Bits,
4000b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
4010b57cec5SDimitry Andric     bool evaluateZEXTi(const APInt &A1, unsigned Width, unsigned Bits,
4020b57cec5SDimitry Andric           APInt &Result);
4030b57cec5SDimitry Andric     bool evaluateSEXTr(const RegisterSubReg &R1, unsigned Width, unsigned Bits,
4040b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
4050b57cec5SDimitry Andric     bool evaluateSEXTi(const APInt &A1, unsigned Width, unsigned Bits,
4060b57cec5SDimitry Andric           APInt &Result);
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric     // Leading/trailing bits.
4090b57cec5SDimitry Andric     bool evaluateCLBr(const RegisterSubReg &R1, bool Zeros, bool Ones,
4100b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
4110b57cec5SDimitry Andric     bool evaluateCLBi(const APInt &A1, bool Zeros, bool Ones, APInt &Result);
4120b57cec5SDimitry Andric     bool evaluateCTBr(const RegisterSubReg &R1, bool Zeros, bool Ones,
4130b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
4140b57cec5SDimitry Andric     bool evaluateCTBi(const APInt &A1, bool Zeros, bool Ones, APInt &Result);
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric     // Bitfield extract.
4170b57cec5SDimitry Andric     bool evaluateEXTRACTr(const RegisterSubReg &R1, unsigned Width, unsigned Bits,
4180b57cec5SDimitry Andric           unsigned Offset, bool Signed, const CellMap &Inputs,
4190b57cec5SDimitry Andric           LatticeCell &Result);
4200b57cec5SDimitry Andric     bool evaluateEXTRACTi(const APInt &A1, unsigned Bits, unsigned Offset,
4210b57cec5SDimitry Andric           bool Signed, APInt &Result);
4220b57cec5SDimitry Andric     // Vector operations.
4230b57cec5SDimitry Andric     bool evaluateSplatr(const RegisterSubReg &R1, unsigned Bits, unsigned Count,
4240b57cec5SDimitry Andric           const CellMap &Inputs, LatticeCell &Result);
4250b57cec5SDimitry Andric     bool evaluateSplati(const APInt &A1, unsigned Bits, unsigned Count,
4260b57cec5SDimitry Andric           APInt &Result);
4270b57cec5SDimitry Andric   };
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric } // end anonymous namespace
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric uint32_t ConstantProperties::deduce(const Constant *C) {
4320b57cec5SDimitry Andric   if (isa<ConstantInt>(C)) {
4330b57cec5SDimitry Andric     const ConstantInt *CI = cast<ConstantInt>(C);
4340b57cec5SDimitry Andric     if (CI->isZero())
4350b57cec5SDimitry Andric       return Zero | PosOrZero | NegOrZero | Finite;
4360b57cec5SDimitry Andric     uint32_t Props = (NonZero | Finite);
4370b57cec5SDimitry Andric     if (CI->isNegative())
4380b57cec5SDimitry Andric       return Props | NegOrZero;
4390b57cec5SDimitry Andric     return Props | PosOrZero;
4400b57cec5SDimitry Andric   }
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric   if (isa<ConstantFP>(C)) {
4430b57cec5SDimitry Andric     const ConstantFP *CF = cast<ConstantFP>(C);
4440b57cec5SDimitry Andric     uint32_t Props = CF->isNegative() ? (NegOrZero|NonZero)
4450b57cec5SDimitry Andric                                       : PosOrZero;
4460b57cec5SDimitry Andric     if (CF->isZero())
4470b57cec5SDimitry Andric       return (Props & ~NumericProperties) | (Zero|Finite);
4480b57cec5SDimitry Andric     Props = (Props & ~NumericProperties) | NonZero;
4490b57cec5SDimitry Andric     if (CF->isNaN())
4500b57cec5SDimitry Andric       return (Props & ~NumericProperties) | NaN;
4510b57cec5SDimitry Andric     const APFloat &Val = CF->getValueAPF();
4520b57cec5SDimitry Andric     if (Val.isInfinity())
4530b57cec5SDimitry Andric       return (Props & ~NumericProperties) | Infinity;
4540b57cec5SDimitry Andric     Props |= Finite;
4550b57cec5SDimitry Andric     return Props;
4560b57cec5SDimitry Andric   }
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   return Unknown;
4590b57cec5SDimitry Andric }
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric // Convert a cell from a set of specific values to a cell that tracks
4620b57cec5SDimitry Andric // properties.
4630b57cec5SDimitry Andric bool LatticeCell::convertToProperty() {
4640b57cec5SDimitry Andric   if (isProperty())
4650b57cec5SDimitry Andric     return false;
4660b57cec5SDimitry Andric   // Corner case: converting a fresh (top) cell to "special".
4670b57cec5SDimitry Andric   // This can happen, when adding a property to a top cell.
4680b57cec5SDimitry Andric   uint32_t Everything = ConstantProperties::Everything;
4690b57cec5SDimitry Andric   uint32_t Ps = !isTop() ? properties()
4700b57cec5SDimitry Andric                          : Everything;
4710b57cec5SDimitry Andric   if (Ps != ConstantProperties::Unknown) {
4720b57cec5SDimitry Andric     Properties = Ps;
4730b57cec5SDimitry Andric     setProperty();
4740b57cec5SDimitry Andric   } else {
4750b57cec5SDimitry Andric     setBottom();
4760b57cec5SDimitry Andric   }
4770b57cec5SDimitry Andric   return true;
4780b57cec5SDimitry Andric }
4790b57cec5SDimitry Andric 
4800b57cec5SDimitry Andric #ifndef NDEBUG
4810b57cec5SDimitry Andric void LatticeCell::print(raw_ostream &os) const {
4820b57cec5SDimitry Andric   if (isProperty()) {
4830b57cec5SDimitry Andric     os << "{ ";
4840b57cec5SDimitry Andric     uint32_t Ps = properties();
4850b57cec5SDimitry Andric     if (Ps & ConstantProperties::Zero)
4860b57cec5SDimitry Andric       os << "zero ";
4870b57cec5SDimitry Andric     if (Ps & ConstantProperties::NonZero)
4880b57cec5SDimitry Andric       os << "nonzero ";
4890b57cec5SDimitry Andric     if (Ps & ConstantProperties::Finite)
4900b57cec5SDimitry Andric       os << "finite ";
4910b57cec5SDimitry Andric     if (Ps & ConstantProperties::Infinity)
4920b57cec5SDimitry Andric       os << "infinity ";
4930b57cec5SDimitry Andric     if (Ps & ConstantProperties::NaN)
4940b57cec5SDimitry Andric       os << "nan ";
4950b57cec5SDimitry Andric     if (Ps & ConstantProperties::PosOrZero)
4960b57cec5SDimitry Andric       os << "poz ";
4970b57cec5SDimitry Andric     if (Ps & ConstantProperties::NegOrZero)
4980b57cec5SDimitry Andric       os << "nez ";
4990b57cec5SDimitry Andric     os << '}';
5000b57cec5SDimitry Andric     return;
5010b57cec5SDimitry Andric   }
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric   os << "{ ";
5040b57cec5SDimitry Andric   if (isBottom()) {
5050b57cec5SDimitry Andric     os << "bottom";
5060b57cec5SDimitry Andric   } else if (isTop()) {
5070b57cec5SDimitry Andric     os << "top";
5080b57cec5SDimitry Andric   } else {
5090b57cec5SDimitry Andric     for (unsigned i = 0; i < size(); ++i) {
5100b57cec5SDimitry Andric       const Constant *C = Values[i];
5110b57cec5SDimitry Andric       if (i != 0)
5120b57cec5SDimitry Andric         os << ", ";
5130b57cec5SDimitry Andric       C->print(os);
5140b57cec5SDimitry Andric     }
5150b57cec5SDimitry Andric   }
5160b57cec5SDimitry Andric   os << " }";
5170b57cec5SDimitry Andric }
5180b57cec5SDimitry Andric #endif
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric // "Meet" operation on two cells. This is the key of the propagation
5210b57cec5SDimitry Andric // algorithm.
5220b57cec5SDimitry Andric bool LatticeCell::meet(const LatticeCell &L) {
5230b57cec5SDimitry Andric   bool Changed = false;
5240b57cec5SDimitry Andric   if (L.isBottom())
5250b57cec5SDimitry Andric     Changed = setBottom();
5260b57cec5SDimitry Andric   if (isBottom() || L.isTop())
5270b57cec5SDimitry Andric     return Changed;
5280b57cec5SDimitry Andric   if (isTop()) {
5290b57cec5SDimitry Andric     *this = L;
5300b57cec5SDimitry Andric     // L can be neither Top nor Bottom, so *this must have changed.
5310b57cec5SDimitry Andric     return true;
5320b57cec5SDimitry Andric   }
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric   // Top/bottom cases covered. Need to integrate L's set into ours.
5350b57cec5SDimitry Andric   if (L.isProperty())
5360b57cec5SDimitry Andric     return add(L.properties());
5370b57cec5SDimitry Andric   for (unsigned i = 0; i < L.size(); ++i) {
5380b57cec5SDimitry Andric     const Constant *LC = L.Values[i];
5390b57cec5SDimitry Andric     Changed |= add(LC);
5400b57cec5SDimitry Andric   }
5410b57cec5SDimitry Andric   return Changed;
5420b57cec5SDimitry Andric }
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric // Add a new constant to the cell. This is actually where the cell update
5450b57cec5SDimitry Andric // happens. If a cell has room for more constants, the new constant is added.
5460b57cec5SDimitry Andric // Otherwise, the cell is converted to a "property" cell (i.e. a cell that
5470b57cec5SDimitry Andric // will track properties of the associated values, and not the values
5480b57cec5SDimitry Andric // themselves. Care is taken to handle special cases, like "bottom", etc.
5490b57cec5SDimitry Andric bool LatticeCell::add(const Constant *LC) {
5500b57cec5SDimitry Andric   assert(LC);
5510b57cec5SDimitry Andric   if (isBottom())
5520b57cec5SDimitry Andric     return false;
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric   if (!isProperty()) {
5550b57cec5SDimitry Andric     // Cell is not special. Try to add the constant here first,
5560b57cec5SDimitry Andric     // if there is room.
5570b57cec5SDimitry Andric     unsigned Index = 0;
5580b57cec5SDimitry Andric     while (Index < Size) {
5590b57cec5SDimitry Andric       const Constant *C = Values[Index];
5600b57cec5SDimitry Andric       // If the constant is already here, no change is needed.
5610b57cec5SDimitry Andric       if (C == LC)
5620b57cec5SDimitry Andric         return false;
5630b57cec5SDimitry Andric       Index++;
5640b57cec5SDimitry Andric     }
5650b57cec5SDimitry Andric     if (Index < MaxCellSize) {
5660b57cec5SDimitry Andric       Values[Index] = LC;
5670b57cec5SDimitry Andric       Kind = Normal;
5680b57cec5SDimitry Andric       Size++;
5690b57cec5SDimitry Andric       return true;
5700b57cec5SDimitry Andric     }
5710b57cec5SDimitry Andric   }
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric   bool Changed = false;
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric   // This cell is special, or is not special, but is full. After this
5760b57cec5SDimitry Andric   // it will be special.
5770b57cec5SDimitry Andric   Changed = convertToProperty();
5780b57cec5SDimitry Andric   uint32_t Ps = properties();
5790b57cec5SDimitry Andric   uint32_t NewPs = Ps & ConstantProperties::deduce(LC);
5800b57cec5SDimitry Andric   if (NewPs == ConstantProperties::Unknown) {
5810b57cec5SDimitry Andric     setBottom();
5820b57cec5SDimitry Andric     return true;
5830b57cec5SDimitry Andric   }
5840b57cec5SDimitry Andric   if (Ps != NewPs) {
5850b57cec5SDimitry Andric     Properties = NewPs;
5860b57cec5SDimitry Andric     Changed = true;
5870b57cec5SDimitry Andric   }
5880b57cec5SDimitry Andric   return Changed;
5890b57cec5SDimitry Andric }
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric // Add a property to the cell. This will force the cell to become a property-
5920b57cec5SDimitry Andric // tracking cell.
5930b57cec5SDimitry Andric bool LatticeCell::add(uint32_t Property) {
5940b57cec5SDimitry Andric   bool Changed = convertToProperty();
5950b57cec5SDimitry Andric   uint32_t Ps = properties();
5960b57cec5SDimitry Andric   if (Ps == (Ps & Property))
5970b57cec5SDimitry Andric     return Changed;
5980b57cec5SDimitry Andric   Properties = Property & Ps;
5990b57cec5SDimitry Andric   return true;
6000b57cec5SDimitry Andric }
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric // Return the properties of the values in the cell. This is valid for any
6030b57cec5SDimitry Andric // cell, and does not alter the cell itself.
6040b57cec5SDimitry Andric uint32_t LatticeCell::properties() const {
6050b57cec5SDimitry Andric   if (isProperty())
6060b57cec5SDimitry Andric     return Properties;
6070b57cec5SDimitry Andric   assert(!isTop() && "Should not call this for a top cell");
6080b57cec5SDimitry Andric   if (isBottom())
6090b57cec5SDimitry Andric     return ConstantProperties::Unknown;
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric   assert(size() > 0 && "Empty cell");
6120b57cec5SDimitry Andric   uint32_t Ps = ConstantProperties::deduce(Values[0]);
6130b57cec5SDimitry Andric   for (unsigned i = 1; i < size(); ++i) {
6140b57cec5SDimitry Andric     if (Ps == ConstantProperties::Unknown)
6150b57cec5SDimitry Andric       break;
6160b57cec5SDimitry Andric     Ps &= ConstantProperties::deduce(Values[i]);
6170b57cec5SDimitry Andric   }
6180b57cec5SDimitry Andric   return Ps;
6190b57cec5SDimitry Andric }
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric #ifndef NDEBUG
6220b57cec5SDimitry Andric void MachineConstPropagator::CellMap::print(raw_ostream &os,
6230b57cec5SDimitry Andric       const TargetRegisterInfo &TRI) const {
6240b57cec5SDimitry Andric   for (auto &I : Map)
6250b57cec5SDimitry Andric     dbgs() << "  " << printReg(I.first, &TRI) << " -> " << I.second << '\n';
6260b57cec5SDimitry Andric }
6270b57cec5SDimitry Andric #endif
6280b57cec5SDimitry Andric 
6290b57cec5SDimitry Andric void MachineConstPropagator::visitPHI(const MachineInstr &PN) {
6300b57cec5SDimitry Andric   const MachineBasicBlock *MB = PN.getParent();
6310b57cec5SDimitry Andric   unsigned MBN = MB->getNumber();
6320b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Visiting FI(" << printMBBReference(*MB) << "): " << PN);
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric   const MachineOperand &MD = PN.getOperand(0);
6350b57cec5SDimitry Andric   RegisterSubReg DefR(MD);
6368bcb0991SDimitry Andric   assert(Register::isVirtualRegister(DefR.Reg));
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric   bool Changed = false;
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric   // If the def has a sub-register, set the corresponding cell to "bottom".
6410b57cec5SDimitry Andric   if (DefR.SubReg) {
6420b57cec5SDimitry Andric Bottomize:
6430b57cec5SDimitry Andric     const LatticeCell &T = Cells.get(DefR.Reg);
6440b57cec5SDimitry Andric     Changed = !T.isBottom();
6450b57cec5SDimitry Andric     Cells.update(DefR.Reg, Bottom);
6460b57cec5SDimitry Andric     if (Changed)
6470b57cec5SDimitry Andric       visitUsesOf(DefR.Reg);
6480b57cec5SDimitry Andric     return;
6490b57cec5SDimitry Andric   }
6500b57cec5SDimitry Andric 
6510b57cec5SDimitry Andric   LatticeCell DefC = Cells.get(DefR.Reg);
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric   for (unsigned i = 1, n = PN.getNumOperands(); i < n; i += 2) {
6540b57cec5SDimitry Andric     const MachineBasicBlock *PB = PN.getOperand(i+1).getMBB();
6550b57cec5SDimitry Andric     unsigned PBN = PB->getNumber();
6560b57cec5SDimitry Andric     if (!EdgeExec.count(CFGEdge(PBN, MBN))) {
6570b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "  edge " << printMBBReference(*PB) << "->"
6580b57cec5SDimitry Andric                         << printMBBReference(*MB) << " not executable\n");
6590b57cec5SDimitry Andric       continue;
6600b57cec5SDimitry Andric     }
6610b57cec5SDimitry Andric     const MachineOperand &SO = PN.getOperand(i);
6620b57cec5SDimitry Andric     RegisterSubReg UseR(SO);
6630b57cec5SDimitry Andric     // If the input is not a virtual register, we don't really know what
6640b57cec5SDimitry Andric     // value it holds.
6658bcb0991SDimitry Andric     if (!Register::isVirtualRegister(UseR.Reg))
6660b57cec5SDimitry Andric       goto Bottomize;
6670b57cec5SDimitry Andric     // If there is no cell for an input register, it means top.
6680b57cec5SDimitry Andric     if (!Cells.has(UseR.Reg))
6690b57cec5SDimitry Andric       continue;
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric     LatticeCell SrcC;
6720b57cec5SDimitry Andric     bool Eval = MCE.evaluate(UseR, Cells.get(UseR.Reg), SrcC);
6730b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "  edge from " << printMBBReference(*PB) << ": "
6740b57cec5SDimitry Andric                       << printReg(UseR.Reg, &MCE.TRI, UseR.SubReg) << SrcC
6750b57cec5SDimitry Andric                       << '\n');
6760b57cec5SDimitry Andric     Changed |= Eval ? DefC.meet(SrcC)
6770b57cec5SDimitry Andric                     : DefC.setBottom();
6780b57cec5SDimitry Andric     Cells.update(DefR.Reg, DefC);
6790b57cec5SDimitry Andric     if (DefC.isBottom())
6800b57cec5SDimitry Andric       break;
6810b57cec5SDimitry Andric   }
6820b57cec5SDimitry Andric   if (Changed)
6830b57cec5SDimitry Andric     visitUsesOf(DefR.Reg);
6840b57cec5SDimitry Andric }
6850b57cec5SDimitry Andric 
6860b57cec5SDimitry Andric void MachineConstPropagator::visitNonBranch(const MachineInstr &MI) {
6870b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Visiting MI(" << printMBBReference(*MI.getParent())
6880b57cec5SDimitry Andric                     << "): " << MI);
6890b57cec5SDimitry Andric   CellMap Outputs;
6900b57cec5SDimitry Andric   bool Eval = MCE.evaluate(MI, Cells, Outputs);
6910b57cec5SDimitry Andric   LLVM_DEBUG({
6920b57cec5SDimitry Andric     if (Eval) {
6930b57cec5SDimitry Andric       dbgs() << "  outputs:";
6940b57cec5SDimitry Andric       for (auto &I : Outputs)
6950b57cec5SDimitry Andric         dbgs() << ' ' << I.second;
6960b57cec5SDimitry Andric       dbgs() << '\n';
6970b57cec5SDimitry Andric     }
6980b57cec5SDimitry Andric   });
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric   // Update outputs. If the value was not computed, set all the
7010b57cec5SDimitry Andric   // def cells to bottom.
7020b57cec5SDimitry Andric   for (const MachineOperand &MO : MI.operands()) {
7030b57cec5SDimitry Andric     if (!MO.isReg() || !MO.isDef())
7040b57cec5SDimitry Andric       continue;
7050b57cec5SDimitry Andric     RegisterSubReg DefR(MO);
7060b57cec5SDimitry Andric     // Only track virtual registers.
7078bcb0991SDimitry Andric     if (!Register::isVirtualRegister(DefR.Reg))
7080b57cec5SDimitry Andric       continue;
7090b57cec5SDimitry Andric     bool Changed = false;
7100b57cec5SDimitry Andric     // If the evaluation failed, set cells for all output registers to bottom.
7110b57cec5SDimitry Andric     if (!Eval) {
7120b57cec5SDimitry Andric       const LatticeCell &T = Cells.get(DefR.Reg);
7130b57cec5SDimitry Andric       Changed = !T.isBottom();
7140b57cec5SDimitry Andric       Cells.update(DefR.Reg, Bottom);
7150b57cec5SDimitry Andric     } else {
7160b57cec5SDimitry Andric       // Find the corresponding cell in the computed outputs.
7170b57cec5SDimitry Andric       // If it's not there, go on to the next def.
7180b57cec5SDimitry Andric       if (!Outputs.has(DefR.Reg))
7190b57cec5SDimitry Andric         continue;
7200b57cec5SDimitry Andric       LatticeCell RC = Cells.get(DefR.Reg);
7210b57cec5SDimitry Andric       Changed = RC.meet(Outputs.get(DefR.Reg));
7220b57cec5SDimitry Andric       Cells.update(DefR.Reg, RC);
7230b57cec5SDimitry Andric     }
7240b57cec5SDimitry Andric     if (Changed)
7250b57cec5SDimitry Andric       visitUsesOf(DefR.Reg);
7260b57cec5SDimitry Andric   }
7270b57cec5SDimitry Andric }
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric // Starting at a given branch, visit remaining branches in the block.
7300b57cec5SDimitry Andric // Traverse over the subsequent branches for as long as the preceding one
7310b57cec5SDimitry Andric // can fall through. Add all the possible targets to the flow work queue,
7320b57cec5SDimitry Andric // including the potential fall-through to the layout-successor block.
7330b57cec5SDimitry Andric void MachineConstPropagator::visitBranchesFrom(const MachineInstr &BrI) {
7340b57cec5SDimitry Andric   const MachineBasicBlock &B = *BrI.getParent();
7350b57cec5SDimitry Andric   unsigned MBN = B.getNumber();
7360b57cec5SDimitry Andric   MachineBasicBlock::const_iterator It = BrI.getIterator();
7370b57cec5SDimitry Andric   MachineBasicBlock::const_iterator End = B.end();
7380b57cec5SDimitry Andric 
7390b57cec5SDimitry Andric   SetVector<const MachineBasicBlock*> Targets;
7400b57cec5SDimitry Andric   bool EvalOk = true, FallsThru = true;
7410b57cec5SDimitry Andric   while (It != End) {
7420b57cec5SDimitry Andric     const MachineInstr &MI = *It;
7430b57cec5SDimitry Andric     InstrExec.insert(&MI);
7440b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Visiting " << (EvalOk ? "BR" : "br") << "("
7450b57cec5SDimitry Andric                       << printMBBReference(B) << "): " << MI);
7460b57cec5SDimitry Andric     // Do not evaluate subsequent branches if the evaluation of any of the
7470b57cec5SDimitry Andric     // previous branches failed. Keep iterating over the branches only
7480b57cec5SDimitry Andric     // to mark them as executable.
7490b57cec5SDimitry Andric     EvalOk = EvalOk && MCE.evaluate(MI, Cells, Targets, FallsThru);
7500b57cec5SDimitry Andric     if (!EvalOk)
7510b57cec5SDimitry Andric       FallsThru = true;
7520b57cec5SDimitry Andric     if (!FallsThru)
7530b57cec5SDimitry Andric       break;
7540b57cec5SDimitry Andric     ++It;
7550b57cec5SDimitry Andric   }
7560b57cec5SDimitry Andric 
757*5ffd83dbSDimitry Andric   if (B.mayHaveInlineAsmBr())
758*5ffd83dbSDimitry Andric     EvalOk = false;
759*5ffd83dbSDimitry Andric 
7600b57cec5SDimitry Andric   if (EvalOk) {
7610b57cec5SDimitry Andric     // Need to add all CFG successors that lead to EH landing pads.
7620b57cec5SDimitry Andric     // There won't be explicit branches to these blocks, but they must
7630b57cec5SDimitry Andric     // be processed.
7640b57cec5SDimitry Andric     for (const MachineBasicBlock *SB : B.successors()) {
7650b57cec5SDimitry Andric       if (SB->isEHPad())
7660b57cec5SDimitry Andric         Targets.insert(SB);
7670b57cec5SDimitry Andric     }
7680b57cec5SDimitry Andric     if (FallsThru) {
7690b57cec5SDimitry Andric       const MachineFunction &MF = *B.getParent();
7700b57cec5SDimitry Andric       MachineFunction::const_iterator BI = B.getIterator();
7710b57cec5SDimitry Andric       MachineFunction::const_iterator Next = std::next(BI);
7720b57cec5SDimitry Andric       if (Next != MF.end())
7730b57cec5SDimitry Andric         Targets.insert(&*Next);
7740b57cec5SDimitry Andric     }
7750b57cec5SDimitry Andric   } else {
7760b57cec5SDimitry Andric     // If the evaluation of the branches failed, make "Targets" to be the
7770b57cec5SDimitry Andric     // set of all successors of the block from the CFG.
7780b57cec5SDimitry Andric     // If the evaluation succeeded for all visited branches, then if the
7790b57cec5SDimitry Andric     // last one set "FallsThru", then add an edge to the layout successor
7800b57cec5SDimitry Andric     // to the targets.
7810b57cec5SDimitry Andric     Targets.clear();
7820b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "  failed to evaluate a branch...adding all CFG "
7830b57cec5SDimitry Andric                          "successors\n");
7840b57cec5SDimitry Andric     for (const MachineBasicBlock *SB : B.successors())
7850b57cec5SDimitry Andric       Targets.insert(SB);
7860b57cec5SDimitry Andric   }
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric   for (const MachineBasicBlock *TB : Targets) {
7890b57cec5SDimitry Andric     unsigned TBN = TB->getNumber();
7900b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "  pushing edge " << printMBBReference(B) << " -> "
7910b57cec5SDimitry Andric                       << printMBBReference(*TB) << "\n");
7920b57cec5SDimitry Andric     FlowQ.push(CFGEdge(MBN, TBN));
7930b57cec5SDimitry Andric   }
7940b57cec5SDimitry Andric }
7950b57cec5SDimitry Andric 
7960b57cec5SDimitry Andric void MachineConstPropagator::visitUsesOf(unsigned Reg) {
7970b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Visiting uses of " << printReg(Reg, &MCE.TRI)
7980b57cec5SDimitry Andric                     << Cells.get(Reg) << '\n');
7990b57cec5SDimitry Andric   for (MachineInstr &MI : MRI->use_nodbg_instructions(Reg)) {
8000b57cec5SDimitry Andric     // Do not process non-executable instructions. They can become exceutable
8010b57cec5SDimitry Andric     // later (via a flow-edge in the work queue). In such case, the instruc-
8020b57cec5SDimitry Andric     // tion will be visited at that time.
8030b57cec5SDimitry Andric     if (!InstrExec.count(&MI))
8040b57cec5SDimitry Andric       continue;
8050b57cec5SDimitry Andric     if (MI.isPHI())
8060b57cec5SDimitry Andric       visitPHI(MI);
8070b57cec5SDimitry Andric     else if (!MI.isBranch())
8080b57cec5SDimitry Andric       visitNonBranch(MI);
8090b57cec5SDimitry Andric     else
8100b57cec5SDimitry Andric       visitBranchesFrom(MI);
8110b57cec5SDimitry Andric   }
8120b57cec5SDimitry Andric }
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric bool MachineConstPropagator::computeBlockSuccessors(const MachineBasicBlock *MB,
8150b57cec5SDimitry Andric       SetVector<const MachineBasicBlock*> &Targets) {
816*5ffd83dbSDimitry Andric   Targets.clear();
817*5ffd83dbSDimitry Andric 
8180b57cec5SDimitry Andric   MachineBasicBlock::const_iterator FirstBr = MB->end();
8190b57cec5SDimitry Andric   for (const MachineInstr &MI : *MB) {
820*5ffd83dbSDimitry Andric     if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
821*5ffd83dbSDimitry Andric       return false;
8220b57cec5SDimitry Andric     if (MI.isDebugInstr())
8230b57cec5SDimitry Andric       continue;
8240b57cec5SDimitry Andric     if (MI.isBranch()) {
8250b57cec5SDimitry Andric       FirstBr = MI.getIterator();
8260b57cec5SDimitry Andric       break;
8270b57cec5SDimitry Andric     }
8280b57cec5SDimitry Andric   }
8290b57cec5SDimitry Andric 
8300b57cec5SDimitry Andric   MachineBasicBlock::const_iterator End = MB->end();
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric   bool DoNext = true;
8330b57cec5SDimitry Andric   for (MachineBasicBlock::const_iterator I = FirstBr; I != End; ++I) {
8340b57cec5SDimitry Andric     const MachineInstr &MI = *I;
8350b57cec5SDimitry Andric     // Can there be debug instructions between branches?
8360b57cec5SDimitry Andric     if (MI.isDebugInstr())
8370b57cec5SDimitry Andric       continue;
8380b57cec5SDimitry Andric     if (!InstrExec.count(&MI))
8390b57cec5SDimitry Andric       continue;
8400b57cec5SDimitry Andric     bool Eval = MCE.evaluate(MI, Cells, Targets, DoNext);
8410b57cec5SDimitry Andric     if (!Eval)
8420b57cec5SDimitry Andric       return false;
8430b57cec5SDimitry Andric     if (!DoNext)
8440b57cec5SDimitry Andric       break;
8450b57cec5SDimitry Andric   }
8460b57cec5SDimitry Andric   // If the last branch could fall-through, add block's layout successor.
8470b57cec5SDimitry Andric   if (DoNext) {
8480b57cec5SDimitry Andric     MachineFunction::const_iterator BI = MB->getIterator();
8490b57cec5SDimitry Andric     MachineFunction::const_iterator NextI = std::next(BI);
8500b57cec5SDimitry Andric     if (NextI != MB->getParent()->end())
8510b57cec5SDimitry Andric       Targets.insert(&*NextI);
8520b57cec5SDimitry Andric   }
8530b57cec5SDimitry Andric 
8540b57cec5SDimitry Andric   // Add all the EH landing pads.
8550b57cec5SDimitry Andric   for (const MachineBasicBlock *SB : MB->successors())
8560b57cec5SDimitry Andric     if (SB->isEHPad())
8570b57cec5SDimitry Andric       Targets.insert(SB);
8580b57cec5SDimitry Andric 
8590b57cec5SDimitry Andric   return true;
8600b57cec5SDimitry Andric }
8610b57cec5SDimitry Andric 
8620b57cec5SDimitry Andric void MachineConstPropagator::removeCFGEdge(MachineBasicBlock *From,
8630b57cec5SDimitry Andric       MachineBasicBlock *To) {
8640b57cec5SDimitry Andric   // First, remove the CFG successor/predecessor information.
8650b57cec5SDimitry Andric   From->removeSuccessor(To);
8660b57cec5SDimitry Andric   // Remove all corresponding PHI operands in the To block.
8670b57cec5SDimitry Andric   for (auto I = To->begin(), E = To->getFirstNonPHI(); I != E; ++I) {
8680b57cec5SDimitry Andric     MachineInstr *PN = &*I;
8690b57cec5SDimitry Andric     // reg0 = PHI reg1, bb2, reg3, bb4, ...
8700b57cec5SDimitry Andric     int N = PN->getNumOperands()-2;
8710b57cec5SDimitry Andric     while (N > 0) {
8720b57cec5SDimitry Andric       if (PN->getOperand(N+1).getMBB() == From) {
8730b57cec5SDimitry Andric         PN->RemoveOperand(N+1);
8740b57cec5SDimitry Andric         PN->RemoveOperand(N);
8750b57cec5SDimitry Andric       }
8760b57cec5SDimitry Andric       N -= 2;
8770b57cec5SDimitry Andric     }
8780b57cec5SDimitry Andric   }
8790b57cec5SDimitry Andric }
8800b57cec5SDimitry Andric 
8810b57cec5SDimitry Andric void MachineConstPropagator::propagate(MachineFunction &MF) {
8820b57cec5SDimitry Andric   MachineBasicBlock *Entry = GraphTraits<MachineFunction*>::getEntryNode(&MF);
8830b57cec5SDimitry Andric   unsigned EntryNum = Entry->getNumber();
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric   // Start with a fake edge, just to process the entry node.
8860b57cec5SDimitry Andric   FlowQ.push(CFGEdge(EntryNum, EntryNum));
8870b57cec5SDimitry Andric 
8880b57cec5SDimitry Andric   while (!FlowQ.empty()) {
8890b57cec5SDimitry Andric     CFGEdge Edge = FlowQ.front();
8900b57cec5SDimitry Andric     FlowQ.pop();
8910b57cec5SDimitry Andric 
8920b57cec5SDimitry Andric     LLVM_DEBUG(
8930b57cec5SDimitry Andric         dbgs() << "Picked edge "
8940b57cec5SDimitry Andric                << printMBBReference(*MF.getBlockNumbered(Edge.first)) << "->"
8950b57cec5SDimitry Andric                << printMBBReference(*MF.getBlockNumbered(Edge.second)) << '\n');
8960b57cec5SDimitry Andric     if (Edge.first != EntryNum)
8970b57cec5SDimitry Andric       if (EdgeExec.count(Edge))
8980b57cec5SDimitry Andric         continue;
8990b57cec5SDimitry Andric     EdgeExec.insert(Edge);
9000b57cec5SDimitry Andric     MachineBasicBlock *SB = MF.getBlockNumbered(Edge.second);
9010b57cec5SDimitry Andric 
9020b57cec5SDimitry Andric     // Process the block in three stages:
9030b57cec5SDimitry Andric     // - visit all PHI nodes,
9040b57cec5SDimitry Andric     // - visit all non-branch instructions,
9050b57cec5SDimitry Andric     // - visit block branches.
9060b57cec5SDimitry Andric     MachineBasicBlock::const_iterator It = SB->begin(), End = SB->end();
9070b57cec5SDimitry Andric 
9080b57cec5SDimitry Andric     // Visit PHI nodes in the successor block.
9090b57cec5SDimitry Andric     while (It != End && It->isPHI()) {
9100b57cec5SDimitry Andric       InstrExec.insert(&*It);
9110b57cec5SDimitry Andric       visitPHI(*It);
9120b57cec5SDimitry Andric       ++It;
9130b57cec5SDimitry Andric     }
9140b57cec5SDimitry Andric 
9150b57cec5SDimitry Andric     // If the successor block just became executable, visit all instructions.
9160b57cec5SDimitry Andric     // To see if this is the first time we're visiting it, check the first
9170b57cec5SDimitry Andric     // non-debug instruction to see if it is executable.
9180b57cec5SDimitry Andric     while (It != End && It->isDebugInstr())
9190b57cec5SDimitry Andric       ++It;
9200b57cec5SDimitry Andric     assert(It == End || !It->isPHI());
9210b57cec5SDimitry Andric     // If this block has been visited, go on to the next one.
9220b57cec5SDimitry Andric     if (It != End && InstrExec.count(&*It))
9230b57cec5SDimitry Andric       continue;
9240b57cec5SDimitry Andric     // For now, scan all non-branch instructions. Branches require different
9250b57cec5SDimitry Andric     // processing.
9260b57cec5SDimitry Andric     while (It != End && !It->isBranch()) {
9270b57cec5SDimitry Andric       if (!It->isDebugInstr()) {
9280b57cec5SDimitry Andric         InstrExec.insert(&*It);
9290b57cec5SDimitry Andric         visitNonBranch(*It);
9300b57cec5SDimitry Andric       }
9310b57cec5SDimitry Andric       ++It;
9320b57cec5SDimitry Andric     }
9330b57cec5SDimitry Andric 
9340b57cec5SDimitry Andric     // Time to process the end of the block. This is different from
9350b57cec5SDimitry Andric     // processing regular (non-branch) instructions, because there can
9360b57cec5SDimitry Andric     // be multiple branches in a block, and they can cause the block to
9370b57cec5SDimitry Andric     // terminate early.
9380b57cec5SDimitry Andric     if (It != End) {
9390b57cec5SDimitry Andric       visitBranchesFrom(*It);
9400b57cec5SDimitry Andric     } else {
9410b57cec5SDimitry Andric       // If the block didn't have a branch, add all successor edges to the
9420b57cec5SDimitry Andric       // work queue. (There should really be only one successor in such case.)
9430b57cec5SDimitry Andric       unsigned SBN = SB->getNumber();
9440b57cec5SDimitry Andric       for (const MachineBasicBlock *SSB : SB->successors())
9450b57cec5SDimitry Andric         FlowQ.push(CFGEdge(SBN, SSB->getNumber()));
9460b57cec5SDimitry Andric     }
9470b57cec5SDimitry Andric   } // while (FlowQ)
9480b57cec5SDimitry Andric 
9490b57cec5SDimitry Andric   LLVM_DEBUG({
9500b57cec5SDimitry Andric     dbgs() << "Cells after propagation:\n";
9510b57cec5SDimitry Andric     Cells.print(dbgs(), MCE.TRI);
9520b57cec5SDimitry Andric     dbgs() << "Dead CFG edges:\n";
9530b57cec5SDimitry Andric     for (const MachineBasicBlock &B : MF) {
9540b57cec5SDimitry Andric       unsigned BN = B.getNumber();
9550b57cec5SDimitry Andric       for (const MachineBasicBlock *SB : B.successors()) {
9560b57cec5SDimitry Andric         unsigned SN = SB->getNumber();
9570b57cec5SDimitry Andric         if (!EdgeExec.count(CFGEdge(BN, SN)))
9580b57cec5SDimitry Andric           dbgs() << "  " << printMBBReference(B) << " -> "
9590b57cec5SDimitry Andric                  << printMBBReference(*SB) << '\n';
9600b57cec5SDimitry Andric       }
9610b57cec5SDimitry Andric     }
9620b57cec5SDimitry Andric   });
9630b57cec5SDimitry Andric }
9640b57cec5SDimitry Andric 
9650b57cec5SDimitry Andric bool MachineConstPropagator::rewrite(MachineFunction &MF) {
9660b57cec5SDimitry Andric   bool Changed = false;
9670b57cec5SDimitry Andric   // Rewrite all instructions based on the collected cell information.
9680b57cec5SDimitry Andric   //
9690b57cec5SDimitry Andric   // Traverse the instructions in a post-order, so that rewriting an
9700b57cec5SDimitry Andric   // instruction can make changes "downstream" in terms of control-flow
9710b57cec5SDimitry Andric   // without affecting the rewriting process. (We should not change
9720b57cec5SDimitry Andric   // instructions that have not yet been visited by the rewriter.)
9730b57cec5SDimitry Andric   // The reason for this is that the rewriter can introduce new vregs,
9740b57cec5SDimitry Andric   // and replace uses of old vregs (which had corresponding cells
9750b57cec5SDimitry Andric   // computed during propagation) with these new vregs (which at this
9760b57cec5SDimitry Andric   // point would not have any cells, and would appear to be "top").
9770b57cec5SDimitry Andric   // If an attempt was made to evaluate an instruction with a fresh
9780b57cec5SDimitry Andric   // "top" vreg, it would cause an error (abend) in the evaluator.
9790b57cec5SDimitry Andric 
9800b57cec5SDimitry Andric   // Collect the post-order-traversal block ordering. The subsequent
9810b57cec5SDimitry Andric   // traversal/rewrite will update block successors, so it's safer
9820b57cec5SDimitry Andric   // if the visiting order it computed ahead of time.
9830b57cec5SDimitry Andric   std::vector<MachineBasicBlock*> POT;
9840b57cec5SDimitry Andric   for (MachineBasicBlock *B : post_order(&MF))
9850b57cec5SDimitry Andric     if (!B->empty())
9860b57cec5SDimitry Andric       POT.push_back(B);
9870b57cec5SDimitry Andric 
9880b57cec5SDimitry Andric   for (MachineBasicBlock *B : POT) {
9890b57cec5SDimitry Andric     // Walk the block backwards (which usually begin with the branches).
9900b57cec5SDimitry Andric     // If any branch is rewritten, we may need to update the successor
9910b57cec5SDimitry Andric     // information for this block. Unless the block's successors can be
9920b57cec5SDimitry Andric     // precisely determined (which may not be the case for indirect
9930b57cec5SDimitry Andric     // branches), we cannot modify any branch.
9940b57cec5SDimitry Andric 
9950b57cec5SDimitry Andric     // Compute the successor information.
9960b57cec5SDimitry Andric     SetVector<const MachineBasicBlock*> Targets;
9970b57cec5SDimitry Andric     bool HaveTargets = computeBlockSuccessors(B, Targets);
9980b57cec5SDimitry Andric     // Rewrite the executable instructions. Skip branches if we don't
9990b57cec5SDimitry Andric     // have block successor information.
10000b57cec5SDimitry Andric     for (auto I = B->rbegin(), E = B->rend(); I != E; ++I) {
10010b57cec5SDimitry Andric       MachineInstr &MI = *I;
10020b57cec5SDimitry Andric       if (InstrExec.count(&MI)) {
10030b57cec5SDimitry Andric         if (MI.isBranch() && !HaveTargets)
10040b57cec5SDimitry Andric           continue;
10050b57cec5SDimitry Andric         Changed |= MCE.rewrite(MI, Cells);
10060b57cec5SDimitry Andric       }
10070b57cec5SDimitry Andric     }
10080b57cec5SDimitry Andric     // The rewriting could rewrite PHI nodes to non-PHI nodes, causing
10090b57cec5SDimitry Andric     // regular instructions to appear in between PHI nodes. Bring all
10100b57cec5SDimitry Andric     // the PHI nodes to the beginning of the block.
10110b57cec5SDimitry Andric     for (auto I = B->begin(), E = B->end(); I != E; ++I) {
10120b57cec5SDimitry Andric       if (I->isPHI())
10130b57cec5SDimitry Andric         continue;
10140b57cec5SDimitry Andric       // I is not PHI. Find the next PHI node P.
10150b57cec5SDimitry Andric       auto P = I;
10160b57cec5SDimitry Andric       while (++P != E)
10170b57cec5SDimitry Andric         if (P->isPHI())
10180b57cec5SDimitry Andric           break;
10190b57cec5SDimitry Andric       // Not found.
10200b57cec5SDimitry Andric       if (P == E)
10210b57cec5SDimitry Andric         break;
10220b57cec5SDimitry Andric       // Splice P right before I.
10230b57cec5SDimitry Andric       B->splice(I, B, P);
10240b57cec5SDimitry Andric       // Reset I to point at the just spliced PHI node.
10250b57cec5SDimitry Andric       --I;
10260b57cec5SDimitry Andric     }
10270b57cec5SDimitry Andric     // Update the block successor information: remove unnecessary successors.
10280b57cec5SDimitry Andric     if (HaveTargets) {
10290b57cec5SDimitry Andric       SmallVector<MachineBasicBlock*,2> ToRemove;
10300b57cec5SDimitry Andric       for (MachineBasicBlock *SB : B->successors()) {
10310b57cec5SDimitry Andric         if (!Targets.count(SB))
10320b57cec5SDimitry Andric           ToRemove.push_back(const_cast<MachineBasicBlock*>(SB));
10330b57cec5SDimitry Andric         Targets.remove(SB);
10340b57cec5SDimitry Andric       }
10350b57cec5SDimitry Andric       for (unsigned i = 0, n = ToRemove.size(); i < n; ++i)
10360b57cec5SDimitry Andric         removeCFGEdge(B, ToRemove[i]);
10370b57cec5SDimitry Andric       // If there are any blocks left in the computed targets, it means that
10380b57cec5SDimitry Andric       // we think that the block could go somewhere, but the CFG does not.
10390b57cec5SDimitry Andric       // This could legitimately happen in blocks that have non-returning
10400b57cec5SDimitry Andric       // calls---we would think that the execution can continue, but the
10410b57cec5SDimitry Andric       // CFG will not have a successor edge.
10420b57cec5SDimitry Andric     }
10430b57cec5SDimitry Andric   }
10440b57cec5SDimitry Andric   // Need to do some final post-processing.
10450b57cec5SDimitry Andric   // If a branch was not executable, it will not get rewritten, but should
10460b57cec5SDimitry Andric   // be removed (or replaced with something equivalent to a A2_nop). We can't
10470b57cec5SDimitry Andric   // erase instructions during rewriting, so this needs to be delayed until
10480b57cec5SDimitry Andric   // now.
10490b57cec5SDimitry Andric   for (MachineBasicBlock &B : MF) {
10500b57cec5SDimitry Andric     MachineBasicBlock::iterator I = B.begin(), E = B.end();
10510b57cec5SDimitry Andric     while (I != E) {
10520b57cec5SDimitry Andric       auto Next = std::next(I);
10530b57cec5SDimitry Andric       if (I->isBranch() && !InstrExec.count(&*I))
10540b57cec5SDimitry Andric         B.erase(I);
10550b57cec5SDimitry Andric       I = Next;
10560b57cec5SDimitry Andric     }
10570b57cec5SDimitry Andric   }
10580b57cec5SDimitry Andric   return Changed;
10590b57cec5SDimitry Andric }
10600b57cec5SDimitry Andric 
10610b57cec5SDimitry Andric // This is the constant propagation algorithm as described by Wegman-Zadeck.
10620b57cec5SDimitry Andric // Most of the terminology comes from there.
10630b57cec5SDimitry Andric bool MachineConstPropagator::run(MachineFunction &MF) {
10640b57cec5SDimitry Andric   LLVM_DEBUG(MF.print(dbgs() << "Starting MachineConstPropagator\n", nullptr));
10650b57cec5SDimitry Andric 
10660b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric   Cells.clear();
10690b57cec5SDimitry Andric   EdgeExec.clear();
10700b57cec5SDimitry Andric   InstrExec.clear();
10710b57cec5SDimitry Andric   assert(FlowQ.empty());
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric   propagate(MF);
10740b57cec5SDimitry Andric   bool Changed = rewrite(MF);
10750b57cec5SDimitry Andric 
10760b57cec5SDimitry Andric   LLVM_DEBUG({
10770b57cec5SDimitry Andric     dbgs() << "End of MachineConstPropagator (Changed=" << Changed << ")\n";
10780b57cec5SDimitry Andric     if (Changed)
10790b57cec5SDimitry Andric       MF.print(dbgs(), nullptr);
10800b57cec5SDimitry Andric   });
10810b57cec5SDimitry Andric   return Changed;
10820b57cec5SDimitry Andric }
10830b57cec5SDimitry Andric 
10840b57cec5SDimitry Andric // --------------------------------------------------------------------
10850b57cec5SDimitry Andric // Machine const evaluator.
10860b57cec5SDimitry Andric 
10870b57cec5SDimitry Andric bool MachineConstEvaluator::getCell(const RegisterSubReg &R, const CellMap &Inputs,
10880b57cec5SDimitry Andric       LatticeCell &RC) {
10898bcb0991SDimitry Andric   if (!Register::isVirtualRegister(R.Reg))
10900b57cec5SDimitry Andric     return false;
10910b57cec5SDimitry Andric   const LatticeCell &L = Inputs.get(R.Reg);
10920b57cec5SDimitry Andric   if (!R.SubReg) {
10930b57cec5SDimitry Andric     RC = L;
10940b57cec5SDimitry Andric     return !RC.isBottom();
10950b57cec5SDimitry Andric   }
10960b57cec5SDimitry Andric   bool Eval = evaluate(R, L, RC);
10970b57cec5SDimitry Andric   return Eval && !RC.isBottom();
10980b57cec5SDimitry Andric }
10990b57cec5SDimitry Andric 
11000b57cec5SDimitry Andric bool MachineConstEvaluator::constToInt(const Constant *C,
11010b57cec5SDimitry Andric       APInt &Val) const {
11020b57cec5SDimitry Andric   const ConstantInt *CI = dyn_cast<ConstantInt>(C);
11030b57cec5SDimitry Andric   if (!CI)
11040b57cec5SDimitry Andric     return false;
11050b57cec5SDimitry Andric   Val = CI->getValue();
11060b57cec5SDimitry Andric   return true;
11070b57cec5SDimitry Andric }
11080b57cec5SDimitry Andric 
11090b57cec5SDimitry Andric const ConstantInt *MachineConstEvaluator::intToConst(const APInt &Val) const {
11100b57cec5SDimitry Andric   return ConstantInt::get(CX, Val);
11110b57cec5SDimitry Andric }
11120b57cec5SDimitry Andric 
11130b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPrr(uint32_t Cmp, const RegisterSubReg &R1,
11140b57cec5SDimitry Andric       const RegisterSubReg &R2, const CellMap &Inputs, bool &Result) {
11150b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
11160b57cec5SDimitry Andric   LatticeCell LS1, LS2;
11170b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1) || !getCell(R2, Inputs, LS2))
11180b57cec5SDimitry Andric     return false;
11190b57cec5SDimitry Andric 
11200b57cec5SDimitry Andric   bool IsProp1 = LS1.isProperty();
11210b57cec5SDimitry Andric   bool IsProp2 = LS2.isProperty();
11220b57cec5SDimitry Andric   if (IsProp1) {
11230b57cec5SDimitry Andric     uint32_t Prop1 = LS1.properties();
11240b57cec5SDimitry Andric     if (IsProp2)
11250b57cec5SDimitry Andric       return evaluateCMPpp(Cmp, Prop1, LS2.properties(), Result);
11260b57cec5SDimitry Andric     uint32_t NegCmp = Comparison::negate(Cmp);
11270b57cec5SDimitry Andric     return evaluateCMPrp(NegCmp, R2, Prop1, Inputs, Result);
11280b57cec5SDimitry Andric   }
11290b57cec5SDimitry Andric   if (IsProp2) {
11300b57cec5SDimitry Andric     uint32_t Prop2 = LS2.properties();
11310b57cec5SDimitry Andric     return evaluateCMPrp(Cmp, R1, Prop2, Inputs, Result);
11320b57cec5SDimitry Andric   }
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric   APInt A;
11350b57cec5SDimitry Andric   bool IsTrue = true, IsFalse = true;
11360b57cec5SDimitry Andric   for (unsigned i = 0; i < LS2.size(); ++i) {
11370b57cec5SDimitry Andric     bool Res;
11380b57cec5SDimitry Andric     bool Computed = constToInt(LS2.Values[i], A) &&
11390b57cec5SDimitry Andric                     evaluateCMPri(Cmp, R1, A, Inputs, Res);
11400b57cec5SDimitry Andric     if (!Computed)
11410b57cec5SDimitry Andric       return false;
11420b57cec5SDimitry Andric     IsTrue &= Res;
11430b57cec5SDimitry Andric     IsFalse &= !Res;
11440b57cec5SDimitry Andric   }
11450b57cec5SDimitry Andric   assert(!IsTrue || !IsFalse);
11460b57cec5SDimitry Andric   // The actual logical value of the comparison is same as IsTrue.
11470b57cec5SDimitry Andric   Result = IsTrue;
11480b57cec5SDimitry Andric   // Return true if the result was proven to be true or proven to be false.
11490b57cec5SDimitry Andric   return IsTrue || IsFalse;
11500b57cec5SDimitry Andric }
11510b57cec5SDimitry Andric 
11520b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPri(uint32_t Cmp, const RegisterSubReg &R1,
11530b57cec5SDimitry Andric       const APInt &A2, const CellMap &Inputs, bool &Result) {
11540b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
11550b57cec5SDimitry Andric   LatticeCell LS;
11560b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS))
11570b57cec5SDimitry Andric     return false;
11580b57cec5SDimitry Andric   if (LS.isProperty())
11590b57cec5SDimitry Andric     return evaluateCMPpi(Cmp, LS.properties(), A2, Result);
11600b57cec5SDimitry Andric 
11610b57cec5SDimitry Andric   APInt A;
11620b57cec5SDimitry Andric   bool IsTrue = true, IsFalse = true;
11630b57cec5SDimitry Andric   for (unsigned i = 0; i < LS.size(); ++i) {
11640b57cec5SDimitry Andric     bool Res;
11650b57cec5SDimitry Andric     bool Computed = constToInt(LS.Values[i], A) &&
11660b57cec5SDimitry Andric                     evaluateCMPii(Cmp, A, A2, Res);
11670b57cec5SDimitry Andric     if (!Computed)
11680b57cec5SDimitry Andric       return false;
11690b57cec5SDimitry Andric     IsTrue &= Res;
11700b57cec5SDimitry Andric     IsFalse &= !Res;
11710b57cec5SDimitry Andric   }
11720b57cec5SDimitry Andric   assert(!IsTrue || !IsFalse);
11730b57cec5SDimitry Andric   // The actual logical value of the comparison is same as IsTrue.
11740b57cec5SDimitry Andric   Result = IsTrue;
11750b57cec5SDimitry Andric   // Return true if the result was proven to be true or proven to be false.
11760b57cec5SDimitry Andric   return IsTrue || IsFalse;
11770b57cec5SDimitry Andric }
11780b57cec5SDimitry Andric 
11790b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPrp(uint32_t Cmp, const RegisterSubReg &R1,
11800b57cec5SDimitry Andric       uint64_t Props2, const CellMap &Inputs, bool &Result) {
11810b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
11820b57cec5SDimitry Andric   LatticeCell LS;
11830b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS))
11840b57cec5SDimitry Andric     return false;
11850b57cec5SDimitry Andric   if (LS.isProperty())
11860b57cec5SDimitry Andric     return evaluateCMPpp(Cmp, LS.properties(), Props2, Result);
11870b57cec5SDimitry Andric 
11880b57cec5SDimitry Andric   APInt A;
11890b57cec5SDimitry Andric   uint32_t NegCmp = Comparison::negate(Cmp);
11900b57cec5SDimitry Andric   bool IsTrue = true, IsFalse = true;
11910b57cec5SDimitry Andric   for (unsigned i = 0; i < LS.size(); ++i) {
11920b57cec5SDimitry Andric     bool Res;
11930b57cec5SDimitry Andric     bool Computed = constToInt(LS.Values[i], A) &&
11940b57cec5SDimitry Andric                     evaluateCMPpi(NegCmp, Props2, A, Res);
11950b57cec5SDimitry Andric     if (!Computed)
11960b57cec5SDimitry Andric       return false;
11970b57cec5SDimitry Andric     IsTrue &= Res;
11980b57cec5SDimitry Andric     IsFalse &= !Res;
11990b57cec5SDimitry Andric   }
12000b57cec5SDimitry Andric   assert(!IsTrue || !IsFalse);
12010b57cec5SDimitry Andric   Result = IsTrue;
12020b57cec5SDimitry Andric   return IsTrue || IsFalse;
12030b57cec5SDimitry Andric }
12040b57cec5SDimitry Andric 
12050b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPii(uint32_t Cmp, const APInt &A1,
12060b57cec5SDimitry Andric       const APInt &A2, bool &Result) {
12070b57cec5SDimitry Andric   // NE is a special kind of comparison (not composed of smaller properties).
12080b57cec5SDimitry Andric   if (Cmp == Comparison::NE) {
12090b57cec5SDimitry Andric     Result = !APInt::isSameValue(A1, A2);
12100b57cec5SDimitry Andric     return true;
12110b57cec5SDimitry Andric   }
12120b57cec5SDimitry Andric   if (Cmp == Comparison::EQ) {
12130b57cec5SDimitry Andric     Result = APInt::isSameValue(A1, A2);
12140b57cec5SDimitry Andric     return true;
12150b57cec5SDimitry Andric   }
12160b57cec5SDimitry Andric   if (Cmp & Comparison::EQ) {
12170b57cec5SDimitry Andric     if (APInt::isSameValue(A1, A2))
12180b57cec5SDimitry Andric       return (Result = true);
12190b57cec5SDimitry Andric   }
12200b57cec5SDimitry Andric   assert((Cmp & (Comparison::L | Comparison::G)) && "Malformed comparison");
12210b57cec5SDimitry Andric   Result = false;
12220b57cec5SDimitry Andric 
12230b57cec5SDimitry Andric   unsigned W1 = A1.getBitWidth();
12240b57cec5SDimitry Andric   unsigned W2 = A2.getBitWidth();
12250b57cec5SDimitry Andric   unsigned MaxW = (W1 >= W2) ? W1 : W2;
12260b57cec5SDimitry Andric   if (Cmp & Comparison::U) {
12270b57cec5SDimitry Andric     const APInt Zx1 = A1.zextOrSelf(MaxW);
12280b57cec5SDimitry Andric     const APInt Zx2 = A2.zextOrSelf(MaxW);
12290b57cec5SDimitry Andric     if (Cmp & Comparison::L)
12300b57cec5SDimitry Andric       Result = Zx1.ult(Zx2);
12310b57cec5SDimitry Andric     else if (Cmp & Comparison::G)
12320b57cec5SDimitry Andric       Result = Zx2.ult(Zx1);
12330b57cec5SDimitry Andric     return true;
12340b57cec5SDimitry Andric   }
12350b57cec5SDimitry Andric 
12360b57cec5SDimitry Andric   // Signed comparison.
12370b57cec5SDimitry Andric   const APInt Sx1 = A1.sextOrSelf(MaxW);
12380b57cec5SDimitry Andric   const APInt Sx2 = A2.sextOrSelf(MaxW);
12390b57cec5SDimitry Andric   if (Cmp & Comparison::L)
12400b57cec5SDimitry Andric     Result = Sx1.slt(Sx2);
12410b57cec5SDimitry Andric   else if (Cmp & Comparison::G)
12420b57cec5SDimitry Andric     Result = Sx2.slt(Sx1);
12430b57cec5SDimitry Andric   return true;
12440b57cec5SDimitry Andric }
12450b57cec5SDimitry Andric 
12460b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPpi(uint32_t Cmp, uint32_t Props,
12470b57cec5SDimitry Andric       const APInt &A2, bool &Result) {
12480b57cec5SDimitry Andric   if (Props == ConstantProperties::Unknown)
12490b57cec5SDimitry Andric     return false;
12500b57cec5SDimitry Andric 
12510b57cec5SDimitry Andric   // Should never see NaN here, but check for it for completeness.
12520b57cec5SDimitry Andric   if (Props & ConstantProperties::NaN)
12530b57cec5SDimitry Andric     return false;
12540b57cec5SDimitry Andric   // Infinity could theoretically be compared to a number, but the
12550b57cec5SDimitry Andric   // presence of infinity here would be very suspicious. If we don't
12560b57cec5SDimitry Andric   // know for sure that the number is finite, bail out.
12570b57cec5SDimitry Andric   if (!(Props & ConstantProperties::Finite))
12580b57cec5SDimitry Andric     return false;
12590b57cec5SDimitry Andric 
12600b57cec5SDimitry Andric   // Let X be a number that has properties Props.
12610b57cec5SDimitry Andric 
12620b57cec5SDimitry Andric   if (Cmp & Comparison::U) {
12630b57cec5SDimitry Andric     // In case of unsigned comparisons, we can only compare against 0.
12640b57cec5SDimitry Andric     if (A2 == 0) {
12650b57cec5SDimitry Andric       // Any x!=0 will be considered >0 in an unsigned comparison.
12660b57cec5SDimitry Andric       if (Props & ConstantProperties::Zero)
12670b57cec5SDimitry Andric         Result = (Cmp & Comparison::EQ);
12680b57cec5SDimitry Andric       else if (Props & ConstantProperties::NonZero)
12690b57cec5SDimitry Andric         Result = (Cmp & Comparison::G) || (Cmp == Comparison::NE);
12700b57cec5SDimitry Andric       else
12710b57cec5SDimitry Andric         return false;
12720b57cec5SDimitry Andric       return true;
12730b57cec5SDimitry Andric     }
12740b57cec5SDimitry Andric     // A2 is not zero. The only handled case is if X = 0.
12750b57cec5SDimitry Andric     if (Props & ConstantProperties::Zero) {
12760b57cec5SDimitry Andric       Result = (Cmp & Comparison::L) || (Cmp == Comparison::NE);
12770b57cec5SDimitry Andric       return true;
12780b57cec5SDimitry Andric     }
12790b57cec5SDimitry Andric     return false;
12800b57cec5SDimitry Andric   }
12810b57cec5SDimitry Andric 
12820b57cec5SDimitry Andric   // Signed comparisons are different.
12830b57cec5SDimitry Andric   if (Props & ConstantProperties::Zero) {
12840b57cec5SDimitry Andric     if (A2 == 0)
12850b57cec5SDimitry Andric       Result = (Cmp & Comparison::EQ);
12860b57cec5SDimitry Andric     else
12870b57cec5SDimitry Andric       Result = (Cmp == Comparison::NE) ||
12880b57cec5SDimitry Andric                ((Cmp & Comparison::L) && !A2.isNegative()) ||
12890b57cec5SDimitry Andric                ((Cmp & Comparison::G) &&  A2.isNegative());
12900b57cec5SDimitry Andric     return true;
12910b57cec5SDimitry Andric   }
12920b57cec5SDimitry Andric   if (Props & ConstantProperties::PosOrZero) {
12930b57cec5SDimitry Andric     // X >= 0 and !(A2 < 0) => cannot compare
12940b57cec5SDimitry Andric     if (!A2.isNegative())
12950b57cec5SDimitry Andric       return false;
12960b57cec5SDimitry Andric     // X >= 0 and A2 < 0
12970b57cec5SDimitry Andric     Result = (Cmp & Comparison::G) || (Cmp == Comparison::NE);
12980b57cec5SDimitry Andric     return true;
12990b57cec5SDimitry Andric   }
13000b57cec5SDimitry Andric   if (Props & ConstantProperties::NegOrZero) {
13010b57cec5SDimitry Andric     // X <= 0 and Src1 < 0 => cannot compare
13020b57cec5SDimitry Andric     if (A2 == 0 || A2.isNegative())
13030b57cec5SDimitry Andric       return false;
13040b57cec5SDimitry Andric     // X <= 0 and A2 > 0
13050b57cec5SDimitry Andric     Result = (Cmp & Comparison::L) || (Cmp == Comparison::NE);
13060b57cec5SDimitry Andric     return true;
13070b57cec5SDimitry Andric   }
13080b57cec5SDimitry Andric 
13090b57cec5SDimitry Andric   return false;
13100b57cec5SDimitry Andric }
13110b57cec5SDimitry Andric 
13120b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPpp(uint32_t Cmp, uint32_t Props1,
13130b57cec5SDimitry Andric       uint32_t Props2, bool &Result) {
13140b57cec5SDimitry Andric   using P = ConstantProperties;
13150b57cec5SDimitry Andric 
13160b57cec5SDimitry Andric   if ((Props1 & P::NaN) && (Props2 & P::NaN))
13170b57cec5SDimitry Andric     return false;
13180b57cec5SDimitry Andric   if (!(Props1 & P::Finite) || !(Props2 & P::Finite))
13190b57cec5SDimitry Andric     return false;
13200b57cec5SDimitry Andric 
13210b57cec5SDimitry Andric   bool Zero1 = (Props1 & P::Zero), Zero2 = (Props2 & P::Zero);
13220b57cec5SDimitry Andric   bool NonZero1 = (Props1 & P::NonZero), NonZero2 = (Props2 & P::NonZero);
13230b57cec5SDimitry Andric   if (Zero1 && Zero2) {
13240b57cec5SDimitry Andric     Result = (Cmp & Comparison::EQ);
13250b57cec5SDimitry Andric     return true;
13260b57cec5SDimitry Andric   }
13270b57cec5SDimitry Andric   if (Cmp == Comparison::NE) {
13280b57cec5SDimitry Andric     if ((Zero1 && NonZero2) || (NonZero1 && Zero2))
13290b57cec5SDimitry Andric       return (Result = true);
13300b57cec5SDimitry Andric     return false;
13310b57cec5SDimitry Andric   }
13320b57cec5SDimitry Andric 
13330b57cec5SDimitry Andric   if (Cmp & Comparison::U) {
13340b57cec5SDimitry Andric     // In unsigned comparisons, we can only compare against a known zero,
13350b57cec5SDimitry Andric     // or a known non-zero.
13360b57cec5SDimitry Andric     if (Zero1 && NonZero2) {
13370b57cec5SDimitry Andric       Result = (Cmp & Comparison::L);
13380b57cec5SDimitry Andric       return true;
13390b57cec5SDimitry Andric     }
13400b57cec5SDimitry Andric     if (NonZero1 && Zero2) {
13410b57cec5SDimitry Andric       Result = (Cmp & Comparison::G);
13420b57cec5SDimitry Andric       return true;
13430b57cec5SDimitry Andric     }
13440b57cec5SDimitry Andric     return false;
13450b57cec5SDimitry Andric   }
13460b57cec5SDimitry Andric 
13470b57cec5SDimitry Andric   // Signed comparison. The comparison is not NE.
13480b57cec5SDimitry Andric   bool Poz1 = (Props1 & P::PosOrZero), Poz2 = (Props2 & P::PosOrZero);
13490b57cec5SDimitry Andric   bool Nez1 = (Props1 & P::NegOrZero), Nez2 = (Props2 & P::NegOrZero);
13500b57cec5SDimitry Andric   if (Nez1 && Poz2) {
13510b57cec5SDimitry Andric     if (NonZero1 || NonZero2) {
13520b57cec5SDimitry Andric       Result = (Cmp & Comparison::L);
13530b57cec5SDimitry Andric       return true;
13540b57cec5SDimitry Andric     }
13550b57cec5SDimitry Andric     // Either (or both) could be zero. Can only say that X <= Y.
13560b57cec5SDimitry Andric     if ((Cmp & Comparison::EQ) && (Cmp & Comparison::L))
13570b57cec5SDimitry Andric       return (Result = true);
13580b57cec5SDimitry Andric   }
13590b57cec5SDimitry Andric   if (Poz1 && Nez2) {
13600b57cec5SDimitry Andric     if (NonZero1 || NonZero2) {
13610b57cec5SDimitry Andric       Result = (Cmp & Comparison::G);
13620b57cec5SDimitry Andric       return true;
13630b57cec5SDimitry Andric     }
13640b57cec5SDimitry Andric     // Either (or both) could be zero. Can only say that X >= Y.
13650b57cec5SDimitry Andric     if ((Cmp & Comparison::EQ) && (Cmp & Comparison::G))
13660b57cec5SDimitry Andric       return (Result = true);
13670b57cec5SDimitry Andric   }
13680b57cec5SDimitry Andric 
13690b57cec5SDimitry Andric   return false;
13700b57cec5SDimitry Andric }
13710b57cec5SDimitry Andric 
13720b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCOPY(const RegisterSubReg &R1,
13730b57cec5SDimitry Andric       const CellMap &Inputs, LatticeCell &Result) {
13740b57cec5SDimitry Andric   return getCell(R1, Inputs, Result);
13750b57cec5SDimitry Andric }
13760b57cec5SDimitry Andric 
13770b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateANDrr(const RegisterSubReg &R1,
13780b57cec5SDimitry Andric       const RegisterSubReg &R2, const CellMap &Inputs, LatticeCell &Result) {
13790b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
13800b57cec5SDimitry Andric   const LatticeCell &L1 = Inputs.get(R2.Reg);
13810b57cec5SDimitry Andric   const LatticeCell &L2 = Inputs.get(R2.Reg);
13820b57cec5SDimitry Andric   // If both sources are bottom, exit. Otherwise try to evaluate ANDri
13830b57cec5SDimitry Andric   // with the non-bottom argument passed as the immediate. This is to
13840b57cec5SDimitry Andric   // catch cases of ANDing with 0.
13850b57cec5SDimitry Andric   if (L2.isBottom()) {
13860b57cec5SDimitry Andric     if (L1.isBottom())
13870b57cec5SDimitry Andric       return false;
13880b57cec5SDimitry Andric     return evaluateANDrr(R2, R1, Inputs, Result);
13890b57cec5SDimitry Andric   }
13900b57cec5SDimitry Andric   LatticeCell LS2;
13910b57cec5SDimitry Andric   if (!evaluate(R2, L2, LS2))
13920b57cec5SDimitry Andric     return false;
13930b57cec5SDimitry Andric   if (LS2.isBottom() || LS2.isProperty())
13940b57cec5SDimitry Andric     return false;
13950b57cec5SDimitry Andric 
13960b57cec5SDimitry Andric   APInt A;
13970b57cec5SDimitry Andric   for (unsigned i = 0; i < LS2.size(); ++i) {
13980b57cec5SDimitry Andric     LatticeCell RC;
13990b57cec5SDimitry Andric     bool Eval = constToInt(LS2.Values[i], A) &&
14000b57cec5SDimitry Andric                 evaluateANDri(R1, A, Inputs, RC);
14010b57cec5SDimitry Andric     if (!Eval)
14020b57cec5SDimitry Andric       return false;
14030b57cec5SDimitry Andric     Result.meet(RC);
14040b57cec5SDimitry Andric   }
14050b57cec5SDimitry Andric   return !Result.isBottom();
14060b57cec5SDimitry Andric }
14070b57cec5SDimitry Andric 
14080b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateANDri(const RegisterSubReg &R1,
14090b57cec5SDimitry Andric       const APInt &A2, const CellMap &Inputs, LatticeCell &Result) {
14100b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
14110b57cec5SDimitry Andric   if (A2 == -1)
14120b57cec5SDimitry Andric     return getCell(R1, Inputs, Result);
14130b57cec5SDimitry Andric   if (A2 == 0) {
14140b57cec5SDimitry Andric     LatticeCell RC;
14150b57cec5SDimitry Andric     RC.add(intToConst(A2));
14160b57cec5SDimitry Andric     // Overwrite Result.
14170b57cec5SDimitry Andric     Result = RC;
14180b57cec5SDimitry Andric     return true;
14190b57cec5SDimitry Andric   }
14200b57cec5SDimitry Andric   LatticeCell LS1;
14210b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
14220b57cec5SDimitry Andric     return false;
14230b57cec5SDimitry Andric   if (LS1.isBottom() || LS1.isProperty())
14240b57cec5SDimitry Andric     return false;
14250b57cec5SDimitry Andric 
14260b57cec5SDimitry Andric   APInt A, ResA;
14270b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
14280b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
14290b57cec5SDimitry Andric                 evaluateANDii(A, A2, ResA);
14300b57cec5SDimitry Andric     if (!Eval)
14310b57cec5SDimitry Andric       return false;
14320b57cec5SDimitry Andric     const Constant *C = intToConst(ResA);
14330b57cec5SDimitry Andric     Result.add(C);
14340b57cec5SDimitry Andric   }
14350b57cec5SDimitry Andric   return !Result.isBottom();
14360b57cec5SDimitry Andric }
14370b57cec5SDimitry Andric 
14380b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateANDii(const APInt &A1,
14390b57cec5SDimitry Andric       const APInt &A2, APInt &Result) {
14400b57cec5SDimitry Andric   Result = A1 & A2;
14410b57cec5SDimitry Andric   return true;
14420b57cec5SDimitry Andric }
14430b57cec5SDimitry Andric 
14440b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateORrr(const RegisterSubReg &R1,
14450b57cec5SDimitry Andric       const RegisterSubReg &R2, const CellMap &Inputs, LatticeCell &Result) {
14460b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
14470b57cec5SDimitry Andric   const LatticeCell &L1 = Inputs.get(R2.Reg);
14480b57cec5SDimitry Andric   const LatticeCell &L2 = Inputs.get(R2.Reg);
14490b57cec5SDimitry Andric   // If both sources are bottom, exit. Otherwise try to evaluate ORri
14500b57cec5SDimitry Andric   // with the non-bottom argument passed as the immediate. This is to
14510b57cec5SDimitry Andric   // catch cases of ORing with -1.
14520b57cec5SDimitry Andric   if (L2.isBottom()) {
14530b57cec5SDimitry Andric     if (L1.isBottom())
14540b57cec5SDimitry Andric       return false;
14550b57cec5SDimitry Andric     return evaluateORrr(R2, R1, Inputs, Result);
14560b57cec5SDimitry Andric   }
14570b57cec5SDimitry Andric   LatticeCell LS2;
14580b57cec5SDimitry Andric   if (!evaluate(R2, L2, LS2))
14590b57cec5SDimitry Andric     return false;
14600b57cec5SDimitry Andric   if (LS2.isBottom() || LS2.isProperty())
14610b57cec5SDimitry Andric     return false;
14620b57cec5SDimitry Andric 
14630b57cec5SDimitry Andric   APInt A;
14640b57cec5SDimitry Andric   for (unsigned i = 0; i < LS2.size(); ++i) {
14650b57cec5SDimitry Andric     LatticeCell RC;
14660b57cec5SDimitry Andric     bool Eval = constToInt(LS2.Values[i], A) &&
14670b57cec5SDimitry Andric                 evaluateORri(R1, A, Inputs, RC);
14680b57cec5SDimitry Andric     if (!Eval)
14690b57cec5SDimitry Andric       return false;
14700b57cec5SDimitry Andric     Result.meet(RC);
14710b57cec5SDimitry Andric   }
14720b57cec5SDimitry Andric   return !Result.isBottom();
14730b57cec5SDimitry Andric }
14740b57cec5SDimitry Andric 
14750b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateORri(const RegisterSubReg &R1,
14760b57cec5SDimitry Andric       const APInt &A2, const CellMap &Inputs, LatticeCell &Result) {
14770b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
14780b57cec5SDimitry Andric   if (A2 == 0)
14790b57cec5SDimitry Andric     return getCell(R1, Inputs, Result);
14800b57cec5SDimitry Andric   if (A2 == -1) {
14810b57cec5SDimitry Andric     LatticeCell RC;
14820b57cec5SDimitry Andric     RC.add(intToConst(A2));
14830b57cec5SDimitry Andric     // Overwrite Result.
14840b57cec5SDimitry Andric     Result = RC;
14850b57cec5SDimitry Andric     return true;
14860b57cec5SDimitry Andric   }
14870b57cec5SDimitry Andric   LatticeCell LS1;
14880b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
14890b57cec5SDimitry Andric     return false;
14900b57cec5SDimitry Andric   if (LS1.isBottom() || LS1.isProperty())
14910b57cec5SDimitry Andric     return false;
14920b57cec5SDimitry Andric 
14930b57cec5SDimitry Andric   APInt A, ResA;
14940b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
14950b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
14960b57cec5SDimitry Andric                 evaluateORii(A, A2, ResA);
14970b57cec5SDimitry Andric     if (!Eval)
14980b57cec5SDimitry Andric       return false;
14990b57cec5SDimitry Andric     const Constant *C = intToConst(ResA);
15000b57cec5SDimitry Andric     Result.add(C);
15010b57cec5SDimitry Andric   }
15020b57cec5SDimitry Andric   return !Result.isBottom();
15030b57cec5SDimitry Andric }
15040b57cec5SDimitry Andric 
15050b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateORii(const APInt &A1,
15060b57cec5SDimitry Andric       const APInt &A2, APInt &Result) {
15070b57cec5SDimitry Andric   Result = A1 | A2;
15080b57cec5SDimitry Andric   return true;
15090b57cec5SDimitry Andric }
15100b57cec5SDimitry Andric 
15110b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateXORrr(const RegisterSubReg &R1,
15120b57cec5SDimitry Andric       const RegisterSubReg &R2, const CellMap &Inputs, LatticeCell &Result) {
15130b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
15140b57cec5SDimitry Andric   LatticeCell LS1, LS2;
15150b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1) || !getCell(R2, Inputs, LS2))
15160b57cec5SDimitry Andric     return false;
15170b57cec5SDimitry Andric   if (LS1.isProperty()) {
15180b57cec5SDimitry Andric     if (LS1.properties() & ConstantProperties::Zero)
15190b57cec5SDimitry Andric       return !(Result = LS2).isBottom();
15200b57cec5SDimitry Andric     return false;
15210b57cec5SDimitry Andric   }
15220b57cec5SDimitry Andric   if (LS2.isProperty()) {
15230b57cec5SDimitry Andric     if (LS2.properties() & ConstantProperties::Zero)
15240b57cec5SDimitry Andric       return !(Result = LS1).isBottom();
15250b57cec5SDimitry Andric     return false;
15260b57cec5SDimitry Andric   }
15270b57cec5SDimitry Andric 
15280b57cec5SDimitry Andric   APInt A;
15290b57cec5SDimitry Andric   for (unsigned i = 0; i < LS2.size(); ++i) {
15300b57cec5SDimitry Andric     LatticeCell RC;
15310b57cec5SDimitry Andric     bool Eval = constToInt(LS2.Values[i], A) &&
15320b57cec5SDimitry Andric                 evaluateXORri(R1, A, Inputs, RC);
15330b57cec5SDimitry Andric     if (!Eval)
15340b57cec5SDimitry Andric       return false;
15350b57cec5SDimitry Andric     Result.meet(RC);
15360b57cec5SDimitry Andric   }
15370b57cec5SDimitry Andric   return !Result.isBottom();
15380b57cec5SDimitry Andric }
15390b57cec5SDimitry Andric 
15400b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateXORri(const RegisterSubReg &R1,
15410b57cec5SDimitry Andric       const APInt &A2, const CellMap &Inputs, LatticeCell &Result) {
15420b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
15430b57cec5SDimitry Andric   LatticeCell LS1;
15440b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
15450b57cec5SDimitry Andric     return false;
15460b57cec5SDimitry Andric   if (LS1.isProperty()) {
15470b57cec5SDimitry Andric     if (LS1.properties() & ConstantProperties::Zero) {
15480b57cec5SDimitry Andric       const Constant *C = intToConst(A2);
15490b57cec5SDimitry Andric       Result.add(C);
15500b57cec5SDimitry Andric       return !Result.isBottom();
15510b57cec5SDimitry Andric     }
15520b57cec5SDimitry Andric     return false;
15530b57cec5SDimitry Andric   }
15540b57cec5SDimitry Andric 
15550b57cec5SDimitry Andric   APInt A, XA;
15560b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
15570b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
15580b57cec5SDimitry Andric                 evaluateXORii(A, A2, XA);
15590b57cec5SDimitry Andric     if (!Eval)
15600b57cec5SDimitry Andric       return false;
15610b57cec5SDimitry Andric     const Constant *C = intToConst(XA);
15620b57cec5SDimitry Andric     Result.add(C);
15630b57cec5SDimitry Andric   }
15640b57cec5SDimitry Andric   return !Result.isBottom();
15650b57cec5SDimitry Andric }
15660b57cec5SDimitry Andric 
15670b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateXORii(const APInt &A1,
15680b57cec5SDimitry Andric       const APInt &A2, APInt &Result) {
15690b57cec5SDimitry Andric   Result = A1 ^ A2;
15700b57cec5SDimitry Andric   return true;
15710b57cec5SDimitry Andric }
15720b57cec5SDimitry Andric 
15730b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateZEXTr(const RegisterSubReg &R1, unsigned Width,
15740b57cec5SDimitry Andric       unsigned Bits, const CellMap &Inputs, LatticeCell &Result) {
15750b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
15760b57cec5SDimitry Andric   LatticeCell LS1;
15770b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
15780b57cec5SDimitry Andric     return false;
15790b57cec5SDimitry Andric   if (LS1.isProperty())
15800b57cec5SDimitry Andric     return false;
15810b57cec5SDimitry Andric 
15820b57cec5SDimitry Andric   APInt A, XA;
15830b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
15840b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
15850b57cec5SDimitry Andric                 evaluateZEXTi(A, Width, Bits, XA);
15860b57cec5SDimitry Andric     if (!Eval)
15870b57cec5SDimitry Andric       return false;
15880b57cec5SDimitry Andric     const Constant *C = intToConst(XA);
15890b57cec5SDimitry Andric     Result.add(C);
15900b57cec5SDimitry Andric   }
15910b57cec5SDimitry Andric   return true;
15920b57cec5SDimitry Andric }
15930b57cec5SDimitry Andric 
15940b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateZEXTi(const APInt &A1, unsigned Width,
15950b57cec5SDimitry Andric       unsigned Bits, APInt &Result) {
15960b57cec5SDimitry Andric   unsigned BW = A1.getBitWidth();
15970b57cec5SDimitry Andric   (void)BW;
15980b57cec5SDimitry Andric   assert(Width >= Bits && BW >= Bits);
15990b57cec5SDimitry Andric   APInt Mask = APInt::getLowBitsSet(Width, Bits);
16000b57cec5SDimitry Andric   Result = A1.zextOrTrunc(Width) & Mask;
16010b57cec5SDimitry Andric   return true;
16020b57cec5SDimitry Andric }
16030b57cec5SDimitry Andric 
16040b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateSEXTr(const RegisterSubReg &R1, unsigned Width,
16050b57cec5SDimitry Andric       unsigned Bits, const CellMap &Inputs, LatticeCell &Result) {
16060b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
16070b57cec5SDimitry Andric   LatticeCell LS1;
16080b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
16090b57cec5SDimitry Andric     return false;
16100b57cec5SDimitry Andric   if (LS1.isBottom() || LS1.isProperty())
16110b57cec5SDimitry Andric     return false;
16120b57cec5SDimitry Andric 
16130b57cec5SDimitry Andric   APInt A, XA;
16140b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
16150b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
16160b57cec5SDimitry Andric                 evaluateSEXTi(A, Width, Bits, XA);
16170b57cec5SDimitry Andric     if (!Eval)
16180b57cec5SDimitry Andric       return false;
16190b57cec5SDimitry Andric     const Constant *C = intToConst(XA);
16200b57cec5SDimitry Andric     Result.add(C);
16210b57cec5SDimitry Andric   }
16220b57cec5SDimitry Andric   return true;
16230b57cec5SDimitry Andric }
16240b57cec5SDimitry Andric 
16250b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateSEXTi(const APInt &A1, unsigned Width,
16260b57cec5SDimitry Andric       unsigned Bits, APInt &Result) {
16270b57cec5SDimitry Andric   unsigned BW = A1.getBitWidth();
16280b57cec5SDimitry Andric   assert(Width >= Bits && BW >= Bits);
16290b57cec5SDimitry Andric   // Special case to make things faster for smaller source widths.
16300b57cec5SDimitry Andric   // Sign extension of 0 bits generates 0 as a result. This is consistent
16310b57cec5SDimitry Andric   // with what the HW does.
16320b57cec5SDimitry Andric   if (Bits == 0) {
16330b57cec5SDimitry Andric     Result = APInt(Width, 0);
16340b57cec5SDimitry Andric     return true;
16350b57cec5SDimitry Andric   }
16360b57cec5SDimitry Andric   // In C, shifts by 64 invoke undefined behavior: handle that case in APInt.
16370b57cec5SDimitry Andric   if (BW <= 64 && Bits != 0) {
16380b57cec5SDimitry Andric     int64_t V = A1.getSExtValue();
16390b57cec5SDimitry Andric     switch (Bits) {
16400b57cec5SDimitry Andric       case 8:
16410b57cec5SDimitry Andric         V = static_cast<int8_t>(V);
16420b57cec5SDimitry Andric         break;
16430b57cec5SDimitry Andric       case 16:
16440b57cec5SDimitry Andric         V = static_cast<int16_t>(V);
16450b57cec5SDimitry Andric         break;
16460b57cec5SDimitry Andric       case 32:
16470b57cec5SDimitry Andric         V = static_cast<int32_t>(V);
16480b57cec5SDimitry Andric         break;
16490b57cec5SDimitry Andric       default:
16500b57cec5SDimitry Andric         // Shift left to lose all bits except lower "Bits" bits, then shift
16510b57cec5SDimitry Andric         // the value back, replicating what was a sign bit after the first
16520b57cec5SDimitry Andric         // shift.
16530b57cec5SDimitry Andric         V = (V << (64-Bits)) >> (64-Bits);
16540b57cec5SDimitry Andric         break;
16550b57cec5SDimitry Andric     }
16560b57cec5SDimitry Andric     // V is a 64-bit sign-extended value. Convert it to APInt of desired
16570b57cec5SDimitry Andric     // width.
16580b57cec5SDimitry Andric     Result = APInt(Width, V, true);
16590b57cec5SDimitry Andric     return true;
16600b57cec5SDimitry Andric   }
16610b57cec5SDimitry Andric   // Slow case: the value doesn't fit in int64_t.
16620b57cec5SDimitry Andric   if (Bits < BW)
16630b57cec5SDimitry Andric     Result = A1.trunc(Bits).sext(Width);
16640b57cec5SDimitry Andric   else // Bits == BW
16650b57cec5SDimitry Andric     Result = A1.sext(Width);
16660b57cec5SDimitry Andric   return true;
16670b57cec5SDimitry Andric }
16680b57cec5SDimitry Andric 
16690b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCLBr(const RegisterSubReg &R1, bool Zeros,
16700b57cec5SDimitry Andric       bool Ones, const CellMap &Inputs, LatticeCell &Result) {
16710b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
16720b57cec5SDimitry Andric   LatticeCell LS1;
16730b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
16740b57cec5SDimitry Andric     return false;
16750b57cec5SDimitry Andric   if (LS1.isBottom() || LS1.isProperty())
16760b57cec5SDimitry Andric     return false;
16770b57cec5SDimitry Andric 
16780b57cec5SDimitry Andric   APInt A, CA;
16790b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
16800b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
16810b57cec5SDimitry Andric                 evaluateCLBi(A, Zeros, Ones, CA);
16820b57cec5SDimitry Andric     if (!Eval)
16830b57cec5SDimitry Andric       return false;
16840b57cec5SDimitry Andric     const Constant *C = intToConst(CA);
16850b57cec5SDimitry Andric     Result.add(C);
16860b57cec5SDimitry Andric   }
16870b57cec5SDimitry Andric   return true;
16880b57cec5SDimitry Andric }
16890b57cec5SDimitry Andric 
16900b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCLBi(const APInt &A1, bool Zeros,
16910b57cec5SDimitry Andric       bool Ones, APInt &Result) {
16920b57cec5SDimitry Andric   unsigned BW = A1.getBitWidth();
16930b57cec5SDimitry Andric   if (!Zeros && !Ones)
16940b57cec5SDimitry Andric     return false;
16950b57cec5SDimitry Andric   unsigned Count = 0;
16960b57cec5SDimitry Andric   if (Zeros && (Count == 0))
16970b57cec5SDimitry Andric     Count = A1.countLeadingZeros();
16980b57cec5SDimitry Andric   if (Ones && (Count == 0))
16990b57cec5SDimitry Andric     Count = A1.countLeadingOnes();
17000b57cec5SDimitry Andric   Result = APInt(BW, static_cast<uint64_t>(Count), false);
17010b57cec5SDimitry Andric   return true;
17020b57cec5SDimitry Andric }
17030b57cec5SDimitry Andric 
17040b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCTBr(const RegisterSubReg &R1, bool Zeros,
17050b57cec5SDimitry Andric       bool Ones, const CellMap &Inputs, LatticeCell &Result) {
17060b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
17070b57cec5SDimitry Andric   LatticeCell LS1;
17080b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
17090b57cec5SDimitry Andric     return false;
17100b57cec5SDimitry Andric   if (LS1.isBottom() || LS1.isProperty())
17110b57cec5SDimitry Andric     return false;
17120b57cec5SDimitry Andric 
17130b57cec5SDimitry Andric   APInt A, CA;
17140b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
17150b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
17160b57cec5SDimitry Andric                 evaluateCTBi(A, Zeros, Ones, CA);
17170b57cec5SDimitry Andric     if (!Eval)
17180b57cec5SDimitry Andric       return false;
17190b57cec5SDimitry Andric     const Constant *C = intToConst(CA);
17200b57cec5SDimitry Andric     Result.add(C);
17210b57cec5SDimitry Andric   }
17220b57cec5SDimitry Andric   return true;
17230b57cec5SDimitry Andric }
17240b57cec5SDimitry Andric 
17250b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCTBi(const APInt &A1, bool Zeros,
17260b57cec5SDimitry Andric       bool Ones, APInt &Result) {
17270b57cec5SDimitry Andric   unsigned BW = A1.getBitWidth();
17280b57cec5SDimitry Andric   if (!Zeros && !Ones)
17290b57cec5SDimitry Andric     return false;
17300b57cec5SDimitry Andric   unsigned Count = 0;
17310b57cec5SDimitry Andric   if (Zeros && (Count == 0))
17320b57cec5SDimitry Andric     Count = A1.countTrailingZeros();
17330b57cec5SDimitry Andric   if (Ones && (Count == 0))
17340b57cec5SDimitry Andric     Count = A1.countTrailingOnes();
17350b57cec5SDimitry Andric   Result = APInt(BW, static_cast<uint64_t>(Count), false);
17360b57cec5SDimitry Andric   return true;
17370b57cec5SDimitry Andric }
17380b57cec5SDimitry Andric 
17390b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateEXTRACTr(const RegisterSubReg &R1,
17400b57cec5SDimitry Andric       unsigned Width, unsigned Bits, unsigned Offset, bool Signed,
17410b57cec5SDimitry Andric       const CellMap &Inputs, LatticeCell &Result) {
17420b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
17430b57cec5SDimitry Andric   assert(Bits+Offset <= Width);
17440b57cec5SDimitry Andric   LatticeCell LS1;
17450b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
17460b57cec5SDimitry Andric     return false;
17470b57cec5SDimitry Andric   if (LS1.isBottom())
17480b57cec5SDimitry Andric     return false;
17490b57cec5SDimitry Andric   if (LS1.isProperty()) {
17500b57cec5SDimitry Andric     uint32_t Ps = LS1.properties();
17510b57cec5SDimitry Andric     if (Ps & ConstantProperties::Zero) {
17520b57cec5SDimitry Andric       const Constant *C = intToConst(APInt(Width, 0, false));
17530b57cec5SDimitry Andric       Result.add(C);
17540b57cec5SDimitry Andric       return true;
17550b57cec5SDimitry Andric     }
17560b57cec5SDimitry Andric     return false;
17570b57cec5SDimitry Andric   }
17580b57cec5SDimitry Andric 
17590b57cec5SDimitry Andric   APInt A, CA;
17600b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
17610b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
17620b57cec5SDimitry Andric                 evaluateEXTRACTi(A, Bits, Offset, Signed, CA);
17630b57cec5SDimitry Andric     if (!Eval)
17640b57cec5SDimitry Andric       return false;
17650b57cec5SDimitry Andric     const Constant *C = intToConst(CA);
17660b57cec5SDimitry Andric     Result.add(C);
17670b57cec5SDimitry Andric   }
17680b57cec5SDimitry Andric   return true;
17690b57cec5SDimitry Andric }
17700b57cec5SDimitry Andric 
17710b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateEXTRACTi(const APInt &A1, unsigned Bits,
17720b57cec5SDimitry Andric       unsigned Offset, bool Signed, APInt &Result) {
17730b57cec5SDimitry Andric   unsigned BW = A1.getBitWidth();
17740b57cec5SDimitry Andric   assert(Bits+Offset <= BW);
17750b57cec5SDimitry Andric   // Extracting 0 bits generates 0 as a result (as indicated by the HW people).
17760b57cec5SDimitry Andric   if (Bits == 0) {
17770b57cec5SDimitry Andric     Result = APInt(BW, 0);
17780b57cec5SDimitry Andric     return true;
17790b57cec5SDimitry Andric   }
17800b57cec5SDimitry Andric   if (BW <= 64) {
17810b57cec5SDimitry Andric     int64_t V = A1.getZExtValue();
17820b57cec5SDimitry Andric     V <<= (64-Bits-Offset);
17830b57cec5SDimitry Andric     if (Signed)
17840b57cec5SDimitry Andric       V >>= (64-Bits);
17850b57cec5SDimitry Andric     else
17860b57cec5SDimitry Andric       V = static_cast<uint64_t>(V) >> (64-Bits);
17870b57cec5SDimitry Andric     Result = APInt(BW, V, Signed);
17880b57cec5SDimitry Andric     return true;
17890b57cec5SDimitry Andric   }
17900b57cec5SDimitry Andric   if (Signed)
17910b57cec5SDimitry Andric     Result = A1.shl(BW-Bits-Offset).ashr(BW-Bits);
17920b57cec5SDimitry Andric   else
17930b57cec5SDimitry Andric     Result = A1.shl(BW-Bits-Offset).lshr(BW-Bits);
17940b57cec5SDimitry Andric   return true;
17950b57cec5SDimitry Andric }
17960b57cec5SDimitry Andric 
17970b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateSplatr(const RegisterSubReg &R1,
17980b57cec5SDimitry Andric       unsigned Bits, unsigned Count, const CellMap &Inputs,
17990b57cec5SDimitry Andric       LatticeCell &Result) {
18000b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
18010b57cec5SDimitry Andric   LatticeCell LS1;
18020b57cec5SDimitry Andric   if (!getCell(R1, Inputs, LS1))
18030b57cec5SDimitry Andric     return false;
18040b57cec5SDimitry Andric   if (LS1.isBottom() || LS1.isProperty())
18050b57cec5SDimitry Andric     return false;
18060b57cec5SDimitry Andric 
18070b57cec5SDimitry Andric   APInt A, SA;
18080b57cec5SDimitry Andric   for (unsigned i = 0; i < LS1.size(); ++i) {
18090b57cec5SDimitry Andric     bool Eval = constToInt(LS1.Values[i], A) &&
18100b57cec5SDimitry Andric                 evaluateSplati(A, Bits, Count, SA);
18110b57cec5SDimitry Andric     if (!Eval)
18120b57cec5SDimitry Andric       return false;
18130b57cec5SDimitry Andric     const Constant *C = intToConst(SA);
18140b57cec5SDimitry Andric     Result.add(C);
18150b57cec5SDimitry Andric   }
18160b57cec5SDimitry Andric   return true;
18170b57cec5SDimitry Andric }
18180b57cec5SDimitry Andric 
18190b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateSplati(const APInt &A1, unsigned Bits,
18200b57cec5SDimitry Andric       unsigned Count, APInt &Result) {
18210b57cec5SDimitry Andric   assert(Count > 0);
18220b57cec5SDimitry Andric   unsigned BW = A1.getBitWidth(), SW = Count*Bits;
18230b57cec5SDimitry Andric   APInt LoBits = (Bits < BW) ? A1.trunc(Bits) : A1.zextOrSelf(Bits);
18240b57cec5SDimitry Andric   if (Count > 1)
18250b57cec5SDimitry Andric     LoBits = LoBits.zext(SW);
18260b57cec5SDimitry Andric 
18270b57cec5SDimitry Andric   APInt Res(SW, 0, false);
18280b57cec5SDimitry Andric   for (unsigned i = 0; i < Count; ++i) {
18290b57cec5SDimitry Andric     Res <<= Bits;
18300b57cec5SDimitry Andric     Res |= LoBits;
18310b57cec5SDimitry Andric   }
18320b57cec5SDimitry Andric   Result = Res;
18330b57cec5SDimitry Andric   return true;
18340b57cec5SDimitry Andric }
18350b57cec5SDimitry Andric 
18360b57cec5SDimitry Andric // ----------------------------------------------------------------------
18370b57cec5SDimitry Andric // Hexagon-specific code.
18380b57cec5SDimitry Andric 
18390b57cec5SDimitry Andric namespace llvm {
18400b57cec5SDimitry Andric 
18410b57cec5SDimitry Andric   FunctionPass *createHexagonConstPropagationPass();
18420b57cec5SDimitry Andric   void initializeHexagonConstPropagationPass(PassRegistry &Registry);
18430b57cec5SDimitry Andric 
18440b57cec5SDimitry Andric } // end namespace llvm
18450b57cec5SDimitry Andric 
18460b57cec5SDimitry Andric namespace {
18470b57cec5SDimitry Andric 
18480b57cec5SDimitry Andric   class HexagonConstEvaluator : public MachineConstEvaluator {
18490b57cec5SDimitry Andric   public:
18500b57cec5SDimitry Andric     HexagonConstEvaluator(MachineFunction &Fn);
18510b57cec5SDimitry Andric 
18520b57cec5SDimitry Andric     bool evaluate(const MachineInstr &MI, const CellMap &Inputs,
18530b57cec5SDimitry Andric           CellMap &Outputs) override;
18540b57cec5SDimitry Andric     bool evaluate(const RegisterSubReg &R, const LatticeCell &SrcC,
18550b57cec5SDimitry Andric           LatticeCell &Result) override;
18560b57cec5SDimitry Andric     bool evaluate(const MachineInstr &BrI, const CellMap &Inputs,
18570b57cec5SDimitry Andric           SetVector<const MachineBasicBlock*> &Targets, bool &FallsThru)
18580b57cec5SDimitry Andric           override;
18590b57cec5SDimitry Andric     bool rewrite(MachineInstr &MI, const CellMap &Inputs) override;
18600b57cec5SDimitry Andric 
18610b57cec5SDimitry Andric   private:
18620b57cec5SDimitry Andric     unsigned getRegBitWidth(unsigned Reg) const;
18630b57cec5SDimitry Andric 
18640b57cec5SDimitry Andric     static uint32_t getCmp(unsigned Opc);
18650b57cec5SDimitry Andric     static APInt getCmpImm(unsigned Opc, unsigned OpX,
18660b57cec5SDimitry Andric           const MachineOperand &MO);
18670b57cec5SDimitry Andric     void replaceWithNop(MachineInstr &MI);
18680b57cec5SDimitry Andric 
18690b57cec5SDimitry Andric     bool evaluateHexRSEQ32(RegisterSubReg RL, RegisterSubReg RH, const CellMap &Inputs,
18700b57cec5SDimitry Andric           LatticeCell &Result);
18710b57cec5SDimitry Andric     bool evaluateHexCompare(const MachineInstr &MI, const CellMap &Inputs,
18720b57cec5SDimitry Andric           CellMap &Outputs);
18730b57cec5SDimitry Andric     // This is suitable to be called for compare-and-jump instructions.
18740b57cec5SDimitry Andric     bool evaluateHexCompare2(uint32_t Cmp, const MachineOperand &Src1,
18750b57cec5SDimitry Andric           const MachineOperand &Src2, const CellMap &Inputs, bool &Result);
18760b57cec5SDimitry Andric     bool evaluateHexLogical(const MachineInstr &MI, const CellMap &Inputs,
18770b57cec5SDimitry Andric           CellMap &Outputs);
18780b57cec5SDimitry Andric     bool evaluateHexCondMove(const MachineInstr &MI, const CellMap &Inputs,
18790b57cec5SDimitry Andric           CellMap &Outputs);
18800b57cec5SDimitry Andric     bool evaluateHexExt(const MachineInstr &MI, const CellMap &Inputs,
18810b57cec5SDimitry Andric           CellMap &Outputs);
18820b57cec5SDimitry Andric     bool evaluateHexVector1(const MachineInstr &MI, const CellMap &Inputs,
18830b57cec5SDimitry Andric           CellMap &Outputs);
18840b57cec5SDimitry Andric     bool evaluateHexVector2(const MachineInstr &MI, const CellMap &Inputs,
18850b57cec5SDimitry Andric           CellMap &Outputs);
18860b57cec5SDimitry Andric 
18870b57cec5SDimitry Andric     void replaceAllRegUsesWith(unsigned FromReg, unsigned ToReg);
18880b57cec5SDimitry Andric     bool rewriteHexBranch(MachineInstr &BrI, const CellMap &Inputs);
18890b57cec5SDimitry Andric     bool rewriteHexConstDefs(MachineInstr &MI, const CellMap &Inputs,
18900b57cec5SDimitry Andric           bool &AllDefs);
18910b57cec5SDimitry Andric     bool rewriteHexConstUses(MachineInstr &MI, const CellMap &Inputs);
18920b57cec5SDimitry Andric 
18930b57cec5SDimitry Andric     MachineRegisterInfo *MRI;
18940b57cec5SDimitry Andric     const HexagonInstrInfo &HII;
18950b57cec5SDimitry Andric     const HexagonRegisterInfo &HRI;
18960b57cec5SDimitry Andric   };
18970b57cec5SDimitry Andric 
18980b57cec5SDimitry Andric   class HexagonConstPropagation : public MachineFunctionPass {
18990b57cec5SDimitry Andric   public:
19000b57cec5SDimitry Andric     static char ID;
19010b57cec5SDimitry Andric 
19020b57cec5SDimitry Andric     HexagonConstPropagation() : MachineFunctionPass(ID) {}
19030b57cec5SDimitry Andric 
19040b57cec5SDimitry Andric     StringRef getPassName() const override {
19050b57cec5SDimitry Andric       return "Hexagon Constant Propagation";
19060b57cec5SDimitry Andric     }
19070b57cec5SDimitry Andric 
19080b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &MF) override {
19090b57cec5SDimitry Andric       const Function &F = MF.getFunction();
19100b57cec5SDimitry Andric       if (skipFunction(F))
19110b57cec5SDimitry Andric         return false;
19120b57cec5SDimitry Andric 
19130b57cec5SDimitry Andric       HexagonConstEvaluator HCE(MF);
19140b57cec5SDimitry Andric       return MachineConstPropagator(HCE).run(MF);
19150b57cec5SDimitry Andric     }
19160b57cec5SDimitry Andric   };
19170b57cec5SDimitry Andric 
19180b57cec5SDimitry Andric } // end anonymous namespace
19190b57cec5SDimitry Andric 
19200b57cec5SDimitry Andric char HexagonConstPropagation::ID = 0;
19210b57cec5SDimitry Andric 
19220b57cec5SDimitry Andric INITIALIZE_PASS(HexagonConstPropagation, "hexagon-constp",
19230b57cec5SDimitry Andric   "Hexagon Constant Propagation", false, false)
19240b57cec5SDimitry Andric 
19250b57cec5SDimitry Andric HexagonConstEvaluator::HexagonConstEvaluator(MachineFunction &Fn)
19260b57cec5SDimitry Andric   : MachineConstEvaluator(Fn),
19270b57cec5SDimitry Andric     HII(*Fn.getSubtarget<HexagonSubtarget>().getInstrInfo()),
19280b57cec5SDimitry Andric     HRI(*Fn.getSubtarget<HexagonSubtarget>().getRegisterInfo()) {
19290b57cec5SDimitry Andric   MRI = &Fn.getRegInfo();
19300b57cec5SDimitry Andric }
19310b57cec5SDimitry Andric 
19320b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluate(const MachineInstr &MI,
19330b57cec5SDimitry Andric       const CellMap &Inputs, CellMap &Outputs) {
19340b57cec5SDimitry Andric   if (MI.isCall())
19350b57cec5SDimitry Andric     return false;
19360b57cec5SDimitry Andric   if (MI.getNumOperands() == 0 || !MI.getOperand(0).isReg())
19370b57cec5SDimitry Andric     return false;
19380b57cec5SDimitry Andric   const MachineOperand &MD = MI.getOperand(0);
19390b57cec5SDimitry Andric   if (!MD.isDef())
19400b57cec5SDimitry Andric     return false;
19410b57cec5SDimitry Andric 
19420b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
19430b57cec5SDimitry Andric   RegisterSubReg DefR(MD);
19440b57cec5SDimitry Andric   assert(!DefR.SubReg);
19458bcb0991SDimitry Andric   if (!Register::isVirtualRegister(DefR.Reg))
19460b57cec5SDimitry Andric     return false;
19470b57cec5SDimitry Andric 
19480b57cec5SDimitry Andric   if (MI.isCopy()) {
19490b57cec5SDimitry Andric     LatticeCell RC;
19500b57cec5SDimitry Andric     RegisterSubReg SrcR(MI.getOperand(1));
19510b57cec5SDimitry Andric     bool Eval = evaluateCOPY(SrcR, Inputs, RC);
19520b57cec5SDimitry Andric     if (!Eval)
19530b57cec5SDimitry Andric       return false;
19540b57cec5SDimitry Andric     Outputs.update(DefR.Reg, RC);
19550b57cec5SDimitry Andric     return true;
19560b57cec5SDimitry Andric   }
19570b57cec5SDimitry Andric   if (MI.isRegSequence()) {
19580b57cec5SDimitry Andric     unsigned Sub1 = MI.getOperand(2).getImm();
19590b57cec5SDimitry Andric     unsigned Sub2 = MI.getOperand(4).getImm();
19600b57cec5SDimitry Andric     const TargetRegisterClass &DefRC = *MRI->getRegClass(DefR.Reg);
19610b57cec5SDimitry Andric     unsigned SubLo = HRI.getHexagonSubRegIndex(DefRC, Hexagon::ps_sub_lo);
19620b57cec5SDimitry Andric     unsigned SubHi = HRI.getHexagonSubRegIndex(DefRC, Hexagon::ps_sub_hi);
19630b57cec5SDimitry Andric     if (Sub1 != SubLo && Sub1 != SubHi)
19640b57cec5SDimitry Andric       return false;
19650b57cec5SDimitry Andric     if (Sub2 != SubLo && Sub2 != SubHi)
19660b57cec5SDimitry Andric       return false;
19670b57cec5SDimitry Andric     assert(Sub1 != Sub2);
19680b57cec5SDimitry Andric     bool LoIs1 = (Sub1 == SubLo);
19690b57cec5SDimitry Andric     const MachineOperand &OpLo = LoIs1 ? MI.getOperand(1) : MI.getOperand(3);
19700b57cec5SDimitry Andric     const MachineOperand &OpHi = LoIs1 ? MI.getOperand(3) : MI.getOperand(1);
19710b57cec5SDimitry Andric     LatticeCell RC;
19720b57cec5SDimitry Andric     RegisterSubReg SrcRL(OpLo), SrcRH(OpHi);
19730b57cec5SDimitry Andric     bool Eval = evaluateHexRSEQ32(SrcRL, SrcRH, Inputs, RC);
19740b57cec5SDimitry Andric     if (!Eval)
19750b57cec5SDimitry Andric       return false;
19760b57cec5SDimitry Andric     Outputs.update(DefR.Reg, RC);
19770b57cec5SDimitry Andric     return true;
19780b57cec5SDimitry Andric   }
19790b57cec5SDimitry Andric   if (MI.isCompare()) {
19800b57cec5SDimitry Andric     bool Eval = evaluateHexCompare(MI, Inputs, Outputs);
19810b57cec5SDimitry Andric     return Eval;
19820b57cec5SDimitry Andric   }
19830b57cec5SDimitry Andric 
19840b57cec5SDimitry Andric   switch (Opc) {
19850b57cec5SDimitry Andric     default:
19860b57cec5SDimitry Andric       return false;
19870b57cec5SDimitry Andric     case Hexagon::A2_tfrsi:
19880b57cec5SDimitry Andric     case Hexagon::A2_tfrpi:
19890b57cec5SDimitry Andric     case Hexagon::CONST32:
19900b57cec5SDimitry Andric     case Hexagon::CONST64:
19910b57cec5SDimitry Andric     {
19920b57cec5SDimitry Andric       const MachineOperand &VO = MI.getOperand(1);
19930b57cec5SDimitry Andric       // The operand of CONST32 can be a blockaddress, e.g.
19940b57cec5SDimitry Andric       //   %0 = CONST32 <blockaddress(@eat, %l)>
19950b57cec5SDimitry Andric       // Do this check for all instructions for safety.
19960b57cec5SDimitry Andric       if (!VO.isImm())
19970b57cec5SDimitry Andric         return false;
19980b57cec5SDimitry Andric       int64_t V = MI.getOperand(1).getImm();
19990b57cec5SDimitry Andric       unsigned W = getRegBitWidth(DefR.Reg);
20000b57cec5SDimitry Andric       if (W != 32 && W != 64)
20010b57cec5SDimitry Andric         return false;
20020b57cec5SDimitry Andric       IntegerType *Ty = (W == 32) ? Type::getInt32Ty(CX)
20030b57cec5SDimitry Andric                                   : Type::getInt64Ty(CX);
20040b57cec5SDimitry Andric       const ConstantInt *CI = ConstantInt::get(Ty, V, true);
20050b57cec5SDimitry Andric       LatticeCell RC = Outputs.get(DefR.Reg);
20060b57cec5SDimitry Andric       RC.add(CI);
20070b57cec5SDimitry Andric       Outputs.update(DefR.Reg, RC);
20080b57cec5SDimitry Andric       break;
20090b57cec5SDimitry Andric     }
20100b57cec5SDimitry Andric 
20110b57cec5SDimitry Andric     case Hexagon::PS_true:
20120b57cec5SDimitry Andric     case Hexagon::PS_false:
20130b57cec5SDimitry Andric     {
20140b57cec5SDimitry Andric       LatticeCell RC = Outputs.get(DefR.Reg);
20150b57cec5SDimitry Andric       bool NonZero = (Opc == Hexagon::PS_true);
20160b57cec5SDimitry Andric       uint32_t P = NonZero ? ConstantProperties::NonZero
20170b57cec5SDimitry Andric                            : ConstantProperties::Zero;
20180b57cec5SDimitry Andric       RC.add(P);
20190b57cec5SDimitry Andric       Outputs.update(DefR.Reg, RC);
20200b57cec5SDimitry Andric       break;
20210b57cec5SDimitry Andric     }
20220b57cec5SDimitry Andric 
20230b57cec5SDimitry Andric     case Hexagon::A2_and:
20240b57cec5SDimitry Andric     case Hexagon::A2_andir:
20250b57cec5SDimitry Andric     case Hexagon::A2_andp:
20260b57cec5SDimitry Andric     case Hexagon::A2_or:
20270b57cec5SDimitry Andric     case Hexagon::A2_orir:
20280b57cec5SDimitry Andric     case Hexagon::A2_orp:
20290b57cec5SDimitry Andric     case Hexagon::A2_xor:
20300b57cec5SDimitry Andric     case Hexagon::A2_xorp:
20310b57cec5SDimitry Andric     {
20320b57cec5SDimitry Andric       bool Eval = evaluateHexLogical(MI, Inputs, Outputs);
20330b57cec5SDimitry Andric       if (!Eval)
20340b57cec5SDimitry Andric         return false;
20350b57cec5SDimitry Andric       break;
20360b57cec5SDimitry Andric     }
20370b57cec5SDimitry Andric 
20380b57cec5SDimitry Andric     case Hexagon::A2_combineii:  // combine(#s8Ext, #s8)
20390b57cec5SDimitry Andric     case Hexagon::A4_combineii:  // combine(#s8, #u6Ext)
20400b57cec5SDimitry Andric     {
20410b57cec5SDimitry Andric       if (!MI.getOperand(1).isImm() || !MI.getOperand(2).isImm())
20420b57cec5SDimitry Andric         return false;
20430b57cec5SDimitry Andric       uint64_t Hi = MI.getOperand(1).getImm();
20440b57cec5SDimitry Andric       uint64_t Lo = MI.getOperand(2).getImm();
20450b57cec5SDimitry Andric       uint64_t Res = (Hi << 32) | (Lo & 0xFFFFFFFF);
20460b57cec5SDimitry Andric       IntegerType *Ty = Type::getInt64Ty(CX);
20470b57cec5SDimitry Andric       const ConstantInt *CI = ConstantInt::get(Ty, Res, false);
20480b57cec5SDimitry Andric       LatticeCell RC = Outputs.get(DefR.Reg);
20490b57cec5SDimitry Andric       RC.add(CI);
20500b57cec5SDimitry Andric       Outputs.update(DefR.Reg, RC);
20510b57cec5SDimitry Andric       break;
20520b57cec5SDimitry Andric     }
20530b57cec5SDimitry Andric 
20540b57cec5SDimitry Andric     case Hexagon::S2_setbit_i:
20550b57cec5SDimitry Andric     {
20560b57cec5SDimitry Andric       int64_t B = MI.getOperand(2).getImm();
20570b57cec5SDimitry Andric       assert(B >=0 && B < 32);
20580b57cec5SDimitry Andric       APInt A(32, (1ull << B), false);
20590b57cec5SDimitry Andric       RegisterSubReg R(MI.getOperand(1));
20600b57cec5SDimitry Andric       LatticeCell RC = Outputs.get(DefR.Reg);
20610b57cec5SDimitry Andric       bool Eval = evaluateORri(R, A, Inputs, RC);
20620b57cec5SDimitry Andric       if (!Eval)
20630b57cec5SDimitry Andric         return false;
20640b57cec5SDimitry Andric       Outputs.update(DefR.Reg, RC);
20650b57cec5SDimitry Andric       break;
20660b57cec5SDimitry Andric     }
20670b57cec5SDimitry Andric 
20680b57cec5SDimitry Andric     case Hexagon::C2_mux:
20690b57cec5SDimitry Andric     case Hexagon::C2_muxir:
20700b57cec5SDimitry Andric     case Hexagon::C2_muxri:
20710b57cec5SDimitry Andric     case Hexagon::C2_muxii:
20720b57cec5SDimitry Andric     {
20730b57cec5SDimitry Andric       bool Eval = evaluateHexCondMove(MI, Inputs, Outputs);
20740b57cec5SDimitry Andric       if (!Eval)
20750b57cec5SDimitry Andric         return false;
20760b57cec5SDimitry Andric       break;
20770b57cec5SDimitry Andric     }
20780b57cec5SDimitry Andric 
20790b57cec5SDimitry Andric     case Hexagon::A2_sxtb:
20800b57cec5SDimitry Andric     case Hexagon::A2_sxth:
20810b57cec5SDimitry Andric     case Hexagon::A2_sxtw:
20820b57cec5SDimitry Andric     case Hexagon::A2_zxtb:
20830b57cec5SDimitry Andric     case Hexagon::A2_zxth:
20840b57cec5SDimitry Andric     {
20850b57cec5SDimitry Andric       bool Eval = evaluateHexExt(MI, Inputs, Outputs);
20860b57cec5SDimitry Andric       if (!Eval)
20870b57cec5SDimitry Andric         return false;
20880b57cec5SDimitry Andric       break;
20890b57cec5SDimitry Andric     }
20900b57cec5SDimitry Andric 
20910b57cec5SDimitry Andric     case Hexagon::S2_ct0:
20920b57cec5SDimitry Andric     case Hexagon::S2_ct0p:
20930b57cec5SDimitry Andric     case Hexagon::S2_ct1:
20940b57cec5SDimitry Andric     case Hexagon::S2_ct1p:
20950b57cec5SDimitry Andric     {
20960b57cec5SDimitry Andric       using namespace Hexagon;
20970b57cec5SDimitry Andric 
20980b57cec5SDimitry Andric       bool Ones = (Opc == S2_ct1) || (Opc == S2_ct1p);
20990b57cec5SDimitry Andric       RegisterSubReg R1(MI.getOperand(1));
21000b57cec5SDimitry Andric       assert(Inputs.has(R1.Reg));
21010b57cec5SDimitry Andric       LatticeCell T;
21020b57cec5SDimitry Andric       bool Eval = evaluateCTBr(R1, !Ones, Ones, Inputs, T);
21030b57cec5SDimitry Andric       if (!Eval)
21040b57cec5SDimitry Andric         return false;
21050b57cec5SDimitry Andric       // All of these instructions return a 32-bit value. The evaluate
21060b57cec5SDimitry Andric       // will generate the same type as the operand, so truncate the
21070b57cec5SDimitry Andric       // result if necessary.
21080b57cec5SDimitry Andric       APInt C;
21090b57cec5SDimitry Andric       LatticeCell RC = Outputs.get(DefR.Reg);
21100b57cec5SDimitry Andric       for (unsigned i = 0; i < T.size(); ++i) {
21110b57cec5SDimitry Andric         const Constant *CI = T.Values[i];
21120b57cec5SDimitry Andric         if (constToInt(CI, C) && C.getBitWidth() > 32)
21130b57cec5SDimitry Andric           CI = intToConst(C.trunc(32));
21140b57cec5SDimitry Andric         RC.add(CI);
21150b57cec5SDimitry Andric       }
21160b57cec5SDimitry Andric       Outputs.update(DefR.Reg, RC);
21170b57cec5SDimitry Andric       break;
21180b57cec5SDimitry Andric     }
21190b57cec5SDimitry Andric 
21200b57cec5SDimitry Andric     case Hexagon::S2_cl0:
21210b57cec5SDimitry Andric     case Hexagon::S2_cl0p:
21220b57cec5SDimitry Andric     case Hexagon::S2_cl1:
21230b57cec5SDimitry Andric     case Hexagon::S2_cl1p:
21240b57cec5SDimitry Andric     case Hexagon::S2_clb:
21250b57cec5SDimitry Andric     case Hexagon::S2_clbp:
21260b57cec5SDimitry Andric     {
21270b57cec5SDimitry Andric       using namespace Hexagon;
21280b57cec5SDimitry Andric 
21290b57cec5SDimitry Andric       bool OnlyZeros = (Opc == S2_cl0) || (Opc == S2_cl0p);
21300b57cec5SDimitry Andric       bool OnlyOnes =  (Opc == S2_cl1) || (Opc == S2_cl1p);
21310b57cec5SDimitry Andric       RegisterSubReg R1(MI.getOperand(1));
21320b57cec5SDimitry Andric       assert(Inputs.has(R1.Reg));
21330b57cec5SDimitry Andric       LatticeCell T;
21340b57cec5SDimitry Andric       bool Eval = evaluateCLBr(R1, !OnlyOnes, !OnlyZeros, Inputs, T);
21350b57cec5SDimitry Andric       if (!Eval)
21360b57cec5SDimitry Andric         return false;
21370b57cec5SDimitry Andric       // All of these instructions return a 32-bit value. The evaluate
21380b57cec5SDimitry Andric       // will generate the same type as the operand, so truncate the
21390b57cec5SDimitry Andric       // result if necessary.
21400b57cec5SDimitry Andric       APInt C;
21410b57cec5SDimitry Andric       LatticeCell RC = Outputs.get(DefR.Reg);
21420b57cec5SDimitry Andric       for (unsigned i = 0; i < T.size(); ++i) {
21430b57cec5SDimitry Andric         const Constant *CI = T.Values[i];
21440b57cec5SDimitry Andric         if (constToInt(CI, C) && C.getBitWidth() > 32)
21450b57cec5SDimitry Andric           CI = intToConst(C.trunc(32));
21460b57cec5SDimitry Andric         RC.add(CI);
21470b57cec5SDimitry Andric       }
21480b57cec5SDimitry Andric       Outputs.update(DefR.Reg, RC);
21490b57cec5SDimitry Andric       break;
21500b57cec5SDimitry Andric     }
21510b57cec5SDimitry Andric 
21520b57cec5SDimitry Andric     case Hexagon::S4_extract:
21530b57cec5SDimitry Andric     case Hexagon::S4_extractp:
21540b57cec5SDimitry Andric     case Hexagon::S2_extractu:
21550b57cec5SDimitry Andric     case Hexagon::S2_extractup:
21560b57cec5SDimitry Andric     {
21570b57cec5SDimitry Andric       bool Signed = (Opc == Hexagon::S4_extract) ||
21580b57cec5SDimitry Andric                     (Opc == Hexagon::S4_extractp);
21590b57cec5SDimitry Andric       RegisterSubReg R1(MI.getOperand(1));
21600b57cec5SDimitry Andric       unsigned BW = getRegBitWidth(R1.Reg);
21610b57cec5SDimitry Andric       unsigned Bits = MI.getOperand(2).getImm();
21620b57cec5SDimitry Andric       unsigned Offset = MI.getOperand(3).getImm();
21630b57cec5SDimitry Andric       LatticeCell RC = Outputs.get(DefR.Reg);
21640b57cec5SDimitry Andric       if (Offset >= BW) {
21650b57cec5SDimitry Andric         APInt Zero(BW, 0, false);
21660b57cec5SDimitry Andric         RC.add(intToConst(Zero));
21670b57cec5SDimitry Andric         break;
21680b57cec5SDimitry Andric       }
21690b57cec5SDimitry Andric       if (Offset+Bits > BW) {
21700b57cec5SDimitry Andric         // If the requested bitfield extends beyond the most significant bit,
21710b57cec5SDimitry Andric         // the extra bits are treated as 0s. To emulate this behavior, reduce
21720b57cec5SDimitry Andric         // the number of requested bits, and make the extract unsigned.
21730b57cec5SDimitry Andric         Bits = BW-Offset;
21740b57cec5SDimitry Andric         Signed = false;
21750b57cec5SDimitry Andric       }
21760b57cec5SDimitry Andric       bool Eval = evaluateEXTRACTr(R1, BW, Bits, Offset, Signed, Inputs, RC);
21770b57cec5SDimitry Andric       if (!Eval)
21780b57cec5SDimitry Andric         return false;
21790b57cec5SDimitry Andric       Outputs.update(DefR.Reg, RC);
21800b57cec5SDimitry Andric       break;
21810b57cec5SDimitry Andric     }
21820b57cec5SDimitry Andric 
21830b57cec5SDimitry Andric     case Hexagon::S2_vsplatrb:
21840b57cec5SDimitry Andric     case Hexagon::S2_vsplatrh:
21850b57cec5SDimitry Andric     // vabsh, vabsh:sat
21860b57cec5SDimitry Andric     // vabsw, vabsw:sat
21870b57cec5SDimitry Andric     // vconj:sat
21880b57cec5SDimitry Andric     // vrndwh, vrndwh:sat
21890b57cec5SDimitry Andric     // vsathb, vsathub, vsatwuh
21900b57cec5SDimitry Andric     // vsxtbh, vsxthw
21910b57cec5SDimitry Andric     // vtrunehb, vtrunohb
21920b57cec5SDimitry Andric     // vzxtbh, vzxthw
21930b57cec5SDimitry Andric     {
21940b57cec5SDimitry Andric       bool Eval = evaluateHexVector1(MI, Inputs, Outputs);
21950b57cec5SDimitry Andric       if (!Eval)
21960b57cec5SDimitry Andric         return false;
21970b57cec5SDimitry Andric       break;
21980b57cec5SDimitry Andric     }
21990b57cec5SDimitry Andric 
22000b57cec5SDimitry Andric     // TODO:
22010b57cec5SDimitry Andric     // A2_vaddh
22020b57cec5SDimitry Andric     // A2_vaddhs
22030b57cec5SDimitry Andric     // A2_vaddw
22040b57cec5SDimitry Andric     // A2_vaddws
22050b57cec5SDimitry Andric   }
22060b57cec5SDimitry Andric 
22070b57cec5SDimitry Andric   return true;
22080b57cec5SDimitry Andric }
22090b57cec5SDimitry Andric 
22100b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluate(const RegisterSubReg &R,
22110b57cec5SDimitry Andric       const LatticeCell &Input, LatticeCell &Result) {
22120b57cec5SDimitry Andric   if (!R.SubReg) {
22130b57cec5SDimitry Andric     Result = Input;
22140b57cec5SDimitry Andric     return true;
22150b57cec5SDimitry Andric   }
22160b57cec5SDimitry Andric   const TargetRegisterClass *RC = MRI->getRegClass(R.Reg);
22170b57cec5SDimitry Andric   if (RC != &Hexagon::DoubleRegsRegClass)
22180b57cec5SDimitry Andric     return false;
22190b57cec5SDimitry Andric   if (R.SubReg != Hexagon::isub_lo && R.SubReg != Hexagon::isub_hi)
22200b57cec5SDimitry Andric     return false;
22210b57cec5SDimitry Andric 
22220b57cec5SDimitry Andric   assert(!Input.isTop());
22230b57cec5SDimitry Andric   if (Input.isBottom())
22240b57cec5SDimitry Andric     return false;
22250b57cec5SDimitry Andric 
22260b57cec5SDimitry Andric   using P = ConstantProperties;
22270b57cec5SDimitry Andric 
22280b57cec5SDimitry Andric   if (Input.isProperty()) {
22290b57cec5SDimitry Andric     uint32_t Ps = Input.properties();
22300b57cec5SDimitry Andric     if (Ps & (P::Zero|P::NaN)) {
22310b57cec5SDimitry Andric       uint32_t Ns = (Ps & (P::Zero|P::NaN|P::SignProperties));
22320b57cec5SDimitry Andric       Result.add(Ns);
22330b57cec5SDimitry Andric       return true;
22340b57cec5SDimitry Andric     }
22350b57cec5SDimitry Andric     if (R.SubReg == Hexagon::isub_hi) {
22360b57cec5SDimitry Andric       uint32_t Ns = (Ps & P::SignProperties);
22370b57cec5SDimitry Andric       Result.add(Ns);
22380b57cec5SDimitry Andric       return true;
22390b57cec5SDimitry Andric     }
22400b57cec5SDimitry Andric     return false;
22410b57cec5SDimitry Andric   }
22420b57cec5SDimitry Andric 
22430b57cec5SDimitry Andric   // The Input cell contains some known values. Pick the word corresponding
22440b57cec5SDimitry Andric   // to the subregister.
22450b57cec5SDimitry Andric   APInt A;
22460b57cec5SDimitry Andric   for (unsigned i = 0; i < Input.size(); ++i) {
22470b57cec5SDimitry Andric     const Constant *C = Input.Values[i];
22480b57cec5SDimitry Andric     if (!constToInt(C, A))
22490b57cec5SDimitry Andric       return false;
22500b57cec5SDimitry Andric     if (!A.isIntN(64))
22510b57cec5SDimitry Andric       return false;
22520b57cec5SDimitry Andric     uint64_t U = A.getZExtValue();
22530b57cec5SDimitry Andric     if (R.SubReg == Hexagon::isub_hi)
22540b57cec5SDimitry Andric       U >>= 32;
22550b57cec5SDimitry Andric     U &= 0xFFFFFFFFULL;
22560b57cec5SDimitry Andric     uint32_t U32 = Lo_32(U);
22570b57cec5SDimitry Andric     int32_t V32;
22580b57cec5SDimitry Andric     memcpy(&V32, &U32, sizeof V32);
22590b57cec5SDimitry Andric     IntegerType *Ty = Type::getInt32Ty(CX);
22600b57cec5SDimitry Andric     const ConstantInt *C32 = ConstantInt::get(Ty, static_cast<int64_t>(V32));
22610b57cec5SDimitry Andric     Result.add(C32);
22620b57cec5SDimitry Andric   }
22630b57cec5SDimitry Andric   return true;
22640b57cec5SDimitry Andric }
22650b57cec5SDimitry Andric 
22660b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluate(const MachineInstr &BrI,
22670b57cec5SDimitry Andric       const CellMap &Inputs, SetVector<const MachineBasicBlock*> &Targets,
22680b57cec5SDimitry Andric       bool &FallsThru) {
22690b57cec5SDimitry Andric   // We need to evaluate one branch at a time. TII::analyzeBranch checks
22700b57cec5SDimitry Andric   // all the branches in a basic block at once, so we cannot use it.
22710b57cec5SDimitry Andric   unsigned Opc = BrI.getOpcode();
22720b57cec5SDimitry Andric   bool SimpleBranch = false;
22730b57cec5SDimitry Andric   bool Negated = false;
22740b57cec5SDimitry Andric   switch (Opc) {
22750b57cec5SDimitry Andric     case Hexagon::J2_jumpf:
22760b57cec5SDimitry Andric     case Hexagon::J2_jumpfnew:
22770b57cec5SDimitry Andric     case Hexagon::J2_jumpfnewpt:
22780b57cec5SDimitry Andric       Negated = true;
22790b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
22800b57cec5SDimitry Andric     case Hexagon::J2_jumpt:
22810b57cec5SDimitry Andric     case Hexagon::J2_jumptnew:
22820b57cec5SDimitry Andric     case Hexagon::J2_jumptnewpt:
22830b57cec5SDimitry Andric       // Simple branch:  if([!]Pn) jump ...
22840b57cec5SDimitry Andric       // i.e. Op0 = predicate, Op1 = branch target.
22850b57cec5SDimitry Andric       SimpleBranch = true;
22860b57cec5SDimitry Andric       break;
22870b57cec5SDimitry Andric     case Hexagon::J2_jump:
22880b57cec5SDimitry Andric       Targets.insert(BrI.getOperand(0).getMBB());
22890b57cec5SDimitry Andric       FallsThru = false;
22900b57cec5SDimitry Andric       return true;
22910b57cec5SDimitry Andric     default:
22920b57cec5SDimitry Andric Undetermined:
22930b57cec5SDimitry Andric       // If the branch is of unknown type, assume that all successors are
22940b57cec5SDimitry Andric       // executable.
22950b57cec5SDimitry Andric       FallsThru = !BrI.isUnconditionalBranch();
22960b57cec5SDimitry Andric       return false;
22970b57cec5SDimitry Andric   }
22980b57cec5SDimitry Andric 
22990b57cec5SDimitry Andric   if (SimpleBranch) {
23000b57cec5SDimitry Andric     const MachineOperand &MD = BrI.getOperand(0);
23010b57cec5SDimitry Andric     RegisterSubReg PR(MD);
23020b57cec5SDimitry Andric     // If the condition operand has a subregister, this is not something
23030b57cec5SDimitry Andric     // we currently recognize.
23040b57cec5SDimitry Andric     if (PR.SubReg)
23050b57cec5SDimitry Andric       goto Undetermined;
23060b57cec5SDimitry Andric     assert(Inputs.has(PR.Reg));
23070b57cec5SDimitry Andric     const LatticeCell &PredC = Inputs.get(PR.Reg);
23080b57cec5SDimitry Andric     if (PredC.isBottom())
23090b57cec5SDimitry Andric       goto Undetermined;
23100b57cec5SDimitry Andric 
23110b57cec5SDimitry Andric     uint32_t Props = PredC.properties();
23120b57cec5SDimitry Andric     bool CTrue = false, CFalse = false;
23130b57cec5SDimitry Andric     if (Props & ConstantProperties::Zero)
23140b57cec5SDimitry Andric       CFalse = true;
23150b57cec5SDimitry Andric     else if (Props & ConstantProperties::NonZero)
23160b57cec5SDimitry Andric       CTrue = true;
23170b57cec5SDimitry Andric     // If the condition is not known to be either, bail out.
23180b57cec5SDimitry Andric     if (!CTrue && !CFalse)
23190b57cec5SDimitry Andric       goto Undetermined;
23200b57cec5SDimitry Andric 
23210b57cec5SDimitry Andric     const MachineBasicBlock *BranchTarget = BrI.getOperand(1).getMBB();
23220b57cec5SDimitry Andric 
23230b57cec5SDimitry Andric     FallsThru = false;
23240b57cec5SDimitry Andric     if ((!Negated && CTrue) || (Negated && CFalse))
23250b57cec5SDimitry Andric       Targets.insert(BranchTarget);
23260b57cec5SDimitry Andric     else if ((!Negated && CFalse) || (Negated && CTrue))
23270b57cec5SDimitry Andric       FallsThru = true;
23280b57cec5SDimitry Andric     else
23290b57cec5SDimitry Andric       goto Undetermined;
23300b57cec5SDimitry Andric   }
23310b57cec5SDimitry Andric 
23320b57cec5SDimitry Andric   return true;
23330b57cec5SDimitry Andric }
23340b57cec5SDimitry Andric 
23350b57cec5SDimitry Andric bool HexagonConstEvaluator::rewrite(MachineInstr &MI, const CellMap &Inputs) {
23360b57cec5SDimitry Andric   if (MI.isBranch())
23370b57cec5SDimitry Andric     return rewriteHexBranch(MI, Inputs);
23380b57cec5SDimitry Andric 
23390b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
23400b57cec5SDimitry Andric   switch (Opc) {
23410b57cec5SDimitry Andric     default:
23420b57cec5SDimitry Andric       break;
23430b57cec5SDimitry Andric     case Hexagon::A2_tfrsi:
23440b57cec5SDimitry Andric     case Hexagon::A2_tfrpi:
23450b57cec5SDimitry Andric     case Hexagon::CONST32:
23460b57cec5SDimitry Andric     case Hexagon::CONST64:
23470b57cec5SDimitry Andric     case Hexagon::PS_true:
23480b57cec5SDimitry Andric     case Hexagon::PS_false:
23490b57cec5SDimitry Andric       return false;
23500b57cec5SDimitry Andric   }
23510b57cec5SDimitry Andric 
23520b57cec5SDimitry Andric   unsigned NumOp = MI.getNumOperands();
23530b57cec5SDimitry Andric   if (NumOp == 0)
23540b57cec5SDimitry Andric     return false;
23550b57cec5SDimitry Andric 
23560b57cec5SDimitry Andric   bool AllDefs, Changed;
23570b57cec5SDimitry Andric   Changed = rewriteHexConstDefs(MI, Inputs, AllDefs);
23580b57cec5SDimitry Andric   // If not all defs have been rewritten (i.e. the instruction defines
23590b57cec5SDimitry Andric   // a register that is not compile-time constant), then try to rewrite
23600b57cec5SDimitry Andric   // register operands that are known to be constant with immediates.
23610b57cec5SDimitry Andric   if (!AllDefs)
23620b57cec5SDimitry Andric     Changed |= rewriteHexConstUses(MI, Inputs);
23630b57cec5SDimitry Andric 
23640b57cec5SDimitry Andric   return Changed;
23650b57cec5SDimitry Andric }
23660b57cec5SDimitry Andric 
23670b57cec5SDimitry Andric unsigned HexagonConstEvaluator::getRegBitWidth(unsigned Reg) const {
23680b57cec5SDimitry Andric   const TargetRegisterClass *RC = MRI->getRegClass(Reg);
23690b57cec5SDimitry Andric   if (Hexagon::IntRegsRegClass.hasSubClassEq(RC))
23700b57cec5SDimitry Andric     return 32;
23710b57cec5SDimitry Andric   if (Hexagon::DoubleRegsRegClass.hasSubClassEq(RC))
23720b57cec5SDimitry Andric     return 64;
23730b57cec5SDimitry Andric   if (Hexagon::PredRegsRegClass.hasSubClassEq(RC))
23740b57cec5SDimitry Andric     return 8;
23750b57cec5SDimitry Andric   llvm_unreachable("Invalid register");
23760b57cec5SDimitry Andric   return 0;
23770b57cec5SDimitry Andric }
23780b57cec5SDimitry Andric 
23790b57cec5SDimitry Andric uint32_t HexagonConstEvaluator::getCmp(unsigned Opc) {
23800b57cec5SDimitry Andric   switch (Opc) {
23810b57cec5SDimitry Andric     case Hexagon::C2_cmpeq:
23820b57cec5SDimitry Andric     case Hexagon::C2_cmpeqp:
23830b57cec5SDimitry Andric     case Hexagon::A4_cmpbeq:
23840b57cec5SDimitry Andric     case Hexagon::A4_cmpheq:
23850b57cec5SDimitry Andric     case Hexagon::A4_cmpbeqi:
23860b57cec5SDimitry Andric     case Hexagon::A4_cmpheqi:
23870b57cec5SDimitry Andric     case Hexagon::C2_cmpeqi:
23880b57cec5SDimitry Andric     case Hexagon::J4_cmpeqn1_t_jumpnv_nt:
23890b57cec5SDimitry Andric     case Hexagon::J4_cmpeqn1_t_jumpnv_t:
23900b57cec5SDimitry Andric     case Hexagon::J4_cmpeqi_t_jumpnv_nt:
23910b57cec5SDimitry Andric     case Hexagon::J4_cmpeqi_t_jumpnv_t:
23920b57cec5SDimitry Andric     case Hexagon::J4_cmpeq_t_jumpnv_nt:
23930b57cec5SDimitry Andric     case Hexagon::J4_cmpeq_t_jumpnv_t:
23940b57cec5SDimitry Andric       return Comparison::EQ;
23950b57cec5SDimitry Andric 
23960b57cec5SDimitry Andric     case Hexagon::C4_cmpneq:
23970b57cec5SDimitry Andric     case Hexagon::C4_cmpneqi:
23980b57cec5SDimitry Andric     case Hexagon::J4_cmpeqn1_f_jumpnv_nt:
23990b57cec5SDimitry Andric     case Hexagon::J4_cmpeqn1_f_jumpnv_t:
24000b57cec5SDimitry Andric     case Hexagon::J4_cmpeqi_f_jumpnv_nt:
24010b57cec5SDimitry Andric     case Hexagon::J4_cmpeqi_f_jumpnv_t:
24020b57cec5SDimitry Andric     case Hexagon::J4_cmpeq_f_jumpnv_nt:
24030b57cec5SDimitry Andric     case Hexagon::J4_cmpeq_f_jumpnv_t:
24040b57cec5SDimitry Andric       return Comparison::NE;
24050b57cec5SDimitry Andric 
24060b57cec5SDimitry Andric     case Hexagon::C2_cmpgt:
24070b57cec5SDimitry Andric     case Hexagon::C2_cmpgtp:
24080b57cec5SDimitry Andric     case Hexagon::A4_cmpbgt:
24090b57cec5SDimitry Andric     case Hexagon::A4_cmphgt:
24100b57cec5SDimitry Andric     case Hexagon::A4_cmpbgti:
24110b57cec5SDimitry Andric     case Hexagon::A4_cmphgti:
24120b57cec5SDimitry Andric     case Hexagon::C2_cmpgti:
24130b57cec5SDimitry Andric     case Hexagon::J4_cmpgtn1_t_jumpnv_nt:
24140b57cec5SDimitry Andric     case Hexagon::J4_cmpgtn1_t_jumpnv_t:
24150b57cec5SDimitry Andric     case Hexagon::J4_cmpgti_t_jumpnv_nt:
24160b57cec5SDimitry Andric     case Hexagon::J4_cmpgti_t_jumpnv_t:
24170b57cec5SDimitry Andric     case Hexagon::J4_cmpgt_t_jumpnv_nt:
24180b57cec5SDimitry Andric     case Hexagon::J4_cmpgt_t_jumpnv_t:
24190b57cec5SDimitry Andric       return Comparison::GTs;
24200b57cec5SDimitry Andric 
24210b57cec5SDimitry Andric     case Hexagon::C4_cmplte:
24220b57cec5SDimitry Andric     case Hexagon::C4_cmpltei:
24230b57cec5SDimitry Andric     case Hexagon::J4_cmpgtn1_f_jumpnv_nt:
24240b57cec5SDimitry Andric     case Hexagon::J4_cmpgtn1_f_jumpnv_t:
24250b57cec5SDimitry Andric     case Hexagon::J4_cmpgti_f_jumpnv_nt:
24260b57cec5SDimitry Andric     case Hexagon::J4_cmpgti_f_jumpnv_t:
24270b57cec5SDimitry Andric     case Hexagon::J4_cmpgt_f_jumpnv_nt:
24280b57cec5SDimitry Andric     case Hexagon::J4_cmpgt_f_jumpnv_t:
24290b57cec5SDimitry Andric       return Comparison::LEs;
24300b57cec5SDimitry Andric 
24310b57cec5SDimitry Andric     case Hexagon::C2_cmpgtu:
24320b57cec5SDimitry Andric     case Hexagon::C2_cmpgtup:
24330b57cec5SDimitry Andric     case Hexagon::A4_cmpbgtu:
24340b57cec5SDimitry Andric     case Hexagon::A4_cmpbgtui:
24350b57cec5SDimitry Andric     case Hexagon::A4_cmphgtu:
24360b57cec5SDimitry Andric     case Hexagon::A4_cmphgtui:
24370b57cec5SDimitry Andric     case Hexagon::C2_cmpgtui:
24380b57cec5SDimitry Andric     case Hexagon::J4_cmpgtui_t_jumpnv_nt:
24390b57cec5SDimitry Andric     case Hexagon::J4_cmpgtui_t_jumpnv_t:
24400b57cec5SDimitry Andric     case Hexagon::J4_cmpgtu_t_jumpnv_nt:
24410b57cec5SDimitry Andric     case Hexagon::J4_cmpgtu_t_jumpnv_t:
24420b57cec5SDimitry Andric       return Comparison::GTu;
24430b57cec5SDimitry Andric 
24440b57cec5SDimitry Andric     case Hexagon::J4_cmpltu_f_jumpnv_nt:
24450b57cec5SDimitry Andric     case Hexagon::J4_cmpltu_f_jumpnv_t:
24460b57cec5SDimitry Andric       return Comparison::GEu;
24470b57cec5SDimitry Andric 
24480b57cec5SDimitry Andric     case Hexagon::J4_cmpltu_t_jumpnv_nt:
24490b57cec5SDimitry Andric     case Hexagon::J4_cmpltu_t_jumpnv_t:
24500b57cec5SDimitry Andric       return Comparison::LTu;
24510b57cec5SDimitry Andric 
24520b57cec5SDimitry Andric     case Hexagon::J4_cmplt_f_jumpnv_nt:
24530b57cec5SDimitry Andric     case Hexagon::J4_cmplt_f_jumpnv_t:
24540b57cec5SDimitry Andric       return Comparison::GEs;
24550b57cec5SDimitry Andric 
24560b57cec5SDimitry Andric     case Hexagon::C4_cmplteu:
24570b57cec5SDimitry Andric     case Hexagon::C4_cmplteui:
24580b57cec5SDimitry Andric     case Hexagon::J4_cmpgtui_f_jumpnv_nt:
24590b57cec5SDimitry Andric     case Hexagon::J4_cmpgtui_f_jumpnv_t:
24600b57cec5SDimitry Andric     case Hexagon::J4_cmpgtu_f_jumpnv_nt:
24610b57cec5SDimitry Andric     case Hexagon::J4_cmpgtu_f_jumpnv_t:
24620b57cec5SDimitry Andric       return Comparison::LEu;
24630b57cec5SDimitry Andric 
24640b57cec5SDimitry Andric     case Hexagon::J4_cmplt_t_jumpnv_nt:
24650b57cec5SDimitry Andric     case Hexagon::J4_cmplt_t_jumpnv_t:
24660b57cec5SDimitry Andric       return Comparison::LTs;
24670b57cec5SDimitry Andric 
24680b57cec5SDimitry Andric     default:
24690b57cec5SDimitry Andric       break;
24700b57cec5SDimitry Andric   }
24710b57cec5SDimitry Andric   return Comparison::Unk;
24720b57cec5SDimitry Andric }
24730b57cec5SDimitry Andric 
24740b57cec5SDimitry Andric APInt HexagonConstEvaluator::getCmpImm(unsigned Opc, unsigned OpX,
24750b57cec5SDimitry Andric       const MachineOperand &MO) {
24760b57cec5SDimitry Andric   bool Signed = false;
24770b57cec5SDimitry Andric   switch (Opc) {
24780b57cec5SDimitry Andric     case Hexagon::A4_cmpbgtui:   // u7
24790b57cec5SDimitry Andric     case Hexagon::A4_cmphgtui:   // u7
24800b57cec5SDimitry Andric       break;
24810b57cec5SDimitry Andric     case Hexagon::A4_cmpheqi:    // s8
24820b57cec5SDimitry Andric     case Hexagon::C4_cmpneqi:   // s8
24830b57cec5SDimitry Andric       Signed = true;
24840b57cec5SDimitry Andric       break;
24850b57cec5SDimitry Andric     case Hexagon::A4_cmpbeqi:    // u8
24860b57cec5SDimitry Andric       break;
24870b57cec5SDimitry Andric     case Hexagon::C2_cmpgtui:      // u9
24880b57cec5SDimitry Andric     case Hexagon::C4_cmplteui:  // u9
24890b57cec5SDimitry Andric       break;
24900b57cec5SDimitry Andric     case Hexagon::C2_cmpeqi:       // s10
24910b57cec5SDimitry Andric     case Hexagon::C2_cmpgti:       // s10
24920b57cec5SDimitry Andric     case Hexagon::C4_cmpltei:   // s10
24930b57cec5SDimitry Andric       Signed = true;
24940b57cec5SDimitry Andric       break;
24950b57cec5SDimitry Andric     case Hexagon::J4_cmpeqi_f_jumpnv_nt:   // u5
24960b57cec5SDimitry Andric     case Hexagon::J4_cmpeqi_f_jumpnv_t:    // u5
24970b57cec5SDimitry Andric     case Hexagon::J4_cmpeqi_t_jumpnv_nt:   // u5
24980b57cec5SDimitry Andric     case Hexagon::J4_cmpeqi_t_jumpnv_t:    // u5
24990b57cec5SDimitry Andric     case Hexagon::J4_cmpgti_f_jumpnv_nt:   // u5
25000b57cec5SDimitry Andric     case Hexagon::J4_cmpgti_f_jumpnv_t:    // u5
25010b57cec5SDimitry Andric     case Hexagon::J4_cmpgti_t_jumpnv_nt:   // u5
25020b57cec5SDimitry Andric     case Hexagon::J4_cmpgti_t_jumpnv_t:    // u5
25030b57cec5SDimitry Andric     case Hexagon::J4_cmpgtui_f_jumpnv_nt:  // u5
25040b57cec5SDimitry Andric     case Hexagon::J4_cmpgtui_f_jumpnv_t:   // u5
25050b57cec5SDimitry Andric     case Hexagon::J4_cmpgtui_t_jumpnv_nt:  // u5
25060b57cec5SDimitry Andric     case Hexagon::J4_cmpgtui_t_jumpnv_t:   // u5
25070b57cec5SDimitry Andric       break;
25080b57cec5SDimitry Andric     default:
25090b57cec5SDimitry Andric       llvm_unreachable("Unhandled instruction");
25100b57cec5SDimitry Andric       break;
25110b57cec5SDimitry Andric   }
25120b57cec5SDimitry Andric 
25130b57cec5SDimitry Andric   uint64_t Val = MO.getImm();
25140b57cec5SDimitry Andric   return APInt(32, Val, Signed);
25150b57cec5SDimitry Andric }
25160b57cec5SDimitry Andric 
25170b57cec5SDimitry Andric void HexagonConstEvaluator::replaceWithNop(MachineInstr &MI) {
25180b57cec5SDimitry Andric   MI.setDesc(HII.get(Hexagon::A2_nop));
25190b57cec5SDimitry Andric   while (MI.getNumOperands() > 0)
25200b57cec5SDimitry Andric     MI.RemoveOperand(0);
25210b57cec5SDimitry Andric }
25220b57cec5SDimitry Andric 
25230b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexRSEQ32(RegisterSubReg RL, RegisterSubReg RH,
25240b57cec5SDimitry Andric       const CellMap &Inputs, LatticeCell &Result) {
25250b57cec5SDimitry Andric   assert(Inputs.has(RL.Reg) && Inputs.has(RH.Reg));
25260b57cec5SDimitry Andric   LatticeCell LSL, LSH;
25270b57cec5SDimitry Andric   if (!getCell(RL, Inputs, LSL) || !getCell(RH, Inputs, LSH))
25280b57cec5SDimitry Andric     return false;
25290b57cec5SDimitry Andric   if (LSL.isProperty() || LSH.isProperty())
25300b57cec5SDimitry Andric     return false;
25310b57cec5SDimitry Andric 
25320b57cec5SDimitry Andric   unsigned LN = LSL.size(), HN = LSH.size();
25330b57cec5SDimitry Andric   SmallVector<APInt,4> LoVs(LN), HiVs(HN);
25340b57cec5SDimitry Andric   for (unsigned i = 0; i < LN; ++i) {
25350b57cec5SDimitry Andric     bool Eval = constToInt(LSL.Values[i], LoVs[i]);
25360b57cec5SDimitry Andric     if (!Eval)
25370b57cec5SDimitry Andric       return false;
25380b57cec5SDimitry Andric     assert(LoVs[i].getBitWidth() == 32);
25390b57cec5SDimitry Andric   }
25400b57cec5SDimitry Andric   for (unsigned i = 0; i < HN; ++i) {
25410b57cec5SDimitry Andric     bool Eval = constToInt(LSH.Values[i], HiVs[i]);
25420b57cec5SDimitry Andric     if (!Eval)
25430b57cec5SDimitry Andric       return false;
25440b57cec5SDimitry Andric     assert(HiVs[i].getBitWidth() == 32);
25450b57cec5SDimitry Andric   }
25460b57cec5SDimitry Andric 
25470b57cec5SDimitry Andric   for (unsigned i = 0; i < HiVs.size(); ++i) {
25480b57cec5SDimitry Andric     APInt HV = HiVs[i].zextOrSelf(64) << 32;
25490b57cec5SDimitry Andric     for (unsigned j = 0; j < LoVs.size(); ++j) {
25500b57cec5SDimitry Andric       APInt LV = LoVs[j].zextOrSelf(64);
25510b57cec5SDimitry Andric       const Constant *C = intToConst(HV | LV);
25520b57cec5SDimitry Andric       Result.add(C);
25530b57cec5SDimitry Andric       if (Result.isBottom())
25540b57cec5SDimitry Andric         return false;
25550b57cec5SDimitry Andric     }
25560b57cec5SDimitry Andric   }
25570b57cec5SDimitry Andric   return !Result.isBottom();
25580b57cec5SDimitry Andric }
25590b57cec5SDimitry Andric 
25600b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexCompare(const MachineInstr &MI,
25610b57cec5SDimitry Andric       const CellMap &Inputs, CellMap &Outputs) {
25620b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
25630b57cec5SDimitry Andric   bool Classic = false;
25640b57cec5SDimitry Andric   switch (Opc) {
25650b57cec5SDimitry Andric     case Hexagon::C2_cmpeq:
25660b57cec5SDimitry Andric     case Hexagon::C2_cmpeqp:
25670b57cec5SDimitry Andric     case Hexagon::C2_cmpgt:
25680b57cec5SDimitry Andric     case Hexagon::C2_cmpgtp:
25690b57cec5SDimitry Andric     case Hexagon::C2_cmpgtu:
25700b57cec5SDimitry Andric     case Hexagon::C2_cmpgtup:
25710b57cec5SDimitry Andric     case Hexagon::C2_cmpeqi:
25720b57cec5SDimitry Andric     case Hexagon::C2_cmpgti:
25730b57cec5SDimitry Andric     case Hexagon::C2_cmpgtui:
25740b57cec5SDimitry Andric       // Classic compare:  Dst0 = CMP Src1, Src2
25750b57cec5SDimitry Andric       Classic = true;
25760b57cec5SDimitry Andric       break;
25770b57cec5SDimitry Andric     default:
25780b57cec5SDimitry Andric       // Not handling other compare instructions now.
25790b57cec5SDimitry Andric       return false;
25800b57cec5SDimitry Andric   }
25810b57cec5SDimitry Andric 
25820b57cec5SDimitry Andric   if (Classic) {
25830b57cec5SDimitry Andric     const MachineOperand &Src1 = MI.getOperand(1);
25840b57cec5SDimitry Andric     const MachineOperand &Src2 = MI.getOperand(2);
25850b57cec5SDimitry Andric 
25860b57cec5SDimitry Andric     bool Result;
25870b57cec5SDimitry Andric     unsigned Opc = MI.getOpcode();
25880b57cec5SDimitry Andric     bool Computed = evaluateHexCompare2(Opc, Src1, Src2, Inputs, Result);
25890b57cec5SDimitry Andric     if (Computed) {
25900b57cec5SDimitry Andric       // Only create a zero/non-zero cell. At this time there isn't really
25910b57cec5SDimitry Andric       // much need for specific values.
25920b57cec5SDimitry Andric       RegisterSubReg DefR(MI.getOperand(0));
25930b57cec5SDimitry Andric       LatticeCell L = Outputs.get(DefR.Reg);
25940b57cec5SDimitry Andric       uint32_t P = Result ? ConstantProperties::NonZero
25950b57cec5SDimitry Andric                           : ConstantProperties::Zero;
25960b57cec5SDimitry Andric       L.add(P);
25970b57cec5SDimitry Andric       Outputs.update(DefR.Reg, L);
25980b57cec5SDimitry Andric       return true;
25990b57cec5SDimitry Andric     }
26000b57cec5SDimitry Andric   }
26010b57cec5SDimitry Andric 
26020b57cec5SDimitry Andric   return false;
26030b57cec5SDimitry Andric }
26040b57cec5SDimitry Andric 
26050b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexCompare2(unsigned Opc,
26060b57cec5SDimitry Andric       const MachineOperand &Src1, const MachineOperand &Src2,
26070b57cec5SDimitry Andric       const CellMap &Inputs, bool &Result) {
26080b57cec5SDimitry Andric   uint32_t Cmp = getCmp(Opc);
26090b57cec5SDimitry Andric   bool Reg1 = Src1.isReg(), Reg2 = Src2.isReg();
26100b57cec5SDimitry Andric   bool Imm1 = Src1.isImm(), Imm2 = Src2.isImm();
26110b57cec5SDimitry Andric   if (Reg1) {
26120b57cec5SDimitry Andric     RegisterSubReg R1(Src1);
26130b57cec5SDimitry Andric     if (Reg2) {
26140b57cec5SDimitry Andric       RegisterSubReg R2(Src2);
26150b57cec5SDimitry Andric       return evaluateCMPrr(Cmp, R1, R2, Inputs, Result);
26160b57cec5SDimitry Andric     } else if (Imm2) {
26170b57cec5SDimitry Andric       APInt A2 = getCmpImm(Opc, 2, Src2);
26180b57cec5SDimitry Andric       return evaluateCMPri(Cmp, R1, A2, Inputs, Result);
26190b57cec5SDimitry Andric     }
26200b57cec5SDimitry Andric   } else if (Imm1) {
26210b57cec5SDimitry Andric     APInt A1 = getCmpImm(Opc, 1, Src1);
26220b57cec5SDimitry Andric     if (Reg2) {
26230b57cec5SDimitry Andric       RegisterSubReg R2(Src2);
26240b57cec5SDimitry Andric       uint32_t NegCmp = Comparison::negate(Cmp);
26250b57cec5SDimitry Andric       return evaluateCMPri(NegCmp, R2, A1, Inputs, Result);
26260b57cec5SDimitry Andric     } else if (Imm2) {
26270b57cec5SDimitry Andric       APInt A2 = getCmpImm(Opc, 2, Src2);
26280b57cec5SDimitry Andric       return evaluateCMPii(Cmp, A1, A2, Result);
26290b57cec5SDimitry Andric     }
26300b57cec5SDimitry Andric   }
26310b57cec5SDimitry Andric   // Unknown kind of comparison.
26320b57cec5SDimitry Andric   return false;
26330b57cec5SDimitry Andric }
26340b57cec5SDimitry Andric 
26350b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexLogical(const MachineInstr &MI,
26360b57cec5SDimitry Andric       const CellMap &Inputs, CellMap &Outputs) {
26370b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
26380b57cec5SDimitry Andric   if (MI.getNumOperands() != 3)
26390b57cec5SDimitry Andric     return false;
26400b57cec5SDimitry Andric   const MachineOperand &Src1 = MI.getOperand(1);
26410b57cec5SDimitry Andric   const MachineOperand &Src2 = MI.getOperand(2);
26420b57cec5SDimitry Andric   RegisterSubReg R1(Src1);
26430b57cec5SDimitry Andric   bool Eval = false;
26440b57cec5SDimitry Andric   LatticeCell RC;
26450b57cec5SDimitry Andric   switch (Opc) {
26460b57cec5SDimitry Andric     default:
26470b57cec5SDimitry Andric       return false;
26480b57cec5SDimitry Andric     case Hexagon::A2_and:
26490b57cec5SDimitry Andric     case Hexagon::A2_andp:
26500b57cec5SDimitry Andric       Eval = evaluateANDrr(R1, RegisterSubReg(Src2), Inputs, RC);
26510b57cec5SDimitry Andric       break;
26520b57cec5SDimitry Andric     case Hexagon::A2_andir: {
26530b57cec5SDimitry Andric       if (!Src2.isImm())
26540b57cec5SDimitry Andric         return false;
26550b57cec5SDimitry Andric       APInt A(32, Src2.getImm(), true);
26560b57cec5SDimitry Andric       Eval = evaluateANDri(R1, A, Inputs, RC);
26570b57cec5SDimitry Andric       break;
26580b57cec5SDimitry Andric     }
26590b57cec5SDimitry Andric     case Hexagon::A2_or:
26600b57cec5SDimitry Andric     case Hexagon::A2_orp:
26610b57cec5SDimitry Andric       Eval = evaluateORrr(R1, RegisterSubReg(Src2), Inputs, RC);
26620b57cec5SDimitry Andric       break;
26630b57cec5SDimitry Andric     case Hexagon::A2_orir: {
26640b57cec5SDimitry Andric       if (!Src2.isImm())
26650b57cec5SDimitry Andric         return false;
26660b57cec5SDimitry Andric       APInt A(32, Src2.getImm(), true);
26670b57cec5SDimitry Andric       Eval = evaluateORri(R1, A, Inputs, RC);
26680b57cec5SDimitry Andric       break;
26690b57cec5SDimitry Andric     }
26700b57cec5SDimitry Andric     case Hexagon::A2_xor:
26710b57cec5SDimitry Andric     case Hexagon::A2_xorp:
26720b57cec5SDimitry Andric       Eval = evaluateXORrr(R1, RegisterSubReg(Src2), Inputs, RC);
26730b57cec5SDimitry Andric       break;
26740b57cec5SDimitry Andric   }
26750b57cec5SDimitry Andric   if (Eval) {
26760b57cec5SDimitry Andric     RegisterSubReg DefR(MI.getOperand(0));
26770b57cec5SDimitry Andric     Outputs.update(DefR.Reg, RC);
26780b57cec5SDimitry Andric   }
26790b57cec5SDimitry Andric   return Eval;
26800b57cec5SDimitry Andric }
26810b57cec5SDimitry Andric 
26820b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexCondMove(const MachineInstr &MI,
26830b57cec5SDimitry Andric       const CellMap &Inputs, CellMap &Outputs) {
26840b57cec5SDimitry Andric   // Dst0 = Cond1 ? Src2 : Src3
26850b57cec5SDimitry Andric   RegisterSubReg CR(MI.getOperand(1));
26860b57cec5SDimitry Andric   assert(Inputs.has(CR.Reg));
26870b57cec5SDimitry Andric   LatticeCell LS;
26880b57cec5SDimitry Andric   if (!getCell(CR, Inputs, LS))
26890b57cec5SDimitry Andric     return false;
26900b57cec5SDimitry Andric   uint32_t Ps = LS.properties();
26910b57cec5SDimitry Andric   unsigned TakeOp;
26920b57cec5SDimitry Andric   if (Ps & ConstantProperties::Zero)
26930b57cec5SDimitry Andric     TakeOp = 3;
26940b57cec5SDimitry Andric   else if (Ps & ConstantProperties::NonZero)
26950b57cec5SDimitry Andric     TakeOp = 2;
26960b57cec5SDimitry Andric   else
26970b57cec5SDimitry Andric     return false;
26980b57cec5SDimitry Andric 
26990b57cec5SDimitry Andric   const MachineOperand &ValOp = MI.getOperand(TakeOp);
27000b57cec5SDimitry Andric   RegisterSubReg DefR(MI.getOperand(0));
27010b57cec5SDimitry Andric   LatticeCell RC = Outputs.get(DefR.Reg);
27020b57cec5SDimitry Andric 
27030b57cec5SDimitry Andric   if (ValOp.isImm()) {
27040b57cec5SDimitry Andric     int64_t V = ValOp.getImm();
27050b57cec5SDimitry Andric     unsigned W = getRegBitWidth(DefR.Reg);
27060b57cec5SDimitry Andric     APInt A(W, V, true);
27070b57cec5SDimitry Andric     const Constant *C = intToConst(A);
27080b57cec5SDimitry Andric     RC.add(C);
27090b57cec5SDimitry Andric     Outputs.update(DefR.Reg, RC);
27100b57cec5SDimitry Andric     return true;
27110b57cec5SDimitry Andric   }
27120b57cec5SDimitry Andric   if (ValOp.isReg()) {
27130b57cec5SDimitry Andric     RegisterSubReg R(ValOp);
27140b57cec5SDimitry Andric     const LatticeCell &LR = Inputs.get(R.Reg);
27150b57cec5SDimitry Andric     LatticeCell LSR;
27160b57cec5SDimitry Andric     if (!evaluate(R, LR, LSR))
27170b57cec5SDimitry Andric       return false;
27180b57cec5SDimitry Andric     RC.meet(LSR);
27190b57cec5SDimitry Andric     Outputs.update(DefR.Reg, RC);
27200b57cec5SDimitry Andric     return true;
27210b57cec5SDimitry Andric   }
27220b57cec5SDimitry Andric   return false;
27230b57cec5SDimitry Andric }
27240b57cec5SDimitry Andric 
27250b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexExt(const MachineInstr &MI,
27260b57cec5SDimitry Andric       const CellMap &Inputs, CellMap &Outputs) {
27270b57cec5SDimitry Andric   // Dst0 = ext R1
27280b57cec5SDimitry Andric   RegisterSubReg R1(MI.getOperand(1));
27290b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
27300b57cec5SDimitry Andric 
27310b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
27320b57cec5SDimitry Andric   unsigned Bits;
27330b57cec5SDimitry Andric   switch (Opc) {
27340b57cec5SDimitry Andric     case Hexagon::A2_sxtb:
27350b57cec5SDimitry Andric     case Hexagon::A2_zxtb:
27360b57cec5SDimitry Andric       Bits = 8;
27370b57cec5SDimitry Andric       break;
27380b57cec5SDimitry Andric     case Hexagon::A2_sxth:
27390b57cec5SDimitry Andric     case Hexagon::A2_zxth:
27400b57cec5SDimitry Andric       Bits = 16;
27410b57cec5SDimitry Andric       break;
27420b57cec5SDimitry Andric     case Hexagon::A2_sxtw:
27430b57cec5SDimitry Andric       Bits = 32;
27440b57cec5SDimitry Andric       break;
27450b57cec5SDimitry Andric     default:
27460b57cec5SDimitry Andric       llvm_unreachable("Unhandled extension opcode");
27470b57cec5SDimitry Andric   }
27480b57cec5SDimitry Andric 
27490b57cec5SDimitry Andric   bool Signed = false;
27500b57cec5SDimitry Andric   switch (Opc) {
27510b57cec5SDimitry Andric     case Hexagon::A2_sxtb:
27520b57cec5SDimitry Andric     case Hexagon::A2_sxth:
27530b57cec5SDimitry Andric     case Hexagon::A2_sxtw:
27540b57cec5SDimitry Andric       Signed = true;
27550b57cec5SDimitry Andric       break;
27560b57cec5SDimitry Andric   }
27570b57cec5SDimitry Andric 
27580b57cec5SDimitry Andric   RegisterSubReg DefR(MI.getOperand(0));
27590b57cec5SDimitry Andric   unsigned BW = getRegBitWidth(DefR.Reg);
27600b57cec5SDimitry Andric   LatticeCell RC = Outputs.get(DefR.Reg);
27610b57cec5SDimitry Andric   bool Eval = Signed ? evaluateSEXTr(R1, BW, Bits, Inputs, RC)
27620b57cec5SDimitry Andric                      : evaluateZEXTr(R1, BW, Bits, Inputs, RC);
27630b57cec5SDimitry Andric   if (!Eval)
27640b57cec5SDimitry Andric     return false;
27650b57cec5SDimitry Andric   Outputs.update(DefR.Reg, RC);
27660b57cec5SDimitry Andric   return true;
27670b57cec5SDimitry Andric }
27680b57cec5SDimitry Andric 
27690b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexVector1(const MachineInstr &MI,
27700b57cec5SDimitry Andric       const CellMap &Inputs, CellMap &Outputs) {
27710b57cec5SDimitry Andric   // DefR = op R1
27720b57cec5SDimitry Andric   RegisterSubReg DefR(MI.getOperand(0));
27730b57cec5SDimitry Andric   RegisterSubReg R1(MI.getOperand(1));
27740b57cec5SDimitry Andric   assert(Inputs.has(R1.Reg));
27750b57cec5SDimitry Andric   LatticeCell RC = Outputs.get(DefR.Reg);
27760b57cec5SDimitry Andric   bool Eval;
27770b57cec5SDimitry Andric 
27780b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
27790b57cec5SDimitry Andric   switch (Opc) {
27800b57cec5SDimitry Andric     case Hexagon::S2_vsplatrb:
27810b57cec5SDimitry Andric       // Rd = 4 times Rs:0..7
27820b57cec5SDimitry Andric       Eval = evaluateSplatr(R1, 8, 4, Inputs, RC);
27830b57cec5SDimitry Andric       break;
27840b57cec5SDimitry Andric     case Hexagon::S2_vsplatrh:
27850b57cec5SDimitry Andric       // Rdd = 4 times Rs:0..15
27860b57cec5SDimitry Andric       Eval = evaluateSplatr(R1, 16, 4, Inputs, RC);
27870b57cec5SDimitry Andric       break;
27880b57cec5SDimitry Andric     default:
27890b57cec5SDimitry Andric       return false;
27900b57cec5SDimitry Andric   }
27910b57cec5SDimitry Andric 
27920b57cec5SDimitry Andric   if (!Eval)
27930b57cec5SDimitry Andric     return false;
27940b57cec5SDimitry Andric   Outputs.update(DefR.Reg, RC);
27950b57cec5SDimitry Andric   return true;
27960b57cec5SDimitry Andric }
27970b57cec5SDimitry Andric 
27980b57cec5SDimitry Andric bool HexagonConstEvaluator::rewriteHexConstDefs(MachineInstr &MI,
27990b57cec5SDimitry Andric       const CellMap &Inputs, bool &AllDefs) {
28000b57cec5SDimitry Andric   AllDefs = false;
28010b57cec5SDimitry Andric 
28020b57cec5SDimitry Andric   // Some diagnostics.
28030b57cec5SDimitry Andric   // LLVM_DEBUG({...}) gets confused with all this code as an argument.
28040b57cec5SDimitry Andric #ifndef NDEBUG
28050b57cec5SDimitry Andric   bool Debugging = DebugFlag && isCurrentDebugType(DEBUG_TYPE);
28060b57cec5SDimitry Andric   if (Debugging) {
28070b57cec5SDimitry Andric     bool Const = true, HasUse = false;
28080b57cec5SDimitry Andric     for (const MachineOperand &MO : MI.operands()) {
28090b57cec5SDimitry Andric       if (!MO.isReg() || !MO.isUse() || MO.isImplicit())
28100b57cec5SDimitry Andric         continue;
28110b57cec5SDimitry Andric       RegisterSubReg R(MO);
28128bcb0991SDimitry Andric       if (!Register::isVirtualRegister(R.Reg))
28130b57cec5SDimitry Andric         continue;
28140b57cec5SDimitry Andric       HasUse = true;
28150b57cec5SDimitry Andric       // PHIs can legitimately have "top" cells after propagation.
28160b57cec5SDimitry Andric       if (!MI.isPHI() && !Inputs.has(R.Reg)) {
28170b57cec5SDimitry Andric         dbgs() << "Top " << printReg(R.Reg, &HRI, R.SubReg)
28180b57cec5SDimitry Andric                << " in MI: " << MI;
28190b57cec5SDimitry Andric         continue;
28200b57cec5SDimitry Andric       }
28210b57cec5SDimitry Andric       const LatticeCell &L = Inputs.get(R.Reg);
28220b57cec5SDimitry Andric       Const &= L.isSingle();
28230b57cec5SDimitry Andric       if (!Const)
28240b57cec5SDimitry Andric         break;
28250b57cec5SDimitry Andric     }
28260b57cec5SDimitry Andric     if (HasUse && Const) {
28270b57cec5SDimitry Andric       if (!MI.isCopy()) {
28280b57cec5SDimitry Andric         dbgs() << "CONST: " << MI;
28290b57cec5SDimitry Andric         for (const MachineOperand &MO : MI.operands()) {
28300b57cec5SDimitry Andric           if (!MO.isReg() || !MO.isUse() || MO.isImplicit())
28310b57cec5SDimitry Andric             continue;
28328bcb0991SDimitry Andric           Register R = MO.getReg();
28330b57cec5SDimitry Andric           dbgs() << printReg(R, &TRI) << ": " << Inputs.get(R) << "\n";
28340b57cec5SDimitry Andric         }
28350b57cec5SDimitry Andric       }
28360b57cec5SDimitry Andric     }
28370b57cec5SDimitry Andric   }
28380b57cec5SDimitry Andric #endif
28390b57cec5SDimitry Andric 
28400b57cec5SDimitry Andric   // Avoid generating TFRIs for register transfers---this will keep the
28410b57cec5SDimitry Andric   // coalescing opportunities.
28420b57cec5SDimitry Andric   if (MI.isCopy())
28430b57cec5SDimitry Andric     return false;
28440b57cec5SDimitry Andric 
2845*5ffd83dbSDimitry Andric   MachineFunction *MF = MI.getParent()->getParent();
2846*5ffd83dbSDimitry Andric   auto &HST = MF->getSubtarget<HexagonSubtarget>();
2847*5ffd83dbSDimitry Andric 
28480b57cec5SDimitry Andric   // Collect all virtual register-def operands.
28490b57cec5SDimitry Andric   SmallVector<unsigned,2> DefRegs;
28500b57cec5SDimitry Andric   for (const MachineOperand &MO : MI.operands()) {
28510b57cec5SDimitry Andric     if (!MO.isReg() || !MO.isDef())
28520b57cec5SDimitry Andric       continue;
28538bcb0991SDimitry Andric     Register R = MO.getReg();
28548bcb0991SDimitry Andric     if (!Register::isVirtualRegister(R))
28550b57cec5SDimitry Andric       continue;
28560b57cec5SDimitry Andric     assert(!MO.getSubReg());
28570b57cec5SDimitry Andric     assert(Inputs.has(R));
28580b57cec5SDimitry Andric     DefRegs.push_back(R);
28590b57cec5SDimitry Andric   }
28600b57cec5SDimitry Andric 
28610b57cec5SDimitry Andric   MachineBasicBlock &B = *MI.getParent();
28620b57cec5SDimitry Andric   const DebugLoc &DL = MI.getDebugLoc();
28630b57cec5SDimitry Andric   unsigned ChangedNum = 0;
28640b57cec5SDimitry Andric #ifndef NDEBUG
28650b57cec5SDimitry Andric   SmallVector<const MachineInstr*,4> NewInstrs;
28660b57cec5SDimitry Andric #endif
28670b57cec5SDimitry Andric 
28680b57cec5SDimitry Andric   // For each defined register, if it is a constant, create an instruction
28690b57cec5SDimitry Andric   //   NewR = const
28700b57cec5SDimitry Andric   // and replace all uses of the defined register with NewR.
28710b57cec5SDimitry Andric   for (unsigned i = 0, n = DefRegs.size(); i < n; ++i) {
28720b57cec5SDimitry Andric     unsigned R = DefRegs[i];
28730b57cec5SDimitry Andric     const LatticeCell &L = Inputs.get(R);
28740b57cec5SDimitry Andric     if (L.isBottom())
28750b57cec5SDimitry Andric       continue;
28760b57cec5SDimitry Andric     const TargetRegisterClass *RC = MRI->getRegClass(R);
28770b57cec5SDimitry Andric     MachineBasicBlock::iterator At = MI.getIterator();
28780b57cec5SDimitry Andric 
28790b57cec5SDimitry Andric     if (!L.isSingle()) {
28800b57cec5SDimitry Andric       // If this a zero/non-zero cell, we can fold a definition
28810b57cec5SDimitry Andric       // of a predicate register.
28820b57cec5SDimitry Andric       using P = ConstantProperties;
28830b57cec5SDimitry Andric 
28840b57cec5SDimitry Andric       uint64_t Ps = L.properties();
28850b57cec5SDimitry Andric       if (!(Ps & (P::Zero|P::NonZero)))
28860b57cec5SDimitry Andric         continue;
28870b57cec5SDimitry Andric       const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
28880b57cec5SDimitry Andric       if (RC != PredRC)
28890b57cec5SDimitry Andric         continue;
28900b57cec5SDimitry Andric       const MCInstrDesc *NewD = (Ps & P::Zero) ?
28910b57cec5SDimitry Andric         &HII.get(Hexagon::PS_false) :
28920b57cec5SDimitry Andric         &HII.get(Hexagon::PS_true);
28938bcb0991SDimitry Andric       Register NewR = MRI->createVirtualRegister(PredRC);
28940b57cec5SDimitry Andric       const MachineInstrBuilder &MIB = BuildMI(B, At, DL, *NewD, NewR);
28950b57cec5SDimitry Andric       (void)MIB;
28960b57cec5SDimitry Andric #ifndef NDEBUG
28970b57cec5SDimitry Andric       NewInstrs.push_back(&*MIB);
28980b57cec5SDimitry Andric #endif
28990b57cec5SDimitry Andric       replaceAllRegUsesWith(R, NewR);
29000b57cec5SDimitry Andric     } else {
29010b57cec5SDimitry Andric       // This cell has a single value.
29020b57cec5SDimitry Andric       APInt A;
29030b57cec5SDimitry Andric       if (!constToInt(L.Value, A) || !A.isSignedIntN(64))
29040b57cec5SDimitry Andric         continue;
29050b57cec5SDimitry Andric       const TargetRegisterClass *NewRC;
29060b57cec5SDimitry Andric       const MCInstrDesc *NewD;
29070b57cec5SDimitry Andric 
29080b57cec5SDimitry Andric       unsigned W = getRegBitWidth(R);
29090b57cec5SDimitry Andric       int64_t V = A.getSExtValue();
29100b57cec5SDimitry Andric       assert(W == 32 || W == 64);
29110b57cec5SDimitry Andric       if (W == 32)
29120b57cec5SDimitry Andric         NewRC = &Hexagon::IntRegsRegClass;
29130b57cec5SDimitry Andric       else
29140b57cec5SDimitry Andric         NewRC = &Hexagon::DoubleRegsRegClass;
29158bcb0991SDimitry Andric       Register NewR = MRI->createVirtualRegister(NewRC);
29160b57cec5SDimitry Andric       const MachineInstr *NewMI;
29170b57cec5SDimitry Andric 
29180b57cec5SDimitry Andric       if (W == 32) {
29190b57cec5SDimitry Andric         NewD = &HII.get(Hexagon::A2_tfrsi);
29200b57cec5SDimitry Andric         NewMI = BuildMI(B, At, DL, *NewD, NewR)
29210b57cec5SDimitry Andric                   .addImm(V);
29220b57cec5SDimitry Andric       } else {
29230b57cec5SDimitry Andric         if (A.isSignedIntN(8)) {
29240b57cec5SDimitry Andric           NewD = &HII.get(Hexagon::A2_tfrpi);
29250b57cec5SDimitry Andric           NewMI = BuildMI(B, At, DL, *NewD, NewR)
29260b57cec5SDimitry Andric                     .addImm(V);
29270b57cec5SDimitry Andric         } else {
29280b57cec5SDimitry Andric           int32_t Hi = V >> 32;
29290b57cec5SDimitry Andric           int32_t Lo = V & 0xFFFFFFFFLL;
29300b57cec5SDimitry Andric           if (isInt<8>(Hi) && isInt<8>(Lo)) {
29310b57cec5SDimitry Andric             NewD = &HII.get(Hexagon::A2_combineii);
29320b57cec5SDimitry Andric             NewMI = BuildMI(B, At, DL, *NewD, NewR)
29330b57cec5SDimitry Andric                       .addImm(Hi)
29340b57cec5SDimitry Andric                       .addImm(Lo);
2935*5ffd83dbSDimitry Andric           } else if (MF->getFunction().hasOptSize() || !HST.isTinyCore()) {
2936*5ffd83dbSDimitry Andric             // Disable CONST64 for tiny core since it takes a LD resource.
29370b57cec5SDimitry Andric             NewD = &HII.get(Hexagon::CONST64);
29380b57cec5SDimitry Andric             NewMI = BuildMI(B, At, DL, *NewD, NewR)
29390b57cec5SDimitry Andric                       .addImm(V);
2940*5ffd83dbSDimitry Andric           } else
2941*5ffd83dbSDimitry Andric             return false;
29420b57cec5SDimitry Andric         }
29430b57cec5SDimitry Andric       }
29440b57cec5SDimitry Andric       (void)NewMI;
29450b57cec5SDimitry Andric #ifndef NDEBUG
29460b57cec5SDimitry Andric       NewInstrs.push_back(NewMI);
29470b57cec5SDimitry Andric #endif
29480b57cec5SDimitry Andric       replaceAllRegUsesWith(R, NewR);
29490b57cec5SDimitry Andric     }
29500b57cec5SDimitry Andric     ChangedNum++;
29510b57cec5SDimitry Andric   }
29520b57cec5SDimitry Andric 
29530b57cec5SDimitry Andric   LLVM_DEBUG({
29540b57cec5SDimitry Andric     if (!NewInstrs.empty()) {
29550b57cec5SDimitry Andric       MachineFunction &MF = *MI.getParent()->getParent();
29560b57cec5SDimitry Andric       dbgs() << "In function: " << MF.getName() << "\n";
29570b57cec5SDimitry Andric       dbgs() << "Rewrite: for " << MI << "  created " << *NewInstrs[0];
29580b57cec5SDimitry Andric       for (unsigned i = 1; i < NewInstrs.size(); ++i)
29590b57cec5SDimitry Andric         dbgs() << "          " << *NewInstrs[i];
29600b57cec5SDimitry Andric     }
29610b57cec5SDimitry Andric   });
29620b57cec5SDimitry Andric 
29630b57cec5SDimitry Andric   AllDefs = (ChangedNum == DefRegs.size());
29640b57cec5SDimitry Andric   return ChangedNum > 0;
29650b57cec5SDimitry Andric }
29660b57cec5SDimitry Andric 
29670b57cec5SDimitry Andric bool HexagonConstEvaluator::rewriteHexConstUses(MachineInstr &MI,
29680b57cec5SDimitry Andric       const CellMap &Inputs) {
29690b57cec5SDimitry Andric   bool Changed = false;
29700b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
29710b57cec5SDimitry Andric   MachineBasicBlock &B = *MI.getParent();
29720b57cec5SDimitry Andric   const DebugLoc &DL = MI.getDebugLoc();
29730b57cec5SDimitry Andric   MachineBasicBlock::iterator At = MI.getIterator();
29740b57cec5SDimitry Andric   MachineInstr *NewMI = nullptr;
29750b57cec5SDimitry Andric 
29760b57cec5SDimitry Andric   switch (Opc) {
29770b57cec5SDimitry Andric     case Hexagon::M2_maci:
29780b57cec5SDimitry Andric     // Convert DefR += mpyi(R2, R3)
29790b57cec5SDimitry Andric     //   to   DefR += mpyi(R, #imm),
29800b57cec5SDimitry Andric     //   or   DefR -= mpyi(R, #imm).
29810b57cec5SDimitry Andric     {
29820b57cec5SDimitry Andric       RegisterSubReg DefR(MI.getOperand(0));
29830b57cec5SDimitry Andric       assert(!DefR.SubReg);
29840b57cec5SDimitry Andric       RegisterSubReg R2(MI.getOperand(2));
29850b57cec5SDimitry Andric       RegisterSubReg R3(MI.getOperand(3));
29860b57cec5SDimitry Andric       assert(Inputs.has(R2.Reg) && Inputs.has(R3.Reg));
29870b57cec5SDimitry Andric       LatticeCell LS2, LS3;
29880b57cec5SDimitry Andric       // It is enough to get one of the input cells, since we will only try
29890b57cec5SDimitry Andric       // to replace one argument---whichever happens to be a single constant.
29900b57cec5SDimitry Andric       bool HasC2 = getCell(R2, Inputs, LS2), HasC3 = getCell(R3, Inputs, LS3);
29910b57cec5SDimitry Andric       if (!HasC2 && !HasC3)
29920b57cec5SDimitry Andric         return false;
29930b57cec5SDimitry Andric       bool Zero = ((HasC2 && (LS2.properties() & ConstantProperties::Zero)) ||
29940b57cec5SDimitry Andric                    (HasC3 && (LS3.properties() & ConstantProperties::Zero)));
29950b57cec5SDimitry Andric       // If one of the operands is zero, eliminate the multiplication.
29960b57cec5SDimitry Andric       if (Zero) {
29970b57cec5SDimitry Andric         // DefR == R1 (tied operands).
29980b57cec5SDimitry Andric         MachineOperand &Acc = MI.getOperand(1);
29990b57cec5SDimitry Andric         RegisterSubReg R1(Acc);
30000b57cec5SDimitry Andric         unsigned NewR = R1.Reg;
30010b57cec5SDimitry Andric         if (R1.SubReg) {
30020b57cec5SDimitry Andric           // Generate COPY. FIXME: Replace with the register:subregister.
30030b57cec5SDimitry Andric           const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg);
30040b57cec5SDimitry Andric           NewR = MRI->createVirtualRegister(RC);
30050b57cec5SDimitry Andric           NewMI = BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR)
30060b57cec5SDimitry Andric                     .addReg(R1.Reg, getRegState(Acc), R1.SubReg);
30070b57cec5SDimitry Andric         }
30080b57cec5SDimitry Andric         replaceAllRegUsesWith(DefR.Reg, NewR);
30090b57cec5SDimitry Andric         MRI->clearKillFlags(NewR);
30100b57cec5SDimitry Andric         Changed = true;
30110b57cec5SDimitry Andric         break;
30120b57cec5SDimitry Andric       }
30130b57cec5SDimitry Andric 
30140b57cec5SDimitry Andric       bool Swap = false;
30150b57cec5SDimitry Andric       if (!LS3.isSingle()) {
30160b57cec5SDimitry Andric         if (!LS2.isSingle())
30170b57cec5SDimitry Andric           return false;
30180b57cec5SDimitry Andric         Swap = true;
30190b57cec5SDimitry Andric       }
30200b57cec5SDimitry Andric       const LatticeCell &LI = Swap ? LS2 : LS3;
30210b57cec5SDimitry Andric       const MachineOperand &OpR2 = Swap ? MI.getOperand(3)
30220b57cec5SDimitry Andric                                         : MI.getOperand(2);
30230b57cec5SDimitry Andric       // LI is single here.
30240b57cec5SDimitry Andric       APInt A;
30250b57cec5SDimitry Andric       if (!constToInt(LI.Value, A) || !A.isSignedIntN(8))
30260b57cec5SDimitry Andric         return false;
30270b57cec5SDimitry Andric       int64_t V = A.getSExtValue();
30280b57cec5SDimitry Andric       const MCInstrDesc &D = (V >= 0) ? HII.get(Hexagon::M2_macsip)
30290b57cec5SDimitry Andric                                       : HII.get(Hexagon::M2_macsin);
30300b57cec5SDimitry Andric       if (V < 0)
30310b57cec5SDimitry Andric         V = -V;
30320b57cec5SDimitry Andric       const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg);
30338bcb0991SDimitry Andric       Register NewR = MRI->createVirtualRegister(RC);
30340b57cec5SDimitry Andric       const MachineOperand &Src1 = MI.getOperand(1);
30350b57cec5SDimitry Andric       NewMI = BuildMI(B, At, DL, D, NewR)
30360b57cec5SDimitry Andric                 .addReg(Src1.getReg(), getRegState(Src1), Src1.getSubReg())
30370b57cec5SDimitry Andric                 .addReg(OpR2.getReg(), getRegState(OpR2), OpR2.getSubReg())
30380b57cec5SDimitry Andric                 .addImm(V);
30390b57cec5SDimitry Andric       replaceAllRegUsesWith(DefR.Reg, NewR);
30400b57cec5SDimitry Andric       Changed = true;
30410b57cec5SDimitry Andric       break;
30420b57cec5SDimitry Andric     }
30430b57cec5SDimitry Andric 
30440b57cec5SDimitry Andric     case Hexagon::A2_and:
30450b57cec5SDimitry Andric     {
30460b57cec5SDimitry Andric       RegisterSubReg R1(MI.getOperand(1));
30470b57cec5SDimitry Andric       RegisterSubReg R2(MI.getOperand(2));
30480b57cec5SDimitry Andric       assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
30490b57cec5SDimitry Andric       LatticeCell LS1, LS2;
30500b57cec5SDimitry Andric       unsigned CopyOf = 0;
30510b57cec5SDimitry Andric       // Check if any of the operands is -1 (i.e. all bits set).
30520b57cec5SDimitry Andric       if (getCell(R1, Inputs, LS1) && LS1.isSingle()) {
30530b57cec5SDimitry Andric         APInt M1;
30540b57cec5SDimitry Andric         if (constToInt(LS1.Value, M1) && !~M1)
30550b57cec5SDimitry Andric           CopyOf = 2;
30560b57cec5SDimitry Andric       }
30570b57cec5SDimitry Andric       else if (getCell(R2, Inputs, LS2) && LS2.isSingle()) {
30580b57cec5SDimitry Andric         APInt M1;
30590b57cec5SDimitry Andric         if (constToInt(LS2.Value, M1) && !~M1)
30600b57cec5SDimitry Andric           CopyOf = 1;
30610b57cec5SDimitry Andric       }
30620b57cec5SDimitry Andric       if (!CopyOf)
30630b57cec5SDimitry Andric         return false;
30640b57cec5SDimitry Andric       MachineOperand &SO = MI.getOperand(CopyOf);
30650b57cec5SDimitry Andric       RegisterSubReg SR(SO);
30660b57cec5SDimitry Andric       RegisterSubReg DefR(MI.getOperand(0));
30670b57cec5SDimitry Andric       unsigned NewR = SR.Reg;
30680b57cec5SDimitry Andric       if (SR.SubReg) {
30690b57cec5SDimitry Andric         const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg);
30700b57cec5SDimitry Andric         NewR = MRI->createVirtualRegister(RC);
30710b57cec5SDimitry Andric         NewMI = BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR)
30720b57cec5SDimitry Andric                   .addReg(SR.Reg, getRegState(SO), SR.SubReg);
30730b57cec5SDimitry Andric       }
30740b57cec5SDimitry Andric       replaceAllRegUsesWith(DefR.Reg, NewR);
30750b57cec5SDimitry Andric       MRI->clearKillFlags(NewR);
30760b57cec5SDimitry Andric       Changed = true;
30770b57cec5SDimitry Andric     }
30780b57cec5SDimitry Andric     break;
30790b57cec5SDimitry Andric 
30800b57cec5SDimitry Andric     case Hexagon::A2_or:
30810b57cec5SDimitry Andric     {
30820b57cec5SDimitry Andric       RegisterSubReg R1(MI.getOperand(1));
30830b57cec5SDimitry Andric       RegisterSubReg R2(MI.getOperand(2));
30840b57cec5SDimitry Andric       assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
30850b57cec5SDimitry Andric       LatticeCell LS1, LS2;
30860b57cec5SDimitry Andric       unsigned CopyOf = 0;
30870b57cec5SDimitry Andric 
30880b57cec5SDimitry Andric       using P = ConstantProperties;
30890b57cec5SDimitry Andric 
30900b57cec5SDimitry Andric       if (getCell(R1, Inputs, LS1) && (LS1.properties() & P::Zero))
30910b57cec5SDimitry Andric         CopyOf = 2;
30920b57cec5SDimitry Andric       else if (getCell(R2, Inputs, LS2) && (LS2.properties() & P::Zero))
30930b57cec5SDimitry Andric         CopyOf = 1;
30940b57cec5SDimitry Andric       if (!CopyOf)
30950b57cec5SDimitry Andric         return false;
30960b57cec5SDimitry Andric       MachineOperand &SO = MI.getOperand(CopyOf);
30970b57cec5SDimitry Andric       RegisterSubReg SR(SO);
30980b57cec5SDimitry Andric       RegisterSubReg DefR(MI.getOperand(0));
30990b57cec5SDimitry Andric       unsigned NewR = SR.Reg;
31000b57cec5SDimitry Andric       if (SR.SubReg) {
31010b57cec5SDimitry Andric         const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg);
31020b57cec5SDimitry Andric         NewR = MRI->createVirtualRegister(RC);
31030b57cec5SDimitry Andric         NewMI = BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR)
31040b57cec5SDimitry Andric                   .addReg(SR.Reg, getRegState(SO), SR.SubReg);
31050b57cec5SDimitry Andric       }
31060b57cec5SDimitry Andric       replaceAllRegUsesWith(DefR.Reg, NewR);
31070b57cec5SDimitry Andric       MRI->clearKillFlags(NewR);
31080b57cec5SDimitry Andric       Changed = true;
31090b57cec5SDimitry Andric     }
31100b57cec5SDimitry Andric     break;
31110b57cec5SDimitry Andric   }
31120b57cec5SDimitry Andric 
31130b57cec5SDimitry Andric   if (NewMI) {
31140b57cec5SDimitry Andric     // clear all the kill flags of this new instruction.
31150b57cec5SDimitry Andric     for (MachineOperand &MO : NewMI->operands())
31160b57cec5SDimitry Andric       if (MO.isReg() && MO.isUse())
31170b57cec5SDimitry Andric         MO.setIsKill(false);
31180b57cec5SDimitry Andric   }
31190b57cec5SDimitry Andric 
31200b57cec5SDimitry Andric   LLVM_DEBUG({
31210b57cec5SDimitry Andric     if (NewMI) {
31220b57cec5SDimitry Andric       dbgs() << "Rewrite: for " << MI;
31230b57cec5SDimitry Andric       if (NewMI != &MI)
31240b57cec5SDimitry Andric         dbgs() << "  created " << *NewMI;
31250b57cec5SDimitry Andric       else
31260b57cec5SDimitry Andric         dbgs() << "  modified the instruction itself and created:" << *NewMI;
31270b57cec5SDimitry Andric     }
31280b57cec5SDimitry Andric   });
31290b57cec5SDimitry Andric 
31300b57cec5SDimitry Andric   return Changed;
31310b57cec5SDimitry Andric }
31320b57cec5SDimitry Andric 
31330b57cec5SDimitry Andric void HexagonConstEvaluator::replaceAllRegUsesWith(unsigned FromReg,
31340b57cec5SDimitry Andric       unsigned ToReg) {
31358bcb0991SDimitry Andric   assert(Register::isVirtualRegister(FromReg));
31368bcb0991SDimitry Andric   assert(Register::isVirtualRegister(ToReg));
31370b57cec5SDimitry Andric   for (auto I = MRI->use_begin(FromReg), E = MRI->use_end(); I != E;) {
31380b57cec5SDimitry Andric     MachineOperand &O = *I;
31390b57cec5SDimitry Andric     ++I;
31400b57cec5SDimitry Andric     O.setReg(ToReg);
31410b57cec5SDimitry Andric   }
31420b57cec5SDimitry Andric }
31430b57cec5SDimitry Andric 
31440b57cec5SDimitry Andric bool HexagonConstEvaluator::rewriteHexBranch(MachineInstr &BrI,
31450b57cec5SDimitry Andric       const CellMap &Inputs) {
31460b57cec5SDimitry Andric   MachineBasicBlock &B = *BrI.getParent();
31470b57cec5SDimitry Andric   unsigned NumOp = BrI.getNumOperands();
31480b57cec5SDimitry Andric   if (!NumOp)
31490b57cec5SDimitry Andric     return false;
31500b57cec5SDimitry Andric 
31510b57cec5SDimitry Andric   bool FallsThru;
31520b57cec5SDimitry Andric   SetVector<const MachineBasicBlock*> Targets;
31530b57cec5SDimitry Andric   bool Eval = evaluate(BrI, Inputs, Targets, FallsThru);
31540b57cec5SDimitry Andric   unsigned NumTargets = Targets.size();
31550b57cec5SDimitry Andric   if (!Eval || NumTargets > 1 || (NumTargets == 1 && FallsThru))
31560b57cec5SDimitry Andric     return false;
31570b57cec5SDimitry Andric   if (BrI.getOpcode() == Hexagon::J2_jump)
31580b57cec5SDimitry Andric     return false;
31590b57cec5SDimitry Andric 
31600b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Rewrite(" << printMBBReference(B) << "):" << BrI);
31610b57cec5SDimitry Andric   bool Rewritten = false;
31620b57cec5SDimitry Andric   if (NumTargets > 0) {
31630b57cec5SDimitry Andric     assert(!FallsThru && "This should have been checked before");
31640b57cec5SDimitry Andric     // MIB.addMBB needs non-const pointer.
31650b57cec5SDimitry Andric     MachineBasicBlock *TargetB = const_cast<MachineBasicBlock*>(Targets[0]);
31660b57cec5SDimitry Andric     bool Moot = B.isLayoutSuccessor(TargetB);
31670b57cec5SDimitry Andric     if (!Moot) {
31680b57cec5SDimitry Andric       // If we build a branch here, we must make sure that it won't be
31690b57cec5SDimitry Andric       // erased as "non-executable". We can't mark any new instructions
31700b57cec5SDimitry Andric       // as executable here, so we need to overwrite the BrI, which we
31710b57cec5SDimitry Andric       // know is executable.
31720b57cec5SDimitry Andric       const MCInstrDesc &JD = HII.get(Hexagon::J2_jump);
31730b57cec5SDimitry Andric       auto NI = BuildMI(B, BrI.getIterator(), BrI.getDebugLoc(), JD)
31740b57cec5SDimitry Andric                   .addMBB(TargetB);
31750b57cec5SDimitry Andric       BrI.setDesc(JD);
31760b57cec5SDimitry Andric       while (BrI.getNumOperands() > 0)
31770b57cec5SDimitry Andric         BrI.RemoveOperand(0);
31780b57cec5SDimitry Andric       // This ensures that all implicit operands (e.g. implicit-def %r31, etc)
31790b57cec5SDimitry Andric       // are present in the rewritten branch.
31800b57cec5SDimitry Andric       for (auto &Op : NI->operands())
31810b57cec5SDimitry Andric         BrI.addOperand(Op);
31820b57cec5SDimitry Andric       NI->eraseFromParent();
31830b57cec5SDimitry Andric       Rewritten = true;
31840b57cec5SDimitry Andric     }
31850b57cec5SDimitry Andric   }
31860b57cec5SDimitry Andric 
31870b57cec5SDimitry Andric   // Do not erase instructions. A newly created instruction could get
31880b57cec5SDimitry Andric   // the same address as an instruction marked as executable during the
31890b57cec5SDimitry Andric   // propagation.
31900b57cec5SDimitry Andric   if (!Rewritten)
31910b57cec5SDimitry Andric     replaceWithNop(BrI);
31920b57cec5SDimitry Andric   return true;
31930b57cec5SDimitry Andric }
31940b57cec5SDimitry Andric 
31950b57cec5SDimitry Andric FunctionPass *llvm::createHexagonConstPropagationPass() {
31960b57cec5SDimitry Andric   return new HexagonConstPropagation();
31970b57cec5SDimitry Andric }
3198