LLVM 24.0.0git
AMDGPUAsmParser.cpp
Go to the documentation of this file.
1//===- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ----------===//
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#include "AMDKernelCodeT.h"
16#include "SIDefines.h"
17#include "SIInstrInfo.h"
22#include "llvm/ADT/APFloat.h"
24#include "llvm/ADT/Twine.h"
27#include "llvm/MC/MCAsmInfo.h"
28#include "llvm/MC/MCContext.h"
29#include "llvm/MC/MCExpr.h"
30#include "llvm/MC/MCInst.h"
31#include "llvm/MC/MCInstrDesc.h"
37#include "llvm/MC/MCSymbol.h"
46#include <optional>
47
48using namespace llvm;
49using namespace llvm::AMDGPU;
50using namespace llvm::amdhsa;
51
52namespace {
53
54class AMDGPUAsmParser;
55
56enum RegisterKind {
57 IS_UNKNOWN,
58 IS_VGPR,
59 IS_SGPR,
60 IS_AGPR,
61 IS_TTMP,
62 IS_SPECIAL
63};
64
65//===----------------------------------------------------------------------===//
66// Operand
67//===----------------------------------------------------------------------===//
68
69class AMDGPUOperand : public MCParsedAsmOperand {
70 enum KindTy { Token, Immediate, Register, Expression } Kind;
71
72 SMLoc StartLoc, EndLoc;
73 const AMDGPUAsmParser *AsmParser;
74
75public:
76 AMDGPUOperand(KindTy Kind_, const AMDGPUAsmParser *AsmParser_)
77 : Kind(Kind_), AsmParser(AsmParser_) {}
78
79 using Ptr = std::unique_ptr<AMDGPUOperand>;
80
81 struct Modifiers {
82 bool Abs = false;
83 bool Neg = false;
84 bool Sext = false;
85 LitModifier Lit = LitModifier::None;
86
87 bool hasFPModifiers() const { return Abs || Neg; }
88 bool hasIntModifiers() const { return Sext; }
89 bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); }
90 bool isForcedLit() const { return Lit == LitModifier::Lit; }
91 bool isForcedLit64() const { return Lit == LitModifier::Lit64; }
92
93 int64_t getFPModifiersOperand() const {
94 int64_t Operand = 0;
95 Operand |= Abs ? SISrcMods::ABS : 0u;
96 Operand |= Neg ? SISrcMods::NEG : 0u;
97 return Operand;
98 }
99
100 int64_t getIntModifiersOperand() const {
101 int64_t Operand = 0;
102 Operand |= Sext ? SISrcMods::SEXT : 0u;
103 return Operand;
104 }
105
106 int64_t getModifiersOperand() const {
107 assert(!(hasFPModifiers() && hasIntModifiers()) &&
108 "fp and int modifiers should not be used simultaneously");
109 if (hasFPModifiers())
110 return getFPModifiersOperand();
111 if (hasIntModifiers())
112 return getIntModifiersOperand();
113 return 0;
114 }
115
116 friend raw_ostream &operator<<(raw_ostream &OS,
117 AMDGPUOperand::Modifiers Mods);
118 };
119
120 enum ImmTy {
121 ImmTyNone,
122 ImmTyGDS,
123 ImmTyLDS,
124 ImmTyOffen,
125 ImmTyIdxen,
126 ImmTyAddr64,
127 ImmTyOffset,
128 ImmTyInstOffset,
129 ImmTyOffset0,
130 ImmTyOffset1,
131 ImmTySMEMOffsetMod,
132 ImmTyCPol,
133 ImmTyTFE,
134 ImmTyIsAsync,
135 ImmTyD16,
136 ImmTyClamp,
137 ImmTyOModSI,
138 ImmTySDWADstSel,
139 ImmTySDWASrc0Sel,
140 ImmTySDWASrc1Sel,
141 ImmTySDWADstUnused,
142 ImmTyDMask,
143 ImmTyDim,
144 ImmTyUNorm,
145 ImmTyDA,
146 ImmTyR128A16,
147 ImmTyA16,
148 ImmTyLWE,
149 ImmTyExpTgt,
150 ImmTyExpCompr,
151 ImmTyExpVM,
152 ImmTyDone,
153 ImmTyRowEn,
154 ImmTyFORMAT,
155 ImmTyHwreg,
156 ImmTyOff,
157 ImmTySendMsg,
158 ImmTyWaitEvent,
159 ImmTyInterpSlot,
160 ImmTyInterpAttr,
161 ImmTyInterpAttrChan,
162 ImmTyOpSel,
163 ImmTyOpSelHi,
164 ImmTyNegLo,
165 ImmTyNegHi,
166 ImmTyIndexKey8bit,
167 ImmTyIndexKey16bit,
168 ImmTyIndexKey32bit,
169 ImmTyDPP8,
170 ImmTyDppCtrl,
171 ImmTyDppRowMask,
172 ImmTyDppBankMask,
173 ImmTyDppBoundCtrl,
174 ImmTyDppFI,
175 ImmTySwizzle,
176 ImmTyGprIdxMode,
177 ImmTyHigh,
178 ImmTyBLGP,
179 ImmTyCBSZ,
180 ImmTyABID,
181 ImmTyEndpgm,
182 ImmTyWaitVDST,
183 ImmTyWaitEXP,
184 ImmTyWaitVAVDst,
185 ImmTyWaitVMVSrc,
186 ImmTyBitOp3,
187 ImmTyMatrixAFMT,
188 ImmTyMatrixBFMT,
189 ImmTyMatrixAScale,
190 ImmTyMatrixBScale,
191 ImmTyMatrixAScaleFmt,
192 ImmTyMatrixBScaleFmt,
193 ImmTyMatrixAReuse,
194 ImmTyMatrixBReuse,
195 ImmTyScaleSel,
196 ImmTyByteSel,
197 };
198
199private:
200 struct TokOp {
201 const char *Data;
202 unsigned Length;
203 };
204
205 struct ImmOp {
206 int64_t Val;
207 ImmTy Type;
208 bool IsFPImm;
209 Modifiers Mods;
210 };
211
212 struct RegOp {
213 MCRegister RegNo;
214 Modifiers Mods;
215 };
216
217 union {
218 TokOp Tok;
219 ImmOp Imm;
220 RegOp Reg;
221 const MCExpr *Expr;
222 };
223
224 // The index of the associated MCInst operand.
225 mutable int MCOpIdx = -1;
226
227public:
228 bool isToken() const override { return Kind == Token; }
229
230 bool isSymbolRefExpr() const {
231 return isExpr() && Expr && isa<MCSymbolRefExpr>(Expr);
232 }
233
234 bool isImm() const override { return Kind == Immediate; }
235
236 bool isInlinableImm(MVT type) const;
237 bool isLiteralImm(MVT type) const;
238
239 bool isRegKind() const { return Kind == Register; }
240
241 bool isReg() const override { return isRegKind() && !hasModifiers(); }
242
243 bool isRegOrInline(unsigned RCID, MVT type) const {
244 return isRegClass(RCID) || isInlinableImm(type);
245 }
246
247 bool isRegOrImmWithInputMods(unsigned RCID, MVT type) const {
248 return isRegOrInline(RCID, type) || isLiteralImm(type);
249 }
250
251 bool isRegOrImmWithInt16InputMods() const {
252 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::i16);
253 }
254
255 template <bool IsFake16> bool isRegOrImmWithIntT16InputMods() const {
257 IsFake16 ? AMDGPU::VS_32RegClassID : AMDGPU::VS_16RegClassID, MVT::i16);
258 }
259
260 bool isRegOrImmWithInt32InputMods() const {
261 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::i32);
262 }
263
264 bool isRegOrInlineImmWithInt16InputMods() const {
265 return isRegOrInline(AMDGPU::VS_32RegClassID, MVT::i16);
266 }
267
268 template <bool IsFake16> bool isRegOrInlineImmWithIntT16InputMods() const {
269 return isRegOrInline(
270 IsFake16 ? AMDGPU::VS_32RegClassID : AMDGPU::VS_16RegClassID, MVT::i16);
271 }
272
273 bool isRegOrInlineImmWithInt32InputMods() const {
274 return isRegOrInline(AMDGPU::VS_32RegClassID, MVT::i32);
275 }
276
277 bool isRegOrImmWithInt64InputMods() const {
278 return isRegOrImmWithInputMods(AMDGPU::VS_64RegClassID, MVT::i64);
279 }
280
281 bool isRegOrImmWithFP16InputMods() const {
282 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::f16);
283 }
284
285 template <bool IsFake16> bool isRegOrImmWithFPT16InputMods() const {
287 IsFake16 ? AMDGPU::VS_32RegClassID : AMDGPU::VS_16RegClassID, MVT::f16);
288 }
289
290 bool isRegOrImmWithFP32InputMods() const {
291 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::f32);
292 }
293
294 bool isRegOrImmWithFP64InputMods() const {
295 return isRegOrImmWithInputMods(AMDGPU::VS_64RegClassID, MVT::f64);
296 }
297
298 template <bool IsFake16> bool isRegOrInlineImmWithFP16InputMods() const {
299 return isRegOrInline(
300 IsFake16 ? AMDGPU::VS_32RegClassID : AMDGPU::VS_16RegClassID, MVT::f16);
301 }
302
303 bool isRegOrInlineImmWithFP32InputMods() const {
304 return isRegOrInline(AMDGPU::VS_32RegClassID, MVT::f32);
305 }
306
307 bool isRegOrInlineImmWithFP64InputMods() const {
308 return isRegOrInline(AMDGPU::VS_64RegClassID, MVT::f64);
309 }
310
311 bool isVRegWithInputMods(unsigned RCID) const { return isRegClass(RCID); }
312
313 bool isVRegWithFP32InputMods() const {
314 return isVRegWithInputMods(AMDGPU::VGPR_32RegClassID);
315 }
316
317 bool isVRegWithFP64InputMods() const {
318 return isVRegWithInputMods(AMDGPU::VReg_64RegClassID);
319 }
320
321 bool isPackedFP16InputMods() const {
322 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::v2f16);
323 }
324
325 bool isPackedVGPRFP32InputMods() const {
326 return isRegOrImmWithInputMods(AMDGPU::VReg_64RegClassID, MVT::v2f32);
327 }
328
329 bool isVReg() const {
330 return isRegClass(AMDGPU::VGPR_32RegClassID) ||
331 isRegClass(AMDGPU::VReg_64RegClassID) ||
332 isRegClass(AMDGPU::VReg_96RegClassID) ||
333 isRegClass(AMDGPU::VReg_128RegClassID) ||
334 isRegClass(AMDGPU::VReg_160RegClassID) ||
335 isRegClass(AMDGPU::VReg_192RegClassID) ||
336 isRegClass(AMDGPU::VReg_256RegClassID) ||
337 isRegClass(AMDGPU::VReg_512RegClassID) ||
338 isRegClass(AMDGPU::VReg_1024RegClassID);
339 }
340
341 bool isVReg32() const { return isRegClass(AMDGPU::VGPR_32RegClassID); }
342
343 bool isVReg32OrOff() const { return isOff() || isVReg32(); }
344
345 bool isRsrcReg32() const { return isRegClass(AMDGPU::RsrcReg32RegClassID); }
346
347 bool isNull() const { return isRegKind() && getReg() == AMDGPU::SGPR_NULL; }
348
349 bool isAV_LdSt_32_Align2_RegOp() const {
350 return isRegClass(AMDGPU::VGPR_32RegClassID) ||
351 isRegClass(AMDGPU::AGPR_32RegClassID);
352 }
353
354 bool isVRegWithInputMods() const;
355 template <bool IsFake16> bool isT16_Lo128VRegWithInputMods() const;
356 template <bool IsFake16> bool isT16VRegWithInputMods() const;
357
358 bool isSDWAOperand(MVT type) const;
359 bool isSDWAFP16Operand() const;
360 bool isSDWAFP32Operand() const;
361 bool isSDWAInt16Operand() const;
362 bool isSDWAInt32Operand() const;
363
364 bool isImmTy(ImmTy ImmT) const { return isImm() && Imm.Type == ImmT; }
365
366 template <ImmTy Ty> bool isImmTy() const { return isImmTy(Ty); }
367
368 bool isImmLiteral() const { return isImmTy(ImmTyNone); }
369
370 bool isImmModifier() const { return isImm() && Imm.Type != ImmTyNone; }
371
372 bool isOModSI() const { return isImmTy(ImmTyOModSI); }
373 bool isDim() const { return isImmTy(ImmTyDim); }
374 bool isR128A16() const { return isImmTy(ImmTyR128A16); }
375 bool isOff() const { return isImmTy(ImmTyOff); }
376 bool isExpTgt() const { return isImmTy(ImmTyExpTgt); }
377 bool isOffen() const { return isImmTy(ImmTyOffen); }
378 bool isIdxen() const { return isImmTy(ImmTyIdxen); }
379 bool isAddr64() const { return isImmTy(ImmTyAddr64); }
380 bool isSMEMOffsetMod() const { return isImmTy(ImmTySMEMOffsetMod); }
381 bool isFlatOffset() const {
382 return isImmTy(ImmTyOffset) || isImmTy(ImmTyInstOffset);
383 }
384 bool isGDS() const { return isImmTy(ImmTyGDS); }
385 bool isLDS() const { return isImmTy(ImmTyLDS); }
386 bool isCPol() const { return isImmTy(ImmTyCPol); }
387 bool isIndexKey8bit() const { return isImmTy(ImmTyIndexKey8bit); }
388 bool isIndexKey16bit() const { return isImmTy(ImmTyIndexKey16bit); }
389 bool isIndexKey32bit() const { return isImmTy(ImmTyIndexKey32bit); }
390 bool isMatrixAFMT() const { return isImmTy(ImmTyMatrixAFMT); }
391 bool isMatrixBFMT() const { return isImmTy(ImmTyMatrixBFMT); }
392 bool isMatrixAScale() const { return isImmTy(ImmTyMatrixAScale); }
393 bool isMatrixBScale() const { return isImmTy(ImmTyMatrixBScale); }
394 bool isMatrixAScaleFmt() const { return isImmTy(ImmTyMatrixAScaleFmt); }
395 bool isMatrixBScaleFmt() const { return isImmTy(ImmTyMatrixBScaleFmt); }
396 bool isMatrixAReuse() const { return isImmTy(ImmTyMatrixAReuse); }
397 bool isMatrixBReuse() const { return isImmTy(ImmTyMatrixBReuse); }
398 bool isTFE() const { return isImmTy(ImmTyTFE); }
399 bool isFORMAT() const { return isImmTy(ImmTyFORMAT) && isUInt<7>(getImm()); }
400 bool isDppFI() const { return isImmTy(ImmTyDppFI); }
401 bool isSDWADstSel() const { return isImmTy(ImmTySDWADstSel); }
402 bool isSDWASrc0Sel() const { return isImmTy(ImmTySDWASrc0Sel); }
403 bool isSDWASrc1Sel() const { return isImmTy(ImmTySDWASrc1Sel); }
404 bool isSDWADstUnused() const { return isImmTy(ImmTySDWADstUnused); }
405 bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); }
406 bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); }
407 bool isInterpAttrChan() const { return isImmTy(ImmTyInterpAttrChan); }
408 bool isOpSel() const { return isImmTy(ImmTyOpSel); }
409 bool isOpSelHi() const { return isImmTy(ImmTyOpSelHi); }
410 bool isNegLo() const { return isImmTy(ImmTyNegLo); }
411 bool isNegHi() const { return isImmTy(ImmTyNegHi); }
412 bool isBitOp3() const { return isImmTy(ImmTyBitOp3) && isUInt<8>(getImm()); }
413 bool isDone() const { return isImmTy(ImmTyDone); }
414 bool isRowEn() const { return isImmTy(ImmTyRowEn); }
415
416 bool isRegOrImm() const { return isReg() || isImm(); }
417
418 bool isRegClass(unsigned RCID) const;
419
420 bool isInlineValue() const;
421
422 bool isRegOrInlineNoMods(unsigned RCID, MVT type) const {
423 return isRegOrInline(RCID, type) && !hasModifiers();
424 }
425
426 bool isSCSrcB16() const {
427 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i16);
428 }
429
430 bool isSCSrcV2B16() const { return isSCSrcB16(); }
431
432 bool isSCSrc_b32() const {
433 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i32);
434 }
435
436 bool isSCSrc_b64() const {
437 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::i64);
438 }
439
440 bool isBoolReg() const;
441
442 bool isSCSrcF16() const {
443 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f16);
444 }
445
446 bool isSCSrcV2F16() const { return isSCSrcF16(); }
447
448 bool isSCSrcF32() const {
449 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f32);
450 }
451
452 bool isSCSrcF64() const {
453 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::f64);
454 }
455
456 bool isSSrc_b32() const {
457 return isSCSrc_b32() || isLiteralImm(MVT::i32) || isExpr();
458 }
459
460 bool isSSrc_b16() const { return isSCSrcB16() || isLiteralImm(MVT::i16); }
461
462 bool isSSrcV2B16() const {
463 llvm_unreachable("cannot happen");
464 return isSSrc_b16();
465 }
466
467 bool isSSrc_b64() const {
468 // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits.
469 // See isVSrc64().
470 return isSCSrc_b64() || isLiteralImm(MVT::i64) ||
471 (((const MCTargetAsmParser *)AsmParser)
472 ->getAvailableFeatures()[AMDGPU::Feature64BitLiterals] &&
473 isExpr());
474 }
475
476 bool isSSrc_f32() const {
477 return isSCSrc_b32() || isLiteralImm(MVT::f32) || isExpr();
478 }
479
480 bool isSSrcF64() const { return isSCSrc_b64() || isLiteralImm(MVT::f64); }
481
482 bool isSSrc_bf16() const { return isSCSrcB16() || isLiteralImm(MVT::bf16); }
483
484 bool isSSrc_f16() const { return isSCSrcB16() || isLiteralImm(MVT::f16); }
485
486 bool isSSrc_NoInline_f16() const { return isSSrc_f16(); }
487
488 bool isSSrcV2F16() const {
489 llvm_unreachable("cannot happen");
490 return isSSrc_f16();
491 }
492
493 bool isSSrcV2FP32() const {
494 llvm_unreachable("cannot happen");
495 return isSSrc_f32();
496 }
497
498 bool isSCSrcV2FP32() const {
499 llvm_unreachable("cannot happen");
500 return isSCSrcF32();
501 }
502
503 bool isSSrcV2INT32() const {
504 llvm_unreachable("cannot happen");
505 return isSSrc_b32();
506 }
507
508 bool isSCSrcV2INT32() const {
509 llvm_unreachable("cannot happen");
510 return isSCSrc_b32();
511 }
512
513 bool isSSrcOrLds_b32() const {
514 return isRegOrInlineNoMods(AMDGPU::SRegOrLds_32RegClassID, MVT::i32) ||
515 isLiteralImm(MVT::i32) || isExpr();
516 }
517
518 bool isVCSrc_b32() const {
519 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i32);
520 }
521
522 bool isVCSrc_b32_Lo256() const {
523 return isRegOrInlineNoMods(AMDGPU::VS_32_Lo256RegClassID, MVT::i32);
524 }
525
526 bool isVCSrc_b64_Lo256() const {
527 return isRegOrInlineNoMods(AMDGPU::VS_64_Lo256RegClassID, MVT::i64);
528 }
529
530 bool isVCSrc_b64() const {
531 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::i64);
532 }
533
534 bool isVCSrcT_b16() const {
535 return isRegOrInlineNoMods(AMDGPU::VS_16RegClassID, MVT::i16);
536 }
537
538 bool isVCSrcTB16_Lo128() const {
539 return isRegOrInlineNoMods(AMDGPU::VS_16_Lo128RegClassID, MVT::i16);
540 }
541
542 bool isVCSrcFake16B16_Lo128() const {
543 return isRegOrInlineNoMods(AMDGPU::VS_32_Lo128RegClassID, MVT::i16);
544 }
545
546 bool isVCSrc_b16() const {
547 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i16);
548 }
549
550 bool isVCSrc_v2b16() const { return isVCSrc_b16(); }
551
552 bool isVCSrc_f32() const {
553 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f32);
554 }
555
556 bool isVCSrc_f64() const {
557 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::f64);
558 }
559
560 bool isVCSrcTBF16() const {
561 return isRegOrInlineNoMods(AMDGPU::VS_16RegClassID, MVT::bf16);
562 }
563
564 bool isVCSrcT_f16() const {
565 return isRegOrInlineNoMods(AMDGPU::VS_16RegClassID, MVT::f16);
566 }
567
568 bool isVCSrcT_bf16() const {
569 return isRegOrInlineNoMods(AMDGPU::VS_16RegClassID, MVT::f16);
570 }
571
572 bool isVCSrcTBF16_Lo128() const {
573 return isRegOrInlineNoMods(AMDGPU::VS_16_Lo128RegClassID, MVT::bf16);
574 }
575
576 bool isVCSrcTF16_Lo128() const {
577 return isRegOrInlineNoMods(AMDGPU::VS_16_Lo128RegClassID, MVT::f16);
578 }
579
580 bool isVCSrcFake16BF16_Lo128() const {
581 return isRegOrInlineNoMods(AMDGPU::VS_32_Lo128RegClassID, MVT::bf16);
582 }
583
584 bool isVCSrcFake16F16_Lo128() const {
585 return isRegOrInlineNoMods(AMDGPU::VS_32_Lo128RegClassID, MVT::f16);
586 }
587
588 bool isVCSrc_bf16() const {
589 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::bf16);
590 }
591
592 bool isVCSrc_f16() const {
593 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f16);
594 }
595
596 bool isVCSrc_v2bf16() const { return isVCSrc_bf16(); }
597
598 bool isVCSrc_v2f16() const { return isVCSrc_f16(); }
599
600 bool isVSrc_b32() const {
601 return isVCSrc_f32() || isLiteralImm(MVT::i32) || isExpr();
602 }
603
604 bool isVSrc_b64() const { return isVCSrc_f64() || isLiteralImm(MVT::i64); }
605
606 bool isVSrc_v2b64() const {
607 return isRegOrInlineNoMods(AMDGPU::VS_128RegClassID, MVT::i64) ||
608 isLiteralImm(MVT::i64);
609 }
610
611 bool isVSrc_v2f64() const {
612 return isRegOrInlineNoMods(AMDGPU::VS_128RegClassID, MVT::f64) ||
613 isLiteralImm(MVT::f64);
614 }
615
616 bool isVSrcT_b16() const { return isVCSrcT_b16() || isLiteralImm(MVT::i16); }
617
618 bool isVSrcT_b16_Lo128() const {
619 return isVCSrcTB16_Lo128() || isLiteralImm(MVT::i16);
620 }
621
622 bool isVSrcFake16_b16_Lo128() const {
623 return isVCSrcFake16B16_Lo128() || isLiteralImm(MVT::i16);
624 }
625
626 bool isVSrc_b16() const { return isVCSrc_b16() || isLiteralImm(MVT::i16); }
627
628 bool isVSrc_v2b16() const { return isVSrc_b16() || isLiteralImm(MVT::v2i16); }
629
630 bool isVCSrcV2FP32() const { return isVCSrc_f64(); }
631
632 bool isVSrc_v2f32() const { return isVSrc_f64() || isLiteralImm(MVT::v2f32); }
633
634 bool isVCSrc_v2b32() const { return isVCSrc_b64(); }
635
636 bool isVSrc_v2b32() const { return isVSrc_b64() || isLiteralImm(MVT::v2i32); }
637
638 bool isVSrc_f32() const {
639 return isVCSrc_f32() || isLiteralImm(MVT::f32) || isExpr();
640 }
641
642 bool isVSrc_f64() const { return isVCSrc_f64() || isLiteralImm(MVT::f64); }
643
644 bool isVSrcT_bf16() const {
645 return isVCSrcTBF16() || isLiteralImm(MVT::bf16);
646 }
647
648 bool isVSrcT_f16() const { return isVCSrcT_f16() || isLiteralImm(MVT::f16); }
649
650 bool isVSrcT_bf16_Lo128() const {
651 return isVCSrcTBF16_Lo128() || isLiteralImm(MVT::bf16);
652 }
653
654 bool isVSrcT_f16_Lo128() const {
655 return isVCSrcTF16_Lo128() || isLiteralImm(MVT::f16);
656 }
657
658 bool isVSrcFake16_bf16_Lo128() const {
659 return isVCSrcFake16BF16_Lo128() || isLiteralImm(MVT::bf16);
660 }
661
662 bool isVSrcFake16_f16_Lo128() const {
663 return isVCSrcFake16F16_Lo128() || isLiteralImm(MVT::f16);
664 }
665
666 bool isVSrc_bf16() const { return isVCSrc_bf16() || isLiteralImm(MVT::bf16); }
667
668 bool isVSrc_f16() const { return isVCSrc_f16() || isLiteralImm(MVT::f16); }
669
670 bool isVSrc_v2bf16() const {
671 return isVSrc_bf16() || isLiteralImm(MVT::v2bf16);
672 }
673
674 bool isVSrc_v2f16() const { return isVSrc_f16() || isLiteralImm(MVT::v2f16); }
675
676 bool isVSrc_v2f16_splat() const { return isVSrc_v2f16(); }
677
678 bool isVSrc_NoInline_v2f16() const { return isVSrc_v2f16(); }
679
680 bool isVISrcB32() const {
681 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::i32);
682 }
683
684 bool isVISrcB16() const {
685 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::i16);
686 }
687
688 bool isVISrcV2B16() const { return isVISrcB16(); }
689
690 bool isVISrcF32() const {
691 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::f32);
692 }
693
694 bool isVISrcF16() const {
695 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::f16);
696 }
697
698 bool isVISrcV2F16() const { return isVISrcF16() || isVISrcB32(); }
699
700 bool isVISrc_64_bf16() const {
701 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::bf16);
702 }
703
704 bool isVISrc_64_f16() const {
705 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::f16);
706 }
707
708 bool isVISrc_64_b32() const {
709 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::i32);
710 }
711
712 bool isVISrc_64B64() const {
713 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::i64);
714 }
715
716 bool isVISrc_64_f64() const {
717 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::f64);
718 }
719
720 bool isVISrc_64V2FP32() const {
721 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::f32);
722 }
723
724 bool isVISrc_64V2INT32() const {
725 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::i32);
726 }
727
728 bool isVISrc_256_b32() const {
729 return isRegOrInlineNoMods(AMDGPU::VReg_256RegClassID, MVT::i32);
730 }
731
732 bool isVISrc_256_f32() const {
733 return isRegOrInlineNoMods(AMDGPU::VReg_256RegClassID, MVT::f32);
734 }
735
736 bool isVISrc_256B64() const {
737 return isRegOrInlineNoMods(AMDGPU::VReg_256RegClassID, MVT::i64);
738 }
739
740 bool isVISrc_256_f64() const {
741 return isRegOrInlineNoMods(AMDGPU::VReg_256RegClassID, MVT::f64);
742 }
743
744 bool isVISrc_512_f64() const {
745 return isRegOrInlineNoMods(AMDGPU::VReg_512RegClassID, MVT::f64);
746 }
747
748 bool isVISrc_128B16() const {
749 return isRegOrInlineNoMods(AMDGPU::VReg_128RegClassID, MVT::i16);
750 }
751
752 bool isVISrc_128V2B16() const { return isVISrc_128B16(); }
753
754 bool isVISrc_128_b32() const {
755 return isRegOrInlineNoMods(AMDGPU::VReg_128RegClassID, MVT::i32);
756 }
757
758 bool isVISrc_128_f32() const {
759 return isRegOrInlineNoMods(AMDGPU::VReg_128RegClassID, MVT::f32);
760 }
761
762 bool isVISrc_256V2FP32() const {
763 return isRegOrInlineNoMods(AMDGPU::VReg_256RegClassID, MVT::f32);
764 }
765
766 bool isVISrc_256V2INT32() const {
767 return isRegOrInlineNoMods(AMDGPU::VReg_256RegClassID, MVT::i32);
768 }
769
770 bool isVISrc_512_b32() const {
771 return isRegOrInlineNoMods(AMDGPU::VReg_512RegClassID, MVT::i32);
772 }
773
774 bool isVISrc_512B16() const {
775 return isRegOrInlineNoMods(AMDGPU::VReg_512RegClassID, MVT::i16);
776 }
777
778 bool isVISrc_512V2B16() const { return isVISrc_512B16(); }
779
780 bool isVISrc_512_f32() const {
781 return isRegOrInlineNoMods(AMDGPU::VReg_512RegClassID, MVT::f32);
782 }
783
784 bool isVISrc_512F16() const {
785 return isRegOrInlineNoMods(AMDGPU::VReg_512RegClassID, MVT::f16);
786 }
787
788 bool isVISrc_512V2F16() const {
789 return isVISrc_512F16() || isVISrc_512_b32();
790 }
791
792 bool isVISrc_1024_b32() const {
793 return isRegOrInlineNoMods(AMDGPU::VReg_1024RegClassID, MVT::i32);
794 }
795
796 bool isVISrc_1024B16() const {
797 return isRegOrInlineNoMods(AMDGPU::VReg_1024RegClassID, MVT::i16);
798 }
799
800 bool isVISrc_1024V2B16() const { return isVISrc_1024B16(); }
801
802 bool isVISrc_1024_f32() const {
803 return isRegOrInlineNoMods(AMDGPU::VReg_1024RegClassID, MVT::f32);
804 }
805
806 bool isVISrc_1024F16() const {
807 return isRegOrInlineNoMods(AMDGPU::VReg_1024RegClassID, MVT::f16);
808 }
809
810 bool isVISrc_1024V2F16() const {
811 return isVISrc_1024F16() || isVISrc_1024_b32();
812 }
813
814 bool isAISrcB32() const {
815 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::i32);
816 }
817
818 bool isAISrcB16() const {
819 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::i16);
820 }
821
822 bool isAISrcV2B16() const { return isAISrcB16(); }
823
824 bool isAISrcF32() const {
825 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::f32);
826 }
827
828 bool isAISrcF16() const {
829 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::f16);
830 }
831
832 bool isAISrcV2F16() const { return isAISrcF16() || isAISrcB32(); }
833
834 bool isAISrc_64B64() const {
835 return isRegOrInlineNoMods(AMDGPU::AReg_64RegClassID, MVT::i64);
836 }
837
838 bool isAISrc_64_f64() const {
839 return isRegOrInlineNoMods(AMDGPU::AReg_64RegClassID, MVT::f64);
840 }
841
842 bool isAISrc_128_b32() const {
843 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::i32);
844 }
845
846 bool isAISrc_128B16() const {
847 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::i16);
848 }
849
850 bool isAISrc_128V2B16() const { return isAISrc_128B16(); }
851
852 bool isAISrc_128_f32() const {
853 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::f32);
854 }
855
856 bool isAISrc_128F16() const {
857 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::f16);
858 }
859
860 bool isAISrc_128V2F16() const {
861 return isAISrc_128F16() || isAISrc_128_b32();
862 }
863
864 bool isVISrc_128_bf16() const {
865 return isRegOrInlineNoMods(AMDGPU::VReg_128RegClassID, MVT::bf16);
866 }
867
868 bool isVISrc_128_f16() const {
869 return isRegOrInlineNoMods(AMDGPU::VReg_128RegClassID, MVT::f16);
870 }
871
872 bool isVISrc_128V2F16() const {
873 return isVISrc_128_f16() || isVISrc_128_b32();
874 }
875
876 bool isAISrc_256B64() const {
877 return isRegOrInlineNoMods(AMDGPU::AReg_256RegClassID, MVT::i64);
878 }
879
880 bool isAISrc_256_f64() const {
881 return isRegOrInlineNoMods(AMDGPU::AReg_256RegClassID, MVT::f64);
882 }
883
884 bool isAISrc_512_b32() const {
885 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::i32);
886 }
887
888 bool isAISrc_512B16() const {
889 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::i16);
890 }
891
892 bool isAISrc_512V2B16() const { return isAISrc_512B16(); }
893
894 bool isAISrc_512_f32() const {
895 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::f32);
896 }
897
898 bool isAISrc_512F16() const {
899 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::f16);
900 }
901
902 bool isAISrc_512V2F16() const {
903 return isAISrc_512F16() || isAISrc_512_b32();
904 }
905
906 bool isAISrc_1024_b32() const {
907 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::i32);
908 }
909
910 bool isAISrc_1024B16() const {
911 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::i16);
912 }
913
914 bool isAISrc_1024V2B16() const { return isAISrc_1024B16(); }
915
916 bool isAISrc_1024_f32() const {
917 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::f32);
918 }
919
920 bool isAISrc_1024F16() const {
921 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::f16);
922 }
923
924 bool isAISrc_1024V2F16() const {
925 return isAISrc_1024F16() || isAISrc_1024_b32();
926 }
927
928 bool isKImmFP32() const { return isLiteralImm(MVT::f32); }
929
930 bool isKImmFP16() const { return isLiteralImm(MVT::f16); }
931
932 bool isKImmFP64() const { return isLiteralImm(MVT::f64); }
933
934 bool isMem() const override { return false; }
935
936 bool isExpr() const { return Kind == Expression; }
937
938 bool isSOPPBrTarget() const { return isExpr() || isImm(); }
939
940 bool isSWaitCnt() const;
941 bool isDepCtr() const;
942 bool isSDelayALU() const;
943 bool isHwreg() const;
944 bool isSendMsg() const;
945 bool isWaitEvent() const;
946 bool isSplitBarrier() const;
947 bool isSwizzle() const;
948 bool isSMRDOffset8() const;
949 bool isSMEMOffset() const;
950 bool isSMRDLiteralOffset() const;
951 bool isDPP8() const;
952 bool isDPPCtrl() const;
953 bool isBLGP() const;
954 bool isGPRIdxMode() const;
955 bool isS16Imm() const;
956 bool isU16Imm() const;
957 bool isEndpgm() const;
958
959 auto getPredicate(std::function<bool(const AMDGPUOperand &Op)> P) const {
960 return [this, P]() { return P(*this); };
961 }
962
963 StringRef getToken() const {
964 assert(isToken());
965 return StringRef(Tok.Data, Tok.Length);
966 }
967
968 int64_t getImm() const {
969 assert(isImm());
970 return Imm.Val;
971 }
972
973 void setImm(int64_t Val) {
974 assert(isImm());
975 Imm.Val = Val;
976 }
977
978 ImmTy getImmTy() const {
979 assert(isImm());
980 return Imm.Type;
981 }
982
983 MCRegister getReg() const override {
984 assert(isRegKind());
985 return Reg.RegNo;
986 }
987
988 SMLoc getStartLoc() const override { return StartLoc; }
989
990 SMLoc getEndLoc() const override { return EndLoc; }
991
992 SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
993
994 int getMCOpIdx() const { return MCOpIdx; }
995
996 Modifiers getModifiers() const {
997 assert(isRegKind() || isImmTy(ImmTyNone));
998 return isRegKind() ? Reg.Mods : Imm.Mods;
999 }
1000
1001 void setModifiers(Modifiers Mods) {
1002 assert(isRegKind() || isImmTy(ImmTyNone));
1003 if (isRegKind())
1004 Reg.Mods = Mods;
1005 else
1006 Imm.Mods = Mods;
1007 }
1008
1009 bool hasModifiers() const { return getModifiers().hasModifiers(); }
1010
1011 bool hasFPModifiers() const { return getModifiers().hasFPModifiers(); }
1012
1013 bool hasIntModifiers() const { return getModifiers().hasIntModifiers(); }
1014
1015 bool isForcedLit() const {
1016 return isImmLiteral() && getModifiers().isForcedLit();
1017 }
1018
1019 bool isForcedLit64() const {
1020 return isImmLiteral() && getModifiers().isForcedLit64();
1021 }
1022
1023 uint64_t applyInputFPModifiers(uint64_t Val, unsigned Size) const;
1024
1025 void addImmOperands(MCInst &Inst, unsigned N,
1026 bool ApplyModifiers = true) const;
1027
1028 void addLiteralImmOperand(MCInst &Inst, int64_t Val,
1029 bool ApplyModifiers) const;
1030
1031 void addRegOperands(MCInst &Inst, unsigned N) const;
1032
1033 void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
1034 if (isRegKind())
1035 addRegOperands(Inst, N);
1036 else
1037 addImmOperands(Inst, N);
1038 }
1039
1040 void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const {
1041 Modifiers Mods = getModifiers();
1042 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
1043 if (isRegKind()) {
1044 addRegOperands(Inst, N);
1045 } else {
1046 addImmOperands(Inst, N, false);
1047 }
1048 }
1049
1050 void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
1051 assert(!hasIntModifiers());
1052 addRegOrImmWithInputModsOperands(Inst, N);
1053 }
1054
1055 void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
1056 assert(!hasFPModifiers());
1057 addRegOrImmWithInputModsOperands(Inst, N);
1058 }
1059
1060 void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const {
1061 Modifiers Mods = getModifiers();
1062 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
1063 assert(isRegKind());
1064 addRegOperands(Inst, N);
1065 }
1066
1067 void addRegWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
1068 assert(!hasIntModifiers());
1069 addRegWithInputModsOperands(Inst, N);
1070 }
1071
1072 void addRegWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
1073 assert(!hasFPModifiers());
1074 addRegWithInputModsOperands(Inst, N);
1075 }
1076
1077 static void printImmTy(raw_ostream &OS, ImmTy Type) {
1078 // clang-format off
1079 switch (Type) {
1080 case ImmTyNone: OS << "None"; break;
1081 case ImmTyGDS: OS << "GDS"; break;
1082 case ImmTyLDS: OS << "LDS"; break;
1083 case ImmTyOffen: OS << "Offen"; break;
1084 case ImmTyIdxen: OS << "Idxen"; break;
1085 case ImmTyAddr64: OS << "Addr64"; break;
1086 case ImmTyOffset: OS << "Offset"; break;
1087 case ImmTyInstOffset: OS << "InstOffset"; break;
1088 case ImmTyOffset0: OS << "Offset0"; break;
1089 case ImmTyOffset1: OS << "Offset1"; break;
1090 case ImmTySMEMOffsetMod: OS << "SMEMOffsetMod"; break;
1091 case ImmTyCPol: OS << "CPol"; break;
1092 case ImmTyIndexKey8bit: OS << "index_key"; break;
1093 case ImmTyIndexKey16bit: OS << "index_key"; break;
1094 case ImmTyIndexKey32bit: OS << "index_key"; break;
1095 case ImmTyTFE: OS << "TFE"; break;
1096 case ImmTyIsAsync: OS << "IsAsync"; break;
1097 case ImmTyD16: OS << "D16"; break;
1098 case ImmTyFORMAT: OS << "FORMAT"; break;
1099 case ImmTyClamp: OS << "Clamp"; break;
1100 case ImmTyOModSI: OS << "OModSI"; break;
1101 case ImmTyDPP8: OS << "DPP8"; break;
1102 case ImmTyDppCtrl: OS << "DppCtrl"; break;
1103 case ImmTyDppRowMask: OS << "DppRowMask"; break;
1104 case ImmTyDppBankMask: OS << "DppBankMask"; break;
1105 case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break;
1106 case ImmTyDppFI: OS << "DppFI"; break;
1107 case ImmTySDWADstSel: OS << "SDWADstSel"; break;
1108 case ImmTySDWASrc0Sel: OS << "SDWASrc0Sel"; break;
1109 case ImmTySDWASrc1Sel: OS << "SDWASrc1Sel"; break;
1110 case ImmTySDWADstUnused: OS << "SDWADstUnused"; break;
1111 case ImmTyDMask: OS << "DMask"; break;
1112 case ImmTyDim: OS << "Dim"; break;
1113 case ImmTyUNorm: OS << "UNorm"; break;
1114 case ImmTyDA: OS << "DA"; break;
1115 case ImmTyR128A16: OS << "R128A16"; break;
1116 case ImmTyA16: OS << "A16"; break;
1117 case ImmTyLWE: OS << "LWE"; break;
1118 case ImmTyOff: OS << "Off"; break;
1119 case ImmTyExpTgt: OS << "ExpTgt"; break;
1120 case ImmTyExpCompr: OS << "ExpCompr"; break;
1121 case ImmTyExpVM: OS << "ExpVM"; break;
1122 case ImmTyDone: OS << "Done"; break;
1123 case ImmTyRowEn: OS << "RowEn"; break;
1124 case ImmTyHwreg: OS << "Hwreg"; break;
1125 case ImmTySendMsg: OS << "SendMsg"; break;
1126 case ImmTyWaitEvent: OS << "WaitEvent"; break;
1127 case ImmTyInterpSlot: OS << "InterpSlot"; break;
1128 case ImmTyInterpAttr: OS << "InterpAttr"; break;
1129 case ImmTyInterpAttrChan: OS << "InterpAttrChan"; break;
1130 case ImmTyOpSel: OS << "OpSel"; break;
1131 case ImmTyOpSelHi: OS << "OpSelHi"; break;
1132 case ImmTyNegLo: OS << "NegLo"; break;
1133 case ImmTyNegHi: OS << "NegHi"; break;
1134 case ImmTySwizzle: OS << "Swizzle"; break;
1135 case ImmTyGprIdxMode: OS << "GprIdxMode"; break;
1136 case ImmTyHigh: OS << "High"; break;
1137 case ImmTyBLGP: OS << "BLGP"; break;
1138 case ImmTyCBSZ: OS << "CBSZ"; break;
1139 case ImmTyABID: OS << "ABID"; break;
1140 case ImmTyEndpgm: OS << "Endpgm"; break;
1141 case ImmTyWaitVDST: OS << "WaitVDST"; break;
1142 case ImmTyWaitEXP: OS << "WaitEXP"; break;
1143 case ImmTyWaitVAVDst: OS << "WaitVAVDst"; break;
1144 case ImmTyWaitVMVSrc: OS << "WaitVMVSrc"; break;
1145 case ImmTyBitOp3: OS << "BitOp3"; break;
1146 case ImmTyMatrixAFMT: OS << "ImmTyMatrixAFMT"; break;
1147 case ImmTyMatrixBFMT: OS << "ImmTyMatrixBFMT"; break;
1148 case ImmTyMatrixAScale: OS << "ImmTyMatrixAScale"; break;
1149 case ImmTyMatrixBScale: OS << "ImmTyMatrixBScale"; break;
1150 case ImmTyMatrixAScaleFmt: OS << "ImmTyMatrixAScaleFmt"; break;
1151 case ImmTyMatrixBScaleFmt: OS << "ImmTyMatrixBScaleFmt"; break;
1152 case ImmTyMatrixAReuse: OS << "ImmTyMatrixAReuse"; break;
1153 case ImmTyMatrixBReuse: OS << "ImmTyMatrixBReuse"; break;
1154 case ImmTyScaleSel: OS << "ScaleSel" ; break;
1155 case ImmTyByteSel: OS << "ByteSel" ; break;
1156 }
1157 // clang-format on
1158 }
1159
1160 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override {
1161 switch (Kind) {
1162 case Register:
1163 OS << "<register " << AMDGPUInstPrinter::getRegisterName(getReg())
1164 << " mods: " << Reg.Mods << '>';
1165 break;
1166 case Immediate:
1167 OS << '<' << getImm();
1168 if (getImmTy() != ImmTyNone) {
1169 OS << " type: ";
1170 printImmTy(OS, getImmTy());
1171 }
1172 OS << " mods: " << Imm.Mods << '>';
1173 break;
1174 case Token:
1175 OS << '\'' << getToken() << '\'';
1176 break;
1177 case Expression:
1178 OS << "<expr ";
1179 MAI.printExpr(OS, *Expr);
1180 OS << '>';
1181 break;
1182 }
1183 }
1184
1185 static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser,
1186 int64_t Val, SMLoc Loc,
1187 ImmTy Type = ImmTyNone,
1188 bool IsFPImm = false) {
1189 auto Op = std::make_unique<AMDGPUOperand>(Immediate, AsmParser);
1190 Op->Imm.Val = Val;
1191 Op->Imm.IsFPImm = IsFPImm;
1192 Op->Imm.Type = Type;
1193 Op->Imm.Mods = Modifiers();
1194 Op->StartLoc = Loc;
1195 Op->EndLoc = Loc;
1196 return Op;
1197 }
1198
1199 static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser,
1200 StringRef Str, SMLoc Loc,
1201 bool HasExplicitEncodingSize = true) {
1202 auto Res = std::make_unique<AMDGPUOperand>(Token, AsmParser);
1203 Res->Tok.Data = Str.data();
1204 Res->Tok.Length = Str.size();
1205 Res->StartLoc = Loc;
1206 Res->EndLoc = Loc;
1207 return Res;
1208 }
1209
1210 static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser,
1211 MCRegister Reg, SMLoc S, SMLoc E) {
1212 auto Op = std::make_unique<AMDGPUOperand>(Register, AsmParser);
1213 Op->Reg.RegNo = Reg;
1214 Op->Reg.Mods = Modifiers();
1215 Op->StartLoc = S;
1216 Op->EndLoc = E;
1217 return Op;
1218 }
1219
1220 static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser,
1221 const class MCExpr *Expr, SMLoc S) {
1222 auto Op = std::make_unique<AMDGPUOperand>(Expression, AsmParser);
1223 Op->Expr = Expr;
1224 Op->StartLoc = S;
1225 Op->EndLoc = S;
1226 return Op;
1227 }
1228};
1229
1230raw_ostream &operator<<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) {
1231 OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext;
1232 return OS;
1233}
1234
1235//===----------------------------------------------------------------------===//
1236// AsmParser
1237//===----------------------------------------------------------------------===//
1238
1239// TODO: define GET_SUBTARGET_FEATURE_NAME
1240#define GET_REGISTER_MATCHER
1241#include "AMDGPUGenAsmMatcher.inc"
1242#undef GET_REGISTER_MATCHER
1243#undef GET_SUBTARGET_FEATURE_NAME
1244
1245// Holds info related to the current kernel, e.g. count of SGPRs used.
1246// Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next
1247// .amdgpu_hsa_kernel or at EOF.
1248class KernelScopeInfo {
1249 int SgprIndexUnusedMin = -1;
1250 int VgprIndexUnusedMin = -1;
1251 int AgprIndexUnusedMin = -1;
1252 MCContext *Ctx = nullptr;
1253 MCSubtargetInfo const *MSTI = nullptr;
1254
1255 void usesSgprAt(int i) {
1256 if (i >= SgprIndexUnusedMin) {
1257 SgprIndexUnusedMin = ++i;
1258 if (Ctx) {
1259 MCSymbol *const Sym =
1260 Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count"));
1261 Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx));
1262 }
1263 }
1264 }
1265
1266 void usesVgprAt(int i) {
1267 if (i >= VgprIndexUnusedMin) {
1268 VgprIndexUnusedMin = ++i;
1269 if (Ctx) {
1270 MCSymbol *const Sym =
1271 Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count"));
1272 int totalVGPR = getTotalNumVGPRs(isGFX90A(*MSTI), AgprIndexUnusedMin,
1273 VgprIndexUnusedMin);
1274 Sym->setVariableValue(MCConstantExpr::create(totalVGPR, *Ctx));
1275 }
1276 }
1277 }
1278
1279 void usesAgprAt(int i) {
1280 // Instruction will error in AMDGPUAsmParser::matchAndEmitInstruction
1281 if (!hasMAIInsts(*MSTI))
1282 return;
1283
1284 if (i >= AgprIndexUnusedMin) {
1285 AgprIndexUnusedMin = ++i;
1286 if (Ctx) {
1287 MCSymbol *const Sym =
1288 Ctx->getOrCreateSymbol(Twine(".kernel.agpr_count"));
1289 Sym->setVariableValue(MCConstantExpr::create(AgprIndexUnusedMin, *Ctx));
1290
1291 // Also update vgpr_count (dependent on agpr_count for gfx908/gfx90a)
1292 MCSymbol *const vSym =
1293 Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count"));
1294 int totalVGPR = getTotalNumVGPRs(isGFX90A(*MSTI), AgprIndexUnusedMin,
1295 VgprIndexUnusedMin);
1296 vSym->setVariableValue(MCConstantExpr::create(totalVGPR, *Ctx));
1297 }
1298 }
1299 }
1300
1301public:
1302 KernelScopeInfo() = default;
1303
1304 void initialize(MCContext &Context) {
1305 Ctx = &Context;
1306 MSTI = Ctx->getSubtargetInfo();
1307
1308 usesSgprAt(SgprIndexUnusedMin = -1);
1309 usesVgprAt(VgprIndexUnusedMin = -1);
1310 if (hasMAIInsts(*MSTI)) {
1311 usesAgprAt(AgprIndexUnusedMin = -1);
1312 }
1313 }
1314
1315 void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex,
1316 unsigned RegWidth) {
1317 switch (RegKind) {
1318 case IS_SGPR:
1319 usesSgprAt(DwordRegIndex + divideCeil(RegWidth, 32) - 1);
1320 break;
1321 case IS_AGPR:
1322 usesAgprAt(DwordRegIndex + divideCeil(RegWidth, 32) - 1);
1323 break;
1324 case IS_VGPR:
1325 usesVgprAt(DwordRegIndex + divideCeil(RegWidth, 32) - 1);
1326 break;
1327 default:
1328 break;
1329 }
1330 }
1331};
1332
1333class AMDGPUAsmParser : public MCTargetAsmParser {
1334 MCAsmParser &Parser;
1335
1336 unsigned ForcedEncodingSize = 0;
1337 bool ForcedDPP = false;
1338 bool ForcedSDWA = false;
1339 KernelScopeInfo KernelScope;
1340 const unsigned HwMode;
1341 const AMDGPU::GPUKind Gfx;
1342 const AMDGPU::IsaVersion ISA;
1343
1344 /// @name Auto-generated Match Functions
1345 /// {
1346
1347#define GET_ASSEMBLER_HEADER
1348#include "AMDGPUGenAsmMatcher.inc"
1349
1350 /// }
1351
1352 /// Get size of register operand
1353 unsigned getRegOperandSize(const MCInstrDesc &Desc, unsigned OpNo) const {
1354 assert(OpNo < Desc.NumOperands);
1355 int16_t RCID = MII.getOpRegClassID(Desc.operands()[OpNo], HwMode);
1356 return getRegBitWidth(RCID) / 8;
1357 }
1358
1359 std::optional<AMDGPU::InfoSectionData> InfoData;
1360
1361 /// Whether the leading .amdgcn_target directive has been emitted to the
1362 /// output streamer yet. The emission is deferred until the first piece of
1363 /// content (instruction or kernel descriptor) so that any leading
1364 /// .amdgcn_target/.amd_amdgpu_isa directive in the source has had a chance to
1365 /// update the target ID first.
1366 bool TargetDirectiveEmitted = false;
1367
1368 /// State for checking that every kernel named in a .amdhsa_kernel directive
1369 /// begins with the required prologue instruction sequence. Because the
1370 /// directive may appear either before or after the kernel's label (it is
1371 /// normally emitted after the function body, in .rodata), validation is
1372 /// deferred to onEndOfFile(). We record an order-independent timeline of
1373 /// parsed labels and emitted instruction opcodes, plus the set of symbols
1374 /// named by .amdhsa_kernel directives, and match them up at end of file.
1375 SmallVector<unsigned> OpcodeStream;
1377 OpcodeStreamSymbols;
1378 SmallPtrSet<const MCSymbol *, 8> AMDHSAKernelSymbols;
1379
1380 /// Verify recorded kernel prologues.
1381 void checkKernelPrologues();
1382
1383private:
1384 void createConstantSymbol(StringRef Id, int64_t Val);
1385
1386 bool ParseAsAbsoluteExpression(uint32_t &Ret);
1387 bool OutOfRangeError(SMRange Range);
1388 /// Calculate VGPR/SGPR blocks required for given target, reserved
1389 /// registers, and user-specified NextFreeXGPR values.
1390 ///
1391 /// \param Features [in] Target features, used for bug corrections.
1392 /// \param VCCUsed [in] Whether VCC special SGPR is reserved.
1393 /// \param FlatScrUsed [in] Whether FLAT_SCRATCH special SGPR is reserved.
1394 /// \param XNACKUsed [in] Whether XNACK_MASK special SGPR is reserved.
1395 /// \param EnableWavefrontSize32 [in] Value of ENABLE_WAVEFRONT_SIZE32 kernel
1396 /// descriptor field, if valid.
1397 /// \param NextFreeVGPR [in] Max VGPR number referenced, plus one.
1398 /// \param VGPRRange [in] Token range, used for VGPR diagnostics.
1399 /// \param NextFreeSGPR [in] Max SGPR number referenced, plus one.
1400 /// \param SGPRRange [in] Token range, used for SGPR diagnostics.
1401 /// \param VGPRBlocks [out] Result VGPR block count.
1402 /// \param SGPRBlocks [out] Result SGPR block count.
1403 bool calculateGPRBlocks(const FeatureBitset &Features, const MCExpr *VCCUsed,
1404 const MCExpr *FlatScrUsed, bool XNACKUsed,
1405 std::optional<bool> EnableWavefrontSize32,
1406 const MCExpr *NextFreeVGPR, SMRange VGPRRange,
1407 const MCExpr *NextFreeSGPR, SMRange SGPRRange,
1408 const MCExpr *&VGPRBlocks, const MCExpr *&SGPRBlocks);
1409 bool ParseDirectiveAMDGCNTarget();
1410 bool ParseDirectiveAMDHSACodeObjectVersion();
1411 bool ParseDirectiveAMDHSAKernel();
1412 bool ParseAMDKernelCodeTValue(StringRef ID, AMDGPUMCKernelCodeT &Header);
1413 bool ParseDirectiveAMDKernelCodeT();
1414 // TODO: Possibly make subtargetHasRegister const.
1415 bool subtargetHasRegister(const MCRegisterInfo &MRI, MCRegister Reg);
1416 bool ParseDirectiveAMDGPUHsaKernel();
1417
1418 bool ParseDirectiveISAVersion();
1419 bool ParseDirectiveHSAMetadata();
1420 bool ParseDirectivePALMetadataBegin();
1421 bool ParseDirectivePALMetadata();
1422 bool ParseDirectiveAMDGPULDS();
1423 bool ParseDirectiveAMDGPUInfo();
1424
1425 /// Common code to parse out a block of text (typically YAML) between start
1426 /// and end directives.
1427 bool ParseToEndDirective(const char *AssemblerDirectiveBegin,
1428 const char *AssemblerDirectiveEnd,
1429 std::string &CollectString);
1430
1431 bool AddNextRegisterToList(MCRegister &Reg, unsigned &RegWidth,
1432 RegisterKind RegKind, MCRegister Reg1,
1433 RegisterKind RegKind1, SMLoc Loc);
1434 bool ParseAMDGPURegister(RegisterKind &RegKind, MCRegister &Reg,
1435 unsigned &RegNum, unsigned &RegWidth,
1436 bool RestoreOnFailure = false);
1437 bool ParseAMDGPURegister(RegisterKind &RegKind, MCRegister &Reg,
1438 unsigned &RegNum, unsigned &RegWidth,
1439 SmallVectorImpl<AsmToken> &Tokens);
1440 MCRegister ParseRegularReg(RegisterKind &RegKind, unsigned &RegNum,
1441 unsigned &RegWidth,
1442 SmallVectorImpl<AsmToken> &Tokens);
1443 MCRegister ParseSpecialReg(RegisterKind &RegKind, unsigned &RegNum,
1444 unsigned &RegWidth,
1445 SmallVectorImpl<AsmToken> &Tokens);
1446 MCRegister ParseRegList(RegisterKind &RegKind, unsigned &RegNum,
1447 unsigned &RegWidth,
1448 SmallVectorImpl<AsmToken> &Tokens);
1449 bool ParseRegRange(unsigned &Num, unsigned &Width, unsigned &SubReg);
1450 MCRegister getRegularReg(RegisterKind RegKind, unsigned RegNum,
1451 unsigned SubReg, unsigned RegWidth, SMLoc Loc);
1452
1453 bool isRegister();
1454 bool isRegister(const AsmToken &Token, const AsmToken &NextToken) const;
1455 std::optional<StringRef> getGprCountSymbolName(RegisterKind RegKind);
1456 void initializeGprCountSymbol(RegisterKind RegKind);
1457 bool updateGprCountSymbols(RegisterKind RegKind, unsigned DwordRegIndex,
1458 unsigned RegWidth);
1459 void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands, bool IsAtomic);
1460
1461public:
1462 enum OperandMode {
1463 OperandMode_Default,
1464 OperandMode_NSA,
1465 };
1466
1467 using OptionalImmIndexMap = std::map<AMDGPUOperand::ImmTy, unsigned>;
1468
1469 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
1470 const MCInstrInfo &MII)
1471 : MCTargetAsmParser(STI, MII), Parser(_Parser),
1472 HwMode(STI.getHwMode(MCSubtargetInfo::HwMode_RegInfo)),
1473 Gfx(AMDGPU::parseArchAMDGCN(STI.getCPU())),
1474 ISA(AMDGPU::getIsaVersion(STI.getCPU())) {
1476
1477 setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits()));
1478
1479 if (ISA.Major >= 6 && isHsaAbi(getSTI())) {
1480 createConstantSymbol(".amdgcn.gfx_generation_number", ISA.Major);
1481 createConstantSymbol(".amdgcn.gfx_generation_minor", ISA.Minor);
1482 createConstantSymbol(".amdgcn.gfx_generation_stepping", ISA.Stepping);
1483 } else {
1484 createConstantSymbol(".option.machine_version_major", ISA.Major);
1485 createConstantSymbol(".option.machine_version_minor", ISA.Minor);
1486 createConstantSymbol(".option.machine_version_stepping", ISA.Stepping);
1487 }
1488 if (ISA.Major >= 6 && isHsaAbi(getSTI())) {
1489 initializeGprCountSymbol(IS_VGPR);
1490 initializeGprCountSymbol(IS_SGPR);
1491 } else
1492 KernelScope.initialize(getContext());
1493
1494 for (auto [Symbol, Code] : AMDGPU::UCVersion::getGFXVersions())
1495 createConstantSymbol(Symbol, Code);
1496
1497 createConstantSymbol("UC_VERSION_W64_BIT", 0x2000);
1498 createConstantSymbol("UC_VERSION_W32_BIT", 0x4000);
1499 createConstantSymbol("UC_VERSION_MDP_BIT", 0x8000);
1500 }
1501
1502 bool hasMIMG_R128() const { return AMDGPU::hasMIMG_R128(getSTI()); }
1503
1504 bool hasPackedD16() const { return AMDGPU::hasPackedD16(getSTI()); }
1505
1506 bool hasA16() const { return AMDGPU::hasA16(getSTI()); }
1507
1508 bool hasG16() const { return AMDGPU::hasG16(getSTI()); }
1509
1510 bool hasGDS() const { return AMDGPU::hasGDS(getSTI()); }
1511
1512 bool isSI() const { return AMDGPU::isSI(getSTI()); }
1513
1514 bool isCI() const { return AMDGPU::isCI(getSTI()); }
1515
1516 bool isVI() const { return AMDGPU::isVI(getSTI()); }
1517
1518 bool isGFX9() const { return AMDGPU::isGFX9(getSTI()); }
1519
1520 // TODO: isGFX90A is also true for GFX940. We need to clean it.
1521 bool isGFX90A() const { return AMDGPU::isGFX90A(getSTI()); }
1522
1523 bool isGFX940() const { return AMDGPU::isGFX940(getSTI()); }
1524
1525 bool isGFX9Plus() const { return AMDGPU::isGFX9Plus(getSTI()); }
1526
1527 bool isGFX10() const { return AMDGPU::isGFX10(getSTI()); }
1528
1529 bool isGFX10Plus() const { return AMDGPU::isGFX10Plus(getSTI()); }
1530
1531 bool isGFX11() const { return AMDGPU::isGFX11(getSTI()); }
1532
1533 bool isGFX11Plus() const { return AMDGPU::isGFX11Plus(getSTI()); }
1534
1535 bool isGFX12() const { return AMDGPU::isGFX12(getSTI()); }
1536
1537 bool isGFX12Plus() const { return AMDGPU::isGFX12Plus(getSTI()); }
1538
1539 bool isGFX1250() const { return AMDGPU::isGFX1250(getSTI()); }
1540
1541 bool isGFX1250Plus() const { return AMDGPU::isGFX1250Plus(getSTI()); }
1542
1543 bool isGFX13() const { return AMDGPU::isGFX13(getSTI()); }
1544
1545 bool isGFX13Plus() const { return AMDGPU::isGFX13Plus(getSTI()); }
1546
1547 bool hasBVHRayTracingInsts() const {
1548 return getFeatureBits()[AMDGPU::FeatureBVHRayTracingInsts];
1549 }
1550
1551 bool isGFX10_BEncoding() const { return AMDGPU::isGFX10_BEncoding(getSTI()); }
1552
1553 bool isWave32() const { return getAvailableFeatures()[Feature_isWave32Bit]; }
1554
1555 bool isWave64() const { return getAvailableFeatures()[Feature_isWave64Bit]; }
1556
1557 bool hasInv2PiInlineImm() const {
1558 return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm];
1559 }
1560
1561 bool has64BitLiterals() const {
1562 return getFeatureBits()[AMDGPU::Feature64BitLiterals];
1563 }
1564
1565 bool hasFlatOffsets() const {
1566 return getFeatureBits()[AMDGPU::FeatureFlatInstOffsets];
1567 }
1568
1569 bool hasTrue16Insts() const {
1570 return getFeatureBits()[AMDGPU::FeatureTrue16BitInsts];
1571 }
1572
1573 bool hasArchitectedFlatScratch() const {
1574 return getFeatureBits()[AMDGPU::FeatureArchitectedFlatScratch];
1575 }
1576
1577 bool hasSGPR102_SGPR103() const { return !isVI() && !isGFX9(); }
1578
1579 bool hasSGPR104_SGPR105() const { return isGFX10Plus(); }
1580
1581 bool hasIntClamp() const { return getFeatureBits()[AMDGPU::FeatureIntClamp]; }
1582
1583 bool hasPartialNSAEncoding() const {
1584 return getFeatureBits()[AMDGPU::FeaturePartialNSAEncoding];
1585 }
1586
1587 bool hasGloballyAddressableScratch() const {
1588 return getFeatureBits()[AMDGPU::FeatureGloballyAddressableScratch];
1589 }
1590
1591 unsigned getNSAMaxSize(bool HasSampler = false) const {
1592 return AMDGPU::getNSAMaxSize(getSTI(), HasSampler);
1593 }
1594
1595 unsigned getMaxNumUserSGPRs() const {
1596 return AMDGPU::getMaxNumUserSGPRs(getSTI());
1597 }
1598
1599 bool hasKernargPreload() const { return AMDGPU::hasKernargPreload(getSTI()); }
1600
1601 AMDGPUTargetStreamer &getTargetStreamer() {
1602 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
1603 return static_cast<AMDGPUTargetStreamer &>(TS);
1604 }
1605
1606 MCContext &getContext() const {
1607 // We need this const_cast because for some reason getContext() is not const
1608 // in MCAsmParser.
1609 return const_cast<AMDGPUAsmParser *>(this)->MCTargetAsmParser::getContext();
1610 }
1611
1612 const MCRegisterInfo *getMRI() const {
1613 return getContext().getRegisterInfo();
1614 }
1615
1616 const MCInstrInfo *getMII() const { return &MII; }
1617
1618 // FIXME: This should not be used. Instead, should use queries derived from
1619 // getAvailableFeatures().
1620 const FeatureBitset &getFeatureBits() const {
1621 return getSTI().getFeatureBits();
1622 }
1623
1624 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
1625 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
1626 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
1627
1628 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
1629 bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
1630 bool isForcedDPP() const { return ForcedDPP; }
1631 bool isForcedSDWA() const { return ForcedSDWA; }
1632 ArrayRef<unsigned> getMatchedVariants() const;
1633 StringRef getMatchedVariantName() const;
1634
1635 std::unique_ptr<AMDGPUOperand> parseRegister(bool RestoreOnFailure = false);
1636 bool ParseRegister(MCRegister &RegNo, SMLoc &StartLoc, SMLoc &EndLoc,
1637 bool RestoreOnFailure);
1638 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
1639 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1640 SMLoc &EndLoc) override;
1641 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
1642 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
1643 unsigned Kind) override;
1644 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1645 OperandVector &Operands, MCStreamer &Out,
1646 uint64_t &ErrorInfo,
1647 bool MatchingInlineAsm) override;
1648 bool ParseDirective(AsmToken DirectiveID) override;
1649 void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) override;
1650 void onEndOfFile() override;
1651 ParseStatus parseOperand(OperandVector &Operands, StringRef Mnemonic,
1652 OperandMode Mode = OperandMode_Default);
1653 StringRef parseMnemonicSuffix(StringRef Name);
1654 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
1655 SMLoc NameLoc, OperandVector &Operands) override;
1656 // bool ProcessInstruction(MCInst &Inst);
1657
1658 ParseStatus parseTokenOp(StringRef Name, OperandVector &Operands);
1659
1660 ParseStatus parseIntWithPrefix(const char *Prefix, int64_t &Int);
1661
1662 ParseStatus
1663 parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
1664 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1665 std::function<bool(int64_t &)> ConvertResult = nullptr);
1666
1667 ParseStatus parseOperandArrayWithPrefix(
1668 const char *Prefix, OperandVector &Operands,
1669 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1670 bool (*ConvertResult)(int64_t &) = nullptr);
1671
1672 ParseStatus
1673 parseNamedBit(StringRef Name, OperandVector &Operands,
1674 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1675 bool IgnoreNegative = false);
1676 unsigned getCPolKind(StringRef Id, StringRef Mnemo, bool &Disabling) const;
1677 ParseStatus parseCPol(OperandVector &Operands);
1678 ParseStatus parseScope(OperandVector &Operands, int64_t &Scope);
1679 ParseStatus parseTH(OperandVector &Operands, int64_t &TH);
1680 ParseStatus parseStringWithPrefix(StringRef Prefix, StringRef &Value,
1681 SMLoc &StringLoc);
1682 ParseStatus parseStringOrIntWithPrefix(OperandVector &Operands,
1683 StringRef Name,
1684 ArrayRef<const char *> Ids,
1685 int64_t &IntVal);
1686 ParseStatus parseStringOrIntWithPrefix(OperandVector &Operands,
1687 StringRef Name,
1688 ArrayRef<const char *> Ids,
1689 AMDGPUOperand::ImmTy Type);
1690
1691 bool isModifier();
1692 bool isOperandModifier(const AsmToken &Token,
1693 const AsmToken &NextToken) const;
1694 bool isRegOrOperandModifier(const AsmToken &Token,
1695 const AsmToken &NextToken) const;
1696 bool isNamedOperandModifier(const AsmToken &Token,
1697 const AsmToken &NextToken) const;
1698 bool isOpcodeModifierWithVal(const AsmToken &Token,
1699 const AsmToken &NextToken) const;
1700 bool parseSP3NegModifier();
1701 ParseStatus parseImm(OperandVector &Operands, bool HasSP3AbsModifier = false,
1702 LitModifier Lit = LitModifier::None);
1703 ParseStatus parseReg(OperandVector &Operands);
1704 ParseStatus parseRegOrImm(OperandVector &Operands, bool HasSP3AbsMod = false,
1705 LitModifier Lit = LitModifier::None);
1706 ParseStatus parseRegOrImmWithFPInputMods(OperandVector &Operands,
1707 bool AllowImm = true);
1708 ParseStatus parseRegOrImmWithIntInputMods(OperandVector &Operands,
1709 bool AllowImm = true);
1710 ParseStatus parseRegWithFPInputMods(OperandVector &Operands);
1711 ParseStatus parseRegWithIntInputMods(OperandVector &Operands);
1712 ParseStatus parseRsrcReg(OperandVector &Operands);
1713 ParseStatus parseVReg32OrOff(OperandVector &Operands);
1714 ParseStatus tryParseIndexKey(OperandVector &Operands,
1715 AMDGPUOperand::ImmTy ImmTy);
1716 ParseStatus parseIndexKey8bit(OperandVector &Operands);
1717 ParseStatus parseIndexKey16bit(OperandVector &Operands);
1718 ParseStatus parseIndexKey32bit(OperandVector &Operands);
1719 ParseStatus tryParseMatrixFMT(OperandVector &Operands, StringRef Name,
1720 AMDGPUOperand::ImmTy Type);
1721 ParseStatus parseMatrixAFMT(OperandVector &Operands);
1722 ParseStatus parseMatrixBFMT(OperandVector &Operands);
1723 ParseStatus tryParseMatrixScale(OperandVector &Operands, StringRef Name,
1724 AMDGPUOperand::ImmTy Type);
1725 ParseStatus parseMatrixAScale(OperandVector &Operands);
1726 ParseStatus parseMatrixBScale(OperandVector &Operands);
1727 ParseStatus tryParseMatrixScaleFmt(OperandVector &Operands, StringRef Name,
1728 AMDGPUOperand::ImmTy Type);
1729 ParseStatus parseMatrixAScaleFmt(OperandVector &Operands);
1730 ParseStatus parseMatrixBScaleFmt(OperandVector &Operands);
1731
1732 ParseStatus parseDfmtNfmt(int64_t &Format);
1733 ParseStatus parseUfmt(int64_t &Format);
1734 ParseStatus parseSymbolicSplitFormat(StringRef FormatStr, SMLoc Loc,
1735 int64_t &Format);
1736 ParseStatus parseSymbolicUnifiedFormat(StringRef FormatStr, SMLoc Loc,
1737 int64_t &Format);
1738 ParseStatus parseFORMAT(OperandVector &Operands);
1739 ParseStatus parseSymbolicOrNumericFormat(int64_t &Format);
1740 ParseStatus parseNumericFormat(int64_t &Format);
1741 ParseStatus parseFlatOffset(OperandVector &Operands);
1742 ParseStatus parseR128A16(OperandVector &Operands);
1743 ParseStatus parseBLGP(OperandVector &Operands);
1744 bool tryParseFmt(const char *Pref, int64_t MaxVal, int64_t &Val);
1745 bool matchDfmtNfmt(int64_t &Dfmt, int64_t &Nfmt, StringRef FormatStr,
1746 SMLoc Loc);
1747
1748 void cvtExp(MCInst &Inst, const OperandVector &Operands);
1749
1750 bool parseCnt(int64_t &IntVal);
1751 ParseStatus parseSWaitCnt(OperandVector &Operands);
1752
1753 bool parseDepCtr(int64_t &IntVal, unsigned &Mask);
1754 void depCtrError(SMLoc Loc, int ErrorId, StringRef DepCtrName);
1755 ParseStatus parseDepCtr(OperandVector &Operands);
1756
1757 bool parseDelay(int64_t &Delay);
1758 ParseStatus parseSDelayALU(OperandVector &Operands);
1759
1760 ParseStatus parseHwreg(OperandVector &Operands);
1761
1762private:
1763 struct OperandInfoTy {
1764 SMLoc Loc;
1765 int64_t Val;
1766 bool IsSymbolic = false;
1767 bool IsDefined = false;
1768
1769 constexpr OperandInfoTy(int64_t Val) : Val(Val) {}
1770 };
1771
1772 struct StructuredOpField : OperandInfoTy {
1773 StringLiteral Id;
1774 StringLiteral Desc;
1775 unsigned Width;
1776 bool IsDefined = false;
1777
1778 constexpr StructuredOpField(StringLiteral Id, StringLiteral Desc,
1779 unsigned Width, int64_t Default)
1780 : OperandInfoTy(Default), Id(Id), Desc(Desc), Width(Width) {}
1781 virtual ~StructuredOpField() = default;
1782
1783 bool Error(AMDGPUAsmParser &Parser, const Twine &Err) const {
1784 Parser.Error(Loc, "invalid " + Desc + ": " + Err);
1785 return false;
1786 }
1787
1788 virtual bool validate(AMDGPUAsmParser &Parser) const {
1789 if (IsSymbolic && Val == OPR_ID_UNSUPPORTED)
1790 return Error(Parser, "not supported on this GPU");
1791 if (!isUIntN(Width, Val))
1792 return Error(Parser, "only " + Twine(Width) + "-bit values are legal");
1793 return true;
1794 }
1795 };
1796
1797 ParseStatus parseStructuredOpFields(ArrayRef<StructuredOpField *> Fields);
1798 bool validateStructuredOpFields(ArrayRef<const StructuredOpField *> Fields);
1799
1800 bool parseSendMsgBody(OperandInfoTy &Msg, OperandInfoTy &Op,
1801 OperandInfoTy &Stream);
1802 bool validateSendMsg(const OperandInfoTy &Msg, const OperandInfoTy &Op,
1803 const OperandInfoTy &Stream);
1804
1805 ParseStatus parseHwregFunc(OperandInfoTy &HwReg, OperandInfoTy &Offset,
1806 OperandInfoTy &Width);
1807
1808 const AMDGPUOperand &findMCOperand(const OperandVector &Operands,
1809 int MCOpIdx) const;
1810
1811 static SMLoc getLaterLoc(SMLoc a, SMLoc b);
1812
1813 SMLoc getFlatOffsetLoc(const OperandVector &Operands) const;
1814 SMLoc getSMEMOffsetLoc(const OperandVector &Operands) const;
1815 SMLoc getBLGPLoc(const OperandVector &Operands) const;
1816
1817 SMLoc getOperandLoc(const OperandVector &Operands, int MCOpIdx) const;
1818 SMLoc getOperandLoc(std::function<bool(const AMDGPUOperand &)> Test,
1819 const OperandVector &Operands) const;
1820 SMLoc getImmLoc(AMDGPUOperand::ImmTy Type,
1821 const OperandVector &Operands) const;
1822 SMLoc getInstLoc(const OperandVector &Operands) const;
1823
1824 bool validateInstruction(const MCInst &Inst, SMLoc IDLoc,
1825 const OperandVector &Operands);
1826 bool validateOffset(const MCInst &Inst, const OperandVector &Operands);
1827 bool validateFlatOffset(const MCInst &Inst, const OperandVector &Operands);
1828 bool validateSMEMOffset(const MCInst &Inst, const OperandVector &Operands);
1829 bool validateSOPLiteral(const MCInst &Inst, const OperandVector &Operands);
1830 bool validateConstantBusLimitations(const MCInst &Inst,
1831 const OperandVector &Operands);
1832 std::optional<unsigned> checkVOPDRegBankConstraints(const MCInst &Inst,
1833 bool AsVOPD3);
1834 bool validateVOPD(const MCInst &Inst, const OperandVector &Operands);
1835 bool tryVOPD(const MCInst &Inst);
1836 bool tryVOPD3(const MCInst &Inst);
1837 bool tryAnotherVOPDEncoding(const MCInst &Inst);
1838
1839 bool validateIntClampSupported(const MCInst &Inst);
1840 bool validateMIMGAtomicDMask(const MCInst &Inst);
1841 bool validateMIMGGatherDMask(const MCInst &Inst);
1842 bool validateMovrels(const MCInst &Inst, const OperandVector &Operands);
1843 bool validateMIMGDataSize(const MCInst &Inst, SMLoc IDLoc);
1844 bool validateMIMGAddrSize(const MCInst &Inst, SMLoc IDLoc);
1845 bool validateMIMGD16(const MCInst &Inst);
1846 bool validateMIMGDim(const MCInst &Inst, const OperandVector &Operands);
1847 bool validateTensorR128(const MCInst &Inst);
1848 bool validateMIMGMSAA(const MCInst &Inst);
1849 bool validateOpSel(const MCInst &Inst);
1850 bool validateTrue16OpSel(const MCInst &Inst);
1851 bool validateNeg(const MCInst &Inst, AMDGPU::OpName OpName);
1852 bool validateDPP(const MCInst &Inst, const OperandVector &Operands);
1853 bool validateVccOperand(MCRegister Reg) const;
1854 bool validateVOPLiteral(const MCInst &Inst, const OperandVector &Operands);
1855 bool validateMAIAccWrite(const MCInst &Inst, const OperandVector &Operands);
1856 bool validateMAISrc2(const MCInst &Inst, const OperandVector &Operands);
1857 bool validateMFMA(const MCInst &Inst, const OperandVector &Operands);
1858 bool validateAGPRLdSt(const MCInst &Inst) const;
1859 bool validateVGPRAlign(const MCInst &Inst) const;
1860 bool validateBLGP(const MCInst &Inst, const OperandVector &Operands);
1861 bool validateDS(const MCInst &Inst, const OperandVector &Operands);
1862 bool validateGWS(const MCInst &Inst, const OperandVector &Operands);
1863 bool validateDivScale(const MCInst &Inst);
1864 bool validateWaitCnt(const MCInst &Inst, const OperandVector &Operands);
1865 bool validateCoherencyBits(const MCInst &Inst, const OperandVector &Operands,
1866 SMLoc IDLoc);
1867 bool validateTHAndScopeBits(const MCInst &Inst, const OperandVector &Operands,
1868 const unsigned CPol);
1869 bool validateTFE(const MCInst &Inst, const OperandVector &Operands);
1870 bool validateLdsDirect(const MCInst &Inst, const OperandVector &Operands);
1871 bool validateWMMA(const MCInst &Inst, const OperandVector &Operands);
1872 bool validateMonitorSleep(const MCInst &Inst, const OperandVector &Operands);
1873 bool validateClusterBarrierIsFirst(const MCInst &Inst,
1874 const OperandVector &Operands);
1875 unsigned getConstantBusLimit(unsigned Opcode) const;
1876 bool usesConstantBus(const MCInst &Inst, unsigned OpIdx);
1877 bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
1878 MCRegister findImplicitSGPRReadInVOP(const MCInst &Inst) const;
1879
1880 bool isSupportedMnemo(StringRef Mnemo, const FeatureBitset &FBS);
1881 bool isSupportedMnemo(StringRef Mnemo, const FeatureBitset &FBS,
1882 ArrayRef<unsigned> Variants);
1883 bool checkUnsupportedInstruction(StringRef Name, SMLoc IDLoc);
1884
1885 bool isId(const StringRef Id) const;
1886 bool isId(const AsmToken &Token, const StringRef Id) const;
1887 bool isToken(const AsmToken::TokenKind Kind) const;
1888 StringRef getId() const;
1889 bool trySkipId(const StringRef Id);
1890 bool trySkipId(const StringRef Pref, const StringRef Id);
1891 bool trySkipId(const StringRef Id, const AsmToken::TokenKind Kind);
1892 bool trySkipToken(const AsmToken::TokenKind Kind);
1893 bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg);
1894 bool parseString(StringRef &Val,
1895 const StringRef ErrMsg = "expected a string");
1896 bool parseId(StringRef &Val, const StringRef ErrMsg = "");
1897
1898 void peekTokens(MutableArrayRef<AsmToken> Tokens);
1899 AsmToken::TokenKind getTokenKind() const;
1900 bool parseExpr(int64_t &Imm, StringRef Expected = "");
1902 StringRef getTokenStr() const;
1903 AsmToken peekToken(bool ShouldSkipSpace = true);
1904 AsmToken getToken() const;
1905 SMLoc getLoc() const;
1906 void lex();
1907
1908public:
1909 void onBeginOfFile() override;
1910 /// Emit the deferred leading .amdgcn_target directive if it has not been
1911 /// emitted yet. Called before emitting the first instruction or kernel
1912 /// descriptor.
1913 void emitTargetDirective();
1914 bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
1915
1916 ParseStatus parseCustomOperand(OperandVector &Operands, unsigned MCK);
1917
1918 ParseStatus parseExpTgt(OperandVector &Operands);
1919 ParseStatus parseSendMsg(OperandVector &Operands);
1920 ParseStatus parseWaitEvent(OperandVector &Operands);
1921 ParseStatus parseInterpSlot(OperandVector &Operands);
1922 ParseStatus parseInterpAttr(OperandVector &Operands);
1923 ParseStatus parseSOPPBrTarget(OperandVector &Operands);
1924 ParseStatus parseBoolReg(OperandVector &Operands);
1925
1926 bool parseSwizzleOperand(int64_t &Op, const unsigned MinVal,
1927 const unsigned MaxVal, const Twine &ErrMsg,
1928 SMLoc &Loc);
1929 bool parseSwizzleOperands(const unsigned OpNum, int64_t *Op,
1930 const unsigned MinVal, const unsigned MaxVal,
1931 const StringRef ErrMsg);
1932 ParseStatus parseSwizzle(OperandVector &Operands);
1933 bool parseSwizzleOffset(int64_t &Imm);
1934 bool parseSwizzleMacro(int64_t &Imm);
1935 bool parseSwizzleQuadPerm(int64_t &Imm);
1936 bool parseSwizzleBitmaskPerm(int64_t &Imm);
1937 bool parseSwizzleBroadcast(int64_t &Imm);
1938 bool parseSwizzleSwap(int64_t &Imm);
1939 bool parseSwizzleReverse(int64_t &Imm);
1940 bool parseSwizzleFFT(int64_t &Imm);
1941 bool parseSwizzleRotate(int64_t &Imm);
1942
1943 ParseStatus parseGPRIdxMode(OperandVector &Operands);
1944 int64_t parseGPRIdxMacro();
1945
1946 void cvtMubuf(MCInst &Inst, const OperandVector &Operands) {
1947 cvtMubufImpl(Inst, Operands, false);
1948 }
1949 void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) {
1950 cvtMubufImpl(Inst, Operands, true);
1951 }
1952
1953 ParseStatus parseOModSI(OperandVector &Operands);
1954
1955 void cvtVOP3(MCInst &Inst, const OperandVector &Operands,
1956 OptionalImmIndexMap &OptionalIdx);
1957 void cvtScaledMFMA(MCInst &Inst, const OperandVector &Operands);
1958 void cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands);
1959 void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
1960 void cvtVOP3P(MCInst &Inst, const OperandVector &Operands);
1961 void cvtSWMMAC(MCInst &Inst, const OperandVector &Operands);
1962
1963 void cvtVOPD(MCInst &Inst, const OperandVector &Operands);
1964 void cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands,
1965 OptionalImmIndexMap &OptionalIdx);
1966 void cvtVOP3P(MCInst &Inst, const OperandVector &Operands,
1967 OptionalImmIndexMap &OptionalIdx);
1968
1969 void cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands);
1970 void cvtVINTERP(MCInst &Inst, const OperandVector &Operands);
1971 void cvtOpSelHelper(MCInst &Inst, unsigned OpSel);
1972
1973 bool parseDimId(unsigned &Encoding);
1974 ParseStatus parseDim(OperandVector &Operands);
1975 bool convertDppBoundCtrl(int64_t &BoundCtrl);
1976 ParseStatus parseDPP8(OperandVector &Operands);
1977 ParseStatus parseDPPCtrl(OperandVector &Operands);
1978 bool isSupportedDPPCtrl(StringRef Ctrl, const OperandVector &Operands);
1979 int64_t parseDPPCtrlSel(StringRef Ctrl);
1980 int64_t parseDPPCtrlPerm();
1981 void cvtDPP(MCInst &Inst, const OperandVector &Operands, bool IsDPP8 = false);
1982 void cvtDPP8(MCInst &Inst, const OperandVector &Operands) {
1983 cvtDPP(Inst, Operands, true);
1984 }
1985 void cvtVOP3DPP(MCInst &Inst, const OperandVector &Operands,
1986 bool IsDPP8 = false);
1987 void cvtVOP3DPP8(MCInst &Inst, const OperandVector &Operands) {
1988 cvtVOP3DPP(Inst, Operands, true);
1989 }
1990
1991 ParseStatus parseSDWASel(OperandVector &Operands, StringRef Prefix,
1992 AMDGPUOperand::ImmTy Type);
1993 ParseStatus parseSDWADstUnused(OperandVector &Operands);
1994 void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands);
1995 void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands);
1996 void cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands);
1997 void cvtSdwaVOP2e(MCInst &Inst, const OperandVector &Operands);
1998 void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands);
1999
2000 enum class SDWAInstType : unsigned { VOP1 = 0, VOP2 = 1, VOPC = 2 };
2001
2002 void cvtSDWA(MCInst &Inst, const OperandVector &Operands,
2003 SDWAInstType BasicInstType, bool SkipDstVcc = false,
2004 bool SkipSrcVcc = false);
2005
2006 ParseStatus parseEndpgm(OperandVector &Operands);
2007
2008 ParseStatus parseVOPD(OperandVector &Operands);
2009};
2010
2011} // end anonymous namespace
2012
2013// May be called with integer type with equivalent bitwidth.
2014static const fltSemantics *getFltSemantics(unsigned Size) {
2015 switch (Size) {
2016 case 4:
2017 return &APFloat::IEEEsingle();
2018 case 8:
2019 return &APFloat::IEEEdouble();
2020 case 2:
2021 return &APFloat::IEEEhalf();
2022 default:
2023 llvm_unreachable("unsupported fp type");
2024 }
2025}
2026
2028 return getFltSemantics(VT.getScalarSizeInBits() / 8);
2029}
2030
2032 switch (OperandType) {
2033 // When floating-point immediate is used as operand of type i16, the 32-bit
2034 // representation of the constant truncated to the 16 LSBs should be used.
2049 return &APFloat::IEEEsingle();
2058 return &APFloat::IEEEdouble();
2067 return &APFloat::IEEEhalf();
2072 return &APFloat::BFloat();
2073 default:
2074 llvm_unreachable("unsupported fp type");
2075 }
2076}
2077
2078//===----------------------------------------------------------------------===//
2079// Operand
2080//===----------------------------------------------------------------------===//
2081
2082static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) {
2083 bool Lost;
2084
2085 // Convert literal to single precision
2086 APFloat::opStatus Status = FPLiteral.convert(
2088 // We allow precision lost but not overflow or underflow
2089 if (Status != APFloat::opOK && Lost &&
2090 ((Status & APFloat::opOverflow) != 0 ||
2091 (Status & APFloat::opUnderflow) != 0)) {
2092 return false;
2093 }
2094
2095 return true;
2096}
2097
2098static bool isSafeTruncation(int64_t Val, unsigned Size) {
2099 return isUIntN(Size, Val) || isIntN(Size, Val);
2100}
2101
2102static bool isInlineableLiteralOp16(int64_t Val, MVT VT, bool HasInv2Pi) {
2103 if (VT.getScalarType() == MVT::i16)
2104 return isInlinableLiteral32(Val, HasInv2Pi);
2105
2106 if (VT.getScalarType() == MVT::f16)
2107 return AMDGPU::isInlinableLiteralFP16(Val, HasInv2Pi);
2108
2109 assert(VT.getScalarType() == MVT::bf16);
2110
2111 return AMDGPU::isInlinableLiteralBF16(Val, HasInv2Pi);
2112}
2113
2114bool AMDGPUOperand::isInlinableImm(MVT type) const {
2115
2116 // This is a hack to enable named inline values like
2117 // shared_base with both 32-bit and 64-bit operands.
2118 // Note that these values are defined as
2119 // 32-bit operands only.
2120 if (isInlineValue()) {
2121 return true;
2122 }
2123
2124 if (!isImmTy(ImmTyNone)) {
2125 // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
2126 return false;
2127 }
2128
2129 if (getModifiers().Lit != LitModifier::None)
2130 return false;
2131
2132 // TODO: We should avoid using host float here. It would be better to
2133 // check the float bit values which is what a few other places do.
2134 // We've had bot failures before due to weird NaN support on mips hosts.
2135
2136 APInt Literal(64, Imm.Val);
2137
2138 if (Imm.IsFPImm) { // We got fp literal token
2139 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
2141 AsmParser->hasInv2PiInlineImm());
2142 }
2143
2144 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
2145 if (!canLosslesslyConvertToFPType(FPLiteral, type))
2146 return false;
2147
2148 if (type.getScalarSizeInBits() == 16) {
2149 bool Lost = false;
2150 switch (type.getScalarType().SimpleTy) {
2151 default:
2152 llvm_unreachable("unknown 16-bit type");
2153 case MVT::bf16:
2154 FPLiteral.convert(APFloatBase::BFloat(), APFloat::rmNearestTiesToEven,
2155 &Lost);
2156 break;
2157 case MVT::f16:
2158 FPLiteral.convert(APFloatBase::IEEEhalf(), APFloat::rmNearestTiesToEven,
2159 &Lost);
2160 break;
2161 case MVT::i16:
2162 FPLiteral.convert(APFloatBase::IEEEsingle(),
2163 APFloat::rmNearestTiesToEven, &Lost);
2164 break;
2165 }
2166 // We need to use 32-bit representation here because when a floating-point
2167 // inline constant is used as an i16 operand, its 32-bit representation
2168 // representation will be used. We will need the 32-bit value to check if
2169 // it is FP inline constant.
2170 uint32_t ImmVal = FPLiteral.bitcastToAPInt().getZExtValue();
2171 return isInlineableLiteralOp16(ImmVal, type,
2172 AsmParser->hasInv2PiInlineImm());
2173 }
2174
2175 // Check if single precision literal is inlinable
2177 static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
2178 AsmParser->hasInv2PiInlineImm());
2179 }
2180
2181 // We got int literal token.
2182 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
2184 AsmParser->hasInv2PiInlineImm());
2185 }
2186
2187 if (!isSafeTruncation(Imm.Val, type.getScalarSizeInBits())) {
2188 return false;
2189 }
2190
2191 if (type.getScalarSizeInBits() == 16) {
2193 static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()), type,
2194 AsmParser->hasInv2PiInlineImm());
2195 }
2196
2198 static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()),
2199 AsmParser->hasInv2PiInlineImm());
2200}
2201
2202bool AMDGPUOperand::isLiteralImm(MVT type) const {
2203 // Check that this immediate can be added as literal
2204 if (!isImmTy(ImmTyNone)) {
2205 return false;
2206 }
2207
2208 bool Allow64Bit =
2209 (type == MVT::i64 || type == MVT::f64) && AsmParser->has64BitLiterals();
2210
2211 if (!Imm.IsFPImm) {
2212 // We got int literal token.
2213
2214 if (type == MVT::f64 && hasFPModifiers()) {
2215 // Cannot apply fp modifiers to int literals preserving the same semantics
2216 // for VOP1/2/C and VOP3 because of integer truncation. To avoid
2217 // ambiguity, disable these cases.
2218 return false;
2219 }
2220
2221 unsigned Size = type.getSizeInBits();
2222 if (Size == 64) {
2223 if (Allow64Bit && !AMDGPU::isValid32BitLiteral(Imm.Val, false))
2224 return true;
2225 Size = 32;
2226 }
2227
2228 // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP
2229 // types.
2230 return isSafeTruncation(Imm.Val, Size);
2231 }
2232
2233 // We got fp literal token
2234 if (type == MVT::f64) { // Expected 64-bit fp operand
2235 // We would set low 64-bits of literal to zeroes but we accept this literals
2236 return true;
2237 }
2238
2239 if (type == MVT::i64) { // Expected 64-bit int operand
2240 // We don't allow fp literals in 64-bit integer instructions. It is
2241 // unclear how we should encode them.
2242 return false;
2243 }
2244
2245 // We allow fp literals with f16x2 operands assuming that the specified
2246 // literal goes into the lower half and the upper half is zero. We also
2247 // require that the literal may be losslessly converted to f16.
2248 //
2249 // For i16x2 operands, we assume that the specified literal is encoded as a
2250 // single-precision float. This is pretty odd, but it matches SP3 and what
2251 // happens in hardware.
2252 MVT ExpectedType = (type == MVT::v2f16) ? MVT::f16
2253 : (type == MVT::v2i16) ? MVT::f32
2254 : (type == MVT::v2f32) ? MVT::f32
2255 : type;
2256
2257 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
2258 return canLosslesslyConvertToFPType(FPLiteral, ExpectedType);
2259}
2260
2261bool AMDGPUOperand::isRegClass(unsigned RCID) const {
2262 return isRegKind() &&
2263 AsmParser->getMRI()->getRegClass(RCID).contains(getReg());
2264}
2265
2266bool AMDGPUOperand::isVRegWithInputMods() const {
2267 return isRegClass(AMDGPU::VGPR_32RegClassID) ||
2268 // GFX90A allows DPP on 64-bit operands.
2269 (isRegClass(AMDGPU::VReg_64RegClassID) &&
2270 AsmParser->getFeatureBits()[AMDGPU::FeatureDPALU_DPP]);
2271}
2272
2273template <bool IsFake16>
2274bool AMDGPUOperand::isT16_Lo128VRegWithInputMods() const {
2275 return isRegClass(IsFake16 ? AMDGPU::VGPR_32_Lo128RegClassID
2276 : AMDGPU::VGPR_16_Lo128RegClassID);
2277}
2278
2279template <bool IsFake16> bool AMDGPUOperand::isT16VRegWithInputMods() const {
2280 return isRegClass(IsFake16 ? AMDGPU::VGPR_32RegClassID
2281 : AMDGPU::VGPR_16RegClassID);
2282}
2283
2284bool AMDGPUOperand::isSDWAOperand(MVT type) const {
2285 if (AsmParser->isVI())
2286 return isVReg32();
2287 if (AsmParser->isGFX9Plus())
2288 return isRegClass(AMDGPU::VS_32RegClassID) || isInlinableImm(type);
2289 return false;
2290}
2291
2292bool AMDGPUOperand::isSDWAFP16Operand() const {
2293 return isSDWAOperand(MVT::f16);
2294}
2295
2296bool AMDGPUOperand::isSDWAFP32Operand() const {
2297 return isSDWAOperand(MVT::f32);
2298}
2299
2300bool AMDGPUOperand::isSDWAInt16Operand() const {
2301 return isSDWAOperand(MVT::i16);
2302}
2303
2304bool AMDGPUOperand::isSDWAInt32Operand() const {
2305 return isSDWAOperand(MVT::i32);
2306}
2307
2308bool AMDGPUOperand::isBoolReg() const {
2309 return isReg() && ((AsmParser->isWave64() && isSCSrc_b64()) ||
2310 (AsmParser->isWave32() && isSCSrc_b32()));
2311}
2312
2313uint64_t AMDGPUOperand::applyInputFPModifiers(uint64_t Val,
2314 unsigned Size) const {
2315 assert(isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
2316 assert(Size == 2 || Size == 4 || Size == 8);
2317
2318 const uint64_t FpSignMask = (1ULL << (Size * 8 - 1));
2319
2320 if (Imm.Mods.Abs) {
2321 Val &= ~FpSignMask;
2322 }
2323 if (Imm.Mods.Neg) {
2324 Val ^= FpSignMask;
2325 }
2326
2327 return Val;
2328}
2329
2330void AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N,
2331 bool ApplyModifiers) const {
2332 MCOpIdx = Inst.getNumOperands();
2333
2334 if (isExpr()) {
2336 return;
2337 }
2338
2339 if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()),
2340 Inst.getNumOperands())) {
2341 addLiteralImmOperand(Inst, Imm.Val,
2342 ApplyModifiers & isImmTy(ImmTyNone) &&
2343 Imm.Mods.hasFPModifiers());
2344 } else {
2345 assert(!isImmTy(ImmTyNone) || !hasModifiers());
2347 }
2348}
2349
2350void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val,
2351 bool ApplyModifiers) const {
2352 const auto &InstDesc = AsmParser->getMII()->get(Inst.getOpcode());
2353 auto OpNum = Inst.getNumOperands();
2354 // Check that this operand accepts literals
2355 assert(AMDGPU::isSISrcOperand(InstDesc, OpNum));
2356
2357 if (ApplyModifiers) {
2358 assert(AMDGPU::isSISrcFPOperand(InstDesc, OpNum));
2359 const unsigned Size =
2360 Imm.IsFPImm ? sizeof(double) : getOperandSize(InstDesc, OpNum);
2361 Val = applyInputFPModifiers(Val, Size);
2362 }
2363
2364 APInt Literal(64, Val);
2365 uint8_t OpTy = InstDesc.operands()[OpNum].OperandType;
2366
2367 bool CanUse64BitLiterals =
2368 AsmParser->has64BitLiterals() && !SIInstrFlags::isVOP3Like(InstDesc);
2369 LitModifier Lit = getModifiers().Lit;
2370 MCContext &Ctx = AsmParser->getContext();
2371
2372 if (Imm.IsFPImm) { // We got fp literal token
2373 switch (OpTy) {
2381 if (Lit == LitModifier::None &&
2383 AsmParser->hasInv2PiInlineImm())) {
2384 Inst.addOperand(MCOperand::createImm(Literal.getZExtValue()));
2385 return;
2386 }
2387
2388 // Non-inlineable
2389 if (AMDGPU::isSISrcFPOperand(InstDesc,
2390 OpNum)) { // Expected 64-bit fp operand
2391 bool HasMandatoryLiteral =
2392 AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::imm);
2393 // For fp operands we check if low 32 bits are zeros
2394 if (Literal.getLoBits(32) != 0 &&
2395 (InstDesc.getSize() != 4 || !AsmParser->has64BitLiterals()) &&
2396 !HasMandatoryLiteral) {
2397 const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(
2398 Inst.getLoc(),
2399 "Can't encode literal as exact 64-bit floating-point operand. "
2400 "Low 32-bits will be set to zero");
2401 Val &= 0xffffffff00000000u;
2402 }
2403
2404 if ((OpTy == AMDGPU::OPERAND_REG_IMM_FP64 ||
2407 if (CanUse64BitLiterals && Lit == LitModifier::None &&
2408 (isInt<32>(Val) || isUInt<32>(Val))) {
2409 // The floating-point operand will be verbalized as an
2410 // integer one. If that integer happens to fit 32 bits, on
2411 // re-assembling it will be intepreted as the high half of
2412 // the actual value, so we have to wrap it into lit64().
2413 Lit = LitModifier::Lit64;
2414 } else if (Lit == LitModifier::Lit) {
2415 // For FP64 operands lit() specifies the high half of the value.
2416 Val = Hi_32(Val);
2417 }
2418 }
2419 break;
2420 }
2421
2422 // We don't allow fp literals in 64-bit integer instructions. It is
2423 // unclear how we should encode them. This case should be checked earlier
2424 // in predicate methods (isLiteralImm())
2425 llvm_unreachable("fp literal in 64-bit integer instruction.");
2426
2428 if (CanUse64BitLiterals && Lit == LitModifier::None &&
2429 (isInt<32>(Val) || isUInt<32>(Val)))
2430 Lit = LitModifier::Lit64;
2431 break;
2432
2437 if (Lit == LitModifier::None && AsmParser->hasInv2PiInlineImm() &&
2438 Literal == 0x3fc45f306725feed) {
2439 // This is the 1/(2*pi) which is going to be truncated to bf16 with the
2440 // loss of precision. The constant represents ideomatic fp32 value of
2441 // 1/(2*pi) = 0.15915494 since bf16 is in fact fp32 with cleared low 16
2442 // bits. Prevent rounding below.
2443 Inst.addOperand(MCOperand::createImm(0x3e22));
2444 return;
2445 }
2446 [[fallthrough]];
2447
2470 bool lost;
2471 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
2472 // Convert literal to single precision
2473 FPLiteral.convert(*getOpFltSemantics(OpTy), APFloat::rmNearestTiesToEven,
2474 &lost);
2475 // We allow precision lost but not overflow or underflow. This should be
2476 // checked earlier in isLiteralImm()
2477
2478 Val = FPLiteral.bitcastToAPInt().getZExtValue();
2479 break;
2480 }
2481 default:
2482 llvm_unreachable("invalid operand size");
2483 }
2484
2485 if (Lit != LitModifier::None) {
2486 Inst.addOperand(
2488 } else {
2490 }
2491 return;
2492 }
2493
2494 // We got int literal token.
2495 // Only sign extend inline immediates.
2496 switch (OpTy) {
2511 break;
2512
2516 if (Lit == LitModifier::None &&
2517 AMDGPU::isInlinableLiteral64(Val, AsmParser->hasInv2PiInlineImm())) {
2519 return;
2520 }
2521
2522 // When the 32 MSBs are not zero (effectively means it can't be safely
2523 // truncated to uint32_t), if the target doesn't support 64-bit literals, or
2524 // the lit modifier is explicitly used, we need to truncate it to the 32
2525 // LSBs.
2526 if (!AsmParser->has64BitLiterals() || Lit == LitModifier::Lit)
2527 Val = Lo_32(Val);
2528 break;
2529
2534 if (Lit == LitModifier::None &&
2535 AMDGPU::isInlinableLiteral64(Val, AsmParser->hasInv2PiInlineImm())) {
2537 return;
2538 }
2539
2540 // If the target doesn't support 64-bit literals, we need to use the
2541 // constant as the high 32 MSBs of a double-precision floating point value.
2542 if (!AsmParser->has64BitLiterals()) {
2543 Val = static_cast<uint64_t>(Val) << 32;
2544 } else {
2545 // Now the target does support 64-bit literals, there are two cases
2546 // where we still want to use src_literal encoding:
2547 // 1) explicitly forced by using lit modifier;
2548 // 2) the value is a valid 32-bit representation (signed or unsigned),
2549 // meanwhile not forced by lit64 modifier.
2550 if (Lit == LitModifier::Lit ||
2551 (Lit != LitModifier::Lit64 && (isInt<32>(Val) || isUInt<32>(Val))))
2552 Val = static_cast<uint64_t>(Val) << 32;
2553 }
2554
2555 // For FP64 operands lit() specifies the high half of the value.
2556 if (Lit == LitModifier::Lit)
2557 Val = Hi_32(Val);
2558 break;
2559
2572 break;
2573
2575 if ((isInt<32>(Val) || isUInt<32>(Val)) && Lit != LitModifier::Lit64)
2576 Val <<= 32;
2577 break;
2578
2579 default:
2580 llvm_unreachable("invalid operand type");
2581 }
2582
2583 if (Lit != LitModifier::None) {
2584 Inst.addOperand(
2586 } else {
2588 }
2589}
2590
2591void AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const {
2592 MCOpIdx = Inst.getNumOperands();
2593 Inst.addOperand(
2594 MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI())));
2595}
2596
2597bool AMDGPUOperand::isInlineValue() const {
2598 return isRegKind() && ::isInlineValue(getReg());
2599}
2600
2601//===----------------------------------------------------------------------===//
2602// AsmParser
2603//===----------------------------------------------------------------------===//
2604
2605void AMDGPUAsmParser::createConstantSymbol(StringRef Id, int64_t Val) {
2606 // TODO: make those pre-defined variables read-only.
2607 // Currently there is none suitable machinery in the core llvm-mc for this.
2608 // MCSymbol::isRedefinable is intended for another purpose, and
2609 // AsmParser::parseDirectiveSet() cannot be specialized for specific target.
2610 MCContext &Ctx = getContext();
2611 MCSymbol *Sym = Ctx.getOrCreateSymbol(Id);
2613}
2614
2615static int getRegClass(RegisterKind Is, unsigned RegWidth) {
2616 if (Is == IS_VGPR) {
2617 switch (RegWidth) {
2618 default:
2619 return -1;
2620 case 32:
2621 return AMDGPU::VGPR_32RegClassID;
2622 case 64:
2623 return AMDGPU::VReg_64RegClassID;
2624 case 96:
2625 return AMDGPU::VReg_96RegClassID;
2626 case 128:
2627 return AMDGPU::VReg_128RegClassID;
2628 case 160:
2629 return AMDGPU::VReg_160RegClassID;
2630 case 192:
2631 return AMDGPU::VReg_192RegClassID;
2632 case 224:
2633 return AMDGPU::VReg_224RegClassID;
2634 case 256:
2635 return AMDGPU::VReg_256RegClassID;
2636 case 288:
2637 return AMDGPU::VReg_288RegClassID;
2638 case 320:
2639 return AMDGPU::VReg_320RegClassID;
2640 case 352:
2641 return AMDGPU::VReg_352RegClassID;
2642 case 384:
2643 return AMDGPU::VReg_384RegClassID;
2644 case 512:
2645 return AMDGPU::VReg_512RegClassID;
2646 case 1024:
2647 return AMDGPU::VReg_1024RegClassID;
2648 }
2649 } else if (Is == IS_TTMP) {
2650 switch (RegWidth) {
2651 default:
2652 return -1;
2653 case 32:
2654 return AMDGPU::TTMP_32RegClassID;
2655 case 64:
2656 return AMDGPU::TTMP_64RegClassID;
2657 case 128:
2658 return AMDGPU::TTMP_128RegClassID;
2659 case 256:
2660 return AMDGPU::TTMP_256RegClassID;
2661 case 512:
2662 return AMDGPU::TTMP_512RegClassID;
2663 }
2664 } else if (Is == IS_SGPR) {
2665 switch (RegWidth) {
2666 default:
2667 return -1;
2668 case 32:
2669 return AMDGPU::SGPR_32RegClassID;
2670 case 64:
2671 return AMDGPU::SGPR_64RegClassID;
2672 case 96:
2673 return AMDGPU::SGPR_96RegClassID;
2674 case 128:
2675 return AMDGPU::SGPR_128RegClassID;
2676 case 160:
2677 return AMDGPU::SGPR_160RegClassID;
2678 case 192:
2679 return AMDGPU::SGPR_192RegClassID;
2680 case 224:
2681 return AMDGPU::SGPR_224RegClassID;
2682 case 256:
2683 return AMDGPU::SGPR_256RegClassID;
2684 case 288:
2685 return AMDGPU::SGPR_288RegClassID;
2686 case 320:
2687 return AMDGPU::SGPR_320RegClassID;
2688 case 352:
2689 return AMDGPU::SGPR_352RegClassID;
2690 case 384:
2691 return AMDGPU::SGPR_384RegClassID;
2692 case 512:
2693 return AMDGPU::SGPR_512RegClassID;
2694 }
2695 } else if (Is == IS_AGPR) {
2696 switch (RegWidth) {
2697 default:
2698 return -1;
2699 case 32:
2700 return AMDGPU::AGPR_32RegClassID;
2701 case 64:
2702 return AMDGPU::AReg_64RegClassID;
2703 case 96:
2704 return AMDGPU::AReg_96RegClassID;
2705 case 128:
2706 return AMDGPU::AReg_128RegClassID;
2707 case 160:
2708 return AMDGPU::AReg_160RegClassID;
2709 case 192:
2710 return AMDGPU::AReg_192RegClassID;
2711 case 224:
2712 return AMDGPU::AReg_224RegClassID;
2713 case 256:
2714 return AMDGPU::AReg_256RegClassID;
2715 case 288:
2716 return AMDGPU::AReg_288RegClassID;
2717 case 320:
2718 return AMDGPU::AReg_320RegClassID;
2719 case 352:
2720 return AMDGPU::AReg_352RegClassID;
2721 case 384:
2722 return AMDGPU::AReg_384RegClassID;
2723 case 512:
2724 return AMDGPU::AReg_512RegClassID;
2725 case 1024:
2726 return AMDGPU::AReg_1024RegClassID;
2727 }
2728 }
2729 return -1;
2730}
2731
2734 .Case("exec", AMDGPU::EXEC)
2735 .Case("vcc", AMDGPU::VCC)
2736 .Case("flat_scratch", AMDGPU::FLAT_SCR)
2737 .Case("xnack_mask", AMDGPU::XNACK_MASK)
2738 .Case("shared_base", AMDGPU::SRC_SHARED_BASE)
2739 .Case("src_shared_base", AMDGPU::SRC_SHARED_BASE)
2740 .Case("shared_limit", AMDGPU::SRC_SHARED_LIMIT)
2741 .Case("src_shared_limit", AMDGPU::SRC_SHARED_LIMIT)
2742 .Case("private_base", AMDGPU::SRC_PRIVATE_BASE)
2743 .Case("src_private_base", AMDGPU::SRC_PRIVATE_BASE)
2744 .Case("private_limit", AMDGPU::SRC_PRIVATE_LIMIT)
2745 .Case("src_private_limit", AMDGPU::SRC_PRIVATE_LIMIT)
2746 .Case("src_flat_scratch_base_lo", AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)
2747 .Case("src_flat_scratch_base_hi", AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)
2748 .Case("pops_exiting_wave_id", AMDGPU::SRC_POPS_EXITING_WAVE_ID)
2749 .Case("src_pops_exiting_wave_id", AMDGPU::SRC_POPS_EXITING_WAVE_ID)
2750 .Case("lds_direct", AMDGPU::LDS_DIRECT)
2751 .Case("src_lds_direct", AMDGPU::LDS_DIRECT)
2752 .Case("m0", AMDGPU::M0)
2753 .Case("vccz", AMDGPU::SRC_VCCZ)
2754 .Case("src_vccz", AMDGPU::SRC_VCCZ)
2755 .Case("execz", AMDGPU::SRC_EXECZ)
2756 .Case("src_execz", AMDGPU::SRC_EXECZ)
2757 .Case("scc", AMDGPU::SRC_SCC)
2758 .Case("src_scc", AMDGPU::SRC_SCC)
2759 .Case("tba", AMDGPU::TBA)
2760 .Case("tma", AMDGPU::TMA)
2761 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
2762 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
2763 .Case("xnack_mask_lo", AMDGPU::XNACK_MASK_LO)
2764 .Case("xnack_mask_hi", AMDGPU::XNACK_MASK_HI)
2765 .Case("vcc_lo", AMDGPU::VCC_LO)
2766 .Case("vcc_hi", AMDGPU::VCC_HI)
2767 .Case("exec_lo", AMDGPU::EXEC_LO)
2768 .Case("exec_hi", AMDGPU::EXEC_HI)
2769 .Case("tma_lo", AMDGPU::TMA_LO)
2770 .Case("tma_hi", AMDGPU::TMA_HI)
2771 .Case("tba_lo", AMDGPU::TBA_LO)
2772 .Case("tba_hi", AMDGPU::TBA_HI)
2773 .Case("pc", AMDGPU::PC_REG)
2774 .Case("null", AMDGPU::SGPR_NULL)
2775 .Default(AMDGPU::NoRegister);
2776}
2777
2778bool AMDGPUAsmParser::ParseRegister(MCRegister &RegNo, SMLoc &StartLoc,
2779 SMLoc &EndLoc, bool RestoreOnFailure) {
2780 auto R = parseRegister();
2781 if (!R)
2782 return true;
2783 assert(R->isReg());
2784 RegNo = R->getReg();
2785 StartLoc = R->getStartLoc();
2786 EndLoc = R->getEndLoc();
2787 return false;
2788}
2789
2790bool AMDGPUAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
2791 SMLoc &EndLoc) {
2792 return ParseRegister(Reg, StartLoc, EndLoc, /*RestoreOnFailure=*/false);
2793}
2794
2795ParseStatus AMDGPUAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
2796 SMLoc &EndLoc) {
2797 bool Result = ParseRegister(Reg, StartLoc, EndLoc, /*RestoreOnFailure=*/true);
2798 bool PendingErrors = getParser().hasPendingError();
2799 getParser().clearPendingErrors();
2800 if (PendingErrors)
2801 return ParseStatus::Failure;
2802 if (Result)
2803 return ParseStatus::NoMatch;
2804 return ParseStatus::Success;
2805}
2806
2807bool AMDGPUAsmParser::AddNextRegisterToList(MCRegister &Reg, unsigned &RegWidth,
2808 RegisterKind RegKind,
2809 MCRegister Reg1,
2810 RegisterKind RegKind1, SMLoc Loc) {
2811 // Allow VCC_LO/HI at the end of SGPR lists.
2812 if (RegKind == IS_SGPR) {
2813 unsigned RegIdx = (Reg - AMDGPU::SGPR0) + RegWidth / 32;
2814 if ((RegIdx == 106 && Reg1 == AMDGPU::VCC_LO) ||
2815 (RegIdx == 107 && Reg1 == AMDGPU::VCC_HI)) {
2816 RegWidth += 32;
2817 return true;
2818 }
2819 }
2820
2821 if (RegKind != RegKind1) {
2822 Error(Loc, "registers in a list must be of the same kind");
2823 return false;
2824 }
2825
2826 switch (RegKind) {
2827 case IS_SPECIAL:
2828 if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) {
2829 Reg = AMDGPU::EXEC;
2830 RegWidth = 64;
2831 return true;
2832 }
2833 if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) {
2834 Reg = AMDGPU::FLAT_SCR;
2835 RegWidth = 64;
2836 return true;
2837 }
2838 if (Reg == AMDGPU::XNACK_MASK_LO && Reg1 == AMDGPU::XNACK_MASK_HI) {
2839 Reg = AMDGPU::XNACK_MASK;
2840 RegWidth = 64;
2841 return true;
2842 }
2843 if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) {
2844 Reg = AMDGPU::VCC;
2845 RegWidth = 64;
2846 return true;
2847 }
2848 if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) {
2849 Reg = AMDGPU::TBA;
2850 RegWidth = 64;
2851 return true;
2852 }
2853 if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) {
2854 Reg = AMDGPU::TMA;
2855 RegWidth = 64;
2856 return true;
2857 }
2858 Error(Loc, "register does not fit in the list");
2859 return false;
2860 case IS_VGPR:
2861 case IS_SGPR:
2862 case IS_AGPR:
2863 case IS_TTMP:
2864 if (Reg1 != Reg + RegWidth / 32) {
2865 Error(Loc, "registers in a list must have consecutive indices");
2866 return false;
2867 }
2868 RegWidth += 32;
2869 return true;
2870 default:
2871 llvm_unreachable("unexpected register kind");
2872 }
2873}
2874
2875struct RegInfo {
2877 RegisterKind Kind;
2878};
2879
2880static constexpr RegInfo RegularRegisters[] = {
2881 {{"v"}, IS_VGPR}, {{"s"}, IS_SGPR}, {{"ttmp"}, IS_TTMP},
2882 {{"acc"}, IS_AGPR}, {{"a"}, IS_AGPR},
2883};
2884
2885static bool isRegularReg(RegisterKind Kind) {
2886 return Kind == IS_VGPR || Kind == IS_SGPR || Kind == IS_TTMP ||
2887 Kind == IS_AGPR;
2888}
2889
2891 for (const RegInfo &Reg : RegularRegisters)
2892 if (Str.starts_with(Reg.Name))
2893 return &Reg;
2894 return nullptr;
2895}
2896
2897static bool getRegNum(StringRef Str, unsigned &Num) {
2898 return !Str.getAsInteger(10, Num);
2899}
2900
2901bool AMDGPUAsmParser::isRegister(const AsmToken &Token,
2902 const AsmToken &NextToken) const {
2903
2904 // A list of consecutive registers: [s0,s1,s2,s3]
2905 if (Token.is(AsmToken::LBrac))
2906 return true;
2907
2908 if (!Token.is(AsmToken::Identifier))
2909 return false;
2910
2911 // A single register like s0 or a range of registers like s[0:1]
2912
2913 StringRef Str = Token.getString();
2914 const RegInfo *Reg = getRegularRegInfo(Str);
2915 if (Reg) {
2916 StringRef RegName = Reg->Name;
2917 StringRef RegSuffix = Str.substr(RegName.size());
2918 if (!RegSuffix.empty()) {
2919 RegSuffix.consume_back(".l");
2920 RegSuffix.consume_back(".h");
2921 unsigned Num;
2922 // A single register with an index: rXX
2923 if (getRegNum(RegSuffix, Num))
2924 return true;
2925 } else {
2926 // A range of registers: r[XX:YY].
2927 if (NextToken.is(AsmToken::LBrac))
2928 return true;
2929 }
2930 }
2931
2932 return getSpecialRegForName(Str).isValid();
2933}
2934
2935bool AMDGPUAsmParser::isRegister() {
2936 return isRegister(getToken(), peekToken());
2937}
2938
2939MCRegister AMDGPUAsmParser::getRegularReg(RegisterKind RegKind, unsigned RegNum,
2940 unsigned SubReg, unsigned RegWidth,
2941 SMLoc Loc) {
2942 assert(isRegularReg(RegKind));
2943
2944 unsigned AlignSize = 1;
2945 if (RegKind == IS_SGPR || RegKind == IS_TTMP) {
2946 // SGPR and TTMP registers must be aligned.
2947 // Max required alignment is 4 dwords.
2948 AlignSize = std::min(llvm::bit_ceil(RegWidth / 32), 4u);
2949 }
2950
2951 if (RegNum % AlignSize != 0) {
2952 Error(Loc, "invalid register alignment");
2953 return MCRegister();
2954 }
2955
2956 unsigned RegIdx = RegNum / AlignSize;
2957 int RCID = getRegClass(RegKind, RegWidth);
2958 if (RCID == -1) {
2959 Error(Loc, "invalid or unsupported register size");
2960 return MCRegister();
2961 }
2962
2963 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
2964 const MCRegisterClass &RC = TRI->getRegClass(RCID);
2965 if (RegIdx >= RC.getNumRegs() || (RegKind == IS_VGPR && RegIdx > 255)) {
2966 Error(Loc, "register index is out of range");
2967 return AMDGPU::NoRegister;
2968 }
2969
2970 if (RegKind == IS_VGPR && !isGFX1250Plus() && RegIdx + RegWidth / 32 > 256) {
2971 Error(Loc, "register index is out of range");
2972 return MCRegister();
2973 }
2974
2975 MCRegister Reg = RC.getRegister(RegIdx);
2976
2977 if (SubReg) {
2978 Reg = TRI->getSubReg(Reg, SubReg);
2979
2980 // Currently all regular registers have their .l and .h subregisters, so
2981 // we should never need to generate an error here.
2982 assert(Reg && "Invalid subregister!");
2983 }
2984
2985 return Reg;
2986}
2987
2988bool AMDGPUAsmParser::ParseRegRange(unsigned &Num, unsigned &RegWidth,
2989 unsigned &SubReg) {
2990 int64_t RegLo, RegHi;
2991 if (!skipToken(AsmToken::LBrac, "missing register index"))
2992 return false;
2993
2994 SMLoc FirstIdxLoc = getLoc();
2995 SMLoc SecondIdxLoc;
2996
2997 if (!parseExpr(RegLo))
2998 return false;
2999
3000 if (trySkipToken(AsmToken::Colon)) {
3001 SecondIdxLoc = getLoc();
3002 if (!parseExpr(RegHi))
3003 return false;
3004 } else {
3005 RegHi = RegLo;
3006 }
3007
3008 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket"))
3009 return false;
3010
3011 if (!isUInt<32>(RegLo)) {
3012 Error(FirstIdxLoc, "invalid register index");
3013 return false;
3014 }
3015
3016 if (!isUInt<32>(RegHi)) {
3017 Error(SecondIdxLoc, "invalid register index");
3018 return false;
3019 }
3020
3021 if (RegLo > RegHi) {
3022 Error(FirstIdxLoc, "first register index should not exceed second index");
3023 return false;
3024 }
3025
3026 if (RegHi == RegLo) {
3027 StringRef RegSuffix = getTokenStr();
3028 if (RegSuffix == ".l") {
3029 SubReg = AMDGPU::lo16;
3030 lex();
3031 } else if (RegSuffix == ".h") {
3032 SubReg = AMDGPU::hi16;
3033 lex();
3034 }
3035 }
3036
3037 Num = static_cast<unsigned>(RegLo);
3038 RegWidth = 32 * ((RegHi - RegLo) + 1);
3039
3040 return true;
3041}
3042
3043MCRegister AMDGPUAsmParser::ParseSpecialReg(RegisterKind &RegKind,
3044 unsigned &RegNum,
3045 unsigned &RegWidth,
3046 SmallVectorImpl<AsmToken> &Tokens) {
3047 assert(isToken(AsmToken::Identifier));
3048 MCRegister Reg = getSpecialRegForName(getTokenStr());
3049 if (Reg) {
3050 RegNum = 0;
3051 RegWidth = 32;
3052 RegKind = IS_SPECIAL;
3053 Tokens.push_back(getToken());
3054 lex(); // skip register name
3055 }
3056 return Reg;
3057}
3058
3059MCRegister AMDGPUAsmParser::ParseRegularReg(RegisterKind &RegKind,
3060 unsigned &RegNum,
3061 unsigned &RegWidth,
3062 SmallVectorImpl<AsmToken> &Tokens) {
3063 assert(isToken(AsmToken::Identifier));
3064 StringRef RegName = getTokenStr();
3065 auto Loc = getLoc();
3066
3067 const RegInfo *RI = getRegularRegInfo(RegName);
3068 if (!RI) {
3069 Error(Loc, "invalid register name");
3070 return MCRegister();
3071 }
3072
3073 Tokens.push_back(getToken());
3074 lex(); // skip register name
3075
3076 RegKind = RI->Kind;
3077 StringRef RegSuffix = RegName.substr(RI->Name.size());
3078 unsigned SubReg = NoSubRegister;
3079 bool IsRange = false;
3080 if (!RegSuffix.empty()) {
3081 if (RegSuffix.consume_back(".l"))
3082 SubReg = AMDGPU::lo16;
3083 else if (RegSuffix.consume_back(".h"))
3084 SubReg = AMDGPU::hi16;
3085
3086 // Single 32-bit register: vXX.
3087 if (!getRegNum(RegSuffix, RegNum)) {
3088 Error(Loc, "invalid register index");
3089 return MCRegister();
3090 }
3091 RegWidth = 32;
3092 } else {
3093 // Range of registers: v[XX:YY]. ":YY" is optional.
3094 IsRange = true;
3095 if (!ParseRegRange(RegNum, RegWidth, SubReg))
3096 return MCRegister();
3097 }
3098
3099 // Do not allow vcc_lo/hi be referred as s106/107.
3100 MCRegister Reg = getRegularReg(RegKind, RegNum, SubReg, RegWidth, Loc);
3101 const MCRegisterInfo &TRI = *getContext().getRegisterInfo();
3102 if (RegKind == IS_SGPR && IsRange
3103 ? (TRI.isSubRegister(Reg, VCC_LO) || TRI.isSubRegister(Reg, VCC_HI))
3104 : (Reg == VCC_LO || Reg == VCC_HI)) {
3105 Error(Loc, "register index is out of range");
3106 return MCRegister();
3107 }
3108
3109 return Reg;
3110}
3111
3112MCRegister AMDGPUAsmParser::ParseRegList(RegisterKind &RegKind,
3113 unsigned &RegNum, unsigned &RegWidth,
3114 SmallVectorImpl<AsmToken> &Tokens) {
3115 MCRegister Reg;
3116 auto ListLoc = getLoc();
3117
3118 if (!skipToken(AsmToken::LBrac,
3119 "expected a register or a list of registers")) {
3120 return MCRegister();
3121 }
3122
3123 // List of consecutive registers, e.g.: [s0,s1,s2,s3]
3124
3125 auto Loc = getLoc();
3126 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth))
3127 return MCRegister();
3128 if (RegWidth != 32) {
3129 Error(Loc, "expected a single 32-bit register");
3130 return MCRegister();
3131 }
3132
3133 for (; trySkipToken(AsmToken::Comma);) {
3134 RegisterKind NextRegKind;
3135 MCRegister NextReg;
3136 unsigned NextRegNum, NextRegWidth;
3137 Loc = getLoc();
3138
3139 if (!ParseAMDGPURegister(NextRegKind, NextReg, NextRegNum, NextRegWidth,
3140 Tokens)) {
3141 return MCRegister();
3142 }
3143 if (NextRegWidth != 32) {
3144 Error(Loc, "expected a single 32-bit register");
3145 return MCRegister();
3146 }
3147 if (!AddNextRegisterToList(Reg, RegWidth, RegKind, NextReg, NextRegKind,
3148 Loc))
3149 return MCRegister();
3150 }
3151
3152 if (!skipToken(AsmToken::RBrac,
3153 "expected a comma or a closing square bracket")) {
3154 return MCRegister();
3155 }
3156
3157 if (isRegularReg(RegKind))
3158 Reg = getRegularReg(RegKind, RegNum, NoSubRegister, RegWidth, ListLoc);
3159
3160 return Reg;
3161}
3162
3163bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind,
3164 MCRegister &Reg, unsigned &RegNum,
3165 unsigned &RegWidth,
3166 SmallVectorImpl<AsmToken> &Tokens) {
3167 auto Loc = getLoc();
3168 Reg = MCRegister();
3169
3170 if (isToken(AsmToken::Identifier)) {
3171 Reg = ParseSpecialReg(RegKind, RegNum, RegWidth, Tokens);
3172 if (!Reg)
3173 Reg = ParseRegularReg(RegKind, RegNum, RegWidth, Tokens);
3174 } else {
3175 Reg = ParseRegList(RegKind, RegNum, RegWidth, Tokens);
3176 }
3177
3178 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
3179 if (!Reg) {
3180 assert(Parser.hasPendingError());
3181 return false;
3182 }
3183
3184 if (!subtargetHasRegister(*TRI, Reg)) {
3185 if (Reg == AMDGPU::SGPR_NULL) {
3186 Error(Loc, "'null' operand is not supported on this GPU");
3187 } else {
3189 " register not available on this GPU");
3190 }
3191 return false;
3192 }
3193
3194 return true;
3195}
3196
3197bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind,
3198 MCRegister &Reg, unsigned &RegNum,
3199 unsigned &RegWidth,
3200 bool RestoreOnFailure /*=false*/) {
3201 Reg = MCRegister();
3202
3204 if (ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, Tokens)) {
3205 if (RestoreOnFailure) {
3206 while (!Tokens.empty()) {
3207 getLexer().UnLex(Tokens.pop_back_val());
3208 }
3209 }
3210 return true;
3211 }
3212 return false;
3213}
3214
3215std::optional<StringRef>
3216AMDGPUAsmParser::getGprCountSymbolName(RegisterKind RegKind) {
3217 switch (RegKind) {
3218 case IS_VGPR:
3219 return StringRef(".amdgcn.next_free_vgpr");
3220 case IS_SGPR:
3221 return StringRef(".amdgcn.next_free_sgpr");
3222 default:
3223 return std::nullopt;
3224 }
3225}
3226
3227void AMDGPUAsmParser::initializeGprCountSymbol(RegisterKind RegKind) {
3228 auto SymbolName = getGprCountSymbolName(RegKind);
3229 assert(SymbolName && "initializing invalid register kind");
3230 MCSymbol *Sym = getContext().getOrCreateSymbol(*SymbolName);
3232 Sym->setRedefinable(true);
3233}
3234
3235bool AMDGPUAsmParser::updateGprCountSymbols(RegisterKind RegKind,
3236 unsigned DwordRegIndex,
3237 unsigned RegWidth) {
3238 // Symbols are only defined for GCN targets
3239 if (ISA.Major < 6)
3240 return true;
3241
3242 auto SymbolName = getGprCountSymbolName(RegKind);
3243 if (!SymbolName)
3244 return true;
3245 MCSymbol *Sym = getContext().getOrCreateSymbol(*SymbolName);
3246
3247 int64_t NewMax = DwordRegIndex + divideCeil(RegWidth, 32) - 1;
3248 int64_t OldCount;
3249
3250 if (!Sym->isVariable())
3251 return !Error(getLoc(),
3252 ".amdgcn.next_free_{v,s}gpr symbols must be variable");
3253 if (!Sym->getVariableValue()->evaluateAsAbsolute(OldCount))
3254 return !Error(
3255 getLoc(),
3256 ".amdgcn.next_free_{v,s}gpr symbols must be absolute expressions");
3257
3258 if (OldCount <= NewMax)
3260
3261 return true;
3262}
3263
3264std::unique_ptr<AMDGPUOperand>
3265AMDGPUAsmParser::parseRegister(bool RestoreOnFailure) {
3266 const auto &Tok = getToken();
3267 SMLoc StartLoc = Tok.getLoc();
3268 SMLoc EndLoc = Tok.getEndLoc();
3269 RegisterKind RegKind;
3270 MCRegister Reg;
3271 unsigned RegNum, RegWidth;
3272
3273 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) {
3274 return nullptr;
3275 }
3276 if (isHsaAbi(getSTI())) {
3277 if (!updateGprCountSymbols(RegKind, RegNum, RegWidth))
3278 return nullptr;
3279 } else
3280 KernelScope.usesRegister(RegKind, RegNum, RegWidth);
3281 return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc);
3282}
3283
3284ParseStatus AMDGPUAsmParser::parseImm(OperandVector &Operands,
3285 bool HasSP3AbsModifier, LitModifier Lit) {
3286 // TODO: add syntactic sugar for 1/(2*PI)
3287
3288 if (isRegister() || isModifier())
3289 return ParseStatus::NoMatch;
3290
3291 if (Lit == LitModifier::None) {
3292 if (trySkipId("lit"))
3293 Lit = LitModifier::Lit;
3294 else if (trySkipId("lit64"))
3295 Lit = LitModifier::Lit64;
3296
3297 if (Lit != LitModifier::None) {
3298 if (!skipToken(AsmToken::LParen, "expected left paren after lit"))
3299 return ParseStatus::Failure;
3300 ParseStatus S = parseImm(Operands, HasSP3AbsModifier, Lit);
3301 if (S.isSuccess() &&
3302 !skipToken(AsmToken::RParen, "expected closing parentheses"))
3303 return ParseStatus::Failure;
3304 return S;
3305 }
3306 }
3307
3308 const auto &Tok = getToken();
3309 const auto &NextTok = peekToken();
3310 bool IsReal = Tok.is(AsmToken::Real);
3311 SMLoc S = getLoc();
3312 bool Negate = false;
3313
3314 if (!IsReal && Tok.is(AsmToken::Minus) && NextTok.is(AsmToken::Real)) {
3315 lex();
3316 IsReal = true;
3317 Negate = true;
3318 }
3319
3320 AMDGPUOperand::Modifiers Mods;
3321 Mods.Lit = Lit;
3322
3323 if (IsReal) {
3324 // Floating-point expressions are not supported.
3325 // Can only allow floating-point literals with an
3326 // optional sign.
3327
3328 StringRef Num = getTokenStr();
3329 lex();
3330
3331 APFloat RealVal(APFloat::IEEEdouble());
3332 auto roundMode = APFloat::rmNearestTiesToEven;
3333 if (errorToBool(RealVal.convertFromString(Num, roundMode).takeError()))
3334 return ParseStatus::Failure;
3335 if (Negate)
3336 RealVal.changeSign();
3337
3338 Operands.push_back(
3339 AMDGPUOperand::CreateImm(this, RealVal.bitcastToAPInt().getZExtValue(),
3340 S, AMDGPUOperand::ImmTyNone, true));
3341 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
3342 Op.setModifiers(Mods);
3343
3344 return ParseStatus::Success;
3345
3346 } else {
3347 int64_t IntVal;
3348 const MCExpr *Expr;
3349 SMLoc S = getLoc();
3350
3351 if (HasSP3AbsModifier) {
3352 // This is a workaround for handling expressions
3353 // as arguments of SP3 'abs' modifier, for example:
3354 // |1.0|
3355 // |-1|
3356 // |1+x|
3357 // This syntax is not compatible with syntax of standard
3358 // MC expressions (due to the trailing '|').
3359 SMLoc EndLoc;
3360 if (getParser().parsePrimaryExpr(Expr, EndLoc, nullptr))
3361 return ParseStatus::Failure;
3362 } else {
3363 if (Parser.parseExpression(Expr))
3364 return ParseStatus::Failure;
3365 }
3366
3367 if (Expr->evaluateAsAbsolute(IntVal)) {
3368 if (Lit == LitModifier::Lit && !isInt<32>(IntVal) && !isUInt<32>(IntVal))
3369 return Error(S, "literal value out of range");
3370 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
3371 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
3372 Op.setModifiers(Mods);
3373 } else {
3374 if (Lit != LitModifier::None)
3375 return ParseStatus::NoMatch;
3376 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
3377 }
3378
3379 return ParseStatus::Success;
3380 }
3381
3382 return ParseStatus::NoMatch;
3383}
3384
3385ParseStatus AMDGPUAsmParser::parseReg(OperandVector &Operands) {
3386 if (!isRegister())
3387 return ParseStatus::NoMatch;
3388
3389 if (auto R = parseRegister()) {
3390 assert(R->isReg());
3391 Operands.push_back(std::move(R));
3392 return ParseStatus::Success;
3393 }
3394 return ParseStatus::Failure;
3395}
3396
3397ParseStatus AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands,
3398 bool HasSP3AbsMod, LitModifier Lit) {
3399 ParseStatus Res = parseReg(Operands);
3400 if (!Res.isNoMatch())
3401 return Res;
3402 if (isModifier())
3403 return ParseStatus::NoMatch;
3404 return parseImm(Operands, HasSP3AbsMod, Lit);
3405}
3406
3407bool AMDGPUAsmParser::isNamedOperandModifier(const AsmToken &Token,
3408 const AsmToken &NextToken) const {
3409 if (Token.is(AsmToken::Identifier) && NextToken.is(AsmToken::LParen)) {
3410 const auto &str = Token.getString();
3411 return str == "abs" || str == "neg" || str == "sext";
3412 }
3413 return false;
3414}
3415
3416bool AMDGPUAsmParser::isOpcodeModifierWithVal(const AsmToken &Token,
3417 const AsmToken &NextToken) const {
3418 return Token.is(AsmToken::Identifier) && NextToken.is(AsmToken::Colon);
3419}
3420
3421bool AMDGPUAsmParser::isOperandModifier(const AsmToken &Token,
3422 const AsmToken &NextToken) const {
3423 return isNamedOperandModifier(Token, NextToken) || Token.is(AsmToken::Pipe);
3424}
3425
3426bool AMDGPUAsmParser::isRegOrOperandModifier(const AsmToken &Token,
3427 const AsmToken &NextToken) const {
3428 return isRegister(Token, NextToken) || isOperandModifier(Token, NextToken);
3429}
3430
3431// Check if this is an operand modifier or an opcode modifier
3432// which may look like an expression but it is not. We should
3433// avoid parsing these modifiers as expressions. Currently
3434// recognized sequences are:
3435// |...|
3436// abs(...)
3437// neg(...)
3438// sext(...)
3439// -reg
3440// -|...|
3441// -abs(...)
3442// name:...
3443//
3444bool AMDGPUAsmParser::isModifier() {
3445
3446 AsmToken Tok = getToken();
3447 AsmToken NextToken[2];
3448 peekTokens(NextToken);
3449
3450 return isOperandModifier(Tok, NextToken[0]) ||
3451 (Tok.is(AsmToken::Minus) &&
3452 isRegOrOperandModifier(NextToken[0], NextToken[1])) ||
3453 isOpcodeModifierWithVal(Tok, NextToken[0]);
3454}
3455
3456// Check if the current token is an SP3 'neg' modifier.
3457// Currently this modifier is allowed in the following context:
3458//
3459// 1. Before a register, e.g. "-v0", "-v[...]" or "-[v0,v1]".
3460// 2. Before an 'abs' modifier: -abs(...)
3461// 3. Before an SP3 'abs' modifier: -|...|
3462//
3463// In all other cases "-" is handled as a part
3464// of an expression that follows the sign.
3465//
3466// Note: When "-" is followed by an integer literal,
3467// this is interpreted as integer negation rather
3468// than a floating-point NEG modifier applied to N.
3469// Beside being contr-intuitive, such use of floating-point
3470// NEG modifier would have resulted in different meaning
3471// of integer literals used with VOP1/2/C and VOP3,
3472// for example:
3473// v_exp_f32_e32 v5, -1 // VOP1: src0 = 0xFFFFFFFF
3474// v_exp_f32_e64 v5, -1 // VOP3: src0 = 0x80000001
3475// Negative fp literals with preceding "-" are
3476// handled likewise for uniformity
3477//
3478bool AMDGPUAsmParser::parseSP3NegModifier() {
3479
3480 AsmToken NextToken[2];
3481 peekTokens(NextToken);
3482
3483 if (isToken(AsmToken::Minus) &&
3484 (isRegister(NextToken[0], NextToken[1]) ||
3485 NextToken[0].is(AsmToken::Pipe) || isId(NextToken[0], "abs"))) {
3486 lex();
3487 return true;
3488 }
3489
3490 return false;
3491}
3492
3493ParseStatus
3494AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands,
3495 bool AllowImm) {
3496 bool Neg, SP3Neg;
3497 bool Abs, SP3Abs;
3498 SMLoc Loc;
3499
3500 // Disable ambiguous constructs like '--1' etc. Should use neg(-1) instead.
3501 if (isToken(AsmToken::Minus) && peekToken().is(AsmToken::Minus))
3502 return Error(getLoc(), "invalid syntax, expected 'neg' modifier");
3503
3504 SP3Neg = parseSP3NegModifier();
3505
3506 Loc = getLoc();
3507 Neg = trySkipId("neg");
3508 if (Neg && SP3Neg)
3509 return Error(Loc, "expected register or immediate");
3510 if (Neg && !skipToken(AsmToken::LParen, "expected left paren after neg"))
3511 return ParseStatus::Failure;
3512
3513 Abs = trySkipId("abs");
3514 if (Abs && !skipToken(AsmToken::LParen, "expected left paren after abs"))
3515 return ParseStatus::Failure;
3516
3517 LitModifier Lit = LitModifier::None;
3518 if (trySkipId("lit")) {
3519 Lit = LitModifier::Lit;
3520 if (!skipToken(AsmToken::LParen, "expected left paren after lit"))
3521 return ParseStatus::Failure;
3522 } else if (trySkipId("lit64")) {
3523 Lit = LitModifier::Lit64;
3524 if (!skipToken(AsmToken::LParen, "expected left paren after lit64"))
3525 return ParseStatus::Failure;
3526 if (!has64BitLiterals())
3527 return Error(Loc, "lit64 is not supported on this GPU");
3528 }
3529
3530 Loc = getLoc();
3531 SP3Abs = trySkipToken(AsmToken::Pipe);
3532 if (Abs && SP3Abs)
3533 return Error(Loc, "expected register or immediate");
3534
3535 ParseStatus Res;
3536 if (AllowImm) {
3537 Res = parseRegOrImm(Operands, SP3Abs, Lit);
3538 } else {
3539 Res = parseReg(Operands);
3540 }
3541 if (!Res.isSuccess())
3542 return (SP3Neg || Neg || SP3Abs || Abs || Lit != LitModifier::None)
3544 : Res;
3545
3546 if (Lit != LitModifier::None && !Operands.back()->isImm())
3547 Error(Loc, "expected immediate with lit modifier");
3548
3549 if (SP3Abs && !skipToken(AsmToken::Pipe, "expected vertical bar"))
3550 return ParseStatus::Failure;
3551 if (Abs && !skipToken(AsmToken::RParen, "expected closing parentheses"))
3552 return ParseStatus::Failure;
3553 if (Neg && !skipToken(AsmToken::RParen, "expected closing parentheses"))
3554 return ParseStatus::Failure;
3555 if (Lit != LitModifier::None &&
3556 !skipToken(AsmToken::RParen, "expected closing parentheses"))
3557 return ParseStatus::Failure;
3558
3559 AMDGPUOperand::Modifiers Mods;
3560 Mods.Abs = Abs || SP3Abs;
3561 Mods.Neg = Neg || SP3Neg;
3562 Mods.Lit = Lit;
3563
3564 if (Mods.hasFPModifiers() || Lit != LitModifier::None) {
3565 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
3566 if (Op.isExpr())
3567 return Error(Op.getStartLoc(), "expected an absolute expression");
3568 Op.setModifiers(Mods);
3569 }
3570 return ParseStatus::Success;
3571}
3572
3573ParseStatus
3574AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands,
3575 bool AllowImm) {
3576 bool Sext = trySkipId("sext");
3577 if (Sext && !skipToken(AsmToken::LParen, "expected left paren after sext"))
3578 return ParseStatus::Failure;
3579
3580 ParseStatus Res;
3581 if (AllowImm) {
3582 Res = parseRegOrImm(Operands);
3583 } else {
3584 Res = parseReg(Operands);
3585 }
3586 if (!Res.isSuccess())
3587 return Sext ? ParseStatus::Failure : Res;
3588
3589 if (Sext && !skipToken(AsmToken::RParen, "expected closing parentheses"))
3590 return ParseStatus::Failure;
3591
3592 AMDGPUOperand::Modifiers Mods;
3593 Mods.Sext = Sext;
3594
3595 if (Mods.hasIntModifiers()) {
3596 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
3597 if (Op.isExpr())
3598 return Error(Op.getStartLoc(), "expected an absolute expression");
3599 Op.setModifiers(Mods);
3600 }
3601
3602 return ParseStatus::Success;
3603}
3604
3605ParseStatus AMDGPUAsmParser::parseRegWithFPInputMods(OperandVector &Operands) {
3606 return parseRegOrImmWithFPInputMods(Operands, false);
3607}
3608
3609ParseStatus AMDGPUAsmParser::parseRegWithIntInputMods(OperandVector &Operands) {
3610 return parseRegOrImmWithIntInputMods(Operands, false);
3611}
3612
3613ParseStatus AMDGPUAsmParser::parseRsrcReg(OperandVector &Operands) {
3614 // Without the marker, fall back to plain register parsing so the legacy
3615 // bare-register form (e.g. `s8`, `v8`) still assembles for indexed
3616 // buffer/image instructions.
3617 if (!trySkipId("rsrcidx"))
3618 return parseReg(Operands);
3619
3620 if (!skipToken(AsmToken::LParen, "expected left paren after rsrcidx"))
3621 return ParseStatus::Failure;
3622
3623 SMLoc RegLoc = getLoc();
3624 std::unique_ptr<AMDGPUOperand> Reg = parseRegister();
3625 if (!Reg)
3626 return ParseStatus::Failure;
3627
3628 // Enforce that the inner register is a valid index register. The matcher
3629 // predicate alone is not sufficient: if it fails, the matcher will fall back
3630 // to a non-indexed instruction variant whose resource operand happens to
3631 // accept the same register, silently dropping the `rsrcidx` intent.
3632 if (!Reg->isRsrcReg32())
3633 return Error(RegLoc, "rsrcidx operand must be a 32-bit SGPR or VGPR");
3634
3635 if (!skipToken(AsmToken::RParen, "expected closing parenthesis"))
3636 return ParseStatus::Failure;
3637
3638 Operands.push_back(std::move(Reg));
3639 return ParseStatus::Success;
3640}
3641
3642ParseStatus AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) {
3643 auto Loc = getLoc();
3644 if (trySkipId("off")) {
3645 Operands.push_back(
3646 AMDGPUOperand::CreateImm(this, 0, Loc, AMDGPUOperand::ImmTyOff, false));
3647 return ParseStatus::Success;
3648 }
3649
3650 if (!isRegister())
3651 return ParseStatus::NoMatch;
3652
3653 std::unique_ptr<AMDGPUOperand> Reg = parseRegister();
3654 if (Reg) {
3655 Operands.push_back(std::move(Reg));
3656 return ParseStatus::Success;
3657 }
3658
3659 return ParseStatus::Failure;
3660}
3661
3662unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3663 if ((getForcedEncodingSize() == 32 && SIInstrFlags::isVOP3(MII, Inst)) ||
3664 (getForcedEncodingSize() == 64 && !SIInstrFlags::isVOP3(MII, Inst)) ||
3665 (isForcedDPP() && !SIInstrFlags::isDPP(MII, Inst)) ||
3666 (isForcedSDWA() && !SIInstrFlags::isSDWA(MII, Inst)))
3667 return Match_InvalidOperand;
3668
3669 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
3670 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
3671 // v_mac_f32/16 allow only dst_sel == DWORD;
3672 auto OpNum =
3673 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::dst_sel);
3674 const auto &Op = Inst.getOperand(OpNum);
3675 if (!Op.isImm() || Op.getImm() != AMDGPU::SDWA::SdwaSel::DWORD) {
3676 return Match_InvalidOperand;
3677 }
3678 }
3679
3680 // Asm can first try to match VOPD or VOPD3. By failing early here with
3681 // Match_InvalidOperand, the parser will retry parsing as VOPD3 or VOPD.
3682 // Checking later during validateInstruction does not give a chance to retry
3683 // parsing as a different encoding.
3684 if (tryAnotherVOPDEncoding(Inst))
3685 return Match_InvalidOperand;
3686
3687 return Match_Success;
3688}
3689
3698
3699// What asm variants we should check
3700ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const {
3701 if (isForcedDPP() && isForcedVOP3()) {
3702 static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3_DPP};
3703 return ArrayRef(Variants);
3704 }
3705 if (getForcedEncodingSize() == 32) {
3706 static const unsigned Variants[] = {AMDGPUAsmVariants::DEFAULT};
3707 return ArrayRef(Variants);
3708 }
3709
3710 if (isForcedVOP3()) {
3711 static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3};
3712 return ArrayRef(Variants);
3713 }
3714
3715 if (isForcedSDWA()) {
3716 static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA,
3718 return ArrayRef(Variants);
3719 }
3720
3721 if (isForcedDPP()) {
3722 static const unsigned Variants[] = {AMDGPUAsmVariants::DPP};
3723 return ArrayRef(Variants);
3724 }
3725
3726 return getAllVariants();
3727}
3728
3729StringRef AMDGPUAsmParser::getMatchedVariantName() const {
3730 if (isForcedDPP() && isForcedVOP3())
3731 return "e64_dpp";
3732
3733 if (getForcedEncodingSize() == 32)
3734 return "e32";
3735
3736 if (isForcedVOP3())
3737 return "e64";
3738
3739 if (isForcedSDWA())
3740 return "sdwa";
3741
3742 if (isForcedDPP())
3743 return "dpp";
3744
3745 return "";
3746}
3747
3748MCRegister
3749AMDGPUAsmParser::findImplicitSGPRReadInVOP(const MCInst &Inst) const {
3750 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3751 for (MCPhysReg Reg : Desc.implicit_uses()) {
3752 switch (Reg) {
3753 case AMDGPU::FLAT_SCR:
3754 case AMDGPU::VCC:
3755 case AMDGPU::VCC_LO:
3756 case AMDGPU::VCC_HI:
3757 case AMDGPU::M0:
3758 return Reg;
3759 default:
3760 break;
3761 }
3762 }
3763 return MCRegister();
3764}
3765
3766// NB: This code is correct only when used to check constant
3767// bus limitations because GFX7 support no f16 inline constants.
3768// Note that there are no cases when a GFX7 opcode violates
3769// constant bus limitations due to the use of an f16 constant.
3770bool AMDGPUAsmParser::isInlineConstant(const MCInst &Inst,
3771 unsigned OpIdx) const {
3772 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3773
3774 if (!AMDGPU::isSISrcOperand(Desc, OpIdx) ||
3775 AMDGPU::isKImmOperand(Desc, OpIdx)) {
3776 return false;
3777 }
3778
3779 const MCOperand &MO = Inst.getOperand(OpIdx);
3780
3781 int64_t Val = MO.isImm() ? MO.getImm() : getLitValue(MO.getExpr());
3782 auto OpSize = AMDGPU::getOperandSize(Desc, OpIdx);
3783
3784 switch (OpSize) { // expected operand size
3785 case 8:
3786 return AMDGPU::isInlinableLiteral64(Val, hasInv2PiInlineImm());
3787 case 4:
3788 return AMDGPU::isInlinableLiteral32(Val, hasInv2PiInlineImm());
3789 case 2: {
3790 const unsigned OperandType = Desc.operands()[OpIdx].OperandType;
3793 return AMDGPU::isInlinableLiteralI16(Val, hasInv2PiInlineImm());
3794
3798
3802
3805
3809
3812 return AMDGPU::isInlinableLiteralFP16(Val, hasInv2PiInlineImm());
3813
3816 return AMDGPU::isInlinableLiteralBF16(Val, hasInv2PiInlineImm());
3817
3820 return false;
3821
3822 llvm_unreachable("invalid operand type");
3823 }
3824 default:
3825 llvm_unreachable("invalid operand size");
3826 }
3827}
3828
3829unsigned AMDGPUAsmParser::getConstantBusLimit(unsigned Opcode) const {
3830 if (!isGFX10Plus())
3831 return 1;
3832
3833 switch (Opcode) {
3834 // 64-bit shift instructions can use only one scalar value input
3835 case AMDGPU::V_LSHLREV_B64_e64:
3836 case AMDGPU::V_LSHLREV_B64_gfx10:
3837 case AMDGPU::V_LSHLREV_B64_e64_gfx11:
3838 case AMDGPU::V_LSHLREV_B64_e32_gfx12:
3839 case AMDGPU::V_LSHLREV_B64_e64_gfx12:
3840 case AMDGPU::V_LSHRREV_B64_e64:
3841 case AMDGPU::V_LSHRREV_B64_gfx10:
3842 case AMDGPU::V_LSHRREV_B64_e64_gfx11:
3843 case AMDGPU::V_LSHRREV_B64_e64_gfx12:
3844 case AMDGPU::V_ASHRREV_I64_e64:
3845 case AMDGPU::V_ASHRREV_I64_gfx10:
3846 case AMDGPU::V_ASHRREV_I64_e64_gfx11:
3847 case AMDGPU::V_ASHRREV_I64_e64_gfx12:
3848 case AMDGPU::V_LSHL_B64_e64:
3849 case AMDGPU::V_LSHR_B64_e64:
3850 case AMDGPU::V_ASHR_I64_e64:
3851 return 1;
3852 default:
3853 return 2;
3854 }
3855}
3856
3857constexpr unsigned MAX_SRC_OPERANDS_NUM = 6;
3859
3860// Get regular operand indices in the same order as specified
3861// in the instruction (but append mandatory literals to the end).
3863 bool AddMandatoryLiterals = false) {
3864
3865 int16_t ImmIdx =
3866 AddMandatoryLiterals ? getNamedOperandIdx(Opcode, OpName::imm) : -1;
3867
3868 if (isVOPD(Opcode)) {
3869 int16_t ImmXIdx =
3870 AddMandatoryLiterals ? getNamedOperandIdx(Opcode, OpName::immX) : -1;
3871
3872 return {getNamedOperandIdx(Opcode, OpName::src0X),
3873 getNamedOperandIdx(Opcode, OpName::vsrc1X),
3874 getNamedOperandIdx(Opcode, OpName::vsrc2X),
3875 getNamedOperandIdx(Opcode, OpName::src0Y),
3876 getNamedOperandIdx(Opcode, OpName::vsrc1Y),
3877 getNamedOperandIdx(Opcode, OpName::vsrc2Y),
3878 ImmXIdx,
3879 ImmIdx};
3880 }
3881
3882 return {getNamedOperandIdx(Opcode, OpName::src0),
3883 getNamedOperandIdx(Opcode, OpName::src1),
3884 getNamedOperandIdx(Opcode, OpName::src2), ImmIdx};
3885}
3886
3887bool AMDGPUAsmParser::usesConstantBus(const MCInst &Inst, unsigned OpIdx) {
3888 const MCOperand &MO = Inst.getOperand(OpIdx);
3889 if (MO.isImm())
3890 return !isInlineConstant(Inst, OpIdx);
3891 if (MO.isReg()) {
3892 auto Reg = MO.getReg();
3893 if (!Reg)
3894 return false;
3895 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
3896 auto PReg = mc2PseudoReg(Reg);
3897 return isSGPR(PReg, TRI) && PReg != SGPR_NULL;
3898 }
3899 return true;
3900}
3901
3902// Based on the comment for `AMDGPUInstructionSelector::selectWritelane`:
3903// Writelane is special in that it can use SGPR and M0 (which would normally
3904// count as using the constant bus twice - but in this case it is allowed since
3905// the lane selector doesn't count as a use of the constant bus). However, it is
3906// still required to abide by the 1 SGPR rule.
3907static bool checkWriteLane(const MCInst &Inst) {
3908 const unsigned Opcode = Inst.getOpcode();
3909 if (Opcode != V_WRITELANE_B32_gfx6_gfx7 && Opcode != V_WRITELANE_B32_vi)
3910 return false;
3911 const MCOperand &LaneSelOp = Inst.getOperand(2);
3912 if (!LaneSelOp.isReg())
3913 return false;
3914 auto LaneSelReg = mc2PseudoReg(LaneSelOp.getReg());
3915 return LaneSelReg == M0 || LaneSelReg == M0_gfxpre11;
3916}
3917
3918bool AMDGPUAsmParser::validateConstantBusLimitations(
3919 const MCInst &Inst, const OperandVector &Operands) {
3920 const unsigned Opcode = Inst.getOpcode();
3921 const MCInstrDesc &Desc = MII.get(Opcode);
3922 MCRegister LastSGPR;
3923 unsigned ConstantBusUseCount = 0;
3924 unsigned NumLiterals = 0;
3925 unsigned LiteralSize;
3926
3929 !SIInstrFlags::isSDWA(Desc) && !isVOPD(Opcode))
3930 return true;
3931
3932 if (checkWriteLane(Inst))
3933 return true;
3934
3935 // Check special imm operands (used by madmk, etc)
3936 if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::imm)) {
3937 ++NumLiterals;
3938 LiteralSize = 4;
3939 }
3940
3941 SmallDenseSet<MCRegister> SGPRsUsed;
3942 MCRegister SGPRUsed = findImplicitSGPRReadInVOP(Inst);
3943 if (SGPRUsed) {
3944 SGPRsUsed.insert(SGPRUsed);
3945 ++ConstantBusUseCount;
3946 }
3947
3948 OperandIndices OpIndices = getSrcOperandIndices(Opcode);
3949
3950 unsigned ConstantBusLimit = getConstantBusLimit(Opcode);
3951
3952 for (int OpIdx : OpIndices) {
3953 if (OpIdx == -1)
3954 continue;
3955
3956 const MCOperand &MO = Inst.getOperand(OpIdx);
3957 if (usesConstantBus(Inst, OpIdx)) {
3958 if (MO.isReg()) {
3959 LastSGPR = mc2PseudoReg(MO.getReg());
3960 // Pairs of registers with a partial intersections like these
3961 // s0, s[0:1]
3962 // flat_scratch_lo, flat_scratch
3963 // flat_scratch_lo, flat_scratch_hi
3964 // are theoretically valid but they are disabled anyway.
3965 // Note that this code mimics SIInstrInfo::verifyInstruction
3966 if (SGPRsUsed.insert(LastSGPR).second) {
3967 ++ConstantBusUseCount;
3968 }
3969 } else { // Expression or a literal
3970
3971 if (Desc.operands()[OpIdx].OperandType == MCOI::OPERAND_IMMEDIATE)
3972 continue; // special operand like VINTERP attr_chan
3973
3974 // An instruction may use only one literal.
3975 // This has been validated on the previous step.
3976 // See validateVOPLiteral.
3977 // This literal may be used as more than one operand.
3978 // If all these operands are of the same size,
3979 // this literal counts as one scalar value.
3980 // Otherwise it counts as 2 scalar values.
3981 // See "GFX10 Shader Programming", section 3.6.2.3.
3982
3983 unsigned Size = AMDGPU::getOperandSize(Desc, OpIdx);
3984 if (Size < 4)
3985 Size = 4;
3986
3987 if (NumLiterals == 0) {
3988 NumLiterals = 1;
3989 LiteralSize = Size;
3990 } else if (LiteralSize != Size) {
3991 NumLiterals = 2;
3992 }
3993 }
3994 }
3995
3996 if (ConstantBusUseCount + NumLiterals > ConstantBusLimit) {
3997 Error(getOperandLoc(Operands, OpIdx),
3998 "invalid operand (violates constant bus restrictions)");
3999 return false;
4000 }
4001 }
4002 return true;
4003}
4004
4005std::optional<unsigned>
4006AMDGPUAsmParser::checkVOPDRegBankConstraints(const MCInst &Inst, bool AsVOPD3) {
4007
4008 const unsigned Opcode = Inst.getOpcode();
4009 if (!isVOPD(Opcode))
4010 return {};
4011
4012 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
4013
4014 auto getVRegIdx = [&](unsigned, unsigned OperandIdx) {
4015 const MCOperand &Opr = Inst.getOperand(OperandIdx);
4016 return (Opr.isReg() && !isSGPR(mc2PseudoReg(Opr.getReg()), TRI))
4017 ? Opr.getReg()
4018 : MCRegister();
4019 };
4020
4021 // On GFX1170+ if both OpX and OpY are V_MOV_B32 then OPY uses SRC2
4022 // source-cache.
4023 bool SkipSrc =
4024 Opcode == AMDGPU::V_DUAL_MOV_B32_e32_X_MOV_B32_e32_gfx1170 ||
4025 Opcode == AMDGPU::V_DUAL_MOV_B32_e32_X_MOV_B32_e32_gfx12 ||
4026 Opcode == AMDGPU::V_DUAL_MOV_B32_e32_X_MOV_B32_e32_gfx1250 ||
4027 Opcode == AMDGPU::V_DUAL_MOV_B32_e32_X_MOV_B32_e32_gfx13 ||
4028 Opcode == AMDGPU::V_DUAL_MOV_B32_e32_X_MOV_B32_e32_e96_gfx1250 ||
4029 Opcode == AMDGPU::V_DUAL_MOV_B32_e32_X_MOV_B32_e32_e96_gfx13;
4030 bool AllowSameVGPR = isGFX12Plus();
4031
4032 if (AsVOPD3) { // Literal constants are not allowed with VOPD3.
4033 for (auto OpName : {OpName::src0X, OpName::src0Y}) {
4034 int I = getNamedOperandIdx(Opcode, OpName);
4035 const MCOperand &Op = Inst.getOperand(I);
4036 if (!Op.isImm())
4037 continue;
4038 int64_t Imm = Op.getImm();
4039 if (!AMDGPU::isInlinableLiteral32(Imm, hasInv2PiInlineImm()) &&
4040 !AMDGPU::isInlinableLiteral64(Imm, hasInv2PiInlineImm()))
4041 return (unsigned)I;
4042 }
4043
4044 for (auto OpName : {OpName::vsrc1X, OpName::vsrc1Y, OpName::vsrc2X,
4045 OpName::vsrc2Y, OpName::imm}) {
4046 int I = getNamedOperandIdx(Opcode, OpName);
4047 if (I == -1)
4048 continue;
4049 const MCOperand &Op = Inst.getOperand(I);
4050 if (Op.isImm())
4051 return (unsigned)I;
4052 }
4053 }
4054
4055 const auto &InstInfo = getVOPDInstInfo(Opcode, &MII);
4056 auto InvalidCompOprIdx = InstInfo.getInvalidCompOperandIndex(
4057 getVRegIdx, *TRI, SkipSrc, AllowSameVGPR, AsVOPD3);
4058
4059 return InvalidCompOprIdx;
4060}
4061
4062bool AMDGPUAsmParser::validateVOPD(const MCInst &Inst,
4063 const OperandVector &Operands) {
4064
4065 unsigned Opcode = Inst.getOpcode();
4066 bool AsVOPD3 = SIInstrFlags::isVOPD3(MII, Inst);
4067
4068 if (AsVOPD3) {
4069 for (const std::unique_ptr<MCParsedAsmOperand> &Operand : Operands) {
4070 AMDGPUOperand &Op = (AMDGPUOperand &)*Operand;
4071 if ((Op.isRegKind() || Op.isImmTy(AMDGPUOperand::ImmTyNone)) &&
4072 (Op.getModifiers().getFPModifiersOperand() & SISrcMods::ABS))
4073 Error(Op.getStartLoc(), "ABS not allowed in VOPD3 instructions");
4074 }
4075 }
4076
4077 auto InvalidCompOprIdx = checkVOPDRegBankConstraints(Inst, AsVOPD3);
4078 if (!InvalidCompOprIdx.has_value())
4079 return true;
4080
4081 auto CompOprIdx = *InvalidCompOprIdx;
4082 const auto &InstInfo = getVOPDInstInfo(Opcode, &MII);
4083 auto ParsedIdx =
4084 std::max(InstInfo[VOPD::X].getIndexInParsedOperands(CompOprIdx),
4085 InstInfo[VOPD::Y].getIndexInParsedOperands(CompOprIdx));
4086 assert(ParsedIdx > 0 && ParsedIdx < Operands.size());
4087
4088 auto Loc = ((AMDGPUOperand &)*Operands[ParsedIdx]).getStartLoc();
4089 if (CompOprIdx == VOPD::Component::DST) {
4090 if (AsVOPD3)
4091 Error(Loc, "dst registers must be distinct");
4092 else
4093 Error(Loc, "one dst register must be even and the other odd");
4094 } else {
4095 auto CompSrcIdx = CompOprIdx - VOPD::Component::DST_NUM;
4096 Error(Loc, Twine("src") + Twine(CompSrcIdx) +
4097 " operands must use different VGPR banks");
4098 }
4099
4100 return false;
4101}
4102
4103// \returns true if \p Inst does not satisfy VOPD constraints, but can be
4104// potentially used as VOPD3 with the same operands.
4105bool AMDGPUAsmParser::tryVOPD3(const MCInst &Inst) {
4106 // First check if it fits VOPD
4107 auto InvalidCompOprIdx = checkVOPDRegBankConstraints(Inst, false);
4108 if (!InvalidCompOprIdx.has_value())
4109 return false;
4110
4111 // Then if it fits VOPD3
4112 InvalidCompOprIdx = checkVOPDRegBankConstraints(Inst, true);
4113 if (InvalidCompOprIdx.has_value()) {
4114 // If failed operand is dst it is better to show error about VOPD3
4115 // instruction as it has more capabilities and error message will be
4116 // more informative. If the dst is not legal for VOPD3, then it is not
4117 // legal for VOPD either.
4118 if (*InvalidCompOprIdx == VOPD::Component::DST)
4119 return true;
4120
4121 // Otherwise prefer VOPD as we may find ourselves in an awkward situation
4122 // with a conflict in tied implicit src2 of fmac and no asm operand to
4123 // to point to.
4124 return false;
4125 }
4126 return true;
4127}
4128
4129// \returns true is a VOPD3 instruction can be also represented as a shorter
4130// VOPD encoding.
4131bool AMDGPUAsmParser::tryVOPD(const MCInst &Inst) {
4132 const unsigned Opcode = Inst.getOpcode();
4133 const auto &II = getVOPDInstInfo(Opcode, &MII);
4134 unsigned EncodingFamily = AMDGPU::getVOPDEncodingFamily(getSTI());
4135 if (!getCanBeVOPD(II[VOPD::X].getOpcode(), EncodingFamily, false).X ||
4136 !getCanBeVOPD(II[VOPD::Y].getOpcode(), EncodingFamily, false).Y)
4137 return false;
4138
4139 // This is an awkward exception, VOPD3 variant of V_DUAL_CNDMASK_B32 has
4140 // explicit src2 even if it is vcc_lo. If it was parsed as VOPD3 it cannot
4141 // be parsed as VOPD which does not accept src2.
4142 if (II[VOPD::X].getOpcode() == AMDGPU::V_CNDMASK_B32_e32 ||
4143 II[VOPD::Y].getOpcode() == AMDGPU::V_CNDMASK_B32_e32)
4144 return false;
4145
4146 // If any modifiers are set this cannot be VOPD.
4147 for (auto OpName : {OpName::src0X_modifiers, OpName::src0Y_modifiers,
4148 OpName::vsrc1X_modifiers, OpName::vsrc1Y_modifiers,
4149 OpName::vsrc2X_modifiers, OpName::vsrc2Y_modifiers}) {
4150 int I = getNamedOperandIdx(Opcode, OpName);
4151 if (I == -1)
4152 continue;
4153 if (Inst.getOperand(I).getImm())
4154 return false;
4155 }
4156
4157 return !tryVOPD3(Inst);
4158}
4159
4160// VOPD3 has more relaxed register constraints than VOPD. We prefer shorter VOPD
4161// form but switch to VOPD3 otherwise.
4162bool AMDGPUAsmParser::tryAnotherVOPDEncoding(const MCInst &Inst) {
4163 if (!isGFX1250Plus() || !isVOPD(Inst.getOpcode()))
4164 return false;
4165
4166 if (SIInstrFlags::isVOPD3(MII, Inst))
4167 return tryVOPD(Inst);
4168 return tryVOPD3(Inst);
4169}
4170
4171bool AMDGPUAsmParser::validateIntClampSupported(const MCInst &Inst) {
4172
4173 const unsigned Opc = Inst.getOpcode();
4174
4175 if (SIInstrFlags::hasIntClamp(MII, Inst) && !hasIntClamp()) {
4176 int ClampIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp);
4177 assert(ClampIdx != -1);
4178 return Inst.getOperand(ClampIdx).getImm() == 0;
4179 }
4180
4181 return true;
4182}
4183
4184bool AMDGPUAsmParser::validateMIMGDataSize(const MCInst &Inst, SMLoc IDLoc) {
4185
4186 const unsigned Opc = Inst.getOpcode();
4187 const MCInstrDesc &Desc = MII.get(Opc);
4188
4189 if ((SIInstrFlags::isImage(Desc)) == 0)
4190 return true;
4191
4192 int VDataIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
4193 int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask);
4194 int TFEIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::tfe);
4195
4196 if (VDataIdx == -1 && isGFX10Plus()) // no return image_sample
4197 return true;
4198
4199 if ((DMaskIdx == -1 || TFEIdx == -1) &&
4200 hasBVHRayTracingInsts()) // intersect_ray
4201 return true;
4202
4203 unsigned VDataSize = getRegOperandSize(Desc, VDataIdx);
4204 unsigned TFESize = (TFEIdx != -1 && Inst.getOperand(TFEIdx).getImm()) ? 1 : 0;
4205 unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf;
4206 if (DMask == 0)
4207 DMask = 1;
4208
4209 bool IsPackedD16 = false;
4210 unsigned DataSize = SIInstrFlags::isGather4(Desc) ? 4 : llvm::popcount(DMask);
4211 if (hasPackedD16()) {
4212 int D16Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::d16);
4213 IsPackedD16 = D16Idx >= 0;
4214 if (IsPackedD16 && Inst.getOperand(D16Idx).getImm())
4215 DataSize = (DataSize + 1) / 2;
4216 }
4217
4218 if ((VDataSize / 4) == DataSize + TFESize)
4219 return true;
4220
4221 StringRef Modifiers;
4222 if (isGFX90A())
4223 Modifiers = IsPackedD16 ? "dmask and d16" : "dmask";
4224 else
4225 Modifiers = IsPackedD16 ? "dmask, d16 and tfe" : "dmask and tfe";
4226
4227 Error(IDLoc, Twine("image data size does not match ") + Modifiers);
4228 return false;
4229}
4230
4231bool AMDGPUAsmParser::validateMIMGAddrSize(const MCInst &Inst, SMLoc IDLoc) {
4232 const unsigned Opc = Inst.getOpcode();
4233 const MCInstrDesc &Desc = MII.get(Opc);
4234
4236 return true;
4237
4238 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opc);
4239
4240 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
4242 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
4243 AMDGPU::OpName RSrcOpName =
4244 SIInstrFlags::isMIMG(Desc) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
4245 int SrsrcIdx = AMDGPU::getNamedOperandIdx(Opc, RSrcOpName);
4246 int DimIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dim);
4247 int A16Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::a16);
4248
4249 assert(VAddr0Idx != -1);
4250 assert(SrsrcIdx != -1);
4251 assert(SrsrcIdx > VAddr0Idx);
4252
4253 bool IsA16 = (A16Idx != -1 && Inst.getOperand(A16Idx).getImm());
4254 if (BaseOpcode->BVH) {
4255 if (IsA16 == BaseOpcode->A16)
4256 return true;
4257 Error(IDLoc, "image address size does not match a16");
4258 return false;
4259 }
4260
4261 unsigned Dim = Inst.getOperand(DimIdx).getImm();
4262 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByEncoding(Dim);
4263 bool IsNSA = SrsrcIdx - VAddr0Idx > 1;
4264 unsigned ActualAddrSize =
4265 IsNSA ? SrsrcIdx - VAddr0Idx : getRegOperandSize(Desc, VAddr0Idx) / 4;
4266
4267 unsigned ExpectedAddrSize =
4268 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, DimInfo, IsA16, hasG16());
4269
4270 if (IsNSA) {
4271 if (hasPartialNSAEncoding() &&
4272 ExpectedAddrSize > getNSAMaxSize(SIInstrFlags::isVSAMPLE(Desc))) {
4273 int VAddrLastIdx = SrsrcIdx - 1;
4274 unsigned VAddrLastSize = getRegOperandSize(Desc, VAddrLastIdx) / 4;
4275
4276 ActualAddrSize = VAddrLastIdx - VAddr0Idx + VAddrLastSize;
4277 }
4278 } else {
4279 if (ExpectedAddrSize > 12)
4280 ExpectedAddrSize = 16;
4281
4282 // Allow oversized 8 VGPR vaddr when only 5/6/7 VGPRs are required.
4283 // This provides backward compatibility for assembly created
4284 // before 160b/192b/224b types were directly supported.
4285 if (ActualAddrSize == 8 && (ExpectedAddrSize >= 5 && ExpectedAddrSize <= 7))
4286 return true;
4287 }
4288
4289 if (ActualAddrSize == ExpectedAddrSize)
4290 return true;
4291
4292 Error(IDLoc, "image address size does not match dim and a16");
4293 return false;
4294}
4295
4296bool AMDGPUAsmParser::validateMIMGAtomicDMask(const MCInst &Inst) {
4297
4298 const unsigned Opc = Inst.getOpcode();
4299 const MCInstrDesc &Desc = MII.get(Opc);
4300
4301 if ((SIInstrFlags::isImage(Desc)) == 0)
4302 return true;
4303 if (!Desc.mayLoad() || !Desc.mayStore())
4304 return true; // Not atomic
4305
4306 int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask);
4307 unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf;
4308
4309 // This is an incomplete check because image_atomic_cmpswap
4310 // may only use 0x3 and 0xf while other atomic operations
4311 // may use 0x1 and 0x3. However these limitations are
4312 // verified when we check that dmask matches dst size.
4313 return DMask == 0x1 || DMask == 0x3 || DMask == 0xf;
4314}
4315
4316bool AMDGPUAsmParser::validateMIMGGatherDMask(const MCInst &Inst) {
4317
4318 const unsigned Opc = Inst.getOpcode();
4319
4320 if (!SIInstrFlags::isGather4(MII, Inst))
4321 return true;
4322
4323 int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask);
4324 unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf;
4325
4326 // GATHER4 instructions use dmask in a different fashion compared to
4327 // other MIMG instructions. The only useful DMASK values are
4328 // 1=red, 2=green, 4=blue, 8=alpha. (e.g. 1 returns
4329 // (red,red,red,red) etc.) The ISA document doesn't mention
4330 // this.
4331 return DMask == 0x1 || DMask == 0x2 || DMask == 0x4 || DMask == 0x8;
4332}
4333
4334bool AMDGPUAsmParser::validateMIMGDim(const MCInst &Inst,
4335 const OperandVector &Operands) {
4336 if (!isGFX10Plus())
4337 return true;
4338
4339 const unsigned Opc = Inst.getOpcode();
4340
4341 if ((SIInstrFlags::isImage(MII, Inst)) == 0)
4342 return true;
4343
4344 // image_bvh_intersect_ray instructions do not have dim
4346 return true;
4347
4348 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
4349 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
4350 if (Op.isDim())
4351 return true;
4352 }
4353 return false;
4354}
4355
4356bool AMDGPUAsmParser::validateMIMGMSAA(const MCInst &Inst) {
4357 const unsigned Opc = Inst.getOpcode();
4358
4359 if ((SIInstrFlags::isImage(MII, Inst)) == 0)
4360 return true;
4361
4362 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opc);
4363 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
4365
4366 if (!BaseOpcode->MSAA)
4367 return true;
4368
4369 int DimIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dim);
4370 assert(DimIdx != -1);
4371
4372 unsigned Dim = Inst.getOperand(DimIdx).getImm();
4373 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByEncoding(Dim);
4374
4375 return DimInfo->MSAA;
4376}
4377
4378static bool IsMovrelsSDWAOpcode(const unsigned Opcode) {
4379 switch (Opcode) {
4380 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
4381 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
4382 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
4383 return true;
4384 default:
4385 return false;
4386 }
4387}
4388
4389// movrels* opcodes should only allow VGPRS as src0.
4390// This is specified in .td description for vop1/vop3,
4391// but sdwa is handled differently. See isSDWAOperand.
4392bool AMDGPUAsmParser::validateMovrels(const MCInst &Inst,
4393 const OperandVector &Operands) {
4394
4395 const unsigned Opc = Inst.getOpcode();
4396
4397 if (!SIInstrFlags::isSDWA(MII, Inst) || !IsMovrelsSDWAOpcode(Opc))
4398 return true;
4399
4400 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
4401 assert(Src0Idx != -1);
4402
4403 const MCOperand &Src0 = Inst.getOperand(Src0Idx);
4404 if (Src0.isReg()) {
4405 auto Reg = mc2PseudoReg(Src0.getReg());
4406 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
4407 if (!isSGPR(Reg, TRI))
4408 return true;
4409 }
4410
4411 Error(getOperandLoc(Operands, Src0Idx), "source operand must be a VGPR");
4412 return false;
4413}
4414
4415bool AMDGPUAsmParser::validateMAIAccWrite(const MCInst &Inst,
4416 const OperandVector &Operands) {
4417
4418 const unsigned Opc = Inst.getOpcode();
4419
4420 if (Opc != AMDGPU::V_ACCVGPR_WRITE_B32_vi)
4421 return true;
4422
4423 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
4424 assert(Src0Idx != -1);
4425
4426 const MCOperand &Src0 = Inst.getOperand(Src0Idx);
4427 if (!Src0.isReg())
4428 return true;
4429
4430 auto Reg = mc2PseudoReg(Src0.getReg());
4431 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
4432 if (!isGFX90A() && isSGPR(Reg, TRI)) {
4433 Error(getOperandLoc(Operands, Src0Idx),
4434 "source operand must be either a VGPR or an inline constant");
4435 return false;
4436 }
4437
4438 return true;
4439}
4440
4441bool AMDGPUAsmParser::validateMAISrc2(const MCInst &Inst,
4442 const OperandVector &Operands) {
4443 unsigned Opcode = Inst.getOpcode();
4444
4445 if (!SIInstrFlags::isMAI(MII, Inst) ||
4446 !getFeatureBits()[FeatureMFMAInlineLiteralBug])
4447 return true;
4448
4449 const int Src2Idx = getNamedOperandIdx(Opcode, OpName::src2);
4450 if (Src2Idx == -1)
4451 return true;
4452
4453 if (Inst.getOperand(Src2Idx).isImm() && isInlineConstant(Inst, Src2Idx)) {
4454 Error(getOperandLoc(Operands, Src2Idx),
4455 "inline constants are not allowed for this operand");
4456 return false;
4457 }
4458
4459 return true;
4460}
4461
4462bool AMDGPUAsmParser::validateMFMA(const MCInst &Inst,
4463 const OperandVector &Operands) {
4464 const unsigned Opc = Inst.getOpcode();
4465 const MCInstrDesc &Desc = MII.get(Opc);
4466
4468 return true;
4469
4470 int BlgpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::blgp);
4471 if (BlgpIdx != -1) {
4472 if (const MFMA_F8F6F4_Info *Info = AMDGPU::isMFMA_F8F6F4(Opc)) {
4473 int CbszIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::cbsz);
4474
4475 unsigned CBSZ = Inst.getOperand(CbszIdx).getImm();
4476 unsigned BLGP = Inst.getOperand(BlgpIdx).getImm();
4477
4478 // Validate the correct register size was used for the floating point
4479 // format operands
4480
4481 bool Success = true;
4482 if (Info->NumRegsSrcA != mfmaScaleF8F6F4FormatToNumRegs(CBSZ)) {
4483 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
4484 Error(getOperandLoc(Operands, Src0Idx),
4485 "wrong register tuple size for cbsz value " + Twine(CBSZ));
4486 Success = false;
4487 }
4488
4489 if (Info->NumRegsSrcB != mfmaScaleF8F6F4FormatToNumRegs(BLGP)) {
4490 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
4491 Error(getOperandLoc(Operands, Src1Idx),
4492 "wrong register tuple size for blgp value " + Twine(BLGP));
4493 Success = false;
4494 }
4495
4496 return Success;
4497 }
4498 }
4499
4500 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2);
4501 if (Src2Idx == -1)
4502 return true;
4503
4504 const MCOperand &Src2 = Inst.getOperand(Src2Idx);
4505 if (!Src2.isReg())
4506 return true;
4507
4508 MCRegister Src2Reg = Src2.getReg();
4509 MCRegister DstReg = Inst.getOperand(0).getReg();
4510 if (Src2Reg == DstReg)
4511 return true;
4512
4513 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
4514 if (TRI->getRegClass(MII.getOpRegClassID(Desc.operands()[0], HwMode))
4515 .getSizeInBits() <= 128)
4516 return true;
4517
4518 if (TRI->regsOverlap(Src2Reg, DstReg)) {
4519 Error(getOperandLoc(Operands, Src2Idx),
4520 "source 2 operand must not partially overlap with dst");
4521 return false;
4522 }
4523
4524 return true;
4525}
4526
4527bool AMDGPUAsmParser::validateDivScale(const MCInst &Inst) {
4528 switch (Inst.getOpcode()) {
4529 default:
4530 return true;
4531 case V_DIV_SCALE_F32_gfx6_gfx7:
4532 case V_DIV_SCALE_F32_vi:
4533 case V_DIV_SCALE_F32_gfx10:
4534 case V_DIV_SCALE_F64_gfx6_gfx7:
4535 case V_DIV_SCALE_F64_vi:
4536 case V_DIV_SCALE_F64_gfx10:
4537 break;
4538 }
4539
4540 // TODO: Check that src0 = src1 or src2.
4541
4542 for (auto Name :
4543 {AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src2_modifiers,
4544 AMDGPU::OpName::src2_modifiers}) {
4545 if (Inst.getOperand(AMDGPU::getNamedOperandIdx(Inst.getOpcode(), Name))
4546 .getImm() &
4548 return false;
4549 }
4550 }
4551
4552 return true;
4553}
4554
4555bool AMDGPUAsmParser::validateMIMGD16(const MCInst &Inst) {
4556
4557 const unsigned Opc = Inst.getOpcode();
4558
4559 if ((SIInstrFlags::isImage(MII, Inst)) == 0)
4560 return true;
4561
4562 int D16Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::d16);
4563 if (D16Idx >= 0 && Inst.getOperand(D16Idx).getImm()) {
4564 if (isCI() || isSI())
4565 return false;
4566 }
4567
4568 return true;
4569}
4570
4571bool AMDGPUAsmParser::validateTensorR128(const MCInst &Inst) {
4572 const unsigned Opc = Inst.getOpcode();
4573
4574 if (!SIInstrFlags::usesTENSOR_CNT(MII, Inst))
4575 return true;
4576
4577 int R128Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::r128);
4578
4579 return R128Idx < 0 || !Inst.getOperand(R128Idx).getImm();
4580}
4581
4582static bool IsRevOpcode(const unsigned Opcode) {
4583 switch (Opcode) {
4584 case AMDGPU::V_SUBREV_F32_e32:
4585 case AMDGPU::V_SUBREV_F32_e64:
4586 case AMDGPU::V_SUBREV_F32_e32_gfx10:
4587 case AMDGPU::V_SUBREV_F32_e32_gfx6_gfx7:
4588 case AMDGPU::V_SUBREV_F32_e32_vi:
4589 case AMDGPU::V_SUBREV_F32_e64_gfx10:
4590 case AMDGPU::V_SUBREV_F32_e64_gfx6_gfx7:
4591 case AMDGPU::V_SUBREV_F32_e64_vi:
4592
4593 case AMDGPU::V_SUBREV_CO_U32_e32:
4594 case AMDGPU::V_SUBREV_CO_U32_e64:
4595 case AMDGPU::V_SUBREV_I32_e32_gfx6_gfx7:
4596 case AMDGPU::V_SUBREV_I32_e64_gfx6_gfx7:
4597
4598 case AMDGPU::V_SUBBREV_U32_e32:
4599 case AMDGPU::V_SUBBREV_U32_e64:
4600 case AMDGPU::V_SUBBREV_U32_e32_gfx6_gfx7:
4601 case AMDGPU::V_SUBBREV_U32_e32_vi:
4602 case AMDGPU::V_SUBBREV_U32_e64_gfx6_gfx7:
4603 case AMDGPU::V_SUBBREV_U32_e64_vi:
4604
4605 case AMDGPU::V_SUBREV_U32_e32:
4606 case AMDGPU::V_SUBREV_U32_e64:
4607 case AMDGPU::V_SUBREV_U32_e32_gfx9:
4608 case AMDGPU::V_SUBREV_U32_e32_vi:
4609 case AMDGPU::V_SUBREV_U32_e64_gfx9:
4610 case AMDGPU::V_SUBREV_U32_e64_vi:
4611
4612 case AMDGPU::V_SUBREV_F16_e32:
4613 case AMDGPU::V_SUBREV_F16_e64:
4614 case AMDGPU::V_SUBREV_F16_e32_gfx10:
4615 case AMDGPU::V_SUBREV_F16_e32_vi:
4616 case AMDGPU::V_SUBREV_F16_e64_gfx10:
4617 case AMDGPU::V_SUBREV_F16_e64_vi:
4618
4619 case AMDGPU::V_SUBREV_U16_e32:
4620 case AMDGPU::V_SUBREV_U16_e64:
4621 case AMDGPU::V_SUBREV_U16_e32_vi:
4622 case AMDGPU::V_SUBREV_U16_e64_vi:
4623
4624 case AMDGPU::V_SUBREV_CO_U32_e32_gfx9:
4625 case AMDGPU::V_SUBREV_CO_U32_e64_gfx10:
4626 case AMDGPU::V_SUBREV_CO_U32_e64_gfx9:
4627
4628 case AMDGPU::V_SUBBREV_CO_U32_e32_gfx9:
4629 case AMDGPU::V_SUBBREV_CO_U32_e64_gfx9:
4630
4631 case AMDGPU::V_SUBREV_NC_U32_e32_gfx10:
4632 case AMDGPU::V_SUBREV_NC_U32_e64_gfx10:
4633
4634 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx10:
4635 case AMDGPU::V_SUBREV_CO_CI_U32_e64_gfx10:
4636
4637 case AMDGPU::V_LSHRREV_B32_e32:
4638 case AMDGPU::V_LSHRREV_B32_e64:
4639 case AMDGPU::V_LSHRREV_B32_e32_gfx6_gfx7:
4640 case AMDGPU::V_LSHRREV_B32_e64_gfx6_gfx7:
4641 case AMDGPU::V_LSHRREV_B32_e32_vi:
4642 case AMDGPU::V_LSHRREV_B32_e64_vi:
4643 case AMDGPU::V_LSHRREV_B32_e32_gfx10:
4644 case AMDGPU::V_LSHRREV_B32_e64_gfx10:
4645
4646 case AMDGPU::V_ASHRREV_I32_e32:
4647 case AMDGPU::V_ASHRREV_I32_e64:
4648 case AMDGPU::V_ASHRREV_I32_e32_gfx10:
4649 case AMDGPU::V_ASHRREV_I32_e32_gfx6_gfx7:
4650 case AMDGPU::V_ASHRREV_I32_e32_vi:
4651 case AMDGPU::V_ASHRREV_I32_e64_gfx10:
4652 case AMDGPU::V_ASHRREV_I32_e64_gfx6_gfx7:
4653 case AMDGPU::V_ASHRREV_I32_e64_vi:
4654
4655 case AMDGPU::V_LSHLREV_B32_e32:
4656 case AMDGPU::V_LSHLREV_B32_e64:
4657 case AMDGPU::V_LSHLREV_B32_e32_gfx10:
4658 case AMDGPU::V_LSHLREV_B32_e32_gfx6_gfx7:
4659 case AMDGPU::V_LSHLREV_B32_e32_vi:
4660 case AMDGPU::V_LSHLREV_B32_e64_gfx10:
4661 case AMDGPU::V_LSHLREV_B32_e64_gfx6_gfx7:
4662 case AMDGPU::V_LSHLREV_B32_e64_vi:
4663
4664 case AMDGPU::V_LSHLREV_B16_e32:
4665 case AMDGPU::V_LSHLREV_B16_e64:
4666 case AMDGPU::V_LSHLREV_B16_e32_vi:
4667 case AMDGPU::V_LSHLREV_B16_e64_vi:
4668 case AMDGPU::V_LSHLREV_B16_gfx10:
4669
4670 case AMDGPU::V_LSHRREV_B16_e32:
4671 case AMDGPU::V_LSHRREV_B16_e64:
4672 case AMDGPU::V_LSHRREV_B16_e32_vi:
4673 case AMDGPU::V_LSHRREV_B16_e64_vi:
4674 case AMDGPU::V_LSHRREV_B16_gfx10:
4675
4676 case AMDGPU::V_ASHRREV_I16_e32:
4677 case AMDGPU::V_ASHRREV_I16_e64:
4678 case AMDGPU::V_ASHRREV_I16_e32_vi:
4679 case AMDGPU::V_ASHRREV_I16_e64_vi:
4680 case AMDGPU::V_ASHRREV_I16_gfx10:
4681
4682 case AMDGPU::V_LSHLREV_B64_e64:
4683 case AMDGPU::V_LSHLREV_B64_gfx10:
4684 case AMDGPU::V_LSHLREV_B64_vi:
4685
4686 case AMDGPU::V_LSHRREV_B64_e64:
4687 case AMDGPU::V_LSHRREV_B64_gfx10:
4688 case AMDGPU::V_LSHRREV_B64_vi:
4689
4690 case AMDGPU::V_ASHRREV_I64_e64:
4691 case AMDGPU::V_ASHRREV_I64_gfx10:
4692 case AMDGPU::V_ASHRREV_I64_vi:
4693
4694 case AMDGPU::V_PK_LSHLREV_B16:
4695 case AMDGPU::V_PK_LSHLREV_B16_gfx10:
4696 case AMDGPU::V_PK_LSHLREV_B16_vi:
4697
4698 case AMDGPU::V_PK_LSHRREV_B16:
4699 case AMDGPU::V_PK_LSHRREV_B16_gfx10:
4700 case AMDGPU::V_PK_LSHRREV_B16_vi:
4701 case AMDGPU::V_PK_ASHRREV_I16:
4702 case AMDGPU::V_PK_ASHRREV_I16_gfx10:
4703 case AMDGPU::V_PK_ASHRREV_I16_vi:
4704 return true;
4705 default:
4706 return false;
4707 }
4708}
4709
4710bool AMDGPUAsmParser::validateLdsDirect(const MCInst &Inst,
4711 const OperandVector &Operands) {
4712 const unsigned Opcode = Inst.getOpcode();
4713
4714 // lds_direct register is defined so that it can be used
4715 // with 9-bit operands only. Ignore encodings which do not accept these.
4716 if (!SIInstrFlags::isVOP1(MII, Inst) && !SIInstrFlags::isVOP2(MII, Inst) &&
4717 !SIInstrFlags::isVOP3Like(MII, Inst) &&
4718 !SIInstrFlags::isVOPC(MII, Inst) && !SIInstrFlags::isSDWA(MII, Inst))
4719 return true;
4720
4721 for (auto SrcName : {OpName::src0, OpName::src1, OpName::src2}) {
4722 auto SrcIdx = getNamedOperandIdx(Opcode, SrcName);
4723 if (SrcIdx == -1)
4724 break;
4725 const auto &Src = Inst.getOperand(SrcIdx);
4726 if (Src.isReg() && Src.getReg() == LDS_DIRECT) {
4727
4728 if (isGFX90A() || isGFX11Plus()) {
4729 Error(getOperandLoc(Operands, SrcIdx),
4730 "lds_direct is not supported on this GPU");
4731 return false;
4732 }
4733
4734 if (IsRevOpcode(Opcode) || SIInstrFlags::isSDWA(MII, Inst)) {
4735 Error(getOperandLoc(Operands, SrcIdx),
4736 "lds_direct cannot be used with this instruction");
4737 return false;
4738 }
4739
4740 if (SrcName != OpName::src0) {
4741 Error(getOperandLoc(Operands, SrcIdx),
4742 "lds_direct may be used as src0 only");
4743 return false;
4744 }
4745 }
4746 }
4747
4748 return true;
4749}
4750
4751SMLoc AMDGPUAsmParser::getFlatOffsetLoc(const OperandVector &Operands) const {
4752 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
4753 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
4754 if (Op.isFlatOffset())
4755 return Op.getStartLoc();
4756 }
4757 return getLoc();
4758}
4759
4760bool AMDGPUAsmParser::validateOffset(const MCInst &Inst,
4761 const OperandVector &Operands) {
4762 auto Opcode = Inst.getOpcode();
4763 auto OpNum = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::offset);
4764 if (OpNum == -1)
4765 return true;
4766
4767 if (SIInstrFlags::isFLAT(MII, Inst))
4768 return validateFlatOffset(Inst, Operands);
4769
4770 if (SIInstrFlags::isSMRD(MII, Inst))
4771 return validateSMEMOffset(Inst, Operands);
4772
4773 const auto &Op = Inst.getOperand(OpNum);
4774 // GFX12+ buffer ops: InstOffset is signed 24, but must not be a negative.
4775 if (isGFX12Plus() && SIInstrFlags::isBuffer(MII, Inst)) {
4776 const unsigned OffsetSize = 24;
4777 if (!isUIntN(OffsetSize - 1, Op.getImm())) {
4778 Error(getFlatOffsetLoc(Operands),
4779 Twine("expected a ") + Twine(OffsetSize - 1) +
4780 "-bit unsigned offset for buffer ops");
4781 return false;
4782 }
4783 } else {
4784 const unsigned OffsetSize = 16;
4785 if (!isUIntN(OffsetSize, Op.getImm())) {
4786 Error(getFlatOffsetLoc(Operands),
4787 Twine("expected a ") + Twine(OffsetSize) + "-bit unsigned offset");
4788 return false;
4789 }
4790 }
4791 return true;
4792}
4793
4794bool AMDGPUAsmParser::validateFlatOffset(const MCInst &Inst,
4795 const OperandVector &Operands) {
4796 if (!SIInstrFlags::isFLAT(MII, Inst))
4797 return true;
4798
4799 auto Opcode = Inst.getOpcode();
4800 auto OpNum = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::offset);
4801 assert(OpNum != -1);
4802
4803 const auto &Op = Inst.getOperand(OpNum);
4804 if (!hasFlatOffsets() && Op.getImm() != 0) {
4805 Error(getFlatOffsetLoc(Operands),
4806 "flat offset modifier is not supported on this GPU");
4807 return false;
4808 }
4809
4810 // For pre-GFX12 FLAT instructions the offset must be positive;
4811 // MSB is ignored and forced to zero.
4812 unsigned OffsetSize = AMDGPU::getNumFlatOffsetBits(getSTI());
4813 bool AllowNegative =
4815 if (!isIntN(OffsetSize, Op.getImm()) || (!AllowNegative && Op.getImm() < 0)) {
4816 Error(getFlatOffsetLoc(Operands),
4817 Twine("expected a ") +
4818 (AllowNegative ? Twine(OffsetSize) + "-bit signed offset"
4819 : Twine(OffsetSize - 1) + "-bit unsigned offset"));
4820 return false;
4821 }
4822
4823 return true;
4824}
4825
4826SMLoc AMDGPUAsmParser::getSMEMOffsetLoc(const OperandVector &Operands) const {
4827 // Start with second operand because SMEM Offset cannot be dst or src0.
4828 for (unsigned i = 2, e = Operands.size(); i != e; ++i) {
4829 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
4830 if (Op.isSMEMOffset() || Op.isSMEMOffsetMod())
4831 return Op.getStartLoc();
4832 }
4833 return getLoc();
4834}
4835
4836bool AMDGPUAsmParser::validateSMEMOffset(const MCInst &Inst,
4837 const OperandVector &Operands) {
4838 if (isCI() || isSI())
4839 return true;
4840
4841 if (!SIInstrFlags::isSMRD(MII, Inst))
4842 return true;
4843
4844 auto Opcode = Inst.getOpcode();
4845 auto OpNum = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::offset);
4846 if (OpNum == -1)
4847 return true;
4848
4849 const auto &Op = Inst.getOperand(OpNum);
4850 if (!Op.isImm())
4851 return true;
4852
4853 uint64_t Offset = Op.getImm();
4854 bool IsBuffer = AMDGPU::getSMEMIsBuffer(Opcode);
4857 return true;
4858
4859 Error(getSMEMOffsetLoc(Operands),
4860 isGFX12Plus() && IsBuffer
4861 ? "expected a 23-bit unsigned offset for buffer ops"
4862 : isGFX12Plus() ? "expected a 24-bit signed offset"
4863 : (isVI() || IsBuffer) ? "expected a 20-bit unsigned offset"
4864 : "expected a 21-bit signed offset");
4865
4866 return false;
4867}
4868
4869bool AMDGPUAsmParser::validateSOPLiteral(const MCInst &Inst,
4870 const OperandVector &Operands) {
4871 unsigned Opcode = Inst.getOpcode();
4872 const MCInstrDesc &Desc = MII.get(Opcode);
4874 return true;
4875
4876 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
4877 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
4878
4879 const int OpIndices[] = {Src0Idx, Src1Idx};
4880
4881 unsigned NumExprs = 0;
4882 unsigned NumLiterals = 0;
4883 int64_t LiteralValue;
4884
4885 for (int OpIdx : OpIndices) {
4886 if (OpIdx == -1)
4887 break;
4888
4889 const MCOperand &MO = Inst.getOperand(OpIdx);
4890 // Exclude special imm operands (like that used by s_set_gpr_idx_on)
4891 if (AMDGPU::isSISrcOperand(Desc, OpIdx)) {
4892 bool IsLit = false;
4893 std::optional<int64_t> Imm;
4894 if (MO.isImm()) {
4895 Imm = MO.getImm();
4896 } else if (MO.isExpr()) {
4897 if (isLitExpr(MO.getExpr())) {
4898 IsLit = true;
4899 Imm = getLitValue(MO.getExpr());
4900 }
4901 } else {
4902 continue;
4903 }
4904
4905 if (!Imm.has_value()) {
4906 ++NumExprs;
4907 } else if (!isInlineConstant(Inst, OpIdx)) {
4908 auto OpType = static_cast<AMDGPU::OperandType>(
4909 Desc.operands()[OpIdx].OperandType);
4910 int64_t Value = encode32BitLiteral(*Imm, OpType, IsLit);
4911 if (NumLiterals == 0 || LiteralValue != Value) {
4913 ++NumLiterals;
4914 }
4915 }
4916 }
4917 }
4918
4919 if (NumLiterals + NumExprs <= 1)
4920 return true;
4921
4922 Error(getOperandLoc(Operands, Src1Idx),
4923 "only one unique literal operand is allowed");
4924 return false;
4925}
4926
4927bool AMDGPUAsmParser::validateOpSel(const MCInst &Inst) {
4928 const unsigned Opc = Inst.getOpcode();
4929 if (isPermlane16(Opc)) {
4930 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
4931 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
4932
4933 if (OpSel & ~3)
4934 return false;
4935 }
4936
4937 if (isGFX940() && SIInstrFlags::isDOT(MII, Inst)) {
4938 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
4939 if (OpSelIdx != -1) {
4940 if (Inst.getOperand(OpSelIdx).getImm() != 0)
4941 return false;
4942 }
4943 int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi);
4944 if (OpSelHiIdx != -1) {
4945 if (Inst.getOperand(OpSelHiIdx).getImm() != -1)
4946 return false;
4947 }
4948 }
4949
4950 // op_sel[0:1] must be 0 for v_dot2_bf16_bf16 and v_dot2_f16_f16 (VOP3 Dot).
4951 if (isGFX11Plus() && SIInstrFlags::isDOT(MII, Inst) &&
4952 SIInstrFlags::isVOP3(MII, Inst) && !SIInstrFlags::isVOP3P(MII, Inst)) {
4953 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
4954 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
4955 if (OpSel & 3)
4956 return false;
4957 }
4958
4959 // Packed math FP32 instructions typically accept SGPRs or VGPRs as source
4960 // operands. On gfx12+, if a source operand uses SGPRs, the HW can only read
4961 // the first SGPR and use it for both the low and high operations.
4963 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
4964 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
4965 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
4966 int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi);
4967
4968 const MCOperand &Src0 = Inst.getOperand(Src0Idx);
4969 const MCOperand &Src1 = Inst.getOperand(Src1Idx);
4970 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
4971 unsigned OpSelHi = Inst.getOperand(OpSelHiIdx).getImm();
4972
4973 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
4974
4975 auto VerifyOneSGPR = [OpSel, OpSelHi](unsigned Index) -> bool {
4976 unsigned Mask = 1U << Index;
4977 return ((OpSel & Mask) == 0) && ((OpSelHi & Mask) == 0);
4978 };
4979
4980 if (Src0.isReg() && isSGPR(Src0.getReg(), TRI) &&
4981 !VerifyOneSGPR(/*Index=*/0))
4982 return false;
4983 if (Src1.isReg() && isSGPR(Src1.getReg(), TRI) &&
4984 !VerifyOneSGPR(/*Index=*/1))
4985 return false;
4986
4987 int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2);
4988 if (Src2Idx != -1) {
4989 const MCOperand &Src2 = Inst.getOperand(Src2Idx);
4990 if (Src2.isReg() && isSGPR(Src2.getReg(), TRI) &&
4991 !VerifyOneSGPR(/*Index=*/2))
4992 return false;
4993 }
4994 }
4995
4996 return true;
4997}
4998
4999bool AMDGPUAsmParser::validateTrue16OpSel(const MCInst &Inst) {
5000 if (!hasTrue16Insts())
5001 return true;
5002 const MCRegisterInfo *MRI = getMRI();
5003 const unsigned Opc = Inst.getOpcode();
5004 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
5005 if (OpSelIdx == -1)
5006 return true;
5007 unsigned OpSelOpValue = Inst.getOperand(OpSelIdx).getImm();
5008 // If the value is 0 we could have a default OpSel Operand, so conservatively
5009 // allow it.
5010 if (OpSelOpValue == 0)
5011 return true;
5012 unsigned OpCount = 0;
5013 for (AMDGPU::OpName OpName : {AMDGPU::OpName::src0, AMDGPU::OpName::src1,
5014 AMDGPU::OpName::src2, AMDGPU::OpName::vdst}) {
5015 int OpIdx = AMDGPU::getNamedOperandIdx(Inst.getOpcode(), OpName);
5016 if (OpIdx == -1)
5017 continue;
5018 const MCOperand &Op = Inst.getOperand(OpIdx);
5019 if (Op.isReg() &&
5020 MRI->getRegClass(AMDGPU::VGPR_16RegClassID).contains(Op.getReg())) {
5021 bool VGPRSuffixIsHi = AMDGPU::isHi16Reg(Op.getReg(), *MRI);
5022 bool OpSelOpIsHi = ((OpSelOpValue & (1 << OpCount)) != 0);
5023 if (OpSelOpIsHi != VGPRSuffixIsHi)
5024 return false;
5025 }
5026 ++OpCount;
5027 }
5028
5029 return true;
5030}
5031
5032bool AMDGPUAsmParser::validateNeg(const MCInst &Inst, AMDGPU::OpName OpName) {
5033 assert(OpName == AMDGPU::OpName::neg_lo || OpName == AMDGPU::OpName::neg_hi);
5034
5035 const unsigned Opc = Inst.getOpcode();
5036
5037 // v_dot4 fp8/bf8 neg_lo/neg_hi not allowed on src0 and src1 (allowed on src2)
5038 // v_wmma iu4/iu8 neg_lo not allowed on src2 (allowed on src0, src1)
5039 // v_swmmac f16/bf16 neg_lo/neg_hi not allowed on src2 (allowed on src0, src1)
5040 // other wmma/swmmac instructions don't have neg_lo/neg_hi operand.
5041 if (!SIInstrFlags::isDOT(MII, Inst) && !SIInstrFlags::isWMMA(MII, Inst) &&
5042 !SIInstrFlags::isSWMMAC(MII, Inst))
5043 return true;
5044
5045 int NegIdx = AMDGPU::getNamedOperandIdx(Opc, OpName);
5046 if (NegIdx == -1)
5047 return true;
5048
5049 unsigned Neg = Inst.getOperand(NegIdx).getImm();
5050
5051 // Instructions that have neg_lo or neg_hi operand but neg modifier is allowed
5052 // on some src operands but not allowed on other.
5053 // It is convenient that such instructions don't have src_modifiers operand
5054 // for src operands that don't allow neg because they also don't allow opsel.
5055
5056 const AMDGPU::OpName SrcMods[3] = {AMDGPU::OpName::src0_modifiers,
5057 AMDGPU::OpName::src1_modifiers,
5058 AMDGPU::OpName::src2_modifiers};
5059
5060 for (unsigned i = 0; i < 3; ++i) {
5061 if (!AMDGPU::hasNamedOperand(Opc, SrcMods[i])) {
5062 if (Neg & (1 << i))
5063 return false;
5064 }
5065 }
5066
5067 return true;
5068}
5069
5070bool AMDGPUAsmParser::validateDPP(const MCInst &Inst,
5071 const OperandVector &Operands) {
5072 const unsigned Opc = Inst.getOpcode();
5073 int DppCtrlIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dpp_ctrl);
5074 if (DppCtrlIdx >= 0) {
5075 unsigned DppCtrl = Inst.getOperand(DppCtrlIdx).getImm();
5076
5077 if (!AMDGPU::isLegalDPALU_DPPControl(getSTI(), DppCtrl) &&
5078 AMDGPU::isDPALU_DPP(MII.get(Opc), MII, getSTI())) {
5079 // DP ALU DPP is supported for row_newbcast only on GFX9* and row_share
5080 // only on GFX12.
5081 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyDppCtrl, Operands);
5082 Error(S, isGFX12() ? "DP ALU dpp only supports row_share"
5083 : "DP ALU dpp only supports row_newbcast");
5084 return false;
5085 }
5086 }
5087
5088 int Dpp8Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dpp8);
5089 bool IsDPP = DppCtrlIdx >= 0 || Dpp8Idx >= 0;
5090
5091 if (IsDPP && !hasDPPSrc1SGPR(getSTI())) {
5092 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
5093 if (Src1Idx >= 0) {
5094 const MCOperand &Src1 = Inst.getOperand(Src1Idx);
5095 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
5096 if (Src1.isReg() && isSGPR(mc2PseudoReg(Src1.getReg()), TRI)) {
5097 Error(getOperandLoc(Operands, Src1Idx),
5098 "invalid operand for instruction");
5099 return false;
5100 }
5101 if (Src1.isImm()) {
5102 Error(getInstLoc(Operands),
5103 "src1 immediate operand invalid for instruction");
5104 return false;
5105 }
5106 }
5107 }
5108
5109 return true;
5110}
5111
5112// Check if VCC register matches wavefront size
5113bool AMDGPUAsmParser::validateVccOperand(MCRegister Reg) const {
5114 return (Reg == AMDGPU::VCC && isWave64()) ||
5115 (Reg == AMDGPU::VCC_LO && isWave32());
5116}
5117
5118// One unique literal can be used. VOP3 literal is only allowed in GFX10+
5119bool AMDGPUAsmParser::validateVOPLiteral(const MCInst &Inst,
5120 const OperandVector &Operands) {
5121 unsigned Opcode = Inst.getOpcode();
5122 const MCInstrDesc &Desc = MII.get(Opcode);
5123 bool HasMandatoryLiteral = getNamedOperandIdx(Opcode, OpName::imm) != -1;
5124 if (!SIInstrFlags::isVOP3Like(Desc) && !HasMandatoryLiteral &&
5125 !isVOPD(Opcode))
5126 return true;
5127
5128 OperandIndices OpIndices = getSrcOperandIndices(Opcode, HasMandatoryLiteral);
5129
5130 std::optional<unsigned> LiteralOpIdx;
5131 std::optional<uint64_t> LiteralValue;
5132
5133 for (int OpIdx : OpIndices) {
5134 if (OpIdx == -1)
5135 continue;
5136
5137 const MCOperand &MO = Inst.getOperand(OpIdx);
5138 if (!MO.isImm() && !MO.isExpr())
5139 continue;
5140 if (!isSISrcOperand(Desc, OpIdx))
5141 continue;
5142
5143 std::optional<int64_t> Imm;
5144 if (MO.isImm())
5145 Imm = MO.getImm();
5146 else if (MO.isExpr() && isLitExpr(MO.getExpr()))
5147 Imm = getLitValue(MO.getExpr());
5148
5149 bool IsAnotherLiteral = false;
5150 bool IsForcedLit = findMCOperand(Operands, OpIdx).isForcedLit();
5151 bool IsForcedLit64 = findMCOperand(Operands, OpIdx).isForcedLit64();
5152 if (!Imm.has_value()) {
5153 // Literal value not known, so we conservately assume it's different.
5154 IsAnotherLiteral = true;
5155 } else if (IsForcedLit || IsForcedLit64 || !isInlineConstant(Inst, OpIdx)) {
5156 uint64_t Value = *Imm;
5157 bool IsForcedFP64 =
5158 Desc.operands()[OpIdx].OperandType == AMDGPU::OPERAND_KIMM64 ||
5159 (Desc.operands()[OpIdx].OperandType == AMDGPU::OPERAND_REG_IMM_FP64 &&
5160 HasMandatoryLiteral);
5161 AMDGPU::OperandType OpTy =
5162 static_cast<AMDGPU::OperandType>(Desc.operands()[OpIdx].OperandType);
5163 bool IsFP64 =
5164 (IsForcedFP64 || (AMDGPU::isSISrcFPOperand(Desc, OpIdx) &&
5166 AMDGPU::getOperandSize(Desc.operands()[OpIdx]) == 8;
5167 bool IsValid32Op =
5168 IsForcedLit || AMDGPU::isValid32BitLiteral(Value, IsFP64);
5169
5170 if (((!IsValid32Op && !isInt<32>(Value) && !isUInt<32>(Value) &&
5171 !IsForcedFP64) ||
5172 (IsForcedLit64 && !HasMandatoryLiteral)) &&
5173 (!has64BitLiterals() || Desc.getSize() != 4)) {
5174 Error(getOperandLoc(Operands, OpIdx),
5175 "invalid operand for instruction");
5176 return false;
5177 }
5178
5179 // Only src0 can use lit64 in VOP* encoding.
5180 if (!IsForcedFP64 && (IsForcedLit64 || !IsValid32Op) &&
5181 OpIdx != getNamedOperandIdx(Opcode, OpName::src0)) {
5182 Error(getOperandLoc(Operands, OpIdx),
5183 "invalid operand for instruction");
5184 return false;
5185 }
5186
5187 // Compare values using the word encoded by a 32-bit literal.
5188 if (IsValid32Op && !IsForcedFP64 && !IsForcedLit64) {
5189 Value = static_cast<uint32_t>(
5190 AMDGPU::encode32BitLiteral(Value, OpTy, IsForcedLit));
5191 }
5192
5193 IsAnotherLiteral = !LiteralValue || *LiteralValue != Value;
5195 }
5196
5197 if (IsAnotherLiteral && !HasMandatoryLiteral &&
5198 !getFeatureBits()[FeatureVOP3Literal]) {
5199 Error(getOperandLoc(Operands, OpIdx),
5200 "literal operands are not supported");
5201 return false;
5202 }
5203
5204 if (LiteralOpIdx && IsAnotherLiteral) {
5205 Error(getLaterLoc(getOperandLoc(Operands, OpIdx),
5206 getOperandLoc(Operands, *LiteralOpIdx)),
5207 "only one unique literal operand is allowed");
5208 return false;
5209 }
5210
5211 if (IsAnotherLiteral)
5212 LiteralOpIdx = OpIdx;
5213 }
5214
5215 return true;
5216}
5217
5218// Returns -1 if not a register, 0 if VGPR and 1 if AGPR.
5219static int IsAGPROperand(const MCInst &Inst, AMDGPU::OpName Name,
5220 const MCRegisterInfo *MRI) {
5221 int OpIdx = AMDGPU::getNamedOperandIdx(Inst.getOpcode(), Name);
5222 if (OpIdx < 0)
5223 return -1;
5224
5225 const MCOperand &Op = Inst.getOperand(OpIdx);
5226 if (!Op.isReg())
5227 return -1;
5228
5229 MCRegister Sub = MRI->getSubReg(Op.getReg(), AMDGPU::sub0);
5230 auto Reg = Sub ? Sub : Op.getReg();
5231 const MCRegisterClass &AGPR32 = MRI->getRegClass(AMDGPU::AGPR_32RegClassID);
5232 return AGPR32.contains(Reg) ? 1 : 0;
5233}
5234
5235bool AMDGPUAsmParser::validateAGPRLdSt(const MCInst &Inst) const {
5236 if (!SIInstrFlags::isFLAT(MII, Inst) && !SIInstrFlags::isBuffer(MII, Inst) &&
5237 !SIInstrFlags::isMIMG(MII, Inst) && !SIInstrFlags::isDS(MII, Inst))
5238 return true;
5239
5240 AMDGPU::OpName DataName = SIInstrFlags::isDS(MII, Inst)
5241 ? AMDGPU::OpName::data0
5242 : AMDGPU::OpName::vdata;
5243
5244 const MCRegisterInfo *MRI = getMRI();
5245 int DstAreg = IsAGPROperand(Inst, AMDGPU::OpName::vdst, MRI);
5246 int DataAreg = IsAGPROperand(Inst, DataName, MRI);
5247
5248 if (SIInstrFlags::isDS(MII, Inst) && DataAreg >= 0) {
5249 int Data2Areg = IsAGPROperand(Inst, AMDGPU::OpName::data1, MRI);
5250 if (Data2Areg >= 0 && Data2Areg != DataAreg)
5251 return false;
5252 }
5253
5254 auto FB = getFeatureBits();
5255 if (FB[AMDGPU::FeatureGFX90AInsts]) {
5256 if (DataAreg < 0 || DstAreg < 0)
5257 return true;
5258 return DstAreg == DataAreg;
5259 }
5260
5261 return DstAreg < 1 && DataAreg < 1;
5262}
5263
5264bool AMDGPUAsmParser::validateVGPRAlign(const MCInst &Inst) const {
5265 auto FB = getFeatureBits();
5266 if (!FB[AMDGPU::FeatureRequiresAlignedVGPRs])
5267 return true;
5268
5269 unsigned Opc = Inst.getOpcode();
5270 const MCRegisterInfo *MRI = getMRI();
5271 // DS_READ_B96_TR_B6 is the only DS instruction in GFX950, that allows
5272 // unaligned VGPR. All others only allow even aligned VGPRs.
5273 if (FB[AMDGPU::FeatureGFX90AInsts] && Opc == AMDGPU::DS_READ_B96_TR_B6_vi)
5274 return true;
5275
5276 if (FB[AMDGPU::FeatureGFX1250Insts]) {
5277 switch (Opc) {
5278 default:
5279 break;
5280 case AMDGPU::DS_LOAD_TR6_B96:
5281 case AMDGPU::DS_LOAD_TR6_B96_gfx12:
5282 // DS_LOAD_TR6_B96 is the only DS instruction in GFX1250, that
5283 // allows unaligned VGPR. All others only allow even aligned VGPRs.
5284 return true;
5285 case AMDGPU::GLOBAL_LOAD_TR6_B96:
5286 case AMDGPU::GLOBAL_LOAD_TR6_B96_gfx1250: {
5287 // GLOBAL_LOAD_TR6_B96 is the only GLOBAL instruction in GFX1250, that
5288 // allows unaligned VGPR for vdst, but other operands still only allow
5289 // even aligned VGPRs.
5290 int VAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr);
5291 if (VAddrIdx != -1) {
5292 const MCOperand &Op = Inst.getOperand(VAddrIdx);
5293 MCRegister Sub = MRI->getSubReg(Op.getReg(), AMDGPU::sub0);
5294 if ((Sub - AMDGPU::VGPR0) & 1)
5295 return false;
5296 }
5297 return true;
5298 }
5299 case AMDGPU::GLOBAL_LOAD_TR6_B96_SADDR:
5300 case AMDGPU::GLOBAL_LOAD_TR6_B96_SADDR_gfx1250:
5301 return true;
5302 }
5303 }
5304
5305 const MCRegisterClass &VGPR32 = MRI->getRegClass(AMDGPU::VGPR_32RegClassID);
5306 const MCRegisterClass &AGPR32 = MRI->getRegClass(AMDGPU::AGPR_32RegClassID);
5307 for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) {
5308 const MCOperand &Op = Inst.getOperand(I);
5309 if (!Op.isReg())
5310 continue;
5311
5312 MCRegister Sub = MRI->getSubReg(Op.getReg(), AMDGPU::sub0);
5313 if (!Sub)
5314 continue;
5315
5316 if (VGPR32.contains(Sub) && ((Sub - AMDGPU::VGPR0) & 1))
5317 return false;
5318 if (AGPR32.contains(Sub) && ((Sub - AMDGPU::AGPR0) & 1))
5319 return false;
5320 }
5321
5322 return true;
5323}
5324
5325SMLoc AMDGPUAsmParser::getBLGPLoc(const OperandVector &Operands) const {
5326 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
5327 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
5328 if (Op.isBLGP())
5329 return Op.getStartLoc();
5330 }
5331 return SMLoc();
5332}
5333
5334bool AMDGPUAsmParser::validateBLGP(const MCInst &Inst,
5335 const OperandVector &Operands) {
5336 unsigned Opc = Inst.getOpcode();
5337 int BlgpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::blgp);
5338 if (BlgpIdx == -1)
5339 return true;
5340 SMLoc BLGPLoc = getBLGPLoc(Operands);
5341 if (!BLGPLoc.isValid())
5342 return true;
5343 bool IsNeg = StringRef(BLGPLoc.getPointer()).starts_with("neg:");
5344 auto FB = getFeatureBits();
5345 bool UsesNeg = false;
5346 if (FB[AMDGPU::FeatureGFX940Insts]) {
5347 switch (Opc) {
5348 case AMDGPU::V_MFMA_F64_16X16X4F64_gfx940_acd:
5349 case AMDGPU::V_MFMA_F64_16X16X4F64_gfx940_vcd:
5350 case AMDGPU::V_MFMA_F64_4X4X4F64_gfx940_acd:
5351 case AMDGPU::V_MFMA_F64_4X4X4F64_gfx940_vcd:
5352 UsesNeg = true;
5353 }
5354 }
5355
5356 if (IsNeg == UsesNeg)
5357 return true;
5358
5359 Error(BLGPLoc, UsesNeg ? "invalid modifier: blgp is not supported"
5360 : "invalid modifier: neg is not supported");
5361
5362 return false;
5363}
5364
5365bool AMDGPUAsmParser::validateWaitCnt(const MCInst &Inst,
5366 const OperandVector &Operands) {
5367 if (!isGFX11Plus())
5368 return true;
5369
5370 unsigned Opc = Inst.getOpcode();
5371 if (Opc != AMDGPU::S_WAITCNT_EXPCNT_gfx11 &&
5372 Opc != AMDGPU::S_WAITCNT_LGKMCNT_gfx11 &&
5373 Opc != AMDGPU::S_WAITCNT_VMCNT_gfx11 &&
5374 Opc != AMDGPU::S_WAITCNT_VSCNT_gfx11)
5375 return true;
5376
5377 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::sdst);
5378 assert(Src0Idx >= 0 && Inst.getOperand(Src0Idx).isReg());
5379 auto Reg = mc2PseudoReg(Inst.getOperand(Src0Idx).getReg());
5380 if (Reg == AMDGPU::SGPR_NULL)
5381 return true;
5382
5383 Error(getOperandLoc(Operands, Src0Idx), "src0 must be null");
5384 return false;
5385}
5386
5387bool AMDGPUAsmParser::validateDS(const MCInst &Inst,
5388 const OperandVector &Operands) {
5389 if (!SIInstrFlags::isDS(MII, Inst))
5390 return true;
5391 if (SIInstrFlags::isGWS(MII, Inst))
5392 return validateGWS(Inst, Operands);
5393 // Only validate GDS for non-GWS instructions.
5394 if (hasGDS())
5395 return true;
5396 int GDSIdx =
5397 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::gds);
5398 if (GDSIdx < 0)
5399 return true;
5400 unsigned GDS = Inst.getOperand(GDSIdx).getImm();
5401 if (GDS) {
5402 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyGDS, Operands);
5403 Error(S, "gds modifier is not supported on this GPU");
5404 return false;
5405 }
5406 return true;
5407}
5408
5409// gfx90a has an undocumented limitation:
5410// DS_GWS opcodes must use even aligned registers.
5411bool AMDGPUAsmParser::validateGWS(const MCInst &Inst,
5412 const OperandVector &Operands) {
5413 if (!getFeatureBits()[AMDGPU::FeatureGFX90AInsts])
5414 return true;
5415
5416 int Opc = Inst.getOpcode();
5417 if (Opc != AMDGPU::DS_GWS_INIT_vi && Opc != AMDGPU::DS_GWS_BARRIER_vi &&
5418 Opc != AMDGPU::DS_GWS_SEMA_BR_vi)
5419 return true;
5420
5421 const MCRegisterInfo *MRI = getMRI();
5422 const MCRegisterClass &VGPR32 = MRI->getRegClass(AMDGPU::VGPR_32RegClassID);
5423 int Data0Pos =
5424 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::data0);
5425 assert(Data0Pos != -1);
5426 auto Reg = Inst.getOperand(Data0Pos).getReg();
5427 auto RegIdx = Reg - (VGPR32.contains(Reg) ? AMDGPU::VGPR0 : AMDGPU::AGPR0);
5428 if (RegIdx & 1) {
5429 Error(getOperandLoc(Operands, Data0Pos), "vgpr must be even aligned");
5430 return false;
5431 }
5432
5433 return true;
5434}
5435
5436bool AMDGPUAsmParser::validateCoherencyBits(const MCInst &Inst,
5437 const OperandVector &Operands,
5438 SMLoc IDLoc) {
5439 int CPolPos =
5440 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::cpol);
5441 if (CPolPos == -1)
5442 return true;
5443
5444 unsigned CPol = Inst.getOperand(CPolPos).getImm();
5445
5446 if (!isGFX1250Plus()) {
5447 if (CPol & CPol::SCAL) {
5448 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands);
5449 StringRef CStr(S.getPointer());
5450 S = SMLoc::getFromPointer(&CStr.data()[CStr.find("scale_offset")]);
5451 Error(S, "scale_offset is not supported on this GPU");
5452 }
5453 if (CPol & CPol::NV) {
5454 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands);
5455 StringRef CStr(S.getPointer());
5456 S = SMLoc::getFromPointer(&CStr.data()[CStr.find("nv")]);
5457 Error(S, "nv is not supported on this GPU");
5458 }
5459 }
5460
5461 if ((CPol & CPol::SCAL) && !supportsScaleOffset(MII, Inst.getOpcode())) {
5462 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands);
5463 StringRef CStr(S.getPointer());
5464 S = SMLoc::getFromPointer(&CStr.data()[CStr.find("scale_offset")]);
5465 Error(S, "scale_offset is not supported for this instruction");
5466 }
5467
5468 if (isGFX12Plus())
5469 return validateTHAndScopeBits(Inst, Operands, CPol);
5470
5471 if (SIInstrFlags::isSMRD(MII, Inst)) {
5472 if (CPol && (isSI() || isCI())) {
5473 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands);
5474 Error(S, "cache policy is not supported for SMRD instructions");
5475 return false;
5476 }
5477 if (CPol & ~(AMDGPU::CPol::GLC | AMDGPU::CPol::DLC)) {
5478 Error(IDLoc, "invalid cache policy for SMEM instruction");
5479 return false;
5480 }
5481 }
5482
5483 if (isGFX90A() && !isGFX940() && (CPol & CPol::SCC)) {
5484 if (!SIInstrFlags::isVMEM(MII, Inst)) {
5485 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands);
5486 StringRef CStr(S.getPointer());
5487 S = SMLoc::getFromPointer(&CStr.data()[CStr.find("scc")]);
5488 Error(S,
5489 "scc modifier is not supported for this instruction on this GPU");
5490 return false;
5491 }
5492 }
5493
5494 if (!SIInstrFlags::isAtomic(MII, Inst))
5495 return true;
5496
5497 if (SIInstrFlags::isAtomicRet(MII, Inst)) {
5498 if (!SIInstrFlags::isMIMG(MII, Inst) && !(CPol & CPol::GLC)) {
5499 Error(IDLoc, isGFX940() ? "instruction must use sc0"
5500 : "instruction must use glc");
5501 return false;
5502 }
5503 } else {
5504 if (CPol & CPol::GLC) {
5505 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands);
5506 StringRef CStr(S.getPointer());
5508 &CStr.data()[CStr.find(isGFX940() ? "sc0" : "glc")]);
5509 Error(S, isGFX940() ? "instruction must not use sc0"
5510 : "instruction must not use glc");
5511 return false;
5512 }
5513 }
5514
5515 return true;
5516}
5517
5518bool AMDGPUAsmParser::validateTHAndScopeBits(const MCInst &Inst,
5519 const OperandVector &Operands,
5520 const unsigned CPol) {
5521 const unsigned TH = CPol & AMDGPU::CPol::TH;
5522 const unsigned Scope = CPol & AMDGPU::CPol::SCOPE;
5523
5524 auto PrintError = [&](StringRef Msg) {
5525 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands);
5526 Error(S, Msg);
5527 return false;
5528 };
5529
5530 if ((TH & AMDGPU::CPol::TH_ATOMIC_RETURN) &&
5531 SIInstrFlags::isAtomicNoRet(MII, Inst))
5532 return PrintError("th:TH_ATOMIC_RETURN requires a destination operand");
5533
5534 if (SIInstrFlags::isAtomicRet(MII, Inst) &&
5535 (SIInstrFlags::isFLAT(MII, Inst) || SIInstrFlags::isMUBUF(MII, Inst)) &&
5537 return PrintError("instruction must use th:TH_ATOMIC_RETURN");
5538
5539 if (TH == 0)
5540 return true;
5541
5542 if (SIInstrFlags::isSMRD(MII, Inst) &&
5543 ((TH == AMDGPU::CPol::TH_NT_RT) || (TH == AMDGPU::CPol::TH_RT_NT) ||
5544 (TH == AMDGPU::CPol::TH_NT_HT)))
5545 return PrintError("invalid th value for SMEM instruction");
5546
5547 if (TH == AMDGPU::CPol::TH_BYPASS) {
5548 if ((Scope != AMDGPU::CPol::SCOPE_SYS &&
5550 (Scope == AMDGPU::CPol::SCOPE_SYS &&
5552 return PrintError("scope and th combination is not valid");
5553 }
5554
5555 unsigned THType = AMDGPU::getTemporalHintType(MII.get(Inst.getOpcode()));
5556 if (THType == AMDGPU::CPol::TH_TYPE_ATOMIC) {
5557 if (!(CPol & AMDGPU::CPol::TH_TYPE_ATOMIC))
5558 return PrintError("invalid th value for atomic instructions");
5559 } else if (THType == AMDGPU::CPol::TH_TYPE_STORE) {
5560 if (!(CPol & AMDGPU::CPol::TH_TYPE_STORE))
5561 return PrintError("invalid th value for store instructions");
5562 } else {
5563 if (!(CPol & AMDGPU::CPol::TH_TYPE_LOAD))
5564 return PrintError("invalid th value for load instructions");
5565 }
5566
5567 return true;
5568}
5569
5570bool AMDGPUAsmParser::validateTFE(const MCInst &Inst,
5571 const OperandVector &Operands) {
5572 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
5573 if (Desc.mayStore() && SIInstrFlags::isBuffer(Desc)) {
5574 SMLoc Loc = getImmLoc(AMDGPUOperand::ImmTyTFE, Operands);
5575 if (Loc != getInstLoc(Operands)) {
5576 Error(Loc, "TFE modifier has no meaning for store instructions");
5577 return false;
5578 }
5579 }
5580
5581 return true;
5582}
5583
5584bool AMDGPUAsmParser::validateWMMA(const MCInst &Inst,
5585 const OperandVector &Operands) {
5586 unsigned Opc = Inst.getOpcode();
5587 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
5588 const MCInstrDesc &Desc = MII.get(Opc);
5589
5590 int AFmtIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_a_fmt);
5591 if (AFmtIdx == -1)
5592 return true;
5593 unsigned AFmt = Inst.getOperand(AFmtIdx).getImm();
5594 int BFmtIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_b_fmt);
5595 unsigned BFmt = Inst.getOperand(BFmtIdx).getImm();
5596
5597 auto validateFmt = [&](unsigned Fmt, AMDGPU::OpName SrcOp) -> bool {
5598 int SrcIdx = AMDGPU::getNamedOperandIdx(Opc, SrcOp);
5599 unsigned RegSize =
5600 TRI->getRegClass(MII.getOpRegClassID(Desc.operands()[SrcIdx], HwMode))
5601 .getSizeInBits();
5602
5604 return true;
5605
5606 Error(getOperandLoc(Operands, SrcIdx),
5607 "wrong register tuple size for " +
5608 Twine(WMMAMods::ModMatrixFmt[Fmt]));
5609 return false;
5610 };
5611
5612 if (!validateFmt(AFmt, AMDGPU::OpName::src0) ||
5613 !validateFmt(BFmt, AMDGPU::OpName::src1))
5614 return false;
5615
5616 int AScaleIdx =
5617 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_a_scale_fmt);
5618 if (AScaleIdx == -1)
5619 return true;
5620 unsigned AScale = Inst.getOperand(AScaleIdx).getImm();
5621 int BScaleIdx =
5622 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_b_scale_fmt);
5623 unsigned BScale = Inst.getOperand(BScaleIdx).getImm();
5624 if (!isValidWMMAScaleFmtCombination(AFmt, AScale, BFmt, BScale)) {
5625 Error(getImmLoc(AMDGPUOperand::ImmTyMatrixAFMT, Operands),
5626 "invalid matrix and scale format combination");
5627 return false;
5628 }
5629
5630 return true;
5631}
5632
5633bool AMDGPUAsmParser::validateMonitorSleep(const MCInst &Inst,
5634 const OperandVector &Operands) {
5635 unsigned Opc = Inst.getOpcode();
5636 if (Opc != AMDGPU::S_MONITOR_SLEEP_gfx12 ||
5637 !getSTI().hasFeature(AMDGPU::FeatureNoSleepForever))
5638 return true;
5639
5640 int ImmIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::simm16);
5641 if (Inst.getOperand(ImmIdx).getImm() & 0x8000) {
5642 Error(getOperandLoc(Operands, ImmIdx),
5643 "sleep forever is unsuported on the target");
5644 return false;
5645 }
5646
5647 return true;
5648}
5649
5650bool AMDGPUAsmParser::validateClusterBarrierIsFirst(
5651 const MCInst &Inst, const OperandVector &Operands) {
5652 unsigned Opc = Inst.getOpcode();
5653 if (Opc != AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM_gfx12 &&
5654 Opc != AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM_gfx13)
5655 return true;
5656
5657 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
5658 int BarrierID = Inst.getOperand(Src0Idx).getImm();
5659 if (BarrierID != AMDGPU::Barrier::CLUSTER)
5660 return true;
5661
5662 Error(
5663 getOperandLoc(Operands, Src0Idx),
5664 "s_barrier_signal_isfirst does not support user_cluster_barrier_id (-3)");
5665 return false;
5666}
5667
5668bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst, SMLoc IDLoc,
5669 const OperandVector &Operands) {
5670 if (!validateLdsDirect(Inst, Operands))
5671 return false;
5672 if (!validateTrue16OpSel(Inst)) {
5673 Error(getImmLoc(AMDGPUOperand::ImmTyOpSel, Operands),
5674 "op_sel operand conflicts with 16-bit operand suffix");
5675 return false;
5676 }
5677 if (!validateSOPLiteral(Inst, Operands))
5678 return false;
5679 if (!validateVOPLiteral(Inst, Operands)) {
5680 return false;
5681 }
5682 if (!validateConstantBusLimitations(Inst, Operands)) {
5683 return false;
5684 }
5685 if (!validateVOPD(Inst, Operands)) {
5686 return false;
5687 }
5688 if (!validateIntClampSupported(Inst)) {
5689 Error(getImmLoc(AMDGPUOperand::ImmTyClamp, Operands),
5690 "integer clamping is not supported on this GPU");
5691 return false;
5692 }
5693 if (!validateOpSel(Inst)) {
5694 Error(getImmLoc(AMDGPUOperand::ImmTyOpSel, Operands),
5695 "invalid op_sel operand");
5696 return false;
5697 }
5698 if (!validateNeg(Inst, AMDGPU::OpName::neg_lo)) {
5699 Error(getImmLoc(AMDGPUOperand::ImmTyNegLo, Operands),
5700 "invalid neg_lo operand");
5701 return false;
5702 }
5703 if (!validateNeg(Inst, AMDGPU::OpName::neg_hi)) {
5704 Error(getImmLoc(AMDGPUOperand::ImmTyNegHi, Operands),
5705 "invalid neg_hi operand");
5706 return false;
5707 }
5708 if (!validateDPP(Inst, Operands)) {
5709 return false;
5710 }
5711 // For MUBUF/MTBUF d16 is a part of opcode, so there is nothing to validate.
5712 if (!validateMIMGD16(Inst)) {
5713 Error(getImmLoc(AMDGPUOperand::ImmTyD16, Operands),
5714 "d16 modifier is not supported on this GPU");
5715 return false;
5716 }
5717 if (!validateMIMGDim(Inst, Operands)) {
5718 Error(IDLoc, "missing dim operand");
5719 return false;
5720 }
5721 if (!validateTensorR128(Inst)) {
5722 Error(getImmLoc(AMDGPUOperand::ImmTyD16, Operands),
5723 "instruction must set modifier r128=0");
5724 return false;
5725 }
5726 if (!validateMIMGMSAA(Inst)) {
5727 Error(getImmLoc(AMDGPUOperand::ImmTyDim, Operands),
5728 "invalid dim; must be MSAA type");
5729 return false;
5730 }
5731 if (!validateMIMGDataSize(Inst, IDLoc)) {
5732 return false;
5733 }
5734 if (!validateMIMGAddrSize(Inst, IDLoc))
5735 return false;
5736 if (!validateMIMGAtomicDMask(Inst)) {
5737 Error(getImmLoc(AMDGPUOperand::ImmTyDMask, Operands),
5738 "invalid atomic image dmask");
5739 return false;
5740 }
5741 if (!validateMIMGGatherDMask(Inst)) {
5742 Error(getImmLoc(AMDGPUOperand::ImmTyDMask, Operands),
5743 "invalid image_gather dmask: only one bit must be set");
5744 return false;
5745 }
5746 if (!validateMovrels(Inst, Operands)) {
5747 return false;
5748 }
5749 if (!validateOffset(Inst, Operands)) {
5750 return false;
5751 }
5752 if (!validateMAIAccWrite(Inst, Operands)) {
5753 return false;
5754 }
5755 if (!validateMAISrc2(Inst, Operands)) {
5756 return false;
5757 }
5758 if (!validateMFMA(Inst, Operands)) {
5759 return false;
5760 }
5761 if (!validateCoherencyBits(Inst, Operands, IDLoc)) {
5762 return false;
5763 }
5764
5765 if (!validateAGPRLdSt(Inst)) {
5766 Error(
5767 IDLoc,
5768 getFeatureBits()[AMDGPU::FeatureGFX90AInsts]
5769 ? "invalid register class: data and dst should be all VGPR or AGPR"
5770 : "invalid register class: agpr loads and stores not supported on "
5771 "this GPU");
5772 return false;
5773 }
5774 if (!validateVGPRAlign(Inst)) {
5775 Error(IDLoc, "invalid register class: vgpr tuples must be 64 bit aligned");
5776 return false;
5777 }
5778 if (!validateDS(Inst, Operands)) {
5779 return false;
5780 }
5781
5782 if (!validateBLGP(Inst, Operands)) {
5783 return false;
5784 }
5785
5786 if (!validateDivScale(Inst)) {
5787 Error(IDLoc, "ABS not allowed in VOP3B instructions");
5788 return false;
5789 }
5790 if (!validateWaitCnt(Inst, Operands)) {
5791 return false;
5792 }
5793 if (!validateTFE(Inst, Operands)) {
5794 return false;
5795 }
5796 if (!validateWMMA(Inst, Operands)) {
5797 return false;
5798 }
5799 if (!validateMonitorSleep(Inst, Operands)) {
5800 return false;
5801 }
5802 if (!validateClusterBarrierIsFirst(Inst, Operands)) {
5803 return false;
5804 }
5805
5806 return true;
5807}
5808
5810 const FeatureBitset &FBS,
5811 unsigned VariantID = 0);
5812
5813static bool AMDGPUCheckMnemonic(StringRef Mnemonic,
5814 const FeatureBitset &AvailableFeatures,
5815 unsigned VariantID);
5816
5817bool AMDGPUAsmParser::isSupportedMnemo(StringRef Mnemo,
5818 const FeatureBitset &FBS) {
5819 return isSupportedMnemo(Mnemo, FBS, getAllVariants());
5820}
5821
5822bool AMDGPUAsmParser::isSupportedMnemo(StringRef Mnemo,
5823 const FeatureBitset &FBS,
5824 ArrayRef<unsigned> Variants) {
5825 for (auto Variant : Variants) {
5826 if (AMDGPUCheckMnemonic(Mnemo, FBS, Variant))
5827 return true;
5828 }
5829
5830 return false;
5831}
5832
5833bool AMDGPUAsmParser::checkUnsupportedInstruction(StringRef Mnemo,
5834 SMLoc IDLoc) {
5835 FeatureBitset FBS = ComputeAvailableFeatures(getFeatureBits());
5836
5837 // Check if requested instruction variant is supported.
5838 if (isSupportedMnemo(Mnemo, FBS, getMatchedVariants()))
5839 return false;
5840
5841 // This instruction is not supported.
5842 // Clear any other pending errors because they are no longer relevant.
5843 getParser().clearPendingErrors();
5844
5845 // Requested instruction variant is not supported.
5846 // Check if any other variants are supported.
5847 StringRef VariantName = getMatchedVariantName();
5848 if (!VariantName.empty() && isSupportedMnemo(Mnemo, FBS)) {
5849 return Error(IDLoc, Twine(VariantName,
5850 " variant of this instruction is not supported"));
5851 }
5852
5853 // Check if this instruction may be used with a different wavesize.
5854 if (isGFX10Plus() && getFeatureBits()[AMDGPU::FeatureWavefrontSize64] &&
5855 !getFeatureBits()[AMDGPU::FeatureWavefrontSize32]) {
5856 // FIXME: Use getAvailableFeatures, and do not manually recompute
5857 FeatureBitset FeaturesWS32 = getFeatureBits();
5858 FeaturesWS32.flip(AMDGPU::FeatureWavefrontSize64)
5859 .flip(AMDGPU::FeatureWavefrontSize32);
5860 FeatureBitset AvailableFeaturesWS32 =
5861 ComputeAvailableFeatures(FeaturesWS32);
5862
5863 if (isSupportedMnemo(Mnemo, AvailableFeaturesWS32, getMatchedVariants()))
5864 return Error(IDLoc, "instruction requires wavesize=32");
5865 }
5866
5867 // Finally check if this instruction is supported on any other GPU.
5868 if (isSupportedMnemo(Mnemo, FeatureBitset().set())) {
5869 return Error(IDLoc, "instruction not supported on this GPU (" +
5870 getSTI().getCPU() + ")" + ": " + Mnemo);
5871 }
5872
5873 // Instruction not supported on any GPU. Probably a typo.
5874 std::string Suggestion = AMDGPUMnemonicSpellCheck(Mnemo, FBS);
5875 return Error(IDLoc, "invalid instruction" + Suggestion);
5876}
5877
5879 uint64_t InvalidOprIdx) {
5880 assert(InvalidOprIdx < Operands.size());
5881 const auto &Op = ((AMDGPUOperand &)*Operands[InvalidOprIdx]);
5882 if (Op.isToken() && InvalidOprIdx > 1) {
5883 const auto &PrevOp = ((AMDGPUOperand &)*Operands[InvalidOprIdx - 1]);
5884 return PrevOp.isToken() && PrevOp.getToken() == "::";
5885 }
5886 return false;
5887}
5888
5889bool AMDGPUAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5891 MCStreamer &Out,
5892 uint64_t &ErrorInfo,
5893 bool MatchingInlineAsm) {
5894 MCInst Inst;
5895 Inst.setLoc(IDLoc);
5896 unsigned Result = Match_Success;
5897
5898 // Order match statuses from least to most specific and keep the most
5899 // specific one:
5900 // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature
5901 auto atLeastAsSpecific = [](unsigned New, unsigned Cur) {
5902 auto rank = [](unsigned M) {
5903 return M == Match_MnemonicFail ? 1
5904 : M == Match_InvalidOperand ? 2
5905 : M == Match_MissingFeature ? 3
5906 : 0; // Match_Success sentinel
5907 };
5908 return rank(New) >= rank(Cur);
5909 };
5910
5911 for (auto Variant : getMatchedVariants()) {
5912 uint64_t EI;
5913 auto R =
5914 MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm, Variant);
5915 if (R == Match_Success || atLeastAsSpecific(R, Result)) {
5916 Result = R;
5917 ErrorInfo = EI;
5918 }
5919 if (R == Match_Success)
5920 break;
5921 }
5922
5923 if (Result == Match_Success) {
5924 if (!validateInstruction(Inst, IDLoc, Operands)) {
5925 return true;
5926 }
5927 emitTargetDirective();
5928 Out.emitInstruction(Inst, getSTI());
5929 // Record for kernel prologue checking.
5930 OpcodeStream.push_back(Inst.getOpcode());
5931 return false;
5932 }
5933
5934 StringRef Mnemo = ((AMDGPUOperand &)*Operands[0]).getToken();
5935 if (checkUnsupportedInstruction(Mnemo, IDLoc)) {
5936 return true;
5937 }
5938
5939 switch (Result) {
5940 default:
5941 break;
5942 case Match_MissingFeature:
5943 // It has been verified that the specified instruction
5944 // mnemonic is valid. A match was found but it requires
5945 // features which are not supported on this GPU.
5946 return Error(IDLoc, "operands are not valid for this GPU or mode");
5947
5948 case Match_InvalidOperand: {
5949 SMLoc ErrorLoc = IDLoc;
5950 if (ErrorInfo != ~0ULL) {
5951 if (ErrorInfo >= Operands.size()) {
5952 return Error(IDLoc, "too few operands for instruction");
5953 }
5954 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
5955 if (ErrorLoc == SMLoc())
5956 ErrorLoc = IDLoc;
5957
5958 if (isInvalidVOPDY(Operands, ErrorInfo))
5959 return Error(ErrorLoc, "invalid VOPDY instruction");
5960 }
5961 return Error(ErrorLoc, "invalid operand for instruction");
5962 }
5963
5964 case Match_MnemonicFail:
5965 llvm_unreachable("Invalid instructions should have been handled already");
5966 }
5967 llvm_unreachable("Implement any new match types added!");
5968}
5969
5970bool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) {
5971 int64_t Tmp = -1;
5972 if (!isToken(AsmToken::Integer) && !isToken(AsmToken::Identifier)) {
5973 return true;
5974 }
5975 if (getParser().parseAbsoluteExpression(Tmp)) {
5976 return true;
5977 }
5978 Ret = static_cast<uint32_t>(Tmp);
5979 return false;
5980}
5981
5982bool AMDGPUAsmParser::ParseDirectiveAMDGCNTarget() {
5983 if (!getSTI().getTargetTriple().isAMDGCN())
5984 return TokError("directive only supported for amdgcn architecture");
5985
5986 std::string TargetIDDirective;
5987 SMLoc TargetStart = getTok().getLoc();
5988 if (getParser().parseEscapedString(TargetIDDirective))
5989 return true;
5990
5991 std::optional<AMDGPU::TargetID> MaybeParsed =
5992 AMDGPU::TargetID::parseTargetIDString(TargetIDDirective);
5993 if (!MaybeParsed)
5994 return getParser().Error(TargetStart,
5995 "malformed target id '" + TargetIDDirective + "'");
5996
5997 const AMDGPU::TargetID &ParsedTargetID = *MaybeParsed;
5998 const Triple &TT = getSTI().getTargetTriple();
5999
6000 // The processor named in the target id must be covered by the triple's
6001 // subarch.
6002 if (!AMDGPU::isCPUValidForSubArch(TT.getSubArch(),
6003 ParsedTargetID.getGPUKind())) {
6004 return getParser().Error(
6005 TargetStart, "target id '" + TargetIDDirective +
6006 "' specifies a processor that is not valid for "
6007 "subarch '" +
6008 TT.getArchName() + "'");
6009 }
6010
6011 const std::optional<AMDGPU::TargetID> &CurrentTargetID =
6012 getTargetStreamer().getTargetID();
6013
6014 Triple DirectiveTriple(ParsedTargetID.getTargetTripleString());
6015 const Triple &STITriple = getSTI().getTargetTriple();
6016 if (!DirectiveTriple.isCompatibleWith(STITriple)) {
6017 return getParser().Error(
6018 TargetStart, ".amdgcn_target " + Twine(ParsedTargetID.toString()) +
6019 " is incompatible with " +
6020 Twine(CurrentTargetID->toString()));
6021 }
6022
6023 // Error if the ISA version doesn't match
6024 StringRef DirectiveProcessor =
6025 AMDGPU::getArchNameAMDGCN(ParsedTargetID.getGPUKind());
6026 AMDGPU::IsaVersion DirectiveISA = AMDGPU::getIsaVersion(DirectiveProcessor);
6027 if (DirectiveISA != ISA) {
6028 return getParser().Error(TargetStart,
6029 ".amdgcn_target directive processor " +
6030 Twine(DirectiveProcessor) +
6031 " does not match the specified processor " +
6032 Twine(getSTI().getCPU()));
6033 }
6034
6035 // Warn if sramecc or xnack mismatch. These do not change the encoding.
6037 ParsedTargetID.getXnackSetting(),
6038 CurrentTargetID->getXnackSetting())) {
6039 Warning(TargetStart,
6040 ".amdgcn_target directive has conflicting xnack settings");
6041 }
6043 ParsedTargetID.getSramEccSetting(),
6044 CurrentTargetID->getSramEccSetting())) {
6045 Warning(TargetStart,
6046 ".amdgcn_target directive has conflicting sramecc settings");
6047 }
6048
6049 // Update the target streamer's TargetID with settings from the directive.
6050 // We don't update the MCSubtargetInfo because we've already validated
6051 // that the directive matches the command-line CPU.
6052 getTargetStreamer().getTargetID()->setXnackSetting(
6053 ParsedTargetID.getXnackSetting());
6054 getTargetStreamer().getTargetID()->setSramEccSetting(
6055 ParsedTargetID.getSramEccSetting());
6056
6057 return false;
6058}
6059
6060bool AMDGPUAsmParser::OutOfRangeError(SMRange Range) {
6061 return Error(Range.Start, "value out of range", Range);
6062}
6063
6064bool AMDGPUAsmParser::calculateGPRBlocks(
6065 const FeatureBitset &Features, const MCExpr *VCCUsed,
6066 const MCExpr *FlatScrUsed, bool XNACKUsed,
6067 std::optional<bool> EnableWavefrontSize32, const MCExpr *NextFreeVGPR,
6068 SMRange VGPRRange, const MCExpr *NextFreeSGPR, SMRange SGPRRange,
6069 const MCExpr *&VGPRBlocks, const MCExpr *&SGPRBlocks) {
6070 // TODO(scott.linder): These calculations are duplicated from
6071 // AMDGPUAsmPrinter::getSIProgramInfo and could be unified.
6072 MCContext &Ctx = getContext();
6073
6074 const MCExpr *NumSGPRs = NextFreeSGPR;
6075 int64_t EvaluatedSGPRs;
6076
6077 if (ISA.Major >= 10)
6079 else {
6080 unsigned MaxAddressableNumSGPRs = AMDGPU::getAddressableNumSGPRs(Gfx);
6081
6082 if (NumSGPRs->evaluateAsAbsolute(EvaluatedSGPRs) && ISA.Major >= 8 &&
6083 !Features.test(FeatureSGPRInitBug) &&
6084 static_cast<uint64_t>(EvaluatedSGPRs) > MaxAddressableNumSGPRs)
6085 return OutOfRangeError(SGPRRange);
6086
6087 const MCExpr *ExtraSGPRs =
6088 AMDGPUMCExpr::createExtraSGPRs(VCCUsed, FlatScrUsed, XNACKUsed, Ctx);
6089 NumSGPRs = MCBinaryExpr::createAdd(NumSGPRs, ExtraSGPRs, Ctx);
6090
6091 if (NumSGPRs->evaluateAsAbsolute(EvaluatedSGPRs) &&
6092 (ISA.Major <= 7 || Features.test(FeatureSGPRInitBug)) &&
6093 static_cast<uint64_t>(EvaluatedSGPRs) > MaxAddressableNumSGPRs)
6094 return OutOfRangeError(SGPRRange);
6095
6096 if (Features.test(FeatureSGPRInitBug))
6097 NumSGPRs =
6099 }
6100
6101 // The MCExpr equivalent of getNumSGPRBlocks/getNumVGPRBlocks:
6102 // (alignTo(max(1u, NumGPR), GPREncodingGranule) / GPREncodingGranule) - 1
6103 auto GetNumGPRBlocks = [&Ctx](const MCExpr *NumGPR,
6104 unsigned Granule) -> const MCExpr * {
6105 const MCExpr *OneConst = MCConstantExpr::create(1ul, Ctx);
6106 const MCExpr *GranuleConst = MCConstantExpr::create(Granule, Ctx);
6107 const MCExpr *MaxNumGPR = AMDGPUMCExpr::createMax({NumGPR, OneConst}, Ctx);
6108 const MCExpr *AlignToGPR =
6109 AMDGPUMCExpr::createAlignTo(MaxNumGPR, GranuleConst, Ctx);
6110 const MCExpr *DivGPR =
6111 MCBinaryExpr::createDiv(AlignToGPR, GranuleConst, Ctx);
6112 const MCExpr *SubGPR = MCBinaryExpr::createSub(DivGPR, OneConst, Ctx);
6113 return SubGPR;
6114 };
6115
6116 VGPRBlocks = GetNumGPRBlocks(
6117 NextFreeVGPR,
6118 IsaInfo::getVGPREncodingGranule(getSTI(), EnableWavefrontSize32));
6119 SGPRBlocks =
6120 GetNumGPRBlocks(NumSGPRs, IsaInfo::getSGPREncodingGranule(getSTI()));
6121
6122 return false;
6123}
6124
6125bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() {
6126 if (!getSTI().getTargetTriple().isAMDGCN())
6127 return TokError("directive only supported for amdgcn architecture");
6128
6129 if (!isHsaAbi(getSTI()))
6130 return TokError("directive only supported for amdhsa OS");
6131
6132 StringRef KernelName;
6133 if (getParser().parseIdentifier(KernelName))
6134 return true;
6135
6136 // Remember the kernel name so its prologue can be checked at end of file.
6137 // The matching label may have been parsed already or may follow later.
6138 AMDHSAKernelSymbols.insert(getContext().getOrCreateSymbol(KernelName));
6139
6140 AMDGPU::MCKernelDescriptor KD =
6142 &getSTI(), getContext());
6143
6144 StringSet<> Seen;
6145
6146 const MCExpr *ZeroExpr = MCConstantExpr::create(0, getContext());
6147 const MCExpr *OneExpr = MCConstantExpr::create(1, getContext());
6148
6149 SMRange VGPRRange;
6150 const MCExpr *NextFreeVGPR = ZeroExpr;
6151 const MCExpr *AccumOffset = MCConstantExpr::create(0, getContext());
6152 const MCExpr *NamedBarCnt = ZeroExpr;
6153 uint64_t SharedVGPRCount = 0;
6154 uint64_t PreloadLength = 0;
6155 uint64_t PreloadOffset = 0;
6156 SMRange SGPRRange;
6157 const MCExpr *NextFreeSGPR = ZeroExpr;
6158
6159 // Count the number of user SGPRs implied from the enabled feature bits.
6160 unsigned ImpliedUserSGPRCount = 0;
6161
6162 // Track if the asm explicitly contains the directive for the user SGPR
6163 // count.
6164 std::optional<unsigned> ExplicitUserSGPRCount;
6165 const MCExpr *ReserveVCC = OneExpr;
6166 const MCExpr *ReserveFlatScr = OneExpr;
6167 std::optional<bool> EnableWavefrontSize32;
6168
6169 while (true) {
6170 while (trySkipToken(AsmToken::EndOfStatement))
6171 ;
6172
6173 StringRef ID;
6174 SMRange IDRange = getTok().getLocRange();
6175 if (!parseId(ID, "expected .amdhsa_ directive or .end_amdhsa_kernel"))
6176 return true;
6177
6178 if (ID == ".end_amdhsa_kernel")
6179 break;
6180
6181 if (!Seen.insert(ID).second)
6182 return TokError(".amdhsa_ directives cannot be repeated");
6183
6184 SMLoc ValStart = getLoc();
6185 const MCExpr *ExprVal;
6186 if (getParser().parseExpression(ExprVal))
6187 return true;
6188 SMLoc ValEnd = getLoc();
6189 SMRange ValRange = SMRange(ValStart, ValEnd);
6190
6191 int64_t IVal = 0;
6192 uint64_t Val = IVal;
6193 bool EvaluatableExpr;
6194 if ((EvaluatableExpr = ExprVal->evaluateAsAbsolute(IVal))) {
6195 if (IVal < 0)
6196 return OutOfRangeError(ValRange);
6197 Val = IVal;
6198 }
6199
6200#define PARSE_BITS_ENTRY(FIELD, ENTRY, VALUE, RANGE) \
6201 if (!isUInt<ENTRY##_WIDTH>(Val)) \
6202 return OutOfRangeError(RANGE); \
6203 AMDGPU::MCKernelDescriptor::bits_set(FIELD, VALUE, ENTRY##_SHIFT, ENTRY, \
6204 getContext());
6205
6206// Some fields use the parsed value immediately which requires the expression to
6207// be solvable.
6208#define EXPR_RESOLVE_OR_ERROR(RESOLVED) \
6209 if (!(RESOLVED)) \
6210 return Error(IDRange.Start, "directive should have resolvable expression", \
6211 IDRange);
6212
6213 if (ID == ".amdhsa_group_segment_fixed_size") {
6215 CHAR_BIT>(Val))
6216 return OutOfRangeError(ValRange);
6217 KD.group_segment_fixed_size = ExprVal;
6218 } else if (ID == ".amdhsa_private_segment_fixed_size") {
6220 CHAR_BIT>(Val))
6221 return OutOfRangeError(ValRange);
6222 KD.private_segment_fixed_size = ExprVal;
6223 } else if (ID == ".amdhsa_kernarg_size") {
6224 if (!isUInt<sizeof(kernel_descriptor_t::kernarg_size) * CHAR_BIT>(Val))
6225 return OutOfRangeError(ValRange);
6226 KD.kernarg_size = ExprVal;
6227 } else if (ID == ".amdhsa_user_sgpr_count") {
6228 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6229 ExplicitUserSGPRCount = Val;
6230 } else if (ID == ".amdhsa_user_sgpr_private_segment_buffer") {
6231 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6233 return Error(IDRange.Start,
6234 "directive is not supported with architected flat scratch",
6235 IDRange);
6237 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER,
6238 ExprVal, ValRange);
6239 if (Val)
6240 ImpliedUserSGPRCount += 4;
6241 } else if (ID == ".amdhsa_user_sgpr_kernarg_preload_length") {
6242 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6243 if (!hasKernargPreload())
6244 return Error(IDRange.Start, "directive requires gfx90a+", IDRange);
6245
6246 if (Val > getMaxNumUserSGPRs())
6247 return OutOfRangeError(ValRange);
6248 PARSE_BITS_ENTRY(KD.kernarg_preload, KERNARG_PRELOAD_SPEC_LENGTH, ExprVal,
6249 ValRange);
6250 if (Val) {
6251 ImpliedUserSGPRCount += Val;
6252 PreloadLength = Val;
6253 }
6254 } else if (ID == ".amdhsa_user_sgpr_kernarg_preload_offset") {
6255 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6256 if (!hasKernargPreload())
6257 return Error(IDRange.Start, "directive requires gfx90a+", IDRange);
6258
6259 if (Val >= 1024)
6260 return OutOfRangeError(ValRange);
6261 PARSE_BITS_ENTRY(KD.kernarg_preload, KERNARG_PRELOAD_SPEC_OFFSET, ExprVal,
6262 ValRange);
6263 if (Val)
6264 PreloadOffset = Val;
6265 } else if (ID == ".amdhsa_user_sgpr_dispatch_ptr") {
6266 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6268 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR, ExprVal,
6269 ValRange);
6270 if (Val)
6271 ImpliedUserSGPRCount += 2;
6272 } else if (ID == ".amdhsa_user_sgpr_queue_ptr") {
6273 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6275 KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR, ExprVal,
6276 ValRange);
6277 if (Val)
6278 ImpliedUserSGPRCount += 2;
6279 } else if (ID == ".amdhsa_user_sgpr_kernarg_segment_ptr") {
6280 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6282 KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR,
6283 ExprVal, ValRange);
6284 if (Val)
6285 ImpliedUserSGPRCount += 2;
6286 } else if (ID == ".amdhsa_user_sgpr_dispatch_id") {
6287 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6289 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID, ExprVal,
6290 ValRange);
6291 if (Val)
6292 ImpliedUserSGPRCount += 2;
6293 } else if (ID == ".amdhsa_user_sgpr_flat_scratch_init") {
6295 return Error(IDRange.Start,
6296 "directive is not supported with architected flat scratch",
6297 IDRange);
6298 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6300 KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT,
6301 ExprVal, ValRange);
6302 if (Val)
6303 ImpliedUserSGPRCount += 2;
6304 } else if (ID == ".amdhsa_user_sgpr_private_segment_size") {
6305 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6307 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE,
6308 ExprVal, ValRange);
6309 if (Val)
6310 ImpliedUserSGPRCount += 1;
6311 } else if (ID == ".amdhsa_wavefront_size32") {
6312 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6313 if (ISA.Major < 10)
6314 return Error(IDRange.Start, "directive requires gfx10+", IDRange);
6315 EnableWavefrontSize32 = Val;
6317 KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, ExprVal,
6318 ValRange);
6319 } else if (ID == ".amdhsa_uses_dynamic_stack") {
6321 KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK, ExprVal,
6322 ValRange);
6323 } else if (ID == ".amdhsa_system_sgpr_private_segment_wavefront_offset") {
6325 return Error(IDRange.Start,
6326 "directive is not supported with architected flat scratch",
6327 IDRange);
6329 COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, ExprVal,
6330 ValRange);
6331 } else if (ID == ".amdhsa_enable_private_segment") {
6333 return Error(
6334 IDRange.Start,
6335 "directive is not supported without architected flat scratch",
6336 IDRange);
6338 COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, ExprVal,
6339 ValRange);
6340 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_x") {
6342 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, ExprVal,
6343 ValRange);
6344 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_y") {
6346 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y, ExprVal,
6347 ValRange);
6348 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_z") {
6350 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z, ExprVal,
6351 ValRange);
6352 } else if (ID == ".amdhsa_system_sgpr_workgroup_info") {
6354 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO, ExprVal,
6355 ValRange);
6356 } else if (ID == ".amdhsa_system_vgpr_workitem_id") {
6358 COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID, ExprVal,
6359 ValRange);
6360 } else if (ID == ".amdhsa_next_free_vgpr") {
6361 VGPRRange = ValRange;
6362 NextFreeVGPR = ExprVal;
6363 } else if (ID == ".amdhsa_next_free_sgpr") {
6364 SGPRRange = ValRange;
6365 NextFreeSGPR = ExprVal;
6366 } else if (ID == ".amdhsa_accum_offset") {
6367 if (!isGFX90A())
6368 return Error(IDRange.Start, "directive requires gfx90a+", IDRange);
6369 AccumOffset = ExprVal;
6370 } else if (ID == ".amdhsa_named_barrier_count") {
6371 if (!isGFX1250Plus())
6372 return Error(IDRange.Start, "directive requires gfx1250+", IDRange);
6373 NamedBarCnt = ExprVal;
6374 } else if (ID == ".amdhsa_reserve_vcc") {
6375 if (EvaluatableExpr && !isUInt<1>(Val))
6376 return OutOfRangeError(ValRange);
6377 ReserveVCC = ExprVal;
6378 } else if (ID == ".amdhsa_reserve_flat_scratch") {
6379 if (ISA.Major < 7)
6380 return Error(IDRange.Start, "directive requires gfx7+", IDRange);
6382 return Error(IDRange.Start,
6383 "directive is not supported with architected flat scratch",
6384 IDRange);
6385 if (EvaluatableExpr && !isUInt<1>(Val))
6386 return OutOfRangeError(ValRange);
6387 ReserveFlatScr = ExprVal;
6388 } else if (ID == ".amdhsa_reserve_xnack_mask") {
6389 if (ISA.Major < 8)
6390 return Error(IDRange.Start, "directive requires gfx8+", IDRange);
6391 if (!isUInt<1>(Val))
6392 return OutOfRangeError(ValRange);
6393 bool XnackOn = getTargetStreamer().getTargetID()->isXnackOnOrAny();
6394 if (Val != XnackOn) {
6395 return getParser().Error(
6396 IDRange.Start,
6397 ".amdhsa_reserve_xnack_mask does not match target id", IDRange);
6398 }
6399 } else if (ID == ".amdhsa_float_round_mode_32") {
6401 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32, ExprVal,
6402 ValRange);
6403 } else if (ID == ".amdhsa_float_round_mode_16_64") {
6405 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64, ExprVal,
6406 ValRange);
6407 } else if (ID == ".amdhsa_float_denorm_mode_32") {
6409 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32, ExprVal,
6410 ValRange);
6411 } else if (ID == ".amdhsa_float_denorm_mode_16_64") {
6413 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, ExprVal,
6414 ValRange);
6415 } else if (ID == ".amdhsa_dx10_clamp") {
6416 if (!getSTI().hasFeature(AMDGPU::FeatureDX10ClampAndIEEEMode))
6417 return Error(IDRange.Start, "directive unsupported on gfx1170+",
6418 IDRange);
6420 COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP, ExprVal,
6421 ValRange);
6422 } else if (ID == ".amdhsa_ieee_mode") {
6423 if (!getSTI().hasFeature(AMDGPU::FeatureDX10ClampAndIEEEMode))
6424 return Error(IDRange.Start, "directive unsupported on gfx1170+",
6425 IDRange);
6427 COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE, ExprVal,
6428 ValRange);
6429 } else if (ID == ".amdhsa_fp16_overflow") {
6430 if (ISA.Major < 9)
6431 return Error(IDRange.Start, "directive requires gfx9+", IDRange);
6433 COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL, ExprVal,
6434 ValRange);
6435 } else if (ID == ".amdhsa_tg_split") {
6436 if (!isGFX90A())
6437 return Error(IDRange.Start, "directive requires gfx90a+", IDRange);
6438 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc3, COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT,
6439 ExprVal, ValRange);
6440 } else if (ID == ".amdhsa_workgroup_processor_mode") {
6441 if (!supportsWGP(getSTI()))
6442 return Error(IDRange.Start,
6443 "directive unsupported on " + getSTI().getCPU(), IDRange);
6445 COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE, ExprVal,
6446 ValRange);
6447 } else if (ID == ".amdhsa_memory_ordered") {
6448 if (ISA.Major < 10)
6449 return Error(IDRange.Start, "directive requires gfx10+", IDRange);
6451 COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED, ExprVal,
6452 ValRange);
6453 } else if (ID == ".amdhsa_forward_progress") {
6454 if (ISA.Major < 10)
6455 return Error(IDRange.Start, "directive requires gfx10+", IDRange);
6457 COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS, ExprVal,
6458 ValRange);
6459 } else if (ID == ".amdhsa_shared_vgpr_count") {
6460 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6461 if (ISA.Major < 10 || ISA.Major >= 12)
6462 return Error(IDRange.Start, "directive requires gfx10 or gfx11",
6463 IDRange);
6464 SharedVGPRCount = Val;
6466 COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT, ExprVal,
6467 ValRange);
6468 } else if (ID == ".amdhsa_inst_pref_size") {
6469 if (ISA.Major < 11)
6470 return Error(IDRange.Start, "directive requires gfx11+", IDRange);
6471 if (ISA.Major == 11) {
6473 COMPUTE_PGM_RSRC3_GFX11_INST_PREF_SIZE, ExprVal,
6474 ValRange);
6475 } else {
6477 COMPUTE_PGM_RSRC3_GFX12_PLUS_INST_PREF_SIZE, ExprVal,
6478 ValRange);
6479 }
6480 } else if (ID == ".amdhsa_exception_fp_ieee_invalid_op") {
6483 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION,
6484 ExprVal, ValRange);
6485 } else if (ID == ".amdhsa_exception_fp_denorm_src") {
6487 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE,
6488 ExprVal, ValRange);
6489 } else if (ID == ".amdhsa_exception_fp_ieee_div_zero") {
6492 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO,
6493 ExprVal, ValRange);
6494 } else if (ID == ".amdhsa_exception_fp_ieee_overflow") {
6496 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW,
6497 ExprVal, ValRange);
6498 } else if (ID == ".amdhsa_exception_fp_ieee_underflow") {
6500 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW,
6501 ExprVal, ValRange);
6502 } else if (ID == ".amdhsa_exception_fp_ieee_inexact") {
6504 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT,
6505 ExprVal, ValRange);
6506 } else if (ID == ".amdhsa_exception_int_div_zero") {
6508 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO,
6509 ExprVal, ValRange);
6510 } else if (ID == ".amdhsa_round_robin_scheduling") {
6511 if (ISA.Major < 12)
6512 return Error(IDRange.Start, "directive requires gfx12+", IDRange);
6514 COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN, ExprVal,
6515 ValRange);
6516 } else {
6517 return Error(IDRange.Start, "unknown .amdhsa_kernel directive", IDRange);
6518 }
6519
6520#undef PARSE_BITS_ENTRY
6521 }
6522
6523 if (!Seen.contains(".amdhsa_next_free_vgpr"))
6524 return TokError(".amdhsa_next_free_vgpr directive is required");
6525
6526 if (!Seen.contains(".amdhsa_next_free_sgpr"))
6527 return TokError(".amdhsa_next_free_sgpr directive is required");
6528
6529 unsigned UserSGPRCount = ExplicitUserSGPRCount.value_or(ImpliedUserSGPRCount);
6530 if (UserSGPRCount > getMaxNumUserSGPRs())
6531 return TokError("too many user SGPRs enabled, found " +
6532 Twine(UserSGPRCount) + ", but only " +
6533 Twine(getMaxNumUserSGPRs()) + " are supported.");
6534
6535 // Consider the case where the total number of UserSGPRs with trailing
6536 // allocated preload SGPRs, is greater than the number of explicitly
6537 // referenced SGPRs.
6538 if (PreloadLength) {
6539 MCContext &Ctx = getContext();
6540 NextFreeSGPR = AMDGPUMCExpr::createMax(
6541 {NextFreeSGPR, MCConstantExpr::create(UserSGPRCount, Ctx)}, Ctx);
6542 }
6543
6544 const MCExpr *VGPRBlocks;
6545 const MCExpr *SGPRBlocks;
6546 if (calculateGPRBlocks(getFeatureBits(), ReserveVCC, ReserveFlatScr,
6547 getTargetStreamer().getTargetID()->isXnackOnOrAny(),
6548 EnableWavefrontSize32, NextFreeVGPR, VGPRRange,
6549 NextFreeSGPR, SGPRRange, VGPRBlocks, SGPRBlocks))
6550 return true;
6551
6552 int64_t EvaluatedVGPRBlocks;
6553 bool VGPRBlocksEvaluatable =
6554 VGPRBlocks->evaluateAsAbsolute(EvaluatedVGPRBlocks);
6555 if (VGPRBlocksEvaluatable &&
6557 static_cast<uint64_t>(EvaluatedVGPRBlocks))) {
6558 return OutOfRangeError(VGPRRange);
6559 }
6561 KD.compute_pgm_rsrc1, VGPRBlocks,
6562 COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT_SHIFT,
6563 COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT, getContext());
6564
6565 int64_t EvaluatedSGPRBlocks;
6566 if (SGPRBlocks->evaluateAsAbsolute(EvaluatedSGPRBlocks) &&
6568 static_cast<uint64_t>(EvaluatedSGPRBlocks)))
6569 return OutOfRangeError(SGPRRange);
6571 KD.compute_pgm_rsrc1, SGPRBlocks,
6572 COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT_SHIFT,
6573 COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT, getContext());
6574
6575 if (ExplicitUserSGPRCount && ImpliedUserSGPRCount > *ExplicitUserSGPRCount)
6576 return TokError("amdgpu_user_sgpr_count smaller than implied by "
6577 "enabled user SGPRs");
6578
6579 if (isGFX1250Plus()) {
6582 MCConstantExpr::create(UserSGPRCount, getContext()),
6583 COMPUTE_PGM_RSRC2_GFX125_USER_SGPR_COUNT_SHIFT,
6584 COMPUTE_PGM_RSRC2_GFX125_USER_SGPR_COUNT, getContext());
6585 } else {
6588 MCConstantExpr::create(UserSGPRCount, getContext()),
6589 COMPUTE_PGM_RSRC2_GFX6_GFX120_USER_SGPR_COUNT_SHIFT,
6590 COMPUTE_PGM_RSRC2_GFX6_GFX120_USER_SGPR_COUNT, getContext());
6591 }
6592
6593 int64_t IVal = 0;
6594 if (!KD.kernarg_size->evaluateAsAbsolute(IVal))
6595 return TokError("Kernarg size should be resolvable");
6596 uint64_t kernarg_size = IVal;
6597 if (PreloadLength && kernarg_size &&
6598 (PreloadLength * 4 + PreloadOffset * 4 > kernarg_size))
6599 return TokError("Kernarg preload length + offset is larger than the "
6600 "kernarg segment size");
6601
6602 if (isGFX90A()) {
6603 if (!Seen.contains(".amdhsa_accum_offset"))
6604 return TokError(".amdhsa_accum_offset directive is required");
6605 int64_t EvaluatedAccum;
6606 bool AccumEvaluatable = AccumOffset->evaluateAsAbsolute(EvaluatedAccum);
6607 uint64_t UEvaluatedAccum = EvaluatedAccum;
6608 if (AccumEvaluatable &&
6609 (UEvaluatedAccum < 4 || UEvaluatedAccum > 256 || (UEvaluatedAccum & 3)))
6610 return TokError("accum_offset should be in range [4..256] in "
6611 "increments of 4");
6612
6613 int64_t EvaluatedNumVGPR;
6614 if (NextFreeVGPR->evaluateAsAbsolute(EvaluatedNumVGPR) &&
6615 AccumEvaluatable &&
6616 UEvaluatedAccum >
6617 alignTo(std::max((uint64_t)1, (uint64_t)EvaluatedNumVGPR), 4))
6618 return TokError("accum_offset exceeds total VGPR allocation");
6619 const MCExpr *AdjustedAccum = MCBinaryExpr::createSub(
6621 AccumOffset, MCConstantExpr::create(4, getContext()), getContext()),
6624 COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT,
6625 COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET,
6626 getContext());
6627 }
6628
6629 if (isGFX1250Plus())
6631 COMPUTE_PGM_RSRC3_GFX125_NAMED_BAR_CNT_SHIFT,
6632 COMPUTE_PGM_RSRC3_GFX125_NAMED_BAR_CNT,
6633 getContext());
6634
6635 if (ISA.Major >= 10 && ISA.Major < 12) {
6636 // SharedVGPRCount < 16 checked by PARSE_ENTRY_BITS
6637 if (SharedVGPRCount && EnableWavefrontSize32 && *EnableWavefrontSize32) {
6638 return TokError("shared_vgpr_count directive not valid on "
6639 "wavefront size 32");
6640 }
6641
6642 if (VGPRBlocksEvaluatable &&
6643 (SharedVGPRCount * 2 + static_cast<uint64_t>(EvaluatedVGPRBlocks) >
6644 63)) {
6645 return TokError("shared_vgpr_count*2 + "
6646 "compute_pgm_rsrc1.GRANULATED_WORKITEM_VGPR_COUNT cannot "
6647 "exceed 63\n");
6648 }
6649 }
6650
6651 emitTargetDirective();
6652 getTargetStreamer().EmitAmdhsaKernelDescriptor(getSTI(), KernelName, KD,
6653 NextFreeVGPR, NextFreeSGPR,
6654 ReserveVCC, ReserveFlatScr);
6655 return false;
6656}
6657
6658bool AMDGPUAsmParser::ParseDirectiveAMDHSACodeObjectVersion() {
6659 uint32_t Version;
6660 if (ParseAsAbsoluteExpression(Version))
6661 return true;
6662
6663 getTargetStreamer().EmitDirectiveAMDHSACodeObjectVersion(Version);
6664 emitTargetDirective();
6665 return false;
6666}
6667
6668bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
6669 AMDGPUMCKernelCodeT &C) {
6670 // max_scratch_backing_memory_byte_size is deprecated. Ignore it while parsing
6671 // assembly for backwards compatibility.
6672 if (ID == "max_scratch_backing_memory_byte_size") {
6673 Parser.eatToEndOfStatement();
6674 return false;
6675 }
6676
6677 SmallString<40> ErrStr;
6678 raw_svector_ostream Err(ErrStr);
6679 if (!C.ParseKernelCodeT(ID, getParser(), Err)) {
6680 return TokError(Err.str());
6681 }
6682 Lex();
6683
6684 if (ID == "enable_wavefront_size32") {
6685 if (C.code_properties & AMD_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32) {
6686 if (!isGFX10Plus())
6687 return TokError("enable_wavefront_size32=1 is only allowed on GFX10+");
6688 if (!isWave32())
6689 return TokError("enable_wavefront_size32=1 requires +WavefrontSize32");
6690 } else {
6691 if (!isWave64())
6692 return TokError("enable_wavefront_size32=0 requires +WavefrontSize64");
6693 }
6694 }
6695
6696 if (ID == "wavefront_size") {
6697 if (C.wavefront_size == 5) {
6698 if (!isGFX10Plus())
6699 return TokError("wavefront_size=5 is only allowed on GFX10+");
6700 if (!isWave32())
6701 return TokError("wavefront_size=5 requires +WavefrontSize32");
6702 } else if (C.wavefront_size == 6) {
6703 if (!isWave64())
6704 return TokError("wavefront_size=6 requires +WavefrontSize64");
6705 }
6706 }
6707
6708 return false;
6709}
6710
6711bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
6712 AMDGPUMCKernelCodeT KernelCode;
6713 KernelCode.initDefault(getSTI(), getContext());
6714
6715 while (true) {
6716 // Lex EndOfStatement. This is in a while loop, because lexing a comment
6717 // will set the current token to EndOfStatement.
6718 while (trySkipToken(AsmToken::EndOfStatement))
6719 ;
6720
6721 StringRef ID;
6722 if (!parseId(ID, "expected value identifier or .end_amd_kernel_code_t"))
6723 return true;
6724
6725 if (ID == ".end_amd_kernel_code_t")
6726 break;
6727
6728 if (ParseAMDKernelCodeTValue(ID, KernelCode))
6729 return true;
6730 }
6731
6732 KernelCode.validate(&getSTI(), getContext());
6733 getTargetStreamer().EmitAMDKernelCodeT(KernelCode);
6734
6735 return false;
6736}
6737
6738bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
6739 StringRef KernelName;
6740 if (!parseId(KernelName, "expected symbol name"))
6741 return true;
6742
6743 getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
6745
6746 KernelScope.initialize(getContext());
6747 return false;
6748}
6749
6750bool AMDGPUAsmParser::ParseDirectiveISAVersion() {
6751 if (!getSTI().getTargetTriple().isAMDGCN()) {
6752 return Error(getLoc(),
6753 ".amd_amdgpu_isa directive is not available on non-amdgcn "
6754 "architectures");
6755 }
6756
6757 StringRef TargetIDDirective = getLexer().getTok().getStringContents();
6758
6759 std::optional<AMDGPU::TargetID> MaybeParsed =
6760 AMDGPU::TargetID::parseTargetIDString(TargetIDDirective);
6761 if (!MaybeParsed)
6762 return Error(getParser().getTok().getLoc(),
6763 "malformed target id '" + TargetIDDirective + "'");
6764
6765 const AMDGPU::TargetID &ParsedTargetID = *MaybeParsed;
6766 const Triple &TT = getSTI().getTargetTriple();
6767
6768 // The processor named in the target id must be covered by the triple's
6769 // subarch.
6770 if (!AMDGPU::isCPUValidForSubArch(TT.getSubArch(),
6771 ParsedTargetID.getGPUKind())) {
6772 return Error(getParser().getTok().getLoc(),
6773 "target id '" + TargetIDDirective +
6774 "' specifies a processor that is not valid for subarch '" +
6775 TT.getArchName() + "'");
6776 }
6777
6778 const std::optional<AMDGPU::TargetID> &CurrentTargetID =
6779 getTargetStreamer().getTargetID();
6780
6781 Triple DirectiveTriple(ParsedTargetID.getTargetTripleString());
6782 const Triple &STITriple = getSTI().getTargetTriple();
6783 if (!DirectiveTriple.isCompatibleWith(STITriple)) {
6784 return Error(getParser().getTok().getLoc(),
6785 ".amd_amdgpu_isa " + Twine(ParsedTargetID.toString()) +
6786 " is incompatible with " +
6787 Twine(CurrentTargetID->toString()));
6788 }
6789
6790 // Error if the ISA version doesn't match
6791 StringRef DirectiveProcessor =
6792 AMDGPU::getArchNameAMDGCN(ParsedTargetID.getGPUKind());
6793 AMDGPU::IsaVersion DirectiveISA = AMDGPU::getIsaVersion(DirectiveProcessor);
6794 if (DirectiveISA != ISA) {
6795 return Error(getParser().getTok().getLoc(),
6796 ".amd_amdgpu_isa directive processor " +
6797 Twine(DirectiveProcessor) +
6798 " does not match the specified processor " +
6799 Twine(getSTI().getCPU()));
6800 }
6801
6802 getTargetStreamer().EmitISAVersion();
6803 Lex();
6804
6805 return false;
6806}
6807
6808bool AMDGPUAsmParser::ParseDirectiveHSAMetadata() {
6809 assert(isHsaAbi(getSTI()));
6810
6811 std::string HSAMetadataString;
6812 if (ParseToEndDirective(HSAMD::V3::AssemblerDirectiveBegin,
6813 HSAMD::V3::AssemblerDirectiveEnd, HSAMetadataString))
6814 return true;
6815
6816 if (!getTargetStreamer().EmitHSAMetadataV3(HSAMetadataString))
6817 return Error(getLoc(), "invalid HSA metadata");
6818
6819 return false;
6820}
6821
6822/// Common code to parse out a block of text (typically YAML) between start and
6823/// end directives.
6824bool AMDGPUAsmParser::ParseToEndDirective(const char *AssemblerDirectiveBegin,
6825 const char *AssemblerDirectiveEnd,
6826 std::string &CollectString) {
6827
6828 raw_string_ostream CollectStream(CollectString);
6829
6830 getLexer().setSkipSpace(false);
6831
6832 bool FoundEnd = false;
6833 while (!isToken(AsmToken::Eof)) {
6834 while (isToken(AsmToken::Space)) {
6835 CollectStream << getTokenStr();
6836 Lex();
6837 }
6838
6839 if (trySkipId(AssemblerDirectiveEnd)) {
6840 FoundEnd = true;
6841 break;
6842 }
6843
6844 CollectStream << Parser.parseStringToEndOfStatement()
6845 << getContext().getAsmInfo().getSeparatorString();
6846
6847 Parser.eatToEndOfStatement();
6848 }
6849
6850 getLexer().setSkipSpace(true);
6851
6852 if (isToken(AsmToken::Eof) && !FoundEnd) {
6853 return TokError(Twine("expected directive ") +
6854 Twine(AssemblerDirectiveEnd) + Twine(" not found"));
6855 }
6856
6857 return false;
6858}
6859
6860/// Parse the assembler directive for new MsgPack-format PAL metadata.
6861bool AMDGPUAsmParser::ParseDirectivePALMetadataBegin() {
6862 std::string String;
6863 if (ParseToEndDirective(AMDGPU::PALMD::AssemblerDirectiveBegin,
6865 return true;
6866
6867 auto *PALMetadata = getTargetStreamer().getPALMetadata();
6868 if (!PALMetadata->setFromString(String))
6869 return Error(getLoc(), "invalid PAL metadata");
6870 return false;
6871}
6872
6873/// Parse the assembler directive for old linear-format PAL metadata.
6874bool AMDGPUAsmParser::ParseDirectivePALMetadata() {
6875 if (getSTI().getTargetTriple().getOS() != Triple::AMDPAL) {
6876 return Error(getLoc(), (Twine(PALMD::AssemblerDirective) +
6877 Twine(" directive is "
6878 "not available on non-amdpal OSes"))
6879 .str());
6880 }
6881
6882 auto *PALMetadata = getTargetStreamer().getPALMetadata();
6883 PALMetadata->setLegacy();
6884 for (;;) {
6885 uint32_t Key, Value;
6886 if (ParseAsAbsoluteExpression(Key)) {
6887 return TokError(Twine("invalid value in ") +
6889 }
6890 if (!trySkipToken(AsmToken::Comma)) {
6891 return TokError(Twine("expected an even number of values in ") +
6893 }
6894 if (ParseAsAbsoluteExpression(Value)) {
6895 return TokError(Twine("invalid value in ") +
6897 }
6898 PALMetadata->setRegister(Key, Value);
6899 if (!trySkipToken(AsmToken::Comma))
6900 break;
6901 }
6902 return false;
6903}
6904
6905/// ParseDirectiveAMDGPULDS
6906/// ::= .amdgpu_lds identifier ',' size_expression [',' align_expression]
6907bool AMDGPUAsmParser::ParseDirectiveAMDGPULDS() {
6908 if (getParser().checkForValidSection())
6909 return true;
6910
6911 StringRef Name;
6912 SMLoc NameLoc = getLoc();
6913 if (getParser().parseIdentifier(Name))
6914 return TokError("expected identifier in directive");
6915
6916 MCSymbol *Symbol = getContext().getOrCreateSymbol(Name);
6917 if (getParser().parseComma())
6918 return true;
6919
6920 unsigned LocalMemorySize = AMDGPU::IsaInfo::getLocalMemorySize(getSTI());
6921
6922 int64_t Size;
6923 SMLoc SizeLoc = getLoc();
6924 if (getParser().parseAbsoluteExpression(Size))
6925 return true;
6926 if (Size < 0)
6927 return Error(SizeLoc, "size must be non-negative");
6928 if (Size > LocalMemorySize)
6929 return Error(SizeLoc, "size is too large");
6930
6931 int64_t Alignment = 4;
6932 if (trySkipToken(AsmToken::Comma)) {
6933 SMLoc AlignLoc = getLoc();
6934 if (getParser().parseAbsoluteExpression(Alignment))
6935 return true;
6936 if (Alignment < 0 || !isPowerOf2_64(Alignment))
6937 return Error(AlignLoc, "alignment must be a power of two");
6938
6939 // Alignment larger than the size of LDS is possible in theory, as long
6940 // as the linker manages to place to symbol at address 0, but we do want
6941 // to make sure the alignment fits nicely into a 32-bit integer.
6942 if (Alignment >= 1u << 31)
6943 return Error(AlignLoc, "alignment is too large");
6944 }
6945
6946 if (parseEOL())
6947 return true;
6948
6949 Symbol->redefineIfPossible();
6950 if (!Symbol->isUndefined())
6951 return Error(NameLoc, "invalid symbol redefinition");
6952
6953 getTargetStreamer().emitAMDGPULDS(Symbol, Size, Align(Alignment));
6954 return false;
6955}
6956
6957bool AMDGPUAsmParser::ParseDirectiveAMDGPUInfo() {
6958 if (getParser().checkForValidSection())
6959 return true;
6960
6961 StringRef FuncName;
6962 if (getParser().parseIdentifier(FuncName))
6963 return TokError("expected symbol name after .amdgpu_info");
6964
6965 MCSymbol *FuncSym = getContext().getOrCreateSymbol(FuncName);
6966 AMDGPU::InfoSectionData ParsedInfoData;
6967 AMDGPU::FuncInfo FI;
6968 FI.Sym = FuncSym;
6969 bool HasScalarAttrs = false;
6970
6971 while (true) {
6972 while (trySkipToken(AsmToken::EndOfStatement))
6973 ;
6974
6975 StringRef ID;
6976 SMLoc IDLoc = getLoc();
6977 if (!parseId(ID, "expected directive or .end_amdgpu_info"))
6978 return true;
6979
6980 if (ID == ".end_amdgpu_info")
6981 break;
6982
6983 // Every per-entry directive shares the `.amdgpu_` namespace prefix; strip
6984 // it once and dispatch on the distinguishing suffix below. The unstripped
6985 // ID is preserved for diagnostics.
6986 StringRef Dir = ID;
6987 if (!Dir.consume_front(".amdgpu_"))
6988 return Error(IDLoc, "unknown .amdgpu_info directive '" + ID + "'");
6989
6990 if (Dir == "flags") {
6991 int64_t Val;
6992 if (getParser().parseAbsoluteExpression(Val))
6993 return true;
6994 auto Flags = static_cast<AMDGPU::FuncInfoFlags>(Val);
6995 FI.UsesVCC = !!(Flags & AMDGPU::FuncInfoFlags::FUNC_USES_VCC);
6996 FI.UsesFlatScratch =
6997 !!(Flags & AMDGPU::FuncInfoFlags::FUNC_USES_FLAT_SCRATCH);
6998 FI.HasDynStack = !!(Flags & AMDGPU::FuncInfoFlags::FUNC_HAS_DYN_STACK);
6999 HasScalarAttrs = true;
7000 } else if (Dir == "num_sgpr") {
7001 int64_t Val;
7002 if (getParser().parseAbsoluteExpression(Val))
7003 return true;
7004 FI.NumSGPR = static_cast<uint32_t>(Val);
7005 HasScalarAttrs = true;
7006 } else if (Dir == "num_vgpr") {
7007 int64_t Val;
7008 if (getParser().parseAbsoluteExpression(Val))
7009 return true;
7010 FI.NumArchVGPR = static_cast<uint32_t>(Val);
7011 HasScalarAttrs = true;
7012 } else if (Dir == "num_agpr") {
7013 int64_t Val;
7014 if (getParser().parseAbsoluteExpression(Val))
7015 return true;
7016 FI.NumAccVGPR = static_cast<uint32_t>(Val);
7017 HasScalarAttrs = true;
7018 } else if (Dir == "private_segment_size") {
7019 int64_t Val;
7020 if (getParser().parseAbsoluteExpression(Val))
7021 return true;
7022 FI.PrivateSegmentSize = static_cast<uint32_t>(Val);
7023 HasScalarAttrs = true;
7024 } else if (Dir == "use") {
7025 StringRef ResName;
7026 if (getParser().parseIdentifier(ResName))
7027 return TokError("expected resource symbol for .amdgpu_use");
7028 ParsedInfoData.Uses.push_back(
7029 {FuncSym, getContext().getOrCreateSymbol(ResName)});
7030 } else if (Dir == "call") {
7031 StringRef DstName;
7032 if (getParser().parseIdentifier(DstName))
7033 return TokError("expected callee symbol for .amdgpu_call");
7034 ParsedInfoData.Calls.push_back(
7035 {FuncSym, getContext().getOrCreateSymbol(DstName)});
7036 } else if (Dir == "indirect_call") {
7037 std::string TypeId;
7038 if (getParser().parseEscapedString(TypeId))
7039 return TokError("expected type ID string for .amdgpu_indirect_call");
7040 ParsedInfoData.IndirectCalls.push_back({FuncSym, std::move(TypeId)});
7041 } else if (Dir == "typeid") {
7042 std::string TypeId;
7043 if (getParser().parseEscapedString(TypeId))
7044 return TokError("expected type ID string for .amdgpu_typeid");
7045 ParsedInfoData.TypeIds.push_back({FuncSym, std::move(TypeId)});
7046 } else {
7047 return Error(IDLoc, "unknown .amdgpu_info directive '" + ID + "'");
7048 }
7049 }
7050
7051 if (HasScalarAttrs)
7052 ParsedInfoData.Funcs.push_back(std::move(FI));
7053
7054 AMDGPU::InfoSectionData &Data = InfoData ? *InfoData : InfoData.emplace();
7055 for (AMDGPU::FuncInfo &Func : ParsedInfoData.Funcs)
7056 Data.Funcs.push_back(std::move(Func));
7057 for (std::pair<MCSymbol *, MCSymbol *> &Use : ParsedInfoData.Uses)
7058 Data.Uses.push_back(Use);
7059 for (std::pair<MCSymbol *, MCSymbol *> &Call : ParsedInfoData.Calls)
7060 Data.Calls.push_back(Call);
7061 for (std::pair<MCSymbol *, std::string> &IndirectCall :
7062 ParsedInfoData.IndirectCalls)
7063 Data.IndirectCalls.push_back(std::move(IndirectCall));
7064 for (std::pair<MCSymbol *, std::string> &TypeId : ParsedInfoData.TypeIds)
7065 Data.TypeIds.push_back(std::move(TypeId));
7066
7067 return false;
7068}
7069
7070void AMDGPUAsmParser::doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) {
7071 // Record every parsed label in the timeline so that, at end of file, the
7072 // instructions following a kernel's label can be located regardless of
7073 // whether the .amdhsa_kernel directive came before or after the label.
7074 OpcodeStreamSymbols.emplace_back(Symbol, IDLoc, OpcodeStream.size());
7075}
7076
7077void AMDGPUAsmParser::checkKernelPrologues() {
7078 if (getFeatureBits()[AMDGPU::FeatureRequiresInitialUnclausedVmem]) {
7079 static const unsigned Required[] = {S_MOV_B64_gfx12, V_NOP_e32_gfx12,
7080 GLOBAL_PREFETCH_B8_SADDR_gfx1250};
7081 for (auto [Sym, Loc, Offset] : OpcodeStreamSymbols) {
7082 if (!AMDHSAKernelSymbols.contains(Sym))
7083 continue;
7084 ArrayRef<unsigned> Prologue = ArrayRef(OpcodeStream).drop_front(Offset);
7085 if (!Prologue.empty() && Prologue.front() == S_SETREG_IMM32_B32_gfx12)
7086 Prologue = Prologue.drop_front();
7087 if (Prologue.take_front(std::size(Required)) != ArrayRef(Required)) {
7088 Warning(Loc, "kernel '" + Sym->getName() +
7089 "' does not begin with the required prologue "
7090 "sequence: s_mov_b64 followed by v_nop and "
7091 "global_prefetch_b8");
7092 }
7093 }
7094 }
7095 OpcodeStream.clear();
7096 OpcodeStreamSymbols.clear();
7097 AMDHSAKernelSymbols.clear();
7098}
7099
7100void AMDGPUAsmParser::onEndOfFile() {
7101 emitTargetDirective();
7102 checkKernelPrologues();
7103 if (InfoData)
7104 getTargetStreamer().emitAMDGPUInfo(*InfoData);
7105}
7106
7107bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
7108 StringRef IDVal = DirectiveID.getString();
7109
7110 if (isHsaAbi(getSTI())) {
7111 if (IDVal == ".amdhsa_kernel")
7112 return ParseDirectiveAMDHSAKernel();
7113
7114 if (IDVal == ".amdhsa_code_object_version")
7115 return ParseDirectiveAMDHSACodeObjectVersion();
7116
7117 // TODO: Restructure/combine with PAL metadata directive.
7119 return ParseDirectiveHSAMetadata();
7120 } else {
7121 if (IDVal == ".amd_kernel_code_t")
7122 return ParseDirectiveAMDKernelCodeT();
7123
7124 if (IDVal == ".amdgpu_hsa_kernel")
7125 return ParseDirectiveAMDGPUHsaKernel();
7126
7127 if (IDVal == ".amd_amdgpu_isa")
7128 return ParseDirectiveISAVersion();
7129
7131 return Error(getLoc(), (Twine(HSAMD::AssemblerDirectiveBegin) +
7132 Twine(" directive is "
7133 "not available on non-amdhsa OSes"))
7134 .str());
7135 }
7136 }
7137
7138 if (IDVal == ".amdgcn_target")
7139 return ParseDirectiveAMDGCNTarget();
7140
7141 if (IDVal == ".amdgpu_lds")
7142 return ParseDirectiveAMDGPULDS();
7143
7144 if (IDVal == ".amdgpu_info")
7145 return ParseDirectiveAMDGPUInfo();
7146
7147 if (IDVal == PALMD::AssemblerDirectiveBegin)
7148 return ParseDirectivePALMetadataBegin();
7149
7150 if (IDVal == PALMD::AssemblerDirective)
7151 return ParseDirectivePALMetadata();
7152
7153 return true;
7154}
7155
7156bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
7157 MCRegister Reg) {
7158 if (MRI.regsOverlap(TTMP12_TTMP13_TTMP14_TTMP15, Reg))
7159 return isGFX9Plus();
7160
7161 // GFX10+ has 2 more SGPRs 104 and 105.
7162 if (MRI.regsOverlap(SGPR104_SGPR105, Reg))
7163 return hasSGPR104_SGPR105();
7164
7165 switch (Reg.id()) {
7166 case SRC_SHARED_BASE_LO:
7167 case SRC_SHARED_BASE:
7168 case SRC_SHARED_LIMIT_LO:
7169 case SRC_SHARED_LIMIT:
7170 return isGFX9Plus();
7171 case SRC_PRIVATE_BASE_LO:
7172 case SRC_PRIVATE_BASE:
7173 case SRC_PRIVATE_LIMIT_LO:
7174 case SRC_PRIVATE_LIMIT:
7175 return AMDGPU::hasPrivateApertureRegs(getSTI());
7176 case SRC_FLAT_SCRATCH_BASE_LO:
7177 case SRC_FLAT_SCRATCH_BASE_HI:
7178 return hasGloballyAddressableScratch();
7179 case SRC_POPS_EXITING_WAVE_ID:
7180 return hasPopsExitingWaveID(getSTI());
7181 case TBA:
7182 case TBA_LO:
7183 case TBA_HI:
7184 case TMA:
7185 case TMA_LO:
7186 case TMA_HI:
7187 return !isGFX9Plus();
7188 case XNACK_MASK:
7189 case XNACK_MASK_LO:
7190 case XNACK_MASK_HI:
7191 return (isVI() || isGFX9()) &&
7192 getTargetStreamer().getTargetID()->isXnackSupported();
7193 case SGPR_NULL:
7194 return isGFX10Plus();
7195 case SRC_EXECZ:
7196 case SRC_VCCZ:
7197 return !isGFX11Plus();
7198 default:
7199 break;
7200 }
7201
7202 if (isCI())
7203 return true;
7204
7205 if (isSI() || isGFX10Plus()) {
7206 // No flat_scr on SI.
7207 // On GFX10Plus flat scratch is not a valid register operand and can only be
7208 // accessed with s_setreg/s_getreg.
7209 switch (Reg.id()) {
7210 case FLAT_SCR:
7211 case FLAT_SCR_LO:
7212 case FLAT_SCR_HI:
7213 return false;
7214 default:
7215 return true;
7216 }
7217 }
7218
7219 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
7220 // SI/CI have.
7221 if (MRI.regsOverlap(SGPR102_SGPR103, Reg))
7222 return hasSGPR102_SGPR103();
7223
7224 return true;
7225}
7226
7227ParseStatus AMDGPUAsmParser::parseOperand(OperandVector &Operands,
7228 StringRef Mnemonic,
7229 OperandMode Mode) {
7230 ParseStatus Res = parseVOPD(Operands);
7231 if (Res.isSuccess() || Res.isFailure() || isToken(AsmToken::EndOfStatement))
7232 return Res;
7233
7234 // Try to parse with a custom parser
7235 Res = MatchOperandParserImpl(Operands, Mnemonic);
7236
7237 // If we successfully parsed the operand or if there as an error parsing,
7238 // we are done.
7239 //
7240 // If we are parsing after we reach EndOfStatement then this means we
7241 // are appending default values to the Operands list. This is only done
7242 // by custom parser, so we shouldn't continue on to the generic parsing.
7243 if (Res.isSuccess() || Res.isFailure() || isToken(AsmToken::EndOfStatement))
7244 return Res;
7245
7246 SMLoc RBraceLoc;
7247 SMLoc LBraceLoc = getLoc();
7248 if (Mode == OperandMode_NSA && trySkipToken(AsmToken::LBrac)) {
7249 unsigned Prefix = Operands.size();
7250
7251 for (;;) {
7252 auto Loc = getLoc();
7253 Res = parseReg(Operands);
7254 if (Res.isNoMatch())
7255 Error(Loc, "expected a register");
7256 if (!Res.isSuccess())
7257 return ParseStatus::Failure;
7258
7259 RBraceLoc = getLoc();
7260 if (trySkipToken(AsmToken::RBrac))
7261 break;
7262
7263 if (!skipToken(AsmToken::Comma,
7264 "expected a comma or a closing square bracket"))
7265 return ParseStatus::Failure;
7266 }
7267
7268 if (Operands.size() - Prefix > 1) {
7269 Operands.insert(Operands.begin() + Prefix,
7270 AMDGPUOperand::CreateToken(this, "[", LBraceLoc));
7271 Operands.push_back(AMDGPUOperand::CreateToken(this, "]", RBraceLoc));
7272 }
7273
7274 return ParseStatus::Success;
7275 }
7276
7277 return parseRegOrImm(Operands);
7278}
7279
7280StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
7281 // Clear any forced encodings from the previous instruction.
7282 setForcedEncodingSize(0);
7283 setForcedDPP(false);
7284 setForcedSDWA(false);
7285
7286 if (Name.consume_back("_e64_dpp")) {
7287 setForcedDPP(true);
7288 setForcedEncodingSize(64);
7289 return Name;
7290 }
7291 if (Name.consume_back("_e64")) {
7292 setForcedEncodingSize(64);
7293 return Name;
7294 }
7295 if (Name.consume_back("_e32")) {
7296 setForcedEncodingSize(32);
7297 return Name;
7298 }
7299 if (Name.consume_back("_dpp")) {
7300 setForcedDPP(true);
7301 return Name;
7302 }
7303 if (Name.consume_back("_sdwa")) {
7304 setForcedSDWA(true);
7305 return Name;
7306 }
7307 return Name;
7308}
7309
7310static void applyMnemonicAliases(StringRef &Mnemonic,
7311 const FeatureBitset &Features,
7312 unsigned VariantID);
7313
7314bool AMDGPUAsmParser::parseInstruction(ParseInstructionInfo &Info,
7315 StringRef Name, SMLoc NameLoc,
7317 // Add the instruction mnemonic
7318 Name = parseMnemonicSuffix(Name);
7319
7320 // If the target architecture uses MnemonicAlias, call it here to parse
7321 // operands correctly.
7322 applyMnemonicAliases(Name, getAvailableFeatures(), 0);
7323
7324 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc));
7325
7326 bool IsMIMG = Name.starts_with("image_");
7327
7328 while (!trySkipToken(AsmToken::EndOfStatement)) {
7329 OperandMode Mode = OperandMode_Default;
7330 if (IsMIMG && isGFX10Plus() && Operands.size() == 2)
7331 Mode = OperandMode_NSA;
7332 ParseStatus Res = parseOperand(Operands, Name, Mode);
7333
7334 if (!Res.isSuccess()) {
7335 checkUnsupportedInstruction(Name, NameLoc);
7336 if (!Parser.hasPendingError()) {
7337 // FIXME: use real operand location rather than the current location.
7338 StringRef Msg = Res.isFailure() ? "failed parsing operand."
7339 : "not a valid operand.";
7340 Error(getLoc(), Msg);
7341 }
7342 while (!trySkipToken(AsmToken::EndOfStatement)) {
7343 lex();
7344 }
7345 return true;
7346 }
7347
7348 // Eat the comma or space if there is one.
7349 trySkipToken(AsmToken::Comma);
7350 }
7351
7352 return false;
7353}
7354
7355//===----------------------------------------------------------------------===//
7356// Utility functions
7357//===----------------------------------------------------------------------===//
7358
7359ParseStatus AMDGPUAsmParser::parseTokenOp(StringRef Name,
7361 SMLoc S = getLoc();
7362 if (!trySkipId(Name))
7363 return ParseStatus::NoMatch;
7364
7365 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, S));
7366 return ParseStatus::Success;
7367}
7368
7369ParseStatus AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix,
7370 int64_t &IntVal) {
7371
7372 if (!trySkipId(Prefix, AsmToken::Colon))
7373 return ParseStatus::NoMatch;
7374
7376}
7377
7378ParseStatus AMDGPUAsmParser::parseIntWithPrefix(
7379 const char *Prefix, OperandVector &Operands, AMDGPUOperand::ImmTy ImmTy,
7380 std::function<bool(int64_t &)> ConvertResult) {
7381 SMLoc S = getLoc();
7382 int64_t Value = 0;
7383
7384 ParseStatus Res = parseIntWithPrefix(Prefix, Value);
7385 if (!Res.isSuccess())
7386 return Res;
7387
7388 if (ConvertResult && !ConvertResult(Value)) {
7389 Error(S, "invalid " + StringRef(Prefix) + " value.");
7390 }
7391
7392 Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy));
7393 return ParseStatus::Success;
7394}
7395
7396ParseStatus AMDGPUAsmParser::parseOperandArrayWithPrefix(
7397 const char *Prefix, OperandVector &Operands, AMDGPUOperand::ImmTy ImmTy,
7398 bool (*ConvertResult)(int64_t &)) {
7399 SMLoc S = getLoc();
7400 if (!trySkipId(Prefix, AsmToken::Colon))
7401 return ParseStatus::NoMatch;
7402
7403 if (!skipToken(AsmToken::LBrac, "expected a left square bracket"))
7404 return ParseStatus::Failure;
7405
7406 unsigned Val = 0;
7407 const unsigned MaxSize = 4;
7408
7409 // FIXME: How to verify the number of elements matches the number of src
7410 // operands?
7411 for (int I = 0;; ++I) {
7412 int64_t Op;
7413 SMLoc Loc = getLoc();
7414 if (!parseExpr(Op))
7415 return ParseStatus::Failure;
7416
7417 if (Op != 0 && Op != 1)
7418 return Error(Loc, "invalid " + StringRef(Prefix) + " value.");
7419
7420 Val |= (Op << I);
7421
7422 if (trySkipToken(AsmToken::RBrac))
7423 break;
7424
7425 if (I + 1 == MaxSize)
7426 return Error(getLoc(), "expected a closing square bracket");
7427
7428 if (!skipToken(AsmToken::Comma, "expected a comma"))
7429 return ParseStatus::Failure;
7430 }
7431
7432 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, ImmTy));
7433 return ParseStatus::Success;
7434}
7435
7436ParseStatus AMDGPUAsmParser::parseNamedBit(StringRef Name,
7438 AMDGPUOperand::ImmTy ImmTy,
7439 bool IgnoreNegative) {
7440 int64_t Bit;
7441 SMLoc S = getLoc();
7442
7443 if (trySkipId(Name)) {
7444 Bit = 1;
7445 } else if (trySkipId("no", Name)) {
7446 if (IgnoreNegative)
7447 return ParseStatus::Success;
7448 Bit = 0;
7449 } else {
7450 return ParseStatus::NoMatch;
7451 }
7452
7453 if (Name == "r128" && !hasMIMG_R128())
7454 return Error(S, "r128 modifier is not supported on this GPU");
7455 if (Name == "a16" && !hasA16())
7456 return Error(S, "a16 modifier is not supported on this GPU");
7457
7458 if (Bit == 0 && Name == "gds") {
7459 StringRef Mnemo = ((AMDGPUOperand &)*Operands[0]).getToken();
7460 if (Mnemo.starts_with("ds_gws"))
7461 return Error(S, "nogds is not allowed");
7462 }
7463
7464 if (isGFX9() && ImmTy == AMDGPUOperand::ImmTyA16)
7465 ImmTy = AMDGPUOperand::ImmTyR128A16;
7466
7467 Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy));
7468 return ParseStatus::Success;
7469}
7470
7471unsigned AMDGPUAsmParser::getCPolKind(StringRef Id, StringRef Mnemo,
7472 bool &Disabling) const {
7473 Disabling = Id.consume_front("no");
7474
7475 if (isGFX940() && !Mnemo.starts_with("s_")) {
7476 return StringSwitch<unsigned>(Id)
7477 .Case("nt", AMDGPU::CPol::NT)
7478 .Case("sc0", AMDGPU::CPol::SC0)
7479 .Case("sc1", AMDGPU::CPol::SC1)
7480 .Default(0);
7481 }
7482
7483 return StringSwitch<unsigned>(Id)
7484 .Case("dlc", AMDGPU::CPol::DLC)
7485 .Case("glc", AMDGPU::CPol::GLC)
7486 .Case("scc", AMDGPU::CPol::SCC)
7487 .Case("slc", AMDGPU::CPol::SLC)
7488 .Default(0);
7489}
7490
7491ParseStatus AMDGPUAsmParser::parseCPol(OperandVector &Operands) {
7492 if (isGFX12Plus()) {
7493 SMLoc StringLoc = getLoc();
7494
7495 int64_t CPolVal = 0;
7496 ParseStatus ResTH = ParseStatus::NoMatch;
7497 ParseStatus ResScope = ParseStatus::NoMatch;
7498 ParseStatus ResNV = ParseStatus::NoMatch;
7499 ParseStatus ResScal = ParseStatus::NoMatch;
7500
7501 for (;;) {
7502 if (ResTH.isNoMatch()) {
7503 int64_t TH;
7504 ResTH = parseTH(Operands, TH);
7505 if (ResTH.isFailure())
7506 return ResTH;
7507 if (ResTH.isSuccess()) {
7508 CPolVal |= TH;
7509 continue;
7510 }
7511 }
7512
7513 if (ResScope.isNoMatch()) {
7514 int64_t Scope;
7515 ResScope = parseScope(Operands, Scope);
7516 if (ResScope.isFailure())
7517 return ResScope;
7518 if (ResScope.isSuccess()) {
7519 CPolVal |= Scope;
7520 continue;
7521 }
7522 }
7523
7524 // NV bit exists on GFX12+, but does something starting from GFX1250.
7525 // Allow parsing on all GFX12 and fail on validation for better
7526 // diagnostics.
7527 if (ResNV.isNoMatch()) {
7528 if (trySkipId("nv")) {
7529 ResNV = ParseStatus::Success;
7530 CPolVal |= CPol::NV;
7531 continue;
7532 } else if (trySkipId("no", "nv")) {
7533 ResNV = ParseStatus::Success;
7534 continue;
7535 }
7536 }
7537
7538 if (ResScal.isNoMatch()) {
7539 if (trySkipId("scale_offset")) {
7540 ResScal = ParseStatus::Success;
7541 CPolVal |= CPol::SCAL;
7542 continue;
7543 } else if (trySkipId("no", "scale_offset")) {
7544 ResScal = ParseStatus::Success;
7545 continue;
7546 }
7547 }
7548
7549 break;
7550 }
7551
7552 if (ResTH.isNoMatch() && ResScope.isNoMatch() && ResNV.isNoMatch() &&
7553 ResScal.isNoMatch())
7554 return ParseStatus::NoMatch;
7555
7556 Operands.push_back(AMDGPUOperand::CreateImm(this, CPolVal, StringLoc,
7557 AMDGPUOperand::ImmTyCPol));
7558 return ParseStatus::Success;
7559 }
7560
7561 StringRef Mnemo = ((AMDGPUOperand &)*Operands[0]).getToken();
7562 SMLoc OpLoc = getLoc();
7563 unsigned Enabled = 0, Seen = 0;
7564 for (;;) {
7565 SMLoc S = getLoc();
7566 bool Disabling;
7567 unsigned CPol = getCPolKind(getId(), Mnemo, Disabling);
7568 if (!CPol)
7569 break;
7570
7571 lex();
7572
7573 if (!isGFX10Plus() && CPol == AMDGPU::CPol::DLC)
7574 return Error(S, "dlc modifier is not supported on this GPU");
7575
7576 if (!isGFX90A() && CPol == AMDGPU::CPol::SCC)
7577 return Error(S, "scc modifier is not supported on this GPU");
7578
7579 if (Seen & CPol)
7580 return Error(S, "duplicate cache policy modifier");
7581
7582 if (!Disabling)
7583 Enabled |= CPol;
7584
7585 Seen |= CPol;
7586 }
7587
7588 if (!Seen)
7589 return ParseStatus::NoMatch;
7590
7591 Operands.push_back(
7592 AMDGPUOperand::CreateImm(this, Enabled, OpLoc, AMDGPUOperand::ImmTyCPol));
7593 return ParseStatus::Success;
7594}
7595
7596ParseStatus AMDGPUAsmParser::parseScope(OperandVector &Operands,
7597 int64_t &Scope) {
7598 static const unsigned Scopes[] = {CPol::SCOPE_CU, CPol::SCOPE_SE,
7600
7601 ParseStatus Res = parseStringOrIntWithPrefix(
7602 Operands, "scope", {"SCOPE_CU", "SCOPE_SE", "SCOPE_DEV", "SCOPE_SYS"},
7603 Scope);
7604
7605 if (Res.isSuccess())
7606 Scope = Scopes[Scope];
7607
7608 return Res;
7609}
7610
7611ParseStatus AMDGPUAsmParser::parseTH(OperandVector &Operands, int64_t &TH) {
7612 TH = AMDGPU::CPol::TH_RT; // default
7613
7614 StringRef Value;
7615 SMLoc StringLoc;
7616 ParseStatus Res = parseStringWithPrefix("th", Value, StringLoc);
7617 if (!Res.isSuccess())
7618 return Res;
7619
7620 if (Value == "TH_DEFAULT")
7622 else if (Value == "TH_STORE_LU" || Value == "TH_LOAD_WB" ||
7623 Value == "TH_LOAD_NT_WB") {
7624 return Error(StringLoc, "invalid th value");
7625 } else if (Value.consume_front("TH_ATOMIC_")) {
7627 } else if (Value.consume_front("TH_LOAD_")) {
7629 } else if (Value.consume_front("TH_STORE_")) {
7631 } else {
7632 return Error(StringLoc, "invalid th value");
7633 }
7634
7635 if (Value == "BYPASS")
7637
7638 if (TH != 0) {
7640 TH |= StringSwitch<int64_t>(Value)
7641 .Case("RETURN", AMDGPU::CPol::TH_ATOMIC_RETURN)
7642 .Case("RT", AMDGPU::CPol::TH_RT)
7643 .Case("RT_RETURN", AMDGPU::CPol::TH_ATOMIC_RETURN)
7644 .Case("NT", AMDGPU::CPol::TH_ATOMIC_NT)
7645 .Case("NT_RETURN", AMDGPU::CPol::TH_ATOMIC_NT |
7647 .Case("CASCADE_RT", AMDGPU::CPol::TH_ATOMIC_CASCADE)
7648 .Case("CASCADE_NT", AMDGPU::CPol::TH_ATOMIC_CASCADE |
7650 .Default(0xffffffff);
7651 else
7652 TH |= StringSwitch<int64_t>(Value)
7653 .Case("RT", AMDGPU::CPol::TH_RT)
7654 .Case("NT", AMDGPU::CPol::TH_NT)
7655 .Case("HT", AMDGPU::CPol::TH_HT)
7656 .Case("LU", AMDGPU::CPol::TH_LU)
7657 .Case("WB", AMDGPU::CPol::TH_WB)
7658 .Case("NT_RT", AMDGPU::CPol::TH_NT_RT)
7659 .Case("RT_NT", AMDGPU::CPol::TH_RT_NT)
7660 .Case("NT_HT", AMDGPU::CPol::TH_NT_HT)
7661 .Case("NT_WB", AMDGPU::CPol::TH_NT_WB)
7662 .Case("BYPASS", AMDGPU::CPol::TH_BYPASS)
7663 .Default(0xffffffff);
7664 }
7665
7666 if (TH == 0xffffffff)
7667 return Error(StringLoc, "invalid th value");
7668
7669 return ParseStatus::Success;
7670}
7671
7672static void
7674 AMDGPUAsmParser::OptionalImmIndexMap &OptionalIdx,
7675 AMDGPUOperand::ImmTy ImmT, int64_t Default = 0,
7676 std::optional<unsigned> InsertAt = std::nullopt) {
7677 auto i = OptionalIdx.find(ImmT);
7678 if (i != OptionalIdx.end()) {
7679 unsigned Idx = i->second;
7680 const AMDGPUOperand &Op =
7681 static_cast<const AMDGPUOperand &>(*Operands[Idx]);
7682 if (InsertAt)
7683 Inst.insert(Inst.begin() + *InsertAt, MCOperand::createImm(Op.getImm()));
7684 else
7685 Op.addImmOperands(Inst, 1);
7686 } else {
7687 if (InsertAt.has_value())
7688 Inst.insert(Inst.begin() + *InsertAt, MCOperand::createImm(Default));
7689 else
7691 }
7692}
7693
7694ParseStatus AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix,
7695 StringRef &Value,
7696 SMLoc &StringLoc) {
7697 if (!trySkipId(Prefix, AsmToken::Colon))
7698 return ParseStatus::NoMatch;
7699
7700 StringLoc = getLoc();
7701 return parseId(Value, "expected an identifier") ? ParseStatus::Success
7703}
7704
7705ParseStatus AMDGPUAsmParser::parseStringOrIntWithPrefix(
7706 OperandVector &Operands, StringRef Name, ArrayRef<const char *> Ids,
7707 int64_t &IntVal) {
7708 if (!trySkipId(Name, AsmToken::Colon))
7709 return ParseStatus::NoMatch;
7710
7711 SMLoc StringLoc = getLoc();
7712
7713 StringRef Value;
7714 if (isToken(AsmToken::Identifier)) {
7715 Value = getTokenStr();
7716 lex();
7717
7718 for (IntVal = 0; IntVal < (int64_t)Ids.size(); ++IntVal)
7719 if (Value == Ids[IntVal])
7720 break;
7721 } else if (!parseExpr(IntVal))
7722 return ParseStatus::Failure;
7723
7724 if (IntVal < 0 || IntVal >= (int64_t)Ids.size())
7725 return Error(StringLoc, "invalid " + Twine(Name) + " value");
7726
7727 return ParseStatus::Success;
7728}
7729
7730ParseStatus AMDGPUAsmParser::parseStringOrIntWithPrefix(
7731 OperandVector &Operands, StringRef Name, ArrayRef<const char *> Ids,
7732 AMDGPUOperand::ImmTy Type) {
7733 SMLoc S = getLoc();
7734 int64_t IntVal;
7735
7736 ParseStatus Res = parseStringOrIntWithPrefix(Operands, Name, Ids, IntVal);
7737 if (Res.isSuccess())
7738 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S, Type));
7739
7740 return Res;
7741}
7742
7743//===----------------------------------------------------------------------===//
7744// MTBUF format
7745//===----------------------------------------------------------------------===//
7746
7747bool AMDGPUAsmParser::tryParseFmt(const char *Pref, int64_t MaxVal,
7748 int64_t &Fmt) {
7749 int64_t Val;
7750 SMLoc Loc = getLoc();
7751
7752 auto Res = parseIntWithPrefix(Pref, Val);
7753 if (Res.isFailure())
7754 return false;
7755 if (Res.isNoMatch())
7756 return true;
7757
7758 if (Val < 0 || Val > MaxVal) {
7759 Error(Loc, Twine("out of range ", StringRef(Pref)));
7760 return false;
7761 }
7762
7763 Fmt = Val;
7764 return true;
7765}
7766
7767ParseStatus AMDGPUAsmParser::tryParseIndexKey(OperandVector &Operands,
7768 AMDGPUOperand::ImmTy ImmTy) {
7769 const char *Pref = "index_key";
7770 int64_t ImmVal = 0;
7771 SMLoc Loc = getLoc();
7772 auto Res = parseIntWithPrefix(Pref, ImmVal);
7773 if (!Res.isSuccess())
7774 return Res;
7775
7776 if ((ImmTy == AMDGPUOperand::ImmTyIndexKey16bit ||
7777 ImmTy == AMDGPUOperand::ImmTyIndexKey32bit) &&
7778 (ImmVal < 0 || ImmVal > 1))
7779 return Error(Loc, Twine("out of range ", StringRef(Pref)));
7780
7781 if (ImmTy == AMDGPUOperand::ImmTyIndexKey8bit && (ImmVal < 0 || ImmVal > 3))
7782 return Error(Loc, Twine("out of range ", StringRef(Pref)));
7783
7784 Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc, ImmTy));
7785 return ParseStatus::Success;
7786}
7787
7788ParseStatus AMDGPUAsmParser::parseIndexKey8bit(OperandVector &Operands) {
7789 return tryParseIndexKey(Operands, AMDGPUOperand::ImmTyIndexKey8bit);
7790}
7791
7792ParseStatus AMDGPUAsmParser::parseIndexKey16bit(OperandVector &Operands) {
7793 return tryParseIndexKey(Operands, AMDGPUOperand::ImmTyIndexKey16bit);
7794}
7795
7796ParseStatus AMDGPUAsmParser::parseIndexKey32bit(OperandVector &Operands) {
7797 return tryParseIndexKey(Operands, AMDGPUOperand::ImmTyIndexKey32bit);
7798}
7799
7800ParseStatus AMDGPUAsmParser::tryParseMatrixFMT(OperandVector &Operands,
7801 StringRef Name,
7802 AMDGPUOperand::ImmTy Type) {
7803 return parseStringOrIntWithPrefix(Operands, Name, WMMAMods::ModMatrixFmt,
7804 Type);
7805}
7806
7807ParseStatus AMDGPUAsmParser::parseMatrixAFMT(OperandVector &Operands) {
7808 return tryParseMatrixFMT(Operands, "matrix_a_fmt",
7809 AMDGPUOperand::ImmTyMatrixAFMT);
7810}
7811
7812ParseStatus AMDGPUAsmParser::parseMatrixBFMT(OperandVector &Operands) {
7813 return tryParseMatrixFMT(Operands, "matrix_b_fmt",
7814 AMDGPUOperand::ImmTyMatrixBFMT);
7815}
7816
7817ParseStatus AMDGPUAsmParser::tryParseMatrixScale(OperandVector &Operands,
7818 StringRef Name,
7819 AMDGPUOperand::ImmTy Type) {
7820 return parseStringOrIntWithPrefix(Operands, Name, WMMAMods::ModMatrixScale,
7821 Type);
7822}
7823
7824ParseStatus AMDGPUAsmParser::parseMatrixAScale(OperandVector &Operands) {
7825 return tryParseMatrixScale(Operands, "matrix_a_scale",
7826 AMDGPUOperand::ImmTyMatrixAScale);
7827}
7828
7829ParseStatus AMDGPUAsmParser::parseMatrixBScale(OperandVector &Operands) {
7830 return tryParseMatrixScale(Operands, "matrix_b_scale",
7831 AMDGPUOperand::ImmTyMatrixBScale);
7832}
7833
7834ParseStatus AMDGPUAsmParser::tryParseMatrixScaleFmt(OperandVector &Operands,
7835 StringRef Name,
7836 AMDGPUOperand::ImmTy Type) {
7837 return parseStringOrIntWithPrefix(Operands, Name, WMMAMods::ModMatrixScaleFmt,
7838 Type);
7839}
7840
7841ParseStatus AMDGPUAsmParser::parseMatrixAScaleFmt(OperandVector &Operands) {
7842 return tryParseMatrixScaleFmt(Operands, "matrix_a_scale_fmt",
7843 AMDGPUOperand::ImmTyMatrixAScaleFmt);
7844}
7845
7846ParseStatus AMDGPUAsmParser::parseMatrixBScaleFmt(OperandVector &Operands) {
7847 return tryParseMatrixScaleFmt(Operands, "matrix_b_scale_fmt",
7848 AMDGPUOperand::ImmTyMatrixBScaleFmt);
7849}
7850
7851// dfmt and nfmt (in a tbuffer instruction) are parsed as one to allow their
7852// values to live in a joint format operand in the MCInst encoding.
7853ParseStatus AMDGPUAsmParser::parseDfmtNfmt(int64_t &Format) {
7854 using namespace llvm::AMDGPU::MTBUFFormat;
7855
7856 int64_t Dfmt = DFMT_UNDEF;
7857 int64_t Nfmt = NFMT_UNDEF;
7858
7859 // dfmt and nfmt can appear in either order, and each is optional.
7860 for (int I = 0; I < 2; ++I) {
7861 if (Dfmt == DFMT_UNDEF && !tryParseFmt("dfmt", DFMT_MAX, Dfmt))
7862 return ParseStatus::Failure;
7863
7864 if (Nfmt == NFMT_UNDEF && !tryParseFmt("nfmt", NFMT_MAX, Nfmt))
7865 return ParseStatus::Failure;
7866
7867 // Skip optional comma between dfmt/nfmt
7868 // but guard against 2 commas following each other.
7869 if ((Dfmt == DFMT_UNDEF) != (Nfmt == NFMT_UNDEF) &&
7870 !peekToken().is(AsmToken::Comma)) {
7871 trySkipToken(AsmToken::Comma);
7872 }
7873 }
7874
7875 if (Dfmt == DFMT_UNDEF && Nfmt == NFMT_UNDEF)
7876 return ParseStatus::NoMatch;
7877
7878 Dfmt = (Dfmt == DFMT_UNDEF) ? DFMT_DEFAULT : Dfmt;
7879 Nfmt = (Nfmt == NFMT_UNDEF) ? NFMT_DEFAULT : Nfmt;
7880
7881 Format = encodeDfmtNfmt(Dfmt, Nfmt);
7882 return ParseStatus::Success;
7883}
7884
7885ParseStatus AMDGPUAsmParser::parseUfmt(int64_t &Format) {
7886 using namespace llvm::AMDGPU::MTBUFFormat;
7887
7888 int64_t Fmt = UFMT_UNDEF;
7889
7890 if (!tryParseFmt("format", UFMT_MAX, Fmt))
7891 return ParseStatus::Failure;
7892
7893 if (Fmt == UFMT_UNDEF)
7894 return ParseStatus::NoMatch;
7895
7896 Format = Fmt;
7897 return ParseStatus::Success;
7898}
7899
7900bool AMDGPUAsmParser::matchDfmtNfmt(int64_t &Dfmt, int64_t &Nfmt,
7901 StringRef FormatStr, SMLoc Loc) {
7902 using namespace llvm::AMDGPU::MTBUFFormat;
7903 int64_t Format;
7904
7905 Format = getDfmt(FormatStr);
7906 if (Format != DFMT_UNDEF) {
7907 Dfmt = Format;
7908 return true;
7909 }
7910
7911 Format = getNfmt(FormatStr, getSTI());
7912 if (Format != NFMT_UNDEF) {
7913 Nfmt = Format;
7914 return true;
7915 }
7916
7917 Error(Loc, "unsupported format");
7918 return false;
7919}
7920
7921ParseStatus AMDGPUAsmParser::parseSymbolicSplitFormat(StringRef FormatStr,
7922 SMLoc FormatLoc,
7923 int64_t &Format) {
7924 using namespace llvm::AMDGPU::MTBUFFormat;
7925
7926 int64_t Dfmt = DFMT_UNDEF;
7927 int64_t Nfmt = NFMT_UNDEF;
7928 if (!matchDfmtNfmt(Dfmt, Nfmt, FormatStr, FormatLoc))
7929 return ParseStatus::Failure;
7930
7931 if (trySkipToken(AsmToken::Comma)) {
7932 StringRef Str;
7933 SMLoc Loc = getLoc();
7934 if (!parseId(Str, "expected a format string") ||
7935 !matchDfmtNfmt(Dfmt, Nfmt, Str, Loc))
7936 return ParseStatus::Failure;
7937 if (Dfmt == DFMT_UNDEF)
7938 return Error(Loc, "duplicate numeric format");
7939 if (Nfmt == NFMT_UNDEF)
7940 return Error(Loc, "duplicate data format");
7941 }
7942
7943 Dfmt = (Dfmt == DFMT_UNDEF) ? DFMT_DEFAULT : Dfmt;
7944 Nfmt = (Nfmt == NFMT_UNDEF) ? NFMT_DEFAULT : Nfmt;
7945
7946 if (isGFX10Plus()) {
7947 auto Ufmt = convertDfmtNfmt2Ufmt(Dfmt, Nfmt, getSTI());
7948 if (Ufmt == UFMT_UNDEF)
7949 return Error(FormatLoc, "unsupported format");
7950 Format = Ufmt;
7951 } else {
7952 Format = encodeDfmtNfmt(Dfmt, Nfmt);
7953 }
7954
7955 return ParseStatus::Success;
7956}
7957
7958ParseStatus AMDGPUAsmParser::parseSymbolicUnifiedFormat(StringRef FormatStr,
7959 SMLoc Loc,
7960 int64_t &Format) {
7961 using namespace llvm::AMDGPU::MTBUFFormat;
7962
7963 auto Id = getUnifiedFormat(FormatStr, getSTI());
7964 if (Id == UFMT_UNDEF)
7965 return ParseStatus::NoMatch;
7966
7967 if (!isGFX10Plus())
7968 return Error(Loc, "unified format is not supported on this GPU");
7969
7970 Format = Id;
7971 return ParseStatus::Success;
7972}
7973
7974ParseStatus AMDGPUAsmParser::parseNumericFormat(int64_t &Format) {
7975 using namespace llvm::AMDGPU::MTBUFFormat;
7976 SMLoc Loc = getLoc();
7977
7978 if (!parseExpr(Format))
7979 return ParseStatus::Failure;
7980 if (!isValidFormatEncoding(Format, getSTI()))
7981 return Error(Loc, "out of range format");
7982
7983 return ParseStatus::Success;
7984}
7985
7986ParseStatus AMDGPUAsmParser::parseSymbolicOrNumericFormat(int64_t &Format) {
7987 using namespace llvm::AMDGPU::MTBUFFormat;
7988
7989 if (!trySkipId("format", AsmToken::Colon))
7990 return ParseStatus::NoMatch;
7991
7992 if (trySkipToken(AsmToken::LBrac)) {
7993 StringRef FormatStr;
7994 SMLoc Loc = getLoc();
7995 if (!parseId(FormatStr, "expected a format string"))
7996 return ParseStatus::Failure;
7997
7998 auto Res = parseSymbolicUnifiedFormat(FormatStr, Loc, Format);
7999 if (Res.isNoMatch())
8000 Res = parseSymbolicSplitFormat(FormatStr, Loc, Format);
8001 if (!Res.isSuccess())
8002 return Res;
8003
8004 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket"))
8005 return ParseStatus::Failure;
8006
8007 return ParseStatus::Success;
8008 }
8009
8010 return parseNumericFormat(Format);
8011}
8012
8013ParseStatus AMDGPUAsmParser::parseFORMAT(OperandVector &Operands) {
8014 using namespace llvm::AMDGPU::MTBUFFormat;
8015
8016 int64_t Format = getDefaultFormatEncoding(getSTI());
8017 ParseStatus Res;
8018 SMLoc Loc = getLoc();
8019
8020 // Parse legacy format syntax.
8021 Res = isGFX10Plus() ? parseUfmt(Format) : parseDfmtNfmt(Format);
8022 if (Res.isFailure())
8023 return Res;
8024
8025 bool FormatFound = Res.isSuccess();
8026
8027 Operands.push_back(
8028 AMDGPUOperand::CreateImm(this, Format, Loc, AMDGPUOperand::ImmTyFORMAT));
8029
8030 if (FormatFound)
8031 trySkipToken(AsmToken::Comma);
8032
8033 if (isToken(AsmToken::EndOfStatement)) {
8034 // We are expecting an soffset operand,
8035 // but let matcher handle the error.
8036 return ParseStatus::Success;
8037 }
8038
8039 // Parse soffset.
8040 Res = parseRegOrImm(Operands);
8041 if (!Res.isSuccess())
8042 return Res;
8043
8044 trySkipToken(AsmToken::Comma);
8045
8046 if (!FormatFound) {
8047 Res = parseSymbolicOrNumericFormat(Format);
8048 if (Res.isFailure())
8049 return Res;
8050 if (Res.isSuccess()) {
8051 auto Size = Operands.size();
8052 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands[Size - 2]);
8053 assert(Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyFORMAT);
8054 Op.setImm(Format);
8055 }
8056 return ParseStatus::Success;
8057 }
8058
8059 if (isId("format") && peekToken().is(AsmToken::Colon))
8060 return Error(getLoc(), "duplicate format");
8061 return ParseStatus::Success;
8062}
8063
8064ParseStatus AMDGPUAsmParser::parseFlatOffset(OperandVector &Operands) {
8065 ParseStatus Res =
8066 parseIntWithPrefix("offset", Operands, AMDGPUOperand::ImmTyOffset);
8067 if (Res.isNoMatch()) {
8068 Res = parseIntWithPrefix("inst_offset", Operands,
8069 AMDGPUOperand::ImmTyInstOffset);
8070 }
8071 return Res;
8072}
8073
8074ParseStatus AMDGPUAsmParser::parseR128A16(OperandVector &Operands) {
8075 ParseStatus Res =
8076 parseNamedBit("r128", Operands, AMDGPUOperand::ImmTyR128A16);
8077 if (Res.isNoMatch())
8078 Res = parseNamedBit("a16", Operands, AMDGPUOperand::ImmTyA16);
8079 return Res;
8080}
8081
8082ParseStatus AMDGPUAsmParser::parseBLGP(OperandVector &Operands) {
8083 ParseStatus Res =
8084 parseIntWithPrefix("blgp", Operands, AMDGPUOperand::ImmTyBLGP);
8085 if (Res.isNoMatch()) {
8086 Res =
8087 parseOperandArrayWithPrefix("neg", Operands, AMDGPUOperand::ImmTyBLGP);
8088 }
8089 return Res;
8090}
8091
8092//===----------------------------------------------------------------------===//
8093// Exp
8094//===----------------------------------------------------------------------===//
8095
8096void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
8097 OptionalImmIndexMap OptionalIdx;
8098
8099 unsigned OperandIdx[4];
8100 unsigned EnMask = 0;
8101 int SrcIdx = 0;
8102
8103 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
8104 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
8105
8106 // Add the register arguments
8107 if (Op.isReg()) {
8108 assert(SrcIdx < 4);
8109 OperandIdx[SrcIdx] = Inst.size();
8110 Op.addRegOperands(Inst, 1);
8111 ++SrcIdx;
8112 continue;
8113 }
8114
8115 if (Op.isOff()) {
8116 assert(SrcIdx < 4);
8117 OperandIdx[SrcIdx] = Inst.size();
8118 Inst.addOperand(MCOperand::createReg(MCRegister()));
8119 ++SrcIdx;
8120 continue;
8121 }
8122
8123 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) {
8124 Op.addImmOperands(Inst, 1);
8125 continue;
8126 }
8127
8128 if (Op.isToken() && (Op.getToken() == "done" || Op.getToken() == "row_en"))
8129 continue;
8130
8131 // Handle optional arguments
8132 OptionalIdx[Op.getImmTy()] = i;
8133 }
8134
8135 assert(SrcIdx == 4);
8136
8137 bool Compr = false;
8138 if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) {
8139 Compr = true;
8140 Inst.getOperand(OperandIdx[1]) = Inst.getOperand(OperandIdx[2]);
8141 Inst.getOperand(OperandIdx[2]).setReg(MCRegister());
8142 Inst.getOperand(OperandIdx[3]).setReg(MCRegister());
8143 }
8144
8145 for (auto i = 0; i < SrcIdx; ++i) {
8146 if (Inst.getOperand(OperandIdx[i]).getReg()) {
8147 EnMask |= Compr ? (0x3 << i * 2) : (0x1 << i);
8148 }
8149 }
8150
8151 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM);
8152 addOptionalImmOperand(Inst, Operands, OptionalIdx,
8153 AMDGPUOperand::ImmTyExpCompr);
8154
8155 Inst.addOperand(MCOperand::createImm(EnMask));
8156}
8157
8158//===----------------------------------------------------------------------===//
8159// s_waitcnt
8160//===----------------------------------------------------------------------===//
8161
8162static bool encodeCnt(const AMDGPU::IsaVersion ISA, int64_t &IntVal,
8163 int64_t CntVal, bool Saturate,
8164 unsigned (*encode)(const IsaVersion &Version, unsigned,
8165 unsigned),
8166 unsigned (*decode)(const IsaVersion &Version, unsigned)) {
8167 bool Failed = false;
8168
8169 IntVal = encode(ISA, IntVal, CntVal);
8170 if (CntVal != decode(ISA, IntVal)) {
8171 if (Saturate) {
8172 IntVal = encode(ISA, IntVal, -1);
8173 } else {
8174 Failed = true;
8175 }
8176 }
8177 return Failed;
8178}
8179
8180bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
8181
8182 SMLoc CntLoc = getLoc();
8183 StringRef CntName = getTokenStr();
8184
8185 if (!skipToken(AsmToken::Identifier, "expected a counter name") ||
8186 !skipToken(AsmToken::LParen, "expected a left parenthesis"))
8187 return false;
8188
8189 int64_t CntVal;
8190 SMLoc ValLoc = getLoc();
8191 if (!parseExpr(CntVal))
8192 return false;
8193
8194 bool Failed = true;
8195 bool Sat = CntName.ends_with("_sat");
8196
8197 if (CntName == "vmcnt" || CntName == "vmcnt_sat") {
8198 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeVmcnt, decodeVmcnt);
8199 } else if (CntName == "expcnt" || CntName == "expcnt_sat") {
8200 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeExpcnt, decodeExpcnt);
8201 } else if (CntName == "lgkmcnt" || CntName == "lgkmcnt_sat") {
8202 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeLgkmcnt, decodeLgkmcnt);
8203 } else {
8204 Error(CntLoc, "invalid counter name " + CntName);
8205 return false;
8206 }
8207
8208 if (Failed) {
8209 Error(ValLoc, "too large value for " + CntName);
8210 return false;
8211 }
8212
8213 if (!skipToken(AsmToken::RParen, "expected a closing parenthesis"))
8214 return false;
8215
8216 if (trySkipToken(AsmToken::Amp) || trySkipToken(AsmToken::Comma)) {
8217 if (isToken(AsmToken::EndOfStatement)) {
8218 Error(getLoc(), "expected a counter name");
8219 return false;
8220 }
8221 }
8222
8223 return true;
8224}
8225
8226ParseStatus AMDGPUAsmParser::parseSWaitCnt(OperandVector &Operands) {
8227 int64_t Waitcnt = getWaitcntBitMask(ISA);
8228 SMLoc S = getLoc();
8229
8230 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) {
8231 while (!isToken(AsmToken::EndOfStatement)) {
8232 if (!parseCnt(Waitcnt))
8233 return ParseStatus::Failure;
8234 }
8235 } else {
8236 if (!parseExpr(Waitcnt))
8237 return ParseStatus::Failure;
8238 }
8239
8240 Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S));
8241 return ParseStatus::Success;
8242}
8243
8244bool AMDGPUAsmParser::parseDelay(int64_t &Delay) {
8245 SMLoc FieldLoc = getLoc();
8246 StringRef FieldName = getTokenStr();
8247 if (!skipToken(AsmToken::Identifier, "expected a field name") ||
8248 !skipToken(AsmToken::LParen, "expected a left parenthesis"))
8249 return false;
8250
8251 SMLoc ValueLoc = getLoc();
8252 StringRef ValueName = getTokenStr();
8253 if (!skipToken(AsmToken::Identifier, "expected a value name") ||
8254 !skipToken(AsmToken::RParen, "expected a right parenthesis"))
8255 return false;
8256
8257 unsigned Shift;
8258 if (FieldName == "instid0") {
8259 Shift = 0;
8260 } else if (FieldName == "instskip") {
8261 Shift = 4;
8262 } else if (FieldName == "instid1") {
8263 Shift = 7;
8264 } else {
8265 Error(FieldLoc, "invalid field name " + FieldName);
8266 return false;
8267 }
8268
8269 int Value;
8270 if (Shift == 4) {
8271 // Parse values for instskip.
8272 Value = StringSwitch<int>(ValueName)
8273 .Case("SAME", 0)
8274 .Case("NEXT", 1)
8275 .Case("SKIP_1", 2)
8276 .Case("SKIP_2", 3)
8277 .Case("SKIP_3", 4)
8278 .Case("SKIP_4", 5)
8279 .Default(-1);
8280 } else {
8281 // Parse values for instid0 and instid1.
8282 Value = StringSwitch<int>(ValueName)
8283 .Case("NO_DEP", 0)
8284 .Case("VALU_DEP_1", 1)
8285 .Case("VALU_DEP_2", 2)
8286 .Case("VALU_DEP_3", 3)
8287 .Case("VALU_DEP_4", 4)
8288 .Case("TRANS32_DEP_1", 5)
8289 .Case("TRANS32_DEP_2", 6)
8290 .Case("TRANS32_DEP_3", 7)
8291 .Case("FMA_ACCUM_CYCLE_1", 8)
8292 .Case("SALU_CYCLE_1", 9)
8293 .Case("SALU_CYCLE_2", 10)
8294 .Case("SALU_CYCLE_3", 11)
8295 .Default(-1);
8296 }
8297 if (Value < 0) {
8298 Error(ValueLoc, "invalid value name " + ValueName);
8299 return false;
8300 }
8301
8302 Delay |= Value << Shift;
8303 return true;
8304}
8305
8306ParseStatus AMDGPUAsmParser::parseSDelayALU(OperandVector &Operands) {
8307 int64_t Delay = 0;
8308 SMLoc S = getLoc();
8309
8310 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) {
8311 do {
8312 if (!parseDelay(Delay))
8313 return ParseStatus::Failure;
8314 } while (trySkipToken(AsmToken::Pipe));
8315 } else {
8316 if (!parseExpr(Delay))
8317 return ParseStatus::Failure;
8318 }
8319
8320 Operands.push_back(AMDGPUOperand::CreateImm(this, Delay, S));
8321 return ParseStatus::Success;
8322}
8323
8324bool AMDGPUOperand::isSWaitCnt() const { return isImm(); }
8325
8326bool AMDGPUOperand::isSDelayALU() const { return isImm(); }
8327
8328//===----------------------------------------------------------------------===//
8329// DepCtr
8330//===----------------------------------------------------------------------===//
8331
8332void AMDGPUAsmParser::depCtrError(SMLoc Loc, int ErrorId,
8333 StringRef DepCtrName) {
8334 switch (ErrorId) {
8335 case OPR_ID_UNKNOWN:
8336 Error(Loc, Twine("invalid counter name ", DepCtrName));
8337 return;
8338 case OPR_ID_UNSUPPORTED:
8339 Error(Loc, Twine(DepCtrName, " is not supported on this GPU"));
8340 return;
8341 case OPR_ID_DUPLICATE:
8342 Error(Loc, Twine("duplicate counter name ", DepCtrName));
8343 return;
8344 case OPR_VAL_INVALID:
8345 Error(Loc, Twine("invalid value for ", DepCtrName));
8346 return;
8347 default:
8348 assert(false);
8349 }
8350}
8351
8352bool AMDGPUAsmParser::parseDepCtr(int64_t &DepCtr, unsigned &UsedOprMask) {
8353
8354 using namespace llvm::AMDGPU::DepCtr;
8355
8356 SMLoc DepCtrLoc = getLoc();
8357 StringRef DepCtrName = getTokenStr();
8358
8359 if (!skipToken(AsmToken::Identifier, "expected a counter name") ||
8360 !skipToken(AsmToken::LParen, "expected a left parenthesis"))
8361 return false;
8362
8363 int64_t ExprVal;
8364 if (!parseExpr(ExprVal))
8365 return false;
8366
8367 unsigned PrevOprMask = UsedOprMask;
8368 int CntVal = encodeDepCtr(DepCtrName, ExprVal, UsedOprMask, getSTI());
8369
8370 if (CntVal < 0) {
8371 depCtrError(DepCtrLoc, CntVal, DepCtrName);
8372 return false;
8373 }
8374
8375 if (!skipToken(AsmToken::RParen, "expected a closing parenthesis"))
8376 return false;
8377
8378 if (trySkipToken(AsmToken::Amp) || trySkipToken(AsmToken::Comma)) {
8379 if (isToken(AsmToken::EndOfStatement)) {
8380 Error(getLoc(), "expected a counter name");
8381 return false;
8382 }
8383 }
8384
8385 int64_t CntValMask = PrevOprMask ^ UsedOprMask;
8386 DepCtr = (DepCtr & ~CntValMask) | CntVal;
8387 return true;
8388}
8389
8390ParseStatus AMDGPUAsmParser::parseDepCtr(OperandVector &Operands) {
8391 using namespace llvm::AMDGPU::DepCtr;
8392
8393 int64_t DepCtr = getDefaultDepCtrEncoding(getSTI());
8394 SMLoc Loc = getLoc();
8395
8396 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) {
8397 unsigned UsedOprMask = 0;
8398 while (!isToken(AsmToken::EndOfStatement)) {
8399 if (!parseDepCtr(DepCtr, UsedOprMask))
8400 return ParseStatus::Failure;
8401 }
8402 } else {
8403 if (!parseExpr(DepCtr))
8404 return ParseStatus::Failure;
8405 }
8406
8407 Operands.push_back(AMDGPUOperand::CreateImm(this, DepCtr, Loc));
8408 return ParseStatus::Success;
8409}
8410
8411bool AMDGPUOperand::isDepCtr() const { return isS16Imm(); }
8412
8413//===----------------------------------------------------------------------===//
8414// hwreg
8415//===----------------------------------------------------------------------===//
8416
8417ParseStatus AMDGPUAsmParser::parseHwregFunc(OperandInfoTy &HwReg,
8418 OperandInfoTy &Offset,
8419 OperandInfoTy &Width) {
8420 using namespace llvm::AMDGPU::Hwreg;
8421
8422 if (!trySkipId("hwreg", AsmToken::LParen))
8423 return ParseStatus::NoMatch;
8424
8425 // The register may be specified by name or using a numeric code
8426 HwReg.Loc = getLoc();
8427 if (isToken(AsmToken::Identifier) &&
8428 (HwReg.Val = getHwregId(getTokenStr(), getSTI())) != OPR_ID_UNKNOWN) {
8429 HwReg.IsSymbolic = true;
8430 lex(); // skip register name
8431 } else if (!parseExpr(HwReg.Val, "a register name")) {
8432 return ParseStatus::Failure;
8433 }
8434
8435 if (trySkipToken(AsmToken::RParen))
8436 return ParseStatus::Success;
8437
8438 // parse optional params
8439 if (!skipToken(AsmToken::Comma, "expected a comma or a closing parenthesis"))
8440 return ParseStatus::Failure;
8441
8442 Offset.Loc = getLoc();
8443 if (!parseExpr(Offset.Val))
8444 return ParseStatus::Failure;
8445
8446 if (!skipToken(AsmToken::Comma, "expected a comma"))
8447 return ParseStatus::Failure;
8448
8449 Width.Loc = getLoc();
8450 if (!parseExpr(Width.Val) ||
8451 !skipToken(AsmToken::RParen, "expected a closing parenthesis"))
8452 return ParseStatus::Failure;
8453
8454 return ParseStatus::Success;
8455}
8456
8457ParseStatus AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
8458 using namespace llvm::AMDGPU::Hwreg;
8459
8460 int64_t ImmVal = 0;
8461 SMLoc Loc = getLoc();
8462
8463 StructuredOpField HwReg("id", "hardware register", HwregId::Width,
8464 HwregId::Default);
8465 StructuredOpField Offset("offset", "bit offset", HwregOffset::Width,
8466 HwregOffset::Default);
8467 struct : StructuredOpField {
8468 using StructuredOpField::StructuredOpField;
8469 bool validate(AMDGPUAsmParser &Parser) const override {
8470 if (!isUIntN(Width, Val - 1))
8471 return Error(Parser, "only values from 1 to 32 are legal");
8472 return true;
8473 }
8474 } Width("size", "bitfield width", HwregSize::Width, HwregSize::Default);
8475 ParseStatus Res = parseStructuredOpFields({&HwReg, &Offset, &Width});
8476
8477 if (Res.isNoMatch())
8478 Res = parseHwregFunc(HwReg, Offset, Width);
8479
8480 if (Res.isSuccess()) {
8481 if (!validateStructuredOpFields({&HwReg, &Offset, &Width}))
8482 return ParseStatus::Failure;
8483 ImmVal = HwregEncoding::encode(HwReg.Val, Offset.Val, Width.Val);
8484 }
8485
8486 if (Res.isNoMatch() &&
8487 parseExpr(ImmVal, "a hwreg macro, structured immediate"))
8489
8490 if (!Res.isSuccess())
8491 return ParseStatus::Failure;
8492
8493 if (!isUInt<16>(ImmVal))
8494 return Error(Loc, "invalid immediate: only 16-bit values are legal");
8495 Operands.push_back(
8496 AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTyHwreg));
8497 return ParseStatus::Success;
8498}
8499
8500bool AMDGPUOperand::isHwreg() const { return isImmTy(ImmTyHwreg); }
8501
8502//===----------------------------------------------------------------------===//
8503// sendmsg
8504//===----------------------------------------------------------------------===//
8505
8506bool AMDGPUAsmParser::parseSendMsgBody(OperandInfoTy &Msg, OperandInfoTy &Op,
8507 OperandInfoTy &Stream) {
8508 using namespace llvm::AMDGPU::SendMsg;
8509
8510 Msg.Loc = getLoc();
8511 if (isToken(AsmToken::Identifier) &&
8512 (Msg.Val = getMsgId(getTokenStr(), getSTI())) != OPR_ID_UNKNOWN) {
8513 Msg.IsSymbolic = true;
8514 lex(); // skip message name
8515 } else if (!parseExpr(Msg.Val, "a message name")) {
8516 return false;
8517 }
8518
8519 if (trySkipToken(AsmToken::Comma)) {
8520 Op.IsDefined = true;
8521 Op.Loc = getLoc();
8522 if (isToken(AsmToken::Identifier) &&
8523 (Op.Val = getMsgOpId(Msg.Val, getTokenStr(), getSTI())) !=
8525 lex(); // skip operation name
8526 } else if (!parseExpr(Op.Val, "an operation name")) {
8527 return false;
8528 }
8529
8530 if (trySkipToken(AsmToken::Comma)) {
8531 Stream.IsDefined = true;
8532 Stream.Loc = getLoc();
8533 if (!parseExpr(Stream.Val))
8534 return false;
8535 }
8536 }
8537
8538 return skipToken(AsmToken::RParen, "expected a closing parenthesis");
8539}
8540
8541bool AMDGPUAsmParser::validateSendMsg(const OperandInfoTy &Msg,
8542 const OperandInfoTy &Op,
8543 const OperandInfoTy &Stream) {
8544 using namespace llvm::AMDGPU::SendMsg;
8545
8546 // Validation strictness depends on whether message is specified
8547 // in a symbolic or in a numeric form. In the latter case
8548 // only encoding possibility is checked.
8549 bool Strict = Msg.IsSymbolic;
8550
8551 if (Strict) {
8552 if (Msg.Val == OPR_ID_UNSUPPORTED) {
8553 Error(Msg.Loc, "specified message id is not supported on this GPU");
8554 return false;
8555 }
8556 } else {
8557 if (!isValidMsgId(Msg.Val, getSTI())) {
8558 Error(Msg.Loc, "invalid message id");
8559 return false;
8560 }
8561 }
8562 if (Strict && (msgRequiresOp(Msg.Val, getSTI()) != Op.IsDefined)) {
8563 if (Op.IsDefined) {
8564 Error(Op.Loc, "message does not support operations");
8565 } else {
8566 Error(Msg.Loc, "missing message operation");
8567 }
8568 return false;
8569 }
8570 if (!isValidMsgOp(Msg.Val, Op.Val, getSTI(), Strict)) {
8571 if (Op.Val == OPR_ID_UNSUPPORTED)
8572 Error(Op.Loc, "specified operation id is not supported on this GPU");
8573 else
8574 Error(Op.Loc, "invalid operation id");
8575 return false;
8576 }
8577 if (Strict && !msgSupportsStream(Msg.Val, Op.Val, getSTI()) &&
8578 Stream.IsDefined) {
8579 Error(Stream.Loc, "message operation does not support streams");
8580 return false;
8581 }
8582 if (!isValidMsgStream(Msg.Val, Op.Val, Stream.Val, getSTI(), Strict)) {
8583 Error(Stream.Loc, "invalid message stream id");
8584 return false;
8585 }
8586 return true;
8587}
8588
8589ParseStatus AMDGPUAsmParser::parseSendMsg(OperandVector &Operands) {
8590 using namespace llvm::AMDGPU::SendMsg;
8591
8592 int64_t ImmVal = 0;
8593 SMLoc Loc = getLoc();
8594
8595 if (trySkipId("sendmsg", AsmToken::LParen)) {
8596 OperandInfoTy Msg(OPR_ID_UNKNOWN);
8597 OperandInfoTy Op(OP_NONE_);
8598 OperandInfoTy Stream(STREAM_ID_NONE_);
8599 if (parseSendMsgBody(Msg, Op, Stream) && validateSendMsg(Msg, Op, Stream)) {
8600 ImmVal = encodeMsg(Msg.Val, Op.Val, Stream.Val);
8601 } else {
8602 return ParseStatus::Failure;
8603 }
8604 } else if (parseExpr(ImmVal, "a sendmsg macro")) {
8605 if (ImmVal < 0 || !isUInt<16>(ImmVal))
8606 return Error(Loc, "invalid immediate: only 16-bit values are legal");
8607 } else {
8608 return ParseStatus::Failure;
8609 }
8610
8611 Operands.push_back(
8612 AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTySendMsg));
8613 return ParseStatus::Success;
8614}
8615
8616bool AMDGPUOperand::isSendMsg() const { return isImmTy(ImmTySendMsg); }
8617
8618ParseStatus AMDGPUAsmParser::parseWaitEvent(OperandVector &Operands) {
8619 using namespace llvm::AMDGPU::WaitEvent;
8620
8621 SMLoc Loc = getLoc();
8622 int64_t ImmVal = 0;
8623
8624 StructuredOpField DontWaitExportReady("dont_wait_export_ready", "bit value",
8625 1, 0);
8626 StructuredOpField ExportReady("export_ready", "bit value", 1, 0);
8627
8628 StructuredOpField *TargetBitfield =
8629 isGFX11() ? &DontWaitExportReady : &ExportReady;
8630
8631 ParseStatus Res = parseStructuredOpFields({TargetBitfield});
8632 if (Res.isNoMatch() && parseExpr(ImmVal, "structured immediate"))
8634 else if (Res.isSuccess()) {
8635 if (!validateStructuredOpFields({TargetBitfield}))
8636 return ParseStatus::Failure;
8637 ImmVal = TargetBitfield->Val;
8638 }
8639
8640 if (!Res.isSuccess())
8641 return ParseStatus::Failure;
8642
8643 if (!isUInt<16>(ImmVal))
8644 return Error(Loc, "invalid immediate: only 16-bit values are legal");
8645
8646 Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc,
8647 AMDGPUOperand::ImmTyWaitEvent));
8648 return ParseStatus::Success;
8649}
8650
8651bool AMDGPUOperand::isWaitEvent() const { return isImmTy(ImmTyWaitEvent); }
8652
8653//===----------------------------------------------------------------------===//
8654// v_interp
8655//===----------------------------------------------------------------------===//
8656
8657ParseStatus AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) {
8658 StringRef Str;
8659 SMLoc S = getLoc();
8660
8661 if (!parseId(Str))
8662 return ParseStatus::NoMatch;
8663
8664 int Slot = StringSwitch<int>(Str)
8665 .Case("p10", 0)
8666 .Case("p20", 1)
8667 .Case("p0", 2)
8668 .Default(-1);
8669
8670 if (Slot == -1)
8671 return Error(S, "invalid interpolation slot");
8672
8673 Operands.push_back(
8674 AMDGPUOperand::CreateImm(this, Slot, S, AMDGPUOperand::ImmTyInterpSlot));
8675 return ParseStatus::Success;
8676}
8677
8678ParseStatus AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) {
8679 StringRef Str;
8680 SMLoc S = getLoc();
8681
8682 if (!parseId(Str))
8683 return ParseStatus::NoMatch;
8684
8685 if (!Str.starts_with("attr"))
8686 return Error(S, "invalid interpolation attribute");
8687
8688 StringRef Chan = Str.take_back(2);
8689 int AttrChan = StringSwitch<int>(Chan)
8690 .Case(".x", 0)
8691 .Case(".y", 1)
8692 .Case(".z", 2)
8693 .Case(".w", 3)
8694 .Default(-1);
8695 if (AttrChan == -1)
8696 return Error(S, "invalid or missing interpolation attribute channel");
8697
8698 Str = Str.drop_back(2).drop_front(4);
8699
8700 uint8_t Attr;
8701 if (Str.getAsInteger(10, Attr))
8702 return Error(S, "invalid or missing interpolation attribute number");
8703
8704 if (Attr > 32)
8705 return Error(S, "out of bounds interpolation attribute number");
8706
8707 SMLoc SChan = SMLoc::getFromPointer(Chan.data());
8708
8709 Operands.push_back(
8710 AMDGPUOperand::CreateImm(this, Attr, S, AMDGPUOperand::ImmTyInterpAttr));
8711 Operands.push_back(AMDGPUOperand::CreateImm(
8712 this, AttrChan, SChan, AMDGPUOperand::ImmTyInterpAttrChan));
8713 return ParseStatus::Success;
8714}
8715
8716//===----------------------------------------------------------------------===//
8717// exp
8718//===----------------------------------------------------------------------===//
8719
8720ParseStatus AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) {
8721 using namespace llvm::AMDGPU::Exp;
8722
8723 StringRef Str;
8724 SMLoc S = getLoc();
8725
8726 if (!parseId(Str))
8727 return ParseStatus::NoMatch;
8728
8729 unsigned Id = getTgtId(Str);
8730 if (Id == ET_INVALID || !isSupportedTgtId(Id, getSTI()))
8731 return Error(S, (Id == ET_INVALID)
8732 ? "invalid exp target"
8733 : "exp target is not supported on this GPU");
8734
8735 Operands.push_back(
8736 AMDGPUOperand::CreateImm(this, Id, S, AMDGPUOperand::ImmTyExpTgt));
8737 return ParseStatus::Success;
8738}
8739
8740//===----------------------------------------------------------------------===//
8741// parser helpers
8742//===----------------------------------------------------------------------===//
8743
8744bool AMDGPUAsmParser::isId(const AsmToken &Token, const StringRef Id) const {
8745 return Token.is(AsmToken::Identifier) && Token.getString() == Id;
8746}
8747
8748bool AMDGPUAsmParser::isId(const StringRef Id) const {
8749 return isId(getToken(), Id);
8750}
8751
8752bool AMDGPUAsmParser::isToken(const AsmToken::TokenKind Kind) const {
8753 return getTokenKind() == Kind;
8754}
8755
8756StringRef AMDGPUAsmParser::getId() const {
8757 return isToken(AsmToken::Identifier) ? getTokenStr() : StringRef();
8758}
8759
8760bool AMDGPUAsmParser::trySkipId(const StringRef Id) {
8761 if (isId(Id)) {
8762 lex();
8763 return true;
8764 }
8765 return false;
8766}
8767
8768bool AMDGPUAsmParser::trySkipId(const StringRef Pref, const StringRef Id) {
8769 if (isToken(AsmToken::Identifier)) {
8770 StringRef Tok = getTokenStr();
8771 if (Tok.starts_with(Pref) && Tok.drop_front(Pref.size()) == Id) {
8772 lex();
8773 return true;
8774 }
8775 }
8776 return false;
8777}
8778
8779bool AMDGPUAsmParser::trySkipId(const StringRef Id,
8780 const AsmToken::TokenKind Kind) {
8781 if (isId(Id) && peekToken().is(Kind)) {
8782 lex();
8783 lex();
8784 return true;
8785 }
8786 return false;
8787}
8788
8789bool AMDGPUAsmParser::trySkipToken(const AsmToken::TokenKind Kind) {
8790 if (isToken(Kind)) {
8791 lex();
8792 return true;
8793 }
8794 return false;
8795}
8796
8797bool AMDGPUAsmParser::skipToken(const AsmToken::TokenKind Kind,
8798 const StringRef ErrMsg) {
8799 if (!trySkipToken(Kind)) {
8800 Error(getLoc(), ErrMsg);
8801 return false;
8802 }
8803 return true;
8804}
8805
8806bool AMDGPUAsmParser::parseExpr(int64_t &Imm, StringRef Expected) {
8807 SMLoc S = getLoc();
8808
8809 const MCExpr *Expr;
8810 if (Parser.parseExpression(Expr))
8811 return false;
8812
8813 if (Expr->evaluateAsAbsolute(Imm))
8814 return true;
8815
8816 if (Expected.empty()) {
8817 Error(S, "expected absolute expression");
8818 } else {
8819 Error(S,
8820 Twine("expected ", Expected) + Twine(" or an absolute expression"));
8821 }
8822 return false;
8823}
8824
8825bool AMDGPUAsmParser::parseExpr(OperandVector &Operands) {
8826 SMLoc S = getLoc();
8827
8828 const MCExpr *Expr;
8829 if (Parser.parseExpression(Expr))
8830 return false;
8831
8832 int64_t IntVal;
8833 if (Expr->evaluateAsAbsolute(IntVal)) {
8834 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
8835 } else {
8836 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
8837 }
8838 return true;
8839}
8840
8841bool AMDGPUAsmParser::parseString(StringRef &Val, const StringRef ErrMsg) {
8842 if (isToken(AsmToken::String)) {
8843 Val = getToken().getStringContents();
8844 lex();
8845 return true;
8846 }
8847 Error(getLoc(), ErrMsg);
8848 return false;
8849}
8850
8851bool AMDGPUAsmParser::parseId(StringRef &Val, const StringRef ErrMsg) {
8852 if (isToken(AsmToken::Identifier)) {
8853 Val = getTokenStr();
8854 lex();
8855 return true;
8856 }
8857 if (!ErrMsg.empty())
8858 Error(getLoc(), ErrMsg);
8859 return false;
8860}
8861
8862AsmToken AMDGPUAsmParser::getToken() const { return Parser.getTok(); }
8863
8864AsmToken AMDGPUAsmParser::peekToken(bool ShouldSkipSpace) {
8865 return isToken(AsmToken::EndOfStatement)
8866 ? getToken()
8867 : getLexer().peekTok(ShouldSkipSpace);
8868}
8869
8870void AMDGPUAsmParser::peekTokens(MutableArrayRef<AsmToken> Tokens) {
8871 auto TokCount = getLexer().peekTokens(Tokens);
8872
8873 for (auto Idx = TokCount; Idx < Tokens.size(); ++Idx)
8874 Tokens[Idx] = AsmToken(AsmToken::Error, "");
8875}
8876
8877AsmToken::TokenKind AMDGPUAsmParser::getTokenKind() const {
8878 return getLexer().getKind();
8879}
8880
8881SMLoc AMDGPUAsmParser::getLoc() const { return getToken().getLoc(); }
8882
8883StringRef AMDGPUAsmParser::getTokenStr() const {
8884 return getToken().getString();
8885}
8886
8887void AMDGPUAsmParser::lex() { Parser.Lex(); }
8888
8889const AMDGPUOperand &
8890AMDGPUAsmParser::findMCOperand(const OperandVector &Operands,
8891 int MCOpIdx) const {
8892 for (const auto &Op : Operands) {
8893 const AMDGPUOperand &TargetOp = static_cast<AMDGPUOperand &>(*Op);
8894 if (TargetOp.getMCOpIdx() == MCOpIdx)
8895 return TargetOp;
8896 }
8897 llvm_unreachable("no such MC operand!");
8898}
8899
8900SMLoc AMDGPUAsmParser::getInstLoc(const OperandVector &Operands) const {
8901 return ((AMDGPUOperand &)*Operands[0]).getStartLoc();
8902}
8903
8904// Returns one of the given locations that comes later in the source.
8905SMLoc AMDGPUAsmParser::getLaterLoc(SMLoc a, SMLoc b) {
8906 return a.getPointer() < b.getPointer() ? b : a;
8907}
8908
8909SMLoc AMDGPUAsmParser::getOperandLoc(const OperandVector &Operands,
8910 int MCOpIdx) const {
8911 return findMCOperand(Operands, MCOpIdx).getStartLoc();
8912}
8913
8914SMLoc AMDGPUAsmParser::getOperandLoc(
8915 std::function<bool(const AMDGPUOperand &)> Test,
8916 const OperandVector &Operands) const {
8917 for (unsigned i = Operands.size() - 1; i > 0; --i) {
8918 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
8919 if (Test(Op))
8920 return Op.getStartLoc();
8921 }
8922 return getInstLoc(Operands);
8923}
8924
8925SMLoc AMDGPUAsmParser::getImmLoc(AMDGPUOperand::ImmTy Type,
8926 const OperandVector &Operands) const {
8927 auto Test = [=](const AMDGPUOperand &Op) { return Op.isImmTy(Type); };
8928 return getOperandLoc(Test, Operands);
8929}
8930
8931ParseStatus
8932AMDGPUAsmParser::parseStructuredOpFields(ArrayRef<StructuredOpField *> Fields) {
8933 if (!trySkipToken(AsmToken::LCurly))
8934 return ParseStatus::NoMatch;
8935
8936 bool First = true;
8937 while (!trySkipToken(AsmToken::RCurly)) {
8938 if (!First &&
8939 !skipToken(AsmToken::Comma, "comma or closing brace expected"))
8940 return ParseStatus::Failure;
8941
8942 StringRef Id = getTokenStr();
8943 SMLoc IdLoc = getLoc();
8944 if (!skipToken(AsmToken::Identifier, "field name expected") ||
8945 !skipToken(AsmToken::Colon, "colon expected"))
8946 return ParseStatus::Failure;
8947
8948 const auto *I =
8949 find_if(Fields, [Id](StructuredOpField *F) { return F->Id == Id; });
8950 if (I == Fields.end())
8951 return Error(IdLoc, "unknown field");
8952 if ((*I)->IsDefined)
8953 return Error(IdLoc, "duplicate field");
8954
8955 // TODO: Support symbolic values.
8956 (*I)->Loc = getLoc();
8957 if (!parseExpr((*I)->Val))
8958 return ParseStatus::Failure;
8959 (*I)->IsDefined = true;
8960
8961 First = false;
8962 }
8963 return ParseStatus::Success;
8964}
8965
8966bool AMDGPUAsmParser::validateStructuredOpFields(
8968 return all_of(Fields, [this](const StructuredOpField *F) {
8969 return F->validate(*this);
8970 });
8971}
8972
8973//===----------------------------------------------------------------------===//
8974// swizzle
8975//===----------------------------------------------------------------------===//
8976
8978static unsigned encodeBitmaskPerm(const unsigned AndMask, const unsigned OrMask,
8979 const unsigned XorMask) {
8980 using namespace llvm::AMDGPU::Swizzle;
8981
8982 return BITMASK_PERM_ENC | (AndMask << BITMASK_AND_SHIFT) |
8983 (OrMask << BITMASK_OR_SHIFT) | (XorMask << BITMASK_XOR_SHIFT);
8984}
8985
8986bool AMDGPUAsmParser::parseSwizzleOperand(int64_t &Op, const unsigned MinVal,
8987 const unsigned MaxVal,
8988 const Twine &ErrMsg, SMLoc &Loc) {
8989 if (!skipToken(AsmToken::Comma, "expected a comma")) {
8990 return false;
8991 }
8992 Loc = getLoc();
8993 if (!parseExpr(Op)) {
8994 return false;
8995 }
8996 if (Op < MinVal || Op > MaxVal) {
8997 Error(Loc, ErrMsg);
8998 return false;
8999 }
9000
9001 return true;
9002}
9003
9004bool AMDGPUAsmParser::parseSwizzleOperands(const unsigned OpNum, int64_t *Op,
9005 const unsigned MinVal,
9006 const unsigned MaxVal,
9007 const StringRef ErrMsg) {
9008 SMLoc Loc;
9009 for (unsigned i = 0; i < OpNum; ++i) {
9010 if (!parseSwizzleOperand(Op[i], MinVal, MaxVal, ErrMsg, Loc))
9011 return false;
9012 }
9013
9014 return true;
9015}
9016
9017bool AMDGPUAsmParser::parseSwizzleQuadPerm(int64_t &Imm) {
9018 using namespace llvm::AMDGPU::Swizzle;
9019
9020 int64_t Lane[LANE_NUM];
9021 if (parseSwizzleOperands(LANE_NUM, Lane, 0, LANE_MAX,
9022 "expected a 2-bit lane id")) {
9024 for (unsigned I = 0; I < LANE_NUM; ++I) {
9025 Imm |= Lane[I] << (LANE_SHIFT * I);
9026 }
9027 return true;
9028 }
9029 return false;
9030}
9031
9032bool AMDGPUAsmParser::parseSwizzleBroadcast(int64_t &Imm) {
9033 using namespace llvm::AMDGPU::Swizzle;
9034
9035 SMLoc Loc;
9036 int64_t GroupSize;
9037 int64_t LaneIdx;
9038
9039 if (!parseSwizzleOperand(GroupSize, 2, 32,
9040 "group size must be in the interval [2,32]", Loc)) {
9041 return false;
9042 }
9043 if (!isPowerOf2_64(GroupSize)) {
9044 Error(Loc, "group size must be a power of two");
9045 return false;
9046 }
9047 if (parseSwizzleOperand(LaneIdx, 0, GroupSize - 1,
9048 "lane id must be in the interval [0,group size - 1]",
9049 Loc)) {
9050 Imm = encodeBitmaskPerm(BITMASK_MAX - GroupSize + 1, LaneIdx, 0);
9051 return true;
9052 }
9053 return false;
9054}
9055
9056bool AMDGPUAsmParser::parseSwizzleReverse(int64_t &Imm) {
9057 using namespace llvm::AMDGPU::Swizzle;
9058
9059 SMLoc Loc;
9060 int64_t GroupSize;
9061
9062 if (!parseSwizzleOperand(GroupSize, 2, 32,
9063 "group size must be in the interval [2,32]", Loc)) {
9064 return false;
9065 }
9066 if (!isPowerOf2_64(GroupSize)) {
9067 Error(Loc, "group size must be a power of two");
9068 return false;
9069 }
9070
9071 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize - 1);
9072 return true;
9073}
9074
9075bool AMDGPUAsmParser::parseSwizzleSwap(int64_t &Imm) {
9076 using namespace llvm::AMDGPU::Swizzle;
9077
9078 SMLoc Loc;
9079 int64_t GroupSize;
9080
9081 if (!parseSwizzleOperand(GroupSize, 1, 16,
9082 "group size must be in the interval [1,16]", Loc)) {
9083 return false;
9084 }
9085 if (!isPowerOf2_64(GroupSize)) {
9086 Error(Loc, "group size must be a power of two");
9087 return false;
9088 }
9089
9090 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize);
9091 return true;
9092}
9093
9094bool AMDGPUAsmParser::parseSwizzleBitmaskPerm(int64_t &Imm) {
9095 using namespace llvm::AMDGPU::Swizzle;
9096
9097 if (!skipToken(AsmToken::Comma, "expected a comma")) {
9098 return false;
9099 }
9100
9101 StringRef Ctl;
9102 SMLoc StrLoc = getLoc();
9103 if (!parseString(Ctl)) {
9104 return false;
9105 }
9106 if (Ctl.size() != BITMASK_WIDTH) {
9107 Error(StrLoc, "expected a 5-character mask");
9108 return false;
9109 }
9110
9111 unsigned AndMask = 0;
9112 unsigned OrMask = 0;
9113 unsigned XorMask = 0;
9114
9115 for (size_t i = 0; i < Ctl.size(); ++i) {
9116 unsigned Mask = 1 << (BITMASK_WIDTH - 1 - i);
9117 switch (Ctl[i]) {
9118 default:
9119 Error(StrLoc, "invalid mask");
9120 return false;
9121 case '0':
9122 break;
9123 case '1':
9124 OrMask |= Mask;
9125 break;
9126 case 'p':
9127 AndMask |= Mask;
9128 break;
9129 case 'i':
9130 AndMask |= Mask;
9131 XorMask |= Mask;
9132 break;
9133 }
9134 }
9135
9136 Imm = encodeBitmaskPerm(AndMask, OrMask, XorMask);
9137 return true;
9138}
9139
9140bool AMDGPUAsmParser::parseSwizzleFFT(int64_t &Imm) {
9141 using namespace llvm::AMDGPU::Swizzle;
9142
9143 if (!AMDGPU::isGFX9Plus(getSTI())) {
9144 Error(getLoc(), "FFT mode swizzle not supported on this GPU");
9145 return false;
9146 }
9147
9148 int64_t Swizzle;
9149 SMLoc Loc;
9150 if (!parseSwizzleOperand(Swizzle, 0, FFT_SWIZZLE_MAX,
9151 "FFT swizzle must be in the interval [0," +
9152 Twine(FFT_SWIZZLE_MAX) + Twine(']'),
9153 Loc))
9154 return false;
9155
9156 Imm = FFT_MODE_ENC | Swizzle;
9157 return true;
9158}
9159
9160bool AMDGPUAsmParser::parseSwizzleRotate(int64_t &Imm) {
9161 using namespace llvm::AMDGPU::Swizzle;
9162
9163 if (!AMDGPU::isGFX9Plus(getSTI())) {
9164 Error(getLoc(), "Rotate mode swizzle not supported on this GPU");
9165 return false;
9166 }
9167
9168 SMLoc Loc;
9169 int64_t Direction;
9170
9171 if (!parseSwizzleOperand(Direction, 0, 1,
9172 "direction must be 0 (left) or 1 (right)", Loc))
9173 return false;
9174
9175 int64_t RotateSize;
9176 if (!parseSwizzleOperand(
9177 RotateSize, 0, ROTATE_MAX_SIZE,
9178 "number of threads to rotate must be in the interval [0," +
9179 Twine(ROTATE_MAX_SIZE) + Twine(']'),
9180 Loc))
9181 return false;
9182
9184 (RotateSize << ROTATE_SIZE_SHIFT);
9185 return true;
9186}
9187
9188bool AMDGPUAsmParser::parseSwizzleOffset(int64_t &Imm) {
9189
9190 SMLoc OffsetLoc = getLoc();
9191
9192 if (!parseExpr(Imm, "a swizzle macro")) {
9193 return false;
9194 }
9195 if (!isUInt<16>(Imm)) {
9196 Error(OffsetLoc, "expected a 16-bit offset");
9197 return false;
9198 }
9199 return true;
9200}
9201
9202bool AMDGPUAsmParser::parseSwizzleMacro(int64_t &Imm) {
9203 using namespace llvm::AMDGPU::Swizzle;
9204
9205 if (skipToken(AsmToken::LParen, "expected a left parentheses")) {
9206
9207 SMLoc ModeLoc = getLoc();
9208 bool Ok = false;
9209
9210 if (trySkipId(IdSymbolic[ID_QUAD_PERM])) {
9211 Ok = parseSwizzleQuadPerm(Imm);
9212 } else if (trySkipId(IdSymbolic[ID_BITMASK_PERM])) {
9213 Ok = parseSwizzleBitmaskPerm(Imm);
9214 } else if (trySkipId(IdSymbolic[ID_BROADCAST])) {
9215 Ok = parseSwizzleBroadcast(Imm);
9216 } else if (trySkipId(IdSymbolic[ID_SWAP])) {
9217 Ok = parseSwizzleSwap(Imm);
9218 } else if (trySkipId(IdSymbolic[ID_REVERSE])) {
9219 Ok = parseSwizzleReverse(Imm);
9220 } else if (trySkipId(IdSymbolic[ID_FFT])) {
9221 Ok = parseSwizzleFFT(Imm);
9222 } else if (trySkipId(IdSymbolic[ID_ROTATE])) {
9223 Ok = parseSwizzleRotate(Imm);
9224 } else {
9225 Error(ModeLoc, "expected a swizzle mode");
9226 }
9227
9228 return Ok && skipToken(AsmToken::RParen, "expected a closing parentheses");
9229 }
9230
9231 return false;
9232}
9233
9234ParseStatus AMDGPUAsmParser::parseSwizzle(OperandVector &Operands) {
9235 SMLoc S = getLoc();
9236 int64_t Imm = 0;
9237
9238 if (trySkipId("offset")) {
9239
9240 bool Ok = false;
9241 if (skipToken(AsmToken::Colon, "expected a colon")) {
9242 if (trySkipId("swizzle")) {
9243 Ok = parseSwizzleMacro(Imm);
9244 } else {
9245 Ok = parseSwizzleOffset(Imm);
9246 }
9247 }
9248
9249 Operands.push_back(
9250 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTySwizzle));
9251
9253 }
9254 return ParseStatus::NoMatch;
9255}
9256
9257bool AMDGPUOperand::isSwizzle() const { return isImmTy(ImmTySwizzle); }
9258
9259//===----------------------------------------------------------------------===//
9260// VGPR Index Mode
9261//===----------------------------------------------------------------------===//
9262
9263int64_t AMDGPUAsmParser::parseGPRIdxMacro() {
9264
9265 using namespace llvm::AMDGPU::VGPRIndexMode;
9266
9267 if (trySkipToken(AsmToken::RParen)) {
9268 return OFF;
9269 }
9270
9271 int64_t Imm = 0;
9272
9273 while (true) {
9274 unsigned Mode = 0;
9275 SMLoc S = getLoc();
9276
9277 for (unsigned ModeId = ID_MIN; ModeId <= ID_MAX; ++ModeId) {
9278 if (trySkipId(IdSymbolic[ModeId])) {
9279 Mode = 1 << ModeId;
9280 break;
9281 }
9282 }
9283
9284 if (Mode == 0) {
9285 Error(S, (Imm == 0)
9286 ? "expected a VGPR index mode or a closing parenthesis"
9287 : "expected a VGPR index mode");
9288 return UNDEF;
9289 }
9290
9291 if (Imm & Mode) {
9292 Error(S, "duplicate VGPR index mode");
9293 return UNDEF;
9294 }
9295 Imm |= Mode;
9296
9297 if (trySkipToken(AsmToken::RParen))
9298 break;
9299 if (!skipToken(AsmToken::Comma,
9300 "expected a comma or a closing parenthesis"))
9301 return UNDEF;
9302 }
9303
9304 return Imm;
9305}
9306
9307ParseStatus AMDGPUAsmParser::parseGPRIdxMode(OperandVector &Operands) {
9308
9309 using namespace llvm::AMDGPU::VGPRIndexMode;
9310
9311 int64_t Imm = 0;
9312 SMLoc S = getLoc();
9313
9314 if (trySkipId("gpr_idx", AsmToken::LParen)) {
9315 Imm = parseGPRIdxMacro();
9316 if (Imm == UNDEF)
9317 return ParseStatus::Failure;
9318 } else {
9319 if (getParser().parseAbsoluteExpression(Imm))
9320 return ParseStatus::Failure;
9321 if (Imm < 0 || !isUInt<4>(Imm))
9322 return Error(S, "invalid immediate: only 4-bit values are legal");
9323 }
9324
9325 Operands.push_back(
9326 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyGprIdxMode));
9327 return ParseStatus::Success;
9328}
9329
9330bool AMDGPUOperand::isGPRIdxMode() const { return isImmTy(ImmTyGprIdxMode); }
9331
9332//===----------------------------------------------------------------------===//
9333// sopp branch targets
9334//===----------------------------------------------------------------------===//
9335
9336ParseStatus AMDGPUAsmParser::parseSOPPBrTarget(OperandVector &Operands) {
9337
9338 // Make sure we are not parsing something
9339 // that looks like a label or an expression but is not.
9340 // This will improve error messages.
9341 if (isRegister() || isModifier())
9342 return ParseStatus::NoMatch;
9343
9344 if (!parseExpr(Operands))
9345 return ParseStatus::Failure;
9346
9347 AMDGPUOperand &Opr = ((AMDGPUOperand &)*Operands[Operands.size() - 1]);
9348 assert(Opr.isImm() || Opr.isExpr());
9349 SMLoc Loc = Opr.getStartLoc();
9350
9351 // Currently we do not support arbitrary expressions as branch targets.
9352 // Only labels and absolute expressions are accepted.
9353 if (Opr.isExpr() && !Opr.isSymbolRefExpr()) {
9354 Error(Loc, "expected an absolute expression or a label");
9355 } else if (Opr.isImm() && !Opr.isS16Imm()) {
9356 Error(Loc, "expected a 16-bit signed jump offset");
9357 }
9358
9359 return ParseStatus::Success;
9360}
9361
9362//===----------------------------------------------------------------------===//
9363// Boolean holding registers
9364//===----------------------------------------------------------------------===//
9365
9366ParseStatus AMDGPUAsmParser::parseBoolReg(OperandVector &Operands) {
9367 return parseReg(Operands);
9368}
9369
9370//===----------------------------------------------------------------------===//
9371// mubuf
9372//===----------------------------------------------------------------------===//
9373
9374void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst, const OperandVector &Operands,
9375 bool IsAtomic) {
9376 OptionalImmIndexMap OptionalIdx;
9377 unsigned FirstOperandIdx = 1;
9378 bool IsAtomicReturn = false;
9379
9380 if (IsAtomic) {
9381 IsAtomicReturn = SIInstrFlags::isAtomicRet(MII, Inst);
9382 }
9383
9384 for (unsigned i = FirstOperandIdx, e = Operands.size(); i != e; ++i) {
9385 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
9386
9387 // Add the register arguments
9388 if (Op.isReg()) {
9389 Op.addRegOperands(Inst, 1);
9390 // Insert a tied src for atomic return dst.
9391 // This cannot be postponed as subsequent calls to
9392 // addImmOperands rely on correct number of MC operands.
9393 if (IsAtomicReturn && i == FirstOperandIdx)
9394 Op.addRegOperands(Inst, 1);
9395 continue;
9396 }
9397
9398 // Handle the case where soffset is an immediate
9399 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
9400 Op.addImmOperands(Inst, 1);
9401 continue;
9402 }
9403
9404 // Handle tokens like 'offen' which are sometimes hard-coded into the
9405 // asm string. There are no MCInst operands for these.
9406 if (Op.isToken()) {
9407 continue;
9408 }
9409 assert(Op.isImm());
9410
9411 // Handle optional arguments
9412 OptionalIdx[Op.getImmTy()] = i;
9413 }
9414
9415 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9416 AMDGPUOperand::ImmTyOffset);
9417 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyCPol,
9418 0);
9419 // Parse a dummy operand as a placeholder for the SWZ operand. This enforces
9420 // agreement between MCInstrDesc.getNumOperands and MCInst.getNumOperands.
9422 // The LDS variants carry a trailing IsAsync operand. Parse a dummy the same
9423 // way as the SWZ operand.
9424 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::IsAsync))
9426}
9427
9428//===----------------------------------------------------------------------===//
9429// smrd
9430//===----------------------------------------------------------------------===//
9431
9432bool AMDGPUOperand::isSMRDOffset8() const {
9433 return isImmLiteral() && isUInt<8>(getImm());
9434}
9435
9436bool AMDGPUOperand::isSMEMOffset() const {
9437 // Offset range is checked later by validator.
9438 return isImmLiteral();
9439}
9440
9441bool AMDGPUOperand::isSMRDLiteralOffset() const {
9442 // 32-bit literals are only supported on CI and we only want to use them
9443 // when the offset is > 8-bits.
9444 return isImmLiteral() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
9445}
9446
9447//===----------------------------------------------------------------------===//
9448// vop3
9449//===----------------------------------------------------------------------===//
9450
9451static bool ConvertOmodMul(int64_t &Mul) {
9452 if (Mul != 1 && Mul != 2 && Mul != 4)
9453 return false;
9454
9455 Mul >>= 1;
9456 return true;
9457}
9458
9459static bool ConvertOmodDiv(int64_t &Div) {
9460 if (Div == 1) {
9461 Div = 0;
9462 return true;
9463 }
9464
9465 if (Div == 2) {
9466 Div = 3;
9467 return true;
9468 }
9469
9470 return false;
9471}
9472
9473// For pre-gfx11 targets, both bound_ctrl:0 and bound_ctrl:1 are encoded as 1.
9474// This is intentional and ensures compatibility with sp3.
9475// See bug 35397 for details.
9476bool AMDGPUAsmParser::convertDppBoundCtrl(int64_t &BoundCtrl) {
9477 if (BoundCtrl == 0 || BoundCtrl == 1) {
9478 if (!isGFX11Plus())
9479 BoundCtrl = 1;
9480 return true;
9481 }
9482 return false;
9483}
9484
9485void AMDGPUAsmParser::onBeginOfFile() {
9486 if (!getParser().getStreamer().getTargetStreamer())
9487 return;
9488
9489 if (!getTargetStreamer().getTargetID())
9490 getTargetStreamer().initializeTargetID(getSTI(),
9491 /*ApplyFeatureString=*/true);
9492}
9493
9494void AMDGPUAsmParser::emitTargetDirective() {
9495 if (TargetDirectiveEmitted)
9496 return;
9497 TargetDirectiveEmitted = true;
9498
9499 if (!getParser().getStreamer().getTargetStreamer() ||
9500 getSTI().getTargetTriple().getArch() == Triple::r600)
9501 return;
9502
9503 if (isHsaAbi(getSTI()))
9504 getTargetStreamer().EmitDirectiveAMDGCNTarget();
9505}
9506
9507/// Parse AMDGPU specific expressions.
9508///
9509/// expr ::= or(expr, ...) |
9510/// max(expr, ...) |
9511/// min(expr, ...)
9512///
9513bool AMDGPUAsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
9514 using AGVK = AMDGPUMCExpr::VariantKind;
9515
9516 if (isToken(AsmToken::Identifier)) {
9517 StringRef TokenId = getTokenStr();
9518 AGVK VK = StringSwitch<AGVK>(TokenId)
9519 .Case("max", AGVK::AGVK_Max)
9520 .Case("min", AGVK::AGVK_Min)
9521 .Case("or", AGVK::AGVK_Or)
9522 .Case("extrasgprs", AGVK::AGVK_ExtraSGPRs)
9523 .Case("totalnumvgprs", AGVK::AGVK_TotalNumVGPRs)
9524 .Case("alignto", AGVK::AGVK_AlignTo)
9525 .Case("occupancy", AGVK::AGVK_Occupancy)
9526 .Case("instprefsize", AGVK::AGVK_InstPrefSize)
9527 .Default(AGVK::AGVK_None);
9528
9529 if (VK != AGVK::AGVK_None && peekToken().is(AsmToken::LParen)) {
9531 uint64_t CommaCount = 0;
9532 lex(); // Eat Arg ('or', 'max', 'occupancy', etc.)
9533 lex(); // Eat '('
9534 while (true) {
9535 if (trySkipToken(AsmToken::RParen)) {
9536 if (Exprs.empty()) {
9537 Error(getToken().getLoc(),
9538 "empty " + Twine(TokenId) + " expression");
9539 return true;
9540 }
9541 if (CommaCount + 1 != Exprs.size()) {
9542 Error(getToken().getLoc(),
9543 "mismatch of commas in " + Twine(TokenId) + " expression");
9544 return true;
9545 }
9546 if (unsigned Expected = AMDGPUMCExpr::getNumExpectedArgs(VK);
9547 Expected && Exprs.size() != Expected) {
9548 Error(getToken().getLoc(), Twine(TokenId) + " expression expects " +
9549 Twine(Expected) + " operands");
9550 return true;
9551 }
9552 Res = AMDGPUMCExpr::create(VK, Exprs, getContext());
9553 return false;
9554 }
9555 const MCExpr *Expr;
9556 if (getParser().parseExpression(Expr, EndLoc))
9557 return true;
9558 Exprs.push_back(Expr);
9559 bool LastTokenWasComma = trySkipToken(AsmToken::Comma);
9560 if (LastTokenWasComma)
9561 CommaCount++;
9562 if (!LastTokenWasComma && !isToken(AsmToken::RParen)) {
9563 Error(getToken().getLoc(),
9564 "unexpected token in " + Twine(TokenId) + " expression");
9565 return true;
9566 }
9567 }
9568 }
9569 }
9570 return getParser().parsePrimaryExpr(Res, EndLoc, nullptr);
9571}
9572
9573ParseStatus AMDGPUAsmParser::parseOModSI(OperandVector &Operands) {
9574 StringRef Name = getTokenStr();
9575 if (Name == "mul") {
9576 return parseIntWithPrefix("mul", Operands, AMDGPUOperand::ImmTyOModSI,
9578 }
9579
9580 if (Name == "div") {
9581 return parseIntWithPrefix("div", Operands, AMDGPUOperand::ImmTyOModSI,
9583 }
9584
9585 return ParseStatus::NoMatch;
9586}
9587
9588// Determines which bit DST_OP_SEL occupies in the op_sel operand according to
9589// the number of src operands present, then copies that bit into src0_modifiers.
9590static void cvtVOP3DstOpSelOnly(MCInst &Inst, const MCRegisterInfo &MRI) {
9591 int Opc = Inst.getOpcode();
9592 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
9593 if (OpSelIdx == -1)
9594 return;
9595
9596 int SrcNum;
9597 const AMDGPU::OpName Ops[] = {AMDGPU::OpName::src0, AMDGPU::OpName::src1,
9598 AMDGPU::OpName::src2};
9599 for (SrcNum = 0; SrcNum < 3 && AMDGPU::hasNamedOperand(Opc, Ops[SrcNum]);
9600 ++SrcNum)
9601 ;
9602 assert(SrcNum > 0);
9603
9604 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
9605
9606 int DstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
9607 if (DstIdx == -1)
9608 return;
9609
9610 const MCOperand &DstOp = Inst.getOperand(DstIdx);
9611 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers);
9612 uint32_t ModVal = Inst.getOperand(ModIdx).getImm();
9613 if (DstOp.isReg() &&
9614 MRI.getRegClass(AMDGPU::VGPR_16RegClassID).contains(DstOp.getReg())) {
9615 if (AMDGPU::isHi16Reg(DstOp.getReg(), MRI))
9616 ModVal |= SISrcMods::DST_OP_SEL;
9617 } else {
9618 if ((OpSel & (1 << SrcNum)) != 0)
9619 ModVal |= SISrcMods::DST_OP_SEL;
9620 }
9621 Inst.getOperand(ModIdx).setImm(ModVal);
9622}
9623
9624void AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst,
9625 const OperandVector &Operands) {
9626 cvtVOP3P(Inst, Operands);
9627 cvtVOP3DstOpSelOnly(Inst, *getMRI());
9628}
9629
9630void AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands,
9631 OptionalImmIndexMap &OptionalIdx) {
9632 cvtVOP3P(Inst, Operands, OptionalIdx);
9633 cvtVOP3DstOpSelOnly(Inst, *getMRI());
9634}
9635
9636static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) {
9637 return
9638 // 1. This operand is input modifiers
9639 Desc.operands()[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS
9640 // 2. This is not last operand
9641 && Desc.NumOperands > (OpNum + 1)
9642 // 3. Next operand is register class
9643 && Desc.operands()[OpNum + 1].RegClass != -1
9644 // 4. Next register is not tied to any other operand
9645 && Desc.getOperandConstraint(OpNum + 1,
9647}
9648
9649void AMDGPUAsmParser::cvtOpSelHelper(MCInst &Inst, unsigned OpSel) {
9650 unsigned Opc = Inst.getOpcode();
9651 constexpr AMDGPU::OpName Ops[] = {AMDGPU::OpName::src0, AMDGPU::OpName::src1,
9652 AMDGPU::OpName::src2};
9653 constexpr AMDGPU::OpName ModOps[] = {AMDGPU::OpName::src0_modifiers,
9654 AMDGPU::OpName::src1_modifiers,
9655 AMDGPU::OpName::src2_modifiers};
9656 for (int J = 0; J < 3; ++J) {
9657 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]);
9658 if (OpIdx == -1)
9659 // Some instructions, e.g. v_interp_p2_f16 in GFX9, have src0, src2, but
9660 // no src1. So continue instead of break.
9661 continue;
9662
9663 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
9664 uint32_t ModVal = Inst.getOperand(ModIdx).getImm();
9665
9666 if ((OpSel & (1 << J)) != 0)
9667 ModVal |= SISrcMods::OP_SEL_0;
9668 // op_sel[3] is encoded in src0_modifiers.
9669 if (ModOps[J] == AMDGPU::OpName::src0_modifiers && (OpSel & (1 << 3)) != 0)
9670 ModVal |= SISrcMods::DST_OP_SEL;
9671
9672 Inst.getOperand(ModIdx).setImm(ModVal);
9673 }
9674}
9675
9676void AMDGPUAsmParser::cvtVOP3Interp(MCInst &Inst,
9677 const OperandVector &Operands) {
9678 OptionalImmIndexMap OptionalIdx;
9679 unsigned Opc = Inst.getOpcode();
9680
9681 unsigned I = 1;
9682 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
9683 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
9684 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
9685 }
9686
9687 for (unsigned E = Operands.size(); I != E; ++I) {
9688 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
9690 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
9691 } else if (Op.isInterpSlot() || Op.isInterpAttr() ||
9692 Op.isInterpAttrChan()) {
9693 Inst.addOperand(MCOperand::createImm(Op.getImm()));
9694 } else if (Op.isImmModifier()) {
9695 OptionalIdx[Op.getImmTy()] = I;
9696 } else {
9697 llvm_unreachable("unhandled operand type");
9698 }
9699 }
9700
9701 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::high))
9702 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9703 AMDGPUOperand::ImmTyHigh);
9704
9705 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp))
9706 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9707 AMDGPUOperand::ImmTyClamp);
9708
9709 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod))
9710 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9711 AMDGPUOperand::ImmTyOModSI);
9712
9713 // Some v_interp instructions use op_sel[3] for dst.
9714 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) {
9715 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9716 AMDGPUOperand::ImmTyOpSel);
9717 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
9718 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
9719
9720 cvtOpSelHelper(Inst, OpSel);
9721 }
9722}
9723
9724void AMDGPUAsmParser::cvtVINTERP(MCInst &Inst, const OperandVector &Operands) {
9725 OptionalImmIndexMap OptionalIdx;
9726 unsigned Opc = Inst.getOpcode();
9727
9728 unsigned I = 1;
9729 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
9730 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
9731 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
9732 }
9733
9734 for (unsigned E = Operands.size(); I != E; ++I) {
9735 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
9737 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
9738 } else if (Op.isImmModifier()) {
9739 OptionalIdx[Op.getImmTy()] = I;
9740 } else {
9741 llvm_unreachable("unhandled operand type");
9742 }
9743 }
9744
9745 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClamp);
9746
9747 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
9748 if (OpSelIdx != -1)
9749 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9750 AMDGPUOperand::ImmTyOpSel);
9751
9752 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9753 AMDGPUOperand::ImmTyWaitEXP);
9754
9755 if (OpSelIdx == -1)
9756 return;
9757
9758 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
9759 cvtOpSelHelper(Inst, OpSel);
9760}
9761
9762void AMDGPUAsmParser::cvtScaledMFMA(MCInst &Inst,
9763 const OperandVector &Operands) {
9764 OptionalImmIndexMap OptionalIdx;
9765 unsigned Opc = Inst.getOpcode();
9766 unsigned I = 1;
9767 int CbszOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::cbsz);
9768
9769 const MCInstrDesc &Desc = MII.get(Opc);
9770
9771 for (unsigned J = 0; J < Desc.getNumDefs(); ++J)
9772 static_cast<AMDGPUOperand &>(*Operands[I++]).addRegOperands(Inst, 1);
9773
9774 for (unsigned E = Operands.size(); I != E; ++I) {
9775 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands[I]);
9776 int NumOperands = Inst.getNumOperands();
9777 // The order of operands in MCInst and parsed operands are different.
9778 // Adding dummy cbsz and blgp operands at corresponding MCInst operand
9779 // indices for parsing scale values correctly.
9780 if (NumOperands == CbszOpIdx) {
9783 }
9784 if (isRegOrImmWithInputMods(Desc, NumOperands)) {
9785 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
9786 } else if (Op.isImmModifier()) {
9787 OptionalIdx[Op.getImmTy()] = I;
9788 } else {
9789 Op.addRegOrImmOperands(Inst, 1);
9790 }
9791 }
9792
9793 // Insert CBSZ and BLGP operands for F8F6F4 variants
9794 auto CbszIdx = OptionalIdx.find(AMDGPUOperand::ImmTyCBSZ);
9795 if (CbszIdx != OptionalIdx.end()) {
9796 int CbszVal = ((AMDGPUOperand &)*Operands[CbszIdx->second]).getImm();
9797 Inst.getOperand(CbszOpIdx).setImm(CbszVal);
9798 }
9799
9800 int BlgpOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::blgp);
9801 auto BlgpIdx = OptionalIdx.find(AMDGPUOperand::ImmTyBLGP);
9802 if (BlgpIdx != OptionalIdx.end()) {
9803 int BlgpVal = ((AMDGPUOperand &)*Operands[BlgpIdx->second]).getImm();
9804 Inst.getOperand(BlgpOpIdx).setImm(BlgpVal);
9805 }
9806
9807 // Add dummy src_modifiers
9810
9811 // Handle op_sel fields
9812
9813 unsigned OpSel = 0;
9814 auto OpselIdx = OptionalIdx.find(AMDGPUOperand::ImmTyOpSel);
9815 if (OpselIdx != OptionalIdx.end()) {
9816 OpSel = static_cast<const AMDGPUOperand &>(*Operands[OpselIdx->second])
9817 .getImm();
9818 }
9819
9820 unsigned OpSelHi = 0;
9821 auto OpselHiIdx = OptionalIdx.find(AMDGPUOperand::ImmTyOpSelHi);
9822 if (OpselHiIdx != OptionalIdx.end()) {
9823 OpSelHi = static_cast<const AMDGPUOperand &>(*Operands[OpselHiIdx->second])
9824 .getImm();
9825 }
9826 const AMDGPU::OpName ModOps[] = {AMDGPU::OpName::src0_modifiers,
9827 AMDGPU::OpName::src1_modifiers};
9828
9829 for (unsigned J = 0; J < 2; ++J) {
9830 unsigned ModVal = 0;
9831 if (OpSel & (1 << J))
9832 ModVal |= SISrcMods::OP_SEL_0;
9833 if (OpSelHi & (1 << J))
9834 ModVal |= SISrcMods::OP_SEL_1;
9835
9836 const int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
9837 Inst.getOperand(ModIdx).setImm(ModVal);
9838 }
9839}
9840
9841void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands,
9842 OptionalImmIndexMap &OptionalIdx) {
9843 unsigned Opc = Inst.getOpcode();
9844
9845 unsigned I = 1;
9846 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
9847 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
9848 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
9849 }
9850
9851 for (unsigned E = Operands.size(); I != E; ++I) {
9852 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
9854 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
9855 } else if (Op.isImmModifier()) {
9856 OptionalIdx[Op.getImmTy()] = I;
9857 } else {
9858 Op.addRegOrImmOperands(Inst, 1);
9859 }
9860 }
9861
9862 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::scale_sel))
9863 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9864 AMDGPUOperand::ImmTyScaleSel);
9865
9866 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp))
9867 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9868 AMDGPUOperand::ImmTyClamp);
9869
9870 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::byte_sel)) {
9871 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::vdst_in))
9872 Inst.addOperand(Inst.getOperand(0));
9873 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9874 AMDGPUOperand::ImmTyByteSel);
9875 }
9876
9877 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod))
9878 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9879 AMDGPUOperand::ImmTyOModSI);
9880
9881 // Special case v_mac_{f16, f32} and v_fmac_{f16, f32} (gfx906/gfx10+):
9882 // it has src2 register operand that is tied to dst operand
9883 // we don't allow modifiers for this operand in assembler so src2_modifiers
9884 // should be 0.
9885 if (isMAC(Opc)) {
9886 auto *it = Inst.begin();
9887 std::advance(
9888 it, AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers));
9889 it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2
9890 ++it;
9891 // Copy the operand to ensure it's not invalidated when Inst grows.
9892 Inst.insert(it, MCOperand(Inst.getOperand(0))); // src2 = dst
9893 }
9894}
9895
9896void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
9897 OptionalImmIndexMap OptionalIdx;
9898 cvtVOP3(Inst, Operands, OptionalIdx);
9899}
9900
9901void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst, const OperandVector &Operands,
9902 OptionalImmIndexMap &OptIdx) {
9903 const int Opc = Inst.getOpcode();
9904
9905 const bool IsPacked = SIInstrFlags::isPacked(MII, Inst);
9906
9907 if (Opc == AMDGPU::V_CVT_SCALEF32_PK_FP4_F16_vi ||
9908 Opc == AMDGPU::V_CVT_SCALEF32_PK_FP4_BF16_vi ||
9909 Opc == AMDGPU::V_CVT_SR_BF8_F32_vi ||
9910 Opc == AMDGPU::V_CVT_SR_FP8_F32_vi ||
9911 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_gfx11 ||
9912 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_gfx11 ||
9913 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_gfx12 ||
9914 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_gfx12 ||
9915 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_gfx13 ||
9916 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_gfx13) {
9917 Inst.addOperand(MCOperand::createImm(0)); // Placeholder for src2_mods
9918 Inst.addOperand(Inst.getOperand(0));
9919 }
9920
9921 // Append vdst_in only if a previous converter (cvtVOP3DPP for DPP variants,
9922 // cvtVOP3 for byte_sel variants) hasn't already placed it. Use the position
9923 // of the named operand to detect that, the same way cvtVOP3DPP does
9924 // internally.
9925 int VdstInIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
9926 if (VdstInIdx != -1 && VdstInIdx == static_cast<int>(Inst.getNumOperands()))
9927 Inst.addOperand(Inst.getOperand(0));
9928
9929 int BitOp3Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::bitop3);
9930 if (BitOp3Idx != -1) {
9931 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyBitOp3);
9932 }
9933
9934 // FIXME: This is messy. Parse the modifiers as if it was a normal VOP3
9935 // instruction, and then figure out where to actually put the modifiers
9936
9937 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
9938 if (OpSelIdx != -1) {
9939 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSel);
9940 }
9941
9942 int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi);
9943 if (OpSelHiIdx != -1) {
9944 int DefaultVal = IsPacked ? -1 : 0;
9945 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSelHi,
9946 DefaultVal);
9947 }
9948
9949 int MatrixAFMTIdx =
9950 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_a_fmt);
9951 if (MatrixAFMTIdx != -1) {
9952 addOptionalImmOperand(Inst, Operands, OptIdx,
9953 AMDGPUOperand::ImmTyMatrixAFMT, 0);
9954 }
9955
9956 int MatrixBFMTIdx =
9957 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_b_fmt);
9958 if (MatrixBFMTIdx != -1) {
9959 addOptionalImmOperand(Inst, Operands, OptIdx,
9960 AMDGPUOperand::ImmTyMatrixBFMT, 0);
9961 }
9962
9963 int MatrixAScaleIdx =
9964 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_a_scale);
9965 if (MatrixAScaleIdx != -1) {
9966 addOptionalImmOperand(Inst, Operands, OptIdx,
9967 AMDGPUOperand::ImmTyMatrixAScale, 0);
9968 }
9969
9970 int MatrixBScaleIdx =
9971 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_b_scale);
9972 if (MatrixBScaleIdx != -1) {
9973 addOptionalImmOperand(Inst, Operands, OptIdx,
9974 AMDGPUOperand::ImmTyMatrixBScale, 0);
9975 }
9976
9977 int MatrixAScaleFmtIdx =
9978 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_a_scale_fmt);
9979 if (MatrixAScaleFmtIdx != -1) {
9980 addOptionalImmOperand(Inst, Operands, OptIdx,
9981 AMDGPUOperand::ImmTyMatrixAScaleFmt, 0);
9982 }
9983
9984 int MatrixBScaleFmtIdx =
9985 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_b_scale_fmt);
9986 if (MatrixBScaleFmtIdx != -1) {
9987 addOptionalImmOperand(Inst, Operands, OptIdx,
9988 AMDGPUOperand::ImmTyMatrixBScaleFmt, 0);
9989 }
9990
9991 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::matrix_a_reuse))
9992 addOptionalImmOperand(Inst, Operands, OptIdx,
9993 AMDGPUOperand::ImmTyMatrixAReuse, 0);
9994
9995 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::matrix_b_reuse))
9996 addOptionalImmOperand(Inst, Operands, OptIdx,
9997 AMDGPUOperand::ImmTyMatrixBReuse, 0);
9998
9999 int NegLoIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_lo);
10000 if (NegLoIdx != -1)
10001 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegLo);
10002
10003 int NegHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_hi);
10004 if (NegHiIdx != -1)
10005 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegHi);
10006
10007 const AMDGPU::OpName Ops[] = {AMDGPU::OpName::src0, AMDGPU::OpName::src1,
10008 AMDGPU::OpName::src2};
10009 const AMDGPU::OpName ModOps[] = {AMDGPU::OpName::src0_modifiers,
10010 AMDGPU::OpName::src1_modifiers,
10011 AMDGPU::OpName::src2_modifiers};
10012
10013 unsigned OpSel = 0;
10014 unsigned OpSelHi = 0;
10015 unsigned NegLo = 0;
10016 unsigned NegHi = 0;
10017
10018 if (OpSelIdx != -1)
10019 OpSel = Inst.getOperand(OpSelIdx).getImm();
10020
10021 if (OpSelHiIdx != -1)
10022 OpSelHi = Inst.getOperand(OpSelHiIdx).getImm();
10023
10024 if (NegLoIdx != -1)
10025 NegLo = Inst.getOperand(NegLoIdx).getImm();
10026
10027 if (NegHiIdx != -1)
10028 NegHi = Inst.getOperand(NegHiIdx).getImm();
10029
10030 for (int J = 0; J < 3; ++J) {
10031 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]);
10032 if (OpIdx == -1)
10033 break;
10034
10035 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
10036
10037 if (ModIdx == -1)
10038 continue;
10039
10040 // For MAC instructions, src2 is tied to vdst and its op_sel bit
10041 // is not encoded.
10042 if (AMDGPU::isMAC(Opc) && ModOps[J] == AMDGPU::OpName::src2_modifiers)
10043 continue;
10044
10045 uint32_t ModVal = 0;
10046
10047 const MCOperand &SrcOp = Inst.getOperand(OpIdx);
10048 if (SrcOp.isReg() && getMRI()
10049 ->getRegClass(AMDGPU::VGPR_16RegClassID)
10050 .contains(SrcOp.getReg())) {
10051 bool VGPRSuffixIsHi = AMDGPU::isHi16Reg(SrcOp.getReg(), *getMRI());
10052 if (VGPRSuffixIsHi)
10053 ModVal |= SISrcMods::OP_SEL_0;
10054 } else {
10055 if ((OpSel & (1 << J)) != 0)
10056 ModVal |= SISrcMods::OP_SEL_0;
10057 }
10058
10059 if ((OpSelHi & (1 << J)) != 0)
10060 ModVal |= SISrcMods::OP_SEL_1;
10061
10062 if ((NegLo & (1 << J)) != 0)
10063 ModVal |= SISrcMods::NEG;
10064
10065 if ((NegHi & (1 << J)) != 0)
10066 ModVal |= SISrcMods::NEG_HI;
10067
10068 Inst.getOperand(ModIdx).setImm(Inst.getOperand(ModIdx).getImm() | ModVal);
10069 }
10070}
10071
10072void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst, const OperandVector &Operands) {
10073 OptionalImmIndexMap OptIdx;
10074 cvtVOP3(Inst, Operands, OptIdx);
10075 cvtVOP3P(Inst, Operands, OptIdx);
10076}
10077
10079 unsigned i, unsigned Opc,
10080 AMDGPU::OpName OpName) {
10081 if (AMDGPU::getNamedOperandIdx(Opc, OpName) != -1)
10082 ((AMDGPUOperand &)*Operands[i]).addRegOrImmWithFPInputModsOperands(Inst, 2);
10083 else
10084 ((AMDGPUOperand &)*Operands[i]).addRegOperands(Inst, 1);
10085}
10086
10087void AMDGPUAsmParser::cvtSWMMAC(MCInst &Inst, const OperandVector &Operands) {
10088 unsigned Opc = Inst.getOpcode();
10089
10090 ((AMDGPUOperand &)*Operands[1]).addRegOperands(Inst, 1);
10091 addSrcModifiersAndSrc(Inst, Operands, 2, Opc, AMDGPU::OpName::src0_modifiers);
10092 addSrcModifiersAndSrc(Inst, Operands, 3, Opc, AMDGPU::OpName::src1_modifiers);
10093 ((AMDGPUOperand &)*Operands[1]).addRegOperands(Inst, 1); // srcTiedDef
10094 ((AMDGPUOperand &)*Operands[4]).addRegOperands(Inst, 1); // src2
10095
10096 OptionalImmIndexMap OptIdx;
10097 for (unsigned i = 5; i < Operands.size(); ++i) {
10098 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
10099 OptIdx[Op.getImmTy()] = i;
10100 }
10101
10102 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::index_key_8bit))
10103 addOptionalImmOperand(Inst, Operands, OptIdx,
10104 AMDGPUOperand::ImmTyIndexKey8bit);
10105
10106 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::index_key_16bit))
10107 addOptionalImmOperand(Inst, Operands, OptIdx,
10108 AMDGPUOperand::ImmTyIndexKey16bit);
10109
10110 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::index_key_32bit))
10111 addOptionalImmOperand(Inst, Operands, OptIdx,
10112 AMDGPUOperand::ImmTyIndexKey32bit);
10113
10114 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp))
10115 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyClamp);
10116
10117 cvtVOP3P(Inst, Operands, OptIdx);
10118}
10119
10120//===----------------------------------------------------------------------===//
10121// VOPD
10122//===----------------------------------------------------------------------===//
10123
10124ParseStatus AMDGPUAsmParser::parseVOPD(OperandVector &Operands) {
10125 if (!hasVOPD(getSTI()))
10126 return ParseStatus::NoMatch;
10127
10128 if (isToken(AsmToken::Colon) && peekToken(false).is(AsmToken::Colon)) {
10129 SMLoc S = getLoc();
10130 lex();
10131 lex();
10132 Operands.push_back(AMDGPUOperand::CreateToken(this, "::", S));
10133 SMLoc OpYLoc = getLoc();
10134 StringRef OpYName;
10135 if (isToken(AsmToken::Identifier) && !Parser.parseIdentifier(OpYName)) {
10136 Operands.push_back(AMDGPUOperand::CreateToken(this, OpYName, OpYLoc));
10137 return ParseStatus::Success;
10138 }
10139 return Error(OpYLoc, "expected a VOPDY instruction after ::");
10140 }
10141 return ParseStatus::NoMatch;
10142}
10143
10144// Create VOPD MCInst operands using parsed assembler operands.
10145void AMDGPUAsmParser::cvtVOPD(MCInst &Inst, const OperandVector &Operands) {
10146 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
10147
10148 auto addOp = [&](uint16_t ParsedOprIdx) { // NOLINT:function pointer
10149 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[ParsedOprIdx]);
10151 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
10152 return;
10153 }
10154 if (Op.isReg()) {
10155 Op.addRegOperands(Inst, 1);
10156 return;
10157 }
10158 if (Op.isImm()) {
10159 Op.addImmOperands(Inst, 1);
10160 return;
10161 }
10162 llvm_unreachable("Unhandled operand type in cvtVOPD");
10163 };
10164
10165 const auto &InstInfo = getVOPDInstInfo(Inst.getOpcode(), &MII);
10166
10167 // MCInst operands are ordered as follows:
10168 // dstX, dstY, src0X [, other OpX operands], src0Y [, other OpY operands]
10169
10170 for (auto CompIdx : VOPD::COMPONENTS) {
10171 addOp(InstInfo[CompIdx].getIndexOfDstInParsedOperands());
10172 }
10173
10174 for (auto CompIdx : VOPD::COMPONENTS) {
10175 const auto &CInfo = InstInfo[CompIdx];
10176 auto CompSrcOperandsNum = InstInfo[CompIdx].getCompParsedSrcOperandsNum();
10177 for (unsigned CompSrcIdx = 0; CompSrcIdx < CompSrcOperandsNum; ++CompSrcIdx)
10178 addOp(CInfo.getIndexOfSrcInParsedOperands(CompSrcIdx));
10179 if (CInfo.hasSrc2Acc())
10180 addOp(CInfo.getIndexOfDstInParsedOperands());
10181 }
10182
10183 int BitOp3Idx =
10184 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::bitop3);
10185 if (BitOp3Idx != -1) {
10186 OptionalImmIndexMap OptIdx;
10187 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands.back());
10188 if (Op.isImm())
10189 OptIdx[Op.getImmTy()] = Operands.size() - 1;
10190
10191 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyBitOp3);
10192 }
10193}
10194
10195//===----------------------------------------------------------------------===//
10196// dpp
10197//===----------------------------------------------------------------------===//
10198
10199bool AMDGPUOperand::isDPP8() const { return isImmTy(ImmTyDPP8); }
10200
10201bool AMDGPUOperand::isDPPCtrl() const {
10202 using namespace AMDGPU::DPP;
10203
10204 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
10205 if (result) {
10206 int64_t Imm = getImm();
10207 return (Imm >= DppCtrl::QUAD_PERM_FIRST &&
10208 Imm <= DppCtrl::QUAD_PERM_LAST) ||
10209 (Imm >= DppCtrl::ROW_SHL_FIRST && Imm <= DppCtrl::ROW_SHL_LAST) ||
10210 (Imm >= DppCtrl::ROW_SHR_FIRST && Imm <= DppCtrl::ROW_SHR_LAST) ||
10211 (Imm >= DppCtrl::ROW_ROR_FIRST && Imm <= DppCtrl::ROW_ROR_LAST) ||
10212 (Imm == DppCtrl::WAVE_SHL1) || (Imm == DppCtrl::WAVE_ROL1) ||
10213 (Imm == DppCtrl::WAVE_SHR1) || (Imm == DppCtrl::WAVE_ROR1) ||
10214 (Imm == DppCtrl::ROW_MIRROR) || (Imm == DppCtrl::ROW_HALF_MIRROR) ||
10215 (Imm == DppCtrl::BCAST15) || (Imm == DppCtrl::BCAST31) ||
10216 (Imm >= DppCtrl::ROW_SHARE_FIRST &&
10217 Imm <= DppCtrl::ROW_SHARE_LAST) ||
10218 (Imm >= DppCtrl::ROW_XMASK_FIRST && Imm <= DppCtrl::ROW_XMASK_LAST);
10219 }
10220 return false;
10221}
10222
10223//===----------------------------------------------------------------------===//
10224// mAI
10225//===----------------------------------------------------------------------===//
10226
10227bool AMDGPUOperand::isBLGP() const {
10228 return isImm() && getImmTy() == ImmTyBLGP && isUInt<3>(getImm());
10229}
10230
10231bool AMDGPUOperand::isS16Imm() const {
10232 return isImmLiteral() && (isInt<16>(getImm()) || isUInt<16>(getImm()));
10233}
10234
10235bool AMDGPUOperand::isU16Imm() const {
10236 return isImmLiteral() && isUInt<16>(getImm());
10237}
10238
10239//===----------------------------------------------------------------------===//
10240// dim
10241//===----------------------------------------------------------------------===//
10242
10243bool AMDGPUAsmParser::parseDimId(unsigned &Encoding) {
10244 // We want to allow "dim:1D" etc.,
10245 // but the initial 1 is tokenized as an integer.
10246 std::string Token;
10247 if (isToken(AsmToken::Integer)) {
10248 SMLoc Loc = getToken().getEndLoc();
10249 Token = std::string(getTokenStr());
10250 lex();
10251 if (getLoc() != Loc)
10252 return false;
10253 }
10254
10255 StringRef Suffix;
10256 if (!parseId(Suffix))
10257 return false;
10258 Token += Suffix;
10259
10260 StringRef DimId = Token;
10261 DimId.consume_front("SQ_RSRC_IMG_");
10262
10263 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByAsmSuffix(DimId);
10264 if (!DimInfo)
10265 return false;
10266
10267 Encoding = DimInfo->Encoding;
10268 return true;
10269}
10270
10271ParseStatus AMDGPUAsmParser::parseDim(OperandVector &Operands) {
10272 if (!isGFX10Plus())
10273 return ParseStatus::NoMatch;
10274
10275 SMLoc S = getLoc();
10276
10277 if (!trySkipId("dim", AsmToken::Colon))
10278 return ParseStatus::NoMatch;
10279
10280 unsigned Encoding;
10281 SMLoc Loc = getLoc();
10282 if (!parseDimId(Encoding))
10283 return Error(Loc, "invalid dim value");
10284
10285 Operands.push_back(
10286 AMDGPUOperand::CreateImm(this, Encoding, S, AMDGPUOperand::ImmTyDim));
10287 return ParseStatus::Success;
10288}
10289
10290//===----------------------------------------------------------------------===//
10291// dpp
10292//===----------------------------------------------------------------------===//
10293
10294ParseStatus AMDGPUAsmParser::parseDPP8(OperandVector &Operands) {
10295 SMLoc S = getLoc();
10296
10297 if (!isGFX10Plus() || !trySkipId("dpp8", AsmToken::Colon))
10298 return ParseStatus::NoMatch;
10299
10300 // dpp8:[%d,%d,%d,%d,%d,%d,%d,%d]
10301
10302 int64_t Sels[8];
10303
10304 if (!skipToken(AsmToken::LBrac, "expected an opening square bracket"))
10305 return ParseStatus::Failure;
10306
10307 for (size_t i = 0; i < 8; ++i) {
10308 if (i > 0 && !skipToken(AsmToken::Comma, "expected a comma"))
10309 return ParseStatus::Failure;
10310
10311 SMLoc Loc = getLoc();
10312 if (getParser().parseAbsoluteExpression(Sels[i]))
10313 return ParseStatus::Failure;
10314 if (0 > Sels[i] || 7 < Sels[i])
10315 return Error(Loc, "expected a 3-bit value");
10316 }
10317
10318 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket"))
10319 return ParseStatus::Failure;
10320
10321 unsigned DPP8 = 0;
10322 for (size_t i = 0; i < 8; ++i)
10323 DPP8 |= (Sels[i] << (i * 3));
10324
10325 Operands.push_back(
10326 AMDGPUOperand::CreateImm(this, DPP8, S, AMDGPUOperand::ImmTyDPP8));
10327 return ParseStatus::Success;
10328}
10329
10330bool AMDGPUAsmParser::isSupportedDPPCtrl(StringRef Ctrl,
10331 const OperandVector &Operands) {
10332 if (Ctrl == "row_newbcast")
10333 return isGFX90A();
10334
10335 if (Ctrl == "row_share" || Ctrl == "row_xmask")
10336 return isGFX10Plus();
10337
10338 if (Ctrl == "wave_shl" || Ctrl == "wave_shr" || Ctrl == "wave_rol" ||
10339 Ctrl == "wave_ror" || Ctrl == "row_bcast")
10340 return isVI() || isGFX9();
10341
10342 return Ctrl == "row_mirror" || Ctrl == "row_half_mirror" ||
10343 Ctrl == "quad_perm" || Ctrl == "row_shl" || Ctrl == "row_shr" ||
10344 Ctrl == "row_ror";
10345}
10346
10347int64_t AMDGPUAsmParser::parseDPPCtrlPerm() {
10348 // quad_perm:[%d,%d,%d,%d]
10349
10350 if (!skipToken(AsmToken::LBrac, "expected an opening square bracket"))
10351 return -1;
10352
10353 int64_t Val = 0;
10354 for (int i = 0; i < 4; ++i) {
10355 if (i > 0 && !skipToken(AsmToken::Comma, "expected a comma"))
10356 return -1;
10357
10358 int64_t Temp;
10359 SMLoc Loc = getLoc();
10360 if (getParser().parseAbsoluteExpression(Temp))
10361 return -1;
10362 if (Temp < 0 || Temp > 3) {
10363 Error(Loc, "expected a 2-bit value");
10364 return -1;
10365 }
10366
10367 Val += (Temp << i * 2);
10368 }
10369
10370 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket"))
10371 return -1;
10372
10373 return Val;
10374}
10375
10376int64_t AMDGPUAsmParser::parseDPPCtrlSel(StringRef Ctrl) {
10377 using namespace AMDGPU::DPP;
10378
10379 // sel:%d
10380
10381 int64_t Val;
10382 SMLoc Loc = getLoc();
10383
10384 if (getParser().parseAbsoluteExpression(Val))
10385 return -1;
10386
10387 struct DppCtrlCheck {
10388 int64_t Ctrl;
10389 int Lo;
10390 int Hi;
10391 };
10392
10393 DppCtrlCheck Check =
10394 StringSwitch<DppCtrlCheck>(Ctrl)
10395 .Case("wave_shl", {DppCtrl::WAVE_SHL1, 1, 1})
10396 .Case("wave_rol", {DppCtrl::WAVE_ROL1, 1, 1})
10397 .Case("wave_shr", {DppCtrl::WAVE_SHR1, 1, 1})
10398 .Case("wave_ror", {DppCtrl::WAVE_ROR1, 1, 1})
10399 .Case("row_shl", {DppCtrl::ROW_SHL0, 1, 15})
10400 .Case("row_shr", {DppCtrl::ROW_SHR0, 1, 15})
10401 .Case("row_ror", {DppCtrl::ROW_ROR0, 1, 15})
10402 .Case("row_share", {DppCtrl::ROW_SHARE_FIRST, 0, 15})
10403 .Case("row_xmask", {DppCtrl::ROW_XMASK_FIRST, 0, 15})
10404 .Case("row_newbcast", {DppCtrl::ROW_NEWBCAST_FIRST, 0, 15})
10405 .Default({-1, 0, 0});
10406
10407 bool Valid;
10408 if (Check.Ctrl == -1) {
10409 Valid = (Ctrl == "row_bcast" && (Val == 15 || Val == 31));
10410 Val = (Val == 15) ? DppCtrl::BCAST15 : DppCtrl::BCAST31;
10411 } else {
10412 Valid = Check.Lo <= Val && Val <= Check.Hi;
10413 Val = (Check.Lo == Check.Hi) ? Check.Ctrl : (Check.Ctrl | Val);
10414 }
10415
10416 if (!Valid) {
10417 Error(Loc, Twine("invalid ", Ctrl) + Twine(" value"));
10418 return -1;
10419 }
10420
10421 return Val;
10422}
10423
10424ParseStatus AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
10425 using namespace AMDGPU::DPP;
10426
10427 if (!isToken(AsmToken::Identifier) ||
10428 !isSupportedDPPCtrl(getTokenStr(), Operands))
10429 return ParseStatus::NoMatch;
10430
10431 SMLoc S = getLoc();
10432 int64_t Val = -1;
10433 StringRef Ctrl;
10434
10435 parseId(Ctrl);
10436
10437 if (Ctrl == "row_mirror") {
10438 Val = DppCtrl::ROW_MIRROR;
10439 } else if (Ctrl == "row_half_mirror") {
10440 Val = DppCtrl::ROW_HALF_MIRROR;
10441 } else {
10442 if (skipToken(AsmToken::Colon, "expected a colon")) {
10443 if (Ctrl == "quad_perm") {
10444 Val = parseDPPCtrlPerm();
10445 } else {
10446 Val = parseDPPCtrlSel(Ctrl);
10447 }
10448 }
10449 }
10450
10451 if (Val == -1)
10452 return ParseStatus::Failure;
10453
10454 Operands.push_back(
10455 AMDGPUOperand::CreateImm(this, Val, S, AMDGPUOperand::ImmTyDppCtrl));
10456 return ParseStatus::Success;
10457}
10458
10459void AMDGPUAsmParser::cvtVOP3DPP(MCInst &Inst, const OperandVector &Operands,
10460 bool IsDPP8) {
10461 OptionalImmIndexMap OptionalIdx;
10462 unsigned Opc = Inst.getOpcode();
10463 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
10464
10465 // MAC instructions are special because they have 'old'
10466 // operand which is not tied to dst (but assumed to be).
10467 // They also have dummy unused src2_modifiers.
10468 int OldIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::old);
10469 int Src2ModIdx =
10470 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers);
10471 bool IsMAC = OldIdx != -1 && Src2ModIdx != -1 &&
10472 Desc.getOperandConstraint(OldIdx, MCOI::TIED_TO) == -1;
10473
10474 unsigned I = 1;
10475 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
10476 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
10477 }
10478
10479 int Fi = 0;
10480 int VdstInIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
10481 bool IsVOP3CvtSrDpp = Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_dpp8_gfx12 ||
10482 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_dpp8_gfx13 ||
10483 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_dpp8_gfx12 ||
10484 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_dpp8_gfx13 ||
10485 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_dpp_gfx12 ||
10486 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_dpp_gfx13 ||
10487 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_dpp_gfx12 ||
10488 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_dpp_gfx13;
10489
10490 for (unsigned E = Operands.size(); I != E; ++I) {
10491
10492 if (IsMAC) {
10493 int NumOperands = Inst.getNumOperands();
10494 if (OldIdx == NumOperands) {
10495 // Handle old operand
10496 constexpr int DST_IDX = 0;
10497 Inst.addOperand(Inst.getOperand(DST_IDX));
10498 } else if (Src2ModIdx == NumOperands) {
10499 // Add unused dummy src2_modifiers
10501 }
10502 }
10503
10504 if (VdstInIdx == static_cast<int>(Inst.getNumOperands())) {
10505 Inst.addOperand(Inst.getOperand(0));
10506 }
10507
10508 if (IsVOP3CvtSrDpp) {
10509 if (Src2ModIdx == static_cast<int>(Inst.getNumOperands())) {
10511 Inst.addOperand(MCOperand::createReg(MCRegister()));
10512 }
10513 }
10514
10515 auto TiedTo =
10516 Desc.getOperandConstraint(Inst.getNumOperands(), MCOI::TIED_TO);
10517 if (TiedTo != -1) {
10518 assert((unsigned)TiedTo < Inst.getNumOperands());
10519 // handle tied old or src2 for MAC instructions
10520 Inst.addOperand(Inst.getOperand(TiedTo));
10521 }
10522 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
10523 // Add the register arguments
10524 if (IsDPP8 && Op.isDppFI()) {
10525 Fi = Op.getImm();
10526 } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
10527 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
10528 } else if (Op.isReg()) {
10529 Op.addRegOperands(Inst, 1);
10530 } else if (Op.isImm() &&
10531 Desc.operands()[Inst.getNumOperands()].RegClass != -1) {
10532 Op.addImmOperands(Inst, 1);
10533 } else if (Op.isImm()) {
10534 OptionalIdx[Op.getImmTy()] = I;
10535 } else {
10536 llvm_unreachable("unhandled operand type");
10537 }
10538 }
10539
10540 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp) && !IsVOP3CvtSrDpp)
10541 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10542 AMDGPUOperand::ImmTyClamp);
10543
10544 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::byte_sel)) {
10545 if (VdstInIdx == static_cast<int>(Inst.getNumOperands()))
10546 Inst.addOperand(Inst.getOperand(0));
10547 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10548 AMDGPUOperand::ImmTyByteSel);
10549 }
10550
10551 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod))
10552 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10553 AMDGPUOperand::ImmTyOModSI);
10554
10556 cvtVOP3P(Inst, Operands, OptionalIdx);
10557 else if (SIInstrFlags::isVOP3(Desc))
10558 cvtVOP3OpSel(Inst, Operands, OptionalIdx);
10559 else if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) {
10560 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10561 AMDGPUOperand::ImmTyOpSel);
10562 }
10563
10564 if (IsDPP8) {
10565 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10566 AMDGPUOperand::ImmTyDPP8);
10567 using namespace llvm::AMDGPU::DPP;
10568 Inst.addOperand(MCOperand::createImm(Fi ? DPP8_FI_1 : DPP8_FI_0));
10569 } else {
10570 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10571 AMDGPUOperand::ImmTyDppCtrl, 0xe4);
10572 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10573 AMDGPUOperand::ImmTyDppRowMask, 0xf);
10574 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10575 AMDGPUOperand::ImmTyDppBankMask, 0xf);
10576 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10577 AMDGPUOperand::ImmTyDppBoundCtrl);
10578
10579 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::fi))
10580 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10581 AMDGPUOperand::ImmTyDppFI);
10582 }
10583}
10584
10585void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands,
10586 bool IsDPP8) {
10587 OptionalImmIndexMap OptionalIdx;
10588
10589 unsigned I = 1;
10590 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
10591 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
10592 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
10593 }
10594
10595 int Fi = 0;
10596 for (unsigned E = Operands.size(); I != E; ++I) {
10597 auto TiedTo =
10598 Desc.getOperandConstraint(Inst.getNumOperands(), MCOI::TIED_TO);
10599 if (TiedTo != -1) {
10600 assert((unsigned)TiedTo < Inst.getNumOperands());
10601 // handle tied old or src2 for MAC instructions
10602 Inst.addOperand(Inst.getOperand(TiedTo));
10603 }
10604 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
10605 // Add the register arguments
10606 if (Op.isReg() && validateVccOperand(Op.getReg())) {
10607 // VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token.
10608 // Skip it.
10609 continue;
10610 }
10611
10612 if (IsDPP8) {
10613 if (Op.isDPP8()) {
10614 Op.addImmOperands(Inst, 1);
10615 } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
10616 Op.addRegWithFPInputModsOperands(Inst, 2);
10617 } else if (Op.isDppFI()) {
10618 Fi = Op.getImm();
10619 } else if (Op.isReg()) {
10620 Op.addRegOperands(Inst, 1);
10621 } else {
10622 llvm_unreachable("Invalid operand type");
10623 }
10624 } else {
10626 Op.addRegWithFPInputModsOperands(Inst, 2);
10627 } else if (Op.isReg()) {
10628 Op.addRegOperands(Inst, 1);
10629 } else if (Op.isDPPCtrl()) {
10630 Op.addImmOperands(Inst, 1);
10631 } else if (Op.isImm()) {
10632 // Handle optional arguments
10633 OptionalIdx[Op.getImmTy()] = I;
10634 } else {
10635 llvm_unreachable("Invalid operand type");
10636 }
10637 }
10638 }
10639
10640 if (IsDPP8) {
10641 using namespace llvm::AMDGPU::DPP;
10642 Inst.addOperand(MCOperand::createImm(Fi ? DPP8_FI_1 : DPP8_FI_0));
10643 } else {
10644 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10645 AMDGPUOperand::ImmTyDppRowMask, 0xf);
10646 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10647 AMDGPUOperand::ImmTyDppBankMask, 0xf);
10648 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10649 AMDGPUOperand::ImmTyDppBoundCtrl);
10650 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::fi)) {
10651 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10652 AMDGPUOperand::ImmTyDppFI);
10653 }
10654 }
10655}
10656
10657//===----------------------------------------------------------------------===//
10658// sdwa
10659//===----------------------------------------------------------------------===//
10660
10661ParseStatus AMDGPUAsmParser::parseSDWASel(OperandVector &Operands,
10662 StringRef Prefix,
10663 AMDGPUOperand::ImmTy Type) {
10664 return parseStringOrIntWithPrefix(
10665 Operands, Prefix,
10666 {"BYTE_0", "BYTE_1", "BYTE_2", "BYTE_3", "WORD_0", "WORD_1", "DWORD"},
10667 Type);
10668}
10669
10670ParseStatus AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
10671 return parseStringOrIntWithPrefix(
10672 Operands, "dst_unused", {"UNUSED_PAD", "UNUSED_SEXT", "UNUSED_PRESERVE"},
10673 AMDGPUOperand::ImmTySDWADstUnused);
10674}
10675
10676void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
10677 cvtSDWA(Inst, Operands, SDWAInstType::VOP1);
10678}
10679
10680void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
10681 cvtSDWA(Inst, Operands, SDWAInstType::VOP2);
10682}
10683
10684void AMDGPUAsmParser::cvtSdwaVOP2b(MCInst &Inst,
10685 const OperandVector &Operands) {
10686 cvtSDWA(Inst, Operands, SDWAInstType::VOP2, true, true);
10687}
10688
10689void AMDGPUAsmParser::cvtSdwaVOP2e(MCInst &Inst,
10690 const OperandVector &Operands) {
10691 cvtSDWA(Inst, Operands, SDWAInstType::VOP2, false, true);
10692}
10693
10694void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
10695 cvtSDWA(Inst, Operands, SDWAInstType::VOPC, isVI());
10696}
10697
10698void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
10699 SDWAInstType BasicInstType, bool SkipDstVcc,
10700 bool SkipSrcVcc) {
10701 using namespace llvm::AMDGPU::SDWA;
10702
10703 OptionalImmIndexMap OptionalIdx;
10704 bool SkipVcc = SkipDstVcc || SkipSrcVcc;
10705 bool SkippedVcc = false;
10706
10707 unsigned I = 1;
10708 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
10709 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
10710 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
10711 }
10712
10713 for (unsigned E = Operands.size(); I != E; ++I) {
10714 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
10715 if (SkipVcc && !SkippedVcc && Op.isReg() &&
10716 (Op.getReg() == AMDGPU::VCC || Op.getReg() == AMDGPU::VCC_LO)) {
10717 // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst.
10718 // Skip it if it's 2nd (e.g. v_add_i32_sdwa v1, vcc, v2, v3)
10719 // or 4th (v_addc_u32_sdwa v1, vcc, v2, v3, vcc) operand.
10720 // Skip VCC only if we didn't skip it on previous iteration.
10721 // Note that src0 and src1 occupy 2 slots each because of modifiers.
10722 if (BasicInstType == SDWAInstType::VOP2 &&
10723 ((SkipDstVcc && Inst.getNumOperands() == 1) ||
10724 (SkipSrcVcc && Inst.getNumOperands() == 5))) {
10725 SkippedVcc = true;
10726 continue;
10727 }
10728 if (BasicInstType == SDWAInstType::VOPC && Inst.getNumOperands() == 0) {
10729 SkippedVcc = true;
10730 continue;
10731 }
10732 }
10734 Op.addRegOrImmWithInputModsOperands(Inst, 2);
10735 } else if (Op.isImm()) {
10736 // Handle optional arguments
10737 OptionalIdx[Op.getImmTy()] = I;
10738 } else {
10739 llvm_unreachable("Invalid operand type");
10740 }
10741 SkippedVcc = false;
10742 }
10743
10744 const unsigned Opc = Inst.getOpcode();
10745 if (Opc != AMDGPU::V_NOP_sdwa_gfx10 && Opc != AMDGPU::V_NOP_sdwa_gfx9 &&
10746 Opc != AMDGPU::V_NOP_sdwa_vi) {
10747 // v_nop_sdwa_sdwa_vi/gfx9 has no optional sdwa arguments
10748 switch (BasicInstType) {
10749 case SDWAInstType::VOP1:
10750 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp))
10751 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10752 AMDGPUOperand::ImmTyClamp, 0);
10753
10754 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod))
10755 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10756 AMDGPUOperand::ImmTyOModSI, 0);
10757
10758 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::dst_sel))
10759 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10760 AMDGPUOperand::ImmTySDWADstSel, SdwaSel::DWORD);
10761
10762 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::dst_unused))
10763 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10764 AMDGPUOperand::ImmTySDWADstUnused,
10765 DstUnused::UNUSED_PRESERVE);
10766
10767 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10768 AMDGPUOperand::ImmTySDWASrc0Sel, SdwaSel::DWORD);
10769 break;
10770
10771 case SDWAInstType::VOP2:
10772 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10773 AMDGPUOperand::ImmTyClamp, 0);
10774
10775 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::omod))
10776 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10777 AMDGPUOperand::ImmTyOModSI, 0);
10778
10779 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10780 AMDGPUOperand::ImmTySDWADstSel, SdwaSel::DWORD);
10781 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10782 AMDGPUOperand::ImmTySDWADstUnused,
10783 DstUnused::UNUSED_PRESERVE);
10784 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10785 AMDGPUOperand::ImmTySDWASrc0Sel, SdwaSel::DWORD);
10786 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10787 AMDGPUOperand::ImmTySDWASrc1Sel, SdwaSel::DWORD);
10788 break;
10789
10790 case SDWAInstType::VOPC:
10791 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::clamp))
10792 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10793 AMDGPUOperand::ImmTyClamp, 0);
10794 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10795 AMDGPUOperand::ImmTySDWASrc0Sel, SdwaSel::DWORD);
10796 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10797 AMDGPUOperand::ImmTySDWASrc1Sel, SdwaSel::DWORD);
10798 break;
10799 }
10800 }
10801
10802 // special case v_mac_{f16, f32}:
10803 // it has src2 register operand that is tied to dst operand
10804 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
10805 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
10806 auto *it = Inst.begin();
10807 std::advance(
10808 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
10809 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
10810 }
10811}
10812
10813/// Force static initialization.
10814extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
10820
10821#define GET_MATCHER_IMPLEMENTATION
10822#define GET_MNEMONIC_SPELL_CHECKER
10823#define GET_MNEMONIC_CHECKER
10824#include "AMDGPUGenAsmMatcher.inc"
10825
10826ParseStatus AMDGPUAsmParser::parseCustomOperand(OperandVector &Operands,
10827 unsigned MCK) {
10828 switch (MCK) {
10829 case MCK_addr64:
10830 return parseTokenOp("addr64", Operands);
10831 case MCK_done:
10832 return parseNamedBit("done", Operands, AMDGPUOperand::ImmTyDone, true);
10833 case MCK_idxen:
10834 return parseTokenOp("idxen", Operands);
10835 case MCK_lds:
10836 return parseNamedBit("lds", Operands, AMDGPUOperand::ImmTyLDS,
10837 /*IgnoreNegative=*/true);
10838 case MCK_offen:
10839 return parseTokenOp("offen", Operands);
10840 case MCK_off:
10841 return parseTokenOp("off", Operands);
10842 case MCK_row_95_en:
10843 return parseNamedBit("row_en", Operands, AMDGPUOperand::ImmTyRowEn, true);
10844 case MCK_gds:
10845 return parseNamedBit("gds", Operands, AMDGPUOperand::ImmTyGDS);
10846 case MCK_tfe:
10847 return parseNamedBit("tfe", Operands, AMDGPUOperand::ImmTyTFE);
10848 }
10849 return tryCustomParseOperand(Operands, MCK);
10850}
10851
10852// This function should be defined after auto-generated include so that we have
10853// MatchClassKind enum defined
10854unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
10855 unsigned Kind) {
10856 // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
10857 // But MatchInstructionImpl() expects to meet token and fails to validate
10858 // operand. This method checks if we are given immediate operand but expect to
10859 // get corresponding token.
10860 AMDGPUOperand &Operand = (AMDGPUOperand &)Op;
10861 switch (Kind) {
10862 case MCK_addr64:
10863 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
10864 case MCK_gds:
10865 return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
10866 case MCK_lds:
10867 return Operand.isLDS() ? Match_Success : Match_InvalidOperand;
10868 case MCK_idxen:
10869 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
10870 case MCK_offen:
10871 return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
10872 case MCK_tfe:
10873 return Operand.isTFE() ? Match_Success : Match_InvalidOperand;
10874 case MCK_done:
10875 return Operand.isDone() ? Match_Success : Match_InvalidOperand;
10876 case MCK_row_95_en:
10877 return Operand.isRowEn() ? Match_Success : Match_InvalidOperand;
10878 case MCK_SSrc_b32:
10879 // When operands have expression values, they will return true for isToken,
10880 // because it is not possible to distinguish between a token and an
10881 // expression at parse time. MatchInstructionImpl() will always try to
10882 // match an operand as a token, when isToken returns true, and when the
10883 // name of the expression is not a valid token, the match will fail,
10884 // so we need to handle it here.
10885 return Operand.isSSrc_b32() ? Match_Success : Match_InvalidOperand;
10886 case MCK_SSrc_f32:
10887 return Operand.isSSrc_f32() ? Match_Success : Match_InvalidOperand;
10888 case MCK_SOPPBrTarget:
10889 return Operand.isSOPPBrTarget() ? Match_Success : Match_InvalidOperand;
10890 case MCK_VReg32OrOff:
10891 return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand;
10892 case MCK_InterpSlot:
10893 return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand;
10894 case MCK_InterpAttr:
10895 return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
10896 case MCK_InterpAttrChan:
10897 return Operand.isInterpAttrChan() ? Match_Success : Match_InvalidOperand;
10898 case MCK_SReg_64:
10899 case MCK_SReg_64_XEXEC:
10900 // Null is defined as a 32-bit register but
10901 // it should also be enabled with 64-bit operands or larger.
10902 // The following code enables it for SReg_64 and larger operands
10903 // used as source and destination. Remaining source
10904 // operands are handled in isInlinableImm.
10905 case MCK_SReg_96:
10906 case MCK_SReg_128:
10907 case MCK_SReg_256:
10908 case MCK_SReg_512:
10909 return Operand.isNull() ? Match_Success : Match_InvalidOperand;
10910 default:
10911 return Match_InvalidOperand;
10912 }
10913}
10914
10915//===----------------------------------------------------------------------===//
10916// endpgm
10917//===----------------------------------------------------------------------===//
10918
10919ParseStatus AMDGPUAsmParser::parseEndpgm(OperandVector &Operands) {
10920 SMLoc S = getLoc();
10921 int64_t Imm = 0;
10922
10923 if (!parseExpr(Imm)) {
10924 // The operand is optional, if not present default to 0
10925 Imm = 0;
10926 }
10927
10928 if (!isUInt<16>(Imm))
10929 return Error(S, "expected a 16-bit value");
10930
10931 Operands.push_back(
10932 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyEndpgm));
10933 return ParseStatus::Success;
10934}
10935
10936bool AMDGPUOperand::isEndpgm() const { return isImmTy(ImmTyEndpgm); }
10937
10938//===----------------------------------------------------------------------===//
10939// Split Barrier
10940//===----------------------------------------------------------------------===//
10941
10942bool AMDGPUOperand::isSplitBarrier() const {
10943 if (!isImm())
10944 return false;
10945
10946 int64_t Imm = getImm();
10949}
#define Success
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
unsigned RegSize
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
SmallVector< int16_t, MAX_SRC_OPERANDS_NUM > OperandIndices
static bool checkWriteLane(const MCInst &Inst)
static bool getRegNum(StringRef Str, unsigned &Num)
static void addSrcModifiersAndSrc(MCInst &Inst, const OperandVector &Operands, unsigned i, unsigned Opc, AMDGPU::OpName OpName)
static constexpr RegInfo RegularRegisters[]
static const RegInfo * getRegularRegInfo(StringRef Str)
static ArrayRef< unsigned > getAllVariants()
static OperandIndices getSrcOperandIndices(unsigned Opcode, bool AddMandatoryLiterals=false)
static int IsAGPROperand(const MCInst &Inst, AMDGPU::OpName Name, const MCRegisterInfo *MRI)
static bool IsMovrelsSDWAOpcode(const unsigned Opcode)
static const fltSemantics * getFltSemantics(unsigned Size)
static bool isRegularReg(RegisterKind Kind)
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAMDGPUAsmParser()
Force static initialization.
static bool ConvertOmodMul(int64_t &Mul)
#define PARSE_BITS_ENTRY(FIELD, ENTRY, VALUE, RANGE)
static bool isInlineableLiteralOp16(int64_t Val, MVT VT, bool HasInv2Pi)
static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT)
static bool AMDGPUCheckMnemonic(StringRef Mnemonic, const FeatureBitset &AvailableFeatures, unsigned VariantID)
static void applyMnemonicAliases(StringRef &Mnemonic, const FeatureBitset &Features, unsigned VariantID)
constexpr unsigned MAX_SRC_OPERANDS_NUM
#define EXPR_RESOLVE_OR_ERROR(RESOLVED)
static bool ConvertOmodDiv(int64_t &Div)
static bool IsRevOpcode(const unsigned Opcode)
static bool encodeCnt(const AMDGPU::IsaVersion ISA, int64_t &IntVal, int64_t CntVal, bool Saturate, unsigned(*encode)(const IsaVersion &Version, unsigned, unsigned), unsigned(*decode)(const IsaVersion &Version, unsigned))
static MCRegister getSpecialRegForName(StringRef RegName)
static void addOptionalImmOperand(MCInst &Inst, const OperandVector &Operands, AMDGPUAsmParser::OptionalImmIndexMap &OptionalIdx, AMDGPUOperand::ImmTy ImmT, int64_t Default=0, std::optional< unsigned > InsertAt=std::nullopt)
static void cvtVOP3DstOpSelOnly(MCInst &Inst, const MCRegisterInfo &MRI)
static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum)
static const fltSemantics * getOpFltSemantics(uint8_t OperandType)
static bool isInvalidVOPDY(const OperandVector &Operands, uint64_t InvalidOprIdx)
static std::string AMDGPUMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, unsigned VariantID=0)
static LLVM_READNONE unsigned encodeBitmaskPerm(const unsigned AndMask, const unsigned OrMask, const unsigned XorMask)
static bool isSafeTruncation(int64_t Val, unsigned Size)
unsigned uint64_t
AMDHSA kernel descriptor MCExpr struct for use in MC layer.
Provides AMDGPU specific target descriptions.
AMDGPU metadata definitions and in-memory representations.
Enums shared between the AMDGPU backend (LLVM) and the ELF linker (LLD) for the .amdgpu....
AMDHSA kernel descriptor definitions.
static bool parseExpr(MCAsmParser &MCParser, const MCExpr *&Value, raw_ostream &Err)
MC layer struct for AMDGPUMCKernelCodeT, provides MCExpr functionality where required.
@ AMD_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32
This file declares a class to represent arbitrary precision floating point values and provide a varie...
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_READNONE
Definition Compiler.h:323
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
@ Default
#define Check(C,...)
static llvm::Expected< InlineInfo > decode(GsymDataExtractor &Data, uint64_t &Offset, uint64_t BaseAddr)
Decode an InlineInfo in Data at the specified offset.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RegName(no)
Loop::LoopBounds::Direction Direction
Definition LoopInfo.cpp:253
static bool hasFeature(StringRef Feature, const FeatureBitset &FeatureBits, ArrayRef< SubtargetFeatureKV > ProcFeatures)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
#define P(N)
if(PassOpts->AAPipeline)
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
SI Fold Operands
Interface definition for SIInstrInfo.
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
const char * Msg
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
This file implements the SmallBitVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
BinaryOperator * Mul
static const char * getRegisterName(MCRegister Reg)
static const AMDGPUMCExpr * createMax(ArrayRef< const MCExpr * > Args, MCContext &Ctx)
static unsigned getNumExpectedArgs(VariantKind Kind)
static const AMDGPUMCExpr * createLit(LitModifier Lit, int64_t Value, MCContext &Ctx)
static const AMDGPUMCExpr * create(VariantKind Kind, ArrayRef< const MCExpr * > Args, MCContext &Ctx)
static const AMDGPUMCExpr * createExtraSGPRs(const MCExpr *VCCUsed, const MCExpr *FlatScrUsed, bool XNACKUsed, MCContext &Ctx)
Allow delayed MCExpr resolve of ExtraSGPRs (in case VCCUsed or FlatScrUsed are unresolvable but neede...
static const AMDGPUMCExpr * createAlignTo(const MCExpr *Value, const MCExpr *Align, MCContext &Ctx)
static std::optional< TargetID > parseTargetIDString(StringRef TargetIDDirective)
Parse and validate a TargetID from a full "<triple>-<processor>:<features>" directive string.
TargetIDSetting getXnackSetting() const
StringRef getTargetTripleString() const
std::string toString() const
TargetIDSetting getSramEccSetting() const
static const fltSemantics & IEEEsingle()
Definition APFloat.h:304
static const fltSemantics & BFloat()
Definition APFloat.h:303
static const fltSemantics & IEEEdouble()
Definition APFloat.h:305
static constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:361
static const fltSemantics & IEEEhalf()
Definition APFloat.h:302
opStatus
IEEE-754R 7: Default exception handling.
Definition APFloat.h:377
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Definition APFloat.cpp:6010
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
Definition ArrayRef.h:218
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
Definition ArrayRef.h:194
const T & front() const
Get the first element.
Definition ArrayRef.h:144
iterator end() const
Definition ArrayRef.h:130
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition MCAsmMacro.h:103
bool is(TokenKind K) const
Definition MCAsmMacro.h:75
Register getReg() const
Container class for subtarget features.
constexpr bool test(unsigned I) const
constexpr FeatureBitset & flip(unsigned I)
void printExpr(raw_ostream &, const MCExpr &) const
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:342
static const MCBinaryExpr * createDiv(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:352
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:427
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
unsigned getNumOperands() const
Definition MCInst.h:212
SMLoc getLoc() const
Definition MCInst.h:208
void setLoc(SMLoc loc)
Definition MCInst.h:207
unsigned getOpcode() const
Definition MCInst.h:202
iterator insert(iterator I, const MCOperand &Op)
Definition MCInst.h:232
void addOperand(const MCOperand Op)
Definition MCInst.h:215
iterator begin()
Definition MCInst.h:227
size_t size() const
Definition MCInst.h:226
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
Describe properties that are true of each instruction in the target description file.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:89
int16_t getOpRegClassID(const MCOperandInfo &OpInfo, unsigned HwModeId) const
Return the ID of the register class to use for OpInfo, for the active HwMode HwModeId.
Definition MCInstrInfo.h:79
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
void setImm(int64_t Val)
Definition MCInst.h:89
static MCOperand createExpr(const MCExpr *Val)
Definition MCInst.h:166
int64_t getImm() const
Definition MCInst.h:84
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
bool isImm() const
Definition MCInst.h:66
void setReg(MCRegister Reg)
Set the register number.
Definition MCInst.h:79
bool isReg() const
Definition MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
MCRegisterClass - Base class of TargetRegisterClass.
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
unsigned getNumRegs() const
getNumRegs - Return the number of registers in this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
bool regsOverlap(MCRegister RegA, MCRegister RegB) const
Returns true if the two registers are equal or alias each other.
const MCRegisterClass & getRegClass(unsigned i) const
Returns the register class associated with the enumeration value.
MCRegister getSubReg(MCRegister Reg, unsigned Idx) const
Returns the physical register number of sub-register "Index" for physical register RegNo.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
constexpr bool isValid() const
Definition MCRegister.h:84
Generic base class for all target subtargets.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
bool isVariable() const
isVariable - Check if this is a variable symbol.
Definition MCSymbol.h:267
LLVM_ABI void setVariableValue(const MCExpr *Value)
Definition MCSymbol.cpp:50
void setRedefinable(bool Value)
Mark this symbol as redefinable.
Definition MCSymbol.h:210
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
Definition MCSymbol.h:270
MCTargetAsmParser - Generic interface to target specific assembly parsers.
Machine Value Type.
SimpleValueType SimpleTy
uint64_t getScalarSizeInBits() const
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
Ternary parse status returned by various parse* methods.
constexpr bool isFailure() const
static constexpr StatusTy Failure
constexpr bool isSuccess() const
static constexpr StatusTy Success
static constexpr StatusTy NoMatch
constexpr bool isNoMatch() const
constexpr unsigned id() const
Definition Register.h:100
Represents a location in source code.
Definition SMLoc.h:22
static SMLoc getFromPointer(const char *Ptr)
Definition SMLoc.h:35
constexpr const char * getPointer() const
Definition SMLoc.h:33
constexpr bool isValid() const
Definition SMLoc.h:28
SMLoc Start
Definition SMLoc.h:49
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition StringRef.h:888
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
Definition StringRef.h:691
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:597
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition StringRef.h:635
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:138
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition StringRef.h:270
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition StringRef.h:661
bool contains(StringRef key) const
Check if the set contains the given key.
Definition StringSet.h:60
std::pair< typename Base::iterator, bool > insert(StringRef key)
Definition StringSet.h:39
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
Definition Twine.cpp:17
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
int encodeDepCtr(const StringRef Name, int64_t Val, unsigned &UsedOprMask, const MCSubtargetInfo &STI)
int getDefaultDepCtrEncoding(const MCSubtargetInfo &STI)
bool isSupportedTgtId(unsigned Id, const MCSubtargetInfo &STI)
unsigned getTgtId(const StringRef Name)
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char NumSGPRs[]
Key for Kernel::CodeProps::Metadata::mNumSGPRs.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
constexpr char AssemblerDirectiveBegin[]
HSA metadata beginning assembler directive.
constexpr char AssemblerDirectiveEnd[]
HSA metadata ending assembler directive.
constexpr char AssemblerDirectiveBegin[]
Old HSA metadata beginning assembler directive for V2.
int64_t getHwregId(StringRef Name, const MCSubtargetInfo &STI)
unsigned getVGPREncodingGranule(const MCSubtargetInfo &STI, std::optional< bool > EnableWavefrontSize32)
unsigned getSGPREncodingGranule(const MCSubtargetInfo &STI)
bool targetIDSettingsConflict(TargetIDSetting Lhs, TargetIDSetting Rhs)
Returns true if Lhs and Rhs are incompatible (both specific but different).
unsigned getLocalMemorySize(const MCSubtargetInfo &STI)
unsigned getDefaultFormatEncoding(const MCSubtargetInfo &STI)
int64_t convertDfmtNfmt2Ufmt(unsigned Dfmt, unsigned Nfmt, const MCSubtargetInfo &STI)
int64_t encodeDfmtNfmt(unsigned Dfmt, unsigned Nfmt)
int64_t getUnifiedFormat(const StringRef Name, const MCSubtargetInfo &STI)
bool isValidFormatEncoding(unsigned Val, const MCSubtargetInfo &STI)
int64_t getNfmt(const StringRef Name, const MCSubtargetInfo &STI)
int64_t getDfmt(const StringRef Name)
constexpr char AssemblerDirective[]
PAL metadata (old linear format) assembler directive.
constexpr char AssemblerDirectiveBegin[]
PAL metadata (new MsgPack format) beginning assembler directive.
constexpr char AssemblerDirectiveEnd[]
PAL metadata (new MsgPack format) ending assembler directive.
int64_t getMsgOpId(int64_t MsgId, StringRef Name, const MCSubtargetInfo &STI)
Map from a symbolic name for a sendmsg operation to the operation portion of the immediate encoding.
int64_t getMsgId(StringRef Name, const MCSubtargetInfo &STI)
Map from a symbolic name for a msg_id to the message portion of the immediate encoding.
uint64_t encodeMsg(uint64_t MsgId, uint64_t OpId, uint64_t StreamId)
bool msgSupportsStream(int64_t MsgId, int64_t OpId, const MCSubtargetInfo &STI)
bool isValidMsgId(int64_t MsgId, const MCSubtargetInfo &STI)
bool isValidMsgStream(int64_t MsgId, int64_t OpId, int64_t StreamId, const MCSubtargetInfo &STI, bool Strict)
bool msgRequiresOp(int64_t MsgId, const MCSubtargetInfo &STI)
bool isValidMsgOp(int64_t MsgId, int64_t OpId, const MCSubtargetInfo &STI, bool Strict)
ArrayRef< GFXVersion > getGFXVersions()
constexpr unsigned COMPONENTS[]
constexpr const char *const ModMatrixFmt[]
constexpr const char *const ModMatrixScaleFmt[]
constexpr const char *const ModMatrixScale[]
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
bool isGFX10_BEncoding(const MCSubtargetInfo &STI)
bool isInlineValue(MCRegister Reg)
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool isSGPR(MCRegister Reg, const MCRegisterInfo *TRI)
Is Reg - scalar register.
MCRegister getMCReg(MCRegister Reg, const MCSubtargetInfo &STI)
If Reg is a pseudo reg, return the correct hardware register given STI otherwise return Reg.
FuncInfoFlags
Per-function flags packed into INFO_FLAGS entries.
uint8_t wmmaScaleF8F6F4FormatToNumRegs(unsigned Fmt)
const int OPR_ID_UNSUPPORTED
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
unsigned getTemporalHintType(const MCInstrDesc TID)
bool isGFX10(const MCSubtargetInfo &STI)
LLVM_READONLY bool isLitExpr(const MCExpr *Expr)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_ABI bool isCPUValidForSubArch(Triple::SubArchType SubArch, GPUKind AK)
Return true if the GPU AK is usable with the triple subarch SubArch.
unsigned getMaxNumUserSGPRs(const MCSubtargetInfo &STI)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool hasA16(const MCSubtargetInfo &STI)
bool isLegalSMRDEncodedSignedOffset(const MCSubtargetInfo &ST, int64_t EncodedOffset, bool IsBuffer)
bool isGFX12Plus(const MCSubtargetInfo &STI)
unsigned getNSAMaxSize(const MCSubtargetInfo &STI, bool HasSampler)
bool hasPackedD16(const MCSubtargetInfo &STI)
bool isGFX940(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
bool isHsaAbi(const MCSubtargetInfo &STI)
bool isGFX11(const MCSubtargetInfo &STI)
const int OPR_VAL_INVALID
bool getSMEMIsBuffer(unsigned Opc)
bool isPackedSingleSGPRFP32Inst(unsigned Opc)
The opcode is a packed fp32 instruction which only reads low 32 bits of a scalar operand and propagat...
bool isGFX13(const MCSubtargetInfo &STI)
LLVM_ABI unsigned getAddressableNumSGPRs(GPUKind AK)
uint8_t mfmaScaleF8F6F4FormatToNumRegs(unsigned EncodingVal)
LLVM_ABI IsaVersion getIsaVersion(StringRef GPU)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
LLVM_ABI unsigned getTotalNumVGPRs(GPUKind AK, bool IsWave32)
CanBeVOPD getCanBeVOPD(unsigned Opc, unsigned EncodingFamily, bool VOPD3)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
bool isSI(const MCSubtargetInfo &STI)
bool hasPrivateApertureRegs(const MCSubtargetInfo &STI)
unsigned decodeLgkmcnt(const IsaVersion &Version, unsigned Waitcnt)
unsigned getWaitcntBitMask(const IsaVersion &Version)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
bool isGFX9(const MCSubtargetInfo &STI)
unsigned getVOPDEncodingFamily(const MCSubtargetInfo &ST)
bool isKImmOperand(const MCInstrDesc &Desc, unsigned OpNo)
Is this a KImm operand?
GPUKind
GPU kinds supported by the AMDGPU target.
bool isGFX90A(const MCSubtargetInfo &STI)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
bool isGFX12(const MCSubtargetInfo &STI)
unsigned encodeExpcnt(const IsaVersion &Version, unsigned Waitcnt, unsigned Expcnt)
bool hasMAIInsts(const MCSubtargetInfo &STI)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByAsmSuffix(StringRef AsmSuffix)
bool hasMIMG_R128(const MCSubtargetInfo &STI)
LLVM_ABI GPUKind parseArchAMDGCN(StringRef CPU)
bool hasG16(const MCSubtargetInfo &STI)
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
bool isGFX13Plus(const MCSubtargetInfo &STI)
bool hasArchitectedFlatScratch(const MCSubtargetInfo &STI)
LLVM_READONLY int64_t getLitValue(const MCExpr *Expr)
bool isGFX11Plus(const MCSubtargetInfo &STI)
bool isSISrcFPOperand(const MCInstrDesc &Desc, unsigned OpNo)
Is this floating-point operand?
bool isGFX10Plus(const MCSubtargetInfo &STI)
AMDGPU::TargetID TargetID
int64_t encode32BitLiteral(int64_t Imm, OperandType Type, bool IsLit)
bool isValidWMMAScaleFmtCombination(unsigned AFmt, unsigned AScale, unsigned BFmt, unsigned BScale)
@ OPERAND_REG_IMM_V2FP64
Definition SIDefines.h:447
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
Definition SIDefines.h:465
@ OPERAND_REG_IMM_INT64
Definition SIDefines.h:432
@ OPERAND_REG_IMM_V2FP16
Definition SIDefines.h:440
@ OPERAND_REG_INLINE_C_FP64
Definition SIDefines.h:456
@ OPERAND_REG_IMM_NOINLINE_FP16
Definition SIDefines.h:438
@ OPERAND_REG_INLINE_C_BF16
Definition SIDefines.h:453
@ OPERAND_REG_INLINE_C_V2BF16
Definition SIDefines.h:458
@ OPERAND_REG_IMM_V2INT64
Definition SIDefines.h:443
@ OPERAND_REG_IMM_V2INT16
Definition SIDefines.h:442
@ OPERAND_REG_IMM_BF16
Definition SIDefines.h:436
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
Definition SIDefines.h:431
@ OPERAND_REG_IMM_V2BF16
Definition SIDefines.h:439
@ OPERAND_REG_IMM_FP16
Definition SIDefines.h:437
@ OPERAND_REG_IMM_V2FP16_SPLAT
Definition SIDefines.h:441
@ OPERAND_REG_INLINE_C_INT64
Definition SIDefines.h:452
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
Definition SIDefines.h:450
@ OPERAND_REG_IMM_NOINLINE_V2FP16
Definition SIDefines.h:444
@ OPERAND_REG_IMM_FP64
Definition SIDefines.h:435
@ OPERAND_REG_INLINE_C_V2FP16
Definition SIDefines.h:459
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
Definition SIDefines.h:470
@ OPERAND_REG_INLINE_AC_FP32
Definition SIDefines.h:471
@ OPERAND_REG_IMM_V2INT32
Definition SIDefines.h:445
@ OPERAND_REG_IMM_FP32
Definition SIDefines.h:434
@ OPERAND_REG_INLINE_C_FP32
Definition SIDefines.h:455
@ OPERAND_REG_INLINE_C_INT32
Definition SIDefines.h:451
@ OPERAND_REG_INLINE_C_V2INT16
Definition SIDefines.h:457
@ OPERAND_REG_IMM_V2FP32
Definition SIDefines.h:446
@ OPERAND_REG_INLINE_AC_FP64
Definition SIDefines.h:472
@ OPERAND_REG_INLINE_C_FP16
Definition SIDefines.h:454
@ OPERAND_REG_IMM_INT16
Definition SIDefines.h:433
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
Definition SIDefines.h:462
bool isDPALU_DPP(const MCInstrDesc &OpDesc, const MCInstrInfo &MII, const MCSubtargetInfo &ST)
LLVM_ABI StringRef getArchNameAMDGCN(GPUKind AK)
bool hasGDS(const MCSubtargetInfo &STI)
bool isLegalSMRDEncodedUnsignedOffset(const MCSubtargetInfo &ST, int64_t EncodedOffset)
bool isGFX9Plus(const MCSubtargetInfo &STI)
bool hasDPPSrc1SGPR(const MCSubtargetInfo &STI)
const int OPR_ID_DUPLICATE
bool isVOPD(unsigned Opc)
VOPD::InstInfo getVOPDInstInfo(const MCInstrDesc &OpX, const MCInstrDesc &OpY)
unsigned encodeVmcnt(const IsaVersion &Version, unsigned Waitcnt, unsigned Vmcnt)
unsigned decodeExpcnt(const IsaVersion &Version, unsigned Waitcnt)
bool isGFX1250(const MCSubtargetInfo &STI)
const MIMGBaseOpcodeInfo * getMIMGBaseOpcode(unsigned Opc)
bool isVI(const MCSubtargetInfo &STI)
bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode)
MCRegister mc2PseudoReg(MCRegister Reg)
Convert hardware register Reg to a pseudo register.
unsigned hasKernargPreload(const MCSubtargetInfo &STI)
bool supportsWGP(const MCSubtargetInfo &STI)
bool isMAC(unsigned Opc)
LLVM_READNONE unsigned getOperandSize(const MCOperandInfo &OpInfo)
bool isCI(const MCSubtargetInfo &STI)
unsigned encodeLgkmcnt(const IsaVersion &Version, unsigned Waitcnt, unsigned Lgkmcnt)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
const int OPR_ID_UNKNOWN
bool isGFX1250Plus(const MCSubtargetInfo &STI)
bool hasPopsExitingWaveID(const MCSubtargetInfo &STI)
unsigned decodeVmcnt(const IsaVersion &Version, unsigned Waitcnt)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
bool hasVOPD(const MCSubtargetInfo &STI)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
bool isPermlane16(unsigned Opc)
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ STT_AMDGPU_HSA_KERNEL
Definition ELF.h:1441
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:233
@ OPERAND_IMMEDIATE
Definition MCInstrDesc.h:61
Predicate getPredicate(unsigned Condition, unsigned Hint)
Return predicate consisting of specified condition and hint bits.
void validate(const Triple &TT, const FeatureBitset &FeatureBits)
constexpr bool isAtomicRet(const T &...O)
Definition SIDefines.h:367
constexpr bool isVOPC(const T &...O)
Definition SIDefines.h:236
constexpr bool isVOP3(const T &...O)
Definition SIDefines.h:239
constexpr bool isVOP1(const T &...O)
Definition SIDefines.h:230
constexpr bool usesTENSOR_CNT(const T &...O)
Definition SIDefines.h:310
constexpr bool isMAI(const T &...O)
Definition SIDefines.h:355
constexpr bool isVOP2(const T &...O)
Definition SIDefines.h:233
constexpr bool isSWMMAC(const T &...O)
Definition SIDefines.h:382
constexpr bool isSOP2(const T &...O)
Definition SIDefines.h:218
constexpr bool isFLAT(const T &...O)
Definition SIDefines.h:286
constexpr bool isVOP3P(const T &...O)
Definition SIDefines.h:242
constexpr bool isBuffer(const T &...O)
Definition SIDefines.h:267
constexpr bool hasIntClamp(const T &...O)
Definition SIDefines.h:331
constexpr bool isAtomicNoRet(const T &...O)
Definition SIDefines.h:364
constexpr bool isSMRD(const T &...O)
Definition SIDefines.h:271
constexpr bool isVOP3Like(const T &...O)
Definition SIDefines.h:245
constexpr bool isMIMG(const T &...O)
Definition SIDefines.h:274
constexpr bool isVMEM(const T &...O)
Definition SIDefines.h:407
constexpr bool isImage(const T &...O)
Definition SIDefines.h:403
constexpr bool isWMMA(const T &...O)
Definition SIDefines.h:370
constexpr bool isVOPD3(const T &...O)
Definition SIDefines.h:385
constexpr bool isGWS(const T &...O)
Definition SIDefines.h:379
constexpr bool isMUBUF(const T &...O)
Definition SIDefines.h:261
constexpr bool isSDWA(const T &...O)
Definition SIDefines.h:252
constexpr bool isSOPC(const T &...O)
Definition SIDefines.h:221
constexpr bool isDOT(const T &...O)
Definition SIDefines.h:358
constexpr bool isVSAMPLE(const T &...O)
Definition SIDefines.h:280
constexpr bool isDS(const T &...O)
Definition SIDefines.h:289
constexpr bool isAtomic(const T &...O)
Definition SIDefines.h:396
constexpr bool isGather4(const T &...O)
Definition SIDefines.h:307
constexpr bool isPacked(const T &...O)
Definition SIDefines.h:340
constexpr bool isDPP(const T &...O)
Definition SIDefines.h:255
constexpr bool isSegmentSpecificFLAT(const T &...O)
Definition SIDefines.h:399
@ Valid
The data is already valid.
EnumSet< Modifier, Modifier_enumSize > Modifiers
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
bool isNull(StringRef S)
Definition YAMLTraits.h:571
This is an optimization pass for GlobalISel generic memory operations.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
Definition Error.h:1129
@ Offset
Definition DWP.cpp:577
StringMapEntry< Value * > ValueName
Definition Value.h:56
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
unsigned encode(MaybeAlign A)
Returns a representation of the alignment that encodes undefined as 0.
Definition Alignment.h:206
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
static bool isMem(const MachineInstr &MI, unsigned Op)
LLVM_ABI std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \t\n\v\f\r")
getToken - This function extracts one token from source, ignoring any leading characters that appear ...
static StringRef getCPU(StringRef CPU)
Processes a CPU name.
testing::Matcher< const detail::ErrorHolder & > Failed()
Definition Error.h:198
LLVM_ABI void PrintError(const Twine &Msg)
Definition Error.cpp:104
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition MathExtras.h:244
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
Definition bit.h:362
Op::Description Desc
Target & getTheR600Target()
The target for R600 GPUs.
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
SmallVectorImpl< std::unique_ptr< MCParsedAsmOperand > > OperandVector
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
Target & getTheGCNTarget()
The target for GCN GPUs.
@ Sub
Subtraction of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
DWARFExpression::Operation Op
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
unsigned M0(unsigned Val)
Definition VE.h:376
ArrayRef(const T &OneElt) -> ArrayRef< T >
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1772
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:249
Target & getTheGCNLegacyTarget()
The target for GCN GPUs, registered under the legacy "amdgcn" architecture name for use with -march.
@ Enabled
Convert any .debug_str_offsets tables to DWARF64 if needed.
Definition DWP.h:31
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
#define N
RegisterKind Kind
StringLiteral Name
void initDefault(const MCSubtargetInfo &STI, MCContext &Ctx, bool InitMCExpr=true)
void validate(const MCSubtargetInfo *STI, MCContext &Ctx)
SmallVector< std::pair< MCSymbol *, std::string >, 4 > IndirectCalls
SmallVector< std::pair< MCSymbol *, MCSymbol * >, 8 > Calls
SmallVector< FuncInfo, 8 > Funcs
SmallVector< std::pair< MCSymbol *, std::string >, 4 > TypeIds
SmallVector< std::pair< MCSymbol *, MCSymbol * >, 4 > Uses
Instruction set architecture version.
static void bits_set(const MCExpr *&Dst, const MCExpr *Value, uint32_t Shift, uint32_t Mask, MCContext &Ctx)
static MCKernelDescriptor getDefaultAmdhsaKernelDescriptor(const MCSubtargetInfo *STI, MCContext &Ctx)
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...