1 | //===-- VE.h - Top-level interface for VE representation --------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file contains the entry points for global functions defined in the LLVM |
10 | // VE back-end. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_LIB_TARGET_VE_VE_H |
15 | #define LLVM_LIB_TARGET_VE_VE_H |
16 | |
17 | #include "MCTargetDesc/VEMCTargetDesc.h" |
18 | #include "llvm/ADT/StringSwitch.h" |
19 | #include "llvm/Support/ErrorHandling.h" |
20 | #include "llvm/Target/TargetMachine.h" |
21 | |
22 | namespace llvm { |
23 | class AsmPrinter; |
24 | class FunctionPass; |
25 | class MCInst; |
26 | class MachineInstr; |
27 | class PassRegistry; |
28 | class VETargetMachine; |
29 | |
30 | FunctionPass *createVEISelDag(VETargetMachine &TM); |
31 | FunctionPass *createLVLGenPass(); |
32 | void initializeVEDAGToDAGISelLegacyPass(PassRegistry &); |
33 | |
34 | void LowerVEMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, |
35 | AsmPrinter &AP); |
36 | } // namespace llvm |
37 | |
38 | namespace llvm { |
39 | // Enums corresponding to VE condition codes, both icc's and fcc's. These |
40 | // values must be kept in sync with the ones in the .td file. |
41 | namespace VECC { |
42 | enum CondCode { |
43 | // Integer comparison |
44 | CC_IG = 0, // Greater |
45 | CC_IL = 1, // Less |
46 | CC_INE = 2, // Not Equal |
47 | CC_IEQ = 3, // Equal |
48 | CC_IGE = 4, // Greater or Equal |
49 | CC_ILE = 5, // Less or Equal |
50 | |
51 | // Floating point comparison |
52 | CC_AF = 0 + 6, // Never |
53 | CC_G = 1 + 6, // Greater |
54 | CC_L = 2 + 6, // Less |
55 | CC_NE = 3 + 6, // Not Equal |
56 | CC_EQ = 4 + 6, // Equal |
57 | CC_GE = 5 + 6, // Greater or Equal |
58 | CC_LE = 6 + 6, // Less or Equal |
59 | CC_NUM = 7 + 6, // Number |
60 | CC_NAN = 8 + 6, // NaN |
61 | CC_GNAN = 9 + 6, // Greater or NaN |
62 | CC_LNAN = 10 + 6, // Less or NaN |
63 | CC_NENAN = 11 + 6, // Not Equal or NaN |
64 | CC_EQNAN = 12 + 6, // Equal or NaN |
65 | CC_GENAN = 13 + 6, // Greater or Equal or NaN |
66 | CC_LENAN = 14 + 6, // Less or Equal or NaN |
67 | CC_AT = 15 + 6, // Always |
68 | UNKNOWN |
69 | }; |
70 | } |
71 | // Enums corresponding to VE Rounding Mode. These values must be kept in |
72 | // sync with the ones in the .td file. |
73 | namespace VERD { |
74 | enum RoundingMode { |
75 | RD_NONE = 0, // According to PSW |
76 | RD_RZ = 8, // Round toward Zero |
77 | RD_RP = 9, // Round toward Plus infinity |
78 | RD_RM = 10, // Round toward Minus infinity |
79 | RD_RN = 11, // Round to Nearest (ties to Even) |
80 | RD_RA = 12, // Round to Nearest (ties to Away) |
81 | UNKNOWN |
82 | }; |
83 | } |
84 | |
85 | inline static const char *VECondCodeToString(VECC::CondCode CC) { |
86 | switch (CC) { |
87 | case VECC::CC_IG: return "gt" ; |
88 | case VECC::CC_IL: return "lt" ; |
89 | case VECC::CC_INE: return "ne" ; |
90 | case VECC::CC_IEQ: return "eq" ; |
91 | case VECC::CC_IGE: return "ge" ; |
92 | case VECC::CC_ILE: return "le" ; |
93 | case VECC::CC_AF: return "af" ; |
94 | case VECC::CC_G: return "gt" ; |
95 | case VECC::CC_L: return "lt" ; |
96 | case VECC::CC_NE: return "ne" ; |
97 | case VECC::CC_EQ: return "eq" ; |
98 | case VECC::CC_GE: return "ge" ; |
99 | case VECC::CC_LE: return "le" ; |
100 | case VECC::CC_NUM: return "num" ; |
101 | case VECC::CC_NAN: return "nan" ; |
102 | case VECC::CC_GNAN: return "gtnan" ; |
103 | case VECC::CC_LNAN: return "ltnan" ; |
104 | case VECC::CC_NENAN: return "nenan" ; |
105 | case VECC::CC_EQNAN: return "eqnan" ; |
106 | case VECC::CC_GENAN: return "genan" ; |
107 | case VECC::CC_LENAN: return "lenan" ; |
108 | case VECC::CC_AT: return "at" ; |
109 | default: |
110 | llvm_unreachable("Invalid cond code" ); |
111 | } |
112 | } |
113 | |
114 | inline static VECC::CondCode stringToVEICondCode(StringRef S) { |
115 | return StringSwitch<VECC::CondCode>(S) |
116 | .Case(S: "gt" , Value: VECC::CC_IG) |
117 | .Case(S: "lt" , Value: VECC::CC_IL) |
118 | .Case(S: "ne" , Value: VECC::CC_INE) |
119 | .Case(S: "eq" , Value: VECC::CC_IEQ) |
120 | .Case(S: "ge" , Value: VECC::CC_IGE) |
121 | .Case(S: "le" , Value: VECC::CC_ILE) |
122 | .Case(S: "af" , Value: VECC::CC_AF) |
123 | .Case(S: "at" , Value: VECC::CC_AT) |
124 | .Case(S: "" , Value: VECC::CC_AT) |
125 | .Default(Value: VECC::UNKNOWN); |
126 | } |
127 | |
128 | inline static VECC::CondCode stringToVEFCondCode(StringRef S) { |
129 | return StringSwitch<VECC::CondCode>(S) |
130 | .Case(S: "gt" , Value: VECC::CC_G) |
131 | .Case(S: "lt" , Value: VECC::CC_L) |
132 | .Case(S: "ne" , Value: VECC::CC_NE) |
133 | .Case(S: "eq" , Value: VECC::CC_EQ) |
134 | .Case(S: "ge" , Value: VECC::CC_GE) |
135 | .Case(S: "le" , Value: VECC::CC_LE) |
136 | .Case(S: "num" , Value: VECC::CC_NUM) |
137 | .Case(S: "nan" , Value: VECC::CC_NAN) |
138 | .Case(S: "gtnan" , Value: VECC::CC_GNAN) |
139 | .Case(S: "ltnan" , Value: VECC::CC_LNAN) |
140 | .Case(S: "nenan" , Value: VECC::CC_NENAN) |
141 | .Case(S: "eqnan" , Value: VECC::CC_EQNAN) |
142 | .Case(S: "genan" , Value: VECC::CC_GENAN) |
143 | .Case(S: "lenan" , Value: VECC::CC_LENAN) |
144 | .Case(S: "af" , Value: VECC::CC_AF) |
145 | .Case(S: "at" , Value: VECC::CC_AT) |
146 | .Case(S: "" , Value: VECC::CC_AT) |
147 | .Default(Value: VECC::UNKNOWN); |
148 | } |
149 | |
150 | inline static bool isIntVECondCode(VECC::CondCode CC) { |
151 | return CC < VECC::CC_AF; |
152 | } |
153 | |
154 | inline static unsigned VECondCodeToVal(VECC::CondCode CC) { |
155 | switch (CC) { |
156 | case VECC::CC_IG: |
157 | return 1; |
158 | case VECC::CC_IL: |
159 | return 2; |
160 | case VECC::CC_INE: |
161 | return 3; |
162 | case VECC::CC_IEQ: |
163 | return 4; |
164 | case VECC::CC_IGE: |
165 | return 5; |
166 | case VECC::CC_ILE: |
167 | return 6; |
168 | case VECC::CC_AF: |
169 | return 0; |
170 | case VECC::CC_G: |
171 | return 1; |
172 | case VECC::CC_L: |
173 | return 2; |
174 | case VECC::CC_NE: |
175 | return 3; |
176 | case VECC::CC_EQ: |
177 | return 4; |
178 | case VECC::CC_GE: |
179 | return 5; |
180 | case VECC::CC_LE: |
181 | return 6; |
182 | case VECC::CC_NUM: |
183 | return 7; |
184 | case VECC::CC_NAN: |
185 | return 8; |
186 | case VECC::CC_GNAN: |
187 | return 9; |
188 | case VECC::CC_LNAN: |
189 | return 10; |
190 | case VECC::CC_NENAN: |
191 | return 11; |
192 | case VECC::CC_EQNAN: |
193 | return 12; |
194 | case VECC::CC_GENAN: |
195 | return 13; |
196 | case VECC::CC_LENAN: |
197 | return 14; |
198 | case VECC::CC_AT: |
199 | return 15; |
200 | default: |
201 | llvm_unreachable("Invalid cond code" ); |
202 | } |
203 | } |
204 | |
205 | inline static VECC::CondCode VEValToCondCode(unsigned Val, bool IsInteger) { |
206 | if (IsInteger) { |
207 | switch (Val) { |
208 | case 0: |
209 | return VECC::CC_AF; |
210 | case 1: |
211 | return VECC::CC_IG; |
212 | case 2: |
213 | return VECC::CC_IL; |
214 | case 3: |
215 | return VECC::CC_INE; |
216 | case 4: |
217 | return VECC::CC_IEQ; |
218 | case 5: |
219 | return VECC::CC_IGE; |
220 | case 6: |
221 | return VECC::CC_ILE; |
222 | case 15: |
223 | return VECC::CC_AT; |
224 | } |
225 | } else { |
226 | switch (Val) { |
227 | case 0: |
228 | return VECC::CC_AF; |
229 | case 1: |
230 | return VECC::CC_G; |
231 | case 2: |
232 | return VECC::CC_L; |
233 | case 3: |
234 | return VECC::CC_NE; |
235 | case 4: |
236 | return VECC::CC_EQ; |
237 | case 5: |
238 | return VECC::CC_GE; |
239 | case 6: |
240 | return VECC::CC_LE; |
241 | case 7: |
242 | return VECC::CC_NUM; |
243 | case 8: |
244 | return VECC::CC_NAN; |
245 | case 9: |
246 | return VECC::CC_GNAN; |
247 | case 10: |
248 | return VECC::CC_LNAN; |
249 | case 11: |
250 | return VECC::CC_NENAN; |
251 | case 12: |
252 | return VECC::CC_EQNAN; |
253 | case 13: |
254 | return VECC::CC_GENAN; |
255 | case 14: |
256 | return VECC::CC_LENAN; |
257 | case 15: |
258 | return VECC::CC_AT; |
259 | } |
260 | } |
261 | llvm_unreachable("Invalid cond code" ); |
262 | } |
263 | |
264 | inline static const char *VERDToString(VERD::RoundingMode R) { |
265 | switch (R) { |
266 | case VERD::RD_NONE: |
267 | return "" ; |
268 | case VERD::RD_RZ: |
269 | return ".rz" ; |
270 | case VERD::RD_RP: |
271 | return ".rp" ; |
272 | case VERD::RD_RM: |
273 | return ".rm" ; |
274 | case VERD::RD_RN: |
275 | return ".rn" ; |
276 | case VERD::RD_RA: |
277 | return ".ra" ; |
278 | default: |
279 | llvm_unreachable("Invalid branch predicate" ); |
280 | } |
281 | } |
282 | |
283 | inline static VERD::RoundingMode stringToVERD(StringRef S) { |
284 | return StringSwitch<VERD::RoundingMode>(S) |
285 | .Case(S: "" , Value: VERD::RD_NONE) |
286 | .Case(S: ".rz" , Value: VERD::RD_RZ) |
287 | .Case(S: ".rp" , Value: VERD::RD_RP) |
288 | .Case(S: ".rm" , Value: VERD::RD_RM) |
289 | .Case(S: ".rn" , Value: VERD::RD_RN) |
290 | .Case(S: ".ra" , Value: VERD::RD_RA) |
291 | .Default(Value: VERD::UNKNOWN); |
292 | } |
293 | |
294 | inline static unsigned VERDToVal(VERD::RoundingMode R) { |
295 | switch (R) { |
296 | case VERD::RD_NONE: |
297 | case VERD::RD_RZ: |
298 | case VERD::RD_RP: |
299 | case VERD::RD_RM: |
300 | case VERD::RD_RN: |
301 | case VERD::RD_RA: |
302 | return static_cast<unsigned>(R); |
303 | default: |
304 | break; |
305 | } |
306 | llvm_unreachable("Invalid branch predicates" ); |
307 | } |
308 | |
309 | inline static VERD::RoundingMode VEValToRD(unsigned Val) { |
310 | switch (Val) { |
311 | case static_cast<unsigned>(VERD::RD_NONE): |
312 | return VERD::RD_NONE; |
313 | case static_cast<unsigned>(VERD::RD_RZ): |
314 | return VERD::RD_RZ; |
315 | case static_cast<unsigned>(VERD::RD_RP): |
316 | return VERD::RD_RP; |
317 | case static_cast<unsigned>(VERD::RD_RM): |
318 | return VERD::RD_RM; |
319 | case static_cast<unsigned>(VERD::RD_RN): |
320 | return VERD::RD_RN; |
321 | case static_cast<unsigned>(VERD::RD_RA): |
322 | return VERD::RD_RA; |
323 | default: |
324 | break; |
325 | } |
326 | llvm_unreachable("Invalid branch predicates" ); |
327 | } |
328 | |
329 | // MImm - Special immediate value of sequential bit stream of 0 or 1. |
330 | // See VEInstrInfo.td for details. |
331 | inline static bool isMImmVal(uint64_t Val) { |
332 | if (Val == 0) { |
333 | // (0)1 is 0 |
334 | return true; |
335 | } |
336 | if (isMask_64(Value: Val)) { |
337 | // (m)0 patterns |
338 | return true; |
339 | } |
340 | // (m)1 patterns |
341 | return (Val & (UINT64_C(1) << 63)) && isShiftedMask_64(Value: Val); |
342 | } |
343 | |
344 | inline static bool isMImm32Val(uint32_t Val) { |
345 | if (Val == 0) { |
346 | // (0)1 is 0 |
347 | return true; |
348 | } |
349 | if (isMask_32(Value: Val)) { |
350 | // (m)0 patterns |
351 | return true; |
352 | } |
353 | // (m)1 patterns |
354 | return (Val & (UINT32_C(1) << 31)) && isShiftedMask_32(Value: Val); |
355 | } |
356 | |
357 | /// val2MImm - Convert an integer immediate value to target MImm immediate. |
358 | inline static uint64_t val2MImm(uint64_t Val) { |
359 | if (Val == 0) |
360 | return 0; // (0)1 |
361 | if (Val & (UINT64_C(1) << 63)) |
362 | return llvm::countl_one(Value: Val); // (m)1 |
363 | return llvm::countl_zero(Val) | 0x40; // (m)0 |
364 | } |
365 | |
366 | /// mimm2Val - Convert a target MImm immediate to an integer immediate value. |
367 | inline static uint64_t mimm2Val(uint64_t Val) { |
368 | if (Val == 0) |
369 | return 0; // (0)1 |
370 | if ((Val & 0x40) == 0) |
371 | return (uint64_t)((INT64_C(1) << 63) >> (Val & 0x3f)); // (m)1 |
372 | return ((uint64_t)INT64_C(-1) >> (Val & 0x3f)); // (m)0 |
373 | } |
374 | |
375 | inline unsigned M0(unsigned Val) { return Val + 64; } |
376 | inline unsigned M1(unsigned Val) { return Val; } |
377 | |
378 | static const unsigned StandardVectorWidth = 256; |
379 | static const unsigned PackedVectorWidth = 512; |
380 | |
381 | } // namespace llvm |
382 | #endif |
383 | |