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