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