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