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