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