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