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