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