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 /// State for checking that every kernel named in a .amdhsa_kernel directive
1156 /// begins with the required prologue instruction sequence. Because the
1157 /// directive may appear either before or after the kernel's label (it is
1158 /// normally emitted after the function body, in .rodata), validation is
1159 /// deferred to onEndOfFile(). We record an order-independent timeline of
1160 /// parsed labels and emitted instruction opcodes, plus the set of symbols
1161 /// named by .amdhsa_kernel directives, and match them up at end of file.
1162 SmallVector<unsigned> OpcodeStream;
1164 OpcodeStreamSymbols;
1165 SmallPtrSet<const MCSymbol *, 8> AMDHSAKernelSymbols;
1166
1167 /// Verify recorded kernel prologues.
1168 void checkKernelPrologues();
1169
1170private:
1171 void createConstantSymbol(StringRef Id, int64_t Val);
1172
1173 bool ParseAsAbsoluteExpression(uint32_t &Ret);
1174 bool OutOfRangeError(SMRange Range);
1175 /// Calculate VGPR/SGPR blocks required for given target, reserved
1176 /// registers, and user-specified NextFreeXGPR values.
1177 ///
1178 /// \param Features [in] Target features, used for bug corrections.
1179 /// \param VCCUsed [in] Whether VCC special SGPR is reserved.
1180 /// \param FlatScrUsed [in] Whether FLAT_SCRATCH special SGPR is reserved.
1181 /// \param XNACKUsed [in] Whether XNACK_MASK special SGPR is reserved.
1182 /// \param EnableWavefrontSize32 [in] Value of ENABLE_WAVEFRONT_SIZE32 kernel
1183 /// descriptor field, if valid.
1184 /// \param NextFreeVGPR [in] Max VGPR number referenced, plus one.
1185 /// \param VGPRRange [in] Token range, used for VGPR diagnostics.
1186 /// \param NextFreeSGPR [in] Max SGPR number referenced, plus one.
1187 /// \param SGPRRange [in] Token range, used for SGPR diagnostics.
1188 /// \param VGPRBlocks [out] Result VGPR block count.
1189 /// \param SGPRBlocks [out] Result SGPR block count.
1190 bool calculateGPRBlocks(const FeatureBitset &Features, const MCExpr *VCCUsed,
1191 const MCExpr *FlatScrUsed, bool XNACKUsed,
1192 std::optional<bool> EnableWavefrontSize32,
1193 const MCExpr *NextFreeVGPR, SMRange VGPRRange,
1194 const MCExpr *NextFreeSGPR, SMRange SGPRRange,
1195 const MCExpr *&VGPRBlocks, const MCExpr *&SGPRBlocks);
1196 bool ParseDirectiveAMDGCNTarget();
1197 bool ParseDirectiveAMDHSACodeObjectVersion();
1198 bool ParseDirectiveAMDHSAKernel();
1199 bool ParseAMDKernelCodeTValue(StringRef ID, AMDGPUMCKernelCodeT &Header);
1200 bool ParseDirectiveAMDKernelCodeT();
1201 // TODO: Possibly make subtargetHasRegister const.
1202 bool subtargetHasRegister(const MCRegisterInfo &MRI, MCRegister Reg);
1203 bool ParseDirectiveAMDGPUHsaKernel();
1204
1205 bool ParseDirectiveISAVersion();
1206 bool ParseDirectiveHSAMetadata();
1207 bool ParseDirectivePALMetadataBegin();
1208 bool ParseDirectivePALMetadata();
1209 bool ParseDirectiveAMDGPULDS();
1210 bool ParseDirectiveAMDGPUInfo();
1211
1212 /// Common code to parse out a block of text (typically YAML) between start
1213 /// and end directives.
1214 bool ParseToEndDirective(const char *AssemblerDirectiveBegin,
1215 const char *AssemblerDirectiveEnd,
1216 std::string &CollectString);
1217
1218 bool AddNextRegisterToList(MCRegister &Reg, unsigned &RegWidth,
1219 RegisterKind RegKind, MCRegister Reg1,
1220 RegisterKind RegKind1, SMLoc Loc);
1221 bool ParseAMDGPURegister(RegisterKind &RegKind, MCRegister &Reg,
1222 unsigned &RegNum, unsigned &RegWidth,
1223 bool RestoreOnFailure = false);
1224 bool ParseAMDGPURegister(RegisterKind &RegKind, MCRegister &Reg,
1225 unsigned &RegNum, unsigned &RegWidth,
1226 SmallVectorImpl<AsmToken> &Tokens);
1227 MCRegister ParseRegularReg(RegisterKind &RegKind, unsigned &RegNum,
1228 unsigned &RegWidth,
1229 SmallVectorImpl<AsmToken> &Tokens);
1230 MCRegister ParseSpecialReg(RegisterKind &RegKind, unsigned &RegNum,
1231 unsigned &RegWidth,
1232 SmallVectorImpl<AsmToken> &Tokens);
1233 MCRegister ParseRegList(RegisterKind &RegKind, unsigned &RegNum,
1234 unsigned &RegWidth,
1235 SmallVectorImpl<AsmToken> &Tokens);
1236 bool ParseRegRange(unsigned &Num, unsigned &Width, unsigned &SubReg);
1237 MCRegister getRegularReg(RegisterKind RegKind, unsigned RegNum,
1238 unsigned SubReg, unsigned RegWidth, SMLoc Loc);
1239
1240 bool isRegister();
1241 bool isRegister(const AsmToken &Token, const AsmToken &NextToken) const;
1242 std::optional<StringRef> getGprCountSymbolName(RegisterKind RegKind);
1243 void initializeGprCountSymbol(RegisterKind RegKind);
1244 bool updateGprCountSymbols(RegisterKind RegKind, unsigned DwordRegIndex,
1245 unsigned RegWidth);
1246 void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands, bool IsAtomic);
1247
1248public:
1249 enum OperandMode {
1250 OperandMode_Default,
1251 OperandMode_NSA,
1252 };
1253
1254 using OptionalImmIndexMap = std::map<AMDGPUOperand::ImmTy, unsigned>;
1255
1256 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
1257 const MCInstrInfo &MII)
1258 : MCTargetAsmParser(STI, MII), Parser(_Parser),
1259 HwMode(STI.getHwMode(MCSubtargetInfo::HwMode_RegInfo)),
1260 Gfx(AMDGPU::parseArchAMDGCN(STI.getCPU())),
1261 ISA(AMDGPU::getIsaVersion(STI.getCPU())) {
1263
1264 setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits()));
1265
1266 if (ISA.Major >= 6 && isHsaAbi(getSTI())) {
1267 createConstantSymbol(".amdgcn.gfx_generation_number", ISA.Major);
1268 createConstantSymbol(".amdgcn.gfx_generation_minor", ISA.Minor);
1269 createConstantSymbol(".amdgcn.gfx_generation_stepping", ISA.Stepping);
1270 } else {
1271 createConstantSymbol(".option.machine_version_major", ISA.Major);
1272 createConstantSymbol(".option.machine_version_minor", ISA.Minor);
1273 createConstantSymbol(".option.machine_version_stepping", ISA.Stepping);
1274 }
1275 if (ISA.Major >= 6 && isHsaAbi(getSTI())) {
1276 initializeGprCountSymbol(IS_VGPR);
1277 initializeGprCountSymbol(IS_SGPR);
1278 } else
1279 KernelScope.initialize(getContext());
1280
1281 for (auto [Symbol, Code] : AMDGPU::UCVersion::getGFXVersions())
1282 createConstantSymbol(Symbol, Code);
1283
1284 createConstantSymbol("UC_VERSION_W64_BIT", 0x2000);
1285 createConstantSymbol("UC_VERSION_W32_BIT", 0x4000);
1286 createConstantSymbol("UC_VERSION_MDP_BIT", 0x8000);
1287 }
1288
1289 bool hasMIMG_R128() const { return AMDGPU::hasMIMG_R128(getSTI()); }
1290
1291 bool hasPackedD16() const { return AMDGPU::hasPackedD16(getSTI()); }
1292
1293 bool hasA16() const { return AMDGPU::hasA16(getSTI()); }
1294
1295 bool hasG16() const { return AMDGPU::hasG16(getSTI()); }
1296
1297 bool hasGDS() const { return AMDGPU::hasGDS(getSTI()); }
1298
1299 bool isSI() const { return AMDGPU::isSI(getSTI()); }
1300
1301 bool isCI() const { return AMDGPU::isCI(getSTI()); }
1302
1303 bool isVI() const { return AMDGPU::isVI(getSTI()); }
1304
1305 bool isGFX9() const { return AMDGPU::isGFX9(getSTI()); }
1306
1307 // TODO: isGFX90A is also true for GFX940. We need to clean it.
1308 bool isGFX90A() const { return AMDGPU::isGFX90A(getSTI()); }
1309
1310 bool isGFX940() const { return AMDGPU::isGFX940(getSTI()); }
1311
1312 bool isGFX9Plus() const { return AMDGPU::isGFX9Plus(getSTI()); }
1313
1314 bool isGFX10Plus() const { return AMDGPU::isGFX10Plus(getSTI()); }
1315
1316 bool isGFX11() const { return AMDGPU::isGFX11(getSTI()); }
1317
1318 bool isGFX11Plus() const { return AMDGPU::isGFX11Plus(getSTI()); }
1319
1320 bool isGFX12() const { return AMDGPU::isGFX12(getSTI()); }
1321
1322 bool isGFX12Plus() const { return AMDGPU::isGFX12Plus(getSTI()); }
1323
1324 bool isGFX1250Plus() const { return AMDGPU::isGFX1250Plus(getSTI()); }
1325
1326 bool hasBVHRayTracingInsts() const {
1327 return getFeatureBits()[AMDGPU::FeatureBVHRayTracingInsts];
1328 }
1329
1330 bool isWave32() const { return getAvailableFeatures()[Feature_isWave32Bit]; }
1331
1332 bool isWave64() const { return getAvailableFeatures()[Feature_isWave64Bit]; }
1333
1334 bool hasInv2PiInlineImm() const {
1335 return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm];
1336 }
1337
1338 bool has64BitLiterals() const {
1339 return getFeatureBits()[AMDGPU::Feature64BitLiterals];
1340 }
1341
1342 bool hasFlatOffsets() const {
1343 return getFeatureBits()[AMDGPU::FeatureFlatInstOffsets];
1344 }
1345
1346 bool hasTrue16Insts() const {
1347 return getFeatureBits()[AMDGPU::FeatureTrue16BitInsts];
1348 }
1349
1350 bool hasArchitectedFlatScratch() const {
1351 return getFeatureBits()[AMDGPU::FeatureArchitectedFlatScratch];
1352 }
1353
1354 bool hasSGPR102_SGPR103() const { return !isVI() && !isGFX9(); }
1355
1356 bool hasSGPR104_SGPR105() const { return isGFX10Plus(); }
1357
1358 bool hasIntClamp() const { return getFeatureBits()[AMDGPU::FeatureIntClamp]; }
1359
1360 bool hasPartialNSAEncoding() const {
1361 return getFeatureBits()[AMDGPU::FeaturePartialNSAEncoding];
1362 }
1363
1364 bool hasGloballyAddressableScratch() const {
1365 return getFeatureBits()[AMDGPU::FeatureGloballyAddressableScratch];
1366 }
1367
1368 bool hasCacheFillSize() const {
1369 return getFeatureBits()[AMDGPU::FeatureCacheFillSize];
1370 }
1371
1372 unsigned getNSAMaxSize(bool HasSampler = false) const {
1373 return AMDGPU::getNSAMaxSize(getSTI(), HasSampler);
1374 }
1375
1376 unsigned getMaxNumUserSGPRs() const {
1377 return AMDGPU::getMaxNumUserSGPRs(getSTI());
1378 }
1379
1380 bool hasKernargPreload() const { return AMDGPU::hasKernargPreload(getSTI()); }
1381
1382 AMDGPUTargetStreamer &getTargetStreamer() {
1383 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
1384 return static_cast<AMDGPUTargetStreamer &>(TS);
1385 }
1386
1387 MCContext &getContext() const {
1388 // We need this const_cast because for some reason getContext() is not const
1389 // in MCAsmParser.
1390 return const_cast<AMDGPUAsmParser *>(this)->MCTargetAsmParser::getContext();
1391 }
1392
1393 const MCRegisterInfo *getMRI() const {
1394 return getContext().getRegisterInfo();
1395 }
1396
1397 const MCInstrInfo *getMII() const { return &MII; }
1398
1399 // Resolve a RegClassByHwModeUses index to a register class id for the active
1400 // HwMode; -1 if the mode has no entry.
1401 int16_t getTargetRegClass(unsigned TargetRCIdx) const {
1402 return MII.getRegClassByHwModeTable(HwMode)[TargetRCIdx];
1403 }
1404
1405 // FIXME: This should not be used. Instead, should use queries derived from
1406 // getAvailableFeatures().
1407 const FeatureBitset &getFeatureBits() const {
1408 return getSTI().getFeatureBits();
1409 }
1410
1411 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
1412 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
1413 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
1414
1415 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
1416 bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
1417 bool isForcedDPP() const { return ForcedDPP; }
1418 bool isForcedSDWA() const { return ForcedSDWA; }
1419 ArrayRef<unsigned> getMatchedVariants() const;
1420 StringRef getMatchedVariantName() const;
1421
1422 std::unique_ptr<AMDGPUOperand> parseRegister(bool RestoreOnFailure = false);
1423 bool ParseRegister(MCRegister &RegNo, SMLoc &StartLoc, SMLoc &EndLoc,
1424 bool RestoreOnFailure);
1425 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
1426 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1427 SMLoc &EndLoc) override;
1428 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
1429 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
1430 unsigned Kind) override;
1431 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1432 OperandVector &Operands, MCStreamer &Out,
1433 uint64_t &ErrorInfo,
1434 bool MatchingInlineAsm) override;
1435 bool ParseDirective(AsmToken DirectiveID) override;
1436 void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) override;
1437 void onEndOfFile() override;
1438 ParseStatus parseOperand(OperandVector &Operands, StringRef Mnemonic,
1439 OperandMode Mode = OperandMode_Default);
1440 StringRef parseMnemonicSuffix(StringRef Name);
1441 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
1442 SMLoc NameLoc, OperandVector &Operands) override;
1443 // bool ProcessInstruction(MCInst &Inst);
1444
1445 ParseStatus parseTokenOp(StringRef Name, OperandVector &Operands);
1446
1447 ParseStatus parseIntWithPrefix(const char *Prefix, int64_t &Int);
1448
1449 ParseStatus
1450 parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
1451 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1452 std::function<bool(int64_t &)> ConvertResult = nullptr);
1453
1454 ParseStatus parseOperandArrayWithPrefix(
1455 const char *Prefix, OperandVector &Operands,
1456 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1457 bool (*ConvertResult)(int64_t &) = nullptr);
1458
1459 ParseStatus
1460 parseNamedBit(StringRef Name, OperandVector &Operands,
1461 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1462 bool IgnoreNegative = false);
1463 unsigned getCPolKind(StringRef Id, StringRef Mnemo, bool &Disabling) const;
1464 ParseStatus parseCPol(OperandVector &Operands);
1465 ParseStatus parseScope(OperandVector &Operands, int64_t &Scope);
1466 ParseStatus parseTH(OperandVector &Operands, int64_t &TH);
1467 ParseStatus parseCFS(OperandVector &Operands, int64_t &CFS);
1468 ParseStatus parseStringWithPrefix(StringRef Prefix, StringRef &Value,
1469 SMLoc &StringLoc);
1470 ParseStatus parseStringOrIntWithPrefix(OperandVector &Operands,
1471 StringRef Name,
1472 ArrayRef<const char *> Ids,
1473 int64_t &IntVal);
1474 ParseStatus parseStringOrIntWithPrefix(OperandVector &Operands,
1475 StringRef Name,
1476 ArrayRef<const char *> Ids,
1477 AMDGPUOperand::ImmTy Type);
1478
1479 bool isModifier();
1480 bool isOperandModifier(const AsmToken &Token,
1481 const AsmToken &NextToken) const;
1482 bool isRegOrOperandModifier(const AsmToken &Token,
1483 const AsmToken &NextToken) const;
1484 bool isNamedOperandModifier(const AsmToken &Token,
1485 const AsmToken &NextToken) const;
1486 bool isOpcodeModifierWithVal(const AsmToken &Token,
1487 const AsmToken &NextToken) const;
1488 bool parseSP3NegModifier();
1489 ParseStatus parseImm(OperandVector &Operands, bool HasSP3AbsModifier = false,
1490 LitModifier Lit = LitModifier::None);
1491 ParseStatus parseReg(OperandVector &Operands);
1492 ParseStatus parseRegOrImm(OperandVector &Operands, bool HasSP3AbsMod = false,
1493 LitModifier Lit = LitModifier::None);
1494 ParseStatus parseRegOrImmWithFPInputMods(OperandVector &Operands,
1495 bool AllowImm = true);
1496 ParseStatus parseRegOrImmWithIntInputMods(OperandVector &Operands,
1497 bool AllowImm = true);
1498 ParseStatus parseRegWithFPInputMods(OperandVector &Operands);
1499 ParseStatus parseRegWithIntInputMods(OperandVector &Operands);
1500 ParseStatus parseRsrcReg(OperandVector &Operands);
1501 ParseStatus parseVReg32OrOff(OperandVector &Operands);
1502 ParseStatus tryParseIndexKey(OperandVector &Operands,
1503 AMDGPUOperand::ImmTy ImmTy);
1504 ParseStatus parseIndexKey8bit(OperandVector &Operands);
1505 ParseStatus parseIndexKey16bit(OperandVector &Operands);
1506 ParseStatus parseIndexKey32bit(OperandVector &Operands);
1507 ParseStatus tryParseMatrixFMT(OperandVector &Operands, StringRef Name,
1508 AMDGPUOperand::ImmTy Type);
1509 ParseStatus parseMatrixAFMT(OperandVector &Operands);
1510 ParseStatus parseMatrixBFMT(OperandVector &Operands);
1511 ParseStatus tryParseMatrixScale(OperandVector &Operands, StringRef Name,
1512 AMDGPUOperand::ImmTy Type);
1513 ParseStatus parseMatrixAScale(OperandVector &Operands);
1514 ParseStatus parseMatrixBScale(OperandVector &Operands);
1515 ParseStatus tryParseMatrixScaleFmt(OperandVector &Operands, StringRef Name,
1516 AMDGPUOperand::ImmTy Type);
1517 ParseStatus parseMatrixAScaleFmt(OperandVector &Operands);
1518 ParseStatus parseMatrixBScaleFmt(OperandVector &Operands);
1519
1520 ParseStatus parseDfmtNfmt(int64_t &Format);
1521 ParseStatus parseUfmt(int64_t &Format);
1522 ParseStatus parseSymbolicSplitFormat(StringRef FormatStr, SMLoc Loc,
1523 int64_t &Format);
1524 ParseStatus parseSymbolicUnifiedFormat(StringRef FormatStr, SMLoc Loc,
1525 int64_t &Format);
1526 ParseStatus parseFORMAT(OperandVector &Operands);
1527 ParseStatus parseSymbolicOrNumericFormat(int64_t &Format);
1528 ParseStatus parseNumericFormat(int64_t &Format);
1529 ParseStatus parseFlatOffset(OperandVector &Operands);
1530 ParseStatus parseR128A16(OperandVector &Operands);
1531 ParseStatus parseBLGP(OperandVector &Operands);
1532 bool tryParseFmt(const char *Pref, int64_t MaxVal, int64_t &Val);
1533 bool matchDfmtNfmt(int64_t &Dfmt, int64_t &Nfmt, StringRef FormatStr,
1534 SMLoc Loc);
1535
1536 void cvtExp(MCInst &Inst, const OperandVector &Operands);
1537
1538 bool parseCnt(int64_t &IntVal);
1539 ParseStatus parseSWaitCnt(OperandVector &Operands);
1540
1541 bool parseDepCtr(int64_t &IntVal, unsigned &Mask);
1542 void depCtrError(SMLoc Loc, int ErrorId, StringRef DepCtrName);
1543 ParseStatus parseDepCtr(OperandVector &Operands);
1544
1545 bool parseDelay(int64_t &Delay);
1546 ParseStatus parseSDelayALU(OperandVector &Operands);
1547
1548 ParseStatus parseHwreg(OperandVector &Operands);
1549
1550private:
1551 struct OperandInfoTy {
1552 SMLoc Loc;
1553 int64_t Val;
1554 bool IsSymbolic = false;
1555 bool IsDefined = false;
1556
1557 constexpr OperandInfoTy(int64_t Val) : Val(Val) {}
1558 };
1559
1560 struct StructuredOpField : OperandInfoTy {
1561 StringLiteral Id;
1562 StringLiteral Desc;
1563 unsigned Width;
1564 bool IsDefined = false;
1565
1566 constexpr StructuredOpField(StringLiteral Id, StringLiteral Desc,
1567 unsigned Width, int64_t Default)
1568 : OperandInfoTy(Default), Id(Id), Desc(Desc), Width(Width) {}
1569 virtual ~StructuredOpField() = default;
1570
1571 bool Error(AMDGPUAsmParser &Parser, const Twine &Err) const {
1572 Parser.Error(Loc, "invalid " + Desc + ": " + Err);
1573 return false;
1574 }
1575
1576 virtual bool validate(AMDGPUAsmParser &Parser) const {
1577 if (IsSymbolic && Val == OPR_ID_UNSUPPORTED)
1578 return Error(Parser, "not supported on this GPU");
1579 if (!isUIntN(Width, Val))
1580 return Error(Parser, "only " + Twine(Width) + "-bit values are legal");
1581 return true;
1582 }
1583 };
1584
1585 ParseStatus parseStructuredOpFields(ArrayRef<StructuredOpField *> Fields);
1586 bool validateStructuredOpFields(ArrayRef<const StructuredOpField *> Fields);
1587
1588 bool parseSendMsgBody(OperandInfoTy &Msg, OperandInfoTy &Op,
1589 OperandInfoTy &Stream);
1590 bool validateSendMsg(const OperandInfoTy &Msg, const OperandInfoTy &Op,
1591 const OperandInfoTy &Stream);
1592
1593 ParseStatus parseHwregFunc(OperandInfoTy &HwReg, OperandInfoTy &Offset,
1594 OperandInfoTy &Width);
1595
1596 const AMDGPUOperand &findMCOperand(const OperandVector &Operands,
1597 int MCOpIdx) const;
1598
1599 static SMLoc getLaterLoc(SMLoc a, SMLoc b);
1600
1601 SMLoc getFlatOffsetLoc(const OperandVector &Operands) const;
1602 SMLoc getSMEMOffsetLoc(const OperandVector &Operands) const;
1603 SMLoc getBLGPLoc(const OperandVector &Operands) const;
1604
1605 SMLoc getOperandLoc(const OperandVector &Operands, int MCOpIdx) const;
1606 SMLoc getOperandLoc(std::function<bool(const AMDGPUOperand &)> Test,
1607 const OperandVector &Operands) const;
1608 SMLoc getImmLoc(AMDGPUOperand::ImmTy Type,
1609 const OperandVector &Operands) const;
1610 SMLoc getInstLoc(const OperandVector &Operands) const;
1611
1612 bool validateInstruction(const MCInst &Inst, SMLoc IDLoc,
1613 const OperandVector &Operands);
1614 bool validateOffset(const MCInst &Inst, const OperandVector &Operands);
1615 bool validateFlatOffset(const MCInst &Inst, const OperandVector &Operands);
1616 bool validateSMEMOffset(const MCInst &Inst, const OperandVector &Operands);
1617 bool validateBF16InlineConst(const MCInst &Inst,
1618 const OperandVector &Operands);
1619 bool validateSOPLiteral(const MCInst &Inst, const OperandVector &Operands);
1620 bool validateConstantBusLimitations(const MCInst &Inst,
1621 const OperandVector &Operands);
1622 std::optional<unsigned> checkVOPDRegBankConstraints(const MCInst &Inst,
1623 bool AsVOPD3);
1624 bool validateVOPD(const MCInst &Inst, const OperandVector &Operands);
1625 bool tryVOPD(const MCInst &Inst);
1626 bool tryVOPD3(const MCInst &Inst);
1627 bool tryAnotherVOPDEncoding(const MCInst &Inst);
1628
1629 bool validateIntClampSupported(const MCInst &Inst);
1630 bool validateMIMGAtomicDMask(const MCInst &Inst);
1631 bool validateMIMGGatherDMask(const MCInst &Inst);
1632 bool validateMovrels(const MCInst &Inst, const OperandVector &Operands);
1633 bool validateMIMGDataSize(const MCInst &Inst, SMLoc IDLoc);
1634 bool validateMIMGAddrSize(const MCInst &Inst, SMLoc IDLoc);
1635 bool validateMIMGD16(const MCInst &Inst);
1636 bool validateMIMGDim(const MCInst &Inst, const OperandVector &Operands);
1637 bool validateTensorR128(const MCInst &Inst);
1638 bool validateMIMGMSAA(const MCInst &Inst);
1639 bool validateOpSel(const MCInst &Inst);
1640 bool validateTrue16OpSel(const MCInst &Inst);
1641 bool validateNeg(const MCInst &Inst, AMDGPU::OpName OpName);
1642 bool validateDPP(const MCInst &Inst, const OperandVector &Operands);
1643 bool validateVccOperand(MCRegister Reg) const;
1644 bool validateVOPLiteral(const MCInst &Inst, const OperandVector &Operands);
1645 bool validateMAIAccWrite(const MCInst &Inst, const OperandVector &Operands);
1646 bool validateMAISrc2(const MCInst &Inst, const OperandVector &Operands);
1647 bool validateMFMA(const MCInst &Inst, const OperandVector &Operands);
1648 bool validateAGPRLdSt(const MCInst &Inst) const;
1649 bool validateVGPRAlign(const MCInst &Inst) const;
1650 bool validateBLGP(const MCInst &Inst, const OperandVector &Operands);
1651 bool validateDS(const MCInst &Inst, const OperandVector &Operands);
1652 bool validateGWS(const MCInst &Inst, const OperandVector &Operands);
1653 bool validateDivScale(const MCInst &Inst);
1654 bool validateWaitCnt(const MCInst &Inst, const OperandVector &Operands);
1655 bool validateCoherencyBits(const MCInst &Inst, const OperandVector &Operands,
1656 SMLoc IDLoc);
1657 bool validateTHAndScopeBits(const MCInst &Inst, const OperandVector &Operands,
1658 const unsigned CPol);
1659 bool validateCFSBits(const MCInst &Inst, const OperandVector &Operands);
1660 bool validateTFE(const MCInst &Inst, const OperandVector &Operands);
1661 bool validateLdsDirect(const MCInst &Inst, const OperandVector &Operands);
1662 bool validateWMMA(const MCInst &Inst, const OperandVector &Operands);
1663 bool validateMonitorSleep(const MCInst &Inst, const OperandVector &Operands);
1664 bool validateClusterBarrierIsFirst(const MCInst &Inst,
1665 const OperandVector &Operands);
1666 bool validateScaleSel(const MCInst &Inst, const OperandVector &Operands);
1667 unsigned getConstantBusLimit(unsigned Opcode) const;
1668 bool usesConstantBus(const MCInst &Inst, unsigned OpIdx);
1669 bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
1670 MCRegister findImplicitSGPRReadInVOP(const MCInst &Inst) const;
1671
1672 bool isSupportedMnemo(StringRef Mnemo, const FeatureBitset &FBS);
1673 bool isSupportedMnemo(StringRef Mnemo, const FeatureBitset &FBS,
1674 ArrayRef<unsigned> Variants);
1675 bool checkUnsupportedInstruction(StringRef Name, SMLoc IDLoc);
1676
1677 bool isId(const StringRef Id) const;
1678 bool isId(const AsmToken &Token, const StringRef Id) const;
1679 bool isToken(const AsmToken::TokenKind Kind) const;
1680 StringRef getId() const;
1681 bool trySkipId(const StringRef Id);
1682 bool trySkipId(const StringRef Pref, const StringRef Id);
1683 bool trySkipId(const StringRef Id, const AsmToken::TokenKind Kind);
1684 bool trySkipToken(const AsmToken::TokenKind Kind);
1685 bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg);
1686 bool parseString(StringRef &Val,
1687 const StringRef ErrMsg = "expected a string");
1688 bool parseId(StringRef &Val, const StringRef ErrMsg = "");
1689
1690 void peekTokens(MutableArrayRef<AsmToken> Tokens);
1691 AsmToken::TokenKind getTokenKind() const;
1692 bool parseExpr(int64_t &Imm, StringRef Expected = "");
1694 StringRef getTokenStr() const;
1695 AsmToken peekToken(bool ShouldSkipSpace = true);
1696 AsmToken getToken() const;
1697 SMLoc getLoc() const;
1698 void lex();
1699
1700public:
1701 void onBeginOfFile() override;
1702 /// Emit the deferred leading .amdgcn_target directive if it has not been
1703 /// emitted yet. Called before emitting the first instruction or kernel
1704 /// descriptor, so that any leading .amdgcn_target/.amd_amdgpu_isa directive
1705 /// in the source has had a chance to update the target ID first.
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 (CPol & CPol::CFS) {
5323 if (!hasCacheFillSize()) {
5324 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands);
5325 StringRef CStr(S.getPointer());
5326 S = SMLoc::getFromPointer(&CStr.data()[CStr.find("cfs")]);
5327 Error(S, "Cache fill size is not supported on this GPU");
5328 } else if (!validateCFSBits(Inst, Operands)) {
5329 return false;
5330 }
5331 }
5332
5333 if (!isGFX1250Plus()) {
5334 if (CPol & CPol::SCAL) {
5335 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands);
5336 StringRef CStr(S.getPointer());
5337 S = SMLoc::getFromPointer(&CStr.data()[CStr.find("scale_offset")]);
5338 Error(S, "scale_offset is not supported on this GPU");
5339 }
5340 if (CPol & CPol::NV) {
5341 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands);
5342 StringRef CStr(S.getPointer());
5343 S = SMLoc::getFromPointer(&CStr.data()[CStr.find("nv")]);
5344 Error(S, "nv is not supported on this GPU");
5345 }
5346 }
5347
5348 if ((CPol & CPol::SCAL) && !supportsScaleOffset(MII, Inst.getOpcode())) {
5349 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands);
5350 StringRef CStr(S.getPointer());
5351 S = SMLoc::getFromPointer(&CStr.data()[CStr.find("scale_offset")]);
5352 Error(S, "scale_offset is not supported for this instruction");
5353 }
5354
5355 if (isGFX12Plus())
5356 return validateTHAndScopeBits(Inst, Operands, CPol);
5357
5358 if (SIInstrFlags::isSMRD(MII, Inst)) {
5359 if (CPol && (isSI() || isCI())) {
5360 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands);
5361 Error(S, "cache policy is not supported for SMRD instructions");
5362 return false;
5363 }
5364 if (CPol & ~(AMDGPU::CPol::GLC | AMDGPU::CPol::DLC)) {
5365 Error(IDLoc, "invalid cache policy for SMEM instruction");
5366 return false;
5367 }
5368 }
5369
5370 if (isGFX90A() && !isGFX940() && (CPol & CPol::SCC)) {
5371 if (!SIInstrFlags::isVMEM(MII, Inst)) {
5372 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands);
5373 StringRef CStr(S.getPointer());
5374 S = SMLoc::getFromPointer(&CStr.data()[CStr.find("scc")]);
5375 Error(S,
5376 "scc modifier is not supported for this instruction on this GPU");
5377 return false;
5378 }
5379 }
5380
5381 if (!SIInstrFlags::isAtomic(MII, Inst))
5382 return true;
5383
5384 if (SIInstrFlags::isAtomicRet(MII, Inst)) {
5385 if (!SIInstrFlags::isMIMG(MII, Inst) && !(CPol & CPol::GLC)) {
5386 Error(IDLoc, isGFX940() ? "instruction must use sc0"
5387 : "instruction must use glc");
5388 return false;
5389 }
5390 } else {
5391 if (CPol & CPol::GLC) {
5392 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands);
5393 StringRef CStr(S.getPointer());
5395 &CStr.data()[CStr.find(isGFX940() ? "sc0" : "glc")]);
5396 Error(S, isGFX940() ? "instruction must not use sc0"
5397 : "instruction must not use glc");
5398 return false;
5399 }
5400 }
5401
5402 return true;
5403}
5404
5405bool AMDGPUAsmParser::validateTHAndScopeBits(const MCInst &Inst,
5406 const OperandVector &Operands,
5407 const unsigned CPol) {
5408 const unsigned TH = CPol & AMDGPU::CPol::TH;
5409 const unsigned Scope = CPol & AMDGPU::CPol::SCOPE;
5410
5411 auto PrintError = [&](StringRef Msg) {
5412 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands);
5413 Error(S, Msg);
5414 return false;
5415 };
5416
5417 if ((TH & AMDGPU::CPol::TH_ATOMIC_RETURN) &&
5418 SIInstrFlags::isAtomicNoRet(MII, Inst))
5419 return PrintError("th:TH_ATOMIC_RETURN requires a destination operand");
5420
5421 if (SIInstrFlags::isAtomicRet(MII, Inst) &&
5422 (SIInstrFlags::isFLAT(MII, Inst) || SIInstrFlags::isMUBUF(MII, Inst)) &&
5424 return PrintError("instruction must use th:TH_ATOMIC_RETURN");
5425
5426 if (TH == 0)
5427 return true;
5428
5429 if (SIInstrFlags::isSMRD(MII, Inst) &&
5430 ((TH == AMDGPU::CPol::TH_NT_RT) || (TH == AMDGPU::CPol::TH_RT_NT) ||
5431 (TH == AMDGPU::CPol::TH_NT_HT)))
5432 return PrintError("invalid th value for SMEM instruction");
5433
5434 if (TH == AMDGPU::CPol::TH_BYPASS) {
5435 if ((Scope != AMDGPU::CPol::SCOPE_SYS &&
5437 (Scope == AMDGPU::CPol::SCOPE_SYS &&
5439 return PrintError("scope and th combination is not valid");
5440 }
5441
5442 unsigned THType = AMDGPU::getTemporalHintType(MII.get(Inst.getOpcode()));
5443 if (THType == AMDGPU::CPol::TH_TYPE_ATOMIC) {
5444 if (!(CPol & AMDGPU::CPol::TH_TYPE_ATOMIC))
5445 return PrintError("invalid th value for atomic instructions");
5446 } else if (THType == AMDGPU::CPol::TH_TYPE_STORE) {
5447 if (!(CPol & AMDGPU::CPol::TH_TYPE_STORE))
5448 return PrintError("invalid th value for store instructions");
5449 } else {
5450 if (!(CPol & AMDGPU::CPol::TH_TYPE_LOAD))
5451 return PrintError("invalid th value for load instructions");
5452 }
5453
5454 return true;
5455}
5456
5457bool AMDGPUAsmParser::validateCFSBits(const MCInst &Inst,
5458 const OperandVector &Operands) {
5459 const unsigned Opcode = Inst.getOpcode();
5460 const MCInstrDesc &Desc = MII.get(Opcode);
5461
5462 auto PrintError = [&](StringRef Msg) {
5463 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands);
5464 Error(S, Msg);
5465 return false;
5466 };
5467
5469 return true;
5470
5471 return PrintError("Cache fill size is only supported for VC operations");
5472}
5473
5474bool AMDGPUAsmParser::validateTFE(const MCInst &Inst,
5475 const OperandVector &Operands) {
5476 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
5477 if (Desc.mayStore() && SIInstrFlags::isBuffer(Desc)) {
5478 SMLoc Loc = getImmLoc(AMDGPUOperand::ImmTyTFE, Operands);
5479 if (Loc != getInstLoc(Operands)) {
5480 Error(Loc, "TFE modifier has no meaning for store instructions");
5481 return false;
5482 }
5483 }
5484
5485 return true;
5486}
5487
5488bool AMDGPUAsmParser::validateWMMA(const MCInst &Inst,
5489 const OperandVector &Operands) {
5490 unsigned Opc = Inst.getOpcode();
5491 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
5492 const MCInstrDesc &Desc = MII.get(Opc);
5493
5494 int AFmtIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_a_fmt);
5495 if (AFmtIdx == -1)
5496 return true;
5497 unsigned AFmt = Inst.getOperand(AFmtIdx).getImm();
5498 int BFmtIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_b_fmt);
5499 unsigned BFmt = Inst.getOperand(BFmtIdx).getImm();
5500
5501 auto validateFmt = [&](unsigned Fmt, AMDGPU::OpName SrcOp) -> bool {
5502 int SrcIdx = AMDGPU::getNamedOperandIdx(Opc, SrcOp);
5503 unsigned RegSize =
5504 TRI->getRegClass(MII.getOpRegClassID(Desc.operands()[SrcIdx], HwMode))
5505 .getSizeInBits();
5506
5508 return true;
5509
5510 Error(getOperandLoc(Operands, SrcIdx),
5511 "wrong register tuple size for " +
5512 Twine(WMMAMods::ModMatrixFmt[Fmt]));
5513 return false;
5514 };
5515
5516 if (!validateFmt(AFmt, AMDGPU::OpName::src0) ||
5517 !validateFmt(BFmt, AMDGPU::OpName::src1))
5518 return false;
5519
5520 int AScaleIdx =
5521 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_a_scale_fmt);
5522 if (AScaleIdx == -1)
5523 return true;
5524 unsigned AScale = Inst.getOperand(AScaleIdx).getImm();
5525 int BScaleIdx =
5526 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_b_scale_fmt);
5527 unsigned BScale = Inst.getOperand(BScaleIdx).getImm();
5528 if (!isValidWMMAScaleFmtCombination(AFmt, AScale, BFmt, BScale)) {
5529 Error(getImmLoc(AMDGPUOperand::ImmTyMatrixAFMT, Operands),
5530 "invalid matrix and scale format combination");
5531 return false;
5532 }
5533
5534 return true;
5535}
5536
5537bool AMDGPUAsmParser::validateMonitorSleep(const MCInst &Inst,
5538 const OperandVector &Operands) {
5539 unsigned Opc = Inst.getOpcode();
5540 if (Opc != AMDGPU::S_MONITOR_SLEEP_gfx12 ||
5541 !getSTI().hasFeature(AMDGPU::FeatureNoSleepForever))
5542 return true;
5543
5544 int ImmIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::simm16);
5545 if (Inst.getOperand(ImmIdx).getImm() & 0x8000) {
5546 Error(getOperandLoc(Operands, ImmIdx),
5547 "sleep forever is unsuported on the target");
5548 return false;
5549 }
5550
5551 return true;
5552}
5553
5554bool AMDGPUAsmParser::validateClusterBarrierIsFirst(
5555 const MCInst &Inst, const OperandVector &Operands) {
5556 unsigned Opc = Inst.getOpcode();
5557 if (Opc != AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM_gfx12 &&
5558 Opc != AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM_gfx13)
5559 return true;
5560
5561 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
5562 int BarrierID = Inst.getOperand(Src0Idx).getImm();
5563 if (BarrierID != AMDGPU::Barrier::CLUSTER)
5564 return true;
5565
5566 Error(
5567 getOperandLoc(Operands, Src0Idx),
5568 "s_barrier_signal_isfirst does not support user_cluster_barrier_id (-3)");
5569 return false;
5570}
5571
5572bool AMDGPUAsmParser::validateScaleSel(const MCInst &Inst,
5573 const OperandVector &Operands) {
5574 unsigned Opc = Inst.getOpcode();
5575 int ScaleSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::scale_sel);
5576 if (ScaleSelIdx == -1)
5577 return true;
5578 int MaxSel = 0;
5579 switch (Opc) {
5580 case AMDGPU::V_CVT_SCALE_PK16_F16_FP6_e64_gfx1250:
5581 case AMDGPU::V_CVT_SCALE_PK16_BF16_FP6_e64_gfx1250:
5582 case AMDGPU::V_CVT_SCALE_PK16_F16_BF6_e64_gfx1250:
5583 case AMDGPU::V_CVT_SCALE_PK16_BF16_BF6_e64_gfx1250:
5584 case AMDGPU::V_CVT_SCALE_PK16_F32_FP6_e64_gfx1250:
5585 case AMDGPU::V_CVT_SCALE_PK16_F32_BF6_e64_gfx1250:
5586 case AMDGPU::V_CVT_SCALE_PK8_F16_FP4_e64_gfx1250:
5587 case AMDGPU::V_CVT_SCALE_PK8_BF16_FP4_e64_gfx1250:
5588 case AMDGPU::V_CVT_SCALE_PK8_F32_FP4_e64_gfx1250:
5589 MaxSel = 4;
5590 break;
5591 case AMDGPU::V_CVT_SCALE_PK8_F16_FP8_e64_gfx1250:
5592 case AMDGPU::V_CVT_SCALE_PK8_BF16_FP8_e64_gfx1250:
5593 case AMDGPU::V_CVT_SCALE_PK8_F16_BF8_e64_gfx1250:
5594 case AMDGPU::V_CVT_SCALE_PK8_BF16_BF8_e64_gfx1250:
5595 case AMDGPU::V_CVT_SCALE_PK8_F32_FP8_e64_gfx1250:
5596 case AMDGPU::V_CVT_SCALE_PK8_F32_BF8_e64_gfx1250:
5597 MaxSel = 8;
5598 break;
5599 default:
5600 return true;
5601 }
5602
5603 if (getSTI().hasFeature(AMDGPU::FeatureBlock16ConversionScaleInsts))
5604 MaxSel *= 2;
5605
5606 int ScaleSel = Inst.getOperand(ScaleSelIdx).getImm();
5607 if (ScaleSel < MaxSel)
5608 return true;
5609
5610 Error(getOperandLoc(Operands, ScaleSelIdx),
5611 "scale_sel maximum supported value is " + Twine(MaxSel - 1));
5612 return false;
5613}
5614
5615bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst, SMLoc IDLoc,
5616 const OperandVector &Operands) {
5617 if (!validateLdsDirect(Inst, Operands))
5618 return false;
5619 if (!validateTrue16OpSel(Inst)) {
5620 Error(getImmLoc(AMDGPUOperand::ImmTyOpSel, Operands),
5621 "op_sel operand conflicts with 16-bit operand suffix");
5622 return false;
5623 }
5624 if (!validateSOPLiteral(Inst, Operands))
5625 return false;
5626 if (!validateVOPLiteral(Inst, Operands)) {
5627 return false;
5628 }
5629 if (!validateConstantBusLimitations(Inst, Operands)) {
5630 return false;
5631 }
5632 if (!validateVOPD(Inst, Operands)) {
5633 return false;
5634 }
5635 if (!validateIntClampSupported(Inst)) {
5636 Error(getImmLoc(AMDGPUOperand::ImmTyClamp, Operands),
5637 "integer clamping is not supported on this GPU");
5638 return false;
5639 }
5640 if (!validateOpSel(Inst)) {
5641 Error(getImmLoc(AMDGPUOperand::ImmTyOpSel, Operands),
5642 "invalid op_sel operand");
5643 return false;
5644 }
5645 if (!validateNeg(Inst, AMDGPU::OpName::neg_lo)) {
5646 Error(getImmLoc(AMDGPUOperand::ImmTyNegLo, Operands),
5647 "invalid neg_lo operand");
5648 return false;
5649 }
5650 if (!validateNeg(Inst, AMDGPU::OpName::neg_hi)) {
5651 Error(getImmLoc(AMDGPUOperand::ImmTyNegHi, Operands),
5652 "invalid neg_hi operand");
5653 return false;
5654 }
5655 if (!validateDPP(Inst, Operands)) {
5656 return false;
5657 }
5658 // For MUBUF/MTBUF d16 is a part of opcode, so there is nothing to validate.
5659 if (!validateMIMGD16(Inst)) {
5660 Error(getImmLoc(AMDGPUOperand::ImmTyD16, Operands),
5661 "d16 modifier is not supported on this GPU");
5662 return false;
5663 }
5664 if (!validateMIMGDim(Inst, Operands)) {
5665 Error(IDLoc, "missing dim operand");
5666 return false;
5667 }
5668 if (!validateTensorR128(Inst)) {
5669 Error(getImmLoc(AMDGPUOperand::ImmTyD16, Operands),
5670 "instruction must set modifier r128=0");
5671 return false;
5672 }
5673 if (!validateMIMGMSAA(Inst)) {
5674 Error(getImmLoc(AMDGPUOperand::ImmTyDim, Operands),
5675 "invalid dim; must be MSAA type");
5676 return false;
5677 }
5678 if (!validateMIMGDataSize(Inst, IDLoc)) {
5679 return false;
5680 }
5681 if (!validateMIMGAddrSize(Inst, IDLoc))
5682 return false;
5683 if (!validateMIMGAtomicDMask(Inst)) {
5684 Error(getImmLoc(AMDGPUOperand::ImmTyDMask, Operands),
5685 "invalid atomic image dmask");
5686 return false;
5687 }
5688 if (!validateMIMGGatherDMask(Inst)) {
5689 Error(getImmLoc(AMDGPUOperand::ImmTyDMask, Operands),
5690 "invalid image_gather dmask: only one bit must be set");
5691 return false;
5692 }
5693 if (!validateMovrels(Inst, Operands)) {
5694 return false;
5695 }
5696 if (!validateOffset(Inst, Operands)) {
5697 return false;
5698 }
5699 if (!validateBF16InlineConst(Inst, Operands)) {
5700 return false;
5701 }
5702 if (!validateMAIAccWrite(Inst, Operands)) {
5703 return false;
5704 }
5705 if (!validateMAISrc2(Inst, Operands)) {
5706 return false;
5707 }
5708 if (!validateMFMA(Inst, Operands)) {
5709 return false;
5710 }
5711 if (!validateCoherencyBits(Inst, Operands, IDLoc)) {
5712 return false;
5713 }
5714
5715 if (!validateAGPRLdSt(Inst)) {
5716 Error(
5717 IDLoc,
5718 getFeatureBits()[AMDGPU::FeatureGFX90AInsts]
5719 ? "invalid register class: data and dst should be all VGPR or AGPR"
5720 : "invalid register class: agpr loads and stores not supported on "
5721 "this GPU");
5722 return false;
5723 }
5724 if (!validateVGPRAlign(Inst)) {
5725 Error(IDLoc, "invalid register class: vgpr tuples must be 64 bit aligned");
5726 return false;
5727 }
5728 if (!validateDS(Inst, Operands)) {
5729 return false;
5730 }
5731
5732 if (!validateBLGP(Inst, Operands)) {
5733 return false;
5734 }
5735
5736 if (!validateDivScale(Inst)) {
5737 Error(IDLoc, "ABS not allowed in VOP3B instructions");
5738 return false;
5739 }
5740 if (!validateWaitCnt(Inst, Operands)) {
5741 return false;
5742 }
5743 if (!validateTFE(Inst, Operands)) {
5744 return false;
5745 }
5746 if (!validateWMMA(Inst, Operands)) {
5747 return false;
5748 }
5749 if (!validateMonitorSleep(Inst, Operands)) {
5750 return false;
5751 }
5752 if (!validateClusterBarrierIsFirst(Inst, Operands)) {
5753 return false;
5754 }
5755 if (!validateScaleSel(Inst, Operands)) {
5756 return false;
5757 }
5758
5759 return true;
5760}
5761
5763 const FeatureBitset &FBS,
5764 unsigned VariantID = 0);
5765
5766static bool AMDGPUCheckMnemonic(StringRef Mnemonic,
5767 const FeatureBitset &AvailableFeatures,
5768 unsigned VariantID);
5769
5770bool AMDGPUAsmParser::isSupportedMnemo(StringRef Mnemo,
5771 const FeatureBitset &FBS) {
5772 return isSupportedMnemo(Mnemo, FBS, getAllVariants());
5773}
5774
5775bool AMDGPUAsmParser::isSupportedMnemo(StringRef Mnemo,
5776 const FeatureBitset &FBS,
5777 ArrayRef<unsigned> Variants) {
5778 for (auto Variant : Variants) {
5779 if (AMDGPUCheckMnemonic(Mnemo, FBS, Variant))
5780 return true;
5781 }
5782
5783 return false;
5784}
5785
5786bool AMDGPUAsmParser::checkUnsupportedInstruction(StringRef Mnemo,
5787 SMLoc IDLoc) {
5788 FeatureBitset FBS = ComputeAvailableFeatures(getFeatureBits());
5789
5790 // Check if requested instruction variant is supported.
5791 if (isSupportedMnemo(Mnemo, FBS, getMatchedVariants()))
5792 return false;
5793
5794 // This instruction is not supported.
5795 // Clear any other pending errors because they are no longer relevant.
5796 getParser().clearPendingErrors();
5797
5798 // Requested instruction variant is not supported.
5799 // Check if any other variants are supported.
5800 StringRef VariantName = getMatchedVariantName();
5801 if (!VariantName.empty() && isSupportedMnemo(Mnemo, FBS)) {
5802 return Error(IDLoc, Twine(VariantName,
5803 " variant of this instruction is not supported"));
5804 }
5805
5806 // Check if this instruction may be used with a different wavesize.
5807 if (isGFX10Plus() && getFeatureBits()[AMDGPU::FeatureWavefrontSize64] &&
5808 !getFeatureBits()[AMDGPU::FeatureWavefrontSize32]) {
5809 // FIXME: Use getAvailableFeatures, and do not manually recompute
5810 FeatureBitset FeaturesWS32 = getFeatureBits();
5811 FeaturesWS32.flip(AMDGPU::FeatureWavefrontSize64)
5812 .flip(AMDGPU::FeatureWavefrontSize32);
5813 FeatureBitset AvailableFeaturesWS32 =
5814 ComputeAvailableFeatures(FeaturesWS32);
5815
5816 if (isSupportedMnemo(Mnemo, AvailableFeaturesWS32, getMatchedVariants()))
5817 return Error(IDLoc, "instruction requires wavesize=32");
5818 }
5819
5820 // Finally check if this instruction is supported on any other GPU.
5821 if (isSupportedMnemo(Mnemo, FeatureBitset().set())) {
5822 return Error(IDLoc, "instruction not supported on this GPU (" +
5823 getSTI().getCPU() + ")" + ": " + Mnemo);
5824 }
5825
5826 // Instruction not supported on any GPU. Probably a typo.
5827 std::string Suggestion = AMDGPUMnemonicSpellCheck(Mnemo, FBS);
5828 return Error(IDLoc, "invalid instruction" + Suggestion);
5829}
5830
5832 uint64_t InvalidOprIdx) {
5833 assert(InvalidOprIdx < Operands.size());
5834 const auto &Op = ((AMDGPUOperand &)*Operands[InvalidOprIdx]);
5835 if (Op.isToken() && InvalidOprIdx > 1) {
5836 const auto &PrevOp = ((AMDGPUOperand &)*Operands[InvalidOprIdx - 1]);
5837 return PrevOp.isToken() && PrevOp.getToken() == "::";
5838 }
5839 return false;
5840}
5841
5842bool AMDGPUAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5844 MCStreamer &Out,
5845 uint64_t &ErrorInfo,
5846 bool MatchingInlineAsm) {
5847 MCInst Inst;
5848 Inst.setLoc(IDLoc);
5849 unsigned Result = Match_Success;
5850
5851 // Order match statuses from least to most specific and keep the most
5852 // specific one:
5853 // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature
5854 auto atLeastAsSpecific = [](unsigned New, unsigned Cur) {
5855 auto rank = [](unsigned M) {
5856 return M == Match_MnemonicFail ? 1
5857 : M == Match_InvalidOperand ? 2
5858 : M == Match_MissingFeature ? 3
5859 : 0; // Match_Success sentinel
5860 };
5861 return rank(New) >= rank(Cur);
5862 };
5863
5864 for (auto Variant : getMatchedVariants()) {
5865 uint64_t EI;
5866 auto R =
5867 MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm, Variant);
5868 if (R == Match_Success || atLeastAsSpecific(R, Result)) {
5869 Result = R;
5870 ErrorInfo = EI;
5871 }
5872 if (R == Match_Success)
5873 break;
5874 }
5875
5876 if (Result == Match_Success) {
5877 if (!validateInstruction(Inst, IDLoc, Operands)) {
5878 return true;
5879 }
5880 emitTargetDirective();
5881 Out.emitInstruction(Inst, getSTI());
5882 // Record for kernel prologue checking.
5883 OpcodeStream.push_back(Inst.getOpcode());
5884 return false;
5885 }
5886
5887 StringRef Mnemo = ((AMDGPUOperand &)*Operands[0]).getToken();
5888 if (checkUnsupportedInstruction(Mnemo, IDLoc)) {
5889 return true;
5890 }
5891
5892 switch (Result) {
5893 default:
5894 break;
5895 case Match_MissingFeature:
5896 // It has been verified that the specified instruction
5897 // mnemonic is valid. A match was found but it requires
5898 // features which are not supported on this GPU.
5899 return Error(IDLoc, "operands are not valid for this GPU or mode");
5900
5901 case Match_InvalidOperand: {
5902 SMLoc ErrorLoc = IDLoc;
5903 if (ErrorInfo != ~0ULL) {
5904 if (ErrorInfo >= Operands.size()) {
5905 return Error(IDLoc, "too few operands for instruction");
5906 }
5907 AMDGPUOperand &ErrorOp = (AMDGPUOperand &)*Operands[ErrorInfo];
5908 ErrorLoc = ErrorOp.getStartLoc();
5909 if (ErrorLoc == SMLoc())
5910 ErrorLoc = IDLoc;
5911
5912 if (isInvalidVOPDY(Operands, ErrorInfo))
5913 return Error(ErrorLoc, "invalid VOPDY instruction");
5914 }
5915 return Error(ErrorLoc, "invalid operand for instruction");
5916 }
5917
5918 case Match_MnemonicFail:
5919 llvm_unreachable("Invalid instructions should have been handled already");
5920 }
5921 llvm_unreachable("Implement any new match types added!");
5922}
5923
5924bool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) {
5925 int64_t Tmp = -1;
5926 if (!isToken(AsmToken::Integer) && !isToken(AsmToken::Identifier)) {
5927 return true;
5928 }
5929 if (getParser().parseAbsoluteExpression(Tmp)) {
5930 return true;
5931 }
5932 Ret = static_cast<uint32_t>(Tmp);
5933 return false;
5934}
5935
5936bool AMDGPUAsmParser::ParseDirectiveAMDGCNTarget() {
5937 if (!getSTI().getTargetTriple().isAMDGCN())
5938 return TokError("directive only supported for amdgcn architecture");
5939
5940 std::string TargetIDDirective;
5941 SMLoc TargetStart = getTok().getLoc();
5942 if (getParser().parseEscapedString(TargetIDDirective))
5943 return true;
5944
5945 std::optional<AMDGPU::TargetID> MaybeParsed =
5946 AMDGPU::TargetID::parseTargetIDString(TargetIDDirective);
5947 if (!MaybeParsed)
5948 return getParser().Error(TargetStart,
5949 "malformed target id '" + TargetIDDirective + "'");
5950
5951 const AMDGPU::TargetID &ParsedTargetID = *MaybeParsed;
5952 const Triple &TT = getSTI().getTargetTriple();
5953
5954 // The processor named in the target id must be covered by the triple's
5955 // subarch.
5956 if (!AMDGPU::isCPUValidForSubArch(TT.getSubArch(),
5957 ParsedTargetID.getGPUKind())) {
5958 return getParser().Error(
5959 TargetStart, "target id '" + TargetIDDirective +
5960 "' specifies a processor that is not valid for "
5961 "subarch '" +
5962 TT.getArchName() + "'");
5963 }
5964
5965 const std::optional<AMDGPU::TargetID> &CurrentTargetID =
5966 getTargetStreamer().getTargetID();
5967
5968 Triple DirectiveTriple(ParsedTargetID.getTargetTripleString());
5969 const Triple &STITriple = getSTI().getTargetTriple();
5970 if (!DirectiveTriple.isCompatibleWith(STITriple)) {
5971 return getParser().Error(
5972 TargetStart, ".amdgcn_target " + Twine(ParsedTargetID.toString()) +
5973 " is incompatible with " +
5974 Twine(CurrentTargetID->toString()));
5975 }
5976
5977 // Error if the ISA version doesn't match
5978 StringRef DirectiveProcessor =
5979 AMDGPU::getArchNameAMDGCN(ParsedTargetID.getGPUKind());
5980 AMDGPU::IsaVersion DirectiveISA = AMDGPU::getIsaVersion(DirectiveProcessor);
5981 if (DirectiveISA != ISA) {
5982 return getParser().Error(TargetStart,
5983 ".amdgcn_target directive processor " +
5984 Twine(DirectiveProcessor) +
5985 " does not match the specified processor " +
5986 Twine(getSTI().getCPU()));
5987 }
5988
5989 // Warn if sramecc or xnack mismatch. These do not change the encoding.
5991 ParsedTargetID.getXnackSetting(),
5992 CurrentTargetID->getXnackSetting())) {
5993 Warning(TargetStart,
5994 ".amdgcn_target directive has conflicting xnack settings");
5995 }
5997 ParsedTargetID.getSramEccSetting(),
5998 CurrentTargetID->getSramEccSetting())) {
5999 Warning(TargetStart,
6000 ".amdgcn_target directive has conflicting sramecc settings");
6001 }
6002
6003 // Update the target streamer's TargetID with settings from the directive.
6004 // We don't update the MCSubtargetInfo because we've already validated
6005 // that the directive matches the command-line CPU.
6006 getTargetStreamer().getTargetID()->setXnackSetting(
6007 ParsedTargetID.getXnackSetting());
6008 getTargetStreamer().getTargetID()->setSramEccSetting(
6009 ParsedTargetID.getSramEccSetting());
6010
6011 return false;
6012}
6013
6014bool AMDGPUAsmParser::OutOfRangeError(SMRange Range) {
6015 return Error(Range.Start, "value out of range", Range);
6016}
6017
6018bool AMDGPUAsmParser::calculateGPRBlocks(
6019 const FeatureBitset &Features, const MCExpr *VCCUsed,
6020 const MCExpr *FlatScrUsed, bool XNACKUsed,
6021 std::optional<bool> EnableWavefrontSize32, const MCExpr *NextFreeVGPR,
6022 SMRange VGPRRange, const MCExpr *NextFreeSGPR, SMRange SGPRRange,
6023 const MCExpr *&VGPRBlocks, const MCExpr *&SGPRBlocks) {
6024 // TODO(scott.linder): These calculations are duplicated from
6025 // AMDGPUAsmPrinter::getSIProgramInfo and could be unified.
6026 MCContext &Ctx = getContext();
6027
6028 const MCExpr *NumSGPRs = NextFreeSGPR;
6029 int64_t EvaluatedSGPRs;
6030
6031 if (ISA.Major >= 10)
6033 else {
6034 unsigned MaxAddressableNumSGPRs = AMDGPU::getAddressableNumSGPRs(Gfx);
6035
6036 if (NumSGPRs->evaluateAsAbsolute(EvaluatedSGPRs) && ISA.Major >= 8 &&
6037 !Features.test(FeatureSGPRInitBug) &&
6038 static_cast<uint64_t>(EvaluatedSGPRs) > MaxAddressableNumSGPRs)
6039 return OutOfRangeError(SGPRRange);
6040
6041 const MCExpr *ExtraSGPRs =
6042 AMDGPUMCExpr::createExtraSGPRs(VCCUsed, FlatScrUsed, XNACKUsed, Ctx);
6043 NumSGPRs = MCBinaryExpr::createAdd(NumSGPRs, ExtraSGPRs, Ctx);
6044
6045 if (NumSGPRs->evaluateAsAbsolute(EvaluatedSGPRs) &&
6046 (ISA.Major <= 7 || Features.test(FeatureSGPRInitBug)) &&
6047 static_cast<uint64_t>(EvaluatedSGPRs) > MaxAddressableNumSGPRs)
6048 return OutOfRangeError(SGPRRange);
6049
6050 if (Features.test(FeatureSGPRInitBug))
6051 NumSGPRs =
6053 }
6054
6055 // The MCExpr equivalent of getNumSGPRBlocks/getNumVGPRBlocks:
6056 // (alignTo(max(1u, NumGPR), GPREncodingGranule) / GPREncodingGranule) - 1
6057 auto GetNumGPRBlocks = [&Ctx](const MCExpr *NumGPR,
6058 unsigned Granule) -> const MCExpr * {
6059 const MCExpr *OneConst = MCConstantExpr::create(1ul, Ctx);
6060 const MCExpr *GranuleConst = MCConstantExpr::create(Granule, Ctx);
6061 const MCExpr *MaxNumGPR = AMDGPUMCExpr::createMax({NumGPR, OneConst}, Ctx);
6062 const MCExpr *AlignToGPR =
6063 AMDGPUMCExpr::createAlignTo(MaxNumGPR, GranuleConst, Ctx);
6064 const MCExpr *DivGPR =
6065 MCBinaryExpr::createDiv(AlignToGPR, GranuleConst, Ctx);
6066 const MCExpr *SubGPR = MCBinaryExpr::createSub(DivGPR, OneConst, Ctx);
6067 return SubGPR;
6068 };
6069
6070 VGPRBlocks = GetNumGPRBlocks(
6071 NextFreeVGPR,
6072 IsaInfo::getVGPREncodingGranule(getSTI(), EnableWavefrontSize32));
6073 SGPRBlocks =
6074 GetNumGPRBlocks(NumSGPRs, IsaInfo::getSGPREncodingGranule(getSTI()));
6075
6076 return false;
6077}
6078
6079bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() {
6080 if (!getSTI().getTargetTriple().isAMDGCN())
6081 return TokError("directive only supported for amdgcn architecture");
6082
6083 if (!isHsaAbi(getSTI()))
6084 return TokError("directive only supported for amdhsa OS");
6085
6086 StringRef KernelName;
6087 if (getParser().parseIdentifier(KernelName))
6088 return true;
6089
6090 // Remember the kernel name so its prologue can be checked at end of file.
6091 // The matching label may have been parsed already or may follow later.
6092 AMDHSAKernelSymbols.insert(getContext().getOrCreateSymbol(KernelName));
6093
6094 AMDGPU::MCKernelDescriptor KD =
6096 &getSTI(), getContext());
6097
6098 StringSet<> Seen;
6099
6100 const MCExpr *ZeroExpr = MCConstantExpr::create(0, getContext());
6101 const MCExpr *OneExpr = MCConstantExpr::create(1, getContext());
6102
6103 SMRange VGPRRange;
6104 const MCExpr *NextFreeVGPR = ZeroExpr;
6105 const MCExpr *AccumOffset = MCConstantExpr::create(0, getContext());
6106 const MCExpr *NamedBarCnt = ZeroExpr;
6107 uint64_t SharedVGPRCount = 0;
6108 uint64_t PreloadLength = 0;
6109 uint64_t PreloadOffset = 0;
6110 SMRange SGPRRange;
6111 const MCExpr *NextFreeSGPR = ZeroExpr;
6112
6113 // Count the number of user SGPRs implied from the enabled feature bits.
6114 unsigned ImpliedUserSGPRCount = 0;
6115
6116 // Track if the asm explicitly contains the directive for the user SGPR
6117 // count.
6118 std::optional<unsigned> ExplicitUserSGPRCount;
6119 const MCExpr *ReserveVCC = OneExpr;
6120 const MCExpr *ReserveFlatScr = OneExpr;
6121 std::optional<bool> EnableWavefrontSize32;
6122
6123 while (true) {
6124 while (trySkipToken(AsmToken::EndOfStatement))
6125 ;
6126
6127 StringRef ID;
6128 SMRange IDRange = getTok().getLocRange();
6129 if (!parseId(ID, "expected .amdhsa_ directive or .end_amdhsa_kernel"))
6130 return true;
6131
6132 if (ID == ".end_amdhsa_kernel")
6133 break;
6134
6135 if (!Seen.insert(ID).second)
6136 return TokError(".amdhsa_ directives cannot be repeated");
6137
6138 SMLoc ValStart = getLoc();
6139 const MCExpr *ExprVal;
6140 if (getParser().parseExpression(ExprVal))
6141 return true;
6142 SMLoc ValEnd = getLoc();
6143 SMRange ValRange = SMRange(ValStart, ValEnd);
6144
6145 int64_t IVal = 0;
6146 uint64_t Val = IVal;
6147 bool EvaluatableExpr;
6148 if ((EvaluatableExpr = ExprVal->evaluateAsAbsolute(IVal))) {
6149 if (IVal < 0)
6150 return OutOfRangeError(ValRange);
6151 Val = IVal;
6152 }
6153
6154#define PARSE_BITS_ENTRY(FIELD, ENTRY, VALUE, RANGE) \
6155 if (!isUInt<ENTRY##_WIDTH>(Val)) \
6156 return OutOfRangeError(RANGE); \
6157 AMDGPU::MCKernelDescriptor::bits_set(FIELD, VALUE, ENTRY##_SHIFT, ENTRY, \
6158 getContext());
6159
6160// Some fields use the parsed value immediately which requires the expression to
6161// be solvable.
6162#define EXPR_RESOLVE_OR_ERROR(RESOLVED) \
6163 if (!(RESOLVED)) \
6164 return Error(IDRange.Start, "directive should have resolvable expression", \
6165 IDRange);
6166
6167 if (ID == ".amdhsa_group_segment_fixed_size") {
6169 CHAR_BIT>(Val))
6170 return OutOfRangeError(ValRange);
6171 KD.group_segment_fixed_size = ExprVal;
6172 } else if (ID == ".amdhsa_private_segment_fixed_size") {
6174 CHAR_BIT>(Val))
6175 return OutOfRangeError(ValRange);
6176 KD.private_segment_fixed_size = ExprVal;
6177 } else if (ID == ".amdhsa_kernarg_size") {
6178 if (!isUInt<sizeof(kernel_descriptor_t::kernarg_size) * CHAR_BIT>(Val))
6179 return OutOfRangeError(ValRange);
6180 KD.kernarg_size = ExprVal;
6181 } else if (ID == ".amdhsa_user_sgpr_count") {
6182 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6183 ExplicitUserSGPRCount = Val;
6184 } else if (ID == ".amdhsa_user_sgpr_private_segment_buffer") {
6185 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6187 return Error(IDRange.Start,
6188 "directive is not supported with architected flat scratch",
6189 IDRange);
6191 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER,
6192 ExprVal, ValRange);
6193 if (Val)
6194 ImpliedUserSGPRCount += 4;
6195 } else if (ID == ".amdhsa_user_sgpr_kernarg_preload_length") {
6196 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6197 if (!hasKernargPreload())
6198 return Error(IDRange.Start, "directive requires gfx90a+", IDRange);
6199
6200 if (Val > getMaxNumUserSGPRs())
6201 return OutOfRangeError(ValRange);
6202 PARSE_BITS_ENTRY(KD.kernarg_preload, KERNARG_PRELOAD_SPEC_LENGTH, ExprVal,
6203 ValRange);
6204 if (Val) {
6205 ImpliedUserSGPRCount += Val;
6206 PreloadLength = Val;
6207 }
6208 } else if (ID == ".amdhsa_user_sgpr_kernarg_preload_offset") {
6209 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6210 if (!hasKernargPreload())
6211 return Error(IDRange.Start, "directive requires gfx90a+", IDRange);
6212
6213 if (Val >= 1024)
6214 return OutOfRangeError(ValRange);
6215 PARSE_BITS_ENTRY(KD.kernarg_preload, KERNARG_PRELOAD_SPEC_OFFSET, ExprVal,
6216 ValRange);
6217 if (Val)
6218 PreloadOffset = Val;
6219 } else if (ID == ".amdhsa_user_sgpr_dispatch_ptr") {
6220 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6222 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR, ExprVal,
6223 ValRange);
6224 if (Val)
6225 ImpliedUserSGPRCount += 2;
6226 } else if (ID == ".amdhsa_user_sgpr_queue_ptr") {
6227 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6229 KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR, ExprVal,
6230 ValRange);
6231 if (Val)
6232 ImpliedUserSGPRCount += 2;
6233 } else if (ID == ".amdhsa_user_sgpr_kernarg_segment_ptr") {
6234 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6236 KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR,
6237 ExprVal, ValRange);
6238 if (Val)
6239 ImpliedUserSGPRCount += 2;
6240 } else if (ID == ".amdhsa_user_sgpr_dispatch_id") {
6241 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6243 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID, ExprVal,
6244 ValRange);
6245 if (Val)
6246 ImpliedUserSGPRCount += 2;
6247 } else if (ID == ".amdhsa_user_sgpr_flat_scratch_init") {
6249 return Error(IDRange.Start,
6250 "directive is not supported with architected flat scratch",
6251 IDRange);
6252 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6254 KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT,
6255 ExprVal, ValRange);
6256 if (Val)
6257 ImpliedUserSGPRCount += 2;
6258 } else if (ID == ".amdhsa_user_sgpr_private_segment_size") {
6259 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6261 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE,
6262 ExprVal, ValRange);
6263 if (Val)
6264 ImpliedUserSGPRCount += 1;
6265 } else if (ID == ".amdhsa_wavefront_size32") {
6266 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6267 if (ISA.Major < 10)
6268 return Error(IDRange.Start, "directive requires gfx10+", IDRange);
6269 EnableWavefrontSize32 = Val;
6271 KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, ExprVal,
6272 ValRange);
6273 } else if (ID == ".amdhsa_uses_dynamic_stack") {
6275 KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK, ExprVal,
6276 ValRange);
6277 } else if (ID == ".amdhsa_system_sgpr_private_segment_wavefront_offset") {
6279 return Error(IDRange.Start,
6280 "directive is not supported with architected flat scratch",
6281 IDRange);
6283 COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, ExprVal,
6284 ValRange);
6285 } else if (ID == ".amdhsa_enable_private_segment") {
6287 return Error(
6288 IDRange.Start,
6289 "directive is not supported without architected flat scratch",
6290 IDRange);
6292 COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, ExprVal,
6293 ValRange);
6294 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_x") {
6296 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, ExprVal,
6297 ValRange);
6298 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_y") {
6300 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y, ExprVal,
6301 ValRange);
6302 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_z") {
6304 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z, ExprVal,
6305 ValRange);
6306 } else if (ID == ".amdhsa_system_sgpr_workgroup_info") {
6308 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO, ExprVal,
6309 ValRange);
6310 } else if (ID == ".amdhsa_system_vgpr_workitem_id") {
6312 COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID, ExprVal,
6313 ValRange);
6314 } else if (ID == ".amdhsa_next_free_vgpr") {
6315 VGPRRange = ValRange;
6316 NextFreeVGPR = ExprVal;
6317 } else if (ID == ".amdhsa_next_free_sgpr") {
6318 SGPRRange = ValRange;
6319 NextFreeSGPR = ExprVal;
6320 } else if (ID == ".amdhsa_accum_offset") {
6321 if (!isGFX90A())
6322 return Error(IDRange.Start, "directive requires gfx90a+", IDRange);
6323 AccumOffset = ExprVal;
6324 } else if (ID == ".amdhsa_named_barrier_count") {
6325 if (!isGFX1250Plus())
6326 return Error(IDRange.Start, "directive requires gfx1250+", IDRange);
6327 NamedBarCnt = ExprVal;
6328 } else if (ID == ".amdhsa_reserve_vcc") {
6329 if (EvaluatableExpr && !isUInt<1>(Val))
6330 return OutOfRangeError(ValRange);
6331 ReserveVCC = ExprVal;
6332 } else if (ID == ".amdhsa_reserve_flat_scratch") {
6333 if (ISA.Major < 7)
6334 return Error(IDRange.Start, "directive requires gfx7+", IDRange);
6336 return Error(IDRange.Start,
6337 "directive is not supported with architected flat scratch",
6338 IDRange);
6339 if (EvaluatableExpr && !isUInt<1>(Val))
6340 return OutOfRangeError(ValRange);
6341 ReserveFlatScr = ExprVal;
6342 } else if (ID == ".amdhsa_reserve_xnack_mask") {
6343 if (ISA.Major < 8)
6344 return Error(IDRange.Start, "directive requires gfx8+", IDRange);
6345 if (!isUInt<1>(Val))
6346 return OutOfRangeError(ValRange);
6347 bool XnackOn = getTargetStreamer().getTargetID()->isXnackOnOrAny();
6348 if (Val != XnackOn) {
6349 return getParser().Error(
6350 IDRange.Start,
6351 ".amdhsa_reserve_xnack_mask does not match target id", IDRange);
6352 }
6353 } else if (ID == ".amdhsa_float_round_mode_32") {
6355 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32, ExprVal,
6356 ValRange);
6357 } else if (ID == ".amdhsa_float_round_mode_16_64") {
6359 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64, ExprVal,
6360 ValRange);
6361 } else if (ID == ".amdhsa_float_denorm_mode_32") {
6363 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32, ExprVal,
6364 ValRange);
6365 } else if (ID == ".amdhsa_float_denorm_mode_16_64") {
6367 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, ExprVal,
6368 ValRange);
6369 } else if (ID == ".amdhsa_dx10_clamp") {
6370 if (!getSTI().hasFeature(AMDGPU::FeatureDX10ClampAndIEEEMode))
6371 return Error(IDRange.Start, "directive unsupported on gfx1170+",
6372 IDRange);
6374 COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP, ExprVal,
6375 ValRange);
6376 } else if (ID == ".amdhsa_ieee_mode") {
6377 if (!getSTI().hasFeature(AMDGPU::FeatureDX10ClampAndIEEEMode))
6378 return Error(IDRange.Start, "directive unsupported on gfx1170+",
6379 IDRange);
6381 COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE, ExprVal,
6382 ValRange);
6383 } else if (ID == ".amdhsa_fp16_overflow") {
6384 if (ISA.Major < 9)
6385 return Error(IDRange.Start, "directive requires gfx9+", IDRange);
6387 COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL, ExprVal,
6388 ValRange);
6389 } else if (ID == ".amdhsa_tg_split") {
6390 if (!isGFX90A())
6391 return Error(IDRange.Start, "directive requires gfx90a+", IDRange);
6392 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc3, COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT,
6393 ExprVal, ValRange);
6394 } else if (ID == ".amdhsa_workgroup_processor_mode") {
6395 if (!supportsWGP(getSTI()))
6396 return Error(IDRange.Start,
6397 "directive unsupported on " + getSTI().getCPU(), IDRange);
6399 COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE, ExprVal,
6400 ValRange);
6401 } else if (ID == ".amdhsa_memory_ordered") {
6402 if (ISA.Major < 10)
6403 return Error(IDRange.Start, "directive requires gfx10+", IDRange);
6405 COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED, ExprVal,
6406 ValRange);
6407 } else if (ID == ".amdhsa_forward_progress") {
6408 if (ISA.Major < 10)
6409 return Error(IDRange.Start, "directive requires gfx10+", IDRange);
6411 COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS, ExprVal,
6412 ValRange);
6413 } else if (ID == ".amdhsa_shared_vgpr_count") {
6414 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6415 if (ISA.Major < 10 || ISA.Major >= 12)
6416 return Error(IDRange.Start, "directive requires gfx10 or gfx11",
6417 IDRange);
6418 SharedVGPRCount = Val;
6420 COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT, ExprVal,
6421 ValRange);
6422 } else if (ID == ".amdhsa_inst_pref_size") {
6423 if (ISA.Major < 11)
6424 return Error(IDRange.Start, "directive requires gfx11+", IDRange);
6425 if (ISA.Major == 11) {
6427 COMPUTE_PGM_RSRC3_GFX11_INST_PREF_SIZE, ExprVal,
6428 ValRange);
6429 } else {
6431 COMPUTE_PGM_RSRC3_GFX12_PLUS_INST_PREF_SIZE, ExprVal,
6432 ValRange);
6433 }
6434 } else if (ID == ".amdhsa_exception_fp_ieee_invalid_op") {
6437 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION,
6438 ExprVal, ValRange);
6439 } else if (ID == ".amdhsa_exception_fp_denorm_src") {
6441 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE,
6442 ExprVal, ValRange);
6443 } else if (ID == ".amdhsa_exception_fp_ieee_div_zero") {
6446 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO,
6447 ExprVal, ValRange);
6448 } else if (ID == ".amdhsa_exception_fp_ieee_overflow") {
6450 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW,
6451 ExprVal, ValRange);
6452 } else if (ID == ".amdhsa_exception_fp_ieee_underflow") {
6454 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW,
6455 ExprVal, ValRange);
6456 } else if (ID == ".amdhsa_exception_fp_ieee_inexact") {
6458 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT,
6459 ExprVal, ValRange);
6460 } else if (ID == ".amdhsa_exception_int_div_zero") {
6462 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO,
6463 ExprVal, ValRange);
6464 } else if (ID == ".amdhsa_round_robin_scheduling") {
6465 if (ISA.Major < 12)
6466 return Error(IDRange.Start, "directive requires gfx12+", IDRange);
6468 COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN, ExprVal,
6469 ValRange);
6470 } else {
6471 return Error(IDRange.Start, "unknown .amdhsa_kernel directive", IDRange);
6472 }
6473
6474#undef PARSE_BITS_ENTRY
6475 }
6476
6477 if (!Seen.contains(".amdhsa_next_free_vgpr"))
6478 return TokError(".amdhsa_next_free_vgpr directive is required");
6479
6480 if (!Seen.contains(".amdhsa_next_free_sgpr"))
6481 return TokError(".amdhsa_next_free_sgpr directive is required");
6482
6483 unsigned UserSGPRCount = ExplicitUserSGPRCount.value_or(ImpliedUserSGPRCount);
6484 if (UserSGPRCount > getMaxNumUserSGPRs())
6485 return TokError("too many user SGPRs enabled, found " +
6486 Twine(UserSGPRCount) + ", but only " +
6487 Twine(getMaxNumUserSGPRs()) + " are supported.");
6488
6489 // Consider the case where the total number of UserSGPRs with trailing
6490 // allocated preload SGPRs, is greater than the number of explicitly
6491 // referenced SGPRs.
6492 if (PreloadLength) {
6493 MCContext &Ctx = getContext();
6494 NextFreeSGPR = AMDGPUMCExpr::createMax(
6495 {NextFreeSGPR, MCConstantExpr::create(UserSGPRCount, Ctx)}, Ctx);
6496 }
6497
6498 const MCExpr *VGPRBlocks;
6499 const MCExpr *SGPRBlocks;
6500 if (calculateGPRBlocks(getFeatureBits(), ReserveVCC, ReserveFlatScr,
6501 getTargetStreamer().getTargetID()->isXnackOnOrAny(),
6502 EnableWavefrontSize32, NextFreeVGPR, VGPRRange,
6503 NextFreeSGPR, SGPRRange, VGPRBlocks, SGPRBlocks))
6504 return true;
6505
6506 int64_t EvaluatedVGPRBlocks;
6507 bool VGPRBlocksEvaluatable =
6508 VGPRBlocks->evaluateAsAbsolute(EvaluatedVGPRBlocks);
6509 if (VGPRBlocksEvaluatable &&
6511 static_cast<uint64_t>(EvaluatedVGPRBlocks))) {
6512 return OutOfRangeError(VGPRRange);
6513 }
6515 KD.compute_pgm_rsrc1, VGPRBlocks,
6516 COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT_SHIFT,
6517 COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT, getContext());
6518
6519 int64_t EvaluatedSGPRBlocks;
6520 if (SGPRBlocks->evaluateAsAbsolute(EvaluatedSGPRBlocks) &&
6522 static_cast<uint64_t>(EvaluatedSGPRBlocks)))
6523 return OutOfRangeError(SGPRRange);
6525 KD.compute_pgm_rsrc1, SGPRBlocks,
6526 COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT_SHIFT,
6527 COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT, getContext());
6528
6529 if (ExplicitUserSGPRCount && ImpliedUserSGPRCount > *ExplicitUserSGPRCount)
6530 return TokError("amdgpu_user_sgpr_count smaller than implied by "
6531 "enabled user SGPRs");
6532
6533 if (isGFX1250Plus()) {
6536 MCConstantExpr::create(UserSGPRCount, getContext()),
6537 COMPUTE_PGM_RSRC2_GFX125_USER_SGPR_COUNT_SHIFT,
6538 COMPUTE_PGM_RSRC2_GFX125_USER_SGPR_COUNT, getContext());
6539 } else {
6542 MCConstantExpr::create(UserSGPRCount, getContext()),
6543 COMPUTE_PGM_RSRC2_GFX6_GFX120_USER_SGPR_COUNT_SHIFT,
6544 COMPUTE_PGM_RSRC2_GFX6_GFX120_USER_SGPR_COUNT, getContext());
6545 }
6546
6547 int64_t IVal = 0;
6548 if (!KD.kernarg_size->evaluateAsAbsolute(IVal))
6549 return TokError("Kernarg size should be resolvable");
6550 uint64_t kernarg_size = IVal;
6551 if (PreloadLength && kernarg_size &&
6552 (PreloadLength * 4 + PreloadOffset * 4 > kernarg_size))
6553 return TokError("Kernarg preload length + offset is larger than the "
6554 "kernarg segment size");
6555
6556 if (isGFX90A()) {
6557 if (!Seen.contains(".amdhsa_accum_offset"))
6558 return TokError(".amdhsa_accum_offset directive is required");
6559 int64_t EvaluatedAccum;
6560 bool AccumEvaluatable = AccumOffset->evaluateAsAbsolute(EvaluatedAccum);
6561 uint64_t UEvaluatedAccum = EvaluatedAccum;
6562 if (AccumEvaluatable &&
6563 (UEvaluatedAccum < 4 || UEvaluatedAccum > 256 || (UEvaluatedAccum & 3)))
6564 return TokError("accum_offset should be in range [4..256] in "
6565 "increments of 4");
6566
6567 int64_t EvaluatedNumVGPR;
6568 if (NextFreeVGPR->evaluateAsAbsolute(EvaluatedNumVGPR) &&
6569 AccumEvaluatable &&
6570 UEvaluatedAccum >
6571 alignTo(std::max((uint64_t)1, (uint64_t)EvaluatedNumVGPR), 4))
6572 return TokError("accum_offset exceeds total VGPR allocation");
6573 const MCExpr *AdjustedAccum = MCBinaryExpr::createSub(
6575 AccumOffset, MCConstantExpr::create(4, getContext()), getContext()),
6578 COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT,
6579 COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET,
6580 getContext());
6581 }
6582
6583 if (isGFX1250Plus())
6585 COMPUTE_PGM_RSRC3_GFX125_NAMED_BAR_CNT_SHIFT,
6586 COMPUTE_PGM_RSRC3_GFX125_NAMED_BAR_CNT,
6587 getContext());
6588
6589 if (ISA.Major >= 10 && ISA.Major < 12) {
6590 // SharedVGPRCount < 16 checked by PARSE_ENTRY_BITS
6591 if (SharedVGPRCount && EnableWavefrontSize32 && *EnableWavefrontSize32) {
6592 return TokError("shared_vgpr_count directive not valid on "
6593 "wavefront size 32");
6594 }
6595
6596 if (VGPRBlocksEvaluatable &&
6597 (SharedVGPRCount * 2 + static_cast<uint64_t>(EvaluatedVGPRBlocks) >
6598 63)) {
6599 return TokError("shared_vgpr_count*2 + "
6600 "compute_pgm_rsrc1.GRANULATED_WORKITEM_VGPR_COUNT cannot "
6601 "exceed 63\n");
6602 }
6603 }
6604
6605 emitTargetDirective();
6606 getTargetStreamer().EmitAmdhsaKernelDescriptor(getSTI(), KernelName, KD,
6607 NextFreeVGPR, NextFreeSGPR,
6608 ReserveVCC, ReserveFlatScr);
6609 return false;
6610}
6611
6612bool AMDGPUAsmParser::ParseDirectiveAMDHSACodeObjectVersion() {
6613 uint32_t Version;
6614 if (ParseAsAbsoluteExpression(Version))
6615 return true;
6616
6617 getTargetStreamer().EmitDirectiveAMDHSACodeObjectVersion(Version);
6618 emitTargetDirective();
6619 return false;
6620}
6621
6622bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
6623 AMDGPUMCKernelCodeT &C) {
6624 // max_scratch_backing_memory_byte_size is deprecated. Ignore it while parsing
6625 // assembly for backwards compatibility.
6626 if (ID == "max_scratch_backing_memory_byte_size") {
6627 Parser.eatToEndOfStatement();
6628 return false;
6629 }
6630
6631 SmallString<40> ErrStr;
6632 raw_svector_ostream Err(ErrStr);
6633 if (!C.ParseKernelCodeT(ID, getParser(), Err)) {
6634 return TokError(Err.str());
6635 }
6636 Lex();
6637
6638 if (ID == "enable_wavefront_size32") {
6639 if (C.code_properties & AMD_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32) {
6640 if (!isGFX10Plus())
6641 return TokError("enable_wavefront_size32=1 is only allowed on GFX10+");
6642 if (!isWave32())
6643 return TokError("enable_wavefront_size32=1 requires +WavefrontSize32");
6644 } else {
6645 if (!isWave64())
6646 return TokError("enable_wavefront_size32=0 requires +WavefrontSize64");
6647 }
6648 }
6649
6650 if (ID == "wavefront_size") {
6651 if (C.wavefront_size == 5) {
6652 if (!isGFX10Plus())
6653 return TokError("wavefront_size=5 is only allowed on GFX10+");
6654 if (!isWave32())
6655 return TokError("wavefront_size=5 requires +WavefrontSize32");
6656 } else if (C.wavefront_size == 6) {
6657 if (!isWave64())
6658 return TokError("wavefront_size=6 requires +WavefrontSize64");
6659 }
6660 }
6661
6662 return false;
6663}
6664
6665bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
6666 AMDGPUMCKernelCodeT KernelCode;
6667 KernelCode.initDefault(getSTI(), getContext());
6668
6669 while (true) {
6670 // Lex EndOfStatement. This is in a while loop, because lexing a comment
6671 // will set the current token to EndOfStatement.
6672 while (trySkipToken(AsmToken::EndOfStatement))
6673 ;
6674
6675 StringRef ID;
6676 if (!parseId(ID, "expected value identifier or .end_amd_kernel_code_t"))
6677 return true;
6678
6679 if (ID == ".end_amd_kernel_code_t")
6680 break;
6681
6682 if (ParseAMDKernelCodeTValue(ID, KernelCode))
6683 return true;
6684 }
6685
6686 KernelCode.validate(&getSTI(), getContext());
6687 getTargetStreamer().EmitAMDKernelCodeT(KernelCode);
6688
6689 return false;
6690}
6691
6692bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
6693 StringRef KernelName;
6694 if (!parseId(KernelName, "expected symbol name"))
6695 return true;
6696
6697 getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
6699
6700 KernelScope.initialize(getContext());
6701 return false;
6702}
6703
6704bool AMDGPUAsmParser::ParseDirectiveISAVersion() {
6705 if (!getSTI().getTargetTriple().isAMDGCN()) {
6706 return Error(getLoc(),
6707 ".amd_amdgpu_isa directive is not available on non-amdgcn "
6708 "architectures");
6709 }
6710
6711 StringRef TargetIDDirective = getLexer().getTok().getStringContents();
6712
6713 std::optional<AMDGPU::TargetID> MaybeParsed =
6714 AMDGPU::TargetID::parseTargetIDString(TargetIDDirective);
6715 if (!MaybeParsed)
6716 return Error(getParser().getTok().getLoc(),
6717 "malformed target id '" + TargetIDDirective + "'");
6718
6719 const AMDGPU::TargetID &ParsedTargetID = *MaybeParsed;
6720 const Triple &TT = getSTI().getTargetTriple();
6721
6722 // The processor named in the target id must be covered by the triple's
6723 // subarch.
6724 if (!AMDGPU::isCPUValidForSubArch(TT.getSubArch(),
6725 ParsedTargetID.getGPUKind())) {
6726 return Error(getParser().getTok().getLoc(),
6727 "target id '" + TargetIDDirective +
6728 "' specifies a processor that is not valid for subarch '" +
6729 TT.getArchName() + "'");
6730 }
6731
6732 const std::optional<AMDGPU::TargetID> &CurrentTargetID =
6733 getTargetStreamer().getTargetID();
6734
6735 Triple DirectiveTriple(ParsedTargetID.getTargetTripleString());
6736 const Triple &STITriple = getSTI().getTargetTriple();
6737 if (!DirectiveTriple.isCompatibleWith(STITriple)) {
6738 return Error(getParser().getTok().getLoc(),
6739 ".amd_amdgpu_isa " + Twine(ParsedTargetID.toString()) +
6740 " is incompatible with " +
6741 Twine(CurrentTargetID->toString()));
6742 }
6743
6744 // Error if the ISA version doesn't match
6745 StringRef DirectiveProcessor =
6746 AMDGPU::getArchNameAMDGCN(ParsedTargetID.getGPUKind());
6747 AMDGPU::IsaVersion DirectiveISA = AMDGPU::getIsaVersion(DirectiveProcessor);
6748 if (DirectiveISA != ISA) {
6749 return Error(getParser().getTok().getLoc(),
6750 ".amd_amdgpu_isa directive processor " +
6751 Twine(DirectiveProcessor) +
6752 " does not match the specified processor " +
6753 Twine(getSTI().getCPU()));
6754 }
6755
6756 getTargetStreamer().EmitISAVersion();
6757 Lex();
6758
6759 return false;
6760}
6761
6762bool AMDGPUAsmParser::ParseDirectiveHSAMetadata() {
6763 assert(isHsaAbi(getSTI()));
6764
6765 std::string HSAMetadataString;
6766 if (ParseToEndDirective(HSAMD::V3::AssemblerDirectiveBegin,
6767 HSAMD::V3::AssemblerDirectiveEnd, HSAMetadataString))
6768 return true;
6769
6770 if (!getTargetStreamer().EmitHSAMetadataV3(HSAMetadataString))
6771 return Error(getLoc(), "invalid HSA metadata");
6772
6773 return false;
6774}
6775
6776/// Common code to parse out a block of text (typically YAML) between start and
6777/// end directives.
6778bool AMDGPUAsmParser::ParseToEndDirective(const char *AssemblerDirectiveBegin,
6779 const char *AssemblerDirectiveEnd,
6780 std::string &CollectString) {
6781
6782 raw_string_ostream CollectStream(CollectString);
6783
6784 getLexer().setSkipSpace(false);
6785
6786 bool FoundEnd = false;
6787 while (!isToken(AsmToken::Eof)) {
6788 while (isToken(AsmToken::Space)) {
6789 CollectStream << getTokenStr();
6790 Lex();
6791 }
6792
6793 if (trySkipId(AssemblerDirectiveEnd)) {
6794 FoundEnd = true;
6795 break;
6796 }
6797
6798 CollectStream << Parser.parseStringToEndOfStatement()
6799 << getContext().getAsmInfo().getSeparatorString();
6800
6801 Parser.eatToEndOfStatement();
6802 }
6803
6804 getLexer().setSkipSpace(true);
6805
6806 if (isToken(AsmToken::Eof) && !FoundEnd) {
6807 return TokError(Twine("expected directive ") +
6808 Twine(AssemblerDirectiveEnd) + Twine(" not found"));
6809 }
6810
6811 return false;
6812}
6813
6814/// Parse the assembler directive for new MsgPack-format PAL metadata.
6815bool AMDGPUAsmParser::ParseDirectivePALMetadataBegin() {
6816 std::string String;
6817 if (ParseToEndDirective(AMDGPU::PALMD::AssemblerDirectiveBegin,
6819 return true;
6820
6821 auto *PALMetadata = getTargetStreamer().getPALMetadata();
6822 if (!PALMetadata->setFromString(String))
6823 return Error(getLoc(), "invalid PAL metadata");
6824 return false;
6825}
6826
6827/// Parse the assembler directive for old linear-format PAL metadata.
6828bool AMDGPUAsmParser::ParseDirectivePALMetadata() {
6829 if (getSTI().getTargetTriple().getOS() != Triple::AMDPAL) {
6830 return Error(getLoc(), (Twine(PALMD::AssemblerDirective) +
6831 Twine(" directive is "
6832 "not available on non-amdpal OSes"))
6833 .str());
6834 }
6835
6836 auto *PALMetadata = getTargetStreamer().getPALMetadata();
6837 PALMetadata->setLegacy();
6838 for (;;) {
6839 uint32_t Key, Value;
6840 if (ParseAsAbsoluteExpression(Key)) {
6841 return TokError(Twine("invalid value in ") +
6843 }
6844 if (!trySkipToken(AsmToken::Comma)) {
6845 return TokError(Twine("expected an even number of values in ") +
6847 }
6848 if (ParseAsAbsoluteExpression(Value)) {
6849 return TokError(Twine("invalid value in ") +
6851 }
6852 PALMetadata->setRegister(Key, Value);
6853 if (!trySkipToken(AsmToken::Comma))
6854 break;
6855 }
6856 return false;
6857}
6858
6859/// ParseDirectiveAMDGPULDS
6860/// ::= .amdgpu_lds identifier ',' size_expression [',' align_expression]
6861bool AMDGPUAsmParser::ParseDirectiveAMDGPULDS() {
6862 if (getParser().checkForValidSection())
6863 return true;
6864
6865 StringRef Name;
6866 SMLoc NameLoc = getLoc();
6867 if (getParser().parseIdentifier(Name))
6868 return TokError("expected identifier in directive");
6869
6870 MCSymbol *Symbol = getContext().getOrCreateSymbol(Name);
6871 if (getParser().parseComma())
6872 return true;
6873
6874 unsigned LocalMemorySize = AMDGPU::IsaInfo::getLocalMemorySize(getSTI());
6875
6876 int64_t Size;
6877 SMLoc SizeLoc = getLoc();
6878 if (getParser().parseAbsoluteExpression(Size))
6879 return true;
6880 if (Size < 0)
6881 return Error(SizeLoc, "size must be non-negative");
6882 if (Size > LocalMemorySize)
6883 return Error(SizeLoc, "size is too large");
6884
6885 int64_t Alignment = 4;
6886 if (trySkipToken(AsmToken::Comma)) {
6887 SMLoc AlignLoc = getLoc();
6888 if (getParser().parseAbsoluteExpression(Alignment))
6889 return true;
6890 if (Alignment < 0 || !isPowerOf2_64(Alignment))
6891 return Error(AlignLoc, "alignment must be a power of two");
6892
6893 // Alignment larger than the size of LDS is possible in theory, as long
6894 // as the linker manages to place to symbol at address 0, but we do want
6895 // to make sure the alignment fits nicely into a 32-bit integer.
6896 if (Alignment >= 1u << 31)
6897 return Error(AlignLoc, "alignment is too large");
6898 }
6899
6900 if (parseEOL())
6901 return true;
6902
6903 Symbol->redefineIfPossible();
6904 if (!Symbol->isUndefined())
6905 return Error(NameLoc, "invalid symbol redefinition");
6906
6907 getTargetStreamer().emitAMDGPULDS(Symbol, Size, Align(Alignment));
6908 return false;
6909}
6910
6911bool AMDGPUAsmParser::ParseDirectiveAMDGPUInfo() {
6912 if (getParser().checkForValidSection())
6913 return true;
6914
6915 StringRef FuncName;
6916 if (getParser().parseIdentifier(FuncName))
6917 return TokError("expected symbol name after .amdgpu_info");
6918
6919 MCSymbol *FuncSym = getContext().getOrCreateSymbol(FuncName);
6920 AMDGPU::InfoSectionData ParsedInfoData;
6921 AMDGPU::FuncInfo FI;
6922 FI.Sym = FuncSym;
6923 bool HasScalarAttrs = false;
6924
6925 while (true) {
6926 while (trySkipToken(AsmToken::EndOfStatement))
6927 ;
6928
6929 StringRef ID;
6930 SMLoc IDLoc = getLoc();
6931 if (!parseId(ID, "expected directive or .end_amdgpu_info"))
6932 return true;
6933
6934 if (ID == ".end_amdgpu_info")
6935 break;
6936
6937 // Every per-entry directive shares the `.amdgpu_` namespace prefix; strip
6938 // it once and dispatch on the distinguishing suffix below. The unstripped
6939 // ID is preserved for diagnostics.
6940 StringRef Dir = ID;
6941 if (!Dir.consume_front(".amdgpu_"))
6942 return Error(IDLoc, "unknown .amdgpu_info directive '" + ID + "'");
6943
6944 if (Dir == "flags") {
6945 int64_t Val;
6946 if (getParser().parseAbsoluteExpression(Val))
6947 return true;
6948 auto Flags = static_cast<AMDGPU::FuncInfoFlags>(Val);
6949 FI.UsesVCC = !!(Flags & AMDGPU::FuncInfoFlags::FUNC_USES_VCC);
6950 FI.UsesFlatScratch =
6951 !!(Flags & AMDGPU::FuncInfoFlags::FUNC_USES_FLAT_SCRATCH);
6952 FI.HasDynStack = !!(Flags & AMDGPU::FuncInfoFlags::FUNC_HAS_DYN_STACK);
6953 HasScalarAttrs = true;
6954 } else if (Dir == "num_sgpr") {
6955 int64_t Val;
6956 if (getParser().parseAbsoluteExpression(Val))
6957 return true;
6958 FI.NumSGPR = static_cast<uint32_t>(Val);
6959 HasScalarAttrs = true;
6960 } else if (Dir == "num_vgpr") {
6961 int64_t Val;
6962 if (getParser().parseAbsoluteExpression(Val))
6963 return true;
6964 FI.NumArchVGPR = static_cast<uint32_t>(Val);
6965 HasScalarAttrs = true;
6966 } else if (Dir == "num_agpr") {
6967 int64_t Val;
6968 if (getParser().parseAbsoluteExpression(Val))
6969 return true;
6970 FI.NumAccVGPR = static_cast<uint32_t>(Val);
6971 HasScalarAttrs = true;
6972 } else if (Dir == "private_segment_size") {
6973 int64_t Val;
6974 if (getParser().parseAbsoluteExpression(Val))
6975 return true;
6976 FI.PrivateSegmentSize = static_cast<uint32_t>(Val);
6977 HasScalarAttrs = true;
6978 } else if (Dir == "use") {
6979 StringRef ResName;
6980 if (getParser().parseIdentifier(ResName))
6981 return TokError("expected resource symbol for .amdgpu_use");
6982 ParsedInfoData.Uses.push_back(
6983 {FuncSym, getContext().getOrCreateSymbol(ResName)});
6984 } else if (Dir == "call") {
6985 StringRef DstName;
6986 if (getParser().parseIdentifier(DstName))
6987 return TokError("expected callee symbol for .amdgpu_call");
6988 ParsedInfoData.Calls.push_back(
6989 {FuncSym, getContext().getOrCreateSymbol(DstName)});
6990 } else if (Dir == "indirect_call") {
6991 std::string TypeId;
6992 if (getParser().parseEscapedString(TypeId))
6993 return TokError("expected type ID string for .amdgpu_indirect_call");
6994 ParsedInfoData.IndirectCalls.push_back({FuncSym, std::move(TypeId)});
6995 } else if (Dir == "typeid") {
6996 std::string TypeId;
6997 if (getParser().parseEscapedString(TypeId))
6998 return TokError("expected type ID string for .amdgpu_typeid");
6999 ParsedInfoData.TypeIds.push_back({FuncSym, std::move(TypeId)});
7000 } else {
7001 return Error(IDLoc, "unknown .amdgpu_info directive '" + ID + "'");
7002 }
7003 }
7004
7005 if (HasScalarAttrs)
7006 ParsedInfoData.Funcs.push_back(std::move(FI));
7007
7008 AMDGPU::InfoSectionData &Data = InfoData ? *InfoData : InfoData.emplace();
7009 for (AMDGPU::FuncInfo &Func : ParsedInfoData.Funcs)
7010 Data.Funcs.push_back(std::move(Func));
7011 for (std::pair<MCSymbol *, MCSymbol *> &Use : ParsedInfoData.Uses)
7012 Data.Uses.push_back(Use);
7013 for (std::pair<MCSymbol *, MCSymbol *> &Call : ParsedInfoData.Calls)
7014 Data.Calls.push_back(Call);
7015 for (std::pair<MCSymbol *, std::string> &IndirectCall :
7016 ParsedInfoData.IndirectCalls)
7017 Data.IndirectCalls.push_back(std::move(IndirectCall));
7018 for (std::pair<MCSymbol *, std::string> &TypeId : ParsedInfoData.TypeIds)
7019 Data.TypeIds.push_back(std::move(TypeId));
7020
7021 return false;
7022}
7023
7024void AMDGPUAsmParser::doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) {
7025 // Record every parsed label in the timeline so that, at end of file, the
7026 // instructions following a kernel's label can be located regardless of
7027 // whether the .amdhsa_kernel directive came before or after the label.
7028 OpcodeStreamSymbols.emplace_back(Symbol, IDLoc, OpcodeStream.size());
7029}
7030
7031void AMDGPUAsmParser::checkKernelPrologues() {
7032 if (getFeatureBits()[AMDGPU::FeatureRequiresInitialUnclausedVmem]) {
7033 static const unsigned Required[] = {S_MOV_B64_gfx12, V_NOP_e32_gfx12,
7034 GLOBAL_PREFETCH_B8_SADDR_gfx1250};
7035 for (auto [Sym, Loc, Offset] : OpcodeStreamSymbols) {
7036 if (!AMDHSAKernelSymbols.contains(Sym))
7037 continue;
7038 ArrayRef<unsigned> Prologue = ArrayRef(OpcodeStream).drop_front(Offset);
7039 if (!Prologue.empty() && Prologue.front() == S_SETREG_IMM32_B32_gfx12)
7040 Prologue = Prologue.drop_front();
7041 if (Prologue.take_front(std::size(Required)) != ArrayRef(Required)) {
7042 Warning(Loc, "kernel '" + Sym->getName() +
7043 "' does not begin with the required prologue "
7044 "sequence: s_mov_b64 followed by v_nop and "
7045 "global_prefetch_b8");
7046 }
7047 }
7048 }
7049 OpcodeStream.clear();
7050 OpcodeStreamSymbols.clear();
7051 AMDHSAKernelSymbols.clear();
7052}
7053
7054void AMDGPUAsmParser::onEndOfFile() {
7055 emitTargetDirective();
7056 checkKernelPrologues();
7057 if (InfoData)
7058 getTargetStreamer().emitAMDGPUInfo(*InfoData);
7059}
7060
7061bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
7062 StringRef IDVal = DirectiveID.getString();
7063
7064 if (isHsaAbi(getSTI())) {
7065 if (IDVal == ".amdhsa_kernel")
7066 return ParseDirectiveAMDHSAKernel();
7067
7068 if (IDVal == ".amdhsa_code_object_version")
7069 return ParseDirectiveAMDHSACodeObjectVersion();
7070
7071 // TODO: Restructure/combine with PAL metadata directive.
7073 return ParseDirectiveHSAMetadata();
7074 } else {
7075 if (IDVal == ".amd_kernel_code_t")
7076 return ParseDirectiveAMDKernelCodeT();
7077
7078 if (IDVal == ".amdgpu_hsa_kernel")
7079 return ParseDirectiveAMDGPUHsaKernel();
7080
7081 if (IDVal == ".amd_amdgpu_isa")
7082 return ParseDirectiveISAVersion();
7083
7085 return Error(getLoc(), (Twine(HSAMD::AssemblerDirectiveBegin) +
7086 Twine(" directive is "
7087 "not available on non-amdhsa OSes"))
7088 .str());
7089 }
7090 }
7091
7092 if (IDVal == ".amdgcn_target")
7093 return ParseDirectiveAMDGCNTarget();
7094
7095 if (IDVal == ".amdgpu_lds")
7096 return ParseDirectiveAMDGPULDS();
7097
7098 if (IDVal == ".amdgpu_info")
7099 return ParseDirectiveAMDGPUInfo();
7100
7101 if (IDVal == PALMD::AssemblerDirectiveBegin)
7102 return ParseDirectivePALMetadataBegin();
7103
7104 if (IDVal == PALMD::AssemblerDirective)
7105 return ParseDirectivePALMetadata();
7106
7107 return true;
7108}
7109
7110bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
7111 MCRegister Reg) {
7112 if (MRI.regsOverlap(TTMP12_TTMP13_TTMP14_TTMP15, Reg))
7113 return isGFX9Plus();
7114
7115 // GFX10+ has 2 more SGPRs 104 and 105.
7116 if (MRI.regsOverlap(SGPR104_SGPR105, Reg))
7117 return hasSGPR104_SGPR105();
7118
7119 switch (Reg.id()) {
7120 case SRC_SHARED_BASE_LO:
7121 case SRC_SHARED_BASE:
7122 case SRC_SHARED_LIMIT_LO:
7123 case SRC_SHARED_LIMIT:
7124 return isGFX9Plus();
7125 case SRC_PRIVATE_BASE_LO:
7126 case SRC_PRIVATE_BASE:
7127 case SRC_PRIVATE_LIMIT_LO:
7128 case SRC_PRIVATE_LIMIT:
7129 return AMDGPU::hasPrivateApertureRegs(getSTI());
7130 case SRC_FLAT_SCRATCH_BASE_LO:
7131 case SRC_FLAT_SCRATCH_BASE_HI:
7132 return hasGloballyAddressableScratch();
7133 case SRC_POPS_EXITING_WAVE_ID:
7134 return hasPopsExitingWaveID(getSTI());
7135 case TBA:
7136 case TBA_LO:
7137 case TBA_HI:
7138 case TMA:
7139 case TMA_LO:
7140 case TMA_HI:
7141 return !isGFX9Plus();
7142 case XNACK_MASK:
7143 case XNACK_MASK_LO:
7144 case XNACK_MASK_HI:
7145 return (isVI() || isGFX9()) &&
7146 getTargetStreamer().getTargetID()->isXnackSupported();
7147 case SGPR_NULL:
7148 return isGFX10Plus();
7149 case SRC_EXECZ:
7150 case SRC_VCCZ:
7151 return !isGFX11Plus();
7152 default:
7153 break;
7154 }
7155
7156 if (isCI())
7157 return true;
7158
7159 if (isSI() || isGFX10Plus()) {
7160 // No flat_scr on SI.
7161 // On GFX10Plus flat scratch is not a valid register operand and can only be
7162 // accessed with s_setreg/s_getreg.
7163 switch (Reg.id()) {
7164 case FLAT_SCR:
7165 case FLAT_SCR_LO:
7166 case FLAT_SCR_HI:
7167 return false;
7168 default:
7169 return true;
7170 }
7171 }
7172
7173 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
7174 // SI/CI have.
7175 if (MRI.regsOverlap(SGPR102_SGPR103, Reg))
7176 return hasSGPR102_SGPR103();
7177
7178 return true;
7179}
7180
7181ParseStatus AMDGPUAsmParser::parseOperand(OperandVector &Operands,
7182 StringRef Mnemonic,
7183 OperandMode Mode) {
7184 ParseStatus Res = parseVOPD(Operands);
7185 if (Res.isSuccess() || Res.isFailure() || isToken(AsmToken::EndOfStatement))
7186 return Res;
7187
7188 // Try to parse with a custom parser
7189 Res = MatchOperandParserImpl(Operands, Mnemonic);
7190
7191 // If we successfully parsed the operand or if there as an error parsing,
7192 // we are done.
7193 //
7194 // If we are parsing after we reach EndOfStatement then this means we
7195 // are appending default values to the Operands list. This is only done
7196 // by custom parser, so we shouldn't continue on to the generic parsing.
7197 if (Res.isSuccess() || Res.isFailure() || isToken(AsmToken::EndOfStatement))
7198 return Res;
7199
7200 SMLoc RBraceLoc;
7201 SMLoc LBraceLoc = getLoc();
7202 if (Mode == OperandMode_NSA && trySkipToken(AsmToken::LBrac)) {
7203 unsigned Prefix = Operands.size();
7204
7205 for (;;) {
7206 auto Loc = getLoc();
7207 Res = parseReg(Operands);
7208 if (Res.isNoMatch())
7209 Error(Loc, "expected a register");
7210 if (!Res.isSuccess())
7211 return ParseStatus::Failure;
7212
7213 RBraceLoc = getLoc();
7214 if (trySkipToken(AsmToken::RBrac))
7215 break;
7216
7217 if (!skipToken(AsmToken::Comma,
7218 "expected a comma or a closing square bracket"))
7219 return ParseStatus::Failure;
7220 }
7221
7222 if (Operands.size() - Prefix > 1) {
7223 Operands.insert(Operands.begin() + Prefix,
7224 AMDGPUOperand::CreateToken(this, "[", LBraceLoc));
7225 Operands.push_back(AMDGPUOperand::CreateToken(this, "]", RBraceLoc));
7226 }
7227
7228 return ParseStatus::Success;
7229 }
7230
7231 return parseRegOrImm(Operands);
7232}
7233
7234StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
7235 // Clear any forced encodings from the previous instruction.
7236 setForcedEncodingSize(0);
7237 setForcedDPP(false);
7238 setForcedSDWA(false);
7239
7240 if (Name.consume_back("_e64_dpp")) {
7241 setForcedDPP(true);
7242 setForcedEncodingSize(64);
7243 return Name;
7244 }
7245 if (Name.consume_back("_e64")) {
7246 setForcedEncodingSize(64);
7247 return Name;
7248 }
7249 if (Name.consume_back("_e32")) {
7250 setForcedEncodingSize(32);
7251 return Name;
7252 }
7253 if (Name.consume_back("_dpp")) {
7254 setForcedDPP(true);
7255 return Name;
7256 }
7257 if (Name.consume_back("_sdwa")) {
7258 setForcedSDWA(true);
7259 return Name;
7260 }
7261 return Name;
7262}
7263
7264static void applyMnemonicAliases(StringRef &Mnemonic,
7265 const FeatureBitset &Features,
7266 unsigned VariantID);
7267
7268bool AMDGPUAsmParser::parseInstruction(ParseInstructionInfo &Info,
7269 StringRef Name, SMLoc NameLoc,
7271 // Add the instruction mnemonic
7272 Name = parseMnemonicSuffix(Name);
7273
7274 // If the target architecture uses MnemonicAlias, call it here to parse
7275 // operands correctly.
7276 applyMnemonicAliases(Name, getAvailableFeatures(), 0);
7277
7278 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc));
7279
7280 bool IsMIMG = Name.starts_with("image_");
7281
7282 while (!trySkipToken(AsmToken::EndOfStatement)) {
7283 OperandMode Mode = OperandMode_Default;
7284 if (IsMIMG && isGFX10Plus() && Operands.size() == 2)
7285 Mode = OperandMode_NSA;
7286 ParseStatus Res = parseOperand(Operands, Name, Mode);
7287
7288 if (!Res.isSuccess()) {
7289 checkUnsupportedInstruction(Name, NameLoc);
7290 if (!Parser.hasPendingError()) {
7291 // FIXME: use real operand location rather than the current location.
7292 StringRef Msg = Res.isFailure() ? "failed parsing operand."
7293 : "not a valid operand.";
7294 Error(getLoc(), Msg);
7295 }
7296 while (!trySkipToken(AsmToken::EndOfStatement)) {
7297 lex();
7298 }
7299 return true;
7300 }
7301
7302 // Eat the comma or space if there is one.
7303 trySkipToken(AsmToken::Comma);
7304 }
7305
7306 return false;
7307}
7308
7309//===----------------------------------------------------------------------===//
7310// Utility functions
7311//===----------------------------------------------------------------------===//
7312
7313ParseStatus AMDGPUAsmParser::parseTokenOp(StringRef Name,
7315 SMLoc S = getLoc();
7316 if (!trySkipId(Name))
7317 return ParseStatus::NoMatch;
7318
7319 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, S));
7320 return ParseStatus::Success;
7321}
7322
7323ParseStatus AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix,
7324 int64_t &IntVal) {
7325
7326 if (!trySkipId(Prefix, AsmToken::Colon))
7327 return ParseStatus::NoMatch;
7328
7330}
7331
7332ParseStatus AMDGPUAsmParser::parseIntWithPrefix(
7333 const char *Prefix, OperandVector &Operands, AMDGPUOperand::ImmTy ImmTy,
7334 std::function<bool(int64_t &)> ConvertResult) {
7335 SMLoc S = getLoc();
7336 int64_t Value = 0;
7337
7338 ParseStatus Res = parseIntWithPrefix(Prefix, Value);
7339 if (!Res.isSuccess())
7340 return Res;
7341
7342 if (ConvertResult && !ConvertResult(Value)) {
7343 Error(S, "invalid " + StringRef(Prefix) + " value.");
7344 }
7345
7346 Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy));
7347 return ParseStatus::Success;
7348}
7349
7350ParseStatus AMDGPUAsmParser::parseOperandArrayWithPrefix(
7351 const char *Prefix, OperandVector &Operands, AMDGPUOperand::ImmTy ImmTy,
7352 bool (*ConvertResult)(int64_t &)) {
7353 SMLoc S = getLoc();
7354 if (!trySkipId(Prefix, AsmToken::Colon))
7355 return ParseStatus::NoMatch;
7356
7357 if (!skipToken(AsmToken::LBrac, "expected a left square bracket"))
7358 return ParseStatus::Failure;
7359
7360 unsigned Val = 0;
7361 const unsigned MaxSize = 4;
7362
7363 // FIXME: How to verify the number of elements matches the number of src
7364 // operands?
7365 for (int I = 0;; ++I) {
7366 int64_t Op;
7367 SMLoc Loc = getLoc();
7368 if (!parseExpr(Op))
7369 return ParseStatus::Failure;
7370
7371 if (Op != 0 && Op != 1)
7372 return Error(Loc, "invalid " + StringRef(Prefix) + " value.");
7373
7374 Val |= (Op << I);
7375
7376 if (trySkipToken(AsmToken::RBrac))
7377 break;
7378
7379 if (I + 1 == MaxSize)
7380 return Error(getLoc(), "expected a closing square bracket");
7381
7382 if (!skipToken(AsmToken::Comma, "expected a comma"))
7383 return ParseStatus::Failure;
7384 }
7385
7386 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, ImmTy));
7387 return ParseStatus::Success;
7388}
7389
7390ParseStatus AMDGPUAsmParser::parseNamedBit(StringRef Name,
7392 AMDGPUOperand::ImmTy ImmTy,
7393 bool IgnoreNegative) {
7394 int64_t Bit;
7395 SMLoc S = getLoc();
7396
7397 if (trySkipId(Name)) {
7398 Bit = 1;
7399 } else if (trySkipId("no", Name)) {
7400 if (IgnoreNegative)
7401 return ParseStatus::Success;
7402 Bit = 0;
7403 } else {
7404 return ParseStatus::NoMatch;
7405 }
7406
7407 if (Name == "r128" && !hasMIMG_R128())
7408 return Error(S, "r128 modifier is not supported on this GPU");
7409 if (Name == "a16" && !hasA16())
7410 return Error(S, "a16 modifier is not supported on this GPU");
7411
7412 if (Bit == 0 && Name == "gds") {
7413 StringRef Mnemo = ((AMDGPUOperand &)*Operands[0]).getToken();
7414 if (Mnemo.starts_with("ds_gws"))
7415 return Error(S, "nogds is not allowed");
7416 }
7417
7418 if (isGFX9() && ImmTy == AMDGPUOperand::ImmTyA16)
7419 ImmTy = AMDGPUOperand::ImmTyR128A16;
7420
7421 Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy));
7422 return ParseStatus::Success;
7423}
7424
7425unsigned AMDGPUAsmParser::getCPolKind(StringRef Id, StringRef Mnemo,
7426 bool &Disabling) const {
7427 Disabling = Id.consume_front("no");
7428
7429 if (isGFX940() && !Mnemo.starts_with("s_")) {
7430 return StringSwitch<unsigned>(Id)
7431 .Case("nt", AMDGPU::CPol::NT)
7432 .Case("sc0", AMDGPU::CPol::SC0)
7433 .Case("sc1", AMDGPU::CPol::SC1)
7434 .Default(0);
7435 }
7436
7437 return StringSwitch<unsigned>(Id)
7438 .Case("dlc", AMDGPU::CPol::DLC)
7439 .Case("glc", AMDGPU::CPol::GLC)
7440 .Case("scc", AMDGPU::CPol::SCC)
7441 .Case("slc", AMDGPU::CPol::SLC)
7442 .Default(0);
7443}
7444
7445ParseStatus AMDGPUAsmParser::parseCPol(OperandVector &Operands) {
7446 if (isGFX12Plus()) {
7447 SMLoc StringLoc = getLoc();
7448
7449 int64_t CPolVal = 0;
7450 ParseStatus ResTH = ParseStatus::NoMatch;
7451 ParseStatus ResScope = ParseStatus::NoMatch;
7452 ParseStatus ResNV = ParseStatus::NoMatch;
7453 ParseStatus ResScal = ParseStatus::NoMatch;
7454 ParseStatus ResCFS = ParseStatus::NoMatch;
7455
7456 for (;;) {
7457 if (ResTH.isNoMatch()) {
7458 int64_t TH;
7459 ResTH = parseTH(Operands, TH);
7460 if (ResTH.isFailure())
7461 return ResTH;
7462 if (ResTH.isSuccess()) {
7463 CPolVal |= TH;
7464 continue;
7465 }
7466 }
7467
7468 if (ResScope.isNoMatch()) {
7469 int64_t Scope;
7470 ResScope = parseScope(Operands, Scope);
7471 if (ResScope.isFailure())
7472 return ResScope;
7473 if (ResScope.isSuccess()) {
7474 CPolVal |= Scope;
7475 continue;
7476 }
7477 }
7478
7479 // NV bit exists on GFX12+, but does something starting from GFX1250.
7480 // Allow parsing on all GFX12 and fail on validation for better
7481 // diagnostics.
7482 if (ResNV.isNoMatch()) {
7483 if (trySkipId("nv")) {
7484 ResNV = ParseStatus::Success;
7485 CPolVal |= CPol::NV;
7486 continue;
7487 } else if (trySkipId("no", "nv")) {
7488 ResNV = ParseStatus::Success;
7489 continue;
7490 }
7491 }
7492
7493 if (ResScal.isNoMatch()) {
7494 if (trySkipId("scale_offset")) {
7495 ResScal = ParseStatus::Success;
7496 CPolVal |= CPol::SCAL;
7497 continue;
7498 } else if (trySkipId("no", "scale_offset")) {
7499 ResScal = ParseStatus::Success;
7500 continue;
7501 }
7502 }
7503
7504 if (ResCFS.isNoMatch()) {
7505 int64_t CFS;
7506 ResCFS = parseCFS(Operands, CFS);
7507 if (ResCFS.isFailure())
7508 return ResCFS;
7509 if (ResCFS.isSuccess()) {
7510 CPolVal |= CFS;
7511 continue;
7512 }
7513 }
7514
7515 break;
7516 }
7517
7518 if (ResTH.isNoMatch() && ResScope.isNoMatch() && ResNV.isNoMatch() &&
7519 ResScal.isNoMatch() && ResCFS.isNoMatch())
7520 return ParseStatus::NoMatch;
7521
7522 Operands.push_back(AMDGPUOperand::CreateImm(this, CPolVal, StringLoc,
7523 AMDGPUOperand::ImmTyCPol));
7524 return ParseStatus::Success;
7525 }
7526
7527 StringRef Mnemo = ((AMDGPUOperand &)*Operands[0]).getToken();
7528 SMLoc OpLoc = getLoc();
7529 unsigned Enabled = 0, Seen = 0;
7530 for (;;) {
7531 SMLoc S = getLoc();
7532 bool Disabling;
7533 unsigned CPol = getCPolKind(getId(), Mnemo, Disabling);
7534 if (!CPol)
7535 break;
7536
7537 lex();
7538
7539 if (!isGFX10Plus() && CPol == AMDGPU::CPol::DLC)
7540 return Error(S, "dlc modifier is not supported on this GPU");
7541
7542 if (!isGFX90A() && CPol == AMDGPU::CPol::SCC)
7543 return Error(S, "scc modifier is not supported on this GPU");
7544
7545 if (Seen & CPol)
7546 return Error(S, "duplicate cache policy modifier");
7547
7548 if (!Disabling)
7549 Enabled |= CPol;
7550
7551 Seen |= CPol;
7552 }
7553
7554 if (!Seen)
7555 return ParseStatus::NoMatch;
7556
7557 Operands.push_back(
7558 AMDGPUOperand::CreateImm(this, Enabled, OpLoc, AMDGPUOperand::ImmTyCPol));
7559 return ParseStatus::Success;
7560}
7561
7562ParseStatus AMDGPUAsmParser::parseScope(OperandVector &Operands,
7563 int64_t &Scope) {
7564 static const unsigned Scopes[] = {CPol::SCOPE_CU, CPol::SCOPE_SE,
7566
7567 ParseStatus Res = parseStringOrIntWithPrefix(
7568 Operands, "scope", {"SCOPE_CU", "SCOPE_SE", "SCOPE_DEV", "SCOPE_SYS"},
7569 Scope);
7570
7571 if (Res.isSuccess())
7572 Scope = Scopes[Scope];
7573
7574 return Res;
7575}
7576
7577ParseStatus AMDGPUAsmParser::parseTH(OperandVector &Operands, int64_t &TH) {
7578 TH = AMDGPU::CPol::TH_RT; // default
7579
7580 StringRef Value;
7581 SMLoc StringLoc;
7582 ParseStatus Res = parseStringWithPrefix("th", Value, StringLoc);
7583 if (!Res.isSuccess())
7584 return Res;
7585
7586 if (Value == "TH_DEFAULT")
7588 else if (Value == "TH_STORE_LU" || Value == "TH_LOAD_WB" ||
7589 Value == "TH_LOAD_NT_WB") {
7590 return Error(StringLoc, "invalid th value");
7591 } else if (Value.consume_front("TH_ATOMIC_")) {
7593 } else if (Value.consume_front("TH_LOAD_")) {
7595 } else if (Value.consume_front("TH_STORE_")) {
7597 } else {
7598 return Error(StringLoc, "invalid th value");
7599 }
7600
7601 if (Value == "BYPASS")
7603
7604 if (TH != 0) {
7606 TH |= StringSwitch<int64_t>(Value)
7607 .Case("RETURN", AMDGPU::CPol::TH_ATOMIC_RETURN)
7608 .Case("RT", AMDGPU::CPol::TH_RT)
7609 .Case("RT_RETURN", AMDGPU::CPol::TH_ATOMIC_RETURN)
7610 .Case("NT", AMDGPU::CPol::TH_ATOMIC_NT)
7611 .Case("NT_RETURN", AMDGPU::CPol::TH_ATOMIC_NT |
7613 .Case("CASCADE_RT", AMDGPU::CPol::TH_ATOMIC_CASCADE)
7614 .Case("CASCADE_NT", AMDGPU::CPol::TH_ATOMIC_CASCADE |
7616 .Default(0xffffffff);
7617 else
7618 TH |= StringSwitch<int64_t>(Value)
7619 .Case("RT", AMDGPU::CPol::TH_RT)
7620 .Case("NT", AMDGPU::CPol::TH_NT)
7621 .Case("HT", AMDGPU::CPol::TH_HT)
7622 .Case("LU", AMDGPU::CPol::TH_LU)
7623 .Case("WB", AMDGPU::CPol::TH_WB)
7624 .Case("NT_RT", AMDGPU::CPol::TH_NT_RT)
7625 .Case("RT_NT", AMDGPU::CPol::TH_RT_NT)
7626 .Case("NT_HT", AMDGPU::CPol::TH_NT_HT)
7627 .Case("NT_WB", AMDGPU::CPol::TH_NT_WB)
7628 .Case("BYPASS", AMDGPU::CPol::TH_BYPASS)
7629 .Default(0xffffffff);
7630 }
7631
7632 if (TH == 0xffffffff)
7633 return Error(StringLoc, "invalid th value");
7634
7635 return ParseStatus::Success;
7636}
7637
7638ParseStatus AMDGPUAsmParser::parseCFS(OperandVector &Operands, int64_t &CFS) {
7639 static const unsigned CFSVals[] = {CPol::CFS_256B, CPol::CFS_128B,
7641
7642 ParseStatus Res = parseStringOrIntWithPrefix(
7643 Operands, "cfs", {"CFS_256B", "CFS_128B", "CFS_64B", "CFS_32B"}, CFS);
7644
7645 if (Res.isSuccess())
7646 CFS = CFSVals[CFS];
7647
7648 return Res;
7649}
7650
7651static void
7653 AMDGPUAsmParser::OptionalImmIndexMap &OptionalIdx,
7654 AMDGPUOperand::ImmTy ImmT, int64_t Default = 0,
7655 std::optional<unsigned> InsertAt = std::nullopt) {
7656 auto i = OptionalIdx.find(ImmT);
7657 if (i != OptionalIdx.end()) {
7658 unsigned Idx = i->second;
7659 const AMDGPUOperand &Op =
7660 static_cast<const AMDGPUOperand &>(*Operands[Idx]);
7661 if (InsertAt)
7662 Inst.insert(Inst.begin() + *InsertAt, MCOperand::createImm(Op.getImm()));
7663 else
7664 Op.addImmOperands(Inst, 1);
7665 } else {
7666 if (InsertAt.has_value())
7667 Inst.insert(Inst.begin() + *InsertAt, MCOperand::createImm(Default));
7668 else
7670 }
7671}
7672
7673ParseStatus AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix,
7674 StringRef &Value,
7675 SMLoc &StringLoc) {
7676 if (!trySkipId(Prefix, AsmToken::Colon))
7677 return ParseStatus::NoMatch;
7678
7679 StringLoc = getLoc();
7680 return parseId(Value, "expected an identifier") ? ParseStatus::Success
7682}
7683
7684ParseStatus AMDGPUAsmParser::parseStringOrIntWithPrefix(
7685 OperandVector &Operands, StringRef Name, ArrayRef<const char *> Ids,
7686 int64_t &IntVal) {
7687 if (!trySkipId(Name, AsmToken::Colon))
7688 return ParseStatus::NoMatch;
7689
7690 SMLoc StringLoc = getLoc();
7691
7692 StringRef Value;
7693 if (isToken(AsmToken::Identifier)) {
7694 Value = getTokenStr();
7695 lex();
7696
7697 for (IntVal = 0; IntVal < (int64_t)Ids.size(); ++IntVal)
7698 if (Value == Ids[IntVal])
7699 break;
7700 } else if (!parseExpr(IntVal))
7701 return ParseStatus::Failure;
7702
7703 if (IntVal < 0 || IntVal >= (int64_t)Ids.size())
7704 return Error(StringLoc, "invalid " + Twine(Name) + " value");
7705
7706 return ParseStatus::Success;
7707}
7708
7709ParseStatus AMDGPUAsmParser::parseStringOrIntWithPrefix(
7710 OperandVector &Operands, StringRef Name, ArrayRef<const char *> Ids,
7711 AMDGPUOperand::ImmTy Type) {
7712 SMLoc S = getLoc();
7713 int64_t IntVal;
7714
7715 ParseStatus Res = parseStringOrIntWithPrefix(Operands, Name, Ids, IntVal);
7716 if (Res.isSuccess())
7717 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S, Type));
7718
7719 return Res;
7720}
7721
7722//===----------------------------------------------------------------------===//
7723// MTBUF format
7724//===----------------------------------------------------------------------===//
7725
7726bool AMDGPUAsmParser::tryParseFmt(const char *Pref, int64_t MaxVal,
7727 int64_t &Fmt) {
7728 int64_t Val;
7729 SMLoc Loc = getLoc();
7730
7731 auto Res = parseIntWithPrefix(Pref, Val);
7732 if (Res.isFailure())
7733 return false;
7734 if (Res.isNoMatch())
7735 return true;
7736
7737 if (Val < 0 || Val > MaxVal) {
7738 Error(Loc, Twine("out of range ", StringRef(Pref)));
7739 return false;
7740 }
7741
7742 Fmt = Val;
7743 return true;
7744}
7745
7746ParseStatus AMDGPUAsmParser::tryParseIndexKey(OperandVector &Operands,
7747 AMDGPUOperand::ImmTy ImmTy) {
7748 const char *Pref = "index_key";
7749 int64_t ImmVal = 0;
7750 SMLoc Loc = getLoc();
7751 auto Res = parseIntWithPrefix(Pref, ImmVal);
7752 if (!Res.isSuccess())
7753 return Res;
7754
7755 if ((ImmTy == AMDGPUOperand::ImmTyIndexKey16bit ||
7756 ImmTy == AMDGPUOperand::ImmTyIndexKey32bit) &&
7757 (ImmVal < 0 || ImmVal > 1))
7758 return Error(Loc, Twine("out of range ", StringRef(Pref)));
7759
7760 if (ImmTy == AMDGPUOperand::ImmTyIndexKey8bit && (ImmVal < 0 || ImmVal > 3))
7761 return Error(Loc, Twine("out of range ", StringRef(Pref)));
7762
7763 Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc, ImmTy));
7764 return ParseStatus::Success;
7765}
7766
7767ParseStatus AMDGPUAsmParser::parseIndexKey8bit(OperandVector &Operands) {
7768 return tryParseIndexKey(Operands, AMDGPUOperand::ImmTyIndexKey8bit);
7769}
7770
7771ParseStatus AMDGPUAsmParser::parseIndexKey16bit(OperandVector &Operands) {
7772 return tryParseIndexKey(Operands, AMDGPUOperand::ImmTyIndexKey16bit);
7773}
7774
7775ParseStatus AMDGPUAsmParser::parseIndexKey32bit(OperandVector &Operands) {
7776 return tryParseIndexKey(Operands, AMDGPUOperand::ImmTyIndexKey32bit);
7777}
7778
7779ParseStatus AMDGPUAsmParser::tryParseMatrixFMT(OperandVector &Operands,
7780 StringRef Name,
7781 AMDGPUOperand::ImmTy Type) {
7782 return parseStringOrIntWithPrefix(Operands, Name, WMMAMods::ModMatrixFmt,
7783 Type);
7784}
7785
7786ParseStatus AMDGPUAsmParser::parseMatrixAFMT(OperandVector &Operands) {
7787 return tryParseMatrixFMT(Operands, "matrix_a_fmt",
7788 AMDGPUOperand::ImmTyMatrixAFMT);
7789}
7790
7791ParseStatus AMDGPUAsmParser::parseMatrixBFMT(OperandVector &Operands) {
7792 return tryParseMatrixFMT(Operands, "matrix_b_fmt",
7793 AMDGPUOperand::ImmTyMatrixBFMT);
7794}
7795
7796ParseStatus AMDGPUAsmParser::tryParseMatrixScale(OperandVector &Operands,
7797 StringRef Name,
7798 AMDGPUOperand::ImmTy Type) {
7799 return parseStringOrIntWithPrefix(Operands, Name, WMMAMods::ModMatrixScale,
7800 Type);
7801}
7802
7803ParseStatus AMDGPUAsmParser::parseMatrixAScale(OperandVector &Operands) {
7804 return tryParseMatrixScale(Operands, "matrix_a_scale",
7805 AMDGPUOperand::ImmTyMatrixAScale);
7806}
7807
7808ParseStatus AMDGPUAsmParser::parseMatrixBScale(OperandVector &Operands) {
7809 return tryParseMatrixScale(Operands, "matrix_b_scale",
7810 AMDGPUOperand::ImmTyMatrixBScale);
7811}
7812
7813ParseStatus AMDGPUAsmParser::tryParseMatrixScaleFmt(OperandVector &Operands,
7814 StringRef Name,
7815 AMDGPUOperand::ImmTy Type) {
7816 return parseStringOrIntWithPrefix(Operands, Name, WMMAMods::ModMatrixScaleFmt,
7817 Type);
7818}
7819
7820ParseStatus AMDGPUAsmParser::parseMatrixAScaleFmt(OperandVector &Operands) {
7821 return tryParseMatrixScaleFmt(Operands, "matrix_a_scale_fmt",
7822 AMDGPUOperand::ImmTyMatrixAScaleFmt);
7823}
7824
7825ParseStatus AMDGPUAsmParser::parseMatrixBScaleFmt(OperandVector &Operands) {
7826 return tryParseMatrixScaleFmt(Operands, "matrix_b_scale_fmt",
7827 AMDGPUOperand::ImmTyMatrixBScaleFmt);
7828}
7829
7830// dfmt and nfmt (in a tbuffer instruction) are parsed as one to allow their
7831// values to live in a joint format operand in the MCInst encoding.
7832ParseStatus AMDGPUAsmParser::parseDfmtNfmt(int64_t &Format) {
7833 using namespace llvm::AMDGPU::MTBUFFormat;
7834
7835 int64_t Dfmt = DFMT_UNDEF;
7836 int64_t Nfmt = NFMT_UNDEF;
7837
7838 // dfmt and nfmt can appear in either order, and each is optional.
7839 for (int I = 0; I < 2; ++I) {
7840 if (Dfmt == DFMT_UNDEF && !tryParseFmt("dfmt", DFMT_MAX, Dfmt))
7841 return ParseStatus::Failure;
7842
7843 if (Nfmt == NFMT_UNDEF && !tryParseFmt("nfmt", NFMT_MAX, Nfmt))
7844 return ParseStatus::Failure;
7845
7846 // Skip optional comma between dfmt/nfmt
7847 // but guard against 2 commas following each other.
7848 if ((Dfmt == DFMT_UNDEF) != (Nfmt == NFMT_UNDEF) &&
7849 !peekToken().is(AsmToken::Comma)) {
7850 trySkipToken(AsmToken::Comma);
7851 }
7852 }
7853
7854 if (Dfmt == DFMT_UNDEF && Nfmt == NFMT_UNDEF)
7855 return ParseStatus::NoMatch;
7856
7857 Dfmt = (Dfmt == DFMT_UNDEF) ? DFMT_DEFAULT : Dfmt;
7858 Nfmt = (Nfmt == NFMT_UNDEF) ? NFMT_DEFAULT : Nfmt;
7859
7860 Format = encodeDfmtNfmt(Dfmt, Nfmt);
7861 return ParseStatus::Success;
7862}
7863
7864ParseStatus AMDGPUAsmParser::parseUfmt(int64_t &Format) {
7865 using namespace llvm::AMDGPU::MTBUFFormat;
7866
7867 int64_t Fmt = UFMT_UNDEF;
7868
7869 if (!tryParseFmt("format", UFMT_MAX, Fmt))
7870 return ParseStatus::Failure;
7871
7872 if (Fmt == UFMT_UNDEF)
7873 return ParseStatus::NoMatch;
7874
7875 Format = Fmt;
7876 return ParseStatus::Success;
7877}
7878
7879bool AMDGPUAsmParser::matchDfmtNfmt(int64_t &Dfmt, int64_t &Nfmt,
7880 StringRef FormatStr, SMLoc Loc) {
7881 using namespace llvm::AMDGPU::MTBUFFormat;
7882 int64_t Format;
7883
7884 Format = getDfmt(FormatStr);
7885 if (Format != DFMT_UNDEF) {
7886 Dfmt = Format;
7887 return true;
7888 }
7889
7890 Format = getNfmt(FormatStr, getSTI());
7891 if (Format != NFMT_UNDEF) {
7892 Nfmt = Format;
7893 return true;
7894 }
7895
7896 Error(Loc, "unsupported format");
7897 return false;
7898}
7899
7900ParseStatus AMDGPUAsmParser::parseSymbolicSplitFormat(StringRef FormatStr,
7901 SMLoc FormatLoc,
7902 int64_t &Format) {
7903 using namespace llvm::AMDGPU::MTBUFFormat;
7904
7905 int64_t Dfmt = DFMT_UNDEF;
7906 int64_t Nfmt = NFMT_UNDEF;
7907 if (!matchDfmtNfmt(Dfmt, Nfmt, FormatStr, FormatLoc))
7908 return ParseStatus::Failure;
7909
7910 if (trySkipToken(AsmToken::Comma)) {
7911 StringRef Str;
7912 SMLoc Loc = getLoc();
7913 if (!parseId(Str, "expected a format string") ||
7914 !matchDfmtNfmt(Dfmt, Nfmt, Str, Loc))
7915 return ParseStatus::Failure;
7916 if (Dfmt == DFMT_UNDEF)
7917 return Error(Loc, "duplicate numeric format");
7918 if (Nfmt == NFMT_UNDEF)
7919 return Error(Loc, "duplicate data format");
7920 }
7921
7922 Dfmt = (Dfmt == DFMT_UNDEF) ? DFMT_DEFAULT : Dfmt;
7923 Nfmt = (Nfmt == NFMT_UNDEF) ? NFMT_DEFAULT : Nfmt;
7924
7925 if (isGFX10Plus()) {
7926 auto Ufmt = convertDfmtNfmt2Ufmt(Dfmt, Nfmt, getSTI());
7927 if (Ufmt == UFMT_UNDEF)
7928 return Error(FormatLoc, "unsupported format");
7929 Format = Ufmt;
7930 } else {
7931 Format = encodeDfmtNfmt(Dfmt, Nfmt);
7932 }
7933
7934 return ParseStatus::Success;
7935}
7936
7937ParseStatus AMDGPUAsmParser::parseSymbolicUnifiedFormat(StringRef FormatStr,
7938 SMLoc Loc,
7939 int64_t &Format) {
7940 using namespace llvm::AMDGPU::MTBUFFormat;
7941
7942 auto Id = getUnifiedFormat(FormatStr, getSTI());
7943 if (Id == UFMT_UNDEF)
7944 return ParseStatus::NoMatch;
7945
7946 if (!isGFX10Plus())
7947 return Error(Loc, "unified format is not supported on this GPU");
7948
7949 Format = Id;
7950 return ParseStatus::Success;
7951}
7952
7953ParseStatus AMDGPUAsmParser::parseNumericFormat(int64_t &Format) {
7954 using namespace llvm::AMDGPU::MTBUFFormat;
7955 SMLoc Loc = getLoc();
7956
7957 if (!parseExpr(Format))
7958 return ParseStatus::Failure;
7959 if (!isValidFormatEncoding(Format, getSTI()))
7960 return Error(Loc, "out of range format");
7961
7962 return ParseStatus::Success;
7963}
7964
7965ParseStatus AMDGPUAsmParser::parseSymbolicOrNumericFormat(int64_t &Format) {
7966 using namespace llvm::AMDGPU::MTBUFFormat;
7967
7968 if (!trySkipId("format", AsmToken::Colon))
7969 return ParseStatus::NoMatch;
7970
7971 if (trySkipToken(AsmToken::LBrac)) {
7972 StringRef FormatStr;
7973 SMLoc Loc = getLoc();
7974 if (!parseId(FormatStr, "expected a format string"))
7975 return ParseStatus::Failure;
7976
7977 auto Res = parseSymbolicUnifiedFormat(FormatStr, Loc, Format);
7978 if (Res.isNoMatch())
7979 Res = parseSymbolicSplitFormat(FormatStr, Loc, Format);
7980 if (!Res.isSuccess())
7981 return Res;
7982
7983 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket"))
7984 return ParseStatus::Failure;
7985
7986 return ParseStatus::Success;
7987 }
7988
7989 return parseNumericFormat(Format);
7990}
7991
7992ParseStatus AMDGPUAsmParser::parseFORMAT(OperandVector &Operands) {
7993 using namespace llvm::AMDGPU::MTBUFFormat;
7994
7995 int64_t Format = getDefaultFormatEncoding(getSTI());
7996 ParseStatus Res;
7997 SMLoc Loc = getLoc();
7998
7999 // Parse legacy format syntax.
8000 Res = isGFX10Plus() ? parseUfmt(Format) : parseDfmtNfmt(Format);
8001 if (Res.isFailure())
8002 return Res;
8003
8004 bool FormatFound = Res.isSuccess();
8005
8006 Operands.push_back(
8007 AMDGPUOperand::CreateImm(this, Format, Loc, AMDGPUOperand::ImmTyFORMAT));
8008
8009 if (FormatFound)
8010 trySkipToken(AsmToken::Comma);
8011
8012 if (isToken(AsmToken::EndOfStatement)) {
8013 // We are expecting an soffset operand,
8014 // but let matcher handle the error.
8015 return ParseStatus::Success;
8016 }
8017
8018 // Parse soffset.
8019 Res = parseRegOrImm(Operands);
8020 if (!Res.isSuccess())
8021 return Res;
8022
8023 trySkipToken(AsmToken::Comma);
8024
8025 if (!FormatFound) {
8026 Res = parseSymbolicOrNumericFormat(Format);
8027 if (Res.isFailure())
8028 return Res;
8029 if (Res.isSuccess()) {
8030 auto Size = Operands.size();
8031 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands[Size - 2]);
8032 assert(Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyFORMAT);
8033 Op.setImm(Format);
8034 }
8035 return ParseStatus::Success;
8036 }
8037
8038 if (isId("format") && peekToken().is(AsmToken::Colon))
8039 return Error(getLoc(), "duplicate format");
8040 return ParseStatus::Success;
8041}
8042
8043ParseStatus AMDGPUAsmParser::parseFlatOffset(OperandVector &Operands) {
8044 ParseStatus Res =
8045 parseIntWithPrefix("offset", Operands, AMDGPUOperand::ImmTyOffset);
8046 if (Res.isNoMatch()) {
8047 Res = parseIntWithPrefix("inst_offset", Operands,
8048 AMDGPUOperand::ImmTyInstOffset);
8049 }
8050 return Res;
8051}
8052
8053ParseStatus AMDGPUAsmParser::parseR128A16(OperandVector &Operands) {
8054 ParseStatus Res =
8055 parseNamedBit("r128", Operands, AMDGPUOperand::ImmTyR128A16);
8056 if (Res.isNoMatch())
8057 Res = parseNamedBit("a16", Operands, AMDGPUOperand::ImmTyA16);
8058 return Res;
8059}
8060
8061ParseStatus AMDGPUAsmParser::parseBLGP(OperandVector &Operands) {
8062 ParseStatus Res =
8063 parseIntWithPrefix("blgp", Operands, AMDGPUOperand::ImmTyBLGP);
8064 if (Res.isNoMatch()) {
8065 Res =
8066 parseOperandArrayWithPrefix("neg", Operands, AMDGPUOperand::ImmTyBLGP);
8067 }
8068 return Res;
8069}
8070
8071//===----------------------------------------------------------------------===//
8072// Exp
8073//===----------------------------------------------------------------------===//
8074
8075void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
8076 OptionalImmIndexMap OptionalIdx;
8077
8078 unsigned OperandIdx[4];
8079 unsigned EnMask = 0;
8080 int SrcIdx = 0;
8081
8082 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
8083 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
8084
8085 // Add the register arguments
8086 if (Op.isReg()) {
8087 assert(SrcIdx < 4);
8088 OperandIdx[SrcIdx] = Inst.size();
8089 Op.addRegOperands(Inst, 1);
8090 ++SrcIdx;
8091 continue;
8092 }
8093
8094 if (Op.isOff()) {
8095 assert(SrcIdx < 4);
8096 OperandIdx[SrcIdx] = Inst.size();
8097 Inst.addOperand(MCOperand::createReg(MCRegister()));
8098 ++SrcIdx;
8099 continue;
8100 }
8101
8102 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) {
8103 Op.addImmOperands(Inst, 1);
8104 continue;
8105 }
8106
8107 if (Op.isToken() && (Op.getToken() == "done" || Op.getToken() == "row_en"))
8108 continue;
8109
8110 // Handle optional arguments
8111 OptionalIdx[Op.getImmTy()] = i;
8112 }
8113
8114 assert(SrcIdx == 4);
8115
8116 bool Compr = false;
8117 if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) {
8118 Compr = true;
8119 Inst.getOperand(OperandIdx[1]) = Inst.getOperand(OperandIdx[2]);
8120 Inst.getOperand(OperandIdx[2]).setReg(MCRegister());
8121 Inst.getOperand(OperandIdx[3]).setReg(MCRegister());
8122 }
8123
8124 for (auto i = 0; i < SrcIdx; ++i) {
8125 if (Inst.getOperand(OperandIdx[i]).getReg()) {
8126 EnMask |= Compr ? (0x3 << i * 2) : (0x1 << i);
8127 }
8128 }
8129
8130 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM);
8131 addOptionalImmOperand(Inst, Operands, OptionalIdx,
8132 AMDGPUOperand::ImmTyExpCompr);
8133
8134 Inst.addOperand(MCOperand::createImm(EnMask));
8135}
8136
8137//===----------------------------------------------------------------------===//
8138// s_waitcnt
8139//===----------------------------------------------------------------------===//
8140
8141static bool encodeCnt(const AMDGPU::IsaVersion ISA, int64_t &IntVal,
8142 int64_t CntVal, bool Saturate,
8143 unsigned (*encode)(const IsaVersion &Version, unsigned,
8144 unsigned),
8145 unsigned (*decode)(const IsaVersion &Version, unsigned)) {
8146 bool Failed = false;
8147
8148 IntVal = encode(ISA, IntVal, CntVal);
8149 if (CntVal != decode(ISA, IntVal)) {
8150 if (Saturate) {
8151 IntVal = encode(ISA, IntVal, -1);
8152 } else {
8153 Failed = true;
8154 }
8155 }
8156 return Failed;
8157}
8158
8159bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
8160
8161 SMLoc CntLoc = getLoc();
8162 StringRef CntName = getTokenStr();
8163
8164 if (!skipToken(AsmToken::Identifier, "expected a counter name") ||
8165 !skipToken(AsmToken::LParen, "expected a left parenthesis"))
8166 return false;
8167
8168 int64_t CntVal;
8169 SMLoc ValLoc = getLoc();
8170 if (!parseExpr(CntVal))
8171 return false;
8172
8173 bool Failed = true;
8174 bool Sat = CntName.ends_with("_sat");
8175
8176 if (CntName == "vmcnt" || CntName == "vmcnt_sat") {
8177 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeVmcnt, decodeVmcnt);
8178 } else if (CntName == "expcnt" || CntName == "expcnt_sat") {
8179 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeExpcnt, decodeExpcnt);
8180 } else if (CntName == "lgkmcnt" || CntName == "lgkmcnt_sat") {
8181 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeLgkmcnt, decodeLgkmcnt);
8182 } else {
8183 Error(CntLoc, "invalid counter name " + CntName);
8184 return false;
8185 }
8186
8187 if (Failed) {
8188 Error(ValLoc, "too large value for " + CntName);
8189 return false;
8190 }
8191
8192 if (!skipToken(AsmToken::RParen, "expected a closing parenthesis"))
8193 return false;
8194
8195 if (trySkipToken(AsmToken::Amp) || trySkipToken(AsmToken::Comma)) {
8196 if (isToken(AsmToken::EndOfStatement)) {
8197 Error(getLoc(), "expected a counter name");
8198 return false;
8199 }
8200 }
8201
8202 return true;
8203}
8204
8205ParseStatus AMDGPUAsmParser::parseSWaitCnt(OperandVector &Operands) {
8206 int64_t Waitcnt = getWaitcntBitMask(ISA);
8207 SMLoc S = getLoc();
8208
8209 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) {
8210 while (!isToken(AsmToken::EndOfStatement)) {
8211 if (!parseCnt(Waitcnt))
8212 return ParseStatus::Failure;
8213 }
8214 } else {
8215 if (!parseExpr(Waitcnt))
8216 return ParseStatus::Failure;
8217 }
8218
8219 Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S));
8220 return ParseStatus::Success;
8221}
8222
8223bool AMDGPUAsmParser::parseDelay(int64_t &Delay) {
8224 SMLoc FieldLoc = getLoc();
8225 StringRef FieldName = getTokenStr();
8226 if (!skipToken(AsmToken::Identifier, "expected a field name") ||
8227 !skipToken(AsmToken::LParen, "expected a left parenthesis"))
8228 return false;
8229
8230 SMLoc ValueLoc = getLoc();
8231 StringRef ValueName = getTokenStr();
8232 if (!skipToken(AsmToken::Identifier, "expected a value name") ||
8233 !skipToken(AsmToken::RParen, "expected a right parenthesis"))
8234 return false;
8235
8236 unsigned Shift;
8237 if (FieldName == "instid0") {
8238 Shift = 0;
8239 } else if (FieldName == "instskip") {
8240 Shift = 4;
8241 } else if (FieldName == "instid1") {
8242 Shift = 7;
8243 } else {
8244 Error(FieldLoc, "invalid field name " + FieldName);
8245 return false;
8246 }
8247
8248 int Value;
8249 if (Shift == 4) {
8250 // Parse values for instskip.
8251 Value = StringSwitch<int>(ValueName)
8252 .Case("SAME", 0)
8253 .Case("NEXT", 1)
8254 .Case("SKIP_1", 2)
8255 .Case("SKIP_2", 3)
8256 .Case("SKIP_3", 4)
8257 .Case("SKIP_4", 5)
8258 .Default(-1);
8259 } else {
8260 // Parse values for instid0 and instid1.
8261 Value = StringSwitch<int>(ValueName)
8262 .Case("NO_DEP", 0)
8263 .Case("VALU_DEP_1", 1)
8264 .Case("VALU_DEP_2", 2)
8265 .Case("VALU_DEP_3", 3)
8266 .Case("VALU_DEP_4", 4)
8267 .Case("TRANS32_DEP_1", 5)
8268 .Case("TRANS32_DEP_2", 6)
8269 .Case("TRANS32_DEP_3", 7)
8270 .Case("FMA_ACCUM_CYCLE_1", 8)
8271 .Case("SALU_CYCLE_1", 9)
8272 .Case("SALU_CYCLE_2", 10)
8273 .Case("SALU_CYCLE_3", 11)
8274 .Default(-1);
8275 }
8276 if (Value < 0) {
8277 Error(ValueLoc, "invalid value name " + ValueName);
8278 return false;
8279 }
8280
8281 Delay |= Value << Shift;
8282 return true;
8283}
8284
8285ParseStatus AMDGPUAsmParser::parseSDelayALU(OperandVector &Operands) {
8286 int64_t Delay = 0;
8287 SMLoc S = getLoc();
8288
8289 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) {
8290 do {
8291 if (!parseDelay(Delay))
8292 return ParseStatus::Failure;
8293 } while (trySkipToken(AsmToken::Pipe));
8294 } else {
8295 if (!parseExpr(Delay))
8296 return ParseStatus::Failure;
8297 }
8298
8299 Operands.push_back(AMDGPUOperand::CreateImm(this, Delay, S));
8300 return ParseStatus::Success;
8301}
8302
8303bool AMDGPUOperand::isSWaitCnt() const { return isImm(); }
8304
8305bool AMDGPUOperand::isSDelayALU() const { return isImm(); }
8306
8307//===----------------------------------------------------------------------===//
8308// DepCtr
8309//===----------------------------------------------------------------------===//
8310
8311void AMDGPUAsmParser::depCtrError(SMLoc Loc, int ErrorId,
8312 StringRef DepCtrName) {
8313 switch (ErrorId) {
8314 case OPR_ID_UNKNOWN:
8315 Error(Loc, Twine("invalid counter name ", DepCtrName));
8316 return;
8317 case OPR_ID_UNSUPPORTED:
8318 Error(Loc, Twine(DepCtrName, " is not supported on this GPU"));
8319 return;
8320 case OPR_ID_DUPLICATE:
8321 Error(Loc, Twine("duplicate counter name ", DepCtrName));
8322 return;
8323 case OPR_VAL_INVALID:
8324 Error(Loc, Twine("invalid value for ", DepCtrName));
8325 return;
8326 default:
8327 assert(false);
8328 }
8329}
8330
8331bool AMDGPUAsmParser::parseDepCtr(int64_t &DepCtr, unsigned &UsedOprMask) {
8332
8333 using namespace llvm::AMDGPU::DepCtr;
8334
8335 SMLoc DepCtrLoc = getLoc();
8336 StringRef DepCtrName = getTokenStr();
8337
8338 if (!skipToken(AsmToken::Identifier, "expected a counter name") ||
8339 !skipToken(AsmToken::LParen, "expected a left parenthesis"))
8340 return false;
8341
8342 int64_t ExprVal;
8343 if (!parseExpr(ExprVal))
8344 return false;
8345
8346 unsigned PrevOprMask = UsedOprMask;
8347 int CntVal = encodeDepCtr(DepCtrName, ExprVal, UsedOprMask, getSTI());
8348
8349 if (CntVal < 0) {
8350 depCtrError(DepCtrLoc, CntVal, DepCtrName);
8351 return false;
8352 }
8353
8354 if (!skipToken(AsmToken::RParen, "expected a closing parenthesis"))
8355 return false;
8356
8357 if (trySkipToken(AsmToken::Amp) || trySkipToken(AsmToken::Comma)) {
8358 if (isToken(AsmToken::EndOfStatement)) {
8359 Error(getLoc(), "expected a counter name");
8360 return false;
8361 }
8362 }
8363
8364 int64_t CntValMask = PrevOprMask ^ UsedOprMask;
8365 DepCtr = (DepCtr & ~CntValMask) | CntVal;
8366 return true;
8367}
8368
8369ParseStatus AMDGPUAsmParser::parseDepCtr(OperandVector &Operands) {
8370 using namespace llvm::AMDGPU::DepCtr;
8371
8372 int64_t DepCtr = getDefaultDepCtrEncoding(getSTI());
8373 SMLoc Loc = getLoc();
8374
8375 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) {
8376 unsigned UsedOprMask = 0;
8377 while (!isToken(AsmToken::EndOfStatement)) {
8378 if (!parseDepCtr(DepCtr, UsedOprMask))
8379 return ParseStatus::Failure;
8380 }
8381 } else {
8382 if (!parseExpr(DepCtr))
8383 return ParseStatus::Failure;
8384 }
8385
8386 Operands.push_back(AMDGPUOperand::CreateImm(this, DepCtr, Loc));
8387 return ParseStatus::Success;
8388}
8389
8390bool AMDGPUOperand::isDepCtr() const { return isS16Imm(); }
8391
8392//===----------------------------------------------------------------------===//
8393// hwreg
8394//===----------------------------------------------------------------------===//
8395
8396ParseStatus AMDGPUAsmParser::parseHwregFunc(OperandInfoTy &HwReg,
8397 OperandInfoTy &Offset,
8398 OperandInfoTy &Width) {
8399 using namespace llvm::AMDGPU::Hwreg;
8400
8401 if (!trySkipId("hwreg", AsmToken::LParen))
8402 return ParseStatus::NoMatch;
8403
8404 // The register may be specified by name or using a numeric code
8405 HwReg.Loc = getLoc();
8406 if (isToken(AsmToken::Identifier) &&
8407 (HwReg.Val = getHwregId(getTokenStr(), getSTI())) != OPR_ID_UNKNOWN) {
8408 HwReg.IsSymbolic = true;
8409 lex(); // skip register name
8410 } else if (!parseExpr(HwReg.Val, "a register name")) {
8411 return ParseStatus::Failure;
8412 }
8413
8414 if (trySkipToken(AsmToken::RParen))
8415 return ParseStatus::Success;
8416
8417 // parse optional params
8418 if (!skipToken(AsmToken::Comma, "expected a comma or a closing parenthesis"))
8419 return ParseStatus::Failure;
8420
8421 Offset.Loc = getLoc();
8422 if (!parseExpr(Offset.Val))
8423 return ParseStatus::Failure;
8424
8425 if (!skipToken(AsmToken::Comma, "expected a comma"))
8426 return ParseStatus::Failure;
8427
8428 Width.Loc = getLoc();
8429 if (!parseExpr(Width.Val) ||
8430 !skipToken(AsmToken::RParen, "expected a closing parenthesis"))
8431 return ParseStatus::Failure;
8432
8433 return ParseStatus::Success;
8434}
8435
8436ParseStatus AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
8437 using namespace llvm::AMDGPU::Hwreg;
8438
8439 int64_t ImmVal = 0;
8440 SMLoc Loc = getLoc();
8441
8442 StructuredOpField HwReg("id", "hardware register", HwregId::Width,
8443 HwregId::Default);
8444 StructuredOpField Offset("offset", "bit offset", HwregOffset::Width,
8445 HwregOffset::Default);
8446 struct : StructuredOpField {
8447 using StructuredOpField::StructuredOpField;
8448 bool validate(AMDGPUAsmParser &Parser) const override {
8449 if (!isUIntN(Width, Val - 1))
8450 return Error(Parser, "only values from 1 to 32 are legal");
8451 return true;
8452 }
8453 } Width("size", "bitfield width", HwregSize::Width, HwregSize::Default);
8454 ParseStatus Res = parseStructuredOpFields({&HwReg, &Offset, &Width});
8455
8456 if (Res.isNoMatch())
8457 Res = parseHwregFunc(HwReg, Offset, Width);
8458
8459 if (Res.isSuccess()) {
8460 if (!validateStructuredOpFields({&HwReg, &Offset, &Width}))
8461 return ParseStatus::Failure;
8462 ImmVal = HwregEncoding::encode(HwReg.Val, Offset.Val, Width.Val);
8463 }
8464
8465 if (Res.isNoMatch() &&
8466 parseExpr(ImmVal, "a hwreg macro, structured immediate"))
8468
8469 if (!Res.isSuccess())
8470 return ParseStatus::Failure;
8471
8472 if (!isUInt<16>(ImmVal))
8473 return Error(Loc, "invalid immediate: only 16-bit values are legal");
8474 Operands.push_back(
8475 AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTyHwreg));
8476 return ParseStatus::Success;
8477}
8478
8479bool AMDGPUOperand::isHwreg() const { return isImmTy(ImmTyHwreg); }
8480
8481//===----------------------------------------------------------------------===//
8482// sendmsg
8483//===----------------------------------------------------------------------===//
8484
8485bool AMDGPUAsmParser::parseSendMsgBody(OperandInfoTy &Msg, OperandInfoTy &Op,
8486 OperandInfoTy &Stream) {
8487 using namespace llvm::AMDGPU::SendMsg;
8488
8489 Msg.Loc = getLoc();
8490 if (isToken(AsmToken::Identifier) &&
8491 (Msg.Val = getMsgId(getTokenStr(), getSTI())) != OPR_ID_UNKNOWN) {
8492 Msg.IsSymbolic = true;
8493 lex(); // skip message name
8494 } else if (!parseExpr(Msg.Val, "a message name")) {
8495 return false;
8496 }
8497
8498 if (trySkipToken(AsmToken::Comma)) {
8499 Op.IsDefined = true;
8500 Op.Loc = getLoc();
8501 if (isToken(AsmToken::Identifier) &&
8502 (Op.Val = getMsgOpId(Msg.Val, getTokenStr(), getSTI())) !=
8504 lex(); // skip operation name
8505 } else if (!parseExpr(Op.Val, "an operation name")) {
8506 return false;
8507 }
8508
8509 if (trySkipToken(AsmToken::Comma)) {
8510 Stream.IsDefined = true;
8511 Stream.Loc = getLoc();
8512 if (!parseExpr(Stream.Val))
8513 return false;
8514 }
8515 }
8516
8517 return skipToken(AsmToken::RParen, "expected a closing parenthesis");
8518}
8519
8520bool AMDGPUAsmParser::validateSendMsg(const OperandInfoTy &Msg,
8521 const OperandInfoTy &Op,
8522 const OperandInfoTy &Stream) {
8523 using namespace llvm::AMDGPU::SendMsg;
8524
8525 // Validation strictness depends on whether message is specified
8526 // in a symbolic or in a numeric form. In the latter case
8527 // only encoding possibility is checked.
8528 bool Strict = Msg.IsSymbolic;
8529
8530 if (Strict) {
8531 if (Msg.Val == OPR_ID_UNSUPPORTED) {
8532 Error(Msg.Loc, "specified message id is not supported on this GPU");
8533 return false;
8534 }
8535 } else {
8536 if (!isValidMsgId(Msg.Val, getSTI())) {
8537 Error(Msg.Loc, "invalid message id");
8538 return false;
8539 }
8540 }
8541 if (Strict && (msgRequiresOp(Msg.Val, getSTI()) != Op.IsDefined)) {
8542 if (Op.IsDefined) {
8543 Error(Op.Loc, "message does not support operations");
8544 } else {
8545 Error(Msg.Loc, "missing message operation");
8546 }
8547 return false;
8548 }
8549 if (!isValidMsgOp(Msg.Val, Op.Val, getSTI(), Strict)) {
8550 if (Op.Val == OPR_ID_UNSUPPORTED)
8551 Error(Op.Loc, "specified operation id is not supported on this GPU");
8552 else
8553 Error(Op.Loc, "invalid operation id");
8554 return false;
8555 }
8556 if (Strict && !msgSupportsStream(Msg.Val, Op.Val, getSTI()) &&
8557 Stream.IsDefined) {
8558 Error(Stream.Loc, "message operation does not support streams");
8559 return false;
8560 }
8561 if (!isValidMsgStream(Msg.Val, Op.Val, Stream.Val, getSTI(), Strict)) {
8562 Error(Stream.Loc, "invalid message stream id");
8563 return false;
8564 }
8565 return true;
8566}
8567
8568ParseStatus AMDGPUAsmParser::parseSendMsg(OperandVector &Operands) {
8569 using namespace llvm::AMDGPU::SendMsg;
8570
8571 int64_t ImmVal = 0;
8572 SMLoc Loc = getLoc();
8573
8574 if (trySkipId("sendmsg", AsmToken::LParen)) {
8575 OperandInfoTy Msg(OPR_ID_UNKNOWN);
8576 OperandInfoTy Op(OP_NONE_);
8577 OperandInfoTy Stream(STREAM_ID_NONE_);
8578 if (parseSendMsgBody(Msg, Op, Stream) && validateSendMsg(Msg, Op, Stream)) {
8579 ImmVal = encodeMsg(Msg.Val, Op.Val, Stream.Val);
8580 } else {
8581 return ParseStatus::Failure;
8582 }
8583 } else if (parseExpr(ImmVal, "a sendmsg macro")) {
8584 if (ImmVal < 0 || !isUInt<16>(ImmVal))
8585 return Error(Loc, "invalid immediate: only 16-bit values are legal");
8586 } else {
8587 return ParseStatus::Failure;
8588 }
8589
8590 Operands.push_back(
8591 AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTySendMsg));
8592 return ParseStatus::Success;
8593}
8594
8595bool AMDGPUOperand::isSendMsg() const { return isImmTy(ImmTySendMsg); }
8596
8597ParseStatus AMDGPUAsmParser::parseWaitEvent(OperandVector &Operands) {
8598 using namespace llvm::AMDGPU::WaitEvent;
8599
8600 SMLoc Loc = getLoc();
8601 int64_t ImmVal = 0;
8602
8603 StructuredOpField DontWaitExportReady("dont_wait_export_ready", "bit value",
8604 1, 0);
8605 StructuredOpField ExportReady("export_ready", "bit value", 1, 0);
8606
8607 StructuredOpField *TargetBitfield =
8608 isGFX11() ? &DontWaitExportReady : &ExportReady;
8609
8610 ParseStatus Res = parseStructuredOpFields({TargetBitfield});
8611 if (Res.isNoMatch() && parseExpr(ImmVal, "structured immediate"))
8613 else if (Res.isSuccess()) {
8614 if (!validateStructuredOpFields({TargetBitfield}))
8615 return ParseStatus::Failure;
8616 ImmVal = TargetBitfield->Val;
8617 }
8618
8619 if (!Res.isSuccess())
8620 return ParseStatus::Failure;
8621
8622 if (!isUInt<16>(ImmVal))
8623 return Error(Loc, "invalid immediate: only 16-bit values are legal");
8624
8625 Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc,
8626 AMDGPUOperand::ImmTyWaitEvent));
8627 return ParseStatus::Success;
8628}
8629
8630bool AMDGPUOperand::isWaitEvent() const { return isImmTy(ImmTyWaitEvent); }
8631
8632//===----------------------------------------------------------------------===//
8633// v_interp
8634//===----------------------------------------------------------------------===//
8635
8636ParseStatus AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) {
8637 StringRef Str;
8638 SMLoc S = getLoc();
8639
8640 if (!parseId(Str))
8641 return ParseStatus::NoMatch;
8642
8643 int Slot = StringSwitch<int>(Str)
8644 .Case("p10", 0)
8645 .Case("p20", 1)
8646 .Case("p0", 2)
8647 .Default(-1);
8648
8649 if (Slot == -1)
8650 return Error(S, "invalid interpolation slot");
8651
8652 Operands.push_back(
8653 AMDGPUOperand::CreateImm(this, Slot, S, AMDGPUOperand::ImmTyInterpSlot));
8654 return ParseStatus::Success;
8655}
8656
8657ParseStatus AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) {
8658 StringRef Str;
8659 SMLoc S = getLoc();
8660
8661 if (!parseId(Str))
8662 return ParseStatus::NoMatch;
8663
8664 if (!Str.starts_with("attr"))
8665 return Error(S, "invalid interpolation attribute");
8666
8667 StringRef Chan = Str.take_back(2);
8668 int AttrChan = StringSwitch<int>(Chan)
8669 .Case(".x", 0)
8670 .Case(".y", 1)
8671 .Case(".z", 2)
8672 .Case(".w", 3)
8673 .Default(-1);
8674 if (AttrChan == -1)
8675 return Error(S, "invalid or missing interpolation attribute channel");
8676
8677 Str = Str.drop_back(2).drop_front(4);
8678
8679 uint8_t Attr;
8680 if (Str.getAsInteger(10, Attr))
8681 return Error(S, "invalid or missing interpolation attribute number");
8682
8683 if (Attr > 32)
8684 return Error(S, "out of bounds interpolation attribute number");
8685
8686 SMLoc SChan = SMLoc::getFromPointer(Chan.data());
8687
8688 Operands.push_back(
8689 AMDGPUOperand::CreateImm(this, Attr, S, AMDGPUOperand::ImmTyInterpAttr));
8690 Operands.push_back(AMDGPUOperand::CreateImm(
8691 this, AttrChan, SChan, AMDGPUOperand::ImmTyInterpAttrChan));
8692 return ParseStatus::Success;
8693}
8694
8695//===----------------------------------------------------------------------===//
8696// exp
8697//===----------------------------------------------------------------------===//
8698
8699ParseStatus AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) {
8700 using namespace llvm::AMDGPU::Exp;
8701
8702 StringRef Str;
8703 SMLoc S = getLoc();
8704
8705 if (!parseId(Str))
8706 return ParseStatus::NoMatch;
8707
8708 unsigned Id = getTgtId(Str);
8709 if (Id == ET_INVALID || !isSupportedTgtId(Id, getSTI()))
8710 return Error(S, (Id == ET_INVALID)
8711 ? "invalid exp target"
8712 : "exp target is not supported on this GPU");
8713
8714 Operands.push_back(
8715 AMDGPUOperand::CreateImm(this, Id, S, AMDGPUOperand::ImmTyExpTgt));
8716 return ParseStatus::Success;
8717}
8718
8719//===----------------------------------------------------------------------===//
8720// parser helpers
8721//===----------------------------------------------------------------------===//
8722
8723bool AMDGPUAsmParser::isId(const AsmToken &Token, const StringRef Id) const {
8724 return Token.is(AsmToken::Identifier) && Token.getString() == Id;
8725}
8726
8727bool AMDGPUAsmParser::isId(const StringRef Id) const {
8728 return isId(getToken(), Id);
8729}
8730
8731bool AMDGPUAsmParser::isToken(const AsmToken::TokenKind Kind) const {
8732 return getTokenKind() == Kind;
8733}
8734
8735StringRef AMDGPUAsmParser::getId() const {
8736 return isToken(AsmToken::Identifier) ? getTokenStr() : StringRef();
8737}
8738
8739bool AMDGPUAsmParser::trySkipId(const StringRef Id) {
8740 if (isId(Id)) {
8741 lex();
8742 return true;
8743 }
8744 return false;
8745}
8746
8747bool AMDGPUAsmParser::trySkipId(const StringRef Pref, const StringRef Id) {
8748 if (isToken(AsmToken::Identifier)) {
8749 StringRef Tok = getTokenStr();
8750 if (Tok.starts_with(Pref) && Tok.drop_front(Pref.size()) == Id) {
8751 lex();
8752 return true;
8753 }
8754 }
8755 return false;
8756}
8757
8758bool AMDGPUAsmParser::trySkipId(const StringRef Id,
8759 const AsmToken::TokenKind Kind) {
8760 if (isId(Id) && peekToken().is(Kind)) {
8761 lex();
8762 lex();
8763 return true;
8764 }
8765 return false;
8766}
8767
8768bool AMDGPUAsmParser::trySkipToken(const AsmToken::TokenKind Kind) {
8769 if (isToken(Kind)) {
8770 lex();
8771 return true;
8772 }
8773 return false;
8774}
8775
8776bool AMDGPUAsmParser::skipToken(const AsmToken::TokenKind Kind,
8777 const StringRef ErrMsg) {
8778 if (!trySkipToken(Kind)) {
8779 Error(getLoc(), ErrMsg);
8780 return false;
8781 }
8782 return true;
8783}
8784
8785bool AMDGPUAsmParser::parseExpr(int64_t &Imm, StringRef Expected) {
8786 SMLoc S = getLoc();
8787
8788 const MCExpr *Expr;
8789 if (Parser.parseExpression(Expr))
8790 return false;
8791
8792 if (Expr->evaluateAsAbsolute(Imm))
8793 return true;
8794
8795 if (Expected.empty()) {
8796 Error(S, "expected absolute expression");
8797 } else {
8798 Error(S,
8799 Twine("expected ", Expected) + Twine(" or an absolute expression"));
8800 }
8801 return false;
8802}
8803
8804bool AMDGPUAsmParser::parseExpr(OperandVector &Operands) {
8805 SMLoc S = getLoc();
8806
8807 const MCExpr *Expr;
8808 if (Parser.parseExpression(Expr))
8809 return false;
8810
8811 int64_t IntVal;
8812 if (Expr->evaluateAsAbsolute(IntVal)) {
8813 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
8814 } else {
8815 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
8816 }
8817 return true;
8818}
8819
8820bool AMDGPUAsmParser::parseString(StringRef &Val, const StringRef ErrMsg) {
8821 if (isToken(AsmToken::String)) {
8822 Val = getToken().getStringContents();
8823 lex();
8824 return true;
8825 }
8826 Error(getLoc(), ErrMsg);
8827 return false;
8828}
8829
8830bool AMDGPUAsmParser::parseId(StringRef &Val, const StringRef ErrMsg) {
8831 if (isToken(AsmToken::Identifier)) {
8832 Val = getTokenStr();
8833 lex();
8834 return true;
8835 }
8836 if (!ErrMsg.empty())
8837 Error(getLoc(), ErrMsg);
8838 return false;
8839}
8840
8841AsmToken AMDGPUAsmParser::getToken() const { return Parser.getTok(); }
8842
8843AsmToken AMDGPUAsmParser::peekToken(bool ShouldSkipSpace) {
8844 return isToken(AsmToken::EndOfStatement)
8845 ? getToken()
8846 : getLexer().peekTok(ShouldSkipSpace);
8847}
8848
8849void AMDGPUAsmParser::peekTokens(MutableArrayRef<AsmToken> Tokens) {
8850 auto TokCount = getLexer().peekTokens(Tokens);
8851
8852 for (auto Idx = TokCount; Idx < Tokens.size(); ++Idx)
8853 Tokens[Idx] = AsmToken(AsmToken::Error, "");
8854}
8855
8856AsmToken::TokenKind AMDGPUAsmParser::getTokenKind() const {
8857 return getLexer().getKind();
8858}
8859
8860SMLoc AMDGPUAsmParser::getLoc() const { return getToken().getLoc(); }
8861
8862StringRef AMDGPUAsmParser::getTokenStr() const {
8863 return getToken().getString();
8864}
8865
8866void AMDGPUAsmParser::lex() { Parser.Lex(); }
8867
8868const AMDGPUOperand &
8869AMDGPUAsmParser::findMCOperand(const OperandVector &Operands,
8870 int MCOpIdx) const {
8871 for (const auto &Op : Operands) {
8872 const AMDGPUOperand &TargetOp = static_cast<AMDGPUOperand &>(*Op);
8873 if (TargetOp.getMCOpIdx() == MCOpIdx)
8874 return TargetOp;
8875 }
8876 llvm_unreachable("no such MC operand!");
8877}
8878
8879SMLoc AMDGPUAsmParser::getInstLoc(const OperandVector &Operands) const {
8880 return ((AMDGPUOperand &)*Operands[0]).getStartLoc();
8881}
8882
8883// Returns one of the given locations that comes later in the source.
8884SMLoc AMDGPUAsmParser::getLaterLoc(SMLoc a, SMLoc b) {
8885 return a.getPointer() < b.getPointer() ? b : a;
8886}
8887
8888SMLoc AMDGPUAsmParser::getOperandLoc(const OperandVector &Operands,
8889 int MCOpIdx) const {
8890 return findMCOperand(Operands, MCOpIdx).getStartLoc();
8891}
8892
8893SMLoc AMDGPUAsmParser::getOperandLoc(
8894 std::function<bool(const AMDGPUOperand &)> Test,
8895 const OperandVector &Operands) const {
8896 for (unsigned i = Operands.size() - 1; i > 0; --i) {
8897 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
8898 if (Test(Op))
8899 return Op.getStartLoc();
8900 }
8901 return getInstLoc(Operands);
8902}
8903
8904SMLoc AMDGPUAsmParser::getImmLoc(AMDGPUOperand::ImmTy Type,
8905 const OperandVector &Operands) const {
8906 auto Test = [=](const AMDGPUOperand &Op) { return Op.isImmTy(Type); };
8907 return getOperandLoc(Test, Operands);
8908}
8909
8910ParseStatus
8911AMDGPUAsmParser::parseStructuredOpFields(ArrayRef<StructuredOpField *> Fields) {
8912 if (!trySkipToken(AsmToken::LCurly))
8913 return ParseStatus::NoMatch;
8914
8915 bool First = true;
8916 while (!trySkipToken(AsmToken::RCurly)) {
8917 if (!First &&
8918 !skipToken(AsmToken::Comma, "comma or closing brace expected"))
8919 return ParseStatus::Failure;
8920
8921 StringRef Id = getTokenStr();
8922 SMLoc IdLoc = getLoc();
8923 if (!skipToken(AsmToken::Identifier, "field name expected") ||
8924 !skipToken(AsmToken::Colon, "colon expected"))
8925 return ParseStatus::Failure;
8926
8927 const auto *I =
8928 find_if(Fields, [Id](StructuredOpField *F) { return F->Id == Id; });
8929 if (I == Fields.end())
8930 return Error(IdLoc, "unknown field");
8931 if ((*I)->IsDefined)
8932 return Error(IdLoc, "duplicate field");
8933
8934 // TODO: Support symbolic values.
8935 (*I)->Loc = getLoc();
8936 if (!parseExpr((*I)->Val))
8937 return ParseStatus::Failure;
8938 (*I)->IsDefined = true;
8939
8940 First = false;
8941 }
8942 return ParseStatus::Success;
8943}
8944
8945bool AMDGPUAsmParser::validateStructuredOpFields(
8947 return all_of(Fields, [this](const StructuredOpField *F) {
8948 return F->validate(*this);
8949 });
8950}
8951
8952//===----------------------------------------------------------------------===//
8953// swizzle
8954//===----------------------------------------------------------------------===//
8955
8957static unsigned encodeBitmaskPerm(const unsigned AndMask, const unsigned OrMask,
8958 const unsigned XorMask) {
8959 using namespace llvm::AMDGPU::Swizzle;
8960
8961 return BITMASK_PERM_ENC | (AndMask << BITMASK_AND_SHIFT) |
8962 (OrMask << BITMASK_OR_SHIFT) | (XorMask << BITMASK_XOR_SHIFT);
8963}
8964
8965bool AMDGPUAsmParser::parseSwizzleOperand(int64_t &Op, const unsigned MinVal,
8966 const unsigned MaxVal,
8967 const Twine &ErrMsg, SMLoc &Loc) {
8968 if (!skipToken(AsmToken::Comma, "expected a comma")) {
8969 return false;
8970 }
8971 Loc = getLoc();
8972 if (!parseExpr(Op)) {
8973 return false;
8974 }
8975 if (Op < MinVal || Op > MaxVal) {
8976 Error(Loc, ErrMsg);
8977 return false;
8978 }
8979
8980 return true;
8981}
8982
8983bool AMDGPUAsmParser::parseSwizzleOperands(const unsigned OpNum, int64_t *Op,
8984 const unsigned MinVal,
8985 const unsigned MaxVal,
8986 const StringRef ErrMsg) {
8987 SMLoc Loc;
8988 for (unsigned i = 0; i < OpNum; ++i) {
8989 if (!parseSwizzleOperand(Op[i], MinVal, MaxVal, ErrMsg, Loc))
8990 return false;
8991 }
8992
8993 return true;
8994}
8995
8996bool AMDGPUAsmParser::parseSwizzleQuadPerm(int64_t &Imm) {
8997 using namespace llvm::AMDGPU::Swizzle;
8998
8999 int64_t Lane[LANE_NUM];
9000 if (parseSwizzleOperands(LANE_NUM, Lane, 0, LANE_MAX,
9001 "expected a 2-bit lane id")) {
9003 for (unsigned I = 0; I < LANE_NUM; ++I) {
9004 Imm |= Lane[I] << (LANE_SHIFT * I);
9005 }
9006 return true;
9007 }
9008 return false;
9009}
9010
9011bool AMDGPUAsmParser::parseSwizzleBroadcast(int64_t &Imm) {
9012 using namespace llvm::AMDGPU::Swizzle;
9013
9014 SMLoc Loc;
9015 int64_t GroupSize;
9016 int64_t LaneIdx;
9017
9018 if (!parseSwizzleOperand(GroupSize, 2, 32,
9019 "group size must be in the interval [2,32]", Loc)) {
9020 return false;
9021 }
9022 if (!isPowerOf2_64(GroupSize)) {
9023 Error(Loc, "group size must be a power of two");
9024 return false;
9025 }
9026 if (parseSwizzleOperand(LaneIdx, 0, GroupSize - 1,
9027 "lane id must be in the interval [0,group size - 1]",
9028 Loc)) {
9029 Imm = encodeBitmaskPerm(BITMASK_MAX - GroupSize + 1, LaneIdx, 0);
9030 return true;
9031 }
9032 return false;
9033}
9034
9035bool AMDGPUAsmParser::parseSwizzleReverse(int64_t &Imm) {
9036 using namespace llvm::AMDGPU::Swizzle;
9037
9038 SMLoc Loc;
9039 int64_t GroupSize;
9040
9041 if (!parseSwizzleOperand(GroupSize, 2, 32,
9042 "group size must be in the interval [2,32]", Loc)) {
9043 return false;
9044 }
9045 if (!isPowerOf2_64(GroupSize)) {
9046 Error(Loc, "group size must be a power of two");
9047 return false;
9048 }
9049
9050 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize - 1);
9051 return true;
9052}
9053
9054bool AMDGPUAsmParser::parseSwizzleSwap(int64_t &Imm) {
9055 using namespace llvm::AMDGPU::Swizzle;
9056
9057 SMLoc Loc;
9058 int64_t GroupSize;
9059
9060 if (!parseSwizzleOperand(GroupSize, 1, 16,
9061 "group size must be in the interval [1,16]", Loc)) {
9062 return false;
9063 }
9064 if (!isPowerOf2_64(GroupSize)) {
9065 Error(Loc, "group size must be a power of two");
9066 return false;
9067 }
9068
9069 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize);
9070 return true;
9071}
9072
9073bool AMDGPUAsmParser::parseSwizzleBitmaskPerm(int64_t &Imm) {
9074 using namespace llvm::AMDGPU::Swizzle;
9075
9076 if (!skipToken(AsmToken::Comma, "expected a comma")) {
9077 return false;
9078 }
9079
9080 StringRef Ctl;
9081 SMLoc StrLoc = getLoc();
9082 if (!parseString(Ctl)) {
9083 return false;
9084 }
9085 if (Ctl.size() != BITMASK_WIDTH) {
9086 Error(StrLoc, "expected a 5-character mask");
9087 return false;
9088 }
9089
9090 unsigned AndMask = 0;
9091 unsigned OrMask = 0;
9092 unsigned XorMask = 0;
9093
9094 for (size_t i = 0; i < Ctl.size(); ++i) {
9095 unsigned Mask = 1 << (BITMASK_WIDTH - 1 - i);
9096 switch (Ctl[i]) {
9097 default:
9098 Error(StrLoc, "invalid mask");
9099 return false;
9100 case '0':
9101 break;
9102 case '1':
9103 OrMask |= Mask;
9104 break;
9105 case 'p':
9106 AndMask |= Mask;
9107 break;
9108 case 'i':
9109 AndMask |= Mask;
9110 XorMask |= Mask;
9111 break;
9112 }
9113 }
9114
9115 Imm = encodeBitmaskPerm(AndMask, OrMask, XorMask);
9116 return true;
9117}
9118
9119bool AMDGPUAsmParser::parseSwizzleFFT(int64_t &Imm) {
9120 using namespace llvm::AMDGPU::Swizzle;
9121
9122 if (!AMDGPU::isGFX9Plus(getSTI())) {
9123 Error(getLoc(), "FFT mode swizzle not supported on this GPU");
9124 return false;
9125 }
9126
9127 int64_t Swizzle;
9128 SMLoc Loc;
9129 if (!parseSwizzleOperand(Swizzle, 0, FFT_SWIZZLE_MAX,
9130 "FFT swizzle must be in the interval [0," +
9131 Twine(FFT_SWIZZLE_MAX) + Twine(']'),
9132 Loc))
9133 return false;
9134
9135 Imm = FFT_MODE_ENC | Swizzle;
9136 return true;
9137}
9138
9139bool AMDGPUAsmParser::parseSwizzleRotate(int64_t &Imm) {
9140 using namespace llvm::AMDGPU::Swizzle;
9141
9142 if (!AMDGPU::isGFX9Plus(getSTI())) {
9143 Error(getLoc(), "Rotate mode swizzle not supported on this GPU");
9144 return false;
9145 }
9146
9147 SMLoc Loc;
9148 int64_t Direction;
9149
9150 if (!parseSwizzleOperand(Direction, 0, 1,
9151 "direction must be 0 (left) or 1 (right)", Loc))
9152 return false;
9153
9154 int64_t RotateSize;
9155 if (!parseSwizzleOperand(
9156 RotateSize, 0, ROTATE_MAX_SIZE,
9157 "number of threads to rotate must be in the interval [0," +
9158 Twine(ROTATE_MAX_SIZE) + Twine(']'),
9159 Loc))
9160 return false;
9161
9163 (RotateSize << ROTATE_SIZE_SHIFT);
9164 return true;
9165}
9166
9167bool AMDGPUAsmParser::parseSwizzleOffset(int64_t &Imm) {
9168
9169 SMLoc OffsetLoc = getLoc();
9170
9171 if (!parseExpr(Imm, "a swizzle macro")) {
9172 return false;
9173 }
9174 if (!isUInt<16>(Imm)) {
9175 Error(OffsetLoc, "expected a 16-bit offset");
9176 return false;
9177 }
9178 return true;
9179}
9180
9181bool AMDGPUAsmParser::parseSwizzleMacro(int64_t &Imm) {
9182 using namespace llvm::AMDGPU::Swizzle;
9183
9184 if (skipToken(AsmToken::LParen, "expected a left parentheses")) {
9185
9186 SMLoc ModeLoc = getLoc();
9187 bool Ok = false;
9188
9189 if (trySkipId(IdSymbolic[ID_QUAD_PERM])) {
9190 Ok = parseSwizzleQuadPerm(Imm);
9191 } else if (trySkipId(IdSymbolic[ID_BITMASK_PERM])) {
9192 Ok = parseSwizzleBitmaskPerm(Imm);
9193 } else if (trySkipId(IdSymbolic[ID_BROADCAST])) {
9194 Ok = parseSwizzleBroadcast(Imm);
9195 } else if (trySkipId(IdSymbolic[ID_SWAP])) {
9196 Ok = parseSwizzleSwap(Imm);
9197 } else if (trySkipId(IdSymbolic[ID_REVERSE])) {
9198 Ok = parseSwizzleReverse(Imm);
9199 } else if (trySkipId(IdSymbolic[ID_FFT])) {
9200 Ok = parseSwizzleFFT(Imm);
9201 } else if (trySkipId(IdSymbolic[ID_ROTATE])) {
9202 Ok = parseSwizzleRotate(Imm);
9203 } else {
9204 Error(ModeLoc, "expected a swizzle mode");
9205 }
9206
9207 return Ok && skipToken(AsmToken::RParen, "expected a closing parentheses");
9208 }
9209
9210 return false;
9211}
9212
9213ParseStatus AMDGPUAsmParser::parseSwizzle(OperandVector &Operands) {
9214 SMLoc S = getLoc();
9215 int64_t Imm = 0;
9216
9217 if (trySkipId("offset")) {
9218
9219 bool Ok = false;
9220 if (skipToken(AsmToken::Colon, "expected a colon")) {
9221 if (trySkipId("swizzle")) {
9222 Ok = parseSwizzleMacro(Imm);
9223 } else {
9224 Ok = parseSwizzleOffset(Imm);
9225 }
9226 }
9227
9228 Operands.push_back(
9229 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTySwizzle));
9230
9232 }
9233 return ParseStatus::NoMatch;
9234}
9235
9236bool AMDGPUOperand::isSwizzle() const { return isImmTy(ImmTySwizzle); }
9237
9238//===----------------------------------------------------------------------===//
9239// VGPR Index Mode
9240//===----------------------------------------------------------------------===//
9241
9242int64_t AMDGPUAsmParser::parseGPRIdxMacro() {
9243
9244 using namespace llvm::AMDGPU::VGPRIndexMode;
9245
9246 if (trySkipToken(AsmToken::RParen)) {
9247 return OFF;
9248 }
9249
9250 int64_t Imm = 0;
9251
9252 while (true) {
9253 unsigned Mode = 0;
9254 SMLoc S = getLoc();
9255
9256 for (unsigned ModeId = ID_MIN; ModeId <= ID_MAX; ++ModeId) {
9257 if (trySkipId(IdSymbolic[ModeId])) {
9258 Mode = 1 << ModeId;
9259 break;
9260 }
9261 }
9262
9263 if (Mode == 0) {
9264 Error(S, (Imm == 0)
9265 ? "expected a VGPR index mode or a closing parenthesis"
9266 : "expected a VGPR index mode");
9267 return UNDEF;
9268 }
9269
9270 if (Imm & Mode) {
9271 Error(S, "duplicate VGPR index mode");
9272 return UNDEF;
9273 }
9274 Imm |= Mode;
9275
9276 if (trySkipToken(AsmToken::RParen))
9277 break;
9278 if (!skipToken(AsmToken::Comma,
9279 "expected a comma or a closing parenthesis"))
9280 return UNDEF;
9281 }
9282
9283 return Imm;
9284}
9285
9286ParseStatus AMDGPUAsmParser::parseGPRIdxMode(OperandVector &Operands) {
9287
9288 using namespace llvm::AMDGPU::VGPRIndexMode;
9289
9290 int64_t Imm = 0;
9291 SMLoc S = getLoc();
9292
9293 if (trySkipId("gpr_idx", AsmToken::LParen)) {
9294 Imm = parseGPRIdxMacro();
9295 if (Imm == UNDEF)
9296 return ParseStatus::Failure;
9297 } else {
9298 if (getParser().parseAbsoluteExpression(Imm))
9299 return ParseStatus::Failure;
9300 if (Imm < 0 || !isUInt<4>(Imm))
9301 return Error(S, "invalid immediate: only 4-bit values are legal");
9302 }
9303
9304 Operands.push_back(
9305 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyGprIdxMode));
9306 return ParseStatus::Success;
9307}
9308
9309bool AMDGPUOperand::isGPRIdxMode() const { return isImmTy(ImmTyGprIdxMode); }
9310
9311//===----------------------------------------------------------------------===//
9312// sopp branch targets
9313//===----------------------------------------------------------------------===//
9314
9315ParseStatus AMDGPUAsmParser::parseSOPPBrTarget(OperandVector &Operands) {
9316
9317 // Make sure we are not parsing something
9318 // that looks like a label or an expression but is not.
9319 // This will improve error messages.
9320 if (isRegister() || isModifier())
9321 return ParseStatus::NoMatch;
9322
9323 if (!parseExpr(Operands))
9324 return ParseStatus::Failure;
9325
9326 AMDGPUOperand &Opr = ((AMDGPUOperand &)*Operands[Operands.size() - 1]);
9327 assert(Opr.isImm() || Opr.isExpr());
9328 SMLoc Loc = Opr.getStartLoc();
9329
9330 // Currently we do not support arbitrary expressions as branch targets.
9331 // Only labels and absolute expressions are accepted.
9332 if (Opr.isExpr() && !Opr.isSymbolRefExpr()) {
9333 Error(Loc, "expected an absolute expression or a label");
9334 } else if (Opr.isImm() && !Opr.isS16Imm()) {
9335 Error(Loc, "expected a 16-bit signed jump offset");
9336 }
9337
9338 return ParseStatus::Success;
9339}
9340
9341//===----------------------------------------------------------------------===//
9342// Boolean holding registers
9343//===----------------------------------------------------------------------===//
9344
9345ParseStatus AMDGPUAsmParser::parseBoolReg(OperandVector &Operands) {
9346 return parseReg(Operands);
9347}
9348
9349//===----------------------------------------------------------------------===//
9350// mubuf
9351//===----------------------------------------------------------------------===//
9352
9353void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst, const OperandVector &Operands,
9354 bool IsAtomic) {
9355 OptionalImmIndexMap OptionalIdx;
9356 unsigned FirstOperandIdx = 1;
9357 bool IsAtomicReturn = false;
9358
9359 if (IsAtomic) {
9360 IsAtomicReturn = SIInstrFlags::isAtomicRet(MII, Inst);
9361 }
9362
9363 for (unsigned i = FirstOperandIdx, e = Operands.size(); i != e; ++i) {
9364 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
9365
9366 // Add the register arguments
9367 if (Op.isReg()) {
9368 Op.addRegOperands(Inst, 1);
9369 // Insert a tied src for atomic return dst.
9370 // This cannot be postponed as subsequent calls to
9371 // addImmOperands rely on correct number of MC operands.
9372 if (IsAtomicReturn && i == FirstOperandIdx)
9373 Op.addRegOperands(Inst, 1);
9374 continue;
9375 }
9376
9377 // Handle the case where soffset is an immediate
9378 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
9379 Op.addImmOperands(Inst, 1);
9380 continue;
9381 }
9382
9383 // Handle tokens like 'offen' which are sometimes hard-coded into the
9384 // asm string. There are no MCInst operands for these.
9385 if (Op.isToken()) {
9386 continue;
9387 }
9388 assert(Op.isImm());
9389
9390 // Handle optional arguments
9391 OptionalIdx[Op.getImmTy()] = i;
9392 }
9393
9394 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9395 AMDGPUOperand::ImmTyOffset);
9396 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyCPol,
9397 0);
9398 // Parse a dummy operand as a placeholder for the SWZ operand. This enforces
9399 // agreement between MCInstrDesc.getNumOperands and MCInst.getNumOperands.
9401 // The LDS variants carry a trailing IsAsync operand. Parse a dummy the same
9402 // way as the SWZ operand.
9403 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::IsAsync))
9405}
9406
9407//===----------------------------------------------------------------------===//
9408// smrd
9409//===----------------------------------------------------------------------===//
9410
9411bool AMDGPUOperand::isSMRDOffset8() const {
9412 return isImmLiteral() && isUInt<8>(getImm());
9413}
9414
9415bool AMDGPUOperand::isSMEMOffset() const {
9416 // Offset range is checked later by validator.
9417 return isImmLiteral();
9418}
9419
9420bool AMDGPUOperand::isSMRDLiteralOffset() const {
9421 // 32-bit literals are only supported on CI and we only want to use them
9422 // when the offset is > 8-bits.
9423 return isImmLiteral() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
9424}
9425
9426//===----------------------------------------------------------------------===//
9427// vop3
9428//===----------------------------------------------------------------------===//
9429
9430static bool ConvertOmodMul(int64_t &Mul) {
9431 if (Mul != 1 && Mul != 2 && Mul != 4)
9432 return false;
9433
9434 Mul >>= 1;
9435 return true;
9436}
9437
9438static bool ConvertOmodDiv(int64_t &Div) {
9439 if (Div == 1) {
9440 Div = 0;
9441 return true;
9442 }
9443
9444 if (Div == 2) {
9445 Div = 3;
9446 return true;
9447 }
9448
9449 return false;
9450}
9451
9452// For pre-gfx11 targets, both bound_ctrl:0 and bound_ctrl:1 are encoded as 1.
9453// This is intentional and ensures compatibility with sp3.
9454// See bug 35397 for details.
9455bool AMDGPUAsmParser::convertDppBoundCtrl(int64_t &BoundCtrl) {
9456 if (BoundCtrl == 0 || BoundCtrl == 1) {
9457 if (!isGFX11Plus())
9458 BoundCtrl = 1;
9459 return true;
9460 }
9461 return false;
9462}
9463
9464void AMDGPUAsmParser::onBeginOfFile() {
9465 if (!getParser().getStreamer().getTargetStreamer())
9466 return;
9467
9468 if (!getTargetStreamer().getTargetID())
9469 getTargetStreamer().initializeTargetID(getSTI(),
9470 /*ApplyFeatureString=*/true);
9471}
9472
9473void AMDGPUAsmParser::emitTargetDirective() {
9474 if (!getParser().getStreamer().getTargetStreamer() ||
9475 getSTI().getTargetTriple().getArch() == Triple::r600)
9476 return;
9477
9478 if (isHsaAbi(getSTI()))
9479 getTargetStreamer().emitDirectiveAMDGCNTargetOnce();
9480}
9481
9482/// Parse AMDGPU specific expressions.
9483///
9484/// expr ::= or(expr, ...) |
9485/// max(expr, ...) |
9486/// min(expr, ...)
9487///
9488bool AMDGPUAsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
9489 using AGVK = AMDGPUMCExpr::VariantKind;
9490
9491 if (isToken(AsmToken::Identifier)) {
9492 StringRef TokenId = getTokenStr();
9493 AGVK VK = StringSwitch<AGVK>(TokenId)
9494 .Case("max", AGVK::AGVK_Max)
9495 .Case("min", AGVK::AGVK_Min)
9496 .Case("or", AGVK::AGVK_Or)
9497 .Case("extrasgprs", AGVK::AGVK_ExtraSGPRs)
9498 .Case("totalnumvgprs", AGVK::AGVK_TotalNumVGPRs)
9499 .Case("alignto", AGVK::AGVK_AlignTo)
9500 .Case("occupancy", AGVK::AGVK_Occupancy)
9501 .Case("instprefsize", AGVK::AGVK_InstPrefSize)
9502 .Default(AGVK::AGVK_None);
9503
9504 if (VK != AGVK::AGVK_None && peekToken().is(AsmToken::LParen)) {
9506 uint64_t CommaCount = 0;
9507 lex(); // Eat Arg ('or', 'max', 'occupancy', etc.)
9508 lex(); // Eat '('
9509 while (true) {
9510 if (trySkipToken(AsmToken::RParen)) {
9511 if (Exprs.empty()) {
9512 Error(getToken().getLoc(),
9513 "empty " + Twine(TokenId) + " expression");
9514 return true;
9515 }
9516 if (CommaCount + 1 != Exprs.size()) {
9517 Error(getToken().getLoc(),
9518 "mismatch of commas in " + Twine(TokenId) + " expression");
9519 return true;
9520 }
9521 if (unsigned Expected = AMDGPUMCExpr::getNumExpectedArgs(VK);
9522 Expected && Exprs.size() != Expected) {
9523 Error(getToken().getLoc(), Twine(TokenId) + " expression expects " +
9524 Twine(Expected) + " operands");
9525 return true;
9526 }
9527 Res = AMDGPUMCExpr::create(VK, Exprs, getContext());
9528 return false;
9529 }
9530 const MCExpr *Expr;
9531 if (getParser().parseExpression(Expr, EndLoc))
9532 return true;
9533 Exprs.push_back(Expr);
9534 bool LastTokenWasComma = trySkipToken(AsmToken::Comma);
9535 if (LastTokenWasComma)
9536 CommaCount++;
9537 if (!LastTokenWasComma && !isToken(AsmToken::RParen)) {
9538 Error(getToken().getLoc(),
9539 "unexpected token in " + Twine(TokenId) + " expression");
9540 return true;
9541 }
9542 }
9543 }
9544 }
9545 return getParser().parsePrimaryExpr(Res, EndLoc, nullptr);
9546}
9547
9548ParseStatus AMDGPUAsmParser::parseOModSI(OperandVector &Operands) {
9549 StringRef Name = getTokenStr();
9550 if (Name == "mul") {
9551 return parseIntWithPrefix("mul", Operands, AMDGPUOperand::ImmTyOModSI,
9553 }
9554
9555 if (Name == "div") {
9556 return parseIntWithPrefix("div", Operands, AMDGPUOperand::ImmTyOModSI,
9558 }
9559
9560 return ParseStatus::NoMatch;
9561}
9562
9563// Determines which bit DST_OP_SEL occupies in the op_sel operand according to
9564// the number of src operands present, then copies that bit into src0_modifiers.
9565static void cvtVOP3DstOpSelOnly(MCInst &Inst, const MCRegisterInfo &MRI) {
9566 int Opc = Inst.getOpcode();
9567 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
9568 if (OpSelIdx == -1)
9569 return;
9570
9571 int SrcNum;
9572 const AMDGPU::OpName Ops[] = {AMDGPU::OpName::src0, AMDGPU::OpName::src1,
9573 AMDGPU::OpName::src2};
9574 for (SrcNum = 0; SrcNum < 3 && AMDGPU::hasNamedOperand(Opc, Ops[SrcNum]);
9575 ++SrcNum)
9576 ;
9577 assert(SrcNum > 0);
9578
9579 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
9580
9581 int DstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
9582 if (DstIdx == -1)
9583 return;
9584
9585 const MCOperand &DstOp = Inst.getOperand(DstIdx);
9586 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers);
9587 uint32_t ModVal = Inst.getOperand(ModIdx).getImm();
9588 if (DstOp.isReg() &&
9589 MRI.getRegClass(AMDGPU::VGPR_16RegClassID).contains(DstOp.getReg())) {
9590 if (AMDGPU::isHi16Reg(DstOp.getReg(), MRI))
9591 ModVal |= SISrcMods::DST_OP_SEL;
9592 } else {
9593 if ((OpSel & (1 << SrcNum)) != 0)
9594 ModVal |= SISrcMods::DST_OP_SEL;
9595 }
9596 Inst.getOperand(ModIdx).setImm(ModVal);
9597}
9598
9599void AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst,
9600 const OperandVector &Operands) {
9601 cvtVOP3P(Inst, Operands);
9602 cvtVOP3DstOpSelOnly(Inst, *getMRI());
9603}
9604
9605void AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands,
9606 OptionalImmIndexMap &OptionalIdx) {
9607 cvtVOP3P(Inst, Operands, OptionalIdx);
9608 cvtVOP3DstOpSelOnly(Inst, *getMRI());
9609}
9610
9611static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) {
9612 return
9613 // 1. This operand is input modifiers
9614 Desc.operands()[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS
9615 // 2. This is not last operand
9616 && Desc.NumOperands > (OpNum + 1)
9617 // 3. Next operand is register class
9618 && Desc.operands()[OpNum + 1].RegClass != -1
9619 // 4. Next register is not tied to any other operand
9620 && Desc.getOperandConstraint(OpNum + 1,
9622}
9623
9624void AMDGPUAsmParser::cvtOpSelHelper(MCInst &Inst, unsigned OpSel) {
9625 unsigned Opc = Inst.getOpcode();
9626 constexpr AMDGPU::OpName Ops[] = {AMDGPU::OpName::src0, AMDGPU::OpName::src1,
9627 AMDGPU::OpName::src2};
9628 constexpr AMDGPU::OpName ModOps[] = {AMDGPU::OpName::src0_modifiers,
9629 AMDGPU::OpName::src1_modifiers,
9630 AMDGPU::OpName::src2_modifiers};
9631 for (int J = 0; J < 3; ++J) {
9632 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]);
9633 if (OpIdx == -1)
9634 // Some instructions, e.g. v_interp_p2_f16 in GFX9, have src0, src2, but
9635 // no src1. So continue instead of break.
9636 continue;
9637
9638 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
9639 uint32_t ModVal = Inst.getOperand(ModIdx).getImm();
9640
9641 if ((OpSel & (1 << J)) != 0)
9642 ModVal |= SISrcMods::OP_SEL_0;
9643 // op_sel[3] is encoded in src0_modifiers.
9644 if (ModOps[J] == AMDGPU::OpName::src0_modifiers && (OpSel & (1 << 3)) != 0)
9645 ModVal |= SISrcMods::DST_OP_SEL;
9646
9647 Inst.getOperand(ModIdx).setImm(ModVal);
9648 }
9649}
9650
9651void AMDGPUAsmParser::cvtVOP3Interp(MCInst &Inst,
9652 const OperandVector &Operands) {
9653 OptionalImmIndexMap OptionalIdx;
9654 unsigned Opc = Inst.getOpcode();
9655
9656 unsigned I = 1;
9657 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
9658 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
9659 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
9660 }
9661
9662 for (unsigned E = Operands.size(); I != E; ++I) {
9663 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
9665 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
9666 } else if (Op.isInterpSlot() || Op.isInterpAttr() ||
9667 Op.isInterpAttrChan()) {
9668 Inst.addOperand(MCOperand::createImm(Op.getImm()));
9669 } else if (Op.isImmModifier()) {
9670 OptionalIdx[Op.getImmTy()] = I;
9671 } else {
9672 llvm_unreachable("unhandled operand type");
9673 }
9674 }
9675
9676 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::high))
9677 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9678 AMDGPUOperand::ImmTyHigh);
9679
9680 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp))
9681 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9682 AMDGPUOperand::ImmTyClamp);
9683
9684 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod))
9685 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9686 AMDGPUOperand::ImmTyOModSI);
9687
9688 // Some v_interp instructions use op_sel[3] for dst.
9689 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) {
9690 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9691 AMDGPUOperand::ImmTyOpSel);
9692 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
9693 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
9694
9695 cvtOpSelHelper(Inst, OpSel);
9696 }
9697}
9698
9699void AMDGPUAsmParser::cvtVINTERP(MCInst &Inst, const OperandVector &Operands) {
9700 OptionalImmIndexMap OptionalIdx;
9701 unsigned Opc = Inst.getOpcode();
9702
9703 unsigned I = 1;
9704 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
9705 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
9706 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
9707 }
9708
9709 for (unsigned E = Operands.size(); I != E; ++I) {
9710 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
9712 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
9713 } else if (Op.isImmModifier()) {
9714 OptionalIdx[Op.getImmTy()] = I;
9715 } else {
9716 llvm_unreachable("unhandled operand type");
9717 }
9718 }
9719
9720 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClamp);
9721
9722 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
9723 if (OpSelIdx != -1)
9724 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9725 AMDGPUOperand::ImmTyOpSel);
9726
9727 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9728 AMDGPUOperand::ImmTyWaitEXP);
9729
9730 if (OpSelIdx == -1)
9731 return;
9732
9733 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
9734 cvtOpSelHelper(Inst, OpSel);
9735}
9736
9737void AMDGPUAsmParser::cvtScaledMFMA(MCInst &Inst,
9738 const OperandVector &Operands) {
9739 OptionalImmIndexMap OptionalIdx;
9740 unsigned Opc = Inst.getOpcode();
9741 unsigned I = 1;
9742 int CbszOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::cbsz);
9743
9744 const MCInstrDesc &Desc = MII.get(Opc);
9745
9746 for (unsigned J = 0; J < Desc.getNumDefs(); ++J)
9747 static_cast<AMDGPUOperand &>(*Operands[I++]).addRegOperands(Inst, 1);
9748
9749 for (unsigned E = Operands.size(); I != E; ++I) {
9750 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands[I]);
9751 int NumOperands = Inst.getNumOperands();
9752 // The order of operands in MCInst and parsed operands are different.
9753 // Adding dummy cbsz and blgp operands at corresponding MCInst operand
9754 // indices for parsing scale values correctly.
9755 if (NumOperands == CbszOpIdx) {
9758 }
9759 if (isRegOrImmWithInputMods(Desc, NumOperands)) {
9760 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
9761 } else if (Op.isImmModifier()) {
9762 OptionalIdx[Op.getImmTy()] = I;
9763 } else {
9764 Op.addRegOrImmOperands(Inst, 1);
9765 }
9766 }
9767
9768 // Insert CBSZ and BLGP operands for F8F6F4 variants
9769 auto CbszIdx = OptionalIdx.find(AMDGPUOperand::ImmTyCBSZ);
9770 if (CbszIdx != OptionalIdx.end()) {
9771 int CbszVal = ((AMDGPUOperand &)*Operands[CbszIdx->second]).getImm();
9772 Inst.getOperand(CbszOpIdx).setImm(CbszVal);
9773 }
9774
9775 int BlgpOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::blgp);
9776 auto BlgpIdx = OptionalIdx.find(AMDGPUOperand::ImmTyBLGP);
9777 if (BlgpIdx != OptionalIdx.end()) {
9778 int BlgpVal = ((AMDGPUOperand &)*Operands[BlgpIdx->second]).getImm();
9779 Inst.getOperand(BlgpOpIdx).setImm(BlgpVal);
9780 }
9781
9782 // Add dummy src_modifiers
9785
9786 // Handle op_sel fields
9787
9788 unsigned OpSel = 0;
9789 auto OpselIdx = OptionalIdx.find(AMDGPUOperand::ImmTyOpSel);
9790 if (OpselIdx != OptionalIdx.end()) {
9791 OpSel = static_cast<const AMDGPUOperand &>(*Operands[OpselIdx->second])
9792 .getImm();
9793 }
9794
9795 unsigned OpSelHi = 0;
9796 auto OpselHiIdx = OptionalIdx.find(AMDGPUOperand::ImmTyOpSelHi);
9797 if (OpselHiIdx != OptionalIdx.end()) {
9798 OpSelHi = static_cast<const AMDGPUOperand &>(*Operands[OpselHiIdx->second])
9799 .getImm();
9800 }
9801 const AMDGPU::OpName ModOps[] = {AMDGPU::OpName::src0_modifiers,
9802 AMDGPU::OpName::src1_modifiers};
9803
9804 for (unsigned J = 0; J < 2; ++J) {
9805 unsigned ModVal = 0;
9806 if (OpSel & (1 << J))
9807 ModVal |= SISrcMods::OP_SEL_0;
9808 if (OpSelHi & (1 << J))
9809 ModVal |= SISrcMods::OP_SEL_1;
9810
9811 const int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
9812 Inst.getOperand(ModIdx).setImm(ModVal);
9813 }
9814}
9815
9816void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands,
9817 OptionalImmIndexMap &OptionalIdx) {
9818 unsigned Opc = Inst.getOpcode();
9819
9820 unsigned I = 1;
9821 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
9822 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
9823 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
9824 }
9825
9826 for (unsigned E = Operands.size(); I != E; ++I) {
9827 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
9829 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
9830 } else if (Op.isImmModifier()) {
9831 OptionalIdx[Op.getImmTy()] = I;
9832 } else {
9833 Op.addRegOrImmOperands(Inst, 1);
9834 }
9835 }
9836
9837 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::scale_sel))
9838 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9839 AMDGPUOperand::ImmTyScaleSel);
9840
9841 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp))
9842 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9843 AMDGPUOperand::ImmTyClamp);
9844
9845 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::byte_sel)) {
9846 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::vdst_in))
9847 Inst.addOperand(Inst.getOperand(0));
9848 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9849 AMDGPUOperand::ImmTyByteSel);
9850 }
9851
9852 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod))
9853 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9854 AMDGPUOperand::ImmTyOModSI);
9855
9856 // Special case v_mac_{f16, f32} and v_fmac_{f16, f32} (gfx906/gfx10+):
9857 // it has src2 register operand that is tied to dst operand
9858 // we don't allow modifiers for this operand in assembler so src2_modifiers
9859 // should be 0.
9860 if (isMAC(Opc)) {
9861 auto *it = Inst.begin();
9862 std::advance(
9863 it, AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers));
9864 it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2
9865 ++it;
9866 // Copy the operand to ensure it's not invalidated when Inst grows.
9867 Inst.insert(it, MCOperand(Inst.getOperand(0))); // src2 = dst
9868 }
9869}
9870
9871void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
9872 OptionalImmIndexMap OptionalIdx;
9873 cvtVOP3(Inst, Operands, OptionalIdx);
9874}
9875
9876void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst, const OperandVector &Operands,
9877 OptionalImmIndexMap &OptIdx) {
9878 const int Opc = Inst.getOpcode();
9879
9880 const bool IsPacked = SIInstrFlags::isPacked(MII, Inst);
9881
9882 if (Opc == AMDGPU::V_CVT_SCALEF32_PK_FP4_F16_vi ||
9883 Opc == AMDGPU::V_CVT_SCALEF32_PK_FP4_BF16_vi ||
9884 Opc == AMDGPU::V_CVT_SR_BF8_F32_vi ||
9885 Opc == AMDGPU::V_CVT_SR_FP8_F32_vi ||
9886 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_gfx11 ||
9887 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_gfx11 ||
9888 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_gfx12 ||
9889 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_gfx12 ||
9890 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_gfx13 ||
9891 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_gfx13) {
9892 Inst.addOperand(MCOperand::createImm(0)); // Placeholder for src2_mods
9893 Inst.addOperand(Inst.getOperand(0));
9894 }
9895
9896 // Append vdst_in only if a previous converter (cvtVOP3DPP for DPP variants,
9897 // cvtVOP3 for byte_sel variants) hasn't already placed it. Use the position
9898 // of the named operand to detect that, the same way cvtVOP3DPP does
9899 // internally.
9900 int VdstInIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
9901 if (VdstInIdx != -1 && VdstInIdx == static_cast<int>(Inst.getNumOperands()))
9902 Inst.addOperand(Inst.getOperand(0));
9903
9904 int BitOp3Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::bitop3);
9905 if (BitOp3Idx != -1) {
9906 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyBitOp3);
9907 }
9908
9909 // FIXME: This is messy. Parse the modifiers as if it was a normal VOP3
9910 // instruction, and then figure out where to actually put the modifiers
9911
9912 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
9913 if (OpSelIdx != -1) {
9914 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSel);
9915 }
9916
9917 int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi);
9918 if (OpSelHiIdx != -1) {
9919 int DefaultVal = IsPacked ? -1 : 0;
9920 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSelHi,
9921 DefaultVal);
9922 }
9923
9924 int MatrixAFMTIdx =
9925 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_a_fmt);
9926 if (MatrixAFMTIdx != -1) {
9927 addOptionalImmOperand(Inst, Operands, OptIdx,
9928 AMDGPUOperand::ImmTyMatrixAFMT, 0);
9929 }
9930
9931 int MatrixBFMTIdx =
9932 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_b_fmt);
9933 if (MatrixBFMTIdx != -1) {
9934 addOptionalImmOperand(Inst, Operands, OptIdx,
9935 AMDGPUOperand::ImmTyMatrixBFMT, 0);
9936 }
9937
9938 int MatrixAScaleIdx =
9939 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_a_scale);
9940 if (MatrixAScaleIdx != -1) {
9941 addOptionalImmOperand(Inst, Operands, OptIdx,
9942 AMDGPUOperand::ImmTyMatrixAScale, 0);
9943 }
9944
9945 int MatrixBScaleIdx =
9946 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_b_scale);
9947 if (MatrixBScaleIdx != -1) {
9948 addOptionalImmOperand(Inst, Operands, OptIdx,
9949 AMDGPUOperand::ImmTyMatrixBScale, 0);
9950 }
9951
9952 int MatrixAScaleFmtIdx =
9953 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_a_scale_fmt);
9954 if (MatrixAScaleFmtIdx != -1) {
9955 addOptionalImmOperand(Inst, Operands, OptIdx,
9956 AMDGPUOperand::ImmTyMatrixAScaleFmt, 0);
9957 }
9958
9959 int MatrixBScaleFmtIdx =
9960 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_b_scale_fmt);
9961 if (MatrixBScaleFmtIdx != -1) {
9962 addOptionalImmOperand(Inst, Operands, OptIdx,
9963 AMDGPUOperand::ImmTyMatrixBScaleFmt, 0);
9964 }
9965
9966 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::matrix_a_reuse))
9967 addOptionalImmOperand(Inst, Operands, OptIdx,
9968 AMDGPUOperand::ImmTyMatrixAReuse, 0);
9969
9970 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::matrix_b_reuse))
9971 addOptionalImmOperand(Inst, Operands, OptIdx,
9972 AMDGPUOperand::ImmTyMatrixBReuse, 0);
9973
9974 int NegLoIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_lo);
9975 if (NegLoIdx != -1)
9976 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegLo);
9977
9978 int NegHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_hi);
9979 if (NegHiIdx != -1)
9980 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegHi);
9981
9982 const AMDGPU::OpName Ops[] = {AMDGPU::OpName::src0, AMDGPU::OpName::src1,
9983 AMDGPU::OpName::src2};
9984 const AMDGPU::OpName ModOps[] = {AMDGPU::OpName::src0_modifiers,
9985 AMDGPU::OpName::src1_modifiers,
9986 AMDGPU::OpName::src2_modifiers};
9987
9988 unsigned OpSel = 0;
9989 unsigned OpSelHi = 0;
9990 unsigned NegLo = 0;
9991 unsigned NegHi = 0;
9992
9993 if (OpSelIdx != -1)
9994 OpSel = Inst.getOperand(OpSelIdx).getImm();
9995
9996 if (OpSelHiIdx != -1)
9997 OpSelHi = Inst.getOperand(OpSelHiIdx).getImm();
9998
9999 if (NegLoIdx != -1)
10000 NegLo = Inst.getOperand(NegLoIdx).getImm();
10001
10002 if (NegHiIdx != -1)
10003 NegHi = Inst.getOperand(NegHiIdx).getImm();
10004
10005 for (int J = 0; J < 3; ++J) {
10006 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]);
10007 if (OpIdx == -1)
10008 break;
10009
10010 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
10011
10012 if (ModIdx == -1)
10013 continue;
10014
10015 // For MAC instructions, src2 is tied to vdst and its op_sel bit
10016 // is not encoded.
10017 if (AMDGPU::isMAC(Opc) && ModOps[J] == AMDGPU::OpName::src2_modifiers)
10018 continue;
10019
10020 uint32_t ModVal = 0;
10021
10022 const MCOperand &SrcOp = Inst.getOperand(OpIdx);
10023 if (SrcOp.isReg() && getMRI()
10024 ->getRegClass(AMDGPU::VGPR_16RegClassID)
10025 .contains(SrcOp.getReg())) {
10026 bool VGPRSuffixIsHi = AMDGPU::isHi16Reg(SrcOp.getReg(), *getMRI());
10027 if (VGPRSuffixIsHi)
10028 ModVal |= SISrcMods::OP_SEL_0;
10029 } else {
10030 if ((OpSel & (1 << J)) != 0)
10031 ModVal |= SISrcMods::OP_SEL_0;
10032 }
10033
10034 if ((OpSelHi & (1 << J)) != 0)
10035 ModVal |= SISrcMods::OP_SEL_1;
10036
10037 if ((NegLo & (1 << J)) != 0)
10038 ModVal |= SISrcMods::NEG;
10039
10040 if ((NegHi & (1 << J)) != 0)
10041 ModVal |= SISrcMods::NEG_HI;
10042
10043 Inst.getOperand(ModIdx).setImm(Inst.getOperand(ModIdx).getImm() | ModVal);
10044 }
10045}
10046
10047void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst, const OperandVector &Operands) {
10048 OptionalImmIndexMap OptIdx;
10049 cvtVOP3(Inst, Operands, OptIdx);
10050 cvtVOP3P(Inst, Operands, OptIdx);
10051}
10052
10054 unsigned i, unsigned Opc,
10055 AMDGPU::OpName OpName) {
10056 if (AMDGPU::getNamedOperandIdx(Opc, OpName) != -1)
10057 ((AMDGPUOperand &)*Operands[i]).addRegOrImmWithFPInputModsOperands(Inst, 2);
10058 else
10059 ((AMDGPUOperand &)*Operands[i]).addRegOperands(Inst, 1);
10060}
10061
10062void AMDGPUAsmParser::cvtSWMMAC(MCInst &Inst, const OperandVector &Operands) {
10063 unsigned Opc = Inst.getOpcode();
10064
10065 ((AMDGPUOperand &)*Operands[1]).addRegOperands(Inst, 1);
10066 addSrcModifiersAndSrc(Inst, Operands, 2, Opc, AMDGPU::OpName::src0_modifiers);
10067 addSrcModifiersAndSrc(Inst, Operands, 3, Opc, AMDGPU::OpName::src1_modifiers);
10068 ((AMDGPUOperand &)*Operands[1]).addRegOperands(Inst, 1); // srcTiedDef
10069 ((AMDGPUOperand &)*Operands[4]).addRegOperands(Inst, 1); // src2
10070
10071 OptionalImmIndexMap OptIdx;
10072 for (unsigned i = 5; i < Operands.size(); ++i) {
10073 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
10074 OptIdx[Op.getImmTy()] = i;
10075 }
10076
10077 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::index_key_8bit))
10078 addOptionalImmOperand(Inst, Operands, OptIdx,
10079 AMDGPUOperand::ImmTyIndexKey8bit);
10080
10081 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::index_key_16bit))
10082 addOptionalImmOperand(Inst, Operands, OptIdx,
10083 AMDGPUOperand::ImmTyIndexKey16bit);
10084
10085 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::index_key_32bit))
10086 addOptionalImmOperand(Inst, Operands, OptIdx,
10087 AMDGPUOperand::ImmTyIndexKey32bit);
10088
10089 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp))
10090 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyClamp);
10091
10092 cvtVOP3P(Inst, Operands, OptIdx);
10093}
10094
10095//===----------------------------------------------------------------------===//
10096// VOPD
10097//===----------------------------------------------------------------------===//
10098
10099ParseStatus AMDGPUAsmParser::parseVOPD(OperandVector &Operands) {
10100 if (!hasVOPD(getSTI()))
10101 return ParseStatus::NoMatch;
10102
10103 if (isToken(AsmToken::Colon) && peekToken(false).is(AsmToken::Colon)) {
10104 SMLoc S = getLoc();
10105 lex();
10106 lex();
10107 Operands.push_back(AMDGPUOperand::CreateToken(this, "::", S));
10108 SMLoc OpYLoc = getLoc();
10109 StringRef OpYName;
10110 if (isToken(AsmToken::Identifier) && !Parser.parseIdentifier(OpYName)) {
10111 Operands.push_back(AMDGPUOperand::CreateToken(this, OpYName, OpYLoc));
10112 return ParseStatus::Success;
10113 }
10114 return Error(OpYLoc, "expected a VOPDY instruction after ::");
10115 }
10116 return ParseStatus::NoMatch;
10117}
10118
10119// Create VOPD MCInst operands using parsed assembler operands.
10120void AMDGPUAsmParser::cvtVOPD(MCInst &Inst, const OperandVector &Operands) {
10121 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
10122
10123 auto addOp = [&](uint16_t ParsedOprIdx) { // NOLINT:function pointer
10124 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[ParsedOprIdx]);
10126 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
10127 return;
10128 }
10129 if (Op.isReg()) {
10130 Op.addRegOperands(Inst, 1);
10131 return;
10132 }
10133 if (Op.isImm() || Op.isExpr()) {
10134 Op.addImmOperands(Inst, 1);
10135 return;
10136 }
10137 llvm_unreachable("Unhandled operand type in cvtVOPD");
10138 };
10139
10140 const auto &InstInfo = getVOPDInstInfo(Inst.getOpcode(), &MII);
10141
10142 // MCInst operands are ordered as follows:
10143 // dstX, dstY, src0X [, other OpX operands], src0Y [, other OpY operands]
10144
10145 for (auto CompIdx : VOPD::COMPONENTS) {
10146 addOp(InstInfo[CompIdx].getIndexOfDstInParsedOperands());
10147 }
10148
10149 for (auto CompIdx : VOPD::COMPONENTS) {
10150 const auto &CInfo = InstInfo[CompIdx];
10151 auto CompSrcOperandsNum = InstInfo[CompIdx].getCompParsedSrcOperandsNum();
10152 for (unsigned CompSrcIdx = 0; CompSrcIdx < CompSrcOperandsNum; ++CompSrcIdx)
10153 addOp(CInfo.getIndexOfSrcInParsedOperands(CompSrcIdx));
10154 if (CInfo.hasSrc2Acc())
10155 addOp(CInfo.getIndexOfDstInParsedOperands());
10156 }
10157
10158 int BitOp3Idx =
10159 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::bitop3);
10160 if (BitOp3Idx != -1) {
10161 OptionalImmIndexMap OptIdx;
10162 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands.back());
10163 if (Op.isImm())
10164 OptIdx[Op.getImmTy()] = Operands.size() - 1;
10165
10166 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyBitOp3);
10167 }
10168}
10169
10170//===----------------------------------------------------------------------===//
10171// dpp
10172//===----------------------------------------------------------------------===//
10173
10174bool AMDGPUOperand::isDPP8() const { return isImmTy(ImmTyDPP8); }
10175
10176bool AMDGPUOperand::isDPPCtrl() const {
10177 using namespace AMDGPU::DPP;
10178
10179 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
10180 if (result) {
10181 int64_t Imm = getImm();
10182 return (Imm >= DppCtrl::QUAD_PERM_FIRST &&
10183 Imm <= DppCtrl::QUAD_PERM_LAST) ||
10184 (Imm >= DppCtrl::ROW_SHL_FIRST && Imm <= DppCtrl::ROW_SHL_LAST) ||
10185 (Imm >= DppCtrl::ROW_SHR_FIRST && Imm <= DppCtrl::ROW_SHR_LAST) ||
10186 (Imm >= DppCtrl::ROW_ROR_FIRST && Imm <= DppCtrl::ROW_ROR_LAST) ||
10187 (Imm == DppCtrl::WAVE_SHL1) || (Imm == DppCtrl::WAVE_ROL1) ||
10188 (Imm == DppCtrl::WAVE_SHR1) || (Imm == DppCtrl::WAVE_ROR1) ||
10189 (Imm == DppCtrl::ROW_MIRROR) || (Imm == DppCtrl::ROW_HALF_MIRROR) ||
10190 (Imm == DppCtrl::BCAST15) || (Imm == DppCtrl::BCAST31) ||
10191 (Imm >= DppCtrl::ROW_SHARE_FIRST &&
10192 Imm <= DppCtrl::ROW_SHARE_LAST) ||
10193 (Imm >= DppCtrl::ROW_XMASK_FIRST && Imm <= DppCtrl::ROW_XMASK_LAST);
10194 }
10195 return false;
10196}
10197
10198//===----------------------------------------------------------------------===//
10199// mAI
10200//===----------------------------------------------------------------------===//
10201
10202bool AMDGPUOperand::isBLGP() const {
10203 return isImm() && getImmTy() == ImmTyBLGP && isUInt<3>(getImm());
10204}
10205
10206bool AMDGPUOperand::isS16Imm() const {
10207 return isImmLiteral() && (isInt<16>(getImm()) || isUInt<16>(getImm()));
10208}
10209
10210bool AMDGPUOperand::isU16Imm() const {
10211 return isImmLiteral() && isUInt<16>(getImm());
10212}
10213
10214//===----------------------------------------------------------------------===//
10215// dim
10216//===----------------------------------------------------------------------===//
10217
10218bool AMDGPUAsmParser::parseDimId(unsigned &Encoding) {
10219 // We want to allow "dim:1D" etc.,
10220 // but the initial 1 is tokenized as an integer.
10221 std::string Token;
10222 if (isToken(AsmToken::Integer)) {
10223 SMLoc Loc = getToken().getEndLoc();
10224 Token = std::string(getTokenStr());
10225 lex();
10226 if (getLoc() != Loc)
10227 return false;
10228 }
10229
10230 StringRef Suffix;
10231 if (!parseId(Suffix))
10232 return false;
10233 Token += Suffix;
10234
10235 StringRef DimId = Token;
10236 DimId.consume_front("SQ_RSRC_IMG_");
10237
10238 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByAsmSuffix(DimId);
10239 if (!DimInfo)
10240 return false;
10241
10242 Encoding = DimInfo->Encoding;
10243 return true;
10244}
10245
10246ParseStatus AMDGPUAsmParser::parseDim(OperandVector &Operands) {
10247 if (!isGFX10Plus())
10248 return ParseStatus::NoMatch;
10249
10250 SMLoc S = getLoc();
10251
10252 if (!trySkipId("dim", AsmToken::Colon))
10253 return ParseStatus::NoMatch;
10254
10255 unsigned Encoding;
10256 SMLoc Loc = getLoc();
10257 if (!parseDimId(Encoding))
10258 return Error(Loc, "invalid dim value");
10259
10260 Operands.push_back(
10261 AMDGPUOperand::CreateImm(this, Encoding, S, AMDGPUOperand::ImmTyDim));
10262 return ParseStatus::Success;
10263}
10264
10265//===----------------------------------------------------------------------===//
10266// dpp
10267//===----------------------------------------------------------------------===//
10268
10269ParseStatus AMDGPUAsmParser::parseDPP8(OperandVector &Operands) {
10270 SMLoc S = getLoc();
10271
10272 if (!isGFX10Plus() || !trySkipId("dpp8", AsmToken::Colon))
10273 return ParseStatus::NoMatch;
10274
10275 // dpp8:[%d,%d,%d,%d,%d,%d,%d,%d]
10276
10277 int64_t Sels[8];
10278
10279 if (!skipToken(AsmToken::LBrac, "expected an opening square bracket"))
10280 return ParseStatus::Failure;
10281
10282 for (size_t i = 0; i < 8; ++i) {
10283 if (i > 0 && !skipToken(AsmToken::Comma, "expected a comma"))
10284 return ParseStatus::Failure;
10285
10286 SMLoc Loc = getLoc();
10287 if (getParser().parseAbsoluteExpression(Sels[i]))
10288 return ParseStatus::Failure;
10289 if (0 > Sels[i] || 7 < Sels[i])
10290 return Error(Loc, "expected a 3-bit value");
10291 }
10292
10293 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket"))
10294 return ParseStatus::Failure;
10295
10296 unsigned DPP8 = 0;
10297 for (size_t i = 0; i < 8; ++i)
10298 DPP8 |= (Sels[i] << (i * 3));
10299
10300 Operands.push_back(
10301 AMDGPUOperand::CreateImm(this, DPP8, S, AMDGPUOperand::ImmTyDPP8));
10302 return ParseStatus::Success;
10303}
10304
10305bool AMDGPUAsmParser::isSupportedDPPCtrl(StringRef Ctrl,
10306 const OperandVector &Operands) {
10307 if (Ctrl == "row_newbcast")
10308 return isGFX90A();
10309
10310 if (Ctrl == "row_share" || Ctrl == "row_xmask")
10311 return isGFX10Plus();
10312
10313 if (Ctrl == "wave_shl" || Ctrl == "wave_shr" || Ctrl == "wave_rol" ||
10314 Ctrl == "wave_ror" || Ctrl == "row_bcast")
10315 return isVI() || isGFX9();
10316
10317 return Ctrl == "row_mirror" || Ctrl == "row_half_mirror" ||
10318 Ctrl == "quad_perm" || Ctrl == "row_shl" || Ctrl == "row_shr" ||
10319 Ctrl == "row_ror";
10320}
10321
10322int64_t AMDGPUAsmParser::parseDPPCtrlPerm() {
10323 // quad_perm:[%d,%d,%d,%d]
10324
10325 if (!skipToken(AsmToken::LBrac, "expected an opening square bracket"))
10326 return -1;
10327
10328 int64_t Val = 0;
10329 for (int i = 0; i < 4; ++i) {
10330 if (i > 0 && !skipToken(AsmToken::Comma, "expected a comma"))
10331 return -1;
10332
10333 int64_t Temp;
10334 SMLoc Loc = getLoc();
10335 if (getParser().parseAbsoluteExpression(Temp))
10336 return -1;
10337 if (Temp < 0 || Temp > 3) {
10338 Error(Loc, "expected a 2-bit value");
10339 return -1;
10340 }
10341
10342 Val += (Temp << i * 2);
10343 }
10344
10345 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket"))
10346 return -1;
10347
10348 return Val;
10349}
10350
10351int64_t AMDGPUAsmParser::parseDPPCtrlSel(StringRef Ctrl) {
10352 using namespace AMDGPU::DPP;
10353
10354 // sel:%d
10355
10356 int64_t Val;
10357 SMLoc Loc = getLoc();
10358
10359 if (getParser().parseAbsoluteExpression(Val))
10360 return -1;
10361
10362 struct DppCtrlCheck {
10363 int64_t Ctrl;
10364 int Lo;
10365 int Hi;
10366 };
10367
10368 DppCtrlCheck Check =
10369 StringSwitch<DppCtrlCheck>(Ctrl)
10370 .Case("wave_shl", {DppCtrl::WAVE_SHL1, 1, 1})
10371 .Case("wave_rol", {DppCtrl::WAVE_ROL1, 1, 1})
10372 .Case("wave_shr", {DppCtrl::WAVE_SHR1, 1, 1})
10373 .Case("wave_ror", {DppCtrl::WAVE_ROR1, 1, 1})
10374 .Case("row_shl", {DppCtrl::ROW_SHL0, 1, 15})
10375 .Case("row_shr", {DppCtrl::ROW_SHR0, 1, 15})
10376 .Case("row_ror", {DppCtrl::ROW_ROR0, 1, 15})
10377 .Case("row_share", {DppCtrl::ROW_SHARE_FIRST, 0, 15})
10378 .Case("row_xmask", {DppCtrl::ROW_XMASK_FIRST, 0, 15})
10379 .Case("row_newbcast", {DppCtrl::ROW_NEWBCAST_FIRST, 0, 15})
10380 .Default({-1, 0, 0});
10381
10382 bool Valid;
10383 if (Check.Ctrl == -1) {
10384 Valid = (Ctrl == "row_bcast" && (Val == 15 || Val == 31));
10385 Val = (Val == 15) ? DppCtrl::BCAST15 : DppCtrl::BCAST31;
10386 } else {
10387 Valid = Check.Lo <= Val && Val <= Check.Hi;
10388 Val = (Check.Lo == Check.Hi) ? Check.Ctrl : (Check.Ctrl | Val);
10389 }
10390
10391 if (!Valid) {
10392 Error(Loc, Twine("invalid ", Ctrl) + Twine(" value"));
10393 return -1;
10394 }
10395
10396 return Val;
10397}
10398
10399ParseStatus AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
10400 using namespace AMDGPU::DPP;
10401
10402 if (!isToken(AsmToken::Identifier) ||
10403 !isSupportedDPPCtrl(getTokenStr(), Operands))
10404 return ParseStatus::NoMatch;
10405
10406 SMLoc S = getLoc();
10407 int64_t Val = -1;
10408 StringRef Ctrl;
10409
10410 parseId(Ctrl);
10411
10412 if (Ctrl == "row_mirror") {
10413 Val = DppCtrl::ROW_MIRROR;
10414 } else if (Ctrl == "row_half_mirror") {
10415 Val = DppCtrl::ROW_HALF_MIRROR;
10416 } else {
10417 if (skipToken(AsmToken::Colon, "expected a colon")) {
10418 if (Ctrl == "quad_perm") {
10419 Val = parseDPPCtrlPerm();
10420 } else {
10421 Val = parseDPPCtrlSel(Ctrl);
10422 }
10423 }
10424 }
10425
10426 if (Val == -1)
10427 return ParseStatus::Failure;
10428
10429 Operands.push_back(
10430 AMDGPUOperand::CreateImm(this, Val, S, AMDGPUOperand::ImmTyDppCtrl));
10431 return ParseStatus::Success;
10432}
10433
10434void AMDGPUAsmParser::cvtVOP3DPP(MCInst &Inst, const OperandVector &Operands,
10435 bool IsDPP8) {
10436 OptionalImmIndexMap OptionalIdx;
10437 unsigned Opc = Inst.getOpcode();
10438 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
10439
10440 // MAC instructions are special because they have 'old'
10441 // operand which is not tied to dst (but assumed to be).
10442 // They also have dummy unused src2_modifiers.
10443 int OldIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::old);
10444 int Src2ModIdx =
10445 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers);
10446 bool IsMAC = OldIdx != -1 && Src2ModIdx != -1 &&
10447 Desc.getOperandConstraint(OldIdx, MCOI::TIED_TO) == -1;
10448
10449 unsigned I = 1;
10450 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
10451 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
10452 }
10453
10454 int Fi = 0;
10455 int VdstInIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
10456 bool IsVOP3CvtSrDpp = Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_dpp8_gfx12 ||
10457 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_dpp8_gfx13 ||
10458 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_dpp8_gfx12 ||
10459 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_dpp8_gfx13 ||
10460 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_dpp_gfx12 ||
10461 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_dpp_gfx13 ||
10462 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_dpp_gfx12 ||
10463 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_dpp_gfx13;
10464
10465 for (unsigned E = Operands.size(); I != E; ++I) {
10466
10467 if (IsMAC) {
10468 int NumOperands = Inst.getNumOperands();
10469 if (OldIdx == NumOperands) {
10470 // Handle old operand
10471 constexpr int DST_IDX = 0;
10472 Inst.addOperand(Inst.getOperand(DST_IDX));
10473 } else if (Src2ModIdx == NumOperands) {
10474 // Add unused dummy src2_modifiers
10476 }
10477 }
10478
10479 if (VdstInIdx == static_cast<int>(Inst.getNumOperands())) {
10480 Inst.addOperand(Inst.getOperand(0));
10481 }
10482
10483 if (IsVOP3CvtSrDpp) {
10484 if (Src2ModIdx == static_cast<int>(Inst.getNumOperands())) {
10486 Inst.addOperand(MCOperand::createReg(MCRegister()));
10487 }
10488 }
10489
10490 auto TiedTo =
10491 Desc.getOperandConstraint(Inst.getNumOperands(), MCOI::TIED_TO);
10492 if (TiedTo != -1) {
10493 assert((unsigned)TiedTo < Inst.getNumOperands());
10494 // handle tied old or src2 for MAC instructions
10495 Inst.addOperand(Inst.getOperand(TiedTo));
10496 }
10497 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
10498 // Add the register arguments
10499 if (IsDPP8 && Op.isDppFI()) {
10500 Fi = Op.getImm();
10501 } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
10502 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
10503 } else if (Op.isReg()) {
10504 Op.addRegOperands(Inst, 1);
10505 } else if (Op.isImm() &&
10506 Desc.operands()[Inst.getNumOperands()].RegClass != -1) {
10507 Op.addImmOperands(Inst, 1);
10508 } else if (Op.isImm()) {
10509 OptionalIdx[Op.getImmTy()] = I;
10510 } else {
10511 llvm_unreachable("unhandled operand type");
10512 }
10513 }
10514
10515 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp) && !IsVOP3CvtSrDpp)
10516 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10517 AMDGPUOperand::ImmTyClamp);
10518
10519 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::byte_sel)) {
10520 if (VdstInIdx == static_cast<int>(Inst.getNumOperands()))
10521 Inst.addOperand(Inst.getOperand(0));
10522 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10523 AMDGPUOperand::ImmTyByteSel);
10524 }
10525
10526 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod))
10527 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10528 AMDGPUOperand::ImmTyOModSI);
10529
10531 cvtVOP3P(Inst, Operands, OptionalIdx);
10532 else if (SIInstrFlags::isVOP3(Desc))
10533 cvtVOP3OpSel(Inst, Operands, OptionalIdx);
10534 else if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) {
10535 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10536 AMDGPUOperand::ImmTyOpSel);
10537 }
10538
10539 if (IsDPP8) {
10540 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10541 AMDGPUOperand::ImmTyDPP8);
10542 using namespace llvm::AMDGPU::DPP;
10543 Inst.addOperand(MCOperand::createImm(Fi ? DPP8_FI_1 : DPP8_FI_0));
10544 } else {
10545 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10546 AMDGPUOperand::ImmTyDppCtrl, 0xe4);
10547 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10548 AMDGPUOperand::ImmTyDppRowMask, 0xf);
10549 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10550 AMDGPUOperand::ImmTyDppBankMask, 0xf);
10551 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10552 AMDGPUOperand::ImmTyDppBoundCtrl);
10553
10554 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::fi))
10555 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10556 AMDGPUOperand::ImmTyDppFI);
10557 }
10558}
10559
10560void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands,
10561 bool IsDPP8) {
10562 OptionalImmIndexMap OptionalIdx;
10563
10564 unsigned I = 1;
10565 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
10566 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
10567 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
10568 }
10569
10570 int Fi = 0;
10571 for (unsigned E = Operands.size(); I != E; ++I) {
10572 auto TiedTo =
10573 Desc.getOperandConstraint(Inst.getNumOperands(), MCOI::TIED_TO);
10574 if (TiedTo != -1) {
10575 assert((unsigned)TiedTo < Inst.getNumOperands());
10576 // handle tied old or src2 for MAC instructions
10577 Inst.addOperand(Inst.getOperand(TiedTo));
10578 }
10579 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
10580 // Add the register arguments
10581 if (Op.isReg() && validateVccOperand(Op.getReg())) {
10582 // VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token.
10583 // Skip it.
10584 continue;
10585 }
10586
10587 if (IsDPP8) {
10588 if (Op.isDPP8()) {
10589 Op.addImmOperands(Inst, 1);
10590 } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
10591 Op.addRegWithFPInputModsOperands(Inst, 2);
10592 } else if (Op.isDppFI()) {
10593 Fi = Op.getImm();
10594 } else if (Op.isReg()) {
10595 Op.addRegOperands(Inst, 1);
10596 } else {
10597 llvm_unreachable("Invalid operand type");
10598 }
10599 } else {
10601 Op.addRegWithFPInputModsOperands(Inst, 2);
10602 } else if (Op.isReg()) {
10603 Op.addRegOperands(Inst, 1);
10604 } else if (Op.isDPPCtrl()) {
10605 Op.addImmOperands(Inst, 1);
10606 } else if (Op.isImm()) {
10607 // Handle optional arguments
10608 OptionalIdx[Op.getImmTy()] = I;
10609 } else {
10610 llvm_unreachable("Invalid operand type");
10611 }
10612 }
10613 }
10614
10615 if (IsDPP8) {
10616 using namespace llvm::AMDGPU::DPP;
10617 Inst.addOperand(MCOperand::createImm(Fi ? DPP8_FI_1 : DPP8_FI_0));
10618 } else {
10619 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10620 AMDGPUOperand::ImmTyDppRowMask, 0xf);
10621 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10622 AMDGPUOperand::ImmTyDppBankMask, 0xf);
10623 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10624 AMDGPUOperand::ImmTyDppBoundCtrl);
10625 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::fi)) {
10626 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10627 AMDGPUOperand::ImmTyDppFI);
10628 }
10629 }
10630}
10631
10632//===----------------------------------------------------------------------===//
10633// sdwa
10634//===----------------------------------------------------------------------===//
10635
10636ParseStatus AMDGPUAsmParser::parseSDWASel(OperandVector &Operands,
10637 StringRef Prefix,
10638 AMDGPUOperand::ImmTy Type) {
10639 return parseStringOrIntWithPrefix(
10640 Operands, Prefix,
10641 {"BYTE_0", "BYTE_1", "BYTE_2", "BYTE_3", "WORD_0", "WORD_1", "DWORD"},
10642 Type);
10643}
10644
10645ParseStatus AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
10646 return parseStringOrIntWithPrefix(
10647 Operands, "dst_unused", {"UNUSED_PAD", "UNUSED_SEXT", "UNUSED_PRESERVE"},
10648 AMDGPUOperand::ImmTySDWADstUnused);
10649}
10650
10651void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
10652 cvtSDWA(Inst, Operands, SDWAInstType::VOP1);
10653}
10654
10655void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
10656 cvtSDWA(Inst, Operands, SDWAInstType::VOP2);
10657}
10658
10659void AMDGPUAsmParser::cvtSdwaVOP2b(MCInst &Inst,
10660 const OperandVector &Operands) {
10661 cvtSDWA(Inst, Operands, SDWAInstType::VOP2, true, true);
10662}
10663
10664void AMDGPUAsmParser::cvtSdwaVOP2e(MCInst &Inst,
10665 const OperandVector &Operands) {
10666 cvtSDWA(Inst, Operands, SDWAInstType::VOP2, false, true);
10667}
10668
10669void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
10670 cvtSDWA(Inst, Operands, SDWAInstType::VOPC, isVI());
10671}
10672
10673void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
10674 SDWAInstType BasicInstType, bool SkipDstVcc,
10675 bool SkipSrcVcc) {
10676 using namespace llvm::AMDGPU::SDWA;
10677
10678 OptionalImmIndexMap OptionalIdx;
10679 bool SkipVcc = SkipDstVcc || SkipSrcVcc;
10680 bool SkippedVcc = false;
10681
10682 unsigned I = 1;
10683 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
10684 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
10685 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
10686 }
10687
10688 for (unsigned E = Operands.size(); I != E; ++I) {
10689 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
10690 if (SkipVcc && !SkippedVcc && Op.isReg() &&
10691 (Op.getReg() == AMDGPU::VCC || Op.getReg() == AMDGPU::VCC_LO)) {
10692 // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst.
10693 // Skip it if it's 2nd (e.g. v_add_i32_sdwa v1, vcc, v2, v3)
10694 // or 4th (v_addc_u32_sdwa v1, vcc, v2, v3, vcc) operand.
10695 // Skip VCC only if we didn't skip it on previous iteration.
10696 // Note that src0 and src1 occupy 2 slots each because of modifiers.
10697 if (BasicInstType == SDWAInstType::VOP2 &&
10698 ((SkipDstVcc && Inst.getNumOperands() == 1) ||
10699 (SkipSrcVcc && Inst.getNumOperands() == 5))) {
10700 SkippedVcc = true;
10701 continue;
10702 }
10703 if (BasicInstType == SDWAInstType::VOPC && Inst.getNumOperands() == 0) {
10704 SkippedVcc = true;
10705 continue;
10706 }
10707 }
10709 Op.addRegOrImmWithInputModsOperands(Inst, 2);
10710 } else if (Op.isImm()) {
10711 // Handle optional arguments
10712 OptionalIdx[Op.getImmTy()] = I;
10713 } else {
10714 llvm_unreachable("Invalid operand type");
10715 }
10716 SkippedVcc = false;
10717 }
10718
10719 const unsigned Opc = Inst.getOpcode();
10720 if (Opc != AMDGPU::V_NOP_sdwa_gfx10 && Opc != AMDGPU::V_NOP_sdwa_gfx9 &&
10721 Opc != AMDGPU::V_NOP_sdwa_vi) {
10722 // v_nop_sdwa_sdwa_vi/gfx9 has no optional sdwa arguments
10723 switch (BasicInstType) {
10724 case SDWAInstType::VOP1:
10725 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp))
10726 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10727 AMDGPUOperand::ImmTyClamp, 0);
10728
10729 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod))
10730 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10731 AMDGPUOperand::ImmTyOModSI, 0);
10732
10733 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::dst_sel))
10734 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10735 AMDGPUOperand::ImmTySDWADstSel, SdwaSel::DWORD);
10736
10737 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::dst_unused))
10738 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10739 AMDGPUOperand::ImmTySDWADstUnused,
10740 DstUnused::UNUSED_PRESERVE);
10741
10742 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10743 AMDGPUOperand::ImmTySDWASrc0Sel, SdwaSel::DWORD);
10744 break;
10745
10746 case SDWAInstType::VOP2:
10747 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10748 AMDGPUOperand::ImmTyClamp, 0);
10749
10750 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::omod))
10751 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10752 AMDGPUOperand::ImmTyOModSI, 0);
10753
10754 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10755 AMDGPUOperand::ImmTySDWADstSel, SdwaSel::DWORD);
10756 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10757 AMDGPUOperand::ImmTySDWADstUnused,
10758 DstUnused::UNUSED_PRESERVE);
10759 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10760 AMDGPUOperand::ImmTySDWASrc0Sel, SdwaSel::DWORD);
10761 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10762 AMDGPUOperand::ImmTySDWASrc1Sel, SdwaSel::DWORD);
10763 break;
10764
10765 case SDWAInstType::VOPC:
10766 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::clamp))
10767 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10768 AMDGPUOperand::ImmTyClamp, 0);
10769 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10770 AMDGPUOperand::ImmTySDWASrc0Sel, SdwaSel::DWORD);
10771 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10772 AMDGPUOperand::ImmTySDWASrc1Sel, SdwaSel::DWORD);
10773 break;
10774 }
10775 }
10776
10777 // special case v_mac_{f16, f32}:
10778 // it has src2 register operand that is tied to dst operand
10779 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
10780 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
10781 auto *it = Inst.begin();
10782 std::advance(
10783 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
10784 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
10785 }
10786}
10787
10788/// Force static initialization.
10789extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
10795
10796#define GET_MATCHER_IMPLEMENTATION
10797#define GET_MNEMONIC_SPELL_CHECKER
10798#define GET_MNEMONIC_CHECKER
10799#include "AMDGPUGenAsmMatcher.inc"
10800
10801ParseStatus AMDGPUAsmParser::parseCustomOperand(OperandVector &Operands,
10802 unsigned MCK) {
10803 switch (MCK) {
10804 case MCK_addr64:
10805 return parseTokenOp("addr64", Operands);
10806 case MCK_done:
10807 return parseNamedBit("done", Operands, AMDGPUOperand::ImmTyDone, true);
10808 case MCK_idxen:
10809 return parseTokenOp("idxen", Operands);
10810 case MCK_lds:
10811 return parseNamedBit("lds", Operands, AMDGPUOperand::ImmTyLDS,
10812 /*IgnoreNegative=*/true);
10813 case MCK_offen:
10814 return parseTokenOp("offen", Operands);
10815 case MCK_off:
10816 return parseTokenOp("off", Operands);
10817 case MCK_row_95_en:
10818 return parseNamedBit("row_en", Operands, AMDGPUOperand::ImmTyRowEn, true);
10819 case MCK_gds:
10820 return parseNamedBit("gds", Operands, AMDGPUOperand::ImmTyGDS);
10821 case MCK_tfe:
10822 return parseNamedBit("tfe", Operands, AMDGPUOperand::ImmTyTFE);
10823 }
10824 return tryCustomParseOperand(Operands, MCK);
10825}
10826
10827// This function should be defined after auto-generated include so that we have
10828// MatchClassKind enum defined
10829unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
10830 unsigned Kind) {
10831 // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
10832 // But MatchInstructionImpl() expects to meet token and fails to validate
10833 // operand. This method checks if we are given immediate operand but expect to
10834 // get corresponding token.
10835 AMDGPUOperand &Operand = (AMDGPUOperand &)Op;
10836 switch (Kind) {
10837 case MCK_addr64:
10838 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
10839 case MCK_gds:
10840 return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
10841 case MCK_lds:
10842 return Operand.isLDS() ? Match_Success : Match_InvalidOperand;
10843 case MCK_idxen:
10844 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
10845 case MCK_offen:
10846 return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
10847 case MCK_tfe:
10848 return Operand.isTFE() ? Match_Success : Match_InvalidOperand;
10849 case MCK_done:
10850 return Operand.isDone() ? Match_Success : Match_InvalidOperand;
10851 case MCK_row_95_en:
10852 return Operand.isRowEn() ? Match_Success : Match_InvalidOperand;
10853 case MCK_SSrc_b32:
10854 // When operands have expression values, they will return true for isToken,
10855 // because it is not possible to distinguish between a token and an
10856 // expression at parse time. MatchInstructionImpl() will always try to
10857 // match an operand as a token, when isToken returns true, and when the
10858 // name of the expression is not a valid token, the match will fail,
10859 // so we need to handle it here.
10860 return Operand.isSSrc_b32() ? Match_Success : Match_InvalidOperand;
10861 case MCK_SSrc_f32:
10862 return Operand.isSSrc_f32() ? Match_Success : Match_InvalidOperand;
10863 case MCK_SOPPBrTarget:
10864 return Operand.isSOPPBrTarget() ? Match_Success : Match_InvalidOperand;
10865 case MCK_VReg32OrOff:
10866 return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand;
10867 case MCK_InterpSlot:
10868 return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand;
10869 case MCK_InterpAttr:
10870 return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
10871 case MCK_InterpAttrChan:
10872 return Operand.isInterpAttrChan() ? Match_Success : Match_InvalidOperand;
10873 case MCK_SReg_64:
10874 case MCK_SReg_64_XEXEC:
10875 // Null is defined as a 32-bit register but
10876 // it should also be enabled with 64-bit operands or larger.
10877 // The following code enables it for SReg_64 and larger operands
10878 // used as source and destination. Remaining source
10879 // operands are handled in isInlinableImm.
10880 case MCK_SReg_96:
10881 case MCK_SReg_128:
10882 case MCK_SReg_256:
10883 case MCK_SReg_512:
10884 return Operand.isNull() ? Match_Success : Match_InvalidOperand;
10885 default:
10886 return Match_InvalidOperand;
10887 }
10888}
10889
10890//===----------------------------------------------------------------------===//
10891// endpgm
10892//===----------------------------------------------------------------------===//
10893
10894ParseStatus AMDGPUAsmParser::parseEndpgm(OperandVector &Operands) {
10895 SMLoc S = getLoc();
10896 int64_t Imm = 0;
10897
10898 if (!parseExpr(Imm)) {
10899 // The operand is optional, if not present default to 0
10900 Imm = 0;
10901 }
10902
10903 if (!isUInt<16>(Imm))
10904 return Error(S, "expected a 16-bit value");
10905
10906 Operands.push_back(
10907 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyEndpgm));
10908 return ParseStatus::Success;
10909}
10910
10911bool AMDGPUOperand::isEndpgm() const { return isImmTy(ImmTyEndpgm); }
10912
10913//===----------------------------------------------------------------------===//
10914// Split Barrier
10915//===----------------------------------------------------------------------===//
10916
10917bool AMDGPUOperand::isSplitBarrier() const {
10918 if (!isImm())
10919 return false;
10920
10921 int64_t Imm = getImm();
10924}
#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)
uint64_t 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:327
#define LLVM_ABI
Definition Compiler.h:211
#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:254
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:480
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:6045
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,...