xref: /aosp_15_r20/external/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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