1*0b57cec5SDimitry Andric //===- HexagonConstPropagation.cpp ----------------------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #define DEBUG_TYPE "hcp" 10*0b57cec5SDimitry Andric 11*0b57cec5SDimitry Andric #include "HexagonInstrInfo.h" 12*0b57cec5SDimitry Andric #include "HexagonRegisterInfo.h" 13*0b57cec5SDimitry Andric #include "HexagonSubtarget.h" 14*0b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h" 15*0b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 16*0b57cec5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h" 17*0b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h" 18*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 19*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 20*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 21*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 22*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 23*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 24*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 25*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 26*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 27*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 28*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 29*0b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 30*0b57cec5SDimitry Andric #include "llvm/IR/Type.h" 31*0b57cec5SDimitry Andric #include "llvm/Pass.h" 32*0b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 33*0b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 34*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 35*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 36*0b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 37*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 38*0b57cec5SDimitry Andric #include <cassert> 39*0b57cec5SDimitry Andric #include <cstdint> 40*0b57cec5SDimitry Andric #include <cstring> 41*0b57cec5SDimitry Andric #include <iterator> 42*0b57cec5SDimitry Andric #include <map> 43*0b57cec5SDimitry Andric #include <queue> 44*0b57cec5SDimitry Andric #include <set> 45*0b57cec5SDimitry Andric #include <utility> 46*0b57cec5SDimitry Andric #include <vector> 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric using namespace llvm; 49*0b57cec5SDimitry Andric 50*0b57cec5SDimitry Andric namespace { 51*0b57cec5SDimitry Andric 52*0b57cec5SDimitry Andric // Properties of a value that are tracked by the propagation. 53*0b57cec5SDimitry Andric // A property that is marked as present (i.e. bit is set) dentes that the 54*0b57cec5SDimitry Andric // value is known (proven) to have this property. Not all combinations 55*0b57cec5SDimitry Andric // of bits make sense, for example Zero and NonZero are mutually exclusive, 56*0b57cec5SDimitry Andric // but on the other hand, Zero implies Finite. In this case, whenever 57*0b57cec5SDimitry Andric // the Zero property is present, Finite should also be present. 58*0b57cec5SDimitry Andric class ConstantProperties { 59*0b57cec5SDimitry Andric public: 60*0b57cec5SDimitry Andric enum { 61*0b57cec5SDimitry Andric Unknown = 0x0000, 62*0b57cec5SDimitry Andric Zero = 0x0001, 63*0b57cec5SDimitry Andric NonZero = 0x0002, 64*0b57cec5SDimitry Andric Finite = 0x0004, 65*0b57cec5SDimitry Andric Infinity = 0x0008, 66*0b57cec5SDimitry Andric NaN = 0x0010, 67*0b57cec5SDimitry Andric SignedZero = 0x0020, 68*0b57cec5SDimitry Andric NumericProperties = (Zero|NonZero|Finite|Infinity|NaN|SignedZero), 69*0b57cec5SDimitry Andric PosOrZero = 0x0100, 70*0b57cec5SDimitry Andric NegOrZero = 0x0200, 71*0b57cec5SDimitry Andric SignProperties = (PosOrZero|NegOrZero), 72*0b57cec5SDimitry Andric Everything = (NumericProperties|SignProperties) 73*0b57cec5SDimitry Andric }; 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric // For a given constant, deduce the set of trackable properties that this 76*0b57cec5SDimitry Andric // constant has. 77*0b57cec5SDimitry Andric static uint32_t deduce(const Constant *C); 78*0b57cec5SDimitry Andric }; 79*0b57cec5SDimitry Andric 80*0b57cec5SDimitry Andric // A representation of a register as it can appear in a MachineOperand, 81*0b57cec5SDimitry Andric // i.e. a pair register:subregister. 82*0b57cec5SDimitry Andric 83*0b57cec5SDimitry Andric // FIXME: Use TargetInstrInfo::RegSubRegPair. Also duplicated in 84*0b57cec5SDimitry Andric // HexagonGenPredicate 85*0b57cec5SDimitry Andric struct RegisterSubReg { 86*0b57cec5SDimitry Andric unsigned Reg, SubReg; 87*0b57cec5SDimitry Andric 88*0b57cec5SDimitry Andric explicit RegisterSubReg(unsigned R, unsigned SR = 0) : Reg(R), SubReg(SR) {} 89*0b57cec5SDimitry Andric explicit RegisterSubReg(const MachineOperand &MO) 90*0b57cec5SDimitry Andric : Reg(MO.getReg()), SubReg(MO.getSubReg()) {} 91*0b57cec5SDimitry Andric 92*0b57cec5SDimitry Andric void print(const TargetRegisterInfo *TRI = nullptr) const { 93*0b57cec5SDimitry Andric dbgs() << printReg(Reg, TRI, SubReg); 94*0b57cec5SDimitry Andric } 95*0b57cec5SDimitry Andric 96*0b57cec5SDimitry Andric bool operator== (const RegisterSubReg &R) const { 97*0b57cec5SDimitry Andric return (Reg == R.Reg) && (SubReg == R.SubReg); 98*0b57cec5SDimitry Andric } 99*0b57cec5SDimitry Andric }; 100*0b57cec5SDimitry Andric 101*0b57cec5SDimitry Andric // Lattice cell, based on that was described in the W-Z paper on constant 102*0b57cec5SDimitry Andric // propagation. 103*0b57cec5SDimitry Andric // Latice cell will be allowed to hold multiple constant values. While 104*0b57cec5SDimitry Andric // multiple values would normally indicate "bottom", we can still derive 105*0b57cec5SDimitry Andric // some useful information from them. For example, comparison X > 0 106*0b57cec5SDimitry Andric // could be folded if all the values in the cell associated with X are 107*0b57cec5SDimitry Andric // positive. 108*0b57cec5SDimitry Andric class LatticeCell { 109*0b57cec5SDimitry Andric private: 110*0b57cec5SDimitry Andric enum { Normal, Top, Bottom }; 111*0b57cec5SDimitry Andric 112*0b57cec5SDimitry Andric static const unsigned MaxCellSize = 4; 113*0b57cec5SDimitry Andric 114*0b57cec5SDimitry Andric unsigned Kind:2; 115*0b57cec5SDimitry Andric unsigned Size:3; 116*0b57cec5SDimitry Andric unsigned IsSpecial:1; 117*0b57cec5SDimitry Andric unsigned :0; 118*0b57cec5SDimitry Andric 119*0b57cec5SDimitry Andric public: 120*0b57cec5SDimitry Andric union { 121*0b57cec5SDimitry Andric uint32_t Properties; 122*0b57cec5SDimitry Andric const Constant *Value; 123*0b57cec5SDimitry Andric const Constant *Values[MaxCellSize]; 124*0b57cec5SDimitry Andric }; 125*0b57cec5SDimitry Andric 126*0b57cec5SDimitry Andric LatticeCell() : Kind(Top), Size(0), IsSpecial(false) { 127*0b57cec5SDimitry Andric for (unsigned i = 0; i < MaxCellSize; ++i) 128*0b57cec5SDimitry Andric Values[i] = nullptr; 129*0b57cec5SDimitry Andric } 130*0b57cec5SDimitry Andric 131*0b57cec5SDimitry Andric bool meet(const LatticeCell &L); 132*0b57cec5SDimitry Andric bool add(const Constant *C); 133*0b57cec5SDimitry Andric bool add(uint32_t Property); 134*0b57cec5SDimitry Andric uint32_t properties() const; 135*0b57cec5SDimitry Andric unsigned size() const { return Size; } 136*0b57cec5SDimitry Andric 137*0b57cec5SDimitry Andric LatticeCell &operator= (const LatticeCell &L) { 138*0b57cec5SDimitry Andric if (this != &L) { 139*0b57cec5SDimitry Andric // This memcpy also copies Properties (when L.Size == 0). 140*0b57cec5SDimitry Andric uint32_t N = L.IsSpecial ? sizeof L.Properties 141*0b57cec5SDimitry Andric : L.Size*sizeof(const Constant*); 142*0b57cec5SDimitry Andric memcpy(Values, L.Values, N); 143*0b57cec5SDimitry Andric Kind = L.Kind; 144*0b57cec5SDimitry Andric Size = L.Size; 145*0b57cec5SDimitry Andric IsSpecial = L.IsSpecial; 146*0b57cec5SDimitry Andric } 147*0b57cec5SDimitry Andric return *this; 148*0b57cec5SDimitry Andric } 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric bool isSingle() const { return size() == 1; } 151*0b57cec5SDimitry Andric bool isProperty() const { return IsSpecial; } 152*0b57cec5SDimitry Andric bool isTop() const { return Kind == Top; } 153*0b57cec5SDimitry Andric bool isBottom() const { return Kind == Bottom; } 154*0b57cec5SDimitry Andric 155*0b57cec5SDimitry Andric bool setBottom() { 156*0b57cec5SDimitry Andric bool Changed = (Kind != Bottom); 157*0b57cec5SDimitry Andric Kind = Bottom; 158*0b57cec5SDimitry Andric Size = 0; 159*0b57cec5SDimitry Andric IsSpecial = false; 160*0b57cec5SDimitry Andric return Changed; 161*0b57cec5SDimitry Andric } 162*0b57cec5SDimitry Andric 163*0b57cec5SDimitry Andric void print(raw_ostream &os) const; 164*0b57cec5SDimitry Andric 165*0b57cec5SDimitry Andric private: 166*0b57cec5SDimitry Andric void setProperty() { 167*0b57cec5SDimitry Andric IsSpecial = true; 168*0b57cec5SDimitry Andric Size = 0; 169*0b57cec5SDimitry Andric Kind = Normal; 170*0b57cec5SDimitry Andric } 171*0b57cec5SDimitry Andric 172*0b57cec5SDimitry Andric bool convertToProperty(); 173*0b57cec5SDimitry Andric }; 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric #ifndef NDEBUG 176*0b57cec5SDimitry Andric raw_ostream &operator<< (raw_ostream &os, const LatticeCell &L) { 177*0b57cec5SDimitry Andric L.print(os); 178*0b57cec5SDimitry Andric return os; 179*0b57cec5SDimitry Andric } 180*0b57cec5SDimitry Andric #endif 181*0b57cec5SDimitry Andric 182*0b57cec5SDimitry Andric class MachineConstEvaluator; 183*0b57cec5SDimitry Andric 184*0b57cec5SDimitry Andric class MachineConstPropagator { 185*0b57cec5SDimitry Andric public: 186*0b57cec5SDimitry Andric MachineConstPropagator(MachineConstEvaluator &E) : MCE(E) { 187*0b57cec5SDimitry Andric Bottom.setBottom(); 188*0b57cec5SDimitry Andric } 189*0b57cec5SDimitry Andric 190*0b57cec5SDimitry Andric // Mapping: vreg -> cell 191*0b57cec5SDimitry Andric // The keys are registers _without_ subregisters. This won't allow 192*0b57cec5SDimitry Andric // definitions in the form of "vreg:subreg = ...". Such definitions 193*0b57cec5SDimitry Andric // would be questionable from the point of view of SSA, since the "vreg" 194*0b57cec5SDimitry Andric // could not be initialized in its entirety (specifically, an instruction 195*0b57cec5SDimitry Andric // defining the "other part" of "vreg" would also count as a definition 196*0b57cec5SDimitry Andric // of "vreg", which would violate the SSA). 197*0b57cec5SDimitry Andric // If a value of a pair vreg:subreg needs to be obtained, the cell for 198*0b57cec5SDimitry Andric // "vreg" needs to be looked up, and then the value of subregister "subreg" 199*0b57cec5SDimitry Andric // needs to be evaluated. 200*0b57cec5SDimitry Andric class CellMap { 201*0b57cec5SDimitry Andric public: 202*0b57cec5SDimitry Andric CellMap() { 203*0b57cec5SDimitry Andric assert(Top.isTop()); 204*0b57cec5SDimitry Andric Bottom.setBottom(); 205*0b57cec5SDimitry Andric } 206*0b57cec5SDimitry Andric 207*0b57cec5SDimitry Andric void clear() { Map.clear(); } 208*0b57cec5SDimitry Andric 209*0b57cec5SDimitry Andric bool has(unsigned R) const { 210*0b57cec5SDimitry Andric // All non-virtual registers are considered "bottom". 211*0b57cec5SDimitry Andric if (!TargetRegisterInfo::isVirtualRegister(R)) 212*0b57cec5SDimitry Andric return true; 213*0b57cec5SDimitry Andric MapType::const_iterator F = Map.find(R); 214*0b57cec5SDimitry Andric return F != Map.end(); 215*0b57cec5SDimitry Andric } 216*0b57cec5SDimitry Andric 217*0b57cec5SDimitry Andric const LatticeCell &get(unsigned R) const { 218*0b57cec5SDimitry Andric if (!TargetRegisterInfo::isVirtualRegister(R)) 219*0b57cec5SDimitry Andric return Bottom; 220*0b57cec5SDimitry Andric MapType::const_iterator F = Map.find(R); 221*0b57cec5SDimitry Andric if (F != Map.end()) 222*0b57cec5SDimitry Andric return F->second; 223*0b57cec5SDimitry Andric return Top; 224*0b57cec5SDimitry Andric } 225*0b57cec5SDimitry Andric 226*0b57cec5SDimitry Andric // Invalidates any const references. 227*0b57cec5SDimitry Andric void update(unsigned R, const LatticeCell &L) { 228*0b57cec5SDimitry Andric Map[R] = L; 229*0b57cec5SDimitry Andric } 230*0b57cec5SDimitry Andric 231*0b57cec5SDimitry Andric void print(raw_ostream &os, const TargetRegisterInfo &TRI) const; 232*0b57cec5SDimitry Andric 233*0b57cec5SDimitry Andric private: 234*0b57cec5SDimitry Andric using MapType = std::map<unsigned, LatticeCell>; 235*0b57cec5SDimitry Andric 236*0b57cec5SDimitry Andric MapType Map; 237*0b57cec5SDimitry Andric // To avoid creating "top" entries, return a const reference to 238*0b57cec5SDimitry Andric // this cell in "get". Also, have a "Bottom" cell to return from 239*0b57cec5SDimitry Andric // get when a value of a physical register is requested. 240*0b57cec5SDimitry Andric LatticeCell Top, Bottom; 241*0b57cec5SDimitry Andric 242*0b57cec5SDimitry Andric public: 243*0b57cec5SDimitry Andric using const_iterator = MapType::const_iterator; 244*0b57cec5SDimitry Andric 245*0b57cec5SDimitry Andric const_iterator begin() const { return Map.begin(); } 246*0b57cec5SDimitry Andric const_iterator end() const { return Map.end(); } 247*0b57cec5SDimitry Andric }; 248*0b57cec5SDimitry Andric 249*0b57cec5SDimitry Andric bool run(MachineFunction &MF); 250*0b57cec5SDimitry Andric 251*0b57cec5SDimitry Andric private: 252*0b57cec5SDimitry Andric void visitPHI(const MachineInstr &PN); 253*0b57cec5SDimitry Andric void visitNonBranch(const MachineInstr &MI); 254*0b57cec5SDimitry Andric void visitBranchesFrom(const MachineInstr &BrI); 255*0b57cec5SDimitry Andric void visitUsesOf(unsigned R); 256*0b57cec5SDimitry Andric bool computeBlockSuccessors(const MachineBasicBlock *MB, 257*0b57cec5SDimitry Andric SetVector<const MachineBasicBlock*> &Targets); 258*0b57cec5SDimitry Andric void removeCFGEdge(MachineBasicBlock *From, MachineBasicBlock *To); 259*0b57cec5SDimitry Andric 260*0b57cec5SDimitry Andric void propagate(MachineFunction &MF); 261*0b57cec5SDimitry Andric bool rewrite(MachineFunction &MF); 262*0b57cec5SDimitry Andric 263*0b57cec5SDimitry Andric MachineRegisterInfo *MRI; 264*0b57cec5SDimitry Andric MachineConstEvaluator &MCE; 265*0b57cec5SDimitry Andric 266*0b57cec5SDimitry Andric using CFGEdge = std::pair<unsigned, unsigned>; 267*0b57cec5SDimitry Andric using SetOfCFGEdge = std::set<CFGEdge>; 268*0b57cec5SDimitry Andric using SetOfInstr = std::set<const MachineInstr *>; 269*0b57cec5SDimitry Andric using QueueOfCFGEdge = std::queue<CFGEdge>; 270*0b57cec5SDimitry Andric 271*0b57cec5SDimitry Andric LatticeCell Bottom; 272*0b57cec5SDimitry Andric CellMap Cells; 273*0b57cec5SDimitry Andric SetOfCFGEdge EdgeExec; 274*0b57cec5SDimitry Andric SetOfInstr InstrExec; 275*0b57cec5SDimitry Andric QueueOfCFGEdge FlowQ; 276*0b57cec5SDimitry Andric }; 277*0b57cec5SDimitry Andric 278*0b57cec5SDimitry Andric // The "evaluator/rewriter" of machine instructions. This is an abstract 279*0b57cec5SDimitry Andric // base class that provides the interface that the propagator will use, 280*0b57cec5SDimitry Andric // as well as some helper functions that are target-independent. 281*0b57cec5SDimitry Andric class MachineConstEvaluator { 282*0b57cec5SDimitry Andric public: 283*0b57cec5SDimitry Andric MachineConstEvaluator(MachineFunction &Fn) 284*0b57cec5SDimitry Andric : TRI(*Fn.getSubtarget().getRegisterInfo()), 285*0b57cec5SDimitry Andric MF(Fn), CX(Fn.getFunction().getContext()) {} 286*0b57cec5SDimitry Andric virtual ~MachineConstEvaluator() = default; 287*0b57cec5SDimitry Andric 288*0b57cec5SDimitry Andric // The required interface: 289*0b57cec5SDimitry Andric // - A set of three "evaluate" functions. Each returns "true" if the 290*0b57cec5SDimitry Andric // computation succeeded, "false" otherwise. 291*0b57cec5SDimitry Andric // (1) Given an instruction MI, and the map with input values "Inputs", 292*0b57cec5SDimitry Andric // compute the set of output values "Outputs". An example of when 293*0b57cec5SDimitry Andric // the computation can "fail" is if MI is not an instruction that 294*0b57cec5SDimitry Andric // is recognized by the evaluator. 295*0b57cec5SDimitry Andric // (2) Given a register R (as reg:subreg), compute the cell that 296*0b57cec5SDimitry Andric // corresponds to the "subreg" part of the given register. 297*0b57cec5SDimitry Andric // (3) Given a branch instruction BrI, compute the set of target blocks. 298*0b57cec5SDimitry Andric // If the branch can fall-through, add null (0) to the list of 299*0b57cec5SDimitry Andric // possible targets. 300*0b57cec5SDimitry Andric // - A function "rewrite", that given the cell map after propagation, 301*0b57cec5SDimitry Andric // could rewrite instruction MI in a more beneficial form. Return 302*0b57cec5SDimitry Andric // "true" if a change has been made, "false" otherwise. 303*0b57cec5SDimitry Andric using CellMap = MachineConstPropagator::CellMap; 304*0b57cec5SDimitry Andric virtual bool evaluate(const MachineInstr &MI, const CellMap &Inputs, 305*0b57cec5SDimitry Andric CellMap &Outputs) = 0; 306*0b57cec5SDimitry Andric virtual bool evaluate(const RegisterSubReg &R, const LatticeCell &SrcC, 307*0b57cec5SDimitry Andric LatticeCell &Result) = 0; 308*0b57cec5SDimitry Andric virtual bool evaluate(const MachineInstr &BrI, const CellMap &Inputs, 309*0b57cec5SDimitry Andric SetVector<const MachineBasicBlock*> &Targets, 310*0b57cec5SDimitry Andric bool &CanFallThru) = 0; 311*0b57cec5SDimitry Andric virtual bool rewrite(MachineInstr &MI, const CellMap &Inputs) = 0; 312*0b57cec5SDimitry Andric 313*0b57cec5SDimitry Andric const TargetRegisterInfo &TRI; 314*0b57cec5SDimitry Andric 315*0b57cec5SDimitry Andric protected: 316*0b57cec5SDimitry Andric MachineFunction &MF; 317*0b57cec5SDimitry Andric LLVMContext &CX; 318*0b57cec5SDimitry Andric 319*0b57cec5SDimitry Andric struct Comparison { 320*0b57cec5SDimitry Andric enum { 321*0b57cec5SDimitry Andric Unk = 0x00, 322*0b57cec5SDimitry Andric EQ = 0x01, 323*0b57cec5SDimitry Andric NE = 0x02, 324*0b57cec5SDimitry Andric L = 0x04, // Less-than property. 325*0b57cec5SDimitry Andric G = 0x08, // Greater-than property. 326*0b57cec5SDimitry Andric U = 0x40, // Unsigned property. 327*0b57cec5SDimitry Andric LTs = L, 328*0b57cec5SDimitry Andric LEs = L | EQ, 329*0b57cec5SDimitry Andric GTs = G, 330*0b57cec5SDimitry Andric GEs = G | EQ, 331*0b57cec5SDimitry Andric LTu = L | U, 332*0b57cec5SDimitry Andric LEu = L | EQ | U, 333*0b57cec5SDimitry Andric GTu = G | U, 334*0b57cec5SDimitry Andric GEu = G | EQ | U 335*0b57cec5SDimitry Andric }; 336*0b57cec5SDimitry Andric 337*0b57cec5SDimitry Andric static uint32_t negate(uint32_t Cmp) { 338*0b57cec5SDimitry Andric if (Cmp == EQ) 339*0b57cec5SDimitry Andric return NE; 340*0b57cec5SDimitry Andric if (Cmp == NE) 341*0b57cec5SDimitry Andric return EQ; 342*0b57cec5SDimitry Andric assert((Cmp & (L|G)) != (L|G)); 343*0b57cec5SDimitry Andric return Cmp ^ (L|G); 344*0b57cec5SDimitry Andric } 345*0b57cec5SDimitry Andric }; 346*0b57cec5SDimitry Andric 347*0b57cec5SDimitry Andric // Helper functions. 348*0b57cec5SDimitry Andric 349*0b57cec5SDimitry Andric bool getCell(const RegisterSubReg &R, const CellMap &Inputs, LatticeCell &RC); 350*0b57cec5SDimitry Andric bool constToInt(const Constant *C, APInt &Val) const; 351*0b57cec5SDimitry Andric bool constToFloat(const Constant *C, APFloat &Val) const; 352*0b57cec5SDimitry Andric const ConstantInt *intToConst(const APInt &Val) const; 353*0b57cec5SDimitry Andric 354*0b57cec5SDimitry Andric // Compares. 355*0b57cec5SDimitry Andric bool evaluateCMPrr(uint32_t Cmp, const RegisterSubReg &R1, const RegisterSubReg &R2, 356*0b57cec5SDimitry Andric const CellMap &Inputs, bool &Result); 357*0b57cec5SDimitry Andric bool evaluateCMPri(uint32_t Cmp, const RegisterSubReg &R1, const APInt &A2, 358*0b57cec5SDimitry Andric const CellMap &Inputs, bool &Result); 359*0b57cec5SDimitry Andric bool evaluateCMPrp(uint32_t Cmp, const RegisterSubReg &R1, uint64_t Props2, 360*0b57cec5SDimitry Andric const CellMap &Inputs, bool &Result); 361*0b57cec5SDimitry Andric bool evaluateCMPii(uint32_t Cmp, const APInt &A1, const APInt &A2, 362*0b57cec5SDimitry Andric bool &Result); 363*0b57cec5SDimitry Andric bool evaluateCMPpi(uint32_t Cmp, uint32_t Props, const APInt &A2, 364*0b57cec5SDimitry Andric bool &Result); 365*0b57cec5SDimitry Andric bool evaluateCMPpp(uint32_t Cmp, uint32_t Props1, uint32_t Props2, 366*0b57cec5SDimitry Andric bool &Result); 367*0b57cec5SDimitry Andric 368*0b57cec5SDimitry Andric bool evaluateCOPY(const RegisterSubReg &R1, const CellMap &Inputs, 369*0b57cec5SDimitry Andric LatticeCell &Result); 370*0b57cec5SDimitry Andric 371*0b57cec5SDimitry Andric // Logical operations. 372*0b57cec5SDimitry Andric bool evaluateANDrr(const RegisterSubReg &R1, const RegisterSubReg &R2, 373*0b57cec5SDimitry Andric const CellMap &Inputs, LatticeCell &Result); 374*0b57cec5SDimitry Andric bool evaluateANDri(const RegisterSubReg &R1, const APInt &A2, 375*0b57cec5SDimitry Andric const CellMap &Inputs, LatticeCell &Result); 376*0b57cec5SDimitry Andric bool evaluateANDii(const APInt &A1, const APInt &A2, APInt &Result); 377*0b57cec5SDimitry Andric bool evaluateORrr(const RegisterSubReg &R1, const RegisterSubReg &R2, 378*0b57cec5SDimitry Andric const CellMap &Inputs, LatticeCell &Result); 379*0b57cec5SDimitry Andric bool evaluateORri(const RegisterSubReg &R1, const APInt &A2, 380*0b57cec5SDimitry Andric const CellMap &Inputs, LatticeCell &Result); 381*0b57cec5SDimitry Andric bool evaluateORii(const APInt &A1, const APInt &A2, APInt &Result); 382*0b57cec5SDimitry Andric bool evaluateXORrr(const RegisterSubReg &R1, const RegisterSubReg &R2, 383*0b57cec5SDimitry Andric const CellMap &Inputs, LatticeCell &Result); 384*0b57cec5SDimitry Andric bool evaluateXORri(const RegisterSubReg &R1, const APInt &A2, 385*0b57cec5SDimitry Andric const CellMap &Inputs, LatticeCell &Result); 386*0b57cec5SDimitry Andric bool evaluateXORii(const APInt &A1, const APInt &A2, APInt &Result); 387*0b57cec5SDimitry Andric 388*0b57cec5SDimitry Andric // Extensions. 389*0b57cec5SDimitry Andric bool evaluateZEXTr(const RegisterSubReg &R1, unsigned Width, unsigned Bits, 390*0b57cec5SDimitry Andric const CellMap &Inputs, LatticeCell &Result); 391*0b57cec5SDimitry Andric bool evaluateZEXTi(const APInt &A1, unsigned Width, unsigned Bits, 392*0b57cec5SDimitry Andric APInt &Result); 393*0b57cec5SDimitry Andric bool evaluateSEXTr(const RegisterSubReg &R1, unsigned Width, unsigned Bits, 394*0b57cec5SDimitry Andric const CellMap &Inputs, LatticeCell &Result); 395*0b57cec5SDimitry Andric bool evaluateSEXTi(const APInt &A1, unsigned Width, unsigned Bits, 396*0b57cec5SDimitry Andric APInt &Result); 397*0b57cec5SDimitry Andric 398*0b57cec5SDimitry Andric // Leading/trailing bits. 399*0b57cec5SDimitry Andric bool evaluateCLBr(const RegisterSubReg &R1, bool Zeros, bool Ones, 400*0b57cec5SDimitry Andric const CellMap &Inputs, LatticeCell &Result); 401*0b57cec5SDimitry Andric bool evaluateCLBi(const APInt &A1, bool Zeros, bool Ones, APInt &Result); 402*0b57cec5SDimitry Andric bool evaluateCTBr(const RegisterSubReg &R1, bool Zeros, bool Ones, 403*0b57cec5SDimitry Andric const CellMap &Inputs, LatticeCell &Result); 404*0b57cec5SDimitry Andric bool evaluateCTBi(const APInt &A1, bool Zeros, bool Ones, APInt &Result); 405*0b57cec5SDimitry Andric 406*0b57cec5SDimitry Andric // Bitfield extract. 407*0b57cec5SDimitry Andric bool evaluateEXTRACTr(const RegisterSubReg &R1, unsigned Width, unsigned Bits, 408*0b57cec5SDimitry Andric unsigned Offset, bool Signed, const CellMap &Inputs, 409*0b57cec5SDimitry Andric LatticeCell &Result); 410*0b57cec5SDimitry Andric bool evaluateEXTRACTi(const APInt &A1, unsigned Bits, unsigned Offset, 411*0b57cec5SDimitry Andric bool Signed, APInt &Result); 412*0b57cec5SDimitry Andric // Vector operations. 413*0b57cec5SDimitry Andric bool evaluateSplatr(const RegisterSubReg &R1, unsigned Bits, unsigned Count, 414*0b57cec5SDimitry Andric const CellMap &Inputs, LatticeCell &Result); 415*0b57cec5SDimitry Andric bool evaluateSplati(const APInt &A1, unsigned Bits, unsigned Count, 416*0b57cec5SDimitry Andric APInt &Result); 417*0b57cec5SDimitry Andric }; 418*0b57cec5SDimitry Andric 419*0b57cec5SDimitry Andric } // end anonymous namespace 420*0b57cec5SDimitry Andric 421*0b57cec5SDimitry Andric uint32_t ConstantProperties::deduce(const Constant *C) { 422*0b57cec5SDimitry Andric if (isa<ConstantInt>(C)) { 423*0b57cec5SDimitry Andric const ConstantInt *CI = cast<ConstantInt>(C); 424*0b57cec5SDimitry Andric if (CI->isZero()) 425*0b57cec5SDimitry Andric return Zero | PosOrZero | NegOrZero | Finite; 426*0b57cec5SDimitry Andric uint32_t Props = (NonZero | Finite); 427*0b57cec5SDimitry Andric if (CI->isNegative()) 428*0b57cec5SDimitry Andric return Props | NegOrZero; 429*0b57cec5SDimitry Andric return Props | PosOrZero; 430*0b57cec5SDimitry Andric } 431*0b57cec5SDimitry Andric 432*0b57cec5SDimitry Andric if (isa<ConstantFP>(C)) { 433*0b57cec5SDimitry Andric const ConstantFP *CF = cast<ConstantFP>(C); 434*0b57cec5SDimitry Andric uint32_t Props = CF->isNegative() ? (NegOrZero|NonZero) 435*0b57cec5SDimitry Andric : PosOrZero; 436*0b57cec5SDimitry Andric if (CF->isZero()) 437*0b57cec5SDimitry Andric return (Props & ~NumericProperties) | (Zero|Finite); 438*0b57cec5SDimitry Andric Props = (Props & ~NumericProperties) | NonZero; 439*0b57cec5SDimitry Andric if (CF->isNaN()) 440*0b57cec5SDimitry Andric return (Props & ~NumericProperties) | NaN; 441*0b57cec5SDimitry Andric const APFloat &Val = CF->getValueAPF(); 442*0b57cec5SDimitry Andric if (Val.isInfinity()) 443*0b57cec5SDimitry Andric return (Props & ~NumericProperties) | Infinity; 444*0b57cec5SDimitry Andric Props |= Finite; 445*0b57cec5SDimitry Andric return Props; 446*0b57cec5SDimitry Andric } 447*0b57cec5SDimitry Andric 448*0b57cec5SDimitry Andric return Unknown; 449*0b57cec5SDimitry Andric } 450*0b57cec5SDimitry Andric 451*0b57cec5SDimitry Andric // Convert a cell from a set of specific values to a cell that tracks 452*0b57cec5SDimitry Andric // properties. 453*0b57cec5SDimitry Andric bool LatticeCell::convertToProperty() { 454*0b57cec5SDimitry Andric if (isProperty()) 455*0b57cec5SDimitry Andric return false; 456*0b57cec5SDimitry Andric // Corner case: converting a fresh (top) cell to "special". 457*0b57cec5SDimitry Andric // This can happen, when adding a property to a top cell. 458*0b57cec5SDimitry Andric uint32_t Everything = ConstantProperties::Everything; 459*0b57cec5SDimitry Andric uint32_t Ps = !isTop() ? properties() 460*0b57cec5SDimitry Andric : Everything; 461*0b57cec5SDimitry Andric if (Ps != ConstantProperties::Unknown) { 462*0b57cec5SDimitry Andric Properties = Ps; 463*0b57cec5SDimitry Andric setProperty(); 464*0b57cec5SDimitry Andric } else { 465*0b57cec5SDimitry Andric setBottom(); 466*0b57cec5SDimitry Andric } 467*0b57cec5SDimitry Andric return true; 468*0b57cec5SDimitry Andric } 469*0b57cec5SDimitry Andric 470*0b57cec5SDimitry Andric #ifndef NDEBUG 471*0b57cec5SDimitry Andric void LatticeCell::print(raw_ostream &os) const { 472*0b57cec5SDimitry Andric if (isProperty()) { 473*0b57cec5SDimitry Andric os << "{ "; 474*0b57cec5SDimitry Andric uint32_t Ps = properties(); 475*0b57cec5SDimitry Andric if (Ps & ConstantProperties::Zero) 476*0b57cec5SDimitry Andric os << "zero "; 477*0b57cec5SDimitry Andric if (Ps & ConstantProperties::NonZero) 478*0b57cec5SDimitry Andric os << "nonzero "; 479*0b57cec5SDimitry Andric if (Ps & ConstantProperties::Finite) 480*0b57cec5SDimitry Andric os << "finite "; 481*0b57cec5SDimitry Andric if (Ps & ConstantProperties::Infinity) 482*0b57cec5SDimitry Andric os << "infinity "; 483*0b57cec5SDimitry Andric if (Ps & ConstantProperties::NaN) 484*0b57cec5SDimitry Andric os << "nan "; 485*0b57cec5SDimitry Andric if (Ps & ConstantProperties::PosOrZero) 486*0b57cec5SDimitry Andric os << "poz "; 487*0b57cec5SDimitry Andric if (Ps & ConstantProperties::NegOrZero) 488*0b57cec5SDimitry Andric os << "nez "; 489*0b57cec5SDimitry Andric os << '}'; 490*0b57cec5SDimitry Andric return; 491*0b57cec5SDimitry Andric } 492*0b57cec5SDimitry Andric 493*0b57cec5SDimitry Andric os << "{ "; 494*0b57cec5SDimitry Andric if (isBottom()) { 495*0b57cec5SDimitry Andric os << "bottom"; 496*0b57cec5SDimitry Andric } else if (isTop()) { 497*0b57cec5SDimitry Andric os << "top"; 498*0b57cec5SDimitry Andric } else { 499*0b57cec5SDimitry Andric for (unsigned i = 0; i < size(); ++i) { 500*0b57cec5SDimitry Andric const Constant *C = Values[i]; 501*0b57cec5SDimitry Andric if (i != 0) 502*0b57cec5SDimitry Andric os << ", "; 503*0b57cec5SDimitry Andric C->print(os); 504*0b57cec5SDimitry Andric } 505*0b57cec5SDimitry Andric } 506*0b57cec5SDimitry Andric os << " }"; 507*0b57cec5SDimitry Andric } 508*0b57cec5SDimitry Andric #endif 509*0b57cec5SDimitry Andric 510*0b57cec5SDimitry Andric // "Meet" operation on two cells. This is the key of the propagation 511*0b57cec5SDimitry Andric // algorithm. 512*0b57cec5SDimitry Andric bool LatticeCell::meet(const LatticeCell &L) { 513*0b57cec5SDimitry Andric bool Changed = false; 514*0b57cec5SDimitry Andric if (L.isBottom()) 515*0b57cec5SDimitry Andric Changed = setBottom(); 516*0b57cec5SDimitry Andric if (isBottom() || L.isTop()) 517*0b57cec5SDimitry Andric return Changed; 518*0b57cec5SDimitry Andric if (isTop()) { 519*0b57cec5SDimitry Andric *this = L; 520*0b57cec5SDimitry Andric // L can be neither Top nor Bottom, so *this must have changed. 521*0b57cec5SDimitry Andric return true; 522*0b57cec5SDimitry Andric } 523*0b57cec5SDimitry Andric 524*0b57cec5SDimitry Andric // Top/bottom cases covered. Need to integrate L's set into ours. 525*0b57cec5SDimitry Andric if (L.isProperty()) 526*0b57cec5SDimitry Andric return add(L.properties()); 527*0b57cec5SDimitry Andric for (unsigned i = 0; i < L.size(); ++i) { 528*0b57cec5SDimitry Andric const Constant *LC = L.Values[i]; 529*0b57cec5SDimitry Andric Changed |= add(LC); 530*0b57cec5SDimitry Andric } 531*0b57cec5SDimitry Andric return Changed; 532*0b57cec5SDimitry Andric } 533*0b57cec5SDimitry Andric 534*0b57cec5SDimitry Andric // Add a new constant to the cell. This is actually where the cell update 535*0b57cec5SDimitry Andric // happens. If a cell has room for more constants, the new constant is added. 536*0b57cec5SDimitry Andric // Otherwise, the cell is converted to a "property" cell (i.e. a cell that 537*0b57cec5SDimitry Andric // will track properties of the associated values, and not the values 538*0b57cec5SDimitry Andric // themselves. Care is taken to handle special cases, like "bottom", etc. 539*0b57cec5SDimitry Andric bool LatticeCell::add(const Constant *LC) { 540*0b57cec5SDimitry Andric assert(LC); 541*0b57cec5SDimitry Andric if (isBottom()) 542*0b57cec5SDimitry Andric return false; 543*0b57cec5SDimitry Andric 544*0b57cec5SDimitry Andric if (!isProperty()) { 545*0b57cec5SDimitry Andric // Cell is not special. Try to add the constant here first, 546*0b57cec5SDimitry Andric // if there is room. 547*0b57cec5SDimitry Andric unsigned Index = 0; 548*0b57cec5SDimitry Andric while (Index < Size) { 549*0b57cec5SDimitry Andric const Constant *C = Values[Index]; 550*0b57cec5SDimitry Andric // If the constant is already here, no change is needed. 551*0b57cec5SDimitry Andric if (C == LC) 552*0b57cec5SDimitry Andric return false; 553*0b57cec5SDimitry Andric Index++; 554*0b57cec5SDimitry Andric } 555*0b57cec5SDimitry Andric if (Index < MaxCellSize) { 556*0b57cec5SDimitry Andric Values[Index] = LC; 557*0b57cec5SDimitry Andric Kind = Normal; 558*0b57cec5SDimitry Andric Size++; 559*0b57cec5SDimitry Andric return true; 560*0b57cec5SDimitry Andric } 561*0b57cec5SDimitry Andric } 562*0b57cec5SDimitry Andric 563*0b57cec5SDimitry Andric bool Changed = false; 564*0b57cec5SDimitry Andric 565*0b57cec5SDimitry Andric // This cell is special, or is not special, but is full. After this 566*0b57cec5SDimitry Andric // it will be special. 567*0b57cec5SDimitry Andric Changed = convertToProperty(); 568*0b57cec5SDimitry Andric uint32_t Ps = properties(); 569*0b57cec5SDimitry Andric uint32_t NewPs = Ps & ConstantProperties::deduce(LC); 570*0b57cec5SDimitry Andric if (NewPs == ConstantProperties::Unknown) { 571*0b57cec5SDimitry Andric setBottom(); 572*0b57cec5SDimitry Andric return true; 573*0b57cec5SDimitry Andric } 574*0b57cec5SDimitry Andric if (Ps != NewPs) { 575*0b57cec5SDimitry Andric Properties = NewPs; 576*0b57cec5SDimitry Andric Changed = true; 577*0b57cec5SDimitry Andric } 578*0b57cec5SDimitry Andric return Changed; 579*0b57cec5SDimitry Andric } 580*0b57cec5SDimitry Andric 581*0b57cec5SDimitry Andric // Add a property to the cell. This will force the cell to become a property- 582*0b57cec5SDimitry Andric // tracking cell. 583*0b57cec5SDimitry Andric bool LatticeCell::add(uint32_t Property) { 584*0b57cec5SDimitry Andric bool Changed = convertToProperty(); 585*0b57cec5SDimitry Andric uint32_t Ps = properties(); 586*0b57cec5SDimitry Andric if (Ps == (Ps & Property)) 587*0b57cec5SDimitry Andric return Changed; 588*0b57cec5SDimitry Andric Properties = Property & Ps; 589*0b57cec5SDimitry Andric return true; 590*0b57cec5SDimitry Andric } 591*0b57cec5SDimitry Andric 592*0b57cec5SDimitry Andric // Return the properties of the values in the cell. This is valid for any 593*0b57cec5SDimitry Andric // cell, and does not alter the cell itself. 594*0b57cec5SDimitry Andric uint32_t LatticeCell::properties() const { 595*0b57cec5SDimitry Andric if (isProperty()) 596*0b57cec5SDimitry Andric return Properties; 597*0b57cec5SDimitry Andric assert(!isTop() && "Should not call this for a top cell"); 598*0b57cec5SDimitry Andric if (isBottom()) 599*0b57cec5SDimitry Andric return ConstantProperties::Unknown; 600*0b57cec5SDimitry Andric 601*0b57cec5SDimitry Andric assert(size() > 0 && "Empty cell"); 602*0b57cec5SDimitry Andric uint32_t Ps = ConstantProperties::deduce(Values[0]); 603*0b57cec5SDimitry Andric for (unsigned i = 1; i < size(); ++i) { 604*0b57cec5SDimitry Andric if (Ps == ConstantProperties::Unknown) 605*0b57cec5SDimitry Andric break; 606*0b57cec5SDimitry Andric Ps &= ConstantProperties::deduce(Values[i]); 607*0b57cec5SDimitry Andric } 608*0b57cec5SDimitry Andric return Ps; 609*0b57cec5SDimitry Andric } 610*0b57cec5SDimitry Andric 611*0b57cec5SDimitry Andric #ifndef NDEBUG 612*0b57cec5SDimitry Andric void MachineConstPropagator::CellMap::print(raw_ostream &os, 613*0b57cec5SDimitry Andric const TargetRegisterInfo &TRI) const { 614*0b57cec5SDimitry Andric for (auto &I : Map) 615*0b57cec5SDimitry Andric dbgs() << " " << printReg(I.first, &TRI) << " -> " << I.second << '\n'; 616*0b57cec5SDimitry Andric } 617*0b57cec5SDimitry Andric #endif 618*0b57cec5SDimitry Andric 619*0b57cec5SDimitry Andric void MachineConstPropagator::visitPHI(const MachineInstr &PN) { 620*0b57cec5SDimitry Andric const MachineBasicBlock *MB = PN.getParent(); 621*0b57cec5SDimitry Andric unsigned MBN = MB->getNumber(); 622*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Visiting FI(" << printMBBReference(*MB) << "): " << PN); 623*0b57cec5SDimitry Andric 624*0b57cec5SDimitry Andric const MachineOperand &MD = PN.getOperand(0); 625*0b57cec5SDimitry Andric RegisterSubReg DefR(MD); 626*0b57cec5SDimitry Andric assert(TargetRegisterInfo::isVirtualRegister(DefR.Reg)); 627*0b57cec5SDimitry Andric 628*0b57cec5SDimitry Andric bool Changed = false; 629*0b57cec5SDimitry Andric 630*0b57cec5SDimitry Andric // If the def has a sub-register, set the corresponding cell to "bottom". 631*0b57cec5SDimitry Andric if (DefR.SubReg) { 632*0b57cec5SDimitry Andric Bottomize: 633*0b57cec5SDimitry Andric const LatticeCell &T = Cells.get(DefR.Reg); 634*0b57cec5SDimitry Andric Changed = !T.isBottom(); 635*0b57cec5SDimitry Andric Cells.update(DefR.Reg, Bottom); 636*0b57cec5SDimitry Andric if (Changed) 637*0b57cec5SDimitry Andric visitUsesOf(DefR.Reg); 638*0b57cec5SDimitry Andric return; 639*0b57cec5SDimitry Andric } 640*0b57cec5SDimitry Andric 641*0b57cec5SDimitry Andric LatticeCell DefC = Cells.get(DefR.Reg); 642*0b57cec5SDimitry Andric 643*0b57cec5SDimitry Andric for (unsigned i = 1, n = PN.getNumOperands(); i < n; i += 2) { 644*0b57cec5SDimitry Andric const MachineBasicBlock *PB = PN.getOperand(i+1).getMBB(); 645*0b57cec5SDimitry Andric unsigned PBN = PB->getNumber(); 646*0b57cec5SDimitry Andric if (!EdgeExec.count(CFGEdge(PBN, MBN))) { 647*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " edge " << printMBBReference(*PB) << "->" 648*0b57cec5SDimitry Andric << printMBBReference(*MB) << " not executable\n"); 649*0b57cec5SDimitry Andric continue; 650*0b57cec5SDimitry Andric } 651*0b57cec5SDimitry Andric const MachineOperand &SO = PN.getOperand(i); 652*0b57cec5SDimitry Andric RegisterSubReg UseR(SO); 653*0b57cec5SDimitry Andric // If the input is not a virtual register, we don't really know what 654*0b57cec5SDimitry Andric // value it holds. 655*0b57cec5SDimitry Andric if (!TargetRegisterInfo::isVirtualRegister(UseR.Reg)) 656*0b57cec5SDimitry Andric goto Bottomize; 657*0b57cec5SDimitry Andric // If there is no cell for an input register, it means top. 658*0b57cec5SDimitry Andric if (!Cells.has(UseR.Reg)) 659*0b57cec5SDimitry Andric continue; 660*0b57cec5SDimitry Andric 661*0b57cec5SDimitry Andric LatticeCell SrcC; 662*0b57cec5SDimitry Andric bool Eval = MCE.evaluate(UseR, Cells.get(UseR.Reg), SrcC); 663*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " edge from " << printMBBReference(*PB) << ": " 664*0b57cec5SDimitry Andric << printReg(UseR.Reg, &MCE.TRI, UseR.SubReg) << SrcC 665*0b57cec5SDimitry Andric << '\n'); 666*0b57cec5SDimitry Andric Changed |= Eval ? DefC.meet(SrcC) 667*0b57cec5SDimitry Andric : DefC.setBottom(); 668*0b57cec5SDimitry Andric Cells.update(DefR.Reg, DefC); 669*0b57cec5SDimitry Andric if (DefC.isBottom()) 670*0b57cec5SDimitry Andric break; 671*0b57cec5SDimitry Andric } 672*0b57cec5SDimitry Andric if (Changed) 673*0b57cec5SDimitry Andric visitUsesOf(DefR.Reg); 674*0b57cec5SDimitry Andric } 675*0b57cec5SDimitry Andric 676*0b57cec5SDimitry Andric void MachineConstPropagator::visitNonBranch(const MachineInstr &MI) { 677*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Visiting MI(" << printMBBReference(*MI.getParent()) 678*0b57cec5SDimitry Andric << "): " << MI); 679*0b57cec5SDimitry Andric CellMap Outputs; 680*0b57cec5SDimitry Andric bool Eval = MCE.evaluate(MI, Cells, Outputs); 681*0b57cec5SDimitry Andric LLVM_DEBUG({ 682*0b57cec5SDimitry Andric if (Eval) { 683*0b57cec5SDimitry Andric dbgs() << " outputs:"; 684*0b57cec5SDimitry Andric for (auto &I : Outputs) 685*0b57cec5SDimitry Andric dbgs() << ' ' << I.second; 686*0b57cec5SDimitry Andric dbgs() << '\n'; 687*0b57cec5SDimitry Andric } 688*0b57cec5SDimitry Andric }); 689*0b57cec5SDimitry Andric 690*0b57cec5SDimitry Andric // Update outputs. If the value was not computed, set all the 691*0b57cec5SDimitry Andric // def cells to bottom. 692*0b57cec5SDimitry Andric for (const MachineOperand &MO : MI.operands()) { 693*0b57cec5SDimitry Andric if (!MO.isReg() || !MO.isDef()) 694*0b57cec5SDimitry Andric continue; 695*0b57cec5SDimitry Andric RegisterSubReg DefR(MO); 696*0b57cec5SDimitry Andric // Only track virtual registers. 697*0b57cec5SDimitry Andric if (!TargetRegisterInfo::isVirtualRegister(DefR.Reg)) 698*0b57cec5SDimitry Andric continue; 699*0b57cec5SDimitry Andric bool Changed = false; 700*0b57cec5SDimitry Andric // If the evaluation failed, set cells for all output registers to bottom. 701*0b57cec5SDimitry Andric if (!Eval) { 702*0b57cec5SDimitry Andric const LatticeCell &T = Cells.get(DefR.Reg); 703*0b57cec5SDimitry Andric Changed = !T.isBottom(); 704*0b57cec5SDimitry Andric Cells.update(DefR.Reg, Bottom); 705*0b57cec5SDimitry Andric } else { 706*0b57cec5SDimitry Andric // Find the corresponding cell in the computed outputs. 707*0b57cec5SDimitry Andric // If it's not there, go on to the next def. 708*0b57cec5SDimitry Andric if (!Outputs.has(DefR.Reg)) 709*0b57cec5SDimitry Andric continue; 710*0b57cec5SDimitry Andric LatticeCell RC = Cells.get(DefR.Reg); 711*0b57cec5SDimitry Andric Changed = RC.meet(Outputs.get(DefR.Reg)); 712*0b57cec5SDimitry Andric Cells.update(DefR.Reg, RC); 713*0b57cec5SDimitry Andric } 714*0b57cec5SDimitry Andric if (Changed) 715*0b57cec5SDimitry Andric visitUsesOf(DefR.Reg); 716*0b57cec5SDimitry Andric } 717*0b57cec5SDimitry Andric } 718*0b57cec5SDimitry Andric 719*0b57cec5SDimitry Andric // Starting at a given branch, visit remaining branches in the block. 720*0b57cec5SDimitry Andric // Traverse over the subsequent branches for as long as the preceding one 721*0b57cec5SDimitry Andric // can fall through. Add all the possible targets to the flow work queue, 722*0b57cec5SDimitry Andric // including the potential fall-through to the layout-successor block. 723*0b57cec5SDimitry Andric void MachineConstPropagator::visitBranchesFrom(const MachineInstr &BrI) { 724*0b57cec5SDimitry Andric const MachineBasicBlock &B = *BrI.getParent(); 725*0b57cec5SDimitry Andric unsigned MBN = B.getNumber(); 726*0b57cec5SDimitry Andric MachineBasicBlock::const_iterator It = BrI.getIterator(); 727*0b57cec5SDimitry Andric MachineBasicBlock::const_iterator End = B.end(); 728*0b57cec5SDimitry Andric 729*0b57cec5SDimitry Andric SetVector<const MachineBasicBlock*> Targets; 730*0b57cec5SDimitry Andric bool EvalOk = true, FallsThru = true; 731*0b57cec5SDimitry Andric while (It != End) { 732*0b57cec5SDimitry Andric const MachineInstr &MI = *It; 733*0b57cec5SDimitry Andric InstrExec.insert(&MI); 734*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Visiting " << (EvalOk ? "BR" : "br") << "(" 735*0b57cec5SDimitry Andric << printMBBReference(B) << "): " << MI); 736*0b57cec5SDimitry Andric // Do not evaluate subsequent branches if the evaluation of any of the 737*0b57cec5SDimitry Andric // previous branches failed. Keep iterating over the branches only 738*0b57cec5SDimitry Andric // to mark them as executable. 739*0b57cec5SDimitry Andric EvalOk = EvalOk && MCE.evaluate(MI, Cells, Targets, FallsThru); 740*0b57cec5SDimitry Andric if (!EvalOk) 741*0b57cec5SDimitry Andric FallsThru = true; 742*0b57cec5SDimitry Andric if (!FallsThru) 743*0b57cec5SDimitry Andric break; 744*0b57cec5SDimitry Andric ++It; 745*0b57cec5SDimitry Andric } 746*0b57cec5SDimitry Andric 747*0b57cec5SDimitry Andric if (EvalOk) { 748*0b57cec5SDimitry Andric // Need to add all CFG successors that lead to EH landing pads. 749*0b57cec5SDimitry Andric // There won't be explicit branches to these blocks, but they must 750*0b57cec5SDimitry Andric // be processed. 751*0b57cec5SDimitry Andric for (const MachineBasicBlock *SB : B.successors()) { 752*0b57cec5SDimitry Andric if (SB->isEHPad()) 753*0b57cec5SDimitry Andric Targets.insert(SB); 754*0b57cec5SDimitry Andric } 755*0b57cec5SDimitry Andric if (FallsThru) { 756*0b57cec5SDimitry Andric const MachineFunction &MF = *B.getParent(); 757*0b57cec5SDimitry Andric MachineFunction::const_iterator BI = B.getIterator(); 758*0b57cec5SDimitry Andric MachineFunction::const_iterator Next = std::next(BI); 759*0b57cec5SDimitry Andric if (Next != MF.end()) 760*0b57cec5SDimitry Andric Targets.insert(&*Next); 761*0b57cec5SDimitry Andric } 762*0b57cec5SDimitry Andric } else { 763*0b57cec5SDimitry Andric // If the evaluation of the branches failed, make "Targets" to be the 764*0b57cec5SDimitry Andric // set of all successors of the block from the CFG. 765*0b57cec5SDimitry Andric // If the evaluation succeeded for all visited branches, then if the 766*0b57cec5SDimitry Andric // last one set "FallsThru", then add an edge to the layout successor 767*0b57cec5SDimitry Andric // to the targets. 768*0b57cec5SDimitry Andric Targets.clear(); 769*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " failed to evaluate a branch...adding all CFG " 770*0b57cec5SDimitry Andric "successors\n"); 771*0b57cec5SDimitry Andric for (const MachineBasicBlock *SB : B.successors()) 772*0b57cec5SDimitry Andric Targets.insert(SB); 773*0b57cec5SDimitry Andric } 774*0b57cec5SDimitry Andric 775*0b57cec5SDimitry Andric for (const MachineBasicBlock *TB : Targets) { 776*0b57cec5SDimitry Andric unsigned TBN = TB->getNumber(); 777*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " pushing edge " << printMBBReference(B) << " -> " 778*0b57cec5SDimitry Andric << printMBBReference(*TB) << "\n"); 779*0b57cec5SDimitry Andric FlowQ.push(CFGEdge(MBN, TBN)); 780*0b57cec5SDimitry Andric } 781*0b57cec5SDimitry Andric } 782*0b57cec5SDimitry Andric 783*0b57cec5SDimitry Andric void MachineConstPropagator::visitUsesOf(unsigned Reg) { 784*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Visiting uses of " << printReg(Reg, &MCE.TRI) 785*0b57cec5SDimitry Andric << Cells.get(Reg) << '\n'); 786*0b57cec5SDimitry Andric for (MachineInstr &MI : MRI->use_nodbg_instructions(Reg)) { 787*0b57cec5SDimitry Andric // Do not process non-executable instructions. They can become exceutable 788*0b57cec5SDimitry Andric // later (via a flow-edge in the work queue). In such case, the instruc- 789*0b57cec5SDimitry Andric // tion will be visited at that time. 790*0b57cec5SDimitry Andric if (!InstrExec.count(&MI)) 791*0b57cec5SDimitry Andric continue; 792*0b57cec5SDimitry Andric if (MI.isPHI()) 793*0b57cec5SDimitry Andric visitPHI(MI); 794*0b57cec5SDimitry Andric else if (!MI.isBranch()) 795*0b57cec5SDimitry Andric visitNonBranch(MI); 796*0b57cec5SDimitry Andric else 797*0b57cec5SDimitry Andric visitBranchesFrom(MI); 798*0b57cec5SDimitry Andric } 799*0b57cec5SDimitry Andric } 800*0b57cec5SDimitry Andric 801*0b57cec5SDimitry Andric bool MachineConstPropagator::computeBlockSuccessors(const MachineBasicBlock *MB, 802*0b57cec5SDimitry Andric SetVector<const MachineBasicBlock*> &Targets) { 803*0b57cec5SDimitry Andric MachineBasicBlock::const_iterator FirstBr = MB->end(); 804*0b57cec5SDimitry Andric for (const MachineInstr &MI : *MB) { 805*0b57cec5SDimitry Andric if (MI.isDebugInstr()) 806*0b57cec5SDimitry Andric continue; 807*0b57cec5SDimitry Andric if (MI.isBranch()) { 808*0b57cec5SDimitry Andric FirstBr = MI.getIterator(); 809*0b57cec5SDimitry Andric break; 810*0b57cec5SDimitry Andric } 811*0b57cec5SDimitry Andric } 812*0b57cec5SDimitry Andric 813*0b57cec5SDimitry Andric Targets.clear(); 814*0b57cec5SDimitry Andric MachineBasicBlock::const_iterator End = MB->end(); 815*0b57cec5SDimitry Andric 816*0b57cec5SDimitry Andric bool DoNext = true; 817*0b57cec5SDimitry Andric for (MachineBasicBlock::const_iterator I = FirstBr; I != End; ++I) { 818*0b57cec5SDimitry Andric const MachineInstr &MI = *I; 819*0b57cec5SDimitry Andric // Can there be debug instructions between branches? 820*0b57cec5SDimitry Andric if (MI.isDebugInstr()) 821*0b57cec5SDimitry Andric continue; 822*0b57cec5SDimitry Andric if (!InstrExec.count(&MI)) 823*0b57cec5SDimitry Andric continue; 824*0b57cec5SDimitry Andric bool Eval = MCE.evaluate(MI, Cells, Targets, DoNext); 825*0b57cec5SDimitry Andric if (!Eval) 826*0b57cec5SDimitry Andric return false; 827*0b57cec5SDimitry Andric if (!DoNext) 828*0b57cec5SDimitry Andric break; 829*0b57cec5SDimitry Andric } 830*0b57cec5SDimitry Andric // If the last branch could fall-through, add block's layout successor. 831*0b57cec5SDimitry Andric if (DoNext) { 832*0b57cec5SDimitry Andric MachineFunction::const_iterator BI = MB->getIterator(); 833*0b57cec5SDimitry Andric MachineFunction::const_iterator NextI = std::next(BI); 834*0b57cec5SDimitry Andric if (NextI != MB->getParent()->end()) 835*0b57cec5SDimitry Andric Targets.insert(&*NextI); 836*0b57cec5SDimitry Andric } 837*0b57cec5SDimitry Andric 838*0b57cec5SDimitry Andric // Add all the EH landing pads. 839*0b57cec5SDimitry Andric for (const MachineBasicBlock *SB : MB->successors()) 840*0b57cec5SDimitry Andric if (SB->isEHPad()) 841*0b57cec5SDimitry Andric Targets.insert(SB); 842*0b57cec5SDimitry Andric 843*0b57cec5SDimitry Andric return true; 844*0b57cec5SDimitry Andric } 845*0b57cec5SDimitry Andric 846*0b57cec5SDimitry Andric void MachineConstPropagator::removeCFGEdge(MachineBasicBlock *From, 847*0b57cec5SDimitry Andric MachineBasicBlock *To) { 848*0b57cec5SDimitry Andric // First, remove the CFG successor/predecessor information. 849*0b57cec5SDimitry Andric From->removeSuccessor(To); 850*0b57cec5SDimitry Andric // Remove all corresponding PHI operands in the To block. 851*0b57cec5SDimitry Andric for (auto I = To->begin(), E = To->getFirstNonPHI(); I != E; ++I) { 852*0b57cec5SDimitry Andric MachineInstr *PN = &*I; 853*0b57cec5SDimitry Andric // reg0 = PHI reg1, bb2, reg3, bb4, ... 854*0b57cec5SDimitry Andric int N = PN->getNumOperands()-2; 855*0b57cec5SDimitry Andric while (N > 0) { 856*0b57cec5SDimitry Andric if (PN->getOperand(N+1).getMBB() == From) { 857*0b57cec5SDimitry Andric PN->RemoveOperand(N+1); 858*0b57cec5SDimitry Andric PN->RemoveOperand(N); 859*0b57cec5SDimitry Andric } 860*0b57cec5SDimitry Andric N -= 2; 861*0b57cec5SDimitry Andric } 862*0b57cec5SDimitry Andric } 863*0b57cec5SDimitry Andric } 864*0b57cec5SDimitry Andric 865*0b57cec5SDimitry Andric void MachineConstPropagator::propagate(MachineFunction &MF) { 866*0b57cec5SDimitry Andric MachineBasicBlock *Entry = GraphTraits<MachineFunction*>::getEntryNode(&MF); 867*0b57cec5SDimitry Andric unsigned EntryNum = Entry->getNumber(); 868*0b57cec5SDimitry Andric 869*0b57cec5SDimitry Andric // Start with a fake edge, just to process the entry node. 870*0b57cec5SDimitry Andric FlowQ.push(CFGEdge(EntryNum, EntryNum)); 871*0b57cec5SDimitry Andric 872*0b57cec5SDimitry Andric while (!FlowQ.empty()) { 873*0b57cec5SDimitry Andric CFGEdge Edge = FlowQ.front(); 874*0b57cec5SDimitry Andric FlowQ.pop(); 875*0b57cec5SDimitry Andric 876*0b57cec5SDimitry Andric LLVM_DEBUG( 877*0b57cec5SDimitry Andric dbgs() << "Picked edge " 878*0b57cec5SDimitry Andric << printMBBReference(*MF.getBlockNumbered(Edge.first)) << "->" 879*0b57cec5SDimitry Andric << printMBBReference(*MF.getBlockNumbered(Edge.second)) << '\n'); 880*0b57cec5SDimitry Andric if (Edge.first != EntryNum) 881*0b57cec5SDimitry Andric if (EdgeExec.count(Edge)) 882*0b57cec5SDimitry Andric continue; 883*0b57cec5SDimitry Andric EdgeExec.insert(Edge); 884*0b57cec5SDimitry Andric MachineBasicBlock *SB = MF.getBlockNumbered(Edge.second); 885*0b57cec5SDimitry Andric 886*0b57cec5SDimitry Andric // Process the block in three stages: 887*0b57cec5SDimitry Andric // - visit all PHI nodes, 888*0b57cec5SDimitry Andric // - visit all non-branch instructions, 889*0b57cec5SDimitry Andric // - visit block branches. 890*0b57cec5SDimitry Andric MachineBasicBlock::const_iterator It = SB->begin(), End = SB->end(); 891*0b57cec5SDimitry Andric 892*0b57cec5SDimitry Andric // Visit PHI nodes in the successor block. 893*0b57cec5SDimitry Andric while (It != End && It->isPHI()) { 894*0b57cec5SDimitry Andric InstrExec.insert(&*It); 895*0b57cec5SDimitry Andric visitPHI(*It); 896*0b57cec5SDimitry Andric ++It; 897*0b57cec5SDimitry Andric } 898*0b57cec5SDimitry Andric 899*0b57cec5SDimitry Andric // If the successor block just became executable, visit all instructions. 900*0b57cec5SDimitry Andric // To see if this is the first time we're visiting it, check the first 901*0b57cec5SDimitry Andric // non-debug instruction to see if it is executable. 902*0b57cec5SDimitry Andric while (It != End && It->isDebugInstr()) 903*0b57cec5SDimitry Andric ++It; 904*0b57cec5SDimitry Andric assert(It == End || !It->isPHI()); 905*0b57cec5SDimitry Andric // If this block has been visited, go on to the next one. 906*0b57cec5SDimitry Andric if (It != End && InstrExec.count(&*It)) 907*0b57cec5SDimitry Andric continue; 908*0b57cec5SDimitry Andric // For now, scan all non-branch instructions. Branches require different 909*0b57cec5SDimitry Andric // processing. 910*0b57cec5SDimitry Andric while (It != End && !It->isBranch()) { 911*0b57cec5SDimitry Andric if (!It->isDebugInstr()) { 912*0b57cec5SDimitry Andric InstrExec.insert(&*It); 913*0b57cec5SDimitry Andric visitNonBranch(*It); 914*0b57cec5SDimitry Andric } 915*0b57cec5SDimitry Andric ++It; 916*0b57cec5SDimitry Andric } 917*0b57cec5SDimitry Andric 918*0b57cec5SDimitry Andric // Time to process the end of the block. This is different from 919*0b57cec5SDimitry Andric // processing regular (non-branch) instructions, because there can 920*0b57cec5SDimitry Andric // be multiple branches in a block, and they can cause the block to 921*0b57cec5SDimitry Andric // terminate early. 922*0b57cec5SDimitry Andric if (It != End) { 923*0b57cec5SDimitry Andric visitBranchesFrom(*It); 924*0b57cec5SDimitry Andric } else { 925*0b57cec5SDimitry Andric // If the block didn't have a branch, add all successor edges to the 926*0b57cec5SDimitry Andric // work queue. (There should really be only one successor in such case.) 927*0b57cec5SDimitry Andric unsigned SBN = SB->getNumber(); 928*0b57cec5SDimitry Andric for (const MachineBasicBlock *SSB : SB->successors()) 929*0b57cec5SDimitry Andric FlowQ.push(CFGEdge(SBN, SSB->getNumber())); 930*0b57cec5SDimitry Andric } 931*0b57cec5SDimitry Andric } // while (FlowQ) 932*0b57cec5SDimitry Andric 933*0b57cec5SDimitry Andric LLVM_DEBUG({ 934*0b57cec5SDimitry Andric dbgs() << "Cells after propagation:\n"; 935*0b57cec5SDimitry Andric Cells.print(dbgs(), MCE.TRI); 936*0b57cec5SDimitry Andric dbgs() << "Dead CFG edges:\n"; 937*0b57cec5SDimitry Andric for (const MachineBasicBlock &B : MF) { 938*0b57cec5SDimitry Andric unsigned BN = B.getNumber(); 939*0b57cec5SDimitry Andric for (const MachineBasicBlock *SB : B.successors()) { 940*0b57cec5SDimitry Andric unsigned SN = SB->getNumber(); 941*0b57cec5SDimitry Andric if (!EdgeExec.count(CFGEdge(BN, SN))) 942*0b57cec5SDimitry Andric dbgs() << " " << printMBBReference(B) << " -> " 943*0b57cec5SDimitry Andric << printMBBReference(*SB) << '\n'; 944*0b57cec5SDimitry Andric } 945*0b57cec5SDimitry Andric } 946*0b57cec5SDimitry Andric }); 947*0b57cec5SDimitry Andric } 948*0b57cec5SDimitry Andric 949*0b57cec5SDimitry Andric bool MachineConstPropagator::rewrite(MachineFunction &MF) { 950*0b57cec5SDimitry Andric bool Changed = false; 951*0b57cec5SDimitry Andric // Rewrite all instructions based on the collected cell information. 952*0b57cec5SDimitry Andric // 953*0b57cec5SDimitry Andric // Traverse the instructions in a post-order, so that rewriting an 954*0b57cec5SDimitry Andric // instruction can make changes "downstream" in terms of control-flow 955*0b57cec5SDimitry Andric // without affecting the rewriting process. (We should not change 956*0b57cec5SDimitry Andric // instructions that have not yet been visited by the rewriter.) 957*0b57cec5SDimitry Andric // The reason for this is that the rewriter can introduce new vregs, 958*0b57cec5SDimitry Andric // and replace uses of old vregs (which had corresponding cells 959*0b57cec5SDimitry Andric // computed during propagation) with these new vregs (which at this 960*0b57cec5SDimitry Andric // point would not have any cells, and would appear to be "top"). 961*0b57cec5SDimitry Andric // If an attempt was made to evaluate an instruction with a fresh 962*0b57cec5SDimitry Andric // "top" vreg, it would cause an error (abend) in the evaluator. 963*0b57cec5SDimitry Andric 964*0b57cec5SDimitry Andric // Collect the post-order-traversal block ordering. The subsequent 965*0b57cec5SDimitry Andric // traversal/rewrite will update block successors, so it's safer 966*0b57cec5SDimitry Andric // if the visiting order it computed ahead of time. 967*0b57cec5SDimitry Andric std::vector<MachineBasicBlock*> POT; 968*0b57cec5SDimitry Andric for (MachineBasicBlock *B : post_order(&MF)) 969*0b57cec5SDimitry Andric if (!B->empty()) 970*0b57cec5SDimitry Andric POT.push_back(B); 971*0b57cec5SDimitry Andric 972*0b57cec5SDimitry Andric for (MachineBasicBlock *B : POT) { 973*0b57cec5SDimitry Andric // Walk the block backwards (which usually begin with the branches). 974*0b57cec5SDimitry Andric // If any branch is rewritten, we may need to update the successor 975*0b57cec5SDimitry Andric // information for this block. Unless the block's successors can be 976*0b57cec5SDimitry Andric // precisely determined (which may not be the case for indirect 977*0b57cec5SDimitry Andric // branches), we cannot modify any branch. 978*0b57cec5SDimitry Andric 979*0b57cec5SDimitry Andric // Compute the successor information. 980*0b57cec5SDimitry Andric SetVector<const MachineBasicBlock*> Targets; 981*0b57cec5SDimitry Andric bool HaveTargets = computeBlockSuccessors(B, Targets); 982*0b57cec5SDimitry Andric // Rewrite the executable instructions. Skip branches if we don't 983*0b57cec5SDimitry Andric // have block successor information. 984*0b57cec5SDimitry Andric for (auto I = B->rbegin(), E = B->rend(); I != E; ++I) { 985*0b57cec5SDimitry Andric MachineInstr &MI = *I; 986*0b57cec5SDimitry Andric if (InstrExec.count(&MI)) { 987*0b57cec5SDimitry Andric if (MI.isBranch() && !HaveTargets) 988*0b57cec5SDimitry Andric continue; 989*0b57cec5SDimitry Andric Changed |= MCE.rewrite(MI, Cells); 990*0b57cec5SDimitry Andric } 991*0b57cec5SDimitry Andric } 992*0b57cec5SDimitry Andric // The rewriting could rewrite PHI nodes to non-PHI nodes, causing 993*0b57cec5SDimitry Andric // regular instructions to appear in between PHI nodes. Bring all 994*0b57cec5SDimitry Andric // the PHI nodes to the beginning of the block. 995*0b57cec5SDimitry Andric for (auto I = B->begin(), E = B->end(); I != E; ++I) { 996*0b57cec5SDimitry Andric if (I->isPHI()) 997*0b57cec5SDimitry Andric continue; 998*0b57cec5SDimitry Andric // I is not PHI. Find the next PHI node P. 999*0b57cec5SDimitry Andric auto P = I; 1000*0b57cec5SDimitry Andric while (++P != E) 1001*0b57cec5SDimitry Andric if (P->isPHI()) 1002*0b57cec5SDimitry Andric break; 1003*0b57cec5SDimitry Andric // Not found. 1004*0b57cec5SDimitry Andric if (P == E) 1005*0b57cec5SDimitry Andric break; 1006*0b57cec5SDimitry Andric // Splice P right before I. 1007*0b57cec5SDimitry Andric B->splice(I, B, P); 1008*0b57cec5SDimitry Andric // Reset I to point at the just spliced PHI node. 1009*0b57cec5SDimitry Andric --I; 1010*0b57cec5SDimitry Andric } 1011*0b57cec5SDimitry Andric // Update the block successor information: remove unnecessary successors. 1012*0b57cec5SDimitry Andric if (HaveTargets) { 1013*0b57cec5SDimitry Andric SmallVector<MachineBasicBlock*,2> ToRemove; 1014*0b57cec5SDimitry Andric for (MachineBasicBlock *SB : B->successors()) { 1015*0b57cec5SDimitry Andric if (!Targets.count(SB)) 1016*0b57cec5SDimitry Andric ToRemove.push_back(const_cast<MachineBasicBlock*>(SB)); 1017*0b57cec5SDimitry Andric Targets.remove(SB); 1018*0b57cec5SDimitry Andric } 1019*0b57cec5SDimitry Andric for (unsigned i = 0, n = ToRemove.size(); i < n; ++i) 1020*0b57cec5SDimitry Andric removeCFGEdge(B, ToRemove[i]); 1021*0b57cec5SDimitry Andric // If there are any blocks left in the computed targets, it means that 1022*0b57cec5SDimitry Andric // we think that the block could go somewhere, but the CFG does not. 1023*0b57cec5SDimitry Andric // This could legitimately happen in blocks that have non-returning 1024*0b57cec5SDimitry Andric // calls---we would think that the execution can continue, but the 1025*0b57cec5SDimitry Andric // CFG will not have a successor edge. 1026*0b57cec5SDimitry Andric } 1027*0b57cec5SDimitry Andric } 1028*0b57cec5SDimitry Andric // Need to do some final post-processing. 1029*0b57cec5SDimitry Andric // If a branch was not executable, it will not get rewritten, but should 1030*0b57cec5SDimitry Andric // be removed (or replaced with something equivalent to a A2_nop). We can't 1031*0b57cec5SDimitry Andric // erase instructions during rewriting, so this needs to be delayed until 1032*0b57cec5SDimitry Andric // now. 1033*0b57cec5SDimitry Andric for (MachineBasicBlock &B : MF) { 1034*0b57cec5SDimitry Andric MachineBasicBlock::iterator I = B.begin(), E = B.end(); 1035*0b57cec5SDimitry Andric while (I != E) { 1036*0b57cec5SDimitry Andric auto Next = std::next(I); 1037*0b57cec5SDimitry Andric if (I->isBranch() && !InstrExec.count(&*I)) 1038*0b57cec5SDimitry Andric B.erase(I); 1039*0b57cec5SDimitry Andric I = Next; 1040*0b57cec5SDimitry Andric } 1041*0b57cec5SDimitry Andric } 1042*0b57cec5SDimitry Andric return Changed; 1043*0b57cec5SDimitry Andric } 1044*0b57cec5SDimitry Andric 1045*0b57cec5SDimitry Andric // This is the constant propagation algorithm as described by Wegman-Zadeck. 1046*0b57cec5SDimitry Andric // Most of the terminology comes from there. 1047*0b57cec5SDimitry Andric bool MachineConstPropagator::run(MachineFunction &MF) { 1048*0b57cec5SDimitry Andric LLVM_DEBUG(MF.print(dbgs() << "Starting MachineConstPropagator\n", nullptr)); 1049*0b57cec5SDimitry Andric 1050*0b57cec5SDimitry Andric MRI = &MF.getRegInfo(); 1051*0b57cec5SDimitry Andric 1052*0b57cec5SDimitry Andric Cells.clear(); 1053*0b57cec5SDimitry Andric EdgeExec.clear(); 1054*0b57cec5SDimitry Andric InstrExec.clear(); 1055*0b57cec5SDimitry Andric assert(FlowQ.empty()); 1056*0b57cec5SDimitry Andric 1057*0b57cec5SDimitry Andric propagate(MF); 1058*0b57cec5SDimitry Andric bool Changed = rewrite(MF); 1059*0b57cec5SDimitry Andric 1060*0b57cec5SDimitry Andric LLVM_DEBUG({ 1061*0b57cec5SDimitry Andric dbgs() << "End of MachineConstPropagator (Changed=" << Changed << ")\n"; 1062*0b57cec5SDimitry Andric if (Changed) 1063*0b57cec5SDimitry Andric MF.print(dbgs(), nullptr); 1064*0b57cec5SDimitry Andric }); 1065*0b57cec5SDimitry Andric return Changed; 1066*0b57cec5SDimitry Andric } 1067*0b57cec5SDimitry Andric 1068*0b57cec5SDimitry Andric // -------------------------------------------------------------------- 1069*0b57cec5SDimitry Andric // Machine const evaluator. 1070*0b57cec5SDimitry Andric 1071*0b57cec5SDimitry Andric bool MachineConstEvaluator::getCell(const RegisterSubReg &R, const CellMap &Inputs, 1072*0b57cec5SDimitry Andric LatticeCell &RC) { 1073*0b57cec5SDimitry Andric if (!TargetRegisterInfo::isVirtualRegister(R.Reg)) 1074*0b57cec5SDimitry Andric return false; 1075*0b57cec5SDimitry Andric const LatticeCell &L = Inputs.get(R.Reg); 1076*0b57cec5SDimitry Andric if (!R.SubReg) { 1077*0b57cec5SDimitry Andric RC = L; 1078*0b57cec5SDimitry Andric return !RC.isBottom(); 1079*0b57cec5SDimitry Andric } 1080*0b57cec5SDimitry Andric bool Eval = evaluate(R, L, RC); 1081*0b57cec5SDimitry Andric return Eval && !RC.isBottom(); 1082*0b57cec5SDimitry Andric } 1083*0b57cec5SDimitry Andric 1084*0b57cec5SDimitry Andric bool MachineConstEvaluator::constToInt(const Constant *C, 1085*0b57cec5SDimitry Andric APInt &Val) const { 1086*0b57cec5SDimitry Andric const ConstantInt *CI = dyn_cast<ConstantInt>(C); 1087*0b57cec5SDimitry Andric if (!CI) 1088*0b57cec5SDimitry Andric return false; 1089*0b57cec5SDimitry Andric Val = CI->getValue(); 1090*0b57cec5SDimitry Andric return true; 1091*0b57cec5SDimitry Andric } 1092*0b57cec5SDimitry Andric 1093*0b57cec5SDimitry Andric const ConstantInt *MachineConstEvaluator::intToConst(const APInt &Val) const { 1094*0b57cec5SDimitry Andric return ConstantInt::get(CX, Val); 1095*0b57cec5SDimitry Andric } 1096*0b57cec5SDimitry Andric 1097*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPrr(uint32_t Cmp, const RegisterSubReg &R1, 1098*0b57cec5SDimitry Andric const RegisterSubReg &R2, const CellMap &Inputs, bool &Result) { 1099*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg)); 1100*0b57cec5SDimitry Andric LatticeCell LS1, LS2; 1101*0b57cec5SDimitry Andric if (!getCell(R1, Inputs, LS1) || !getCell(R2, Inputs, LS2)) 1102*0b57cec5SDimitry Andric return false; 1103*0b57cec5SDimitry Andric 1104*0b57cec5SDimitry Andric bool IsProp1 = LS1.isProperty(); 1105*0b57cec5SDimitry Andric bool IsProp2 = LS2.isProperty(); 1106*0b57cec5SDimitry Andric if (IsProp1) { 1107*0b57cec5SDimitry Andric uint32_t Prop1 = LS1.properties(); 1108*0b57cec5SDimitry Andric if (IsProp2) 1109*0b57cec5SDimitry Andric return evaluateCMPpp(Cmp, Prop1, LS2.properties(), Result); 1110*0b57cec5SDimitry Andric uint32_t NegCmp = Comparison::negate(Cmp); 1111*0b57cec5SDimitry Andric return evaluateCMPrp(NegCmp, R2, Prop1, Inputs, Result); 1112*0b57cec5SDimitry Andric } 1113*0b57cec5SDimitry Andric if (IsProp2) { 1114*0b57cec5SDimitry Andric uint32_t Prop2 = LS2.properties(); 1115*0b57cec5SDimitry Andric return evaluateCMPrp(Cmp, R1, Prop2, Inputs, Result); 1116*0b57cec5SDimitry Andric } 1117*0b57cec5SDimitry Andric 1118*0b57cec5SDimitry Andric APInt A; 1119*0b57cec5SDimitry Andric bool IsTrue = true, IsFalse = true; 1120*0b57cec5SDimitry Andric for (unsigned i = 0; i < LS2.size(); ++i) { 1121*0b57cec5SDimitry Andric bool Res; 1122*0b57cec5SDimitry Andric bool Computed = constToInt(LS2.Values[i], A) && 1123*0b57cec5SDimitry Andric evaluateCMPri(Cmp, R1, A, Inputs, Res); 1124*0b57cec5SDimitry Andric if (!Computed) 1125*0b57cec5SDimitry Andric return false; 1126*0b57cec5SDimitry Andric IsTrue &= Res; 1127*0b57cec5SDimitry Andric IsFalse &= !Res; 1128*0b57cec5SDimitry Andric } 1129*0b57cec5SDimitry Andric assert(!IsTrue || !IsFalse); 1130*0b57cec5SDimitry Andric // The actual logical value of the comparison is same as IsTrue. 1131*0b57cec5SDimitry Andric Result = IsTrue; 1132*0b57cec5SDimitry Andric // Return true if the result was proven to be true or proven to be false. 1133*0b57cec5SDimitry Andric return IsTrue || IsFalse; 1134*0b57cec5SDimitry Andric } 1135*0b57cec5SDimitry Andric 1136*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPri(uint32_t Cmp, const RegisterSubReg &R1, 1137*0b57cec5SDimitry Andric const APInt &A2, const CellMap &Inputs, bool &Result) { 1138*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg)); 1139*0b57cec5SDimitry Andric LatticeCell LS; 1140*0b57cec5SDimitry Andric if (!getCell(R1, Inputs, LS)) 1141*0b57cec5SDimitry Andric return false; 1142*0b57cec5SDimitry Andric if (LS.isProperty()) 1143*0b57cec5SDimitry Andric return evaluateCMPpi(Cmp, LS.properties(), A2, Result); 1144*0b57cec5SDimitry Andric 1145*0b57cec5SDimitry Andric APInt A; 1146*0b57cec5SDimitry Andric bool IsTrue = true, IsFalse = true; 1147*0b57cec5SDimitry Andric for (unsigned i = 0; i < LS.size(); ++i) { 1148*0b57cec5SDimitry Andric bool Res; 1149*0b57cec5SDimitry Andric bool Computed = constToInt(LS.Values[i], A) && 1150*0b57cec5SDimitry Andric evaluateCMPii(Cmp, A, A2, Res); 1151*0b57cec5SDimitry Andric if (!Computed) 1152*0b57cec5SDimitry Andric return false; 1153*0b57cec5SDimitry Andric IsTrue &= Res; 1154*0b57cec5SDimitry Andric IsFalse &= !Res; 1155*0b57cec5SDimitry Andric } 1156*0b57cec5SDimitry Andric assert(!IsTrue || !IsFalse); 1157*0b57cec5SDimitry Andric // The actual logical value of the comparison is same as IsTrue. 1158*0b57cec5SDimitry Andric Result = IsTrue; 1159*0b57cec5SDimitry Andric // Return true if the result was proven to be true or proven to be false. 1160*0b57cec5SDimitry Andric return IsTrue || IsFalse; 1161*0b57cec5SDimitry Andric } 1162*0b57cec5SDimitry Andric 1163*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPrp(uint32_t Cmp, const RegisterSubReg &R1, 1164*0b57cec5SDimitry Andric uint64_t Props2, const CellMap &Inputs, bool &Result) { 1165*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg)); 1166*0b57cec5SDimitry Andric LatticeCell LS; 1167*0b57cec5SDimitry Andric if (!getCell(R1, Inputs, LS)) 1168*0b57cec5SDimitry Andric return false; 1169*0b57cec5SDimitry Andric if (LS.isProperty()) 1170*0b57cec5SDimitry Andric return evaluateCMPpp(Cmp, LS.properties(), Props2, Result); 1171*0b57cec5SDimitry Andric 1172*0b57cec5SDimitry Andric APInt A; 1173*0b57cec5SDimitry Andric uint32_t NegCmp = Comparison::negate(Cmp); 1174*0b57cec5SDimitry Andric bool IsTrue = true, IsFalse = true; 1175*0b57cec5SDimitry Andric for (unsigned i = 0; i < LS.size(); ++i) { 1176*0b57cec5SDimitry Andric bool Res; 1177*0b57cec5SDimitry Andric bool Computed = constToInt(LS.Values[i], A) && 1178*0b57cec5SDimitry Andric evaluateCMPpi(NegCmp, Props2, A, Res); 1179*0b57cec5SDimitry Andric if (!Computed) 1180*0b57cec5SDimitry Andric return false; 1181*0b57cec5SDimitry Andric IsTrue &= Res; 1182*0b57cec5SDimitry Andric IsFalse &= !Res; 1183*0b57cec5SDimitry Andric } 1184*0b57cec5SDimitry Andric assert(!IsTrue || !IsFalse); 1185*0b57cec5SDimitry Andric Result = IsTrue; 1186*0b57cec5SDimitry Andric return IsTrue || IsFalse; 1187*0b57cec5SDimitry Andric } 1188*0b57cec5SDimitry Andric 1189*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPii(uint32_t Cmp, const APInt &A1, 1190*0b57cec5SDimitry Andric const APInt &A2, bool &Result) { 1191*0b57cec5SDimitry Andric // NE is a special kind of comparison (not composed of smaller properties). 1192*0b57cec5SDimitry Andric if (Cmp == Comparison::NE) { 1193*0b57cec5SDimitry Andric Result = !APInt::isSameValue(A1, A2); 1194*0b57cec5SDimitry Andric return true; 1195*0b57cec5SDimitry Andric } 1196*0b57cec5SDimitry Andric if (Cmp == Comparison::EQ) { 1197*0b57cec5SDimitry Andric Result = APInt::isSameValue(A1, A2); 1198*0b57cec5SDimitry Andric return true; 1199*0b57cec5SDimitry Andric } 1200*0b57cec5SDimitry Andric if (Cmp & Comparison::EQ) { 1201*0b57cec5SDimitry Andric if (APInt::isSameValue(A1, A2)) 1202*0b57cec5SDimitry Andric return (Result = true); 1203*0b57cec5SDimitry Andric } 1204*0b57cec5SDimitry Andric assert((Cmp & (Comparison::L | Comparison::G)) && "Malformed comparison"); 1205*0b57cec5SDimitry Andric Result = false; 1206*0b57cec5SDimitry Andric 1207*0b57cec5SDimitry Andric unsigned W1 = A1.getBitWidth(); 1208*0b57cec5SDimitry Andric unsigned W2 = A2.getBitWidth(); 1209*0b57cec5SDimitry Andric unsigned MaxW = (W1 >= W2) ? W1 : W2; 1210*0b57cec5SDimitry Andric if (Cmp & Comparison::U) { 1211*0b57cec5SDimitry Andric const APInt Zx1 = A1.zextOrSelf(MaxW); 1212*0b57cec5SDimitry Andric const APInt Zx2 = A2.zextOrSelf(MaxW); 1213*0b57cec5SDimitry Andric if (Cmp & Comparison::L) 1214*0b57cec5SDimitry Andric Result = Zx1.ult(Zx2); 1215*0b57cec5SDimitry Andric else if (Cmp & Comparison::G) 1216*0b57cec5SDimitry Andric Result = Zx2.ult(Zx1); 1217*0b57cec5SDimitry Andric return true; 1218*0b57cec5SDimitry Andric } 1219*0b57cec5SDimitry Andric 1220*0b57cec5SDimitry Andric // Signed comparison. 1221*0b57cec5SDimitry Andric const APInt Sx1 = A1.sextOrSelf(MaxW); 1222*0b57cec5SDimitry Andric const APInt Sx2 = A2.sextOrSelf(MaxW); 1223*0b57cec5SDimitry Andric if (Cmp & Comparison::L) 1224*0b57cec5SDimitry Andric Result = Sx1.slt(Sx2); 1225*0b57cec5SDimitry Andric else if (Cmp & Comparison::G) 1226*0b57cec5SDimitry Andric Result = Sx2.slt(Sx1); 1227*0b57cec5SDimitry Andric return true; 1228*0b57cec5SDimitry Andric } 1229*0b57cec5SDimitry Andric 1230*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPpi(uint32_t Cmp, uint32_t Props, 1231*0b57cec5SDimitry Andric const APInt &A2, bool &Result) { 1232*0b57cec5SDimitry Andric if (Props == ConstantProperties::Unknown) 1233*0b57cec5SDimitry Andric return false; 1234*0b57cec5SDimitry Andric 1235*0b57cec5SDimitry Andric // Should never see NaN here, but check for it for completeness. 1236*0b57cec5SDimitry Andric if (Props & ConstantProperties::NaN) 1237*0b57cec5SDimitry Andric return false; 1238*0b57cec5SDimitry Andric // Infinity could theoretically be compared to a number, but the 1239*0b57cec5SDimitry Andric // presence of infinity here would be very suspicious. If we don't 1240*0b57cec5SDimitry Andric // know for sure that the number is finite, bail out. 1241*0b57cec5SDimitry Andric if (!(Props & ConstantProperties::Finite)) 1242*0b57cec5SDimitry Andric return false; 1243*0b57cec5SDimitry Andric 1244*0b57cec5SDimitry Andric // Let X be a number that has properties Props. 1245*0b57cec5SDimitry Andric 1246*0b57cec5SDimitry Andric if (Cmp & Comparison::U) { 1247*0b57cec5SDimitry Andric // In case of unsigned comparisons, we can only compare against 0. 1248*0b57cec5SDimitry Andric if (A2 == 0) { 1249*0b57cec5SDimitry Andric // Any x!=0 will be considered >0 in an unsigned comparison. 1250*0b57cec5SDimitry Andric if (Props & ConstantProperties::Zero) 1251*0b57cec5SDimitry Andric Result = (Cmp & Comparison::EQ); 1252*0b57cec5SDimitry Andric else if (Props & ConstantProperties::NonZero) 1253*0b57cec5SDimitry Andric Result = (Cmp & Comparison::G) || (Cmp == Comparison::NE); 1254*0b57cec5SDimitry Andric else 1255*0b57cec5SDimitry Andric return false; 1256*0b57cec5SDimitry Andric return true; 1257*0b57cec5SDimitry Andric } 1258*0b57cec5SDimitry Andric // A2 is not zero. The only handled case is if X = 0. 1259*0b57cec5SDimitry Andric if (Props & ConstantProperties::Zero) { 1260*0b57cec5SDimitry Andric Result = (Cmp & Comparison::L) || (Cmp == Comparison::NE); 1261*0b57cec5SDimitry Andric return true; 1262*0b57cec5SDimitry Andric } 1263*0b57cec5SDimitry Andric return false; 1264*0b57cec5SDimitry Andric } 1265*0b57cec5SDimitry Andric 1266*0b57cec5SDimitry Andric // Signed comparisons are different. 1267*0b57cec5SDimitry Andric if (Props & ConstantProperties::Zero) { 1268*0b57cec5SDimitry Andric if (A2 == 0) 1269*0b57cec5SDimitry Andric Result = (Cmp & Comparison::EQ); 1270*0b57cec5SDimitry Andric else 1271*0b57cec5SDimitry Andric Result = (Cmp == Comparison::NE) || 1272*0b57cec5SDimitry Andric ((Cmp & Comparison::L) && !A2.isNegative()) || 1273*0b57cec5SDimitry Andric ((Cmp & Comparison::G) && A2.isNegative()); 1274*0b57cec5SDimitry Andric return true; 1275*0b57cec5SDimitry Andric } 1276*0b57cec5SDimitry Andric if (Props & ConstantProperties::PosOrZero) { 1277*0b57cec5SDimitry Andric // X >= 0 and !(A2 < 0) => cannot compare 1278*0b57cec5SDimitry Andric if (!A2.isNegative()) 1279*0b57cec5SDimitry Andric return false; 1280*0b57cec5SDimitry Andric // X >= 0 and A2 < 0 1281*0b57cec5SDimitry Andric Result = (Cmp & Comparison::G) || (Cmp == Comparison::NE); 1282*0b57cec5SDimitry Andric return true; 1283*0b57cec5SDimitry Andric } 1284*0b57cec5SDimitry Andric if (Props & ConstantProperties::NegOrZero) { 1285*0b57cec5SDimitry Andric // X <= 0 and Src1 < 0 => cannot compare 1286*0b57cec5SDimitry Andric if (A2 == 0 || A2.isNegative()) 1287*0b57cec5SDimitry Andric return false; 1288*0b57cec5SDimitry Andric // X <= 0 and A2 > 0 1289*0b57cec5SDimitry Andric Result = (Cmp & Comparison::L) || (Cmp == Comparison::NE); 1290*0b57cec5SDimitry Andric return true; 1291*0b57cec5SDimitry Andric } 1292*0b57cec5SDimitry Andric 1293*0b57cec5SDimitry Andric return false; 1294*0b57cec5SDimitry Andric } 1295*0b57cec5SDimitry Andric 1296*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCMPpp(uint32_t Cmp, uint32_t Props1, 1297*0b57cec5SDimitry Andric uint32_t Props2, bool &Result) { 1298*0b57cec5SDimitry Andric using P = ConstantProperties; 1299*0b57cec5SDimitry Andric 1300*0b57cec5SDimitry Andric if ((Props1 & P::NaN) && (Props2 & P::NaN)) 1301*0b57cec5SDimitry Andric return false; 1302*0b57cec5SDimitry Andric if (!(Props1 & P::Finite) || !(Props2 & P::Finite)) 1303*0b57cec5SDimitry Andric return false; 1304*0b57cec5SDimitry Andric 1305*0b57cec5SDimitry Andric bool Zero1 = (Props1 & P::Zero), Zero2 = (Props2 & P::Zero); 1306*0b57cec5SDimitry Andric bool NonZero1 = (Props1 & P::NonZero), NonZero2 = (Props2 & P::NonZero); 1307*0b57cec5SDimitry Andric if (Zero1 && Zero2) { 1308*0b57cec5SDimitry Andric Result = (Cmp & Comparison::EQ); 1309*0b57cec5SDimitry Andric return true; 1310*0b57cec5SDimitry Andric } 1311*0b57cec5SDimitry Andric if (Cmp == Comparison::NE) { 1312*0b57cec5SDimitry Andric if ((Zero1 && NonZero2) || (NonZero1 && Zero2)) 1313*0b57cec5SDimitry Andric return (Result = true); 1314*0b57cec5SDimitry Andric return false; 1315*0b57cec5SDimitry Andric } 1316*0b57cec5SDimitry Andric 1317*0b57cec5SDimitry Andric if (Cmp & Comparison::U) { 1318*0b57cec5SDimitry Andric // In unsigned comparisons, we can only compare against a known zero, 1319*0b57cec5SDimitry Andric // or a known non-zero. 1320*0b57cec5SDimitry Andric if (Zero1 && NonZero2) { 1321*0b57cec5SDimitry Andric Result = (Cmp & Comparison::L); 1322*0b57cec5SDimitry Andric return true; 1323*0b57cec5SDimitry Andric } 1324*0b57cec5SDimitry Andric if (NonZero1 && Zero2) { 1325*0b57cec5SDimitry Andric Result = (Cmp & Comparison::G); 1326*0b57cec5SDimitry Andric return true; 1327*0b57cec5SDimitry Andric } 1328*0b57cec5SDimitry Andric return false; 1329*0b57cec5SDimitry Andric } 1330*0b57cec5SDimitry Andric 1331*0b57cec5SDimitry Andric // Signed comparison. The comparison is not NE. 1332*0b57cec5SDimitry Andric bool Poz1 = (Props1 & P::PosOrZero), Poz2 = (Props2 & P::PosOrZero); 1333*0b57cec5SDimitry Andric bool Nez1 = (Props1 & P::NegOrZero), Nez2 = (Props2 & P::NegOrZero); 1334*0b57cec5SDimitry Andric if (Nez1 && Poz2) { 1335*0b57cec5SDimitry Andric if (NonZero1 || NonZero2) { 1336*0b57cec5SDimitry Andric Result = (Cmp & Comparison::L); 1337*0b57cec5SDimitry Andric return true; 1338*0b57cec5SDimitry Andric } 1339*0b57cec5SDimitry Andric // Either (or both) could be zero. Can only say that X <= Y. 1340*0b57cec5SDimitry Andric if ((Cmp & Comparison::EQ) && (Cmp & Comparison::L)) 1341*0b57cec5SDimitry Andric return (Result = true); 1342*0b57cec5SDimitry Andric } 1343*0b57cec5SDimitry Andric if (Poz1 && Nez2) { 1344*0b57cec5SDimitry Andric if (NonZero1 || NonZero2) { 1345*0b57cec5SDimitry Andric Result = (Cmp & Comparison::G); 1346*0b57cec5SDimitry Andric return true; 1347*0b57cec5SDimitry Andric } 1348*0b57cec5SDimitry Andric // Either (or both) could be zero. Can only say that X >= Y. 1349*0b57cec5SDimitry Andric if ((Cmp & Comparison::EQ) && (Cmp & Comparison::G)) 1350*0b57cec5SDimitry Andric return (Result = true); 1351*0b57cec5SDimitry Andric } 1352*0b57cec5SDimitry Andric 1353*0b57cec5SDimitry Andric return false; 1354*0b57cec5SDimitry Andric } 1355*0b57cec5SDimitry Andric 1356*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCOPY(const RegisterSubReg &R1, 1357*0b57cec5SDimitry Andric const CellMap &Inputs, LatticeCell &Result) { 1358*0b57cec5SDimitry Andric return getCell(R1, Inputs, Result); 1359*0b57cec5SDimitry Andric } 1360*0b57cec5SDimitry Andric 1361*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateANDrr(const RegisterSubReg &R1, 1362*0b57cec5SDimitry Andric const RegisterSubReg &R2, const CellMap &Inputs, LatticeCell &Result) { 1363*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg)); 1364*0b57cec5SDimitry Andric const LatticeCell &L1 = Inputs.get(R2.Reg); 1365*0b57cec5SDimitry Andric const LatticeCell &L2 = Inputs.get(R2.Reg); 1366*0b57cec5SDimitry Andric // If both sources are bottom, exit. Otherwise try to evaluate ANDri 1367*0b57cec5SDimitry Andric // with the non-bottom argument passed as the immediate. This is to 1368*0b57cec5SDimitry Andric // catch cases of ANDing with 0. 1369*0b57cec5SDimitry Andric if (L2.isBottom()) { 1370*0b57cec5SDimitry Andric if (L1.isBottom()) 1371*0b57cec5SDimitry Andric return false; 1372*0b57cec5SDimitry Andric return evaluateANDrr(R2, R1, Inputs, Result); 1373*0b57cec5SDimitry Andric } 1374*0b57cec5SDimitry Andric LatticeCell LS2; 1375*0b57cec5SDimitry Andric if (!evaluate(R2, L2, LS2)) 1376*0b57cec5SDimitry Andric return false; 1377*0b57cec5SDimitry Andric if (LS2.isBottom() || LS2.isProperty()) 1378*0b57cec5SDimitry Andric return false; 1379*0b57cec5SDimitry Andric 1380*0b57cec5SDimitry Andric APInt A; 1381*0b57cec5SDimitry Andric for (unsigned i = 0; i < LS2.size(); ++i) { 1382*0b57cec5SDimitry Andric LatticeCell RC; 1383*0b57cec5SDimitry Andric bool Eval = constToInt(LS2.Values[i], A) && 1384*0b57cec5SDimitry Andric evaluateANDri(R1, A, Inputs, RC); 1385*0b57cec5SDimitry Andric if (!Eval) 1386*0b57cec5SDimitry Andric return false; 1387*0b57cec5SDimitry Andric Result.meet(RC); 1388*0b57cec5SDimitry Andric } 1389*0b57cec5SDimitry Andric return !Result.isBottom(); 1390*0b57cec5SDimitry Andric } 1391*0b57cec5SDimitry Andric 1392*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateANDri(const RegisterSubReg &R1, 1393*0b57cec5SDimitry Andric const APInt &A2, const CellMap &Inputs, LatticeCell &Result) { 1394*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg)); 1395*0b57cec5SDimitry Andric if (A2 == -1) 1396*0b57cec5SDimitry Andric return getCell(R1, Inputs, Result); 1397*0b57cec5SDimitry Andric if (A2 == 0) { 1398*0b57cec5SDimitry Andric LatticeCell RC; 1399*0b57cec5SDimitry Andric RC.add(intToConst(A2)); 1400*0b57cec5SDimitry Andric // Overwrite Result. 1401*0b57cec5SDimitry Andric Result = RC; 1402*0b57cec5SDimitry Andric return true; 1403*0b57cec5SDimitry Andric } 1404*0b57cec5SDimitry Andric LatticeCell LS1; 1405*0b57cec5SDimitry Andric if (!getCell(R1, Inputs, LS1)) 1406*0b57cec5SDimitry Andric return false; 1407*0b57cec5SDimitry Andric if (LS1.isBottom() || LS1.isProperty()) 1408*0b57cec5SDimitry Andric return false; 1409*0b57cec5SDimitry Andric 1410*0b57cec5SDimitry Andric APInt A, ResA; 1411*0b57cec5SDimitry Andric for (unsigned i = 0; i < LS1.size(); ++i) { 1412*0b57cec5SDimitry Andric bool Eval = constToInt(LS1.Values[i], A) && 1413*0b57cec5SDimitry Andric evaluateANDii(A, A2, ResA); 1414*0b57cec5SDimitry Andric if (!Eval) 1415*0b57cec5SDimitry Andric return false; 1416*0b57cec5SDimitry Andric const Constant *C = intToConst(ResA); 1417*0b57cec5SDimitry Andric Result.add(C); 1418*0b57cec5SDimitry Andric } 1419*0b57cec5SDimitry Andric return !Result.isBottom(); 1420*0b57cec5SDimitry Andric } 1421*0b57cec5SDimitry Andric 1422*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateANDii(const APInt &A1, 1423*0b57cec5SDimitry Andric const APInt &A2, APInt &Result) { 1424*0b57cec5SDimitry Andric Result = A1 & A2; 1425*0b57cec5SDimitry Andric return true; 1426*0b57cec5SDimitry Andric } 1427*0b57cec5SDimitry Andric 1428*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateORrr(const RegisterSubReg &R1, 1429*0b57cec5SDimitry Andric const RegisterSubReg &R2, const CellMap &Inputs, LatticeCell &Result) { 1430*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg)); 1431*0b57cec5SDimitry Andric const LatticeCell &L1 = Inputs.get(R2.Reg); 1432*0b57cec5SDimitry Andric const LatticeCell &L2 = Inputs.get(R2.Reg); 1433*0b57cec5SDimitry Andric // If both sources are bottom, exit. Otherwise try to evaluate ORri 1434*0b57cec5SDimitry Andric // with the non-bottom argument passed as the immediate. This is to 1435*0b57cec5SDimitry Andric // catch cases of ORing with -1. 1436*0b57cec5SDimitry Andric if (L2.isBottom()) { 1437*0b57cec5SDimitry Andric if (L1.isBottom()) 1438*0b57cec5SDimitry Andric return false; 1439*0b57cec5SDimitry Andric return evaluateORrr(R2, R1, Inputs, Result); 1440*0b57cec5SDimitry Andric } 1441*0b57cec5SDimitry Andric LatticeCell LS2; 1442*0b57cec5SDimitry Andric if (!evaluate(R2, L2, LS2)) 1443*0b57cec5SDimitry Andric return false; 1444*0b57cec5SDimitry Andric if (LS2.isBottom() || LS2.isProperty()) 1445*0b57cec5SDimitry Andric return false; 1446*0b57cec5SDimitry Andric 1447*0b57cec5SDimitry Andric APInt A; 1448*0b57cec5SDimitry Andric for (unsigned i = 0; i < LS2.size(); ++i) { 1449*0b57cec5SDimitry Andric LatticeCell RC; 1450*0b57cec5SDimitry Andric bool Eval = constToInt(LS2.Values[i], A) && 1451*0b57cec5SDimitry Andric evaluateORri(R1, A, Inputs, RC); 1452*0b57cec5SDimitry Andric if (!Eval) 1453*0b57cec5SDimitry Andric return false; 1454*0b57cec5SDimitry Andric Result.meet(RC); 1455*0b57cec5SDimitry Andric } 1456*0b57cec5SDimitry Andric return !Result.isBottom(); 1457*0b57cec5SDimitry Andric } 1458*0b57cec5SDimitry Andric 1459*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateORri(const RegisterSubReg &R1, 1460*0b57cec5SDimitry Andric const APInt &A2, const CellMap &Inputs, LatticeCell &Result) { 1461*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg)); 1462*0b57cec5SDimitry Andric if (A2 == 0) 1463*0b57cec5SDimitry Andric return getCell(R1, Inputs, Result); 1464*0b57cec5SDimitry Andric if (A2 == -1) { 1465*0b57cec5SDimitry Andric LatticeCell RC; 1466*0b57cec5SDimitry Andric RC.add(intToConst(A2)); 1467*0b57cec5SDimitry Andric // Overwrite Result. 1468*0b57cec5SDimitry Andric Result = RC; 1469*0b57cec5SDimitry Andric return true; 1470*0b57cec5SDimitry Andric } 1471*0b57cec5SDimitry Andric LatticeCell LS1; 1472*0b57cec5SDimitry Andric if (!getCell(R1, Inputs, LS1)) 1473*0b57cec5SDimitry Andric return false; 1474*0b57cec5SDimitry Andric if (LS1.isBottom() || LS1.isProperty()) 1475*0b57cec5SDimitry Andric return false; 1476*0b57cec5SDimitry Andric 1477*0b57cec5SDimitry Andric APInt A, ResA; 1478*0b57cec5SDimitry Andric for (unsigned i = 0; i < LS1.size(); ++i) { 1479*0b57cec5SDimitry Andric bool Eval = constToInt(LS1.Values[i], A) && 1480*0b57cec5SDimitry Andric evaluateORii(A, A2, ResA); 1481*0b57cec5SDimitry Andric if (!Eval) 1482*0b57cec5SDimitry Andric return false; 1483*0b57cec5SDimitry Andric const Constant *C = intToConst(ResA); 1484*0b57cec5SDimitry Andric Result.add(C); 1485*0b57cec5SDimitry Andric } 1486*0b57cec5SDimitry Andric return !Result.isBottom(); 1487*0b57cec5SDimitry Andric } 1488*0b57cec5SDimitry Andric 1489*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateORii(const APInt &A1, 1490*0b57cec5SDimitry Andric const APInt &A2, APInt &Result) { 1491*0b57cec5SDimitry Andric Result = A1 | A2; 1492*0b57cec5SDimitry Andric return true; 1493*0b57cec5SDimitry Andric } 1494*0b57cec5SDimitry Andric 1495*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateXORrr(const RegisterSubReg &R1, 1496*0b57cec5SDimitry Andric const RegisterSubReg &R2, const CellMap &Inputs, LatticeCell &Result) { 1497*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg)); 1498*0b57cec5SDimitry Andric LatticeCell LS1, LS2; 1499*0b57cec5SDimitry Andric if (!getCell(R1, Inputs, LS1) || !getCell(R2, Inputs, LS2)) 1500*0b57cec5SDimitry Andric return false; 1501*0b57cec5SDimitry Andric if (LS1.isProperty()) { 1502*0b57cec5SDimitry Andric if (LS1.properties() & ConstantProperties::Zero) 1503*0b57cec5SDimitry Andric return !(Result = LS2).isBottom(); 1504*0b57cec5SDimitry Andric return false; 1505*0b57cec5SDimitry Andric } 1506*0b57cec5SDimitry Andric if (LS2.isProperty()) { 1507*0b57cec5SDimitry Andric if (LS2.properties() & ConstantProperties::Zero) 1508*0b57cec5SDimitry Andric return !(Result = LS1).isBottom(); 1509*0b57cec5SDimitry Andric return false; 1510*0b57cec5SDimitry Andric } 1511*0b57cec5SDimitry Andric 1512*0b57cec5SDimitry Andric APInt A; 1513*0b57cec5SDimitry Andric for (unsigned i = 0; i < LS2.size(); ++i) { 1514*0b57cec5SDimitry Andric LatticeCell RC; 1515*0b57cec5SDimitry Andric bool Eval = constToInt(LS2.Values[i], A) && 1516*0b57cec5SDimitry Andric evaluateXORri(R1, A, Inputs, RC); 1517*0b57cec5SDimitry Andric if (!Eval) 1518*0b57cec5SDimitry Andric return false; 1519*0b57cec5SDimitry Andric Result.meet(RC); 1520*0b57cec5SDimitry Andric } 1521*0b57cec5SDimitry Andric return !Result.isBottom(); 1522*0b57cec5SDimitry Andric } 1523*0b57cec5SDimitry Andric 1524*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateXORri(const RegisterSubReg &R1, 1525*0b57cec5SDimitry Andric const APInt &A2, const CellMap &Inputs, LatticeCell &Result) { 1526*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg)); 1527*0b57cec5SDimitry Andric LatticeCell LS1; 1528*0b57cec5SDimitry Andric if (!getCell(R1, Inputs, LS1)) 1529*0b57cec5SDimitry Andric return false; 1530*0b57cec5SDimitry Andric if (LS1.isProperty()) { 1531*0b57cec5SDimitry Andric if (LS1.properties() & ConstantProperties::Zero) { 1532*0b57cec5SDimitry Andric const Constant *C = intToConst(A2); 1533*0b57cec5SDimitry Andric Result.add(C); 1534*0b57cec5SDimitry Andric return !Result.isBottom(); 1535*0b57cec5SDimitry Andric } 1536*0b57cec5SDimitry Andric return false; 1537*0b57cec5SDimitry Andric } 1538*0b57cec5SDimitry Andric 1539*0b57cec5SDimitry Andric APInt A, XA; 1540*0b57cec5SDimitry Andric for (unsigned i = 0; i < LS1.size(); ++i) { 1541*0b57cec5SDimitry Andric bool Eval = constToInt(LS1.Values[i], A) && 1542*0b57cec5SDimitry Andric evaluateXORii(A, A2, XA); 1543*0b57cec5SDimitry Andric if (!Eval) 1544*0b57cec5SDimitry Andric return false; 1545*0b57cec5SDimitry Andric const Constant *C = intToConst(XA); 1546*0b57cec5SDimitry Andric Result.add(C); 1547*0b57cec5SDimitry Andric } 1548*0b57cec5SDimitry Andric return !Result.isBottom(); 1549*0b57cec5SDimitry Andric } 1550*0b57cec5SDimitry Andric 1551*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateXORii(const APInt &A1, 1552*0b57cec5SDimitry Andric const APInt &A2, APInt &Result) { 1553*0b57cec5SDimitry Andric Result = A1 ^ A2; 1554*0b57cec5SDimitry Andric return true; 1555*0b57cec5SDimitry Andric } 1556*0b57cec5SDimitry Andric 1557*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateZEXTr(const RegisterSubReg &R1, unsigned Width, 1558*0b57cec5SDimitry Andric unsigned Bits, const CellMap &Inputs, LatticeCell &Result) { 1559*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg)); 1560*0b57cec5SDimitry Andric LatticeCell LS1; 1561*0b57cec5SDimitry Andric if (!getCell(R1, Inputs, LS1)) 1562*0b57cec5SDimitry Andric return false; 1563*0b57cec5SDimitry Andric if (LS1.isProperty()) 1564*0b57cec5SDimitry Andric return false; 1565*0b57cec5SDimitry Andric 1566*0b57cec5SDimitry Andric APInt A, XA; 1567*0b57cec5SDimitry Andric for (unsigned i = 0; i < LS1.size(); ++i) { 1568*0b57cec5SDimitry Andric bool Eval = constToInt(LS1.Values[i], A) && 1569*0b57cec5SDimitry Andric evaluateZEXTi(A, Width, Bits, XA); 1570*0b57cec5SDimitry Andric if (!Eval) 1571*0b57cec5SDimitry Andric return false; 1572*0b57cec5SDimitry Andric const Constant *C = intToConst(XA); 1573*0b57cec5SDimitry Andric Result.add(C); 1574*0b57cec5SDimitry Andric } 1575*0b57cec5SDimitry Andric return true; 1576*0b57cec5SDimitry Andric } 1577*0b57cec5SDimitry Andric 1578*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateZEXTi(const APInt &A1, unsigned Width, 1579*0b57cec5SDimitry Andric unsigned Bits, APInt &Result) { 1580*0b57cec5SDimitry Andric unsigned BW = A1.getBitWidth(); 1581*0b57cec5SDimitry Andric (void)BW; 1582*0b57cec5SDimitry Andric assert(Width >= Bits && BW >= Bits); 1583*0b57cec5SDimitry Andric APInt Mask = APInt::getLowBitsSet(Width, Bits); 1584*0b57cec5SDimitry Andric Result = A1.zextOrTrunc(Width) & Mask; 1585*0b57cec5SDimitry Andric return true; 1586*0b57cec5SDimitry Andric } 1587*0b57cec5SDimitry Andric 1588*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateSEXTr(const RegisterSubReg &R1, unsigned Width, 1589*0b57cec5SDimitry Andric unsigned Bits, const CellMap &Inputs, LatticeCell &Result) { 1590*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg)); 1591*0b57cec5SDimitry Andric LatticeCell LS1; 1592*0b57cec5SDimitry Andric if (!getCell(R1, Inputs, LS1)) 1593*0b57cec5SDimitry Andric return false; 1594*0b57cec5SDimitry Andric if (LS1.isBottom() || LS1.isProperty()) 1595*0b57cec5SDimitry Andric return false; 1596*0b57cec5SDimitry Andric 1597*0b57cec5SDimitry Andric APInt A, XA; 1598*0b57cec5SDimitry Andric for (unsigned i = 0; i < LS1.size(); ++i) { 1599*0b57cec5SDimitry Andric bool Eval = constToInt(LS1.Values[i], A) && 1600*0b57cec5SDimitry Andric evaluateSEXTi(A, Width, Bits, XA); 1601*0b57cec5SDimitry Andric if (!Eval) 1602*0b57cec5SDimitry Andric return false; 1603*0b57cec5SDimitry Andric const Constant *C = intToConst(XA); 1604*0b57cec5SDimitry Andric Result.add(C); 1605*0b57cec5SDimitry Andric } 1606*0b57cec5SDimitry Andric return true; 1607*0b57cec5SDimitry Andric } 1608*0b57cec5SDimitry Andric 1609*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateSEXTi(const APInt &A1, unsigned Width, 1610*0b57cec5SDimitry Andric unsigned Bits, APInt &Result) { 1611*0b57cec5SDimitry Andric unsigned BW = A1.getBitWidth(); 1612*0b57cec5SDimitry Andric assert(Width >= Bits && BW >= Bits); 1613*0b57cec5SDimitry Andric // Special case to make things faster for smaller source widths. 1614*0b57cec5SDimitry Andric // Sign extension of 0 bits generates 0 as a result. This is consistent 1615*0b57cec5SDimitry Andric // with what the HW does. 1616*0b57cec5SDimitry Andric if (Bits == 0) { 1617*0b57cec5SDimitry Andric Result = APInt(Width, 0); 1618*0b57cec5SDimitry Andric return true; 1619*0b57cec5SDimitry Andric } 1620*0b57cec5SDimitry Andric // In C, shifts by 64 invoke undefined behavior: handle that case in APInt. 1621*0b57cec5SDimitry Andric if (BW <= 64 && Bits != 0) { 1622*0b57cec5SDimitry Andric int64_t V = A1.getSExtValue(); 1623*0b57cec5SDimitry Andric switch (Bits) { 1624*0b57cec5SDimitry Andric case 8: 1625*0b57cec5SDimitry Andric V = static_cast<int8_t>(V); 1626*0b57cec5SDimitry Andric break; 1627*0b57cec5SDimitry Andric case 16: 1628*0b57cec5SDimitry Andric V = static_cast<int16_t>(V); 1629*0b57cec5SDimitry Andric break; 1630*0b57cec5SDimitry Andric case 32: 1631*0b57cec5SDimitry Andric V = static_cast<int32_t>(V); 1632*0b57cec5SDimitry Andric break; 1633*0b57cec5SDimitry Andric default: 1634*0b57cec5SDimitry Andric // Shift left to lose all bits except lower "Bits" bits, then shift 1635*0b57cec5SDimitry Andric // the value back, replicating what was a sign bit after the first 1636*0b57cec5SDimitry Andric // shift. 1637*0b57cec5SDimitry Andric V = (V << (64-Bits)) >> (64-Bits); 1638*0b57cec5SDimitry Andric break; 1639*0b57cec5SDimitry Andric } 1640*0b57cec5SDimitry Andric // V is a 64-bit sign-extended value. Convert it to APInt of desired 1641*0b57cec5SDimitry Andric // width. 1642*0b57cec5SDimitry Andric Result = APInt(Width, V, true); 1643*0b57cec5SDimitry Andric return true; 1644*0b57cec5SDimitry Andric } 1645*0b57cec5SDimitry Andric // Slow case: the value doesn't fit in int64_t. 1646*0b57cec5SDimitry Andric if (Bits < BW) 1647*0b57cec5SDimitry Andric Result = A1.trunc(Bits).sext(Width); 1648*0b57cec5SDimitry Andric else // Bits == BW 1649*0b57cec5SDimitry Andric Result = A1.sext(Width); 1650*0b57cec5SDimitry Andric return true; 1651*0b57cec5SDimitry Andric } 1652*0b57cec5SDimitry Andric 1653*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCLBr(const RegisterSubReg &R1, bool Zeros, 1654*0b57cec5SDimitry Andric bool Ones, const CellMap &Inputs, LatticeCell &Result) { 1655*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg)); 1656*0b57cec5SDimitry Andric LatticeCell LS1; 1657*0b57cec5SDimitry Andric if (!getCell(R1, Inputs, LS1)) 1658*0b57cec5SDimitry Andric return false; 1659*0b57cec5SDimitry Andric if (LS1.isBottom() || LS1.isProperty()) 1660*0b57cec5SDimitry Andric return false; 1661*0b57cec5SDimitry Andric 1662*0b57cec5SDimitry Andric APInt A, CA; 1663*0b57cec5SDimitry Andric for (unsigned i = 0; i < LS1.size(); ++i) { 1664*0b57cec5SDimitry Andric bool Eval = constToInt(LS1.Values[i], A) && 1665*0b57cec5SDimitry Andric evaluateCLBi(A, Zeros, Ones, CA); 1666*0b57cec5SDimitry Andric if (!Eval) 1667*0b57cec5SDimitry Andric return false; 1668*0b57cec5SDimitry Andric const Constant *C = intToConst(CA); 1669*0b57cec5SDimitry Andric Result.add(C); 1670*0b57cec5SDimitry Andric } 1671*0b57cec5SDimitry Andric return true; 1672*0b57cec5SDimitry Andric } 1673*0b57cec5SDimitry Andric 1674*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCLBi(const APInt &A1, bool Zeros, 1675*0b57cec5SDimitry Andric bool Ones, APInt &Result) { 1676*0b57cec5SDimitry Andric unsigned BW = A1.getBitWidth(); 1677*0b57cec5SDimitry Andric if (!Zeros && !Ones) 1678*0b57cec5SDimitry Andric return false; 1679*0b57cec5SDimitry Andric unsigned Count = 0; 1680*0b57cec5SDimitry Andric if (Zeros && (Count == 0)) 1681*0b57cec5SDimitry Andric Count = A1.countLeadingZeros(); 1682*0b57cec5SDimitry Andric if (Ones && (Count == 0)) 1683*0b57cec5SDimitry Andric Count = A1.countLeadingOnes(); 1684*0b57cec5SDimitry Andric Result = APInt(BW, static_cast<uint64_t>(Count), false); 1685*0b57cec5SDimitry Andric return true; 1686*0b57cec5SDimitry Andric } 1687*0b57cec5SDimitry Andric 1688*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCTBr(const RegisterSubReg &R1, bool Zeros, 1689*0b57cec5SDimitry Andric bool Ones, const CellMap &Inputs, LatticeCell &Result) { 1690*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg)); 1691*0b57cec5SDimitry Andric LatticeCell LS1; 1692*0b57cec5SDimitry Andric if (!getCell(R1, Inputs, LS1)) 1693*0b57cec5SDimitry Andric return false; 1694*0b57cec5SDimitry Andric if (LS1.isBottom() || LS1.isProperty()) 1695*0b57cec5SDimitry Andric return false; 1696*0b57cec5SDimitry Andric 1697*0b57cec5SDimitry Andric APInt A, CA; 1698*0b57cec5SDimitry Andric for (unsigned i = 0; i < LS1.size(); ++i) { 1699*0b57cec5SDimitry Andric bool Eval = constToInt(LS1.Values[i], A) && 1700*0b57cec5SDimitry Andric evaluateCTBi(A, Zeros, Ones, CA); 1701*0b57cec5SDimitry Andric if (!Eval) 1702*0b57cec5SDimitry Andric return false; 1703*0b57cec5SDimitry Andric const Constant *C = intToConst(CA); 1704*0b57cec5SDimitry Andric Result.add(C); 1705*0b57cec5SDimitry Andric } 1706*0b57cec5SDimitry Andric return true; 1707*0b57cec5SDimitry Andric } 1708*0b57cec5SDimitry Andric 1709*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateCTBi(const APInt &A1, bool Zeros, 1710*0b57cec5SDimitry Andric bool Ones, APInt &Result) { 1711*0b57cec5SDimitry Andric unsigned BW = A1.getBitWidth(); 1712*0b57cec5SDimitry Andric if (!Zeros && !Ones) 1713*0b57cec5SDimitry Andric return false; 1714*0b57cec5SDimitry Andric unsigned Count = 0; 1715*0b57cec5SDimitry Andric if (Zeros && (Count == 0)) 1716*0b57cec5SDimitry Andric Count = A1.countTrailingZeros(); 1717*0b57cec5SDimitry Andric if (Ones && (Count == 0)) 1718*0b57cec5SDimitry Andric Count = A1.countTrailingOnes(); 1719*0b57cec5SDimitry Andric Result = APInt(BW, static_cast<uint64_t>(Count), false); 1720*0b57cec5SDimitry Andric return true; 1721*0b57cec5SDimitry Andric } 1722*0b57cec5SDimitry Andric 1723*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateEXTRACTr(const RegisterSubReg &R1, 1724*0b57cec5SDimitry Andric unsigned Width, unsigned Bits, unsigned Offset, bool Signed, 1725*0b57cec5SDimitry Andric const CellMap &Inputs, LatticeCell &Result) { 1726*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg)); 1727*0b57cec5SDimitry Andric assert(Bits+Offset <= Width); 1728*0b57cec5SDimitry Andric LatticeCell LS1; 1729*0b57cec5SDimitry Andric if (!getCell(R1, Inputs, LS1)) 1730*0b57cec5SDimitry Andric return false; 1731*0b57cec5SDimitry Andric if (LS1.isBottom()) 1732*0b57cec5SDimitry Andric return false; 1733*0b57cec5SDimitry Andric if (LS1.isProperty()) { 1734*0b57cec5SDimitry Andric uint32_t Ps = LS1.properties(); 1735*0b57cec5SDimitry Andric if (Ps & ConstantProperties::Zero) { 1736*0b57cec5SDimitry Andric const Constant *C = intToConst(APInt(Width, 0, false)); 1737*0b57cec5SDimitry Andric Result.add(C); 1738*0b57cec5SDimitry Andric return true; 1739*0b57cec5SDimitry Andric } 1740*0b57cec5SDimitry Andric return false; 1741*0b57cec5SDimitry Andric } 1742*0b57cec5SDimitry Andric 1743*0b57cec5SDimitry Andric APInt A, CA; 1744*0b57cec5SDimitry Andric for (unsigned i = 0; i < LS1.size(); ++i) { 1745*0b57cec5SDimitry Andric bool Eval = constToInt(LS1.Values[i], A) && 1746*0b57cec5SDimitry Andric evaluateEXTRACTi(A, Bits, Offset, Signed, CA); 1747*0b57cec5SDimitry Andric if (!Eval) 1748*0b57cec5SDimitry Andric return false; 1749*0b57cec5SDimitry Andric const Constant *C = intToConst(CA); 1750*0b57cec5SDimitry Andric Result.add(C); 1751*0b57cec5SDimitry Andric } 1752*0b57cec5SDimitry Andric return true; 1753*0b57cec5SDimitry Andric } 1754*0b57cec5SDimitry Andric 1755*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateEXTRACTi(const APInt &A1, unsigned Bits, 1756*0b57cec5SDimitry Andric unsigned Offset, bool Signed, APInt &Result) { 1757*0b57cec5SDimitry Andric unsigned BW = A1.getBitWidth(); 1758*0b57cec5SDimitry Andric assert(Bits+Offset <= BW); 1759*0b57cec5SDimitry Andric // Extracting 0 bits generates 0 as a result (as indicated by the HW people). 1760*0b57cec5SDimitry Andric if (Bits == 0) { 1761*0b57cec5SDimitry Andric Result = APInt(BW, 0); 1762*0b57cec5SDimitry Andric return true; 1763*0b57cec5SDimitry Andric } 1764*0b57cec5SDimitry Andric if (BW <= 64) { 1765*0b57cec5SDimitry Andric int64_t V = A1.getZExtValue(); 1766*0b57cec5SDimitry Andric V <<= (64-Bits-Offset); 1767*0b57cec5SDimitry Andric if (Signed) 1768*0b57cec5SDimitry Andric V >>= (64-Bits); 1769*0b57cec5SDimitry Andric else 1770*0b57cec5SDimitry Andric V = static_cast<uint64_t>(V) >> (64-Bits); 1771*0b57cec5SDimitry Andric Result = APInt(BW, V, Signed); 1772*0b57cec5SDimitry Andric return true; 1773*0b57cec5SDimitry Andric } 1774*0b57cec5SDimitry Andric if (Signed) 1775*0b57cec5SDimitry Andric Result = A1.shl(BW-Bits-Offset).ashr(BW-Bits); 1776*0b57cec5SDimitry Andric else 1777*0b57cec5SDimitry Andric Result = A1.shl(BW-Bits-Offset).lshr(BW-Bits); 1778*0b57cec5SDimitry Andric return true; 1779*0b57cec5SDimitry Andric } 1780*0b57cec5SDimitry Andric 1781*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateSplatr(const RegisterSubReg &R1, 1782*0b57cec5SDimitry Andric unsigned Bits, unsigned Count, const CellMap &Inputs, 1783*0b57cec5SDimitry Andric LatticeCell &Result) { 1784*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg)); 1785*0b57cec5SDimitry Andric LatticeCell LS1; 1786*0b57cec5SDimitry Andric if (!getCell(R1, Inputs, LS1)) 1787*0b57cec5SDimitry Andric return false; 1788*0b57cec5SDimitry Andric if (LS1.isBottom() || LS1.isProperty()) 1789*0b57cec5SDimitry Andric return false; 1790*0b57cec5SDimitry Andric 1791*0b57cec5SDimitry Andric APInt A, SA; 1792*0b57cec5SDimitry Andric for (unsigned i = 0; i < LS1.size(); ++i) { 1793*0b57cec5SDimitry Andric bool Eval = constToInt(LS1.Values[i], A) && 1794*0b57cec5SDimitry Andric evaluateSplati(A, Bits, Count, SA); 1795*0b57cec5SDimitry Andric if (!Eval) 1796*0b57cec5SDimitry Andric return false; 1797*0b57cec5SDimitry Andric const Constant *C = intToConst(SA); 1798*0b57cec5SDimitry Andric Result.add(C); 1799*0b57cec5SDimitry Andric } 1800*0b57cec5SDimitry Andric return true; 1801*0b57cec5SDimitry Andric } 1802*0b57cec5SDimitry Andric 1803*0b57cec5SDimitry Andric bool MachineConstEvaluator::evaluateSplati(const APInt &A1, unsigned Bits, 1804*0b57cec5SDimitry Andric unsigned Count, APInt &Result) { 1805*0b57cec5SDimitry Andric assert(Count > 0); 1806*0b57cec5SDimitry Andric unsigned BW = A1.getBitWidth(), SW = Count*Bits; 1807*0b57cec5SDimitry Andric APInt LoBits = (Bits < BW) ? A1.trunc(Bits) : A1.zextOrSelf(Bits); 1808*0b57cec5SDimitry Andric if (Count > 1) 1809*0b57cec5SDimitry Andric LoBits = LoBits.zext(SW); 1810*0b57cec5SDimitry Andric 1811*0b57cec5SDimitry Andric APInt Res(SW, 0, false); 1812*0b57cec5SDimitry Andric for (unsigned i = 0; i < Count; ++i) { 1813*0b57cec5SDimitry Andric Res <<= Bits; 1814*0b57cec5SDimitry Andric Res |= LoBits; 1815*0b57cec5SDimitry Andric } 1816*0b57cec5SDimitry Andric Result = Res; 1817*0b57cec5SDimitry Andric return true; 1818*0b57cec5SDimitry Andric } 1819*0b57cec5SDimitry Andric 1820*0b57cec5SDimitry Andric // ---------------------------------------------------------------------- 1821*0b57cec5SDimitry Andric // Hexagon-specific code. 1822*0b57cec5SDimitry Andric 1823*0b57cec5SDimitry Andric namespace llvm { 1824*0b57cec5SDimitry Andric 1825*0b57cec5SDimitry Andric FunctionPass *createHexagonConstPropagationPass(); 1826*0b57cec5SDimitry Andric void initializeHexagonConstPropagationPass(PassRegistry &Registry); 1827*0b57cec5SDimitry Andric 1828*0b57cec5SDimitry Andric } // end namespace llvm 1829*0b57cec5SDimitry Andric 1830*0b57cec5SDimitry Andric namespace { 1831*0b57cec5SDimitry Andric 1832*0b57cec5SDimitry Andric class HexagonConstEvaluator : public MachineConstEvaluator { 1833*0b57cec5SDimitry Andric public: 1834*0b57cec5SDimitry Andric HexagonConstEvaluator(MachineFunction &Fn); 1835*0b57cec5SDimitry Andric 1836*0b57cec5SDimitry Andric bool evaluate(const MachineInstr &MI, const CellMap &Inputs, 1837*0b57cec5SDimitry Andric CellMap &Outputs) override; 1838*0b57cec5SDimitry Andric bool evaluate(const RegisterSubReg &R, const LatticeCell &SrcC, 1839*0b57cec5SDimitry Andric LatticeCell &Result) override; 1840*0b57cec5SDimitry Andric bool evaluate(const MachineInstr &BrI, const CellMap &Inputs, 1841*0b57cec5SDimitry Andric SetVector<const MachineBasicBlock*> &Targets, bool &FallsThru) 1842*0b57cec5SDimitry Andric override; 1843*0b57cec5SDimitry Andric bool rewrite(MachineInstr &MI, const CellMap &Inputs) override; 1844*0b57cec5SDimitry Andric 1845*0b57cec5SDimitry Andric private: 1846*0b57cec5SDimitry Andric unsigned getRegBitWidth(unsigned Reg) const; 1847*0b57cec5SDimitry Andric 1848*0b57cec5SDimitry Andric static uint32_t getCmp(unsigned Opc); 1849*0b57cec5SDimitry Andric static APInt getCmpImm(unsigned Opc, unsigned OpX, 1850*0b57cec5SDimitry Andric const MachineOperand &MO); 1851*0b57cec5SDimitry Andric void replaceWithNop(MachineInstr &MI); 1852*0b57cec5SDimitry Andric 1853*0b57cec5SDimitry Andric bool evaluateHexRSEQ32(RegisterSubReg RL, RegisterSubReg RH, const CellMap &Inputs, 1854*0b57cec5SDimitry Andric LatticeCell &Result); 1855*0b57cec5SDimitry Andric bool evaluateHexCompare(const MachineInstr &MI, const CellMap &Inputs, 1856*0b57cec5SDimitry Andric CellMap &Outputs); 1857*0b57cec5SDimitry Andric // This is suitable to be called for compare-and-jump instructions. 1858*0b57cec5SDimitry Andric bool evaluateHexCompare2(uint32_t Cmp, const MachineOperand &Src1, 1859*0b57cec5SDimitry Andric const MachineOperand &Src2, const CellMap &Inputs, bool &Result); 1860*0b57cec5SDimitry Andric bool evaluateHexLogical(const MachineInstr &MI, const CellMap &Inputs, 1861*0b57cec5SDimitry Andric CellMap &Outputs); 1862*0b57cec5SDimitry Andric bool evaluateHexCondMove(const MachineInstr &MI, const CellMap &Inputs, 1863*0b57cec5SDimitry Andric CellMap &Outputs); 1864*0b57cec5SDimitry Andric bool evaluateHexExt(const MachineInstr &MI, const CellMap &Inputs, 1865*0b57cec5SDimitry Andric CellMap &Outputs); 1866*0b57cec5SDimitry Andric bool evaluateHexVector1(const MachineInstr &MI, const CellMap &Inputs, 1867*0b57cec5SDimitry Andric CellMap &Outputs); 1868*0b57cec5SDimitry Andric bool evaluateHexVector2(const MachineInstr &MI, const CellMap &Inputs, 1869*0b57cec5SDimitry Andric CellMap &Outputs); 1870*0b57cec5SDimitry Andric 1871*0b57cec5SDimitry Andric void replaceAllRegUsesWith(unsigned FromReg, unsigned ToReg); 1872*0b57cec5SDimitry Andric bool rewriteHexBranch(MachineInstr &BrI, const CellMap &Inputs); 1873*0b57cec5SDimitry Andric bool rewriteHexConstDefs(MachineInstr &MI, const CellMap &Inputs, 1874*0b57cec5SDimitry Andric bool &AllDefs); 1875*0b57cec5SDimitry Andric bool rewriteHexConstUses(MachineInstr &MI, const CellMap &Inputs); 1876*0b57cec5SDimitry Andric 1877*0b57cec5SDimitry Andric MachineRegisterInfo *MRI; 1878*0b57cec5SDimitry Andric const HexagonInstrInfo &HII; 1879*0b57cec5SDimitry Andric const HexagonRegisterInfo &HRI; 1880*0b57cec5SDimitry Andric }; 1881*0b57cec5SDimitry Andric 1882*0b57cec5SDimitry Andric class HexagonConstPropagation : public MachineFunctionPass { 1883*0b57cec5SDimitry Andric public: 1884*0b57cec5SDimitry Andric static char ID; 1885*0b57cec5SDimitry Andric 1886*0b57cec5SDimitry Andric HexagonConstPropagation() : MachineFunctionPass(ID) {} 1887*0b57cec5SDimitry Andric 1888*0b57cec5SDimitry Andric StringRef getPassName() const override { 1889*0b57cec5SDimitry Andric return "Hexagon Constant Propagation"; 1890*0b57cec5SDimitry Andric } 1891*0b57cec5SDimitry Andric 1892*0b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override { 1893*0b57cec5SDimitry Andric const Function &F = MF.getFunction(); 1894*0b57cec5SDimitry Andric if (skipFunction(F)) 1895*0b57cec5SDimitry Andric return false; 1896*0b57cec5SDimitry Andric 1897*0b57cec5SDimitry Andric HexagonConstEvaluator HCE(MF); 1898*0b57cec5SDimitry Andric return MachineConstPropagator(HCE).run(MF); 1899*0b57cec5SDimitry Andric } 1900*0b57cec5SDimitry Andric }; 1901*0b57cec5SDimitry Andric 1902*0b57cec5SDimitry Andric } // end anonymous namespace 1903*0b57cec5SDimitry Andric 1904*0b57cec5SDimitry Andric char HexagonConstPropagation::ID = 0; 1905*0b57cec5SDimitry Andric 1906*0b57cec5SDimitry Andric INITIALIZE_PASS(HexagonConstPropagation, "hexagon-constp", 1907*0b57cec5SDimitry Andric "Hexagon Constant Propagation", false, false) 1908*0b57cec5SDimitry Andric 1909*0b57cec5SDimitry Andric HexagonConstEvaluator::HexagonConstEvaluator(MachineFunction &Fn) 1910*0b57cec5SDimitry Andric : MachineConstEvaluator(Fn), 1911*0b57cec5SDimitry Andric HII(*Fn.getSubtarget<HexagonSubtarget>().getInstrInfo()), 1912*0b57cec5SDimitry Andric HRI(*Fn.getSubtarget<HexagonSubtarget>().getRegisterInfo()) { 1913*0b57cec5SDimitry Andric MRI = &Fn.getRegInfo(); 1914*0b57cec5SDimitry Andric } 1915*0b57cec5SDimitry Andric 1916*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluate(const MachineInstr &MI, 1917*0b57cec5SDimitry Andric const CellMap &Inputs, CellMap &Outputs) { 1918*0b57cec5SDimitry Andric if (MI.isCall()) 1919*0b57cec5SDimitry Andric return false; 1920*0b57cec5SDimitry Andric if (MI.getNumOperands() == 0 || !MI.getOperand(0).isReg()) 1921*0b57cec5SDimitry Andric return false; 1922*0b57cec5SDimitry Andric const MachineOperand &MD = MI.getOperand(0); 1923*0b57cec5SDimitry Andric if (!MD.isDef()) 1924*0b57cec5SDimitry Andric return false; 1925*0b57cec5SDimitry Andric 1926*0b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 1927*0b57cec5SDimitry Andric RegisterSubReg DefR(MD); 1928*0b57cec5SDimitry Andric assert(!DefR.SubReg); 1929*0b57cec5SDimitry Andric if (!TargetRegisterInfo::isVirtualRegister(DefR.Reg)) 1930*0b57cec5SDimitry Andric return false; 1931*0b57cec5SDimitry Andric 1932*0b57cec5SDimitry Andric if (MI.isCopy()) { 1933*0b57cec5SDimitry Andric LatticeCell RC; 1934*0b57cec5SDimitry Andric RegisterSubReg SrcR(MI.getOperand(1)); 1935*0b57cec5SDimitry Andric bool Eval = evaluateCOPY(SrcR, Inputs, RC); 1936*0b57cec5SDimitry Andric if (!Eval) 1937*0b57cec5SDimitry Andric return false; 1938*0b57cec5SDimitry Andric Outputs.update(DefR.Reg, RC); 1939*0b57cec5SDimitry Andric return true; 1940*0b57cec5SDimitry Andric } 1941*0b57cec5SDimitry Andric if (MI.isRegSequence()) { 1942*0b57cec5SDimitry Andric unsigned Sub1 = MI.getOperand(2).getImm(); 1943*0b57cec5SDimitry Andric unsigned Sub2 = MI.getOperand(4).getImm(); 1944*0b57cec5SDimitry Andric const TargetRegisterClass &DefRC = *MRI->getRegClass(DefR.Reg); 1945*0b57cec5SDimitry Andric unsigned SubLo = HRI.getHexagonSubRegIndex(DefRC, Hexagon::ps_sub_lo); 1946*0b57cec5SDimitry Andric unsigned SubHi = HRI.getHexagonSubRegIndex(DefRC, Hexagon::ps_sub_hi); 1947*0b57cec5SDimitry Andric if (Sub1 != SubLo && Sub1 != SubHi) 1948*0b57cec5SDimitry Andric return false; 1949*0b57cec5SDimitry Andric if (Sub2 != SubLo && Sub2 != SubHi) 1950*0b57cec5SDimitry Andric return false; 1951*0b57cec5SDimitry Andric assert(Sub1 != Sub2); 1952*0b57cec5SDimitry Andric bool LoIs1 = (Sub1 == SubLo); 1953*0b57cec5SDimitry Andric const MachineOperand &OpLo = LoIs1 ? MI.getOperand(1) : MI.getOperand(3); 1954*0b57cec5SDimitry Andric const MachineOperand &OpHi = LoIs1 ? MI.getOperand(3) : MI.getOperand(1); 1955*0b57cec5SDimitry Andric LatticeCell RC; 1956*0b57cec5SDimitry Andric RegisterSubReg SrcRL(OpLo), SrcRH(OpHi); 1957*0b57cec5SDimitry Andric bool Eval = evaluateHexRSEQ32(SrcRL, SrcRH, Inputs, RC); 1958*0b57cec5SDimitry Andric if (!Eval) 1959*0b57cec5SDimitry Andric return false; 1960*0b57cec5SDimitry Andric Outputs.update(DefR.Reg, RC); 1961*0b57cec5SDimitry Andric return true; 1962*0b57cec5SDimitry Andric } 1963*0b57cec5SDimitry Andric if (MI.isCompare()) { 1964*0b57cec5SDimitry Andric bool Eval = evaluateHexCompare(MI, Inputs, Outputs); 1965*0b57cec5SDimitry Andric return Eval; 1966*0b57cec5SDimitry Andric } 1967*0b57cec5SDimitry Andric 1968*0b57cec5SDimitry Andric switch (Opc) { 1969*0b57cec5SDimitry Andric default: 1970*0b57cec5SDimitry Andric return false; 1971*0b57cec5SDimitry Andric case Hexagon::A2_tfrsi: 1972*0b57cec5SDimitry Andric case Hexagon::A2_tfrpi: 1973*0b57cec5SDimitry Andric case Hexagon::CONST32: 1974*0b57cec5SDimitry Andric case Hexagon::CONST64: 1975*0b57cec5SDimitry Andric { 1976*0b57cec5SDimitry Andric const MachineOperand &VO = MI.getOperand(1); 1977*0b57cec5SDimitry Andric // The operand of CONST32 can be a blockaddress, e.g. 1978*0b57cec5SDimitry Andric // %0 = CONST32 <blockaddress(@eat, %l)> 1979*0b57cec5SDimitry Andric // Do this check for all instructions for safety. 1980*0b57cec5SDimitry Andric if (!VO.isImm()) 1981*0b57cec5SDimitry Andric return false; 1982*0b57cec5SDimitry Andric int64_t V = MI.getOperand(1).getImm(); 1983*0b57cec5SDimitry Andric unsigned W = getRegBitWidth(DefR.Reg); 1984*0b57cec5SDimitry Andric if (W != 32 && W != 64) 1985*0b57cec5SDimitry Andric return false; 1986*0b57cec5SDimitry Andric IntegerType *Ty = (W == 32) ? Type::getInt32Ty(CX) 1987*0b57cec5SDimitry Andric : Type::getInt64Ty(CX); 1988*0b57cec5SDimitry Andric const ConstantInt *CI = ConstantInt::get(Ty, V, true); 1989*0b57cec5SDimitry Andric LatticeCell RC = Outputs.get(DefR.Reg); 1990*0b57cec5SDimitry Andric RC.add(CI); 1991*0b57cec5SDimitry Andric Outputs.update(DefR.Reg, RC); 1992*0b57cec5SDimitry Andric break; 1993*0b57cec5SDimitry Andric } 1994*0b57cec5SDimitry Andric 1995*0b57cec5SDimitry Andric case Hexagon::PS_true: 1996*0b57cec5SDimitry Andric case Hexagon::PS_false: 1997*0b57cec5SDimitry Andric { 1998*0b57cec5SDimitry Andric LatticeCell RC = Outputs.get(DefR.Reg); 1999*0b57cec5SDimitry Andric bool NonZero = (Opc == Hexagon::PS_true); 2000*0b57cec5SDimitry Andric uint32_t P = NonZero ? ConstantProperties::NonZero 2001*0b57cec5SDimitry Andric : ConstantProperties::Zero; 2002*0b57cec5SDimitry Andric RC.add(P); 2003*0b57cec5SDimitry Andric Outputs.update(DefR.Reg, RC); 2004*0b57cec5SDimitry Andric break; 2005*0b57cec5SDimitry Andric } 2006*0b57cec5SDimitry Andric 2007*0b57cec5SDimitry Andric case Hexagon::A2_and: 2008*0b57cec5SDimitry Andric case Hexagon::A2_andir: 2009*0b57cec5SDimitry Andric case Hexagon::A2_andp: 2010*0b57cec5SDimitry Andric case Hexagon::A2_or: 2011*0b57cec5SDimitry Andric case Hexagon::A2_orir: 2012*0b57cec5SDimitry Andric case Hexagon::A2_orp: 2013*0b57cec5SDimitry Andric case Hexagon::A2_xor: 2014*0b57cec5SDimitry Andric case Hexagon::A2_xorp: 2015*0b57cec5SDimitry Andric { 2016*0b57cec5SDimitry Andric bool Eval = evaluateHexLogical(MI, Inputs, Outputs); 2017*0b57cec5SDimitry Andric if (!Eval) 2018*0b57cec5SDimitry Andric return false; 2019*0b57cec5SDimitry Andric break; 2020*0b57cec5SDimitry Andric } 2021*0b57cec5SDimitry Andric 2022*0b57cec5SDimitry Andric case Hexagon::A2_combineii: // combine(#s8Ext, #s8) 2023*0b57cec5SDimitry Andric case Hexagon::A4_combineii: // combine(#s8, #u6Ext) 2024*0b57cec5SDimitry Andric { 2025*0b57cec5SDimitry Andric if (!MI.getOperand(1).isImm() || !MI.getOperand(2).isImm()) 2026*0b57cec5SDimitry Andric return false; 2027*0b57cec5SDimitry Andric uint64_t Hi = MI.getOperand(1).getImm(); 2028*0b57cec5SDimitry Andric uint64_t Lo = MI.getOperand(2).getImm(); 2029*0b57cec5SDimitry Andric uint64_t Res = (Hi << 32) | (Lo & 0xFFFFFFFF); 2030*0b57cec5SDimitry Andric IntegerType *Ty = Type::getInt64Ty(CX); 2031*0b57cec5SDimitry Andric const ConstantInt *CI = ConstantInt::get(Ty, Res, false); 2032*0b57cec5SDimitry Andric LatticeCell RC = Outputs.get(DefR.Reg); 2033*0b57cec5SDimitry Andric RC.add(CI); 2034*0b57cec5SDimitry Andric Outputs.update(DefR.Reg, RC); 2035*0b57cec5SDimitry Andric break; 2036*0b57cec5SDimitry Andric } 2037*0b57cec5SDimitry Andric 2038*0b57cec5SDimitry Andric case Hexagon::S2_setbit_i: 2039*0b57cec5SDimitry Andric { 2040*0b57cec5SDimitry Andric int64_t B = MI.getOperand(2).getImm(); 2041*0b57cec5SDimitry Andric assert(B >=0 && B < 32); 2042*0b57cec5SDimitry Andric APInt A(32, (1ull << B), false); 2043*0b57cec5SDimitry Andric RegisterSubReg R(MI.getOperand(1)); 2044*0b57cec5SDimitry Andric LatticeCell RC = Outputs.get(DefR.Reg); 2045*0b57cec5SDimitry Andric bool Eval = evaluateORri(R, A, Inputs, RC); 2046*0b57cec5SDimitry Andric if (!Eval) 2047*0b57cec5SDimitry Andric return false; 2048*0b57cec5SDimitry Andric Outputs.update(DefR.Reg, RC); 2049*0b57cec5SDimitry Andric break; 2050*0b57cec5SDimitry Andric } 2051*0b57cec5SDimitry Andric 2052*0b57cec5SDimitry Andric case Hexagon::C2_mux: 2053*0b57cec5SDimitry Andric case Hexagon::C2_muxir: 2054*0b57cec5SDimitry Andric case Hexagon::C2_muxri: 2055*0b57cec5SDimitry Andric case Hexagon::C2_muxii: 2056*0b57cec5SDimitry Andric { 2057*0b57cec5SDimitry Andric bool Eval = evaluateHexCondMove(MI, Inputs, Outputs); 2058*0b57cec5SDimitry Andric if (!Eval) 2059*0b57cec5SDimitry Andric return false; 2060*0b57cec5SDimitry Andric break; 2061*0b57cec5SDimitry Andric } 2062*0b57cec5SDimitry Andric 2063*0b57cec5SDimitry Andric case Hexagon::A2_sxtb: 2064*0b57cec5SDimitry Andric case Hexagon::A2_sxth: 2065*0b57cec5SDimitry Andric case Hexagon::A2_sxtw: 2066*0b57cec5SDimitry Andric case Hexagon::A2_zxtb: 2067*0b57cec5SDimitry Andric case Hexagon::A2_zxth: 2068*0b57cec5SDimitry Andric { 2069*0b57cec5SDimitry Andric bool Eval = evaluateHexExt(MI, Inputs, Outputs); 2070*0b57cec5SDimitry Andric if (!Eval) 2071*0b57cec5SDimitry Andric return false; 2072*0b57cec5SDimitry Andric break; 2073*0b57cec5SDimitry Andric } 2074*0b57cec5SDimitry Andric 2075*0b57cec5SDimitry Andric case Hexagon::S2_ct0: 2076*0b57cec5SDimitry Andric case Hexagon::S2_ct0p: 2077*0b57cec5SDimitry Andric case Hexagon::S2_ct1: 2078*0b57cec5SDimitry Andric case Hexagon::S2_ct1p: 2079*0b57cec5SDimitry Andric { 2080*0b57cec5SDimitry Andric using namespace Hexagon; 2081*0b57cec5SDimitry Andric 2082*0b57cec5SDimitry Andric bool Ones = (Opc == S2_ct1) || (Opc == S2_ct1p); 2083*0b57cec5SDimitry Andric RegisterSubReg R1(MI.getOperand(1)); 2084*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg)); 2085*0b57cec5SDimitry Andric LatticeCell T; 2086*0b57cec5SDimitry Andric bool Eval = evaluateCTBr(R1, !Ones, Ones, Inputs, T); 2087*0b57cec5SDimitry Andric if (!Eval) 2088*0b57cec5SDimitry Andric return false; 2089*0b57cec5SDimitry Andric // All of these instructions return a 32-bit value. The evaluate 2090*0b57cec5SDimitry Andric // will generate the same type as the operand, so truncate the 2091*0b57cec5SDimitry Andric // result if necessary. 2092*0b57cec5SDimitry Andric APInt C; 2093*0b57cec5SDimitry Andric LatticeCell RC = Outputs.get(DefR.Reg); 2094*0b57cec5SDimitry Andric for (unsigned i = 0; i < T.size(); ++i) { 2095*0b57cec5SDimitry Andric const Constant *CI = T.Values[i]; 2096*0b57cec5SDimitry Andric if (constToInt(CI, C) && C.getBitWidth() > 32) 2097*0b57cec5SDimitry Andric CI = intToConst(C.trunc(32)); 2098*0b57cec5SDimitry Andric RC.add(CI); 2099*0b57cec5SDimitry Andric } 2100*0b57cec5SDimitry Andric Outputs.update(DefR.Reg, RC); 2101*0b57cec5SDimitry Andric break; 2102*0b57cec5SDimitry Andric } 2103*0b57cec5SDimitry Andric 2104*0b57cec5SDimitry Andric case Hexagon::S2_cl0: 2105*0b57cec5SDimitry Andric case Hexagon::S2_cl0p: 2106*0b57cec5SDimitry Andric case Hexagon::S2_cl1: 2107*0b57cec5SDimitry Andric case Hexagon::S2_cl1p: 2108*0b57cec5SDimitry Andric case Hexagon::S2_clb: 2109*0b57cec5SDimitry Andric case Hexagon::S2_clbp: 2110*0b57cec5SDimitry Andric { 2111*0b57cec5SDimitry Andric using namespace Hexagon; 2112*0b57cec5SDimitry Andric 2113*0b57cec5SDimitry Andric bool OnlyZeros = (Opc == S2_cl0) || (Opc == S2_cl0p); 2114*0b57cec5SDimitry Andric bool OnlyOnes = (Opc == S2_cl1) || (Opc == S2_cl1p); 2115*0b57cec5SDimitry Andric RegisterSubReg R1(MI.getOperand(1)); 2116*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg)); 2117*0b57cec5SDimitry Andric LatticeCell T; 2118*0b57cec5SDimitry Andric bool Eval = evaluateCLBr(R1, !OnlyOnes, !OnlyZeros, Inputs, T); 2119*0b57cec5SDimitry Andric if (!Eval) 2120*0b57cec5SDimitry Andric return false; 2121*0b57cec5SDimitry Andric // All of these instructions return a 32-bit value. The evaluate 2122*0b57cec5SDimitry Andric // will generate the same type as the operand, so truncate the 2123*0b57cec5SDimitry Andric // result if necessary. 2124*0b57cec5SDimitry Andric APInt C; 2125*0b57cec5SDimitry Andric LatticeCell RC = Outputs.get(DefR.Reg); 2126*0b57cec5SDimitry Andric for (unsigned i = 0; i < T.size(); ++i) { 2127*0b57cec5SDimitry Andric const Constant *CI = T.Values[i]; 2128*0b57cec5SDimitry Andric if (constToInt(CI, C) && C.getBitWidth() > 32) 2129*0b57cec5SDimitry Andric CI = intToConst(C.trunc(32)); 2130*0b57cec5SDimitry Andric RC.add(CI); 2131*0b57cec5SDimitry Andric } 2132*0b57cec5SDimitry Andric Outputs.update(DefR.Reg, RC); 2133*0b57cec5SDimitry Andric break; 2134*0b57cec5SDimitry Andric } 2135*0b57cec5SDimitry Andric 2136*0b57cec5SDimitry Andric case Hexagon::S4_extract: 2137*0b57cec5SDimitry Andric case Hexagon::S4_extractp: 2138*0b57cec5SDimitry Andric case Hexagon::S2_extractu: 2139*0b57cec5SDimitry Andric case Hexagon::S2_extractup: 2140*0b57cec5SDimitry Andric { 2141*0b57cec5SDimitry Andric bool Signed = (Opc == Hexagon::S4_extract) || 2142*0b57cec5SDimitry Andric (Opc == Hexagon::S4_extractp); 2143*0b57cec5SDimitry Andric RegisterSubReg R1(MI.getOperand(1)); 2144*0b57cec5SDimitry Andric unsigned BW = getRegBitWidth(R1.Reg); 2145*0b57cec5SDimitry Andric unsigned Bits = MI.getOperand(2).getImm(); 2146*0b57cec5SDimitry Andric unsigned Offset = MI.getOperand(3).getImm(); 2147*0b57cec5SDimitry Andric LatticeCell RC = Outputs.get(DefR.Reg); 2148*0b57cec5SDimitry Andric if (Offset >= BW) { 2149*0b57cec5SDimitry Andric APInt Zero(BW, 0, false); 2150*0b57cec5SDimitry Andric RC.add(intToConst(Zero)); 2151*0b57cec5SDimitry Andric break; 2152*0b57cec5SDimitry Andric } 2153*0b57cec5SDimitry Andric if (Offset+Bits > BW) { 2154*0b57cec5SDimitry Andric // If the requested bitfield extends beyond the most significant bit, 2155*0b57cec5SDimitry Andric // the extra bits are treated as 0s. To emulate this behavior, reduce 2156*0b57cec5SDimitry Andric // the number of requested bits, and make the extract unsigned. 2157*0b57cec5SDimitry Andric Bits = BW-Offset; 2158*0b57cec5SDimitry Andric Signed = false; 2159*0b57cec5SDimitry Andric } 2160*0b57cec5SDimitry Andric bool Eval = evaluateEXTRACTr(R1, BW, Bits, Offset, Signed, Inputs, RC); 2161*0b57cec5SDimitry Andric if (!Eval) 2162*0b57cec5SDimitry Andric return false; 2163*0b57cec5SDimitry Andric Outputs.update(DefR.Reg, RC); 2164*0b57cec5SDimitry Andric break; 2165*0b57cec5SDimitry Andric } 2166*0b57cec5SDimitry Andric 2167*0b57cec5SDimitry Andric case Hexagon::S2_vsplatrb: 2168*0b57cec5SDimitry Andric case Hexagon::S2_vsplatrh: 2169*0b57cec5SDimitry Andric // vabsh, vabsh:sat 2170*0b57cec5SDimitry Andric // vabsw, vabsw:sat 2171*0b57cec5SDimitry Andric // vconj:sat 2172*0b57cec5SDimitry Andric // vrndwh, vrndwh:sat 2173*0b57cec5SDimitry Andric // vsathb, vsathub, vsatwuh 2174*0b57cec5SDimitry Andric // vsxtbh, vsxthw 2175*0b57cec5SDimitry Andric // vtrunehb, vtrunohb 2176*0b57cec5SDimitry Andric // vzxtbh, vzxthw 2177*0b57cec5SDimitry Andric { 2178*0b57cec5SDimitry Andric bool Eval = evaluateHexVector1(MI, Inputs, Outputs); 2179*0b57cec5SDimitry Andric if (!Eval) 2180*0b57cec5SDimitry Andric return false; 2181*0b57cec5SDimitry Andric break; 2182*0b57cec5SDimitry Andric } 2183*0b57cec5SDimitry Andric 2184*0b57cec5SDimitry Andric // TODO: 2185*0b57cec5SDimitry Andric // A2_vaddh 2186*0b57cec5SDimitry Andric // A2_vaddhs 2187*0b57cec5SDimitry Andric // A2_vaddw 2188*0b57cec5SDimitry Andric // A2_vaddws 2189*0b57cec5SDimitry Andric } 2190*0b57cec5SDimitry Andric 2191*0b57cec5SDimitry Andric return true; 2192*0b57cec5SDimitry Andric } 2193*0b57cec5SDimitry Andric 2194*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluate(const RegisterSubReg &R, 2195*0b57cec5SDimitry Andric const LatticeCell &Input, LatticeCell &Result) { 2196*0b57cec5SDimitry Andric if (!R.SubReg) { 2197*0b57cec5SDimitry Andric Result = Input; 2198*0b57cec5SDimitry Andric return true; 2199*0b57cec5SDimitry Andric } 2200*0b57cec5SDimitry Andric const TargetRegisterClass *RC = MRI->getRegClass(R.Reg); 2201*0b57cec5SDimitry Andric if (RC != &Hexagon::DoubleRegsRegClass) 2202*0b57cec5SDimitry Andric return false; 2203*0b57cec5SDimitry Andric if (R.SubReg != Hexagon::isub_lo && R.SubReg != Hexagon::isub_hi) 2204*0b57cec5SDimitry Andric return false; 2205*0b57cec5SDimitry Andric 2206*0b57cec5SDimitry Andric assert(!Input.isTop()); 2207*0b57cec5SDimitry Andric if (Input.isBottom()) 2208*0b57cec5SDimitry Andric return false; 2209*0b57cec5SDimitry Andric 2210*0b57cec5SDimitry Andric using P = ConstantProperties; 2211*0b57cec5SDimitry Andric 2212*0b57cec5SDimitry Andric if (Input.isProperty()) { 2213*0b57cec5SDimitry Andric uint32_t Ps = Input.properties(); 2214*0b57cec5SDimitry Andric if (Ps & (P::Zero|P::NaN)) { 2215*0b57cec5SDimitry Andric uint32_t Ns = (Ps & (P::Zero|P::NaN|P::SignProperties)); 2216*0b57cec5SDimitry Andric Result.add(Ns); 2217*0b57cec5SDimitry Andric return true; 2218*0b57cec5SDimitry Andric } 2219*0b57cec5SDimitry Andric if (R.SubReg == Hexagon::isub_hi) { 2220*0b57cec5SDimitry Andric uint32_t Ns = (Ps & P::SignProperties); 2221*0b57cec5SDimitry Andric Result.add(Ns); 2222*0b57cec5SDimitry Andric return true; 2223*0b57cec5SDimitry Andric } 2224*0b57cec5SDimitry Andric return false; 2225*0b57cec5SDimitry Andric } 2226*0b57cec5SDimitry Andric 2227*0b57cec5SDimitry Andric // The Input cell contains some known values. Pick the word corresponding 2228*0b57cec5SDimitry Andric // to the subregister. 2229*0b57cec5SDimitry Andric APInt A; 2230*0b57cec5SDimitry Andric for (unsigned i = 0; i < Input.size(); ++i) { 2231*0b57cec5SDimitry Andric const Constant *C = Input.Values[i]; 2232*0b57cec5SDimitry Andric if (!constToInt(C, A)) 2233*0b57cec5SDimitry Andric return false; 2234*0b57cec5SDimitry Andric if (!A.isIntN(64)) 2235*0b57cec5SDimitry Andric return false; 2236*0b57cec5SDimitry Andric uint64_t U = A.getZExtValue(); 2237*0b57cec5SDimitry Andric if (R.SubReg == Hexagon::isub_hi) 2238*0b57cec5SDimitry Andric U >>= 32; 2239*0b57cec5SDimitry Andric U &= 0xFFFFFFFFULL; 2240*0b57cec5SDimitry Andric uint32_t U32 = Lo_32(U); 2241*0b57cec5SDimitry Andric int32_t V32; 2242*0b57cec5SDimitry Andric memcpy(&V32, &U32, sizeof V32); 2243*0b57cec5SDimitry Andric IntegerType *Ty = Type::getInt32Ty(CX); 2244*0b57cec5SDimitry Andric const ConstantInt *C32 = ConstantInt::get(Ty, static_cast<int64_t>(V32)); 2245*0b57cec5SDimitry Andric Result.add(C32); 2246*0b57cec5SDimitry Andric } 2247*0b57cec5SDimitry Andric return true; 2248*0b57cec5SDimitry Andric } 2249*0b57cec5SDimitry Andric 2250*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluate(const MachineInstr &BrI, 2251*0b57cec5SDimitry Andric const CellMap &Inputs, SetVector<const MachineBasicBlock*> &Targets, 2252*0b57cec5SDimitry Andric bool &FallsThru) { 2253*0b57cec5SDimitry Andric // We need to evaluate one branch at a time. TII::analyzeBranch checks 2254*0b57cec5SDimitry Andric // all the branches in a basic block at once, so we cannot use it. 2255*0b57cec5SDimitry Andric unsigned Opc = BrI.getOpcode(); 2256*0b57cec5SDimitry Andric bool SimpleBranch = false; 2257*0b57cec5SDimitry Andric bool Negated = false; 2258*0b57cec5SDimitry Andric switch (Opc) { 2259*0b57cec5SDimitry Andric case Hexagon::J2_jumpf: 2260*0b57cec5SDimitry Andric case Hexagon::J2_jumpfnew: 2261*0b57cec5SDimitry Andric case Hexagon::J2_jumpfnewpt: 2262*0b57cec5SDimitry Andric Negated = true; 2263*0b57cec5SDimitry Andric LLVM_FALLTHROUGH; 2264*0b57cec5SDimitry Andric case Hexagon::J2_jumpt: 2265*0b57cec5SDimitry Andric case Hexagon::J2_jumptnew: 2266*0b57cec5SDimitry Andric case Hexagon::J2_jumptnewpt: 2267*0b57cec5SDimitry Andric // Simple branch: if([!]Pn) jump ... 2268*0b57cec5SDimitry Andric // i.e. Op0 = predicate, Op1 = branch target. 2269*0b57cec5SDimitry Andric SimpleBranch = true; 2270*0b57cec5SDimitry Andric break; 2271*0b57cec5SDimitry Andric case Hexagon::J2_jump: 2272*0b57cec5SDimitry Andric Targets.insert(BrI.getOperand(0).getMBB()); 2273*0b57cec5SDimitry Andric FallsThru = false; 2274*0b57cec5SDimitry Andric return true; 2275*0b57cec5SDimitry Andric default: 2276*0b57cec5SDimitry Andric Undetermined: 2277*0b57cec5SDimitry Andric // If the branch is of unknown type, assume that all successors are 2278*0b57cec5SDimitry Andric // executable. 2279*0b57cec5SDimitry Andric FallsThru = !BrI.isUnconditionalBranch(); 2280*0b57cec5SDimitry Andric return false; 2281*0b57cec5SDimitry Andric } 2282*0b57cec5SDimitry Andric 2283*0b57cec5SDimitry Andric if (SimpleBranch) { 2284*0b57cec5SDimitry Andric const MachineOperand &MD = BrI.getOperand(0); 2285*0b57cec5SDimitry Andric RegisterSubReg PR(MD); 2286*0b57cec5SDimitry Andric // If the condition operand has a subregister, this is not something 2287*0b57cec5SDimitry Andric // we currently recognize. 2288*0b57cec5SDimitry Andric if (PR.SubReg) 2289*0b57cec5SDimitry Andric goto Undetermined; 2290*0b57cec5SDimitry Andric assert(Inputs.has(PR.Reg)); 2291*0b57cec5SDimitry Andric const LatticeCell &PredC = Inputs.get(PR.Reg); 2292*0b57cec5SDimitry Andric if (PredC.isBottom()) 2293*0b57cec5SDimitry Andric goto Undetermined; 2294*0b57cec5SDimitry Andric 2295*0b57cec5SDimitry Andric uint32_t Props = PredC.properties(); 2296*0b57cec5SDimitry Andric bool CTrue = false, CFalse = false; 2297*0b57cec5SDimitry Andric if (Props & ConstantProperties::Zero) 2298*0b57cec5SDimitry Andric CFalse = true; 2299*0b57cec5SDimitry Andric else if (Props & ConstantProperties::NonZero) 2300*0b57cec5SDimitry Andric CTrue = true; 2301*0b57cec5SDimitry Andric // If the condition is not known to be either, bail out. 2302*0b57cec5SDimitry Andric if (!CTrue && !CFalse) 2303*0b57cec5SDimitry Andric goto Undetermined; 2304*0b57cec5SDimitry Andric 2305*0b57cec5SDimitry Andric const MachineBasicBlock *BranchTarget = BrI.getOperand(1).getMBB(); 2306*0b57cec5SDimitry Andric 2307*0b57cec5SDimitry Andric FallsThru = false; 2308*0b57cec5SDimitry Andric if ((!Negated && CTrue) || (Negated && CFalse)) 2309*0b57cec5SDimitry Andric Targets.insert(BranchTarget); 2310*0b57cec5SDimitry Andric else if ((!Negated && CFalse) || (Negated && CTrue)) 2311*0b57cec5SDimitry Andric FallsThru = true; 2312*0b57cec5SDimitry Andric else 2313*0b57cec5SDimitry Andric goto Undetermined; 2314*0b57cec5SDimitry Andric } 2315*0b57cec5SDimitry Andric 2316*0b57cec5SDimitry Andric return true; 2317*0b57cec5SDimitry Andric } 2318*0b57cec5SDimitry Andric 2319*0b57cec5SDimitry Andric bool HexagonConstEvaluator::rewrite(MachineInstr &MI, const CellMap &Inputs) { 2320*0b57cec5SDimitry Andric if (MI.isBranch()) 2321*0b57cec5SDimitry Andric return rewriteHexBranch(MI, Inputs); 2322*0b57cec5SDimitry Andric 2323*0b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 2324*0b57cec5SDimitry Andric switch (Opc) { 2325*0b57cec5SDimitry Andric default: 2326*0b57cec5SDimitry Andric break; 2327*0b57cec5SDimitry Andric case Hexagon::A2_tfrsi: 2328*0b57cec5SDimitry Andric case Hexagon::A2_tfrpi: 2329*0b57cec5SDimitry Andric case Hexagon::CONST32: 2330*0b57cec5SDimitry Andric case Hexagon::CONST64: 2331*0b57cec5SDimitry Andric case Hexagon::PS_true: 2332*0b57cec5SDimitry Andric case Hexagon::PS_false: 2333*0b57cec5SDimitry Andric return false; 2334*0b57cec5SDimitry Andric } 2335*0b57cec5SDimitry Andric 2336*0b57cec5SDimitry Andric unsigned NumOp = MI.getNumOperands(); 2337*0b57cec5SDimitry Andric if (NumOp == 0) 2338*0b57cec5SDimitry Andric return false; 2339*0b57cec5SDimitry Andric 2340*0b57cec5SDimitry Andric bool AllDefs, Changed; 2341*0b57cec5SDimitry Andric Changed = rewriteHexConstDefs(MI, Inputs, AllDefs); 2342*0b57cec5SDimitry Andric // If not all defs have been rewritten (i.e. the instruction defines 2343*0b57cec5SDimitry Andric // a register that is not compile-time constant), then try to rewrite 2344*0b57cec5SDimitry Andric // register operands that are known to be constant with immediates. 2345*0b57cec5SDimitry Andric if (!AllDefs) 2346*0b57cec5SDimitry Andric Changed |= rewriteHexConstUses(MI, Inputs); 2347*0b57cec5SDimitry Andric 2348*0b57cec5SDimitry Andric return Changed; 2349*0b57cec5SDimitry Andric } 2350*0b57cec5SDimitry Andric 2351*0b57cec5SDimitry Andric unsigned HexagonConstEvaluator::getRegBitWidth(unsigned Reg) const { 2352*0b57cec5SDimitry Andric const TargetRegisterClass *RC = MRI->getRegClass(Reg); 2353*0b57cec5SDimitry Andric if (Hexagon::IntRegsRegClass.hasSubClassEq(RC)) 2354*0b57cec5SDimitry Andric return 32; 2355*0b57cec5SDimitry Andric if (Hexagon::DoubleRegsRegClass.hasSubClassEq(RC)) 2356*0b57cec5SDimitry Andric return 64; 2357*0b57cec5SDimitry Andric if (Hexagon::PredRegsRegClass.hasSubClassEq(RC)) 2358*0b57cec5SDimitry Andric return 8; 2359*0b57cec5SDimitry Andric llvm_unreachable("Invalid register"); 2360*0b57cec5SDimitry Andric return 0; 2361*0b57cec5SDimitry Andric } 2362*0b57cec5SDimitry Andric 2363*0b57cec5SDimitry Andric uint32_t HexagonConstEvaluator::getCmp(unsigned Opc) { 2364*0b57cec5SDimitry Andric switch (Opc) { 2365*0b57cec5SDimitry Andric case Hexagon::C2_cmpeq: 2366*0b57cec5SDimitry Andric case Hexagon::C2_cmpeqp: 2367*0b57cec5SDimitry Andric case Hexagon::A4_cmpbeq: 2368*0b57cec5SDimitry Andric case Hexagon::A4_cmpheq: 2369*0b57cec5SDimitry Andric case Hexagon::A4_cmpbeqi: 2370*0b57cec5SDimitry Andric case Hexagon::A4_cmpheqi: 2371*0b57cec5SDimitry Andric case Hexagon::C2_cmpeqi: 2372*0b57cec5SDimitry Andric case Hexagon::J4_cmpeqn1_t_jumpnv_nt: 2373*0b57cec5SDimitry Andric case Hexagon::J4_cmpeqn1_t_jumpnv_t: 2374*0b57cec5SDimitry Andric case Hexagon::J4_cmpeqi_t_jumpnv_nt: 2375*0b57cec5SDimitry Andric case Hexagon::J4_cmpeqi_t_jumpnv_t: 2376*0b57cec5SDimitry Andric case Hexagon::J4_cmpeq_t_jumpnv_nt: 2377*0b57cec5SDimitry Andric case Hexagon::J4_cmpeq_t_jumpnv_t: 2378*0b57cec5SDimitry Andric return Comparison::EQ; 2379*0b57cec5SDimitry Andric 2380*0b57cec5SDimitry Andric case Hexagon::C4_cmpneq: 2381*0b57cec5SDimitry Andric case Hexagon::C4_cmpneqi: 2382*0b57cec5SDimitry Andric case Hexagon::J4_cmpeqn1_f_jumpnv_nt: 2383*0b57cec5SDimitry Andric case Hexagon::J4_cmpeqn1_f_jumpnv_t: 2384*0b57cec5SDimitry Andric case Hexagon::J4_cmpeqi_f_jumpnv_nt: 2385*0b57cec5SDimitry Andric case Hexagon::J4_cmpeqi_f_jumpnv_t: 2386*0b57cec5SDimitry Andric case Hexagon::J4_cmpeq_f_jumpnv_nt: 2387*0b57cec5SDimitry Andric case Hexagon::J4_cmpeq_f_jumpnv_t: 2388*0b57cec5SDimitry Andric return Comparison::NE; 2389*0b57cec5SDimitry Andric 2390*0b57cec5SDimitry Andric case Hexagon::C2_cmpgt: 2391*0b57cec5SDimitry Andric case Hexagon::C2_cmpgtp: 2392*0b57cec5SDimitry Andric case Hexagon::A4_cmpbgt: 2393*0b57cec5SDimitry Andric case Hexagon::A4_cmphgt: 2394*0b57cec5SDimitry Andric case Hexagon::A4_cmpbgti: 2395*0b57cec5SDimitry Andric case Hexagon::A4_cmphgti: 2396*0b57cec5SDimitry Andric case Hexagon::C2_cmpgti: 2397*0b57cec5SDimitry Andric case Hexagon::J4_cmpgtn1_t_jumpnv_nt: 2398*0b57cec5SDimitry Andric case Hexagon::J4_cmpgtn1_t_jumpnv_t: 2399*0b57cec5SDimitry Andric case Hexagon::J4_cmpgti_t_jumpnv_nt: 2400*0b57cec5SDimitry Andric case Hexagon::J4_cmpgti_t_jumpnv_t: 2401*0b57cec5SDimitry Andric case Hexagon::J4_cmpgt_t_jumpnv_nt: 2402*0b57cec5SDimitry Andric case Hexagon::J4_cmpgt_t_jumpnv_t: 2403*0b57cec5SDimitry Andric return Comparison::GTs; 2404*0b57cec5SDimitry Andric 2405*0b57cec5SDimitry Andric case Hexagon::C4_cmplte: 2406*0b57cec5SDimitry Andric case Hexagon::C4_cmpltei: 2407*0b57cec5SDimitry Andric case Hexagon::J4_cmpgtn1_f_jumpnv_nt: 2408*0b57cec5SDimitry Andric case Hexagon::J4_cmpgtn1_f_jumpnv_t: 2409*0b57cec5SDimitry Andric case Hexagon::J4_cmpgti_f_jumpnv_nt: 2410*0b57cec5SDimitry Andric case Hexagon::J4_cmpgti_f_jumpnv_t: 2411*0b57cec5SDimitry Andric case Hexagon::J4_cmpgt_f_jumpnv_nt: 2412*0b57cec5SDimitry Andric case Hexagon::J4_cmpgt_f_jumpnv_t: 2413*0b57cec5SDimitry Andric return Comparison::LEs; 2414*0b57cec5SDimitry Andric 2415*0b57cec5SDimitry Andric case Hexagon::C2_cmpgtu: 2416*0b57cec5SDimitry Andric case Hexagon::C2_cmpgtup: 2417*0b57cec5SDimitry Andric case Hexagon::A4_cmpbgtu: 2418*0b57cec5SDimitry Andric case Hexagon::A4_cmpbgtui: 2419*0b57cec5SDimitry Andric case Hexagon::A4_cmphgtu: 2420*0b57cec5SDimitry Andric case Hexagon::A4_cmphgtui: 2421*0b57cec5SDimitry Andric case Hexagon::C2_cmpgtui: 2422*0b57cec5SDimitry Andric case Hexagon::J4_cmpgtui_t_jumpnv_nt: 2423*0b57cec5SDimitry Andric case Hexagon::J4_cmpgtui_t_jumpnv_t: 2424*0b57cec5SDimitry Andric case Hexagon::J4_cmpgtu_t_jumpnv_nt: 2425*0b57cec5SDimitry Andric case Hexagon::J4_cmpgtu_t_jumpnv_t: 2426*0b57cec5SDimitry Andric return Comparison::GTu; 2427*0b57cec5SDimitry Andric 2428*0b57cec5SDimitry Andric case Hexagon::J4_cmpltu_f_jumpnv_nt: 2429*0b57cec5SDimitry Andric case Hexagon::J4_cmpltu_f_jumpnv_t: 2430*0b57cec5SDimitry Andric return Comparison::GEu; 2431*0b57cec5SDimitry Andric 2432*0b57cec5SDimitry Andric case Hexagon::J4_cmpltu_t_jumpnv_nt: 2433*0b57cec5SDimitry Andric case Hexagon::J4_cmpltu_t_jumpnv_t: 2434*0b57cec5SDimitry Andric return Comparison::LTu; 2435*0b57cec5SDimitry Andric 2436*0b57cec5SDimitry Andric case Hexagon::J4_cmplt_f_jumpnv_nt: 2437*0b57cec5SDimitry Andric case Hexagon::J4_cmplt_f_jumpnv_t: 2438*0b57cec5SDimitry Andric return Comparison::GEs; 2439*0b57cec5SDimitry Andric 2440*0b57cec5SDimitry Andric case Hexagon::C4_cmplteu: 2441*0b57cec5SDimitry Andric case Hexagon::C4_cmplteui: 2442*0b57cec5SDimitry Andric case Hexagon::J4_cmpgtui_f_jumpnv_nt: 2443*0b57cec5SDimitry Andric case Hexagon::J4_cmpgtui_f_jumpnv_t: 2444*0b57cec5SDimitry Andric case Hexagon::J4_cmpgtu_f_jumpnv_nt: 2445*0b57cec5SDimitry Andric case Hexagon::J4_cmpgtu_f_jumpnv_t: 2446*0b57cec5SDimitry Andric return Comparison::LEu; 2447*0b57cec5SDimitry Andric 2448*0b57cec5SDimitry Andric case Hexagon::J4_cmplt_t_jumpnv_nt: 2449*0b57cec5SDimitry Andric case Hexagon::J4_cmplt_t_jumpnv_t: 2450*0b57cec5SDimitry Andric return Comparison::LTs; 2451*0b57cec5SDimitry Andric 2452*0b57cec5SDimitry Andric default: 2453*0b57cec5SDimitry Andric break; 2454*0b57cec5SDimitry Andric } 2455*0b57cec5SDimitry Andric return Comparison::Unk; 2456*0b57cec5SDimitry Andric } 2457*0b57cec5SDimitry Andric 2458*0b57cec5SDimitry Andric APInt HexagonConstEvaluator::getCmpImm(unsigned Opc, unsigned OpX, 2459*0b57cec5SDimitry Andric const MachineOperand &MO) { 2460*0b57cec5SDimitry Andric bool Signed = false; 2461*0b57cec5SDimitry Andric switch (Opc) { 2462*0b57cec5SDimitry Andric case Hexagon::A4_cmpbgtui: // u7 2463*0b57cec5SDimitry Andric case Hexagon::A4_cmphgtui: // u7 2464*0b57cec5SDimitry Andric break; 2465*0b57cec5SDimitry Andric case Hexagon::A4_cmpheqi: // s8 2466*0b57cec5SDimitry Andric case Hexagon::C4_cmpneqi: // s8 2467*0b57cec5SDimitry Andric Signed = true; 2468*0b57cec5SDimitry Andric break; 2469*0b57cec5SDimitry Andric case Hexagon::A4_cmpbeqi: // u8 2470*0b57cec5SDimitry Andric break; 2471*0b57cec5SDimitry Andric case Hexagon::C2_cmpgtui: // u9 2472*0b57cec5SDimitry Andric case Hexagon::C4_cmplteui: // u9 2473*0b57cec5SDimitry Andric break; 2474*0b57cec5SDimitry Andric case Hexagon::C2_cmpeqi: // s10 2475*0b57cec5SDimitry Andric case Hexagon::C2_cmpgti: // s10 2476*0b57cec5SDimitry Andric case Hexagon::C4_cmpltei: // s10 2477*0b57cec5SDimitry Andric Signed = true; 2478*0b57cec5SDimitry Andric break; 2479*0b57cec5SDimitry Andric case Hexagon::J4_cmpeqi_f_jumpnv_nt: // u5 2480*0b57cec5SDimitry Andric case Hexagon::J4_cmpeqi_f_jumpnv_t: // u5 2481*0b57cec5SDimitry Andric case Hexagon::J4_cmpeqi_t_jumpnv_nt: // u5 2482*0b57cec5SDimitry Andric case Hexagon::J4_cmpeqi_t_jumpnv_t: // u5 2483*0b57cec5SDimitry Andric case Hexagon::J4_cmpgti_f_jumpnv_nt: // u5 2484*0b57cec5SDimitry Andric case Hexagon::J4_cmpgti_f_jumpnv_t: // u5 2485*0b57cec5SDimitry Andric case Hexagon::J4_cmpgti_t_jumpnv_nt: // u5 2486*0b57cec5SDimitry Andric case Hexagon::J4_cmpgti_t_jumpnv_t: // u5 2487*0b57cec5SDimitry Andric case Hexagon::J4_cmpgtui_f_jumpnv_nt: // u5 2488*0b57cec5SDimitry Andric case Hexagon::J4_cmpgtui_f_jumpnv_t: // u5 2489*0b57cec5SDimitry Andric case Hexagon::J4_cmpgtui_t_jumpnv_nt: // u5 2490*0b57cec5SDimitry Andric case Hexagon::J4_cmpgtui_t_jumpnv_t: // u5 2491*0b57cec5SDimitry Andric break; 2492*0b57cec5SDimitry Andric default: 2493*0b57cec5SDimitry Andric llvm_unreachable("Unhandled instruction"); 2494*0b57cec5SDimitry Andric break; 2495*0b57cec5SDimitry Andric } 2496*0b57cec5SDimitry Andric 2497*0b57cec5SDimitry Andric uint64_t Val = MO.getImm(); 2498*0b57cec5SDimitry Andric return APInt(32, Val, Signed); 2499*0b57cec5SDimitry Andric } 2500*0b57cec5SDimitry Andric 2501*0b57cec5SDimitry Andric void HexagonConstEvaluator::replaceWithNop(MachineInstr &MI) { 2502*0b57cec5SDimitry Andric MI.setDesc(HII.get(Hexagon::A2_nop)); 2503*0b57cec5SDimitry Andric while (MI.getNumOperands() > 0) 2504*0b57cec5SDimitry Andric MI.RemoveOperand(0); 2505*0b57cec5SDimitry Andric } 2506*0b57cec5SDimitry Andric 2507*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexRSEQ32(RegisterSubReg RL, RegisterSubReg RH, 2508*0b57cec5SDimitry Andric const CellMap &Inputs, LatticeCell &Result) { 2509*0b57cec5SDimitry Andric assert(Inputs.has(RL.Reg) && Inputs.has(RH.Reg)); 2510*0b57cec5SDimitry Andric LatticeCell LSL, LSH; 2511*0b57cec5SDimitry Andric if (!getCell(RL, Inputs, LSL) || !getCell(RH, Inputs, LSH)) 2512*0b57cec5SDimitry Andric return false; 2513*0b57cec5SDimitry Andric if (LSL.isProperty() || LSH.isProperty()) 2514*0b57cec5SDimitry Andric return false; 2515*0b57cec5SDimitry Andric 2516*0b57cec5SDimitry Andric unsigned LN = LSL.size(), HN = LSH.size(); 2517*0b57cec5SDimitry Andric SmallVector<APInt,4> LoVs(LN), HiVs(HN); 2518*0b57cec5SDimitry Andric for (unsigned i = 0; i < LN; ++i) { 2519*0b57cec5SDimitry Andric bool Eval = constToInt(LSL.Values[i], LoVs[i]); 2520*0b57cec5SDimitry Andric if (!Eval) 2521*0b57cec5SDimitry Andric return false; 2522*0b57cec5SDimitry Andric assert(LoVs[i].getBitWidth() == 32); 2523*0b57cec5SDimitry Andric } 2524*0b57cec5SDimitry Andric for (unsigned i = 0; i < HN; ++i) { 2525*0b57cec5SDimitry Andric bool Eval = constToInt(LSH.Values[i], HiVs[i]); 2526*0b57cec5SDimitry Andric if (!Eval) 2527*0b57cec5SDimitry Andric return false; 2528*0b57cec5SDimitry Andric assert(HiVs[i].getBitWidth() == 32); 2529*0b57cec5SDimitry Andric } 2530*0b57cec5SDimitry Andric 2531*0b57cec5SDimitry Andric for (unsigned i = 0; i < HiVs.size(); ++i) { 2532*0b57cec5SDimitry Andric APInt HV = HiVs[i].zextOrSelf(64) << 32; 2533*0b57cec5SDimitry Andric for (unsigned j = 0; j < LoVs.size(); ++j) { 2534*0b57cec5SDimitry Andric APInt LV = LoVs[j].zextOrSelf(64); 2535*0b57cec5SDimitry Andric const Constant *C = intToConst(HV | LV); 2536*0b57cec5SDimitry Andric Result.add(C); 2537*0b57cec5SDimitry Andric if (Result.isBottom()) 2538*0b57cec5SDimitry Andric return false; 2539*0b57cec5SDimitry Andric } 2540*0b57cec5SDimitry Andric } 2541*0b57cec5SDimitry Andric return !Result.isBottom(); 2542*0b57cec5SDimitry Andric } 2543*0b57cec5SDimitry Andric 2544*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexCompare(const MachineInstr &MI, 2545*0b57cec5SDimitry Andric const CellMap &Inputs, CellMap &Outputs) { 2546*0b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 2547*0b57cec5SDimitry Andric bool Classic = false; 2548*0b57cec5SDimitry Andric switch (Opc) { 2549*0b57cec5SDimitry Andric case Hexagon::C2_cmpeq: 2550*0b57cec5SDimitry Andric case Hexagon::C2_cmpeqp: 2551*0b57cec5SDimitry Andric case Hexagon::C2_cmpgt: 2552*0b57cec5SDimitry Andric case Hexagon::C2_cmpgtp: 2553*0b57cec5SDimitry Andric case Hexagon::C2_cmpgtu: 2554*0b57cec5SDimitry Andric case Hexagon::C2_cmpgtup: 2555*0b57cec5SDimitry Andric case Hexagon::C2_cmpeqi: 2556*0b57cec5SDimitry Andric case Hexagon::C2_cmpgti: 2557*0b57cec5SDimitry Andric case Hexagon::C2_cmpgtui: 2558*0b57cec5SDimitry Andric // Classic compare: Dst0 = CMP Src1, Src2 2559*0b57cec5SDimitry Andric Classic = true; 2560*0b57cec5SDimitry Andric break; 2561*0b57cec5SDimitry Andric default: 2562*0b57cec5SDimitry Andric // Not handling other compare instructions now. 2563*0b57cec5SDimitry Andric return false; 2564*0b57cec5SDimitry Andric } 2565*0b57cec5SDimitry Andric 2566*0b57cec5SDimitry Andric if (Classic) { 2567*0b57cec5SDimitry Andric const MachineOperand &Src1 = MI.getOperand(1); 2568*0b57cec5SDimitry Andric const MachineOperand &Src2 = MI.getOperand(2); 2569*0b57cec5SDimitry Andric 2570*0b57cec5SDimitry Andric bool Result; 2571*0b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 2572*0b57cec5SDimitry Andric bool Computed = evaluateHexCompare2(Opc, Src1, Src2, Inputs, Result); 2573*0b57cec5SDimitry Andric if (Computed) { 2574*0b57cec5SDimitry Andric // Only create a zero/non-zero cell. At this time there isn't really 2575*0b57cec5SDimitry Andric // much need for specific values. 2576*0b57cec5SDimitry Andric RegisterSubReg DefR(MI.getOperand(0)); 2577*0b57cec5SDimitry Andric LatticeCell L = Outputs.get(DefR.Reg); 2578*0b57cec5SDimitry Andric uint32_t P = Result ? ConstantProperties::NonZero 2579*0b57cec5SDimitry Andric : ConstantProperties::Zero; 2580*0b57cec5SDimitry Andric L.add(P); 2581*0b57cec5SDimitry Andric Outputs.update(DefR.Reg, L); 2582*0b57cec5SDimitry Andric return true; 2583*0b57cec5SDimitry Andric } 2584*0b57cec5SDimitry Andric } 2585*0b57cec5SDimitry Andric 2586*0b57cec5SDimitry Andric return false; 2587*0b57cec5SDimitry Andric } 2588*0b57cec5SDimitry Andric 2589*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexCompare2(unsigned Opc, 2590*0b57cec5SDimitry Andric const MachineOperand &Src1, const MachineOperand &Src2, 2591*0b57cec5SDimitry Andric const CellMap &Inputs, bool &Result) { 2592*0b57cec5SDimitry Andric uint32_t Cmp = getCmp(Opc); 2593*0b57cec5SDimitry Andric bool Reg1 = Src1.isReg(), Reg2 = Src2.isReg(); 2594*0b57cec5SDimitry Andric bool Imm1 = Src1.isImm(), Imm2 = Src2.isImm(); 2595*0b57cec5SDimitry Andric if (Reg1) { 2596*0b57cec5SDimitry Andric RegisterSubReg R1(Src1); 2597*0b57cec5SDimitry Andric if (Reg2) { 2598*0b57cec5SDimitry Andric RegisterSubReg R2(Src2); 2599*0b57cec5SDimitry Andric return evaluateCMPrr(Cmp, R1, R2, Inputs, Result); 2600*0b57cec5SDimitry Andric } else if (Imm2) { 2601*0b57cec5SDimitry Andric APInt A2 = getCmpImm(Opc, 2, Src2); 2602*0b57cec5SDimitry Andric return evaluateCMPri(Cmp, R1, A2, Inputs, Result); 2603*0b57cec5SDimitry Andric } 2604*0b57cec5SDimitry Andric } else if (Imm1) { 2605*0b57cec5SDimitry Andric APInt A1 = getCmpImm(Opc, 1, Src1); 2606*0b57cec5SDimitry Andric if (Reg2) { 2607*0b57cec5SDimitry Andric RegisterSubReg R2(Src2); 2608*0b57cec5SDimitry Andric uint32_t NegCmp = Comparison::negate(Cmp); 2609*0b57cec5SDimitry Andric return evaluateCMPri(NegCmp, R2, A1, Inputs, Result); 2610*0b57cec5SDimitry Andric } else if (Imm2) { 2611*0b57cec5SDimitry Andric APInt A2 = getCmpImm(Opc, 2, Src2); 2612*0b57cec5SDimitry Andric return evaluateCMPii(Cmp, A1, A2, Result); 2613*0b57cec5SDimitry Andric } 2614*0b57cec5SDimitry Andric } 2615*0b57cec5SDimitry Andric // Unknown kind of comparison. 2616*0b57cec5SDimitry Andric return false; 2617*0b57cec5SDimitry Andric } 2618*0b57cec5SDimitry Andric 2619*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexLogical(const MachineInstr &MI, 2620*0b57cec5SDimitry Andric const CellMap &Inputs, CellMap &Outputs) { 2621*0b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 2622*0b57cec5SDimitry Andric if (MI.getNumOperands() != 3) 2623*0b57cec5SDimitry Andric return false; 2624*0b57cec5SDimitry Andric const MachineOperand &Src1 = MI.getOperand(1); 2625*0b57cec5SDimitry Andric const MachineOperand &Src2 = MI.getOperand(2); 2626*0b57cec5SDimitry Andric RegisterSubReg R1(Src1); 2627*0b57cec5SDimitry Andric bool Eval = false; 2628*0b57cec5SDimitry Andric LatticeCell RC; 2629*0b57cec5SDimitry Andric switch (Opc) { 2630*0b57cec5SDimitry Andric default: 2631*0b57cec5SDimitry Andric return false; 2632*0b57cec5SDimitry Andric case Hexagon::A2_and: 2633*0b57cec5SDimitry Andric case Hexagon::A2_andp: 2634*0b57cec5SDimitry Andric Eval = evaluateANDrr(R1, RegisterSubReg(Src2), Inputs, RC); 2635*0b57cec5SDimitry Andric break; 2636*0b57cec5SDimitry Andric case Hexagon::A2_andir: { 2637*0b57cec5SDimitry Andric if (!Src2.isImm()) 2638*0b57cec5SDimitry Andric return false; 2639*0b57cec5SDimitry Andric APInt A(32, Src2.getImm(), true); 2640*0b57cec5SDimitry Andric Eval = evaluateANDri(R1, A, Inputs, RC); 2641*0b57cec5SDimitry Andric break; 2642*0b57cec5SDimitry Andric } 2643*0b57cec5SDimitry Andric case Hexagon::A2_or: 2644*0b57cec5SDimitry Andric case Hexagon::A2_orp: 2645*0b57cec5SDimitry Andric Eval = evaluateORrr(R1, RegisterSubReg(Src2), Inputs, RC); 2646*0b57cec5SDimitry Andric break; 2647*0b57cec5SDimitry Andric case Hexagon::A2_orir: { 2648*0b57cec5SDimitry Andric if (!Src2.isImm()) 2649*0b57cec5SDimitry Andric return false; 2650*0b57cec5SDimitry Andric APInt A(32, Src2.getImm(), true); 2651*0b57cec5SDimitry Andric Eval = evaluateORri(R1, A, Inputs, RC); 2652*0b57cec5SDimitry Andric break; 2653*0b57cec5SDimitry Andric } 2654*0b57cec5SDimitry Andric case Hexagon::A2_xor: 2655*0b57cec5SDimitry Andric case Hexagon::A2_xorp: 2656*0b57cec5SDimitry Andric Eval = evaluateXORrr(R1, RegisterSubReg(Src2), Inputs, RC); 2657*0b57cec5SDimitry Andric break; 2658*0b57cec5SDimitry Andric } 2659*0b57cec5SDimitry Andric if (Eval) { 2660*0b57cec5SDimitry Andric RegisterSubReg DefR(MI.getOperand(0)); 2661*0b57cec5SDimitry Andric Outputs.update(DefR.Reg, RC); 2662*0b57cec5SDimitry Andric } 2663*0b57cec5SDimitry Andric return Eval; 2664*0b57cec5SDimitry Andric } 2665*0b57cec5SDimitry Andric 2666*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexCondMove(const MachineInstr &MI, 2667*0b57cec5SDimitry Andric const CellMap &Inputs, CellMap &Outputs) { 2668*0b57cec5SDimitry Andric // Dst0 = Cond1 ? Src2 : Src3 2669*0b57cec5SDimitry Andric RegisterSubReg CR(MI.getOperand(1)); 2670*0b57cec5SDimitry Andric assert(Inputs.has(CR.Reg)); 2671*0b57cec5SDimitry Andric LatticeCell LS; 2672*0b57cec5SDimitry Andric if (!getCell(CR, Inputs, LS)) 2673*0b57cec5SDimitry Andric return false; 2674*0b57cec5SDimitry Andric uint32_t Ps = LS.properties(); 2675*0b57cec5SDimitry Andric unsigned TakeOp; 2676*0b57cec5SDimitry Andric if (Ps & ConstantProperties::Zero) 2677*0b57cec5SDimitry Andric TakeOp = 3; 2678*0b57cec5SDimitry Andric else if (Ps & ConstantProperties::NonZero) 2679*0b57cec5SDimitry Andric TakeOp = 2; 2680*0b57cec5SDimitry Andric else 2681*0b57cec5SDimitry Andric return false; 2682*0b57cec5SDimitry Andric 2683*0b57cec5SDimitry Andric const MachineOperand &ValOp = MI.getOperand(TakeOp); 2684*0b57cec5SDimitry Andric RegisterSubReg DefR(MI.getOperand(0)); 2685*0b57cec5SDimitry Andric LatticeCell RC = Outputs.get(DefR.Reg); 2686*0b57cec5SDimitry Andric 2687*0b57cec5SDimitry Andric if (ValOp.isImm()) { 2688*0b57cec5SDimitry Andric int64_t V = ValOp.getImm(); 2689*0b57cec5SDimitry Andric unsigned W = getRegBitWidth(DefR.Reg); 2690*0b57cec5SDimitry Andric APInt A(W, V, true); 2691*0b57cec5SDimitry Andric const Constant *C = intToConst(A); 2692*0b57cec5SDimitry Andric RC.add(C); 2693*0b57cec5SDimitry Andric Outputs.update(DefR.Reg, RC); 2694*0b57cec5SDimitry Andric return true; 2695*0b57cec5SDimitry Andric } 2696*0b57cec5SDimitry Andric if (ValOp.isReg()) { 2697*0b57cec5SDimitry Andric RegisterSubReg R(ValOp); 2698*0b57cec5SDimitry Andric const LatticeCell &LR = Inputs.get(R.Reg); 2699*0b57cec5SDimitry Andric LatticeCell LSR; 2700*0b57cec5SDimitry Andric if (!evaluate(R, LR, LSR)) 2701*0b57cec5SDimitry Andric return false; 2702*0b57cec5SDimitry Andric RC.meet(LSR); 2703*0b57cec5SDimitry Andric Outputs.update(DefR.Reg, RC); 2704*0b57cec5SDimitry Andric return true; 2705*0b57cec5SDimitry Andric } 2706*0b57cec5SDimitry Andric return false; 2707*0b57cec5SDimitry Andric } 2708*0b57cec5SDimitry Andric 2709*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexExt(const MachineInstr &MI, 2710*0b57cec5SDimitry Andric const CellMap &Inputs, CellMap &Outputs) { 2711*0b57cec5SDimitry Andric // Dst0 = ext R1 2712*0b57cec5SDimitry Andric RegisterSubReg R1(MI.getOperand(1)); 2713*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg)); 2714*0b57cec5SDimitry Andric 2715*0b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 2716*0b57cec5SDimitry Andric unsigned Bits; 2717*0b57cec5SDimitry Andric switch (Opc) { 2718*0b57cec5SDimitry Andric case Hexagon::A2_sxtb: 2719*0b57cec5SDimitry Andric case Hexagon::A2_zxtb: 2720*0b57cec5SDimitry Andric Bits = 8; 2721*0b57cec5SDimitry Andric break; 2722*0b57cec5SDimitry Andric case Hexagon::A2_sxth: 2723*0b57cec5SDimitry Andric case Hexagon::A2_zxth: 2724*0b57cec5SDimitry Andric Bits = 16; 2725*0b57cec5SDimitry Andric break; 2726*0b57cec5SDimitry Andric case Hexagon::A2_sxtw: 2727*0b57cec5SDimitry Andric Bits = 32; 2728*0b57cec5SDimitry Andric break; 2729*0b57cec5SDimitry Andric default: 2730*0b57cec5SDimitry Andric llvm_unreachable("Unhandled extension opcode"); 2731*0b57cec5SDimitry Andric } 2732*0b57cec5SDimitry Andric 2733*0b57cec5SDimitry Andric bool Signed = false; 2734*0b57cec5SDimitry Andric switch (Opc) { 2735*0b57cec5SDimitry Andric case Hexagon::A2_sxtb: 2736*0b57cec5SDimitry Andric case Hexagon::A2_sxth: 2737*0b57cec5SDimitry Andric case Hexagon::A2_sxtw: 2738*0b57cec5SDimitry Andric Signed = true; 2739*0b57cec5SDimitry Andric break; 2740*0b57cec5SDimitry Andric } 2741*0b57cec5SDimitry Andric 2742*0b57cec5SDimitry Andric RegisterSubReg DefR(MI.getOperand(0)); 2743*0b57cec5SDimitry Andric unsigned BW = getRegBitWidth(DefR.Reg); 2744*0b57cec5SDimitry Andric LatticeCell RC = Outputs.get(DefR.Reg); 2745*0b57cec5SDimitry Andric bool Eval = Signed ? evaluateSEXTr(R1, BW, Bits, Inputs, RC) 2746*0b57cec5SDimitry Andric : evaluateZEXTr(R1, BW, Bits, Inputs, RC); 2747*0b57cec5SDimitry Andric if (!Eval) 2748*0b57cec5SDimitry Andric return false; 2749*0b57cec5SDimitry Andric Outputs.update(DefR.Reg, RC); 2750*0b57cec5SDimitry Andric return true; 2751*0b57cec5SDimitry Andric } 2752*0b57cec5SDimitry Andric 2753*0b57cec5SDimitry Andric bool HexagonConstEvaluator::evaluateHexVector1(const MachineInstr &MI, 2754*0b57cec5SDimitry Andric const CellMap &Inputs, CellMap &Outputs) { 2755*0b57cec5SDimitry Andric // DefR = op R1 2756*0b57cec5SDimitry Andric RegisterSubReg DefR(MI.getOperand(0)); 2757*0b57cec5SDimitry Andric RegisterSubReg R1(MI.getOperand(1)); 2758*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg)); 2759*0b57cec5SDimitry Andric LatticeCell RC = Outputs.get(DefR.Reg); 2760*0b57cec5SDimitry Andric bool Eval; 2761*0b57cec5SDimitry Andric 2762*0b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 2763*0b57cec5SDimitry Andric switch (Opc) { 2764*0b57cec5SDimitry Andric case Hexagon::S2_vsplatrb: 2765*0b57cec5SDimitry Andric // Rd = 4 times Rs:0..7 2766*0b57cec5SDimitry Andric Eval = evaluateSplatr(R1, 8, 4, Inputs, RC); 2767*0b57cec5SDimitry Andric break; 2768*0b57cec5SDimitry Andric case Hexagon::S2_vsplatrh: 2769*0b57cec5SDimitry Andric // Rdd = 4 times Rs:0..15 2770*0b57cec5SDimitry Andric Eval = evaluateSplatr(R1, 16, 4, Inputs, RC); 2771*0b57cec5SDimitry Andric break; 2772*0b57cec5SDimitry Andric default: 2773*0b57cec5SDimitry Andric return false; 2774*0b57cec5SDimitry Andric } 2775*0b57cec5SDimitry Andric 2776*0b57cec5SDimitry Andric if (!Eval) 2777*0b57cec5SDimitry Andric return false; 2778*0b57cec5SDimitry Andric Outputs.update(DefR.Reg, RC); 2779*0b57cec5SDimitry Andric return true; 2780*0b57cec5SDimitry Andric } 2781*0b57cec5SDimitry Andric 2782*0b57cec5SDimitry Andric bool HexagonConstEvaluator::rewriteHexConstDefs(MachineInstr &MI, 2783*0b57cec5SDimitry Andric const CellMap &Inputs, bool &AllDefs) { 2784*0b57cec5SDimitry Andric AllDefs = false; 2785*0b57cec5SDimitry Andric 2786*0b57cec5SDimitry Andric // Some diagnostics. 2787*0b57cec5SDimitry Andric // LLVM_DEBUG({...}) gets confused with all this code as an argument. 2788*0b57cec5SDimitry Andric #ifndef NDEBUG 2789*0b57cec5SDimitry Andric bool Debugging = DebugFlag && isCurrentDebugType(DEBUG_TYPE); 2790*0b57cec5SDimitry Andric if (Debugging) { 2791*0b57cec5SDimitry Andric bool Const = true, HasUse = false; 2792*0b57cec5SDimitry Andric for (const MachineOperand &MO : MI.operands()) { 2793*0b57cec5SDimitry Andric if (!MO.isReg() || !MO.isUse() || MO.isImplicit()) 2794*0b57cec5SDimitry Andric continue; 2795*0b57cec5SDimitry Andric RegisterSubReg R(MO); 2796*0b57cec5SDimitry Andric if (!TargetRegisterInfo::isVirtualRegister(R.Reg)) 2797*0b57cec5SDimitry Andric continue; 2798*0b57cec5SDimitry Andric HasUse = true; 2799*0b57cec5SDimitry Andric // PHIs can legitimately have "top" cells after propagation. 2800*0b57cec5SDimitry Andric if (!MI.isPHI() && !Inputs.has(R.Reg)) { 2801*0b57cec5SDimitry Andric dbgs() << "Top " << printReg(R.Reg, &HRI, R.SubReg) 2802*0b57cec5SDimitry Andric << " in MI: " << MI; 2803*0b57cec5SDimitry Andric continue; 2804*0b57cec5SDimitry Andric } 2805*0b57cec5SDimitry Andric const LatticeCell &L = Inputs.get(R.Reg); 2806*0b57cec5SDimitry Andric Const &= L.isSingle(); 2807*0b57cec5SDimitry Andric if (!Const) 2808*0b57cec5SDimitry Andric break; 2809*0b57cec5SDimitry Andric } 2810*0b57cec5SDimitry Andric if (HasUse && Const) { 2811*0b57cec5SDimitry Andric if (!MI.isCopy()) { 2812*0b57cec5SDimitry Andric dbgs() << "CONST: " << MI; 2813*0b57cec5SDimitry Andric for (const MachineOperand &MO : MI.operands()) { 2814*0b57cec5SDimitry Andric if (!MO.isReg() || !MO.isUse() || MO.isImplicit()) 2815*0b57cec5SDimitry Andric continue; 2816*0b57cec5SDimitry Andric unsigned R = MO.getReg(); 2817*0b57cec5SDimitry Andric dbgs() << printReg(R, &TRI) << ": " << Inputs.get(R) << "\n"; 2818*0b57cec5SDimitry Andric } 2819*0b57cec5SDimitry Andric } 2820*0b57cec5SDimitry Andric } 2821*0b57cec5SDimitry Andric } 2822*0b57cec5SDimitry Andric #endif 2823*0b57cec5SDimitry Andric 2824*0b57cec5SDimitry Andric // Avoid generating TFRIs for register transfers---this will keep the 2825*0b57cec5SDimitry Andric // coalescing opportunities. 2826*0b57cec5SDimitry Andric if (MI.isCopy()) 2827*0b57cec5SDimitry Andric return false; 2828*0b57cec5SDimitry Andric 2829*0b57cec5SDimitry Andric // Collect all virtual register-def operands. 2830*0b57cec5SDimitry Andric SmallVector<unsigned,2> DefRegs; 2831*0b57cec5SDimitry Andric for (const MachineOperand &MO : MI.operands()) { 2832*0b57cec5SDimitry Andric if (!MO.isReg() || !MO.isDef()) 2833*0b57cec5SDimitry Andric continue; 2834*0b57cec5SDimitry Andric unsigned R = MO.getReg(); 2835*0b57cec5SDimitry Andric if (!TargetRegisterInfo::isVirtualRegister(R)) 2836*0b57cec5SDimitry Andric continue; 2837*0b57cec5SDimitry Andric assert(!MO.getSubReg()); 2838*0b57cec5SDimitry Andric assert(Inputs.has(R)); 2839*0b57cec5SDimitry Andric DefRegs.push_back(R); 2840*0b57cec5SDimitry Andric } 2841*0b57cec5SDimitry Andric 2842*0b57cec5SDimitry Andric MachineBasicBlock &B = *MI.getParent(); 2843*0b57cec5SDimitry Andric const DebugLoc &DL = MI.getDebugLoc(); 2844*0b57cec5SDimitry Andric unsigned ChangedNum = 0; 2845*0b57cec5SDimitry Andric #ifndef NDEBUG 2846*0b57cec5SDimitry Andric SmallVector<const MachineInstr*,4> NewInstrs; 2847*0b57cec5SDimitry Andric #endif 2848*0b57cec5SDimitry Andric 2849*0b57cec5SDimitry Andric // For each defined register, if it is a constant, create an instruction 2850*0b57cec5SDimitry Andric // NewR = const 2851*0b57cec5SDimitry Andric // and replace all uses of the defined register with NewR. 2852*0b57cec5SDimitry Andric for (unsigned i = 0, n = DefRegs.size(); i < n; ++i) { 2853*0b57cec5SDimitry Andric unsigned R = DefRegs[i]; 2854*0b57cec5SDimitry Andric const LatticeCell &L = Inputs.get(R); 2855*0b57cec5SDimitry Andric if (L.isBottom()) 2856*0b57cec5SDimitry Andric continue; 2857*0b57cec5SDimitry Andric const TargetRegisterClass *RC = MRI->getRegClass(R); 2858*0b57cec5SDimitry Andric MachineBasicBlock::iterator At = MI.getIterator(); 2859*0b57cec5SDimitry Andric 2860*0b57cec5SDimitry Andric if (!L.isSingle()) { 2861*0b57cec5SDimitry Andric // If this a zero/non-zero cell, we can fold a definition 2862*0b57cec5SDimitry Andric // of a predicate register. 2863*0b57cec5SDimitry Andric using P = ConstantProperties; 2864*0b57cec5SDimitry Andric 2865*0b57cec5SDimitry Andric uint64_t Ps = L.properties(); 2866*0b57cec5SDimitry Andric if (!(Ps & (P::Zero|P::NonZero))) 2867*0b57cec5SDimitry Andric continue; 2868*0b57cec5SDimitry Andric const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass; 2869*0b57cec5SDimitry Andric if (RC != PredRC) 2870*0b57cec5SDimitry Andric continue; 2871*0b57cec5SDimitry Andric const MCInstrDesc *NewD = (Ps & P::Zero) ? 2872*0b57cec5SDimitry Andric &HII.get(Hexagon::PS_false) : 2873*0b57cec5SDimitry Andric &HII.get(Hexagon::PS_true); 2874*0b57cec5SDimitry Andric unsigned NewR = MRI->createVirtualRegister(PredRC); 2875*0b57cec5SDimitry Andric const MachineInstrBuilder &MIB = BuildMI(B, At, DL, *NewD, NewR); 2876*0b57cec5SDimitry Andric (void)MIB; 2877*0b57cec5SDimitry Andric #ifndef NDEBUG 2878*0b57cec5SDimitry Andric NewInstrs.push_back(&*MIB); 2879*0b57cec5SDimitry Andric #endif 2880*0b57cec5SDimitry Andric replaceAllRegUsesWith(R, NewR); 2881*0b57cec5SDimitry Andric } else { 2882*0b57cec5SDimitry Andric // This cell has a single value. 2883*0b57cec5SDimitry Andric APInt A; 2884*0b57cec5SDimitry Andric if (!constToInt(L.Value, A) || !A.isSignedIntN(64)) 2885*0b57cec5SDimitry Andric continue; 2886*0b57cec5SDimitry Andric const TargetRegisterClass *NewRC; 2887*0b57cec5SDimitry Andric const MCInstrDesc *NewD; 2888*0b57cec5SDimitry Andric 2889*0b57cec5SDimitry Andric unsigned W = getRegBitWidth(R); 2890*0b57cec5SDimitry Andric int64_t V = A.getSExtValue(); 2891*0b57cec5SDimitry Andric assert(W == 32 || W == 64); 2892*0b57cec5SDimitry Andric if (W == 32) 2893*0b57cec5SDimitry Andric NewRC = &Hexagon::IntRegsRegClass; 2894*0b57cec5SDimitry Andric else 2895*0b57cec5SDimitry Andric NewRC = &Hexagon::DoubleRegsRegClass; 2896*0b57cec5SDimitry Andric unsigned NewR = MRI->createVirtualRegister(NewRC); 2897*0b57cec5SDimitry Andric const MachineInstr *NewMI; 2898*0b57cec5SDimitry Andric 2899*0b57cec5SDimitry Andric if (W == 32) { 2900*0b57cec5SDimitry Andric NewD = &HII.get(Hexagon::A2_tfrsi); 2901*0b57cec5SDimitry Andric NewMI = BuildMI(B, At, DL, *NewD, NewR) 2902*0b57cec5SDimitry Andric .addImm(V); 2903*0b57cec5SDimitry Andric } else { 2904*0b57cec5SDimitry Andric if (A.isSignedIntN(8)) { 2905*0b57cec5SDimitry Andric NewD = &HII.get(Hexagon::A2_tfrpi); 2906*0b57cec5SDimitry Andric NewMI = BuildMI(B, At, DL, *NewD, NewR) 2907*0b57cec5SDimitry Andric .addImm(V); 2908*0b57cec5SDimitry Andric } else { 2909*0b57cec5SDimitry Andric int32_t Hi = V >> 32; 2910*0b57cec5SDimitry Andric int32_t Lo = V & 0xFFFFFFFFLL; 2911*0b57cec5SDimitry Andric if (isInt<8>(Hi) && isInt<8>(Lo)) { 2912*0b57cec5SDimitry Andric NewD = &HII.get(Hexagon::A2_combineii); 2913*0b57cec5SDimitry Andric NewMI = BuildMI(B, At, DL, *NewD, NewR) 2914*0b57cec5SDimitry Andric .addImm(Hi) 2915*0b57cec5SDimitry Andric .addImm(Lo); 2916*0b57cec5SDimitry Andric } else { 2917*0b57cec5SDimitry Andric NewD = &HII.get(Hexagon::CONST64); 2918*0b57cec5SDimitry Andric NewMI = BuildMI(B, At, DL, *NewD, NewR) 2919*0b57cec5SDimitry Andric .addImm(V); 2920*0b57cec5SDimitry Andric } 2921*0b57cec5SDimitry Andric } 2922*0b57cec5SDimitry Andric } 2923*0b57cec5SDimitry Andric (void)NewMI; 2924*0b57cec5SDimitry Andric #ifndef NDEBUG 2925*0b57cec5SDimitry Andric NewInstrs.push_back(NewMI); 2926*0b57cec5SDimitry Andric #endif 2927*0b57cec5SDimitry Andric replaceAllRegUsesWith(R, NewR); 2928*0b57cec5SDimitry Andric } 2929*0b57cec5SDimitry Andric ChangedNum++; 2930*0b57cec5SDimitry Andric } 2931*0b57cec5SDimitry Andric 2932*0b57cec5SDimitry Andric LLVM_DEBUG({ 2933*0b57cec5SDimitry Andric if (!NewInstrs.empty()) { 2934*0b57cec5SDimitry Andric MachineFunction &MF = *MI.getParent()->getParent(); 2935*0b57cec5SDimitry Andric dbgs() << "In function: " << MF.getName() << "\n"; 2936*0b57cec5SDimitry Andric dbgs() << "Rewrite: for " << MI << " created " << *NewInstrs[0]; 2937*0b57cec5SDimitry Andric for (unsigned i = 1; i < NewInstrs.size(); ++i) 2938*0b57cec5SDimitry Andric dbgs() << " " << *NewInstrs[i]; 2939*0b57cec5SDimitry Andric } 2940*0b57cec5SDimitry Andric }); 2941*0b57cec5SDimitry Andric 2942*0b57cec5SDimitry Andric AllDefs = (ChangedNum == DefRegs.size()); 2943*0b57cec5SDimitry Andric return ChangedNum > 0; 2944*0b57cec5SDimitry Andric } 2945*0b57cec5SDimitry Andric 2946*0b57cec5SDimitry Andric bool HexagonConstEvaluator::rewriteHexConstUses(MachineInstr &MI, 2947*0b57cec5SDimitry Andric const CellMap &Inputs) { 2948*0b57cec5SDimitry Andric bool Changed = false; 2949*0b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 2950*0b57cec5SDimitry Andric MachineBasicBlock &B = *MI.getParent(); 2951*0b57cec5SDimitry Andric const DebugLoc &DL = MI.getDebugLoc(); 2952*0b57cec5SDimitry Andric MachineBasicBlock::iterator At = MI.getIterator(); 2953*0b57cec5SDimitry Andric MachineInstr *NewMI = nullptr; 2954*0b57cec5SDimitry Andric 2955*0b57cec5SDimitry Andric switch (Opc) { 2956*0b57cec5SDimitry Andric case Hexagon::M2_maci: 2957*0b57cec5SDimitry Andric // Convert DefR += mpyi(R2, R3) 2958*0b57cec5SDimitry Andric // to DefR += mpyi(R, #imm), 2959*0b57cec5SDimitry Andric // or DefR -= mpyi(R, #imm). 2960*0b57cec5SDimitry Andric { 2961*0b57cec5SDimitry Andric RegisterSubReg DefR(MI.getOperand(0)); 2962*0b57cec5SDimitry Andric assert(!DefR.SubReg); 2963*0b57cec5SDimitry Andric RegisterSubReg R2(MI.getOperand(2)); 2964*0b57cec5SDimitry Andric RegisterSubReg R3(MI.getOperand(3)); 2965*0b57cec5SDimitry Andric assert(Inputs.has(R2.Reg) && Inputs.has(R3.Reg)); 2966*0b57cec5SDimitry Andric LatticeCell LS2, LS3; 2967*0b57cec5SDimitry Andric // It is enough to get one of the input cells, since we will only try 2968*0b57cec5SDimitry Andric // to replace one argument---whichever happens to be a single constant. 2969*0b57cec5SDimitry Andric bool HasC2 = getCell(R2, Inputs, LS2), HasC3 = getCell(R3, Inputs, LS3); 2970*0b57cec5SDimitry Andric if (!HasC2 && !HasC3) 2971*0b57cec5SDimitry Andric return false; 2972*0b57cec5SDimitry Andric bool Zero = ((HasC2 && (LS2.properties() & ConstantProperties::Zero)) || 2973*0b57cec5SDimitry Andric (HasC3 && (LS3.properties() & ConstantProperties::Zero))); 2974*0b57cec5SDimitry Andric // If one of the operands is zero, eliminate the multiplication. 2975*0b57cec5SDimitry Andric if (Zero) { 2976*0b57cec5SDimitry Andric // DefR == R1 (tied operands). 2977*0b57cec5SDimitry Andric MachineOperand &Acc = MI.getOperand(1); 2978*0b57cec5SDimitry Andric RegisterSubReg R1(Acc); 2979*0b57cec5SDimitry Andric unsigned NewR = R1.Reg; 2980*0b57cec5SDimitry Andric if (R1.SubReg) { 2981*0b57cec5SDimitry Andric // Generate COPY. FIXME: Replace with the register:subregister. 2982*0b57cec5SDimitry Andric const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg); 2983*0b57cec5SDimitry Andric NewR = MRI->createVirtualRegister(RC); 2984*0b57cec5SDimitry Andric NewMI = BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR) 2985*0b57cec5SDimitry Andric .addReg(R1.Reg, getRegState(Acc), R1.SubReg); 2986*0b57cec5SDimitry Andric } 2987*0b57cec5SDimitry Andric replaceAllRegUsesWith(DefR.Reg, NewR); 2988*0b57cec5SDimitry Andric MRI->clearKillFlags(NewR); 2989*0b57cec5SDimitry Andric Changed = true; 2990*0b57cec5SDimitry Andric break; 2991*0b57cec5SDimitry Andric } 2992*0b57cec5SDimitry Andric 2993*0b57cec5SDimitry Andric bool Swap = false; 2994*0b57cec5SDimitry Andric if (!LS3.isSingle()) { 2995*0b57cec5SDimitry Andric if (!LS2.isSingle()) 2996*0b57cec5SDimitry Andric return false; 2997*0b57cec5SDimitry Andric Swap = true; 2998*0b57cec5SDimitry Andric } 2999*0b57cec5SDimitry Andric const LatticeCell &LI = Swap ? LS2 : LS3; 3000*0b57cec5SDimitry Andric const MachineOperand &OpR2 = Swap ? MI.getOperand(3) 3001*0b57cec5SDimitry Andric : MI.getOperand(2); 3002*0b57cec5SDimitry Andric // LI is single here. 3003*0b57cec5SDimitry Andric APInt A; 3004*0b57cec5SDimitry Andric if (!constToInt(LI.Value, A) || !A.isSignedIntN(8)) 3005*0b57cec5SDimitry Andric return false; 3006*0b57cec5SDimitry Andric int64_t V = A.getSExtValue(); 3007*0b57cec5SDimitry Andric const MCInstrDesc &D = (V >= 0) ? HII.get(Hexagon::M2_macsip) 3008*0b57cec5SDimitry Andric : HII.get(Hexagon::M2_macsin); 3009*0b57cec5SDimitry Andric if (V < 0) 3010*0b57cec5SDimitry Andric V = -V; 3011*0b57cec5SDimitry Andric const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg); 3012*0b57cec5SDimitry Andric unsigned NewR = MRI->createVirtualRegister(RC); 3013*0b57cec5SDimitry Andric const MachineOperand &Src1 = MI.getOperand(1); 3014*0b57cec5SDimitry Andric NewMI = BuildMI(B, At, DL, D, NewR) 3015*0b57cec5SDimitry Andric .addReg(Src1.getReg(), getRegState(Src1), Src1.getSubReg()) 3016*0b57cec5SDimitry Andric .addReg(OpR2.getReg(), getRegState(OpR2), OpR2.getSubReg()) 3017*0b57cec5SDimitry Andric .addImm(V); 3018*0b57cec5SDimitry Andric replaceAllRegUsesWith(DefR.Reg, NewR); 3019*0b57cec5SDimitry Andric Changed = true; 3020*0b57cec5SDimitry Andric break; 3021*0b57cec5SDimitry Andric } 3022*0b57cec5SDimitry Andric 3023*0b57cec5SDimitry Andric case Hexagon::A2_and: 3024*0b57cec5SDimitry Andric { 3025*0b57cec5SDimitry Andric RegisterSubReg R1(MI.getOperand(1)); 3026*0b57cec5SDimitry Andric RegisterSubReg R2(MI.getOperand(2)); 3027*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg)); 3028*0b57cec5SDimitry Andric LatticeCell LS1, LS2; 3029*0b57cec5SDimitry Andric unsigned CopyOf = 0; 3030*0b57cec5SDimitry Andric // Check if any of the operands is -1 (i.e. all bits set). 3031*0b57cec5SDimitry Andric if (getCell(R1, Inputs, LS1) && LS1.isSingle()) { 3032*0b57cec5SDimitry Andric APInt M1; 3033*0b57cec5SDimitry Andric if (constToInt(LS1.Value, M1) && !~M1) 3034*0b57cec5SDimitry Andric CopyOf = 2; 3035*0b57cec5SDimitry Andric } 3036*0b57cec5SDimitry Andric else if (getCell(R2, Inputs, LS2) && LS2.isSingle()) { 3037*0b57cec5SDimitry Andric APInt M1; 3038*0b57cec5SDimitry Andric if (constToInt(LS2.Value, M1) && !~M1) 3039*0b57cec5SDimitry Andric CopyOf = 1; 3040*0b57cec5SDimitry Andric } 3041*0b57cec5SDimitry Andric if (!CopyOf) 3042*0b57cec5SDimitry Andric return false; 3043*0b57cec5SDimitry Andric MachineOperand &SO = MI.getOperand(CopyOf); 3044*0b57cec5SDimitry Andric RegisterSubReg SR(SO); 3045*0b57cec5SDimitry Andric RegisterSubReg DefR(MI.getOperand(0)); 3046*0b57cec5SDimitry Andric unsigned NewR = SR.Reg; 3047*0b57cec5SDimitry Andric if (SR.SubReg) { 3048*0b57cec5SDimitry Andric const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg); 3049*0b57cec5SDimitry Andric NewR = MRI->createVirtualRegister(RC); 3050*0b57cec5SDimitry Andric NewMI = BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR) 3051*0b57cec5SDimitry Andric .addReg(SR.Reg, getRegState(SO), SR.SubReg); 3052*0b57cec5SDimitry Andric } 3053*0b57cec5SDimitry Andric replaceAllRegUsesWith(DefR.Reg, NewR); 3054*0b57cec5SDimitry Andric MRI->clearKillFlags(NewR); 3055*0b57cec5SDimitry Andric Changed = true; 3056*0b57cec5SDimitry Andric } 3057*0b57cec5SDimitry Andric break; 3058*0b57cec5SDimitry Andric 3059*0b57cec5SDimitry Andric case Hexagon::A2_or: 3060*0b57cec5SDimitry Andric { 3061*0b57cec5SDimitry Andric RegisterSubReg R1(MI.getOperand(1)); 3062*0b57cec5SDimitry Andric RegisterSubReg R2(MI.getOperand(2)); 3063*0b57cec5SDimitry Andric assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg)); 3064*0b57cec5SDimitry Andric LatticeCell LS1, LS2; 3065*0b57cec5SDimitry Andric unsigned CopyOf = 0; 3066*0b57cec5SDimitry Andric 3067*0b57cec5SDimitry Andric using P = ConstantProperties; 3068*0b57cec5SDimitry Andric 3069*0b57cec5SDimitry Andric if (getCell(R1, Inputs, LS1) && (LS1.properties() & P::Zero)) 3070*0b57cec5SDimitry Andric CopyOf = 2; 3071*0b57cec5SDimitry Andric else if (getCell(R2, Inputs, LS2) && (LS2.properties() & P::Zero)) 3072*0b57cec5SDimitry Andric CopyOf = 1; 3073*0b57cec5SDimitry Andric if (!CopyOf) 3074*0b57cec5SDimitry Andric return false; 3075*0b57cec5SDimitry Andric MachineOperand &SO = MI.getOperand(CopyOf); 3076*0b57cec5SDimitry Andric RegisterSubReg SR(SO); 3077*0b57cec5SDimitry Andric RegisterSubReg DefR(MI.getOperand(0)); 3078*0b57cec5SDimitry Andric unsigned NewR = SR.Reg; 3079*0b57cec5SDimitry Andric if (SR.SubReg) { 3080*0b57cec5SDimitry Andric const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg); 3081*0b57cec5SDimitry Andric NewR = MRI->createVirtualRegister(RC); 3082*0b57cec5SDimitry Andric NewMI = BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR) 3083*0b57cec5SDimitry Andric .addReg(SR.Reg, getRegState(SO), SR.SubReg); 3084*0b57cec5SDimitry Andric } 3085*0b57cec5SDimitry Andric replaceAllRegUsesWith(DefR.Reg, NewR); 3086*0b57cec5SDimitry Andric MRI->clearKillFlags(NewR); 3087*0b57cec5SDimitry Andric Changed = true; 3088*0b57cec5SDimitry Andric } 3089*0b57cec5SDimitry Andric break; 3090*0b57cec5SDimitry Andric } 3091*0b57cec5SDimitry Andric 3092*0b57cec5SDimitry Andric if (NewMI) { 3093*0b57cec5SDimitry Andric // clear all the kill flags of this new instruction. 3094*0b57cec5SDimitry Andric for (MachineOperand &MO : NewMI->operands()) 3095*0b57cec5SDimitry Andric if (MO.isReg() && MO.isUse()) 3096*0b57cec5SDimitry Andric MO.setIsKill(false); 3097*0b57cec5SDimitry Andric } 3098*0b57cec5SDimitry Andric 3099*0b57cec5SDimitry Andric LLVM_DEBUG({ 3100*0b57cec5SDimitry Andric if (NewMI) { 3101*0b57cec5SDimitry Andric dbgs() << "Rewrite: for " << MI; 3102*0b57cec5SDimitry Andric if (NewMI != &MI) 3103*0b57cec5SDimitry Andric dbgs() << " created " << *NewMI; 3104*0b57cec5SDimitry Andric else 3105*0b57cec5SDimitry Andric dbgs() << " modified the instruction itself and created:" << *NewMI; 3106*0b57cec5SDimitry Andric } 3107*0b57cec5SDimitry Andric }); 3108*0b57cec5SDimitry Andric 3109*0b57cec5SDimitry Andric return Changed; 3110*0b57cec5SDimitry Andric } 3111*0b57cec5SDimitry Andric 3112*0b57cec5SDimitry Andric void HexagonConstEvaluator::replaceAllRegUsesWith(unsigned FromReg, 3113*0b57cec5SDimitry Andric unsigned ToReg) { 3114*0b57cec5SDimitry Andric assert(TargetRegisterInfo::isVirtualRegister(FromReg)); 3115*0b57cec5SDimitry Andric assert(TargetRegisterInfo::isVirtualRegister(ToReg)); 3116*0b57cec5SDimitry Andric for (auto I = MRI->use_begin(FromReg), E = MRI->use_end(); I != E;) { 3117*0b57cec5SDimitry Andric MachineOperand &O = *I; 3118*0b57cec5SDimitry Andric ++I; 3119*0b57cec5SDimitry Andric O.setReg(ToReg); 3120*0b57cec5SDimitry Andric } 3121*0b57cec5SDimitry Andric } 3122*0b57cec5SDimitry Andric 3123*0b57cec5SDimitry Andric bool HexagonConstEvaluator::rewriteHexBranch(MachineInstr &BrI, 3124*0b57cec5SDimitry Andric const CellMap &Inputs) { 3125*0b57cec5SDimitry Andric MachineBasicBlock &B = *BrI.getParent(); 3126*0b57cec5SDimitry Andric unsigned NumOp = BrI.getNumOperands(); 3127*0b57cec5SDimitry Andric if (!NumOp) 3128*0b57cec5SDimitry Andric return false; 3129*0b57cec5SDimitry Andric 3130*0b57cec5SDimitry Andric bool FallsThru; 3131*0b57cec5SDimitry Andric SetVector<const MachineBasicBlock*> Targets; 3132*0b57cec5SDimitry Andric bool Eval = evaluate(BrI, Inputs, Targets, FallsThru); 3133*0b57cec5SDimitry Andric unsigned NumTargets = Targets.size(); 3134*0b57cec5SDimitry Andric if (!Eval || NumTargets > 1 || (NumTargets == 1 && FallsThru)) 3135*0b57cec5SDimitry Andric return false; 3136*0b57cec5SDimitry Andric if (BrI.getOpcode() == Hexagon::J2_jump) 3137*0b57cec5SDimitry Andric return false; 3138*0b57cec5SDimitry Andric 3139*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Rewrite(" << printMBBReference(B) << "):" << BrI); 3140*0b57cec5SDimitry Andric bool Rewritten = false; 3141*0b57cec5SDimitry Andric if (NumTargets > 0) { 3142*0b57cec5SDimitry Andric assert(!FallsThru && "This should have been checked before"); 3143*0b57cec5SDimitry Andric // MIB.addMBB needs non-const pointer. 3144*0b57cec5SDimitry Andric MachineBasicBlock *TargetB = const_cast<MachineBasicBlock*>(Targets[0]); 3145*0b57cec5SDimitry Andric bool Moot = B.isLayoutSuccessor(TargetB); 3146*0b57cec5SDimitry Andric if (!Moot) { 3147*0b57cec5SDimitry Andric // If we build a branch here, we must make sure that it won't be 3148*0b57cec5SDimitry Andric // erased as "non-executable". We can't mark any new instructions 3149*0b57cec5SDimitry Andric // as executable here, so we need to overwrite the BrI, which we 3150*0b57cec5SDimitry Andric // know is executable. 3151*0b57cec5SDimitry Andric const MCInstrDesc &JD = HII.get(Hexagon::J2_jump); 3152*0b57cec5SDimitry Andric auto NI = BuildMI(B, BrI.getIterator(), BrI.getDebugLoc(), JD) 3153*0b57cec5SDimitry Andric .addMBB(TargetB); 3154*0b57cec5SDimitry Andric BrI.setDesc(JD); 3155*0b57cec5SDimitry Andric while (BrI.getNumOperands() > 0) 3156*0b57cec5SDimitry Andric BrI.RemoveOperand(0); 3157*0b57cec5SDimitry Andric // This ensures that all implicit operands (e.g. implicit-def %r31, etc) 3158*0b57cec5SDimitry Andric // are present in the rewritten branch. 3159*0b57cec5SDimitry Andric for (auto &Op : NI->operands()) 3160*0b57cec5SDimitry Andric BrI.addOperand(Op); 3161*0b57cec5SDimitry Andric NI->eraseFromParent(); 3162*0b57cec5SDimitry Andric Rewritten = true; 3163*0b57cec5SDimitry Andric } 3164*0b57cec5SDimitry Andric } 3165*0b57cec5SDimitry Andric 3166*0b57cec5SDimitry Andric // Do not erase instructions. A newly created instruction could get 3167*0b57cec5SDimitry Andric // the same address as an instruction marked as executable during the 3168*0b57cec5SDimitry Andric // propagation. 3169*0b57cec5SDimitry Andric if (!Rewritten) 3170*0b57cec5SDimitry Andric replaceWithNop(BrI); 3171*0b57cec5SDimitry Andric return true; 3172*0b57cec5SDimitry Andric } 3173*0b57cec5SDimitry Andric 3174*0b57cec5SDimitry Andric FunctionPass *llvm::createHexagonConstPropagationPass() { 3175*0b57cec5SDimitry Andric return new HexagonConstPropagation(); 3176*0b57cec5SDimitry Andric } 3177