1*9880d681SAndroid Build Coastguard Worker //===----- HexagonMCChecker.h - Instruction bundle checking ---------------===// 2*9880d681SAndroid Build Coastguard Worker // 3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure 4*9880d681SAndroid Build Coastguard Worker // 5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*9880d681SAndroid Build Coastguard Worker // 8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*9880d681SAndroid Build Coastguard Worker // 10*9880d681SAndroid Build Coastguard Worker // This implements the checking of insns inside a bundle according to the 11*9880d681SAndroid Build Coastguard Worker // packet constraint rules of the Hexagon ISA. 12*9880d681SAndroid Build Coastguard Worker // 13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 14*9880d681SAndroid Build Coastguard Worker 15*9880d681SAndroid Build Coastguard Worker #ifndef HEXAGONMCCHECKER_H 16*9880d681SAndroid Build Coastguard Worker #define HEXAGONMCCHECKER_H 17*9880d681SAndroid Build Coastguard Worker 18*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/HexagonMCShuffler.h" 19*9880d681SAndroid Build Coastguard Worker #include <queue> 20*9880d681SAndroid Build Coastguard Worker #include <set> 21*9880d681SAndroid Build Coastguard Worker 22*9880d681SAndroid Build Coastguard Worker using namespace llvm; 23*9880d681SAndroid Build Coastguard Worker 24*9880d681SAndroid Build Coastguard Worker namespace llvm { 25*9880d681SAndroid Build Coastguard Worker class MCOperandInfo; 26*9880d681SAndroid Build Coastguard Worker 27*9880d681SAndroid Build Coastguard Worker typedef struct { 28*9880d681SAndroid Build Coastguard Worker unsigned Error, Warning, ShuffleError; 29*9880d681SAndroid Build Coastguard Worker unsigned Register; 30*9880d681SAndroid Build Coastguard Worker } ErrInfo_T; 31*9880d681SAndroid Build Coastguard Worker 32*9880d681SAndroid Build Coastguard Worker class HexagonMCErrInfo { 33*9880d681SAndroid Build Coastguard Worker public: 34*9880d681SAndroid Build Coastguard Worker enum { 35*9880d681SAndroid Build Coastguard Worker CHECK_SUCCESS = 0, 36*9880d681SAndroid Build Coastguard Worker // Errors. 37*9880d681SAndroid Build Coastguard Worker CHECK_ERROR_BRANCHES = 0x00001, 38*9880d681SAndroid Build Coastguard Worker CHECK_ERROR_NEWP = 0x00002, 39*9880d681SAndroid Build Coastguard Worker CHECK_ERROR_NEWV = 0x00004, 40*9880d681SAndroid Build Coastguard Worker CHECK_ERROR_REGISTERS = 0x00008, 41*9880d681SAndroid Build Coastguard Worker CHECK_ERROR_READONLY = 0x00010, 42*9880d681SAndroid Build Coastguard Worker CHECK_ERROR_LOOP = 0x00020, 43*9880d681SAndroid Build Coastguard Worker CHECK_ERROR_ENDLOOP = 0x00040, 44*9880d681SAndroid Build Coastguard Worker CHECK_ERROR_SOLO = 0x00080, 45*9880d681SAndroid Build Coastguard Worker CHECK_ERROR_SHUFFLE = 0x00100, 46*9880d681SAndroid Build Coastguard Worker CHECK_ERROR_NOSLOTS = 0x00200, 47*9880d681SAndroid Build Coastguard Worker CHECK_ERROR_UNKNOWN = 0x00400, 48*9880d681SAndroid Build Coastguard Worker // Warnings. 49*9880d681SAndroid Build Coastguard Worker CHECK_WARN_CURRENT = 0x10000, 50*9880d681SAndroid Build Coastguard Worker CHECK_WARN_TEMPORARY = 0x20000 51*9880d681SAndroid Build Coastguard Worker }; 52*9880d681SAndroid Build Coastguard Worker ErrInfo_T s; 53*9880d681SAndroid Build Coastguard Worker reset()54*9880d681SAndroid Build Coastguard Worker void reset() { 55*9880d681SAndroid Build Coastguard Worker s.Error = CHECK_SUCCESS; 56*9880d681SAndroid Build Coastguard Worker s.Warning = CHECK_SUCCESS; 57*9880d681SAndroid Build Coastguard Worker s.ShuffleError = HexagonShuffler::SHUFFLE_SUCCESS; 58*9880d681SAndroid Build Coastguard Worker s.Register = Hexagon::NoRegister; 59*9880d681SAndroid Build Coastguard Worker }; HexagonMCErrInfo()60*9880d681SAndroid Build Coastguard Worker HexagonMCErrInfo() { 61*9880d681SAndroid Build Coastguard Worker reset(); 62*9880d681SAndroid Build Coastguard Worker }; 63*9880d681SAndroid Build Coastguard Worker 64*9880d681SAndroid Build Coastguard Worker void setError(unsigned e, unsigned r = Hexagon::NoRegister) 65*9880d681SAndroid Build Coastguard Worker { s.Error = e; s.Register = r; }; 66*9880d681SAndroid Build Coastguard Worker void setWarning(unsigned w, unsigned r = Hexagon::NoRegister) 67*9880d681SAndroid Build Coastguard Worker { s.Warning = w; s.Register = r; }; setShuffleError(unsigned e)68*9880d681SAndroid Build Coastguard Worker void setShuffleError(unsigned e) { s.ShuffleError = e; }; 69*9880d681SAndroid Build Coastguard Worker }; 70*9880d681SAndroid Build Coastguard Worker 71*9880d681SAndroid Build Coastguard Worker /// Check for a valid bundle. 72*9880d681SAndroid Build Coastguard Worker class HexagonMCChecker { 73*9880d681SAndroid Build Coastguard Worker /// Insn bundle. 74*9880d681SAndroid Build Coastguard Worker MCInst& MCB; 75*9880d681SAndroid Build Coastguard Worker MCInst& MCBDX; 76*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo& RI; 77*9880d681SAndroid Build Coastguard Worker MCInstrInfo const &MCII; 78*9880d681SAndroid Build Coastguard Worker MCSubtargetInfo const &STI; 79*9880d681SAndroid Build Coastguard Worker bool bLoadErrInfo; 80*9880d681SAndroid Build Coastguard Worker 81*9880d681SAndroid Build Coastguard Worker /// Set of definitions: register #, if predicated, if predicated true. 82*9880d681SAndroid Build Coastguard Worker typedef std::pair<unsigned, bool> PredSense; 83*9880d681SAndroid Build Coastguard Worker static const PredSense Unconditional; 84*9880d681SAndroid Build Coastguard Worker typedef std::multiset<PredSense> PredSet; 85*9880d681SAndroid Build Coastguard Worker typedef std::multiset<PredSense>::iterator PredSetIterator; 86*9880d681SAndroid Build Coastguard Worker 87*9880d681SAndroid Build Coastguard Worker typedef llvm::DenseMap<unsigned, PredSet>::iterator DefsIterator; 88*9880d681SAndroid Build Coastguard Worker llvm::DenseMap<unsigned, PredSet> Defs; 89*9880d681SAndroid Build Coastguard Worker 90*9880d681SAndroid Build Coastguard Worker /// Information about how a new-value register is defined or used: 91*9880d681SAndroid Build Coastguard Worker /// PredReg = predicate register, 0 if use/def not predicated, 92*9880d681SAndroid Build Coastguard Worker /// Cond = true/false for if(PredReg)/if(!PredReg) respectively, 93*9880d681SAndroid Build Coastguard Worker /// IsFloat = true if definition produces a floating point value 94*9880d681SAndroid Build Coastguard Worker /// (not valid for uses), 95*9880d681SAndroid Build Coastguard Worker /// IsNVJ = true if the use is a new-value branch (not valid for 96*9880d681SAndroid Build Coastguard Worker /// definitions). 97*9880d681SAndroid Build Coastguard Worker struct NewSense { 98*9880d681SAndroid Build Coastguard Worker unsigned PredReg; 99*9880d681SAndroid Build Coastguard Worker bool IsFloat, IsNVJ, Cond; 100*9880d681SAndroid Build Coastguard Worker // The special-case "constructors": JmpNewSense101*9880d681SAndroid Build Coastguard Worker static NewSense Jmp(bool isNVJ) { 102*9880d681SAndroid Build Coastguard Worker NewSense NS = { /*PredReg=*/ 0, /*IsFloat=*/ false, /*IsNVJ=*/ isNVJ, 103*9880d681SAndroid Build Coastguard Worker /*Cond=*/ false }; 104*9880d681SAndroid Build Coastguard Worker return NS; 105*9880d681SAndroid Build Coastguard Worker } UseNewSense106*9880d681SAndroid Build Coastguard Worker static NewSense Use(unsigned PR, bool True) { 107*9880d681SAndroid Build Coastguard Worker NewSense NS = { /*PredReg=*/ PR, /*IsFloat=*/ false, /*IsNVJ=*/ false, 108*9880d681SAndroid Build Coastguard Worker /*Cond=*/ True }; 109*9880d681SAndroid Build Coastguard Worker return NS; 110*9880d681SAndroid Build Coastguard Worker } DefNewSense111*9880d681SAndroid Build Coastguard Worker static NewSense Def(unsigned PR, bool True, bool Float) { 112*9880d681SAndroid Build Coastguard Worker NewSense NS = { /*PredReg=*/ PR, /*IsFloat=*/ Float, /*IsNVJ=*/ false, 113*9880d681SAndroid Build Coastguard Worker /*Cond=*/ True }; 114*9880d681SAndroid Build Coastguard Worker return NS; 115*9880d681SAndroid Build Coastguard Worker } 116*9880d681SAndroid Build Coastguard Worker }; 117*9880d681SAndroid Build Coastguard Worker /// Set of definitions that produce new register: 118*9880d681SAndroid Build Coastguard Worker typedef llvm::SmallVector<NewSense,2> NewSenseList; 119*9880d681SAndroid Build Coastguard Worker typedef llvm::DenseMap<unsigned, NewSenseList>::iterator NewDefsIterator; 120*9880d681SAndroid Build Coastguard Worker llvm::DenseMap<unsigned, NewSenseList> NewDefs; 121*9880d681SAndroid Build Coastguard Worker 122*9880d681SAndroid Build Coastguard Worker /// Set of weak definitions whose clashes should be enforced selectively. 123*9880d681SAndroid Build Coastguard Worker typedef std::set<unsigned>::iterator SoftDefsIterator; 124*9880d681SAndroid Build Coastguard Worker std::set<unsigned> SoftDefs; 125*9880d681SAndroid Build Coastguard Worker 126*9880d681SAndroid Build Coastguard Worker /// Set of current definitions committed to the register file. 127*9880d681SAndroid Build Coastguard Worker typedef std::set<unsigned>::iterator CurDefsIterator; 128*9880d681SAndroid Build Coastguard Worker std::set<unsigned> CurDefs; 129*9880d681SAndroid Build Coastguard Worker 130*9880d681SAndroid Build Coastguard Worker /// Set of temporary definitions not committed to the register file. 131*9880d681SAndroid Build Coastguard Worker typedef std::set<unsigned>::iterator TmpDefsIterator; 132*9880d681SAndroid Build Coastguard Worker std::set<unsigned> TmpDefs; 133*9880d681SAndroid Build Coastguard Worker 134*9880d681SAndroid Build Coastguard Worker /// Set of new predicates used. 135*9880d681SAndroid Build Coastguard Worker typedef std::set<unsigned>::iterator NewPredsIterator; 136*9880d681SAndroid Build Coastguard Worker std::set<unsigned> NewPreds; 137*9880d681SAndroid Build Coastguard Worker 138*9880d681SAndroid Build Coastguard Worker /// Set of predicates defined late. 139*9880d681SAndroid Build Coastguard Worker typedef std::multiset<unsigned>::iterator LatePredsIterator; 140*9880d681SAndroid Build Coastguard Worker std::multiset<unsigned> LatePreds; 141*9880d681SAndroid Build Coastguard Worker 142*9880d681SAndroid Build Coastguard Worker /// Set of uses. 143*9880d681SAndroid Build Coastguard Worker typedef std::set<unsigned>::iterator UsesIterator; 144*9880d681SAndroid Build Coastguard Worker std::set<unsigned> Uses; 145*9880d681SAndroid Build Coastguard Worker 146*9880d681SAndroid Build Coastguard Worker /// Set of new values used: new register, if new-value jump. 147*9880d681SAndroid Build Coastguard Worker typedef llvm::DenseMap<unsigned, NewSense>::iterator NewUsesIterator; 148*9880d681SAndroid Build Coastguard Worker llvm::DenseMap<unsigned, NewSense> NewUses; 149*9880d681SAndroid Build Coastguard Worker 150*9880d681SAndroid Build Coastguard Worker /// Pre-defined set of read-only registers. 151*9880d681SAndroid Build Coastguard Worker typedef std::set<unsigned>::iterator ReadOnlyIterator; 152*9880d681SAndroid Build Coastguard Worker std::set<unsigned> ReadOnly; 153*9880d681SAndroid Build Coastguard Worker 154*9880d681SAndroid Build Coastguard Worker std::queue<ErrInfo_T> ErrInfoQ; 155*9880d681SAndroid Build Coastguard Worker HexagonMCErrInfo CrntErrInfo; 156*9880d681SAndroid Build Coastguard Worker getErrInfo()157*9880d681SAndroid Build Coastguard Worker void getErrInfo() { 158*9880d681SAndroid Build Coastguard Worker if (bLoadErrInfo == true) { 159*9880d681SAndroid Build Coastguard Worker if (ErrInfoQ.empty()) { 160*9880d681SAndroid Build Coastguard Worker CrntErrInfo.reset(); 161*9880d681SAndroid Build Coastguard Worker } else { 162*9880d681SAndroid Build Coastguard Worker CrntErrInfo.s = ErrInfoQ.front(); 163*9880d681SAndroid Build Coastguard Worker ErrInfoQ.pop(); 164*9880d681SAndroid Build Coastguard Worker } 165*9880d681SAndroid Build Coastguard Worker } 166*9880d681SAndroid Build Coastguard Worker bLoadErrInfo = false; 167*9880d681SAndroid Build Coastguard Worker } 168*9880d681SAndroid Build Coastguard Worker 169*9880d681SAndroid Build Coastguard Worker void init(); 170*9880d681SAndroid Build Coastguard Worker void init(MCInst const&); 171*9880d681SAndroid Build Coastguard Worker 172*9880d681SAndroid Build Coastguard Worker // Checks performed. 173*9880d681SAndroid Build Coastguard Worker bool checkBranches(); 174*9880d681SAndroid Build Coastguard Worker bool checkPredicates(); 175*9880d681SAndroid Build Coastguard Worker bool checkNewValues(); 176*9880d681SAndroid Build Coastguard Worker bool checkRegisters(); 177*9880d681SAndroid Build Coastguard Worker bool checkSolo(); 178*9880d681SAndroid Build Coastguard Worker bool checkShuffle(); 179*9880d681SAndroid Build Coastguard Worker bool checkSlots(); 180*9880d681SAndroid Build Coastguard Worker 181*9880d681SAndroid Build Coastguard Worker static void compoundRegisterMap(unsigned&); 182*9880d681SAndroid Build Coastguard Worker isPredicateRegister(unsigned R)183*9880d681SAndroid Build Coastguard Worker bool isPredicateRegister(unsigned R) const { 184*9880d681SAndroid Build Coastguard Worker return (Hexagon::P0 == R || Hexagon::P1 == R || 185*9880d681SAndroid Build Coastguard Worker Hexagon::P2 == R || Hexagon::P3 == R); 186*9880d681SAndroid Build Coastguard Worker }; isLoopRegister(unsigned R)187*9880d681SAndroid Build Coastguard Worker bool isLoopRegister(unsigned R) const { 188*9880d681SAndroid Build Coastguard Worker return (Hexagon::SA0 == R || Hexagon::LC0 == R || 189*9880d681SAndroid Build Coastguard Worker Hexagon::SA1 == R || Hexagon::LC1 == R); 190*9880d681SAndroid Build Coastguard Worker }; 191*9880d681SAndroid Build Coastguard Worker 192*9880d681SAndroid Build Coastguard Worker bool hasValidNewValueDef(const NewSense &Use, 193*9880d681SAndroid Build Coastguard Worker const NewSenseList &Defs) const; 194*9880d681SAndroid Build Coastguard Worker 195*9880d681SAndroid Build Coastguard Worker public: 196*9880d681SAndroid Build Coastguard Worker explicit HexagonMCChecker(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst& mcb, MCInst &mcbdx, 197*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo& ri); 198*9880d681SAndroid Build Coastguard Worker 199*9880d681SAndroid Build Coastguard Worker bool check(); 200*9880d681SAndroid Build Coastguard Worker 201*9880d681SAndroid Build Coastguard Worker /// add a new error/warning addErrInfo(HexagonMCErrInfo & err)202*9880d681SAndroid Build Coastguard Worker void addErrInfo(HexagonMCErrInfo &err) { ErrInfoQ.push(err.s); }; 203*9880d681SAndroid Build Coastguard Worker 204*9880d681SAndroid Build Coastguard Worker /// Return the error code for the last operation in the insn bundle. getError()205*9880d681SAndroid Build Coastguard Worker unsigned getError() { getErrInfo(); return CrntErrInfo.s.Error; }; getWarning()206*9880d681SAndroid Build Coastguard Worker unsigned getWarning() { getErrInfo(); return CrntErrInfo.s.Warning; }; getShuffleError()207*9880d681SAndroid Build Coastguard Worker unsigned getShuffleError() { getErrInfo(); return CrntErrInfo.s.ShuffleError; }; getErrRegister()208*9880d681SAndroid Build Coastguard Worker unsigned getErrRegister() { getErrInfo(); return CrntErrInfo.s.Register; }; getNextErrInfo()209*9880d681SAndroid Build Coastguard Worker bool getNextErrInfo() { 210*9880d681SAndroid Build Coastguard Worker bLoadErrInfo = true; 211*9880d681SAndroid Build Coastguard Worker return (ErrInfoQ.empty()) ? false : (getErrInfo(), true); 212*9880d681SAndroid Build Coastguard Worker } 213*9880d681SAndroid Build Coastguard Worker }; 214*9880d681SAndroid Build Coastguard Worker 215*9880d681SAndroid Build Coastguard Worker } 216*9880d681SAndroid Build Coastguard Worker 217*9880d681SAndroid Build Coastguard Worker #endif // HEXAGONMCCHECKER_H 218