LLVM 17.0.0git
ARMAddressingModes.h
Go to the documentation of this file.
1//===-- ARMAddressingModes.h - ARM Addressing Modes -------------*- 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 ARM addressing mode implementation stuff.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMADDRESSINGMODES_H
14#define LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMADDRESSINGMODES_H
15
16#include "llvm/ADT/APFloat.h"
17#include "llvm/ADT/APInt.h"
18#include "llvm/ADT/bit.h"
21#include <cassert>
22
23namespace llvm {
24
25/// ARM_AM - ARM Addressing Mode Stuff
26namespace ARM_AM {
27 enum ShiftOpc {
34 uxtw
35 };
36
37 enum AddrOpc {
38 sub = 0,
39 add
40 };
41
42 inline const char *getAddrOpcStr(AddrOpc Op) { return Op == sub ? "-" : ""; }
43
44 inline const char *getShiftOpcStr(ShiftOpc Op) {
45 switch (Op) {
46 default: llvm_unreachable("Unknown shift opc!");
47 case ARM_AM::asr: return "asr";
48 case ARM_AM::lsl: return "lsl";
49 case ARM_AM::lsr: return "lsr";
50 case ARM_AM::ror: return "ror";
51 case ARM_AM::rrx: return "rrx";
52 case ARM_AM::uxtw: return "uxtw";
53 }
54 }
55
56 inline unsigned getShiftOpcEncoding(ShiftOpc Op) {
57 switch (Op) {
58 default: llvm_unreachable("Unknown shift opc!");
59 case ARM_AM::asr: return 2;
60 case ARM_AM::lsl: return 0;
61 case ARM_AM::lsr: return 1;
62 case ARM_AM::ror: return 3;
63 }
64 }
65
66 enum AMSubMode {
71 db
72 };
73
74 inline const char *getAMSubModeStr(AMSubMode Mode) {
75 switch (Mode) {
76 default: llvm_unreachable("Unknown addressing sub-mode!");
77 case ARM_AM::ia: return "ia";
78 case ARM_AM::ib: return "ib";
79 case ARM_AM::da: return "da";
80 case ARM_AM::db: return "db";
81 }
82 }
83
84 /// rotr32 - Rotate a 32-bit unsigned value right by a specified # bits.
85 ///
86 inline unsigned rotr32(unsigned Val, unsigned Amt) {
87 assert(Amt < 32 && "Invalid rotate amount");
88 return (Val >> Amt) | (Val << ((32-Amt)&31));
89 }
90
91 /// rotl32 - Rotate a 32-bit unsigned value left by a specified # bits.
92 ///
93 inline unsigned rotl32(unsigned Val, unsigned Amt) {
94 assert(Amt < 32 && "Invalid rotate amount");
95 return (Val << Amt) | (Val >> ((32-Amt)&31));
96 }
97
98 //===--------------------------------------------------------------------===//
99 // Addressing Mode #1: shift_operand with registers
100 //===--------------------------------------------------------------------===//
101 //
102 // This 'addressing mode' is used for arithmetic instructions. It can
103 // represent things like:
104 // reg
105 // reg [asr|lsl|lsr|ror|rrx] reg
106 // reg [asr|lsl|lsr|ror|rrx] imm
107 //
108 // This is stored three operands [rega, regb, opc]. The first is the base
109 // reg, the second is the shift amount (or reg0 if not present or imm). The
110 // third operand encodes the shift opcode and the imm if a reg isn't present.
111 //
112 inline unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm) {
113 return ShOp | (Imm << 3);
114 }
115 inline unsigned getSORegOffset(unsigned Op) { return Op >> 3; }
116 inline ShiftOpc getSORegShOp(unsigned Op) { return (ShiftOpc)(Op & 7); }
117
118 /// getSOImmValImm - Given an encoded imm field for the reg/imm form, return
119 /// the 8-bit imm value.
120 inline unsigned getSOImmValImm(unsigned Imm) { return Imm & 0xFF; }
121 /// getSOImmValRot - Given an encoded imm field for the reg/imm form, return
122 /// the rotate amount.
123 inline unsigned getSOImmValRot(unsigned Imm) { return (Imm >> 8) * 2; }
124
125 /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand,
126 /// computing the rotate amount to use. If this immediate value cannot be
127 /// handled with a single shifter-op, determine a good rotate amount that will
128 /// take a maximal chunk of bits out of the immediate.
129 inline unsigned getSOImmValRotate(unsigned Imm) {
130 // 8-bit (or less) immediates are trivially shifter_operands with a rotate
131 // of zero.
132 if ((Imm & ~255U) == 0) return 0;
133
134 // Use CTZ to compute the rotate amount.
135 unsigned TZ = llvm::countr_zero(Imm);
136
137 // Rotate amount must be even. Something like 0x200 must be rotated 8 bits,
138 // not 9.
139 unsigned RotAmt = TZ & ~1;
140
141 // If we can handle this spread, return it.
142 if ((rotr32(Imm, RotAmt) & ~255U) == 0)
143 return (32-RotAmt)&31; // HW rotates right, not left.
144
145 // For values like 0xF000000F, we should ignore the low 6 bits, then
146 // retry the hunt.
147 if (Imm & 63U) {
148 unsigned TZ2 = llvm::countr_zero(Imm & ~63U);
149 unsigned RotAmt2 = TZ2 & ~1;
150 if ((rotr32(Imm, RotAmt2) & ~255U) == 0)
151 return (32-RotAmt2)&31; // HW rotates right, not left.
152 }
153
154 // Otherwise, we have no way to cover this span of bits with a single
155 // shifter_op immediate. Return a chunk of bits that will be useful to
156 // handle.
157 return (32-RotAmt)&31; // HW rotates right, not left.
158 }
159
160 /// getSOImmVal - Given a 32-bit immediate, if it is something that can fit
161 /// into an shifter_operand immediate operand, return the 12-bit encoding for
162 /// it. If not, return -1.
163 inline int getSOImmVal(unsigned Arg) {
164 // 8-bit (or less) immediates are trivially shifter_operands with a rotate
165 // of zero.
166 if ((Arg & ~255U) == 0) return Arg;
167
168 unsigned RotAmt = getSOImmValRotate(Arg);
169
170 // If this cannot be handled with a single shifter_op, bail out.
171 if (rotr32(~255U, RotAmt) & Arg)
172 return -1;
173
174 // Encode this correctly.
175 return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8);
176 }
177
178 /// isSOImmTwoPartVal - Return true if the specified value can be obtained by
179 /// or'ing together two SOImmVal's.
180 inline bool isSOImmTwoPartVal(unsigned V) {
181 // If this can be handled with a single shifter_op, bail out.
182 V = rotr32(~255U, getSOImmValRotate(V)) & V;
183 if (V == 0)
184 return false;
185
186 // If this can be handled with two shifter_op's, accept.
187 V = rotr32(~255U, getSOImmValRotate(V)) & V;
188 return V == 0;
189 }
190
191 /// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal,
192 /// return the first chunk of it.
193 inline unsigned getSOImmTwoPartFirst(unsigned V) {
194 return rotr32(255U, getSOImmValRotate(V)) & V;
195 }
196
197 /// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal,
198 /// return the second chunk of it.
199 inline unsigned getSOImmTwoPartSecond(unsigned V) {
200 // Mask out the first hunk.
201 V = rotr32(~255U, getSOImmValRotate(V)) & V;
202
203 // Take what's left.
204 assert(V == (rotr32(255U, getSOImmValRotate(V)) & V));
205 return V;
206 }
207
208 /// isSOImmTwoPartValNeg - Return true if the specified value can be obtained
209 /// by two SOImmVal, that -V = First + Second.
210 /// "R+V" can be optimized to (sub (sub R, First), Second).
211 /// "R=V" can be optimized to (sub (mvn R, ~(-First)), Second).
212 inline bool isSOImmTwoPartValNeg(unsigned V) {
213 unsigned First;
214 if (!isSOImmTwoPartVal(-V))
215 return false;
216 // Return false if ~(-First) is not a SoImmval.
217 First = getSOImmTwoPartFirst(-V);
218 First = ~(-First);
219 return !(rotr32(~255U, getSOImmValRotate(First)) & First);
220 }
221
222 /// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed
223 /// by a left shift. Returns the shift amount to use.
224 inline unsigned getThumbImmValShift(unsigned Imm) {
225 // 8-bit (or less) immediates are trivially immediate operand with a shift
226 // of zero.
227 if ((Imm & ~255U) == 0) return 0;
228
229 // Use CTZ to compute the shift amount.
230 return llvm::countr_zero(Imm);
231 }
232
233 /// isThumbImmShiftedVal - Return true if the specified value can be obtained
234 /// by left shifting a 8-bit immediate.
235 inline bool isThumbImmShiftedVal(unsigned V) {
236 // If this can be handled with
237 V = (~255U << getThumbImmValShift(V)) & V;
238 return V == 0;
239 }
240
241 /// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed
242 /// by a left shift. Returns the shift amount to use.
243 inline unsigned getThumbImm16ValShift(unsigned Imm) {
244 // 16-bit (or less) immediates are trivially immediate operand with a shift
245 // of zero.
246 if ((Imm & ~65535U) == 0) return 0;
247
248 // Use CTZ to compute the shift amount.
249 return llvm::countr_zero(Imm);
250 }
251
252 /// isThumbImm16ShiftedVal - Return true if the specified value can be
253 /// obtained by left shifting a 16-bit immediate.
254 inline bool isThumbImm16ShiftedVal(unsigned V) {
255 // If this can be handled with
256 V = (~65535U << getThumbImm16ValShift(V)) & V;
257 return V == 0;
258 }
259
260 /// getThumbImmNonShiftedVal - If V is a value that satisfies
261 /// isThumbImmShiftedVal, return the non-shiftd value.
262 inline unsigned getThumbImmNonShiftedVal(unsigned V) {
263 return V >> getThumbImmValShift(V);
264 }
265
266
267 /// getT2SOImmValSplat - Return the 12-bit encoded representation
268 /// if the specified value can be obtained by splatting the low 8 bits
269 /// into every other byte or every byte of a 32-bit value. i.e.,
270 /// 00000000 00000000 00000000 abcdefgh control = 0
271 /// 00000000 abcdefgh 00000000 abcdefgh control = 1
272 /// abcdefgh 00000000 abcdefgh 00000000 control = 2
273 /// abcdefgh abcdefgh abcdefgh abcdefgh control = 3
274 /// Return -1 if none of the above apply.
275 /// See ARM Reference Manual A6.3.2.
276 inline int getT2SOImmValSplatVal(unsigned V) {
277 unsigned u, Vs, Imm;
278 // control = 0
279 if ((V & 0xffffff00) == 0)
280 return V;
281
282 // If the value is zeroes in the first byte, just shift those off
283 Vs = ((V & 0xff) == 0) ? V >> 8 : V;
284 // Any passing value only has 8 bits of payload, splatted across the word
285 Imm = Vs & 0xff;
286 // Likewise, any passing values have the payload splatted into the 3rd byte
287 u = Imm | (Imm << 16);
288
289 // control = 1 or 2
290 if (Vs == u)
291 return (((Vs == V) ? 1 : 2) << 8) | Imm;
292
293 // control = 3
294 if (Vs == (u | (u << 8)))
295 return (3 << 8) | Imm;
296
297 return -1;
298 }
299
300 /// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the
301 /// specified value is a rotated 8-bit value. Return -1 if no rotation
302 /// encoding is possible.
303 /// See ARM Reference Manual A6.3.2.
304 inline int getT2SOImmValRotateVal(unsigned V) {
305 unsigned RotAmt = llvm::countl_zero(V);
306 if (RotAmt >= 24)
307 return -1;
308
309 // If 'Arg' can be handled with a single shifter_op return the value.
310 if ((rotr32(0xff000000U, RotAmt) & V) == V)
311 return (rotr32(V, 24 - RotAmt) & 0x7f) | ((RotAmt + 8) << 7);
312
313 return -1;
314 }
315
316 /// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit
317 /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit
318 /// encoding for it. If not, return -1.
319 /// See ARM Reference Manual A6.3.2.
320 inline int getT2SOImmVal(unsigned Arg) {
321 // If 'Arg' is an 8-bit splat, then get the encoded value.
322 int Splat = getT2SOImmValSplatVal(Arg);
323 if (Splat != -1)
324 return Splat;
325
326 // If 'Arg' can be handled with a single shifter_op return the value.
327 int Rot = getT2SOImmValRotateVal(Arg);
328 if (Rot != -1)
329 return Rot;
330
331 return -1;
332 }
333
334 inline unsigned getT2SOImmValRotate(unsigned V) {
335 if ((V & ~255U) == 0) return 0;
336 // Use CTZ to compute the rotate amount.
337 unsigned RotAmt = llvm::countr_zero(V);
338 return (32 - RotAmt) & 31;
339 }
340
341 inline bool isT2SOImmTwoPartVal(unsigned Imm) {
342 unsigned V = Imm;
343 // Passing values can be any combination of splat values and shifter
344 // values. If this can be handled with a single shifter or splat, bail
345 // out. Those should be handled directly, not with a two-part val.
346 if (getT2SOImmValSplatVal(V) != -1)
347 return false;
348 V = rotr32 (~255U, getT2SOImmValRotate(V)) & V;
349 if (V == 0)
350 return false;
351
352 // If this can be handled as an immediate, accept.
353 if (getT2SOImmVal(V) != -1) return true;
354
355 // Likewise, try masking out a splat value first.
356 V = Imm;
357 if (getT2SOImmValSplatVal(V & 0xff00ff00U) != -1)
358 V &= ~0xff00ff00U;
359 else if (getT2SOImmValSplatVal(V & 0x00ff00ffU) != -1)
360 V &= ~0x00ff00ffU;
361 // If what's left can be handled as an immediate, accept.
362 if (getT2SOImmVal(V) != -1) return true;
363
364 // Otherwise, do not accept.
365 return false;
366 }
367
368 inline unsigned getT2SOImmTwoPartFirst(unsigned Imm) {
370 "Immedate cannot be encoded as two part immediate!");
371 // Try a shifter operand as one part
372 unsigned V = rotr32 (~255, getT2SOImmValRotate(Imm)) & Imm;
373 // If the rest is encodable as an immediate, then return it.
374 if (getT2SOImmVal(V) != -1) return V;
375
376 // Try masking out a splat value first.
377 if (getT2SOImmValSplatVal(Imm & 0xff00ff00U) != -1)
378 return Imm & 0xff00ff00U;
379
380 // The other splat is all that's left as an option.
381 assert (getT2SOImmValSplatVal(Imm & 0x00ff00ffU) != -1);
382 return Imm & 0x00ff00ffU;
383 }
384
385 inline unsigned getT2SOImmTwoPartSecond(unsigned Imm) {
386 // Mask out the first hunk
387 Imm ^= getT2SOImmTwoPartFirst(Imm);
388 // Return what's left
389 assert (getT2SOImmVal(Imm) != -1 &&
390 "Unable to encode second part of T2 two part SO immediate");
391 return Imm;
392 }
393
394
395 //===--------------------------------------------------------------------===//
396 // Addressing Mode #2
397 //===--------------------------------------------------------------------===//
398 //
399 // This is used for most simple load/store instructions.
400 //
401 // addrmode2 := reg +/- reg shop imm
402 // addrmode2 := reg +/- imm12
403 //
404 // The first operand is always a Reg. The second operand is a reg if in
405 // reg/reg form, otherwise it's reg#0. The third field encodes the operation
406 // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The
407 // fourth operand 16-17 encodes the index mode.
408 //
409 // If this addressing mode is a frame index (before prolog/epilog insertion
410 // and code rewriting), this operand will have the form: FI#, reg0, <offs>
411 // with no shift amount for the frame offset.
412 //
413 inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO,
414 unsigned IdxMode = 0) {
415 assert(Imm12 < (1 << 12) && "Imm too large!");
416 bool isSub = Opc == sub;
417 return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16) ;
418 }
419 inline unsigned getAM2Offset(unsigned AM2Opc) {
420 return AM2Opc & ((1 << 12)-1);
421 }
422 inline AddrOpc getAM2Op(unsigned AM2Opc) {
423 return ((AM2Opc >> 12) & 1) ? sub : add;
424 }
425 inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) {
426 return (ShiftOpc)((AM2Opc >> 13) & 7);
427 }
428 inline unsigned getAM2IdxMode(unsigned AM2Opc) { return (AM2Opc >> 16); }
429
430 //===--------------------------------------------------------------------===//
431 // Addressing Mode #3
432 //===--------------------------------------------------------------------===//
433 //
434 // This is used for sign-extending loads, and load/store-pair instructions.
435 //
436 // addrmode3 := reg +/- reg
437 // addrmode3 := reg +/- imm8
438 //
439 // The first operand is always a Reg. The second operand is a reg if in
440 // reg/reg form, otherwise it's reg#0. The third field encodes the operation
441 // in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the
442 // index mode.
443
444 /// getAM3Opc - This function encodes the addrmode3 opc field.
445 inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset,
446 unsigned IdxMode = 0) {
447 bool isSub = Opc == sub;
448 return ((int)isSub << 8) | Offset | (IdxMode << 9);
449 }
450 inline unsigned char getAM3Offset(unsigned AM3Opc) { return AM3Opc & 0xFF; }
451 inline AddrOpc getAM3Op(unsigned AM3Opc) {
452 return ((AM3Opc >> 8) & 1) ? sub : add;
453 }
454 inline unsigned getAM3IdxMode(unsigned AM3Opc) { return (AM3Opc >> 9); }
455
456 //===--------------------------------------------------------------------===//
457 // Addressing Mode #4
458 //===--------------------------------------------------------------------===//
459 //
460 // This is used for load / store multiple instructions.
461 //
462 // addrmode4 := reg, <mode>
463 //
464 // The four modes are:
465 // IA - Increment after
466 // IB - Increment before
467 // DA - Decrement after
468 // DB - Decrement before
469 // For VFP instructions, only the IA and DB modes are valid.
470
471 inline AMSubMode getAM4SubMode(unsigned Mode) {
472 return (AMSubMode)(Mode & 0x7);
473 }
474
475 inline unsigned getAM4ModeImm(AMSubMode SubMode) { return (int)SubMode; }
476
477 //===--------------------------------------------------------------------===//
478 // Addressing Mode #5
479 //===--------------------------------------------------------------------===//
480 //
481 // This is used for coprocessor instructions, such as FP load/stores.
482 //
483 // addrmode5 := reg +/- imm8*4
484 //
485 // The first operand is always a Reg. The second operand encodes the
486 // operation (add or subtract) in bit 8 and the immediate in bits 0-7.
487
488 /// getAM5Opc - This function encodes the addrmode5 opc field.
489 inline unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset) {
490 bool isSub = Opc == sub;
491 return ((int)isSub << 8) | Offset;
492 }
493 inline unsigned char getAM5Offset(unsigned AM5Opc) { return AM5Opc & 0xFF; }
494 inline AddrOpc getAM5Op(unsigned AM5Opc) {
495 return ((AM5Opc >> 8) & 1) ? sub : add;
496 }
497
498 //===--------------------------------------------------------------------===//
499 // Addressing Mode #5 FP16
500 //===--------------------------------------------------------------------===//
501 //
502 // This is used for coprocessor instructions, such as 16-bit FP load/stores.
503 //
504 // addrmode5fp16 := reg +/- imm8*2
505 //
506 // The first operand is always a Reg. The second operand encodes the
507 // operation (add or subtract) in bit 8 and the immediate in bits 0-7.
508
509 /// getAM5FP16Opc - This function encodes the addrmode5fp16 opc field.
510 inline unsigned getAM5FP16Opc(AddrOpc Opc, unsigned char Offset) {
511 bool isSub = Opc == sub;
512 return ((int)isSub << 8) | Offset;
513 }
514 inline unsigned char getAM5FP16Offset(unsigned AM5Opc) {
515 return AM5Opc & 0xFF;
516 }
517 inline AddrOpc getAM5FP16Op(unsigned AM5Opc) {
518 return ((AM5Opc >> 8) & 1) ? sub : add;
519 }
520
521 //===--------------------------------------------------------------------===//
522 // Addressing Mode #6
523 //===--------------------------------------------------------------------===//
524 //
525 // This is used for NEON load / store instructions.
526 //
527 // addrmode6 := reg with optional alignment
528 //
529 // This is stored in two operands [regaddr, align]. The first is the
530 // address register. The second operand is the value of the alignment
531 // specifier in bytes or zero if no explicit alignment.
532 // Valid alignments depend on the specific instruction.
533
534 //===--------------------------------------------------------------------===//
535 // NEON/MVE Modified Immediates
536 //===--------------------------------------------------------------------===//
537 //
538 // Several NEON and MVE instructions (e.g., VMOV) take a "modified immediate"
539 // vector operand, where a small immediate encoded in the instruction
540 // specifies a full NEON vector value. These modified immediates are
541 // represented here as encoded integers. The low 8 bits hold the immediate
542 // value; bit 12 holds the "Op" field of the instruction, and bits 11-8 hold
543 // the "Cmode" field of the instruction. The interfaces below treat the
544 // Op and Cmode values as a single 5-bit value.
545
546 inline unsigned createVMOVModImm(unsigned OpCmode, unsigned Val) {
547 return (OpCmode << 8) | Val;
548 }
549 inline unsigned getVMOVModImmOpCmode(unsigned ModImm) {
550 return (ModImm >> 8) & 0x1f;
551 }
552 inline unsigned getVMOVModImmVal(unsigned ModImm) { return ModImm & 0xff; }
553
554 /// decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the
555 /// element value and the element size in bits. (If the element size is
556 /// smaller than the vector, it is splatted into all the elements.)
557 inline uint64_t decodeVMOVModImm(unsigned ModImm, unsigned &EltBits) {
558 unsigned OpCmode = getVMOVModImmOpCmode(ModImm);
559 unsigned Imm8 = getVMOVModImmVal(ModImm);
560 uint64_t Val = 0;
561
562 if (OpCmode == 0xe) {
563 // 8-bit vector elements
564 Val = Imm8;
565 EltBits = 8;
566 } else if ((OpCmode & 0xc) == 0x8) {
567 // 16-bit vector elements
568 unsigned ByteNum = (OpCmode & 0x6) >> 1;
569 Val = Imm8 << (8 * ByteNum);
570 EltBits = 16;
571 } else if ((OpCmode & 0x8) == 0) {
572 // 32-bit vector elements, zero with one byte set
573 unsigned ByteNum = (OpCmode & 0x6) >> 1;
574 Val = Imm8 << (8 * ByteNum);
575 EltBits = 32;
576 } else if ((OpCmode & 0xe) == 0xc) {
577 // 32-bit vector elements, one byte with low bits set
578 unsigned ByteNum = 1 + (OpCmode & 0x1);
579 Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum)));
580 EltBits = 32;
581 } else if (OpCmode == 0x1e) {
582 // 64-bit vector elements
583 for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) {
584 if ((ModImm >> ByteNum) & 1)
585 Val |= (uint64_t)0xff << (8 * ByteNum);
586 }
587 EltBits = 64;
588 } else {
589 llvm_unreachable("Unsupported VMOV immediate");
590 }
591 return Val;
592 }
593
594 // Generic validation for single-byte immediate (0X00, 00X0, etc).
595 inline bool isNEONBytesplat(unsigned Value, unsigned Size) {
596 assert(Size >= 1 && Size <= 4 && "Invalid size");
597 unsigned count = 0;
598 for (unsigned i = 0; i < Size; ++i) {
599 if (Value & 0xff) count++;
600 Value >>= 8;
601 }
602 return count == 1;
603 }
604
605 /// Checks if Value is a correct immediate for instructions like VBIC/VORR.
606 inline bool isNEONi16splat(unsigned Value) {
607 if (Value > 0xffff)
608 return false;
609 // i16 value with set bits only in one byte X0 or 0X.
610 return Value == 0 || isNEONBytesplat(Value, 2);
611 }
612
613 // Encode NEON 16 bits Splat immediate for instructions like VBIC/VORR
614 inline unsigned encodeNEONi16splat(unsigned Value) {
615 assert(isNEONi16splat(Value) && "Invalid NEON splat value");
616 if (Value >= 0x100)
617 Value = (Value >> 8) | 0xa00;
618 else
619 Value |= 0x800;
620 return Value;
621 }
622
623 /// Checks if Value is a correct immediate for instructions like VBIC/VORR.
624 inline bool isNEONi32splat(unsigned Value) {
625 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
626 return Value == 0 || isNEONBytesplat(Value, 4);
627 }
628
629 /// Encode NEON 32 bits Splat immediate for instructions like VBIC/VORR.
630 inline unsigned encodeNEONi32splat(unsigned Value) {
631 assert(isNEONi32splat(Value) && "Invalid NEON splat value");
632 if (Value >= 0x100 && Value <= 0xff00)
633 Value = (Value >> 8) | 0x200;
634 else if (Value > 0xffff && Value <= 0xff0000)
635 Value = (Value >> 16) | 0x400;
636 else if (Value > 0xffffff)
637 Value = (Value >> 24) | 0x600;
638 return Value;
639 }
640
641 //===--------------------------------------------------------------------===//
642 // Floating-point Immediates
643 //
644 inline float getFPImmFloat(unsigned Imm) {
645 // We expect an 8-bit binary encoding of a floating-point number here.
646
647 uint8_t Sign = (Imm >> 7) & 0x1;
648 uint8_t Exp = (Imm >> 4) & 0x7;
649 uint8_t Mantissa = Imm & 0xf;
650
651 // 8-bit FP IEEE Float Encoding
652 // abcd efgh aBbbbbbc defgh000 00000000 00000000
653 //
654 // where B = NOT(b);
655 uint32_t I = 0;
656 I |= Sign << 31;
657 I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
658 I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
659 I |= (Exp & 0x3) << 23;
660 I |= Mantissa << 19;
661 return bit_cast<float>(I);
662 }
663
664 /// getFP16Imm - Return an 8-bit floating-point version of the 16-bit
665 /// floating-point value. If the value cannot be represented as an 8-bit
666 /// floating-point value, then return -1.
667 inline int getFP16Imm(const APInt &Imm) {
668 uint32_t Sign = Imm.lshr(15).getZExtValue() & 1;
669 int32_t Exp = (Imm.lshr(10).getSExtValue() & 0x1f) - 15; // -14 to 15
670 int64_t Mantissa = Imm.getZExtValue() & 0x3ff; // 10 bits
671
672 // We can handle 4 bits of mantissa.
673 // mantissa = (16+UInt(e:f:g:h))/16.
674 if (Mantissa & 0x3f)
675 return -1;
676 Mantissa >>= 6;
677
678 // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3
679 if (Exp < -3 || Exp > 4)
680 return -1;
681 Exp = ((Exp+3) & 0x7) ^ 4;
682
683 return ((int)Sign << 7) | (Exp << 4) | Mantissa;
684 }
685
686 inline int getFP16Imm(const APFloat &FPImm) {
687 return getFP16Imm(FPImm.bitcastToAPInt());
688 }
689
690 /// If this is a FP16Imm encoded as a fp32 value, return the 8-bit encoding
691 /// for it. Otherwise return -1 like getFP16Imm.
692 inline int getFP32FP16Imm(const APInt &Imm) {
693 if (Imm.getActiveBits() > 16)
694 return -1;
695 return ARM_AM::getFP16Imm(Imm.trunc(16));
696 }
697
698 inline int getFP32FP16Imm(const APFloat &FPImm) {
699 return getFP32FP16Imm(FPImm.bitcastToAPInt());
700 }
701
702 /// getFP32Imm - Return an 8-bit floating-point version of the 32-bit
703 /// floating-point value. If the value cannot be represented as an 8-bit
704 /// floating-point value, then return -1.
705 inline int getFP32Imm(const APInt &Imm) {
706 uint32_t Sign = Imm.lshr(31).getZExtValue() & 1;
707 int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127; // -126 to 127
708 int64_t Mantissa = Imm.getZExtValue() & 0x7fffff; // 23 bits
709
710 // We can handle 4 bits of mantissa.
711 // mantissa = (16+UInt(e:f:g:h))/16.
712 if (Mantissa & 0x7ffff)
713 return -1;
714 Mantissa >>= 19;
715 if ((Mantissa & 0xf) != Mantissa)
716 return -1;
717
718 // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3
719 if (Exp < -3 || Exp > 4)
720 return -1;
721 Exp = ((Exp+3) & 0x7) ^ 4;
722
723 return ((int)Sign << 7) | (Exp << 4) | Mantissa;
724 }
725
726 inline int getFP32Imm(const APFloat &FPImm) {
727 return getFP32Imm(FPImm.bitcastToAPInt());
728 }
729
730 /// getFP64Imm - Return an 8-bit floating-point version of the 64-bit
731 /// floating-point value. If the value cannot be represented as an 8-bit
732 /// floating-point value, then return -1.
733 inline int getFP64Imm(const APInt &Imm) {
734 uint64_t Sign = Imm.lshr(63).getZExtValue() & 1;
735 int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023; // -1022 to 1023
736 uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffULL;
737
738 // We can handle 4 bits of mantissa.
739 // mantissa = (16+UInt(e:f:g:h))/16.
740 if (Mantissa & 0xffffffffffffULL)
741 return -1;
742 Mantissa >>= 48;
743 if ((Mantissa & 0xf) != Mantissa)
744 return -1;
745
746 // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3
747 if (Exp < -3 || Exp > 4)
748 return -1;
749 Exp = ((Exp+3) & 0x7) ^ 4;
750
751 return ((int)Sign << 7) | (Exp << 4) | Mantissa;
752 }
753
754 inline int getFP64Imm(const APFloat &FPImm) {
755 return getFP64Imm(FPImm.bitcastToAPInt());
756 }
757
758} // end namespace ARM_AM
759} // end namespace llvm
760
761#endif
762
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
uint64_t Size
#define I(x, y, z)
Definition: MD5.cpp:58
static cl::opt< RegAllocEvictionAdvisorAnalysis::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Development, "development", "for training")))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements the C++20 <bit> header.
APInt bitcastToAPInt() const
Definition: APFloat.h:1145
Class for arbitrary precision integers.
Definition: APInt.h:75
LLVM Value Representation.
Definition: Value.h:74
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned char getAM3Offset(unsigned AM3Opc)
unsigned char getAM5FP16Offset(unsigned AM5Opc)
unsigned getSORegOffset(unsigned Op)
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
ShiftOpc getAM2ShiftOpc(unsigned AM2Opc)
int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
uint64_t decodeVMOVModImm(unsigned ModImm, unsigned &EltBits)
decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the element value and the element ...
unsigned getAM2IdxMode(unsigned AM2Opc)
unsigned getT2SOImmValRotate(unsigned V)
unsigned encodeNEONi16splat(unsigned Value)
unsigned getAM3IdxMode(unsigned AM3Opc)
unsigned getAM2Offset(unsigned AM2Opc)
unsigned getThumbImmNonShiftedVal(unsigned V)
getThumbImmNonShiftedVal - If V is a value that satisfies isThumbImmShiftedVal, return the non-shiftd...
unsigned getSOImmValRotate(unsigned Imm)
getSOImmValRotate - Try to handle Imm with an immediate shifter operand, computing the rotate amount ...
bool isThumbImmShiftedVal(unsigned V)
isThumbImmShiftedVal - Return true if the specified value can be obtained by left shifting a 8-bit im...
unsigned rotr32(unsigned Val, unsigned Amt)
rotr32 - Rotate a 32-bit unsigned value right by a specified # bits.
const char * getAMSubModeStr(AMSubMode Mode)
unsigned getVMOVModImmVal(unsigned ModImm)
float getFPImmFloat(unsigned Imm)
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, unsigned IdxMode=0)
int getT2SOImmValRotateVal(unsigned V)
getT2SOImmValRotateVal - Return the 12-bit encoded representation if the specified value is a rotated...
unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset)
getAM5Opc - This function encodes the addrmode5 opc field.
unsigned getSOImmValRot(unsigned Imm)
getSOImmValRot - Given an encoded imm field for the reg/imm form, return the rotate amount.
ShiftOpc getSORegShOp(unsigned Op)
AddrOpc getAM5Op(unsigned AM5Opc)
unsigned createVMOVModImm(unsigned OpCmode, unsigned Val)
int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
bool isNEONi16splat(unsigned Value)
Checks if Value is a correct immediate for instructions like VBIC/VORR.
bool isSOImmTwoPartValNeg(unsigned V)
isSOImmTwoPartValNeg - Return true if the specified value can be obtained by two SOImmVal,...
unsigned getSOImmTwoPartSecond(unsigned V)
getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, return the second chunk of ...
unsigned getVMOVModImmOpCmode(unsigned ModImm)
unsigned getAM5FP16Opc(AddrOpc Opc, unsigned char Offset)
getAM5FP16Opc - This function encodes the addrmode5fp16 opc field.
bool isSOImmTwoPartVal(unsigned V)
isSOImmTwoPartVal - Return true if the specified value can be obtained by or'ing together two SOImmVa...
unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset, unsigned IdxMode=0)
getAM3Opc - This function encodes the addrmode3 opc field.
AddrOpc getAM5FP16Op(unsigned AM5Opc)
unsigned getAM4ModeImm(AMSubMode SubMode)
unsigned getThumbImm16ValShift(unsigned Imm)
getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed by a left shift.
bool isNEONi32splat(unsigned Value)
Checks if Value is a correct immediate for instructions like VBIC/VORR.
int getFP16Imm(const APInt &Imm)
getFP16Imm - Return an 8-bit floating-point version of the 16-bit floating-point value.
unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
unsigned rotl32(unsigned Val, unsigned Amt)
rotl32 - Rotate a 32-bit unsigned value left by a specified # bits.
unsigned getShiftOpcEncoding(ShiftOpc Op)
unsigned getT2SOImmTwoPartSecond(unsigned Imm)
int getT2SOImmValSplatVal(unsigned V)
getT2SOImmValSplat - Return the 12-bit encoded representation if the specified value can be obtained ...
const char * getAddrOpcStr(AddrOpc Op)
const char * getShiftOpcStr(ShiftOpc Op)
int getFP32FP16Imm(const APInt &Imm)
If this is a FP16Imm encoded as a fp32 value, return the 8-bit encoding for it.
unsigned getSOImmValImm(unsigned Imm)
getSOImmValImm - Given an encoded imm field for the reg/imm form, return the 8-bit imm value.
unsigned getT2SOImmTwoPartFirst(unsigned Imm)
unsigned encodeNEONi32splat(unsigned Value)
Encode NEON 32 bits Splat immediate for instructions like VBIC/VORR.
bool isT2SOImmTwoPartVal(unsigned Imm)
bool isNEONBytesplat(unsigned Value, unsigned Size)
unsigned char getAM5Offset(unsigned AM5Opc)
unsigned getSOImmTwoPartFirst(unsigned V)
getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, return the first chunk of it...
AddrOpc getAM2Op(unsigned AM2Opc)
AddrOpc getAM3Op(unsigned AM3Opc)
AMSubMode getAM4SubMode(unsigned Mode)
unsigned getThumbImmValShift(unsigned Imm)
getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed by a left shift.
bool isThumbImm16ShiftedVal(unsigned V)
isThumbImm16ShiftedVal - Return true if the specified value can be obtained by left shifting a 16-bit...
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:406
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition: bit.h:179
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
Definition: bit.h:245
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition: STLExtras.h:1896