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