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