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