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