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