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 = "");
1894 bool parseExpr(OperandVector &Operands);
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 MCRegister();
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
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
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)
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.
4922 if (isPackedFP32Inst(Opc) && isGFX12Plus()) {
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 ||
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
5793static bool isInvalidVOPDY(const OperandVector &Operands,
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,
5805 OperandVector &Operands,
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[] = {GLOBAL_PREFETCH_B8_SADDR_gfx1250,
6988 V_NOP_e32_gfx12};
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.take_front(std::size(Required)) != ArrayRef(Required)) {
6994 Warning(Loc, "kernel '" + Sym->getName() +
6995 "' does not begin with the required prologue "
6996 "sequence: GLOBAL_PREFETCH_B8 followed by V_NOP");
6997 }
6998 }
6999 }
7000 OpcodeStream.clear();
7001 OpcodeStreamSymbols.clear();
7002 AMDHSAKernelSymbols.clear();
7003}
7004
7005void AMDGPUAsmParser::onEndOfFile() {
7006 emitTargetDirective();
7007 checkKernelPrologues();
7008 if (InfoData)
7009 getTargetStreamer().emitAMDGPUInfo(*InfoData);
7010}
7011
7012bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
7013 StringRef IDVal = DirectiveID.getString();
7014
7015 if (isHsaAbi(getSTI())) {
7016 if (IDVal == ".amdhsa_kernel")
7017 return ParseDirectiveAMDHSAKernel();
7018
7019 if (IDVal == ".amdhsa_code_object_version")
7020 return ParseDirectiveAMDHSACodeObjectVersion();
7021
7022 // TODO: Restructure/combine with PAL metadata directive.
7024 return ParseDirectiveHSAMetadata();
7025 } else {
7026 if (IDVal == ".amd_kernel_code_t")
7027 return ParseDirectiveAMDKernelCodeT();
7028
7029 if (IDVal == ".amdgpu_hsa_kernel")
7030 return ParseDirectiveAMDGPUHsaKernel();
7031
7032 if (IDVal == ".amd_amdgpu_isa")
7033 return ParseDirectiveISAVersion();
7034
7036 return Error(getLoc(), (Twine(HSAMD::AssemblerDirectiveBegin) +
7037 Twine(" directive is "
7038 "not available on non-amdhsa OSes"))
7039 .str());
7040 }
7041 }
7042
7043 if (IDVal == ".amdgcn_target")
7044 return ParseDirectiveAMDGCNTarget();
7045
7046 if (IDVal == ".amdgpu_lds")
7047 return ParseDirectiveAMDGPULDS();
7048
7049 if (IDVal == ".amdgpu_info")
7050 return ParseDirectiveAMDGPUInfo();
7051
7052 if (IDVal == PALMD::AssemblerDirectiveBegin)
7053 return ParseDirectivePALMetadataBegin();
7054
7055 if (IDVal == PALMD::AssemblerDirective)
7056 return ParseDirectivePALMetadata();
7057
7058 return true;
7059}
7060
7061bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
7062 MCRegister Reg) {
7063 if (MRI.regsOverlap(TTMP12_TTMP13_TTMP14_TTMP15, Reg))
7064 return isGFX9Plus();
7065
7066 // GFX10+ has 2 more SGPRs 104 and 105.
7067 if (MRI.regsOverlap(SGPR104_SGPR105, Reg))
7068 return hasSGPR104_SGPR105();
7069
7070 switch (Reg.id()) {
7071 case SRC_SHARED_BASE_LO:
7072 case SRC_SHARED_BASE:
7073 case SRC_SHARED_LIMIT_LO:
7074 case SRC_SHARED_LIMIT:
7075 case SRC_PRIVATE_BASE_LO:
7076 case SRC_PRIVATE_BASE:
7077 case SRC_PRIVATE_LIMIT_LO:
7078 case SRC_PRIVATE_LIMIT:
7079 return isGFX9Plus();
7080 case SRC_FLAT_SCRATCH_BASE_LO:
7081 case SRC_FLAT_SCRATCH_BASE_HI:
7082 return hasGloballyAddressableScratch();
7083 case SRC_POPS_EXITING_WAVE_ID:
7084 return isGFX9Plus() && !isGFX11Plus();
7085 case TBA:
7086 case TBA_LO:
7087 case TBA_HI:
7088 case TMA:
7089 case TMA_LO:
7090 case TMA_HI:
7091 return !isGFX9Plus();
7092 case XNACK_MASK:
7093 case XNACK_MASK_LO:
7094 case XNACK_MASK_HI:
7095 return (isVI() || isGFX9()) &&
7096 getTargetStreamer().getTargetID()->isXnackSupported();
7097 case SGPR_NULL:
7098 return isGFX10Plus();
7099 case SRC_EXECZ:
7100 case SRC_VCCZ:
7101 return !isGFX11Plus();
7102 default:
7103 break;
7104 }
7105
7106 if (isCI())
7107 return true;
7108
7109 if (isSI() || isGFX10Plus()) {
7110 // No flat_scr on SI.
7111 // On GFX10Plus flat scratch is not a valid register operand and can only be
7112 // accessed with s_setreg/s_getreg.
7113 switch (Reg.id()) {
7114 case FLAT_SCR:
7115 case FLAT_SCR_LO:
7116 case FLAT_SCR_HI:
7117 return false;
7118 default:
7119 return true;
7120 }
7121 }
7122
7123 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
7124 // SI/CI have.
7125 if (MRI.regsOverlap(SGPR102_SGPR103, Reg))
7126 return hasSGPR102_SGPR103();
7127
7128 return true;
7129}
7130
7131ParseStatus AMDGPUAsmParser::parseOperand(OperandVector &Operands,
7132 StringRef Mnemonic,
7133 OperandMode Mode) {
7134 ParseStatus Res = parseVOPD(Operands);
7135 if (Res.isSuccess() || Res.isFailure() || isToken(AsmToken::EndOfStatement))
7136 return Res;
7137
7138 // Try to parse with a custom parser
7139 Res = MatchOperandParserImpl(Operands, Mnemonic);
7140
7141 // If we successfully parsed the operand or if there as an error parsing,
7142 // we are done.
7143 //
7144 // If we are parsing after we reach EndOfStatement then this means we
7145 // are appending default values to the Operands list. This is only done
7146 // by custom parser, so we shouldn't continue on to the generic parsing.
7147 if (Res.isSuccess() || Res.isFailure() || isToken(AsmToken::EndOfStatement))
7148 return Res;
7149
7150 SMLoc RBraceLoc;
7151 SMLoc LBraceLoc = getLoc();
7152 if (Mode == OperandMode_NSA && trySkipToken(AsmToken::LBrac)) {
7153 unsigned Prefix = Operands.size();
7154
7155 for (;;) {
7156 auto Loc = getLoc();
7157 Res = parseReg(Operands);
7158 if (Res.isNoMatch())
7159 Error(Loc, "expected a register");
7160 if (!Res.isSuccess())
7161 return ParseStatus::Failure;
7162
7163 RBraceLoc = getLoc();
7164 if (trySkipToken(AsmToken::RBrac))
7165 break;
7166
7167 if (!skipToken(AsmToken::Comma,
7168 "expected a comma or a closing square bracket"))
7169 return ParseStatus::Failure;
7170 }
7171
7172 if (Operands.size() - Prefix > 1) {
7173 Operands.insert(Operands.begin() + Prefix,
7174 AMDGPUOperand::CreateToken(this, "[", LBraceLoc));
7175 Operands.push_back(AMDGPUOperand::CreateToken(this, "]", RBraceLoc));
7176 }
7177
7178 return ParseStatus::Success;
7179 }
7180
7181 return parseRegOrImm(Operands);
7182}
7183
7184StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
7185 // Clear any forced encodings from the previous instruction.
7186 setForcedEncodingSize(0);
7187 setForcedDPP(false);
7188 setForcedSDWA(false);
7189
7190 if (Name.consume_back("_e64_dpp")) {
7191 setForcedDPP(true);
7192 setForcedEncodingSize(64);
7193 return Name;
7194 }
7195 if (Name.consume_back("_e64")) {
7196 setForcedEncodingSize(64);
7197 return Name;
7198 }
7199 if (Name.consume_back("_e32")) {
7200 setForcedEncodingSize(32);
7201 return Name;
7202 }
7203 if (Name.consume_back("_dpp")) {
7204 setForcedDPP(true);
7205 return Name;
7206 }
7207 if (Name.consume_back("_sdwa")) {
7208 setForcedSDWA(true);
7209 return Name;
7210 }
7211 return Name;
7212}
7213
7214static void applyMnemonicAliases(StringRef &Mnemonic,
7215 const FeatureBitset &Features,
7216 unsigned VariantID);
7217
7218bool AMDGPUAsmParser::parseInstruction(ParseInstructionInfo &Info,
7219 StringRef Name, SMLoc NameLoc,
7220 OperandVector &Operands) {
7221 // Add the instruction mnemonic
7222 Name = parseMnemonicSuffix(Name);
7223
7224 // If the target architecture uses MnemonicAlias, call it here to parse
7225 // operands correctly.
7226 applyMnemonicAliases(Name, getAvailableFeatures(), 0);
7227
7228 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc));
7229
7230 bool IsMIMG = Name.starts_with("image_");
7231
7232 while (!trySkipToken(AsmToken::EndOfStatement)) {
7233 OperandMode Mode = OperandMode_Default;
7234 if (IsMIMG && isGFX10Plus() && Operands.size() == 2)
7235 Mode = OperandMode_NSA;
7236 ParseStatus Res = parseOperand(Operands, Name, Mode);
7237
7238 if (!Res.isSuccess()) {
7239 checkUnsupportedInstruction(Name, NameLoc);
7240 if (!Parser.hasPendingError()) {
7241 // FIXME: use real operand location rather than the current location.
7242 StringRef Msg = Res.isFailure() ? "failed parsing operand."
7243 : "not a valid operand.";
7244 Error(getLoc(), Msg);
7245 }
7246 while (!trySkipToken(AsmToken::EndOfStatement)) {
7247 lex();
7248 }
7249 return true;
7250 }
7251
7252 // Eat the comma or space if there is one.
7253 trySkipToken(AsmToken::Comma);
7254 }
7255
7256 return false;
7257}
7258
7259//===----------------------------------------------------------------------===//
7260// Utility functions
7261//===----------------------------------------------------------------------===//
7262
7263ParseStatus AMDGPUAsmParser::parseTokenOp(StringRef Name,
7264 OperandVector &Operands) {
7265 SMLoc S = getLoc();
7266 if (!trySkipId(Name))
7267 return ParseStatus::NoMatch;
7268
7269 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, S));
7270 return ParseStatus::Success;
7271}
7272
7273ParseStatus AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix,
7274 int64_t &IntVal) {
7275
7276 if (!trySkipId(Prefix, AsmToken::Colon))
7277 return ParseStatus::NoMatch;
7278
7280}
7281
7282ParseStatus AMDGPUAsmParser::parseIntWithPrefix(
7283 const char *Prefix, OperandVector &Operands, AMDGPUOperand::ImmTy ImmTy,
7284 std::function<bool(int64_t &)> ConvertResult) {
7285 SMLoc S = getLoc();
7286 int64_t Value = 0;
7287
7288 ParseStatus Res = parseIntWithPrefix(Prefix, Value);
7289 if (!Res.isSuccess())
7290 return Res;
7291
7292 if (ConvertResult && !ConvertResult(Value)) {
7293 Error(S, "invalid " + StringRef(Prefix) + " value.");
7294 }
7295
7296 Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy));
7297 return ParseStatus::Success;
7298}
7299
7300ParseStatus AMDGPUAsmParser::parseOperandArrayWithPrefix(
7301 const char *Prefix, OperandVector &Operands, AMDGPUOperand::ImmTy ImmTy,
7302 bool (*ConvertResult)(int64_t &)) {
7303 SMLoc S = getLoc();
7304 if (!trySkipId(Prefix, AsmToken::Colon))
7305 return ParseStatus::NoMatch;
7306
7307 if (!skipToken(AsmToken::LBrac, "expected a left square bracket"))
7308 return ParseStatus::Failure;
7309
7310 unsigned Val = 0;
7311 const unsigned MaxSize = 4;
7312
7313 // FIXME: How to verify the number of elements matches the number of src
7314 // operands?
7315 for (int I = 0;; ++I) {
7316 int64_t Op;
7317 SMLoc Loc = getLoc();
7318 if (!parseExpr(Op))
7319 return ParseStatus::Failure;
7320
7321 if (Op != 0 && Op != 1)
7322 return Error(Loc, "invalid " + StringRef(Prefix) + " value.");
7323
7324 Val |= (Op << I);
7325
7326 if (trySkipToken(AsmToken::RBrac))
7327 break;
7328
7329 if (I + 1 == MaxSize)
7330 return Error(getLoc(), "expected a closing square bracket");
7331
7332 if (!skipToken(AsmToken::Comma, "expected a comma"))
7333 return ParseStatus::Failure;
7334 }
7335
7336 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, ImmTy));
7337 return ParseStatus::Success;
7338}
7339
7340ParseStatus AMDGPUAsmParser::parseNamedBit(StringRef Name,
7341 OperandVector &Operands,
7342 AMDGPUOperand::ImmTy ImmTy,
7343 bool IgnoreNegative) {
7344 int64_t Bit;
7345 SMLoc S = getLoc();
7346
7347 if (trySkipId(Name)) {
7348 Bit = 1;
7349 } else if (trySkipId("no", Name)) {
7350 if (IgnoreNegative)
7351 return ParseStatus::Success;
7352 Bit = 0;
7353 } else {
7354 return ParseStatus::NoMatch;
7355 }
7356
7357 if (Name == "r128" && !hasMIMG_R128())
7358 return Error(S, "r128 modifier is not supported on this GPU");
7359 if (Name == "a16" && !hasA16())
7360 return Error(S, "a16 modifier is not supported on this GPU");
7361
7362 if (Bit == 0 && Name == "gds") {
7363 StringRef Mnemo = ((AMDGPUOperand &)*Operands[0]).getToken();
7364 if (Mnemo.starts_with("ds_gws"))
7365 return Error(S, "nogds is not allowed");
7366 }
7367
7368 if (isGFX9() && ImmTy == AMDGPUOperand::ImmTyA16)
7369 ImmTy = AMDGPUOperand::ImmTyR128A16;
7370
7371 Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy));
7372 return ParseStatus::Success;
7373}
7374
7375unsigned AMDGPUAsmParser::getCPolKind(StringRef Id, StringRef Mnemo,
7376 bool &Disabling) const {
7377 Disabling = Id.consume_front("no");
7378
7379 if (isGFX940() && !Mnemo.starts_with("s_")) {
7380 return StringSwitch<unsigned>(Id)
7381 .Case("nt", AMDGPU::CPol::NT)
7382 .Case("sc0", AMDGPU::CPol::SC0)
7383 .Case("sc1", AMDGPU::CPol::SC1)
7384 .Default(0);
7385 }
7386
7387 return StringSwitch<unsigned>(Id)
7388 .Case("dlc", AMDGPU::CPol::DLC)
7389 .Case("glc", AMDGPU::CPol::GLC)
7390 .Case("scc", AMDGPU::CPol::SCC)
7391 .Case("slc", AMDGPU::CPol::SLC)
7392 .Default(0);
7393}
7394
7395ParseStatus AMDGPUAsmParser::parseCPol(OperandVector &Operands) {
7396 if (isGFX12Plus()) {
7397 SMLoc StringLoc = getLoc();
7398
7399 int64_t CPolVal = 0;
7400 ParseStatus ResTH = ParseStatus::NoMatch;
7401 ParseStatus ResScope = ParseStatus::NoMatch;
7402 ParseStatus ResNV = ParseStatus::NoMatch;
7403 ParseStatus ResScal = ParseStatus::NoMatch;
7404
7405 for (;;) {
7406 if (ResTH.isNoMatch()) {
7407 int64_t TH;
7408 ResTH = parseTH(Operands, TH);
7409 if (ResTH.isFailure())
7410 return ResTH;
7411 if (ResTH.isSuccess()) {
7412 CPolVal |= TH;
7413 continue;
7414 }
7415 }
7416
7417 if (ResScope.isNoMatch()) {
7418 int64_t Scope;
7419 ResScope = parseScope(Operands, Scope);
7420 if (ResScope.isFailure())
7421 return ResScope;
7422 if (ResScope.isSuccess()) {
7423 CPolVal |= Scope;
7424 continue;
7425 }
7426 }
7427
7428 // NV bit exists on GFX12+, but does something starting from GFX1250.
7429 // Allow parsing on all GFX12 and fail on validation for better
7430 // diagnostics.
7431 if (ResNV.isNoMatch()) {
7432 if (trySkipId("nv")) {
7433 ResNV = ParseStatus::Success;
7434 CPolVal |= CPol::NV;
7435 continue;
7436 } else if (trySkipId("no", "nv")) {
7437 ResNV = ParseStatus::Success;
7438 continue;
7439 }
7440 }
7441
7442 if (ResScal.isNoMatch()) {
7443 if (trySkipId("scale_offset")) {
7444 ResScal = ParseStatus::Success;
7445 CPolVal |= CPol::SCAL;
7446 continue;
7447 } else if (trySkipId("no", "scale_offset")) {
7448 ResScal = ParseStatus::Success;
7449 continue;
7450 }
7451 }
7452
7453 break;
7454 }
7455
7456 if (ResTH.isNoMatch() && ResScope.isNoMatch() && ResNV.isNoMatch() &&
7457 ResScal.isNoMatch())
7458 return ParseStatus::NoMatch;
7459
7460 Operands.push_back(AMDGPUOperand::CreateImm(this, CPolVal, StringLoc,
7461 AMDGPUOperand::ImmTyCPol));
7462 return ParseStatus::Success;
7463 }
7464
7465 StringRef Mnemo = ((AMDGPUOperand &)*Operands[0]).getToken();
7466 SMLoc OpLoc = getLoc();
7467 unsigned Enabled = 0, Seen = 0;
7468 for (;;) {
7469 SMLoc S = getLoc();
7470 bool Disabling;
7471 unsigned CPol = getCPolKind(getId(), Mnemo, Disabling);
7472 if (!CPol)
7473 break;
7474
7475 lex();
7476
7477 if (!isGFX10Plus() && CPol == AMDGPU::CPol::DLC)
7478 return Error(S, "dlc modifier is not supported on this GPU");
7479
7480 if (!isGFX90A() && CPol == AMDGPU::CPol::SCC)
7481 return Error(S, "scc modifier is not supported on this GPU");
7482
7483 if (Seen & CPol)
7484 return Error(S, "duplicate cache policy modifier");
7485
7486 if (!Disabling)
7487 Enabled |= CPol;
7488
7489 Seen |= CPol;
7490 }
7491
7492 if (!Seen)
7493 return ParseStatus::NoMatch;
7494
7495 Operands.push_back(
7496 AMDGPUOperand::CreateImm(this, Enabled, OpLoc, AMDGPUOperand::ImmTyCPol));
7497 return ParseStatus::Success;
7498}
7499
7500ParseStatus AMDGPUAsmParser::parseScope(OperandVector &Operands,
7501 int64_t &Scope) {
7502 static const unsigned Scopes[] = {CPol::SCOPE_CU, CPol::SCOPE_SE,
7504
7505 ParseStatus Res = parseStringOrIntWithPrefix(
7506 Operands, "scope", {"SCOPE_CU", "SCOPE_SE", "SCOPE_DEV", "SCOPE_SYS"},
7507 Scope);
7508
7509 if (Res.isSuccess())
7510 Scope = Scopes[Scope];
7511
7512 return Res;
7513}
7514
7515ParseStatus AMDGPUAsmParser::parseTH(OperandVector &Operands, int64_t &TH) {
7516 TH = AMDGPU::CPol::TH_RT; // default
7517
7518 StringRef Value;
7519 SMLoc StringLoc;
7520 ParseStatus Res = parseStringWithPrefix("th", Value, StringLoc);
7521 if (!Res.isSuccess())
7522 return Res;
7523
7524 if (Value == "TH_DEFAULT")
7526 else if (Value == "TH_STORE_LU" || Value == "TH_LOAD_WB" ||
7527 Value == "TH_LOAD_NT_WB") {
7528 return Error(StringLoc, "invalid th value");
7529 } else if (Value.consume_front("TH_ATOMIC_")) {
7531 } else if (Value.consume_front("TH_LOAD_")) {
7533 } else if (Value.consume_front("TH_STORE_")) {
7535 } else {
7536 return Error(StringLoc, "invalid th value");
7537 }
7538
7539 if (Value == "BYPASS")
7541
7542 if (TH != 0) {
7544 TH |= StringSwitch<int64_t>(Value)
7545 .Case("RETURN", AMDGPU::CPol::TH_ATOMIC_RETURN)
7546 .Case("RT", AMDGPU::CPol::TH_RT)
7547 .Case("RT_RETURN", AMDGPU::CPol::TH_ATOMIC_RETURN)
7548 .Case("NT", AMDGPU::CPol::TH_ATOMIC_NT)
7549 .Case("NT_RETURN", AMDGPU::CPol::TH_ATOMIC_NT |
7551 .Case("CASCADE_RT", AMDGPU::CPol::TH_ATOMIC_CASCADE)
7552 .Case("CASCADE_NT", AMDGPU::CPol::TH_ATOMIC_CASCADE |
7554 .Default(0xffffffff);
7555 else
7556 TH |= StringSwitch<int64_t>(Value)
7557 .Case("RT", AMDGPU::CPol::TH_RT)
7558 .Case("NT", AMDGPU::CPol::TH_NT)
7559 .Case("HT", AMDGPU::CPol::TH_HT)
7560 .Case("LU", AMDGPU::CPol::TH_LU)
7561 .Case("WB", AMDGPU::CPol::TH_WB)
7562 .Case("NT_RT", AMDGPU::CPol::TH_NT_RT)
7563 .Case("RT_NT", AMDGPU::CPol::TH_RT_NT)
7564 .Case("NT_HT", AMDGPU::CPol::TH_NT_HT)
7565 .Case("NT_WB", AMDGPU::CPol::TH_NT_WB)
7566 .Case("BYPASS", AMDGPU::CPol::TH_BYPASS)
7567 .Default(0xffffffff);
7568 }
7569
7570 if (TH == 0xffffffff)
7571 return Error(StringLoc, "invalid th value");
7572
7573 return ParseStatus::Success;
7574}
7575
7576static void
7578 AMDGPUAsmParser::OptionalImmIndexMap &OptionalIdx,
7579 AMDGPUOperand::ImmTy ImmT, int64_t Default = 0,
7580 std::optional<unsigned> InsertAt = std::nullopt) {
7581 auto i = OptionalIdx.find(ImmT);
7582 if (i != OptionalIdx.end()) {
7583 unsigned Idx = i->second;
7584 const AMDGPUOperand &Op =
7585 static_cast<const AMDGPUOperand &>(*Operands[Idx]);
7586 if (InsertAt)
7587 Inst.insert(Inst.begin() + *InsertAt, MCOperand::createImm(Op.getImm()));
7588 else
7589 Op.addImmOperands(Inst, 1);
7590 } else {
7591 if (InsertAt.has_value())
7592 Inst.insert(Inst.begin() + *InsertAt, MCOperand::createImm(Default));
7593 else
7595 }
7596}
7597
7598ParseStatus AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix,
7599 StringRef &Value,
7600 SMLoc &StringLoc) {
7601 if (!trySkipId(Prefix, AsmToken::Colon))
7602 return ParseStatus::NoMatch;
7603
7604 StringLoc = getLoc();
7605 return parseId(Value, "expected an identifier") ? ParseStatus::Success
7607}
7608
7609ParseStatus AMDGPUAsmParser::parseStringOrIntWithPrefix(
7610 OperandVector &Operands, StringRef Name, ArrayRef<const char *> Ids,
7611 int64_t &IntVal) {
7612 if (!trySkipId(Name, AsmToken::Colon))
7613 return ParseStatus::NoMatch;
7614
7615 SMLoc StringLoc = getLoc();
7616
7617 StringRef Value;
7618 if (isToken(AsmToken::Identifier)) {
7619 Value = getTokenStr();
7620 lex();
7621
7622 for (IntVal = 0; IntVal < (int64_t)Ids.size(); ++IntVal)
7623 if (Value == Ids[IntVal])
7624 break;
7625 } else if (!parseExpr(IntVal))
7626 return ParseStatus::Failure;
7627
7628 if (IntVal < 0 || IntVal >= (int64_t)Ids.size())
7629 return Error(StringLoc, "invalid " + Twine(Name) + " value");
7630
7631 return ParseStatus::Success;
7632}
7633
7634ParseStatus AMDGPUAsmParser::parseStringOrIntWithPrefix(
7635 OperandVector &Operands, StringRef Name, ArrayRef<const char *> Ids,
7636 AMDGPUOperand::ImmTy Type) {
7637 SMLoc S = getLoc();
7638 int64_t IntVal;
7639
7640 ParseStatus Res = parseStringOrIntWithPrefix(Operands, Name, Ids, IntVal);
7641 if (Res.isSuccess())
7642 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S, Type));
7643
7644 return Res;
7645}
7646
7647//===----------------------------------------------------------------------===//
7648// MTBUF format
7649//===----------------------------------------------------------------------===//
7650
7651bool AMDGPUAsmParser::tryParseFmt(const char *Pref, int64_t MaxVal,
7652 int64_t &Fmt) {
7653 int64_t Val;
7654 SMLoc Loc = getLoc();
7655
7656 auto Res = parseIntWithPrefix(Pref, Val);
7657 if (Res.isFailure())
7658 return false;
7659 if (Res.isNoMatch())
7660 return true;
7661
7662 if (Val < 0 || Val > MaxVal) {
7663 Error(Loc, Twine("out of range ", StringRef(Pref)));
7664 return false;
7665 }
7666
7667 Fmt = Val;
7668 return true;
7669}
7670
7671ParseStatus AMDGPUAsmParser::tryParseIndexKey(OperandVector &Operands,
7672 AMDGPUOperand::ImmTy ImmTy) {
7673 const char *Pref = "index_key";
7674 int64_t ImmVal = 0;
7675 SMLoc Loc = getLoc();
7676 auto Res = parseIntWithPrefix(Pref, ImmVal);
7677 if (!Res.isSuccess())
7678 return Res;
7679
7680 if ((ImmTy == AMDGPUOperand::ImmTyIndexKey16bit ||
7681 ImmTy == AMDGPUOperand::ImmTyIndexKey32bit) &&
7682 (ImmVal < 0 || ImmVal > 1))
7683 return Error(Loc, Twine("out of range ", StringRef(Pref)));
7684
7685 if (ImmTy == AMDGPUOperand::ImmTyIndexKey8bit && (ImmVal < 0 || ImmVal > 3))
7686 return Error(Loc, Twine("out of range ", StringRef(Pref)));
7687
7688 Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc, ImmTy));
7689 return ParseStatus::Success;
7690}
7691
7692ParseStatus AMDGPUAsmParser::parseIndexKey8bit(OperandVector &Operands) {
7693 return tryParseIndexKey(Operands, AMDGPUOperand::ImmTyIndexKey8bit);
7694}
7695
7696ParseStatus AMDGPUAsmParser::parseIndexKey16bit(OperandVector &Operands) {
7697 return tryParseIndexKey(Operands, AMDGPUOperand::ImmTyIndexKey16bit);
7698}
7699
7700ParseStatus AMDGPUAsmParser::parseIndexKey32bit(OperandVector &Operands) {
7701 return tryParseIndexKey(Operands, AMDGPUOperand::ImmTyIndexKey32bit);
7702}
7703
7704ParseStatus AMDGPUAsmParser::tryParseMatrixFMT(OperandVector &Operands,
7705 StringRef Name,
7706 AMDGPUOperand::ImmTy Type) {
7707 return parseStringOrIntWithPrefix(Operands, Name, WMMAMods::ModMatrixFmt,
7708 Type);
7709}
7710
7711ParseStatus AMDGPUAsmParser::parseMatrixAFMT(OperandVector &Operands) {
7712 return tryParseMatrixFMT(Operands, "matrix_a_fmt",
7713 AMDGPUOperand::ImmTyMatrixAFMT);
7714}
7715
7716ParseStatus AMDGPUAsmParser::parseMatrixBFMT(OperandVector &Operands) {
7717 return tryParseMatrixFMT(Operands, "matrix_b_fmt",
7718 AMDGPUOperand::ImmTyMatrixBFMT);
7719}
7720
7721ParseStatus AMDGPUAsmParser::tryParseMatrixScale(OperandVector &Operands,
7722 StringRef Name,
7723 AMDGPUOperand::ImmTy Type) {
7724 return parseStringOrIntWithPrefix(Operands, Name, WMMAMods::ModMatrixScale,
7725 Type);
7726}
7727
7728ParseStatus AMDGPUAsmParser::parseMatrixAScale(OperandVector &Operands) {
7729 return tryParseMatrixScale(Operands, "matrix_a_scale",
7730 AMDGPUOperand::ImmTyMatrixAScale);
7731}
7732
7733ParseStatus AMDGPUAsmParser::parseMatrixBScale(OperandVector &Operands) {
7734 return tryParseMatrixScale(Operands, "matrix_b_scale",
7735 AMDGPUOperand::ImmTyMatrixBScale);
7736}
7737
7738ParseStatus AMDGPUAsmParser::tryParseMatrixScaleFmt(OperandVector &Operands,
7739 StringRef Name,
7740 AMDGPUOperand::ImmTy Type) {
7741 return parseStringOrIntWithPrefix(Operands, Name, WMMAMods::ModMatrixScaleFmt,
7742 Type);
7743}
7744
7745ParseStatus AMDGPUAsmParser::parseMatrixAScaleFmt(OperandVector &Operands) {
7746 return tryParseMatrixScaleFmt(Operands, "matrix_a_scale_fmt",
7747 AMDGPUOperand::ImmTyMatrixAScaleFmt);
7748}
7749
7750ParseStatus AMDGPUAsmParser::parseMatrixBScaleFmt(OperandVector &Operands) {
7751 return tryParseMatrixScaleFmt(Operands, "matrix_b_scale_fmt",
7752 AMDGPUOperand::ImmTyMatrixBScaleFmt);
7753}
7754
7755// dfmt and nfmt (in a tbuffer instruction) are parsed as one to allow their
7756// values to live in a joint format operand in the MCInst encoding.
7757ParseStatus AMDGPUAsmParser::parseDfmtNfmt(int64_t &Format) {
7758 using namespace llvm::AMDGPU::MTBUFFormat;
7759
7760 int64_t Dfmt = DFMT_UNDEF;
7761 int64_t Nfmt = NFMT_UNDEF;
7762
7763 // dfmt and nfmt can appear in either order, and each is optional.
7764 for (int I = 0; I < 2; ++I) {
7765 if (Dfmt == DFMT_UNDEF && !tryParseFmt("dfmt", DFMT_MAX, Dfmt))
7766 return ParseStatus::Failure;
7767
7768 if (Nfmt == NFMT_UNDEF && !tryParseFmt("nfmt", NFMT_MAX, Nfmt))
7769 return ParseStatus::Failure;
7770
7771 // Skip optional comma between dfmt/nfmt
7772 // but guard against 2 commas following each other.
7773 if ((Dfmt == DFMT_UNDEF) != (Nfmt == NFMT_UNDEF) &&
7774 !peekToken().is(AsmToken::Comma)) {
7775 trySkipToken(AsmToken::Comma);
7776 }
7777 }
7778
7779 if (Dfmt == DFMT_UNDEF && Nfmt == NFMT_UNDEF)
7780 return ParseStatus::NoMatch;
7781
7782 Dfmt = (Dfmt == DFMT_UNDEF) ? DFMT_DEFAULT : Dfmt;
7783 Nfmt = (Nfmt == NFMT_UNDEF) ? NFMT_DEFAULT : Nfmt;
7784
7785 Format = encodeDfmtNfmt(Dfmt, Nfmt);
7786 return ParseStatus::Success;
7787}
7788
7789ParseStatus AMDGPUAsmParser::parseUfmt(int64_t &Format) {
7790 using namespace llvm::AMDGPU::MTBUFFormat;
7791
7792 int64_t Fmt = UFMT_UNDEF;
7793
7794 if (!tryParseFmt("format", UFMT_MAX, Fmt))
7795 return ParseStatus::Failure;
7796
7797 if (Fmt == UFMT_UNDEF)
7798 return ParseStatus::NoMatch;
7799
7800 Format = Fmt;
7801 return ParseStatus::Success;
7802}
7803
7804bool AMDGPUAsmParser::matchDfmtNfmt(int64_t &Dfmt, int64_t &Nfmt,
7805 StringRef FormatStr, SMLoc Loc) {
7806 using namespace llvm::AMDGPU::MTBUFFormat;
7807 int64_t Format;
7808
7809 Format = getDfmt(FormatStr);
7810 if (Format != DFMT_UNDEF) {
7811 Dfmt = Format;
7812 return true;
7813 }
7814
7815 Format = getNfmt(FormatStr, getSTI());
7816 if (Format != NFMT_UNDEF) {
7817 Nfmt = Format;
7818 return true;
7819 }
7820
7821 Error(Loc, "unsupported format");
7822 return false;
7823}
7824
7825ParseStatus AMDGPUAsmParser::parseSymbolicSplitFormat(StringRef FormatStr,
7826 SMLoc FormatLoc,
7827 int64_t &Format) {
7828 using namespace llvm::AMDGPU::MTBUFFormat;
7829
7830 int64_t Dfmt = DFMT_UNDEF;
7831 int64_t Nfmt = NFMT_UNDEF;
7832 if (!matchDfmtNfmt(Dfmt, Nfmt, FormatStr, FormatLoc))
7833 return ParseStatus::Failure;
7834
7835 if (trySkipToken(AsmToken::Comma)) {
7836 StringRef Str;
7837 SMLoc Loc = getLoc();
7838 if (!parseId(Str, "expected a format string") ||
7839 !matchDfmtNfmt(Dfmt, Nfmt, Str, Loc))
7840 return ParseStatus::Failure;
7841 if (Dfmt == DFMT_UNDEF)
7842 return Error(Loc, "duplicate numeric format");
7843 if (Nfmt == NFMT_UNDEF)
7844 return Error(Loc, "duplicate data format");
7845 }
7846
7847 Dfmt = (Dfmt == DFMT_UNDEF) ? DFMT_DEFAULT : Dfmt;
7848 Nfmt = (Nfmt == NFMT_UNDEF) ? NFMT_DEFAULT : Nfmt;
7849
7850 if (isGFX10Plus()) {
7851 auto Ufmt = convertDfmtNfmt2Ufmt(Dfmt, Nfmt, getSTI());
7852 if (Ufmt == UFMT_UNDEF)
7853 return Error(FormatLoc, "unsupported format");
7854 Format = Ufmt;
7855 } else {
7856 Format = encodeDfmtNfmt(Dfmt, Nfmt);
7857 }
7858
7859 return ParseStatus::Success;
7860}
7861
7862ParseStatus AMDGPUAsmParser::parseSymbolicUnifiedFormat(StringRef FormatStr,
7863 SMLoc Loc,
7864 int64_t &Format) {
7865 using namespace llvm::AMDGPU::MTBUFFormat;
7866
7867 auto Id = getUnifiedFormat(FormatStr, getSTI());
7868 if (Id == UFMT_UNDEF)
7869 return ParseStatus::NoMatch;
7870
7871 if (!isGFX10Plus())
7872 return Error(Loc, "unified format is not supported on this GPU");
7873
7874 Format = Id;
7875 return ParseStatus::Success;
7876}
7877
7878ParseStatus AMDGPUAsmParser::parseNumericFormat(int64_t &Format) {
7879 using namespace llvm::AMDGPU::MTBUFFormat;
7880 SMLoc Loc = getLoc();
7881
7882 if (!parseExpr(Format))
7883 return ParseStatus::Failure;
7884 if (!isValidFormatEncoding(Format, getSTI()))
7885 return Error(Loc, "out of range format");
7886
7887 return ParseStatus::Success;
7888}
7889
7890ParseStatus AMDGPUAsmParser::parseSymbolicOrNumericFormat(int64_t &Format) {
7891 using namespace llvm::AMDGPU::MTBUFFormat;
7892
7893 if (!trySkipId("format", AsmToken::Colon))
7894 return ParseStatus::NoMatch;
7895
7896 if (trySkipToken(AsmToken::LBrac)) {
7897 StringRef FormatStr;
7898 SMLoc Loc = getLoc();
7899 if (!parseId(FormatStr, "expected a format string"))
7900 return ParseStatus::Failure;
7901
7902 auto Res = parseSymbolicUnifiedFormat(FormatStr, Loc, Format);
7903 if (Res.isNoMatch())
7904 Res = parseSymbolicSplitFormat(FormatStr, Loc, Format);
7905 if (!Res.isSuccess())
7906 return Res;
7907
7908 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket"))
7909 return ParseStatus::Failure;
7910
7911 return ParseStatus::Success;
7912 }
7913
7914 return parseNumericFormat(Format);
7915}
7916
7917ParseStatus AMDGPUAsmParser::parseFORMAT(OperandVector &Operands) {
7918 using namespace llvm::AMDGPU::MTBUFFormat;
7919
7920 int64_t Format = getDefaultFormatEncoding(getSTI());
7921 ParseStatus Res;
7922 SMLoc Loc = getLoc();
7923
7924 // Parse legacy format syntax.
7925 Res = isGFX10Plus() ? parseUfmt(Format) : parseDfmtNfmt(Format);
7926 if (Res.isFailure())
7927 return Res;
7928
7929 bool FormatFound = Res.isSuccess();
7930
7931 Operands.push_back(
7932 AMDGPUOperand::CreateImm(this, Format, Loc, AMDGPUOperand::ImmTyFORMAT));
7933
7934 if (FormatFound)
7935 trySkipToken(AsmToken::Comma);
7936
7937 if (isToken(AsmToken::EndOfStatement)) {
7938 // We are expecting an soffset operand,
7939 // but let matcher handle the error.
7940 return ParseStatus::Success;
7941 }
7942
7943 // Parse soffset.
7944 Res = parseRegOrImm(Operands);
7945 if (!Res.isSuccess())
7946 return Res;
7947
7948 trySkipToken(AsmToken::Comma);
7949
7950 if (!FormatFound) {
7951 Res = parseSymbolicOrNumericFormat(Format);
7952 if (Res.isFailure())
7953 return Res;
7954 if (Res.isSuccess()) {
7955 auto Size = Operands.size();
7956 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands[Size - 2]);
7957 assert(Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyFORMAT);
7958 Op.setImm(Format);
7959 }
7960 return ParseStatus::Success;
7961 }
7962
7963 if (isId("format") && peekToken().is(AsmToken::Colon))
7964 return Error(getLoc(), "duplicate format");
7965 return ParseStatus::Success;
7966}
7967
7968ParseStatus AMDGPUAsmParser::parseFlatOffset(OperandVector &Operands) {
7969 ParseStatus Res =
7970 parseIntWithPrefix("offset", Operands, AMDGPUOperand::ImmTyOffset);
7971 if (Res.isNoMatch()) {
7972 Res = parseIntWithPrefix("inst_offset", Operands,
7973 AMDGPUOperand::ImmTyInstOffset);
7974 }
7975 return Res;
7976}
7977
7978ParseStatus AMDGPUAsmParser::parseR128A16(OperandVector &Operands) {
7979 ParseStatus Res =
7980 parseNamedBit("r128", Operands, AMDGPUOperand::ImmTyR128A16);
7981 if (Res.isNoMatch())
7982 Res = parseNamedBit("a16", Operands, AMDGPUOperand::ImmTyA16);
7983 return Res;
7984}
7985
7986ParseStatus AMDGPUAsmParser::parseBLGP(OperandVector &Operands) {
7987 ParseStatus Res =
7988 parseIntWithPrefix("blgp", Operands, AMDGPUOperand::ImmTyBLGP);
7989 if (Res.isNoMatch()) {
7990 Res =
7991 parseOperandArrayWithPrefix("neg", Operands, AMDGPUOperand::ImmTyBLGP);
7992 }
7993 return Res;
7994}
7995
7996//===----------------------------------------------------------------------===//
7997// Exp
7998//===----------------------------------------------------------------------===//
7999
8000void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
8001 OptionalImmIndexMap OptionalIdx;
8002
8003 unsigned OperandIdx[4];
8004 unsigned EnMask = 0;
8005 int SrcIdx = 0;
8006
8007 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
8008 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
8009
8010 // Add the register arguments
8011 if (Op.isReg()) {
8012 assert(SrcIdx < 4);
8013 OperandIdx[SrcIdx] = Inst.size();
8014 Op.addRegOperands(Inst, 1);
8015 ++SrcIdx;
8016 continue;
8017 }
8018
8019 if (Op.isOff()) {
8020 assert(SrcIdx < 4);
8021 OperandIdx[SrcIdx] = Inst.size();
8022 Inst.addOperand(MCOperand::createReg(MCRegister()));
8023 ++SrcIdx;
8024 continue;
8025 }
8026
8027 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) {
8028 Op.addImmOperands(Inst, 1);
8029 continue;
8030 }
8031
8032 if (Op.isToken() && (Op.getToken() == "done" || Op.getToken() == "row_en"))
8033 continue;
8034
8035 // Handle optional arguments
8036 OptionalIdx[Op.getImmTy()] = i;
8037 }
8038
8039 assert(SrcIdx == 4);
8040
8041 bool Compr = false;
8042 if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) {
8043 Compr = true;
8044 Inst.getOperand(OperandIdx[1]) = Inst.getOperand(OperandIdx[2]);
8045 Inst.getOperand(OperandIdx[2]).setReg(MCRegister());
8046 Inst.getOperand(OperandIdx[3]).setReg(MCRegister());
8047 }
8048
8049 for (auto i = 0; i < SrcIdx; ++i) {
8050 if (Inst.getOperand(OperandIdx[i]).getReg()) {
8051 EnMask |= Compr ? (0x3 << i * 2) : (0x1 << i);
8052 }
8053 }
8054
8055 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM);
8056 addOptionalImmOperand(Inst, Operands, OptionalIdx,
8057 AMDGPUOperand::ImmTyExpCompr);
8058
8059 Inst.addOperand(MCOperand::createImm(EnMask));
8060}
8061
8062//===----------------------------------------------------------------------===//
8063// s_waitcnt
8064//===----------------------------------------------------------------------===//
8065
8066static bool encodeCnt(const AMDGPU::IsaVersion ISA, int64_t &IntVal,
8067 int64_t CntVal, bool Saturate,
8068 unsigned (*encode)(const IsaVersion &Version, unsigned,
8069 unsigned),
8070 unsigned (*decode)(const IsaVersion &Version, unsigned)) {
8071 bool Failed = false;
8072
8073 IntVal = encode(ISA, IntVal, CntVal);
8074 if (CntVal != decode(ISA, IntVal)) {
8075 if (Saturate) {
8076 IntVal = encode(ISA, IntVal, -1);
8077 } else {
8078 Failed = true;
8079 }
8080 }
8081 return Failed;
8082}
8083
8084bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
8085
8086 SMLoc CntLoc = getLoc();
8087 StringRef CntName = getTokenStr();
8088
8089 if (!skipToken(AsmToken::Identifier, "expected a counter name") ||
8090 !skipToken(AsmToken::LParen, "expected a left parenthesis"))
8091 return false;
8092
8093 int64_t CntVal;
8094 SMLoc ValLoc = getLoc();
8095 if (!parseExpr(CntVal))
8096 return false;
8097
8098 bool Failed = true;
8099 bool Sat = CntName.ends_with("_sat");
8100
8101 if (CntName == "vmcnt" || CntName == "vmcnt_sat") {
8102 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeVmcnt, decodeVmcnt);
8103 } else if (CntName == "expcnt" || CntName == "expcnt_sat") {
8104 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeExpcnt, decodeExpcnt);
8105 } else if (CntName == "lgkmcnt" || CntName == "lgkmcnt_sat") {
8106 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeLgkmcnt, decodeLgkmcnt);
8107 } else {
8108 Error(CntLoc, "invalid counter name " + CntName);
8109 return false;
8110 }
8111
8112 if (Failed) {
8113 Error(ValLoc, "too large value for " + CntName);
8114 return false;
8115 }
8116
8117 if (!skipToken(AsmToken::RParen, "expected a closing parenthesis"))
8118 return false;
8119
8120 if (trySkipToken(AsmToken::Amp) || trySkipToken(AsmToken::Comma)) {
8121 if (isToken(AsmToken::EndOfStatement)) {
8122 Error(getLoc(), "expected a counter name");
8123 return false;
8124 }
8125 }
8126
8127 return true;
8128}
8129
8130ParseStatus AMDGPUAsmParser::parseSWaitCnt(OperandVector &Operands) {
8131 int64_t Waitcnt = getWaitcntBitMask(ISA);
8132 SMLoc S = getLoc();
8133
8134 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) {
8135 while (!isToken(AsmToken::EndOfStatement)) {
8136 if (!parseCnt(Waitcnt))
8137 return ParseStatus::Failure;
8138 }
8139 } else {
8140 if (!parseExpr(Waitcnt))
8141 return ParseStatus::Failure;
8142 }
8143
8144 Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S));
8145 return ParseStatus::Success;
8146}
8147
8148bool AMDGPUAsmParser::parseDelay(int64_t &Delay) {
8149 SMLoc FieldLoc = getLoc();
8150 StringRef FieldName = getTokenStr();
8151 if (!skipToken(AsmToken::Identifier, "expected a field name") ||
8152 !skipToken(AsmToken::LParen, "expected a left parenthesis"))
8153 return false;
8154
8155 SMLoc ValueLoc = getLoc();
8156 StringRef ValueName = getTokenStr();
8157 if (!skipToken(AsmToken::Identifier, "expected a value name") ||
8158 !skipToken(AsmToken::RParen, "expected a right parenthesis"))
8159 return false;
8160
8161 unsigned Shift;
8162 if (FieldName == "instid0") {
8163 Shift = 0;
8164 } else if (FieldName == "instskip") {
8165 Shift = 4;
8166 } else if (FieldName == "instid1") {
8167 Shift = 7;
8168 } else {
8169 Error(FieldLoc, "invalid field name " + FieldName);
8170 return false;
8171 }
8172
8173 int Value;
8174 if (Shift == 4) {
8175 // Parse values for instskip.
8176 Value = StringSwitch<int>(ValueName)
8177 .Case("SAME", 0)
8178 .Case("NEXT", 1)
8179 .Case("SKIP_1", 2)
8180 .Case("SKIP_2", 3)
8181 .Case("SKIP_3", 4)
8182 .Case("SKIP_4", 5)
8183 .Default(-1);
8184 } else {
8185 // Parse values for instid0 and instid1.
8186 Value = StringSwitch<int>(ValueName)
8187 .Case("NO_DEP", 0)
8188 .Case("VALU_DEP_1", 1)
8189 .Case("VALU_DEP_2", 2)
8190 .Case("VALU_DEP_3", 3)
8191 .Case("VALU_DEP_4", 4)
8192 .Case("TRANS32_DEP_1", 5)
8193 .Case("TRANS32_DEP_2", 6)
8194 .Case("TRANS32_DEP_3", 7)
8195 .Case("FMA_ACCUM_CYCLE_1", 8)
8196 .Case("SALU_CYCLE_1", 9)
8197 .Case("SALU_CYCLE_2", 10)
8198 .Case("SALU_CYCLE_3", 11)
8199 .Default(-1);
8200 }
8201 if (Value < 0) {
8202 Error(ValueLoc, "invalid value name " + ValueName);
8203 return false;
8204 }
8205
8206 Delay |= Value << Shift;
8207 return true;
8208}
8209
8210ParseStatus AMDGPUAsmParser::parseSDelayALU(OperandVector &Operands) {
8211 int64_t Delay = 0;
8212 SMLoc S = getLoc();
8213
8214 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) {
8215 do {
8216 if (!parseDelay(Delay))
8217 return ParseStatus::Failure;
8218 } while (trySkipToken(AsmToken::Pipe));
8219 } else {
8220 if (!parseExpr(Delay))
8221 return ParseStatus::Failure;
8222 }
8223
8224 Operands.push_back(AMDGPUOperand::CreateImm(this, Delay, S));
8225 return ParseStatus::Success;
8226}
8227
8228bool AMDGPUOperand::isSWaitCnt() const { return isImm(); }
8229
8230bool AMDGPUOperand::isSDelayALU() const { return isImm(); }
8231
8232//===----------------------------------------------------------------------===//
8233// DepCtr
8234//===----------------------------------------------------------------------===//
8235
8236void AMDGPUAsmParser::depCtrError(SMLoc Loc, int ErrorId,
8237 StringRef DepCtrName) {
8238 switch (ErrorId) {
8239 case OPR_ID_UNKNOWN:
8240 Error(Loc, Twine("invalid counter name ", DepCtrName));
8241 return;
8242 case OPR_ID_UNSUPPORTED:
8243 Error(Loc, Twine(DepCtrName, " is not supported on this GPU"));
8244 return;
8245 case OPR_ID_DUPLICATE:
8246 Error(Loc, Twine("duplicate counter name ", DepCtrName));
8247 return;
8248 case OPR_VAL_INVALID:
8249 Error(Loc, Twine("invalid value for ", DepCtrName));
8250 return;
8251 default:
8252 assert(false);
8253 }
8254}
8255
8256bool AMDGPUAsmParser::parseDepCtr(int64_t &DepCtr, unsigned &UsedOprMask) {
8257
8258 using namespace llvm::AMDGPU::DepCtr;
8259
8260 SMLoc DepCtrLoc = getLoc();
8261 StringRef DepCtrName = getTokenStr();
8262
8263 if (!skipToken(AsmToken::Identifier, "expected a counter name") ||
8264 !skipToken(AsmToken::LParen, "expected a left parenthesis"))
8265 return false;
8266
8267 int64_t ExprVal;
8268 if (!parseExpr(ExprVal))
8269 return false;
8270
8271 unsigned PrevOprMask = UsedOprMask;
8272 int CntVal = encodeDepCtr(DepCtrName, ExprVal, UsedOprMask, getSTI());
8273
8274 if (CntVal < 0) {
8275 depCtrError(DepCtrLoc, CntVal, DepCtrName);
8276 return false;
8277 }
8278
8279 if (!skipToken(AsmToken::RParen, "expected a closing parenthesis"))
8280 return false;
8281
8282 if (trySkipToken(AsmToken::Amp) || trySkipToken(AsmToken::Comma)) {
8283 if (isToken(AsmToken::EndOfStatement)) {
8284 Error(getLoc(), "expected a counter name");
8285 return false;
8286 }
8287 }
8288
8289 int64_t CntValMask = PrevOprMask ^ UsedOprMask;
8290 DepCtr = (DepCtr & ~CntValMask) | CntVal;
8291 return true;
8292}
8293
8294ParseStatus AMDGPUAsmParser::parseDepCtr(OperandVector &Operands) {
8295 using namespace llvm::AMDGPU::DepCtr;
8296
8297 int64_t DepCtr = getDefaultDepCtrEncoding(getSTI());
8298 SMLoc Loc = getLoc();
8299
8300 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) {
8301 unsigned UsedOprMask = 0;
8302 while (!isToken(AsmToken::EndOfStatement)) {
8303 if (!parseDepCtr(DepCtr, UsedOprMask))
8304 return ParseStatus::Failure;
8305 }
8306 } else {
8307 if (!parseExpr(DepCtr))
8308 return ParseStatus::Failure;
8309 }
8310
8311 Operands.push_back(AMDGPUOperand::CreateImm(this, DepCtr, Loc));
8312 return ParseStatus::Success;
8313}
8314
8315bool AMDGPUOperand::isDepCtr() const { return isS16Imm(); }
8316
8317//===----------------------------------------------------------------------===//
8318// hwreg
8319//===----------------------------------------------------------------------===//
8320
8321ParseStatus AMDGPUAsmParser::parseHwregFunc(OperandInfoTy &HwReg,
8322 OperandInfoTy &Offset,
8323 OperandInfoTy &Width) {
8324 using namespace llvm::AMDGPU::Hwreg;
8325
8326 if (!trySkipId("hwreg", AsmToken::LParen))
8327 return ParseStatus::NoMatch;
8328
8329 // The register may be specified by name or using a numeric code
8330 HwReg.Loc = getLoc();
8331 if (isToken(AsmToken::Identifier) &&
8332 (HwReg.Val = getHwregId(getTokenStr(), getSTI())) != OPR_ID_UNKNOWN) {
8333 HwReg.IsSymbolic = true;
8334 lex(); // skip register name
8335 } else if (!parseExpr(HwReg.Val, "a register name")) {
8336 return ParseStatus::Failure;
8337 }
8338
8339 if (trySkipToken(AsmToken::RParen))
8340 return ParseStatus::Success;
8341
8342 // parse optional params
8343 if (!skipToken(AsmToken::Comma, "expected a comma or a closing parenthesis"))
8344 return ParseStatus::Failure;
8345
8346 Offset.Loc = getLoc();
8347 if (!parseExpr(Offset.Val))
8348 return ParseStatus::Failure;
8349
8350 if (!skipToken(AsmToken::Comma, "expected a comma"))
8351 return ParseStatus::Failure;
8352
8353 Width.Loc = getLoc();
8354 if (!parseExpr(Width.Val) ||
8355 !skipToken(AsmToken::RParen, "expected a closing parenthesis"))
8356 return ParseStatus::Failure;
8357
8358 return ParseStatus::Success;
8359}
8360
8361ParseStatus AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
8362 using namespace llvm::AMDGPU::Hwreg;
8363
8364 int64_t ImmVal = 0;
8365 SMLoc Loc = getLoc();
8366
8367 StructuredOpField HwReg("id", "hardware register", HwregId::Width,
8368 HwregId::Default);
8369 StructuredOpField Offset("offset", "bit offset", HwregOffset::Width,
8370 HwregOffset::Default);
8371 struct : StructuredOpField {
8372 using StructuredOpField::StructuredOpField;
8373 bool validate(AMDGPUAsmParser &Parser) const override {
8374 if (!isUIntN(Width, Val - 1))
8375 return Error(Parser, "only values from 1 to 32 are legal");
8376 return true;
8377 }
8378 } Width("size", "bitfield width", HwregSize::Width, HwregSize::Default);
8379 ParseStatus Res = parseStructuredOpFields({&HwReg, &Offset, &Width});
8380
8381 if (Res.isNoMatch())
8382 Res = parseHwregFunc(HwReg, Offset, Width);
8383
8384 if (Res.isSuccess()) {
8385 if (!validateStructuredOpFields({&HwReg, &Offset, &Width}))
8386 return ParseStatus::Failure;
8387 ImmVal = HwregEncoding::encode(HwReg.Val, Offset.Val, Width.Val);
8388 }
8389
8390 if (Res.isNoMatch() &&
8391 parseExpr(ImmVal, "a hwreg macro, structured immediate"))
8393
8394 if (!Res.isSuccess())
8395 return ParseStatus::Failure;
8396
8397 if (!isUInt<16>(ImmVal))
8398 return Error(Loc, "invalid immediate: only 16-bit values are legal");
8399 Operands.push_back(
8400 AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTyHwreg));
8401 return ParseStatus::Success;
8402}
8403
8404bool AMDGPUOperand::isHwreg() const { return isImmTy(ImmTyHwreg); }
8405
8406//===----------------------------------------------------------------------===//
8407// sendmsg
8408//===----------------------------------------------------------------------===//
8409
8410bool AMDGPUAsmParser::parseSendMsgBody(OperandInfoTy &Msg, OperandInfoTy &Op,
8411 OperandInfoTy &Stream) {
8412 using namespace llvm::AMDGPU::SendMsg;
8413
8414 Msg.Loc = getLoc();
8415 if (isToken(AsmToken::Identifier) &&
8416 (Msg.Val = getMsgId(getTokenStr(), getSTI())) != OPR_ID_UNKNOWN) {
8417 Msg.IsSymbolic = true;
8418 lex(); // skip message name
8419 } else if (!parseExpr(Msg.Val, "a message name")) {
8420 return false;
8421 }
8422
8423 if (trySkipToken(AsmToken::Comma)) {
8424 Op.IsDefined = true;
8425 Op.Loc = getLoc();
8426 if (isToken(AsmToken::Identifier) &&
8427 (Op.Val = getMsgOpId(Msg.Val, getTokenStr(), getSTI())) !=
8429 lex(); // skip operation name
8430 } else if (!parseExpr(Op.Val, "an operation name")) {
8431 return false;
8432 }
8433
8434 if (trySkipToken(AsmToken::Comma)) {
8435 Stream.IsDefined = true;
8436 Stream.Loc = getLoc();
8437 if (!parseExpr(Stream.Val))
8438 return false;
8439 }
8440 }
8441
8442 return skipToken(AsmToken::RParen, "expected a closing parenthesis");
8443}
8444
8445bool AMDGPUAsmParser::validateSendMsg(const OperandInfoTy &Msg,
8446 const OperandInfoTy &Op,
8447 const OperandInfoTy &Stream) {
8448 using namespace llvm::AMDGPU::SendMsg;
8449
8450 // Validation strictness depends on whether message is specified
8451 // in a symbolic or in a numeric form. In the latter case
8452 // only encoding possibility is checked.
8453 bool Strict = Msg.IsSymbolic;
8454
8455 if (Strict) {
8456 if (Msg.Val == OPR_ID_UNSUPPORTED) {
8457 Error(Msg.Loc, "specified message id is not supported on this GPU");
8458 return false;
8459 }
8460 } else {
8461 if (!isValidMsgId(Msg.Val, getSTI())) {
8462 Error(Msg.Loc, "invalid message id");
8463 return false;
8464 }
8465 }
8466 if (Strict && (msgRequiresOp(Msg.Val, getSTI()) != Op.IsDefined)) {
8467 if (Op.IsDefined) {
8468 Error(Op.Loc, "message does not support operations");
8469 } else {
8470 Error(Msg.Loc, "missing message operation");
8471 }
8472 return false;
8473 }
8474 if (!isValidMsgOp(Msg.Val, Op.Val, getSTI(), Strict)) {
8475 if (Op.Val == OPR_ID_UNSUPPORTED)
8476 Error(Op.Loc, "specified operation id is not supported on this GPU");
8477 else
8478 Error(Op.Loc, "invalid operation id");
8479 return false;
8480 }
8481 if (Strict && !msgSupportsStream(Msg.Val, Op.Val, getSTI()) &&
8482 Stream.IsDefined) {
8483 Error(Stream.Loc, "message operation does not support streams");
8484 return false;
8485 }
8486 if (!isValidMsgStream(Msg.Val, Op.Val, Stream.Val, getSTI(), Strict)) {
8487 Error(Stream.Loc, "invalid message stream id");
8488 return false;
8489 }
8490 return true;
8491}
8492
8493ParseStatus AMDGPUAsmParser::parseSendMsg(OperandVector &Operands) {
8494 using namespace llvm::AMDGPU::SendMsg;
8495
8496 int64_t ImmVal = 0;
8497 SMLoc Loc = getLoc();
8498
8499 if (trySkipId("sendmsg", AsmToken::LParen)) {
8500 OperandInfoTy Msg(OPR_ID_UNKNOWN);
8501 OperandInfoTy Op(OP_NONE_);
8502 OperandInfoTy Stream(STREAM_ID_NONE_);
8503 if (parseSendMsgBody(Msg, Op, Stream) && validateSendMsg(Msg, Op, Stream)) {
8504 ImmVal = encodeMsg(Msg.Val, Op.Val, Stream.Val);
8505 } else {
8506 return ParseStatus::Failure;
8507 }
8508 } else if (parseExpr(ImmVal, "a sendmsg macro")) {
8509 if (ImmVal < 0 || !isUInt<16>(ImmVal))
8510 return Error(Loc, "invalid immediate: only 16-bit values are legal");
8511 } else {
8512 return ParseStatus::Failure;
8513 }
8514
8515 Operands.push_back(
8516 AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTySendMsg));
8517 return ParseStatus::Success;
8518}
8519
8520bool AMDGPUOperand::isSendMsg() const { return isImmTy(ImmTySendMsg); }
8521
8522ParseStatus AMDGPUAsmParser::parseWaitEvent(OperandVector &Operands) {
8523 using namespace llvm::AMDGPU::WaitEvent;
8524
8525 SMLoc Loc = getLoc();
8526 int64_t ImmVal = 0;
8527
8528 StructuredOpField DontWaitExportReady("dont_wait_export_ready", "bit value",
8529 1, 0);
8530 StructuredOpField ExportReady("export_ready", "bit value", 1, 0);
8531
8532 StructuredOpField *TargetBitfield =
8533 isGFX11() ? &DontWaitExportReady : &ExportReady;
8534
8535 ParseStatus Res = parseStructuredOpFields({TargetBitfield});
8536 if (Res.isNoMatch() && parseExpr(ImmVal, "structured immediate"))
8538 else if (Res.isSuccess()) {
8539 if (!validateStructuredOpFields({TargetBitfield}))
8540 return ParseStatus::Failure;
8541 ImmVal = TargetBitfield->Val;
8542 }
8543
8544 if (!Res.isSuccess())
8545 return ParseStatus::Failure;
8546
8547 if (!isUInt<16>(ImmVal))
8548 return Error(Loc, "invalid immediate: only 16-bit values are legal");
8549
8550 Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc,
8551 AMDGPUOperand::ImmTyWaitEvent));
8552 return ParseStatus::Success;
8553}
8554
8555bool AMDGPUOperand::isWaitEvent() const { return isImmTy(ImmTyWaitEvent); }
8556
8557//===----------------------------------------------------------------------===//
8558// v_interp
8559//===----------------------------------------------------------------------===//
8560
8561ParseStatus AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) {
8562 StringRef Str;
8563 SMLoc S = getLoc();
8564
8565 if (!parseId(Str))
8566 return ParseStatus::NoMatch;
8567
8568 int Slot = StringSwitch<int>(Str)
8569 .Case("p10", 0)
8570 .Case("p20", 1)
8571 .Case("p0", 2)
8572 .Default(-1);
8573
8574 if (Slot == -1)
8575 return Error(S, "invalid interpolation slot");
8576
8577 Operands.push_back(
8578 AMDGPUOperand::CreateImm(this, Slot, S, AMDGPUOperand::ImmTyInterpSlot));
8579 return ParseStatus::Success;
8580}
8581
8582ParseStatus AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) {
8583 StringRef Str;
8584 SMLoc S = getLoc();
8585
8586 if (!parseId(Str))
8587 return ParseStatus::NoMatch;
8588
8589 if (!Str.starts_with("attr"))
8590 return Error(S, "invalid interpolation attribute");
8591
8592 StringRef Chan = Str.take_back(2);
8593 int AttrChan = StringSwitch<int>(Chan)
8594 .Case(".x", 0)
8595 .Case(".y", 1)
8596 .Case(".z", 2)
8597 .Case(".w", 3)
8598 .Default(-1);
8599 if (AttrChan == -1)
8600 return Error(S, "invalid or missing interpolation attribute channel");
8601
8602 Str = Str.drop_back(2).drop_front(4);
8603
8604 uint8_t Attr;
8605 if (Str.getAsInteger(10, Attr))
8606 return Error(S, "invalid or missing interpolation attribute number");
8607
8608 if (Attr > 32)
8609 return Error(S, "out of bounds interpolation attribute number");
8610
8611 SMLoc SChan = SMLoc::getFromPointer(Chan.data());
8612
8613 Operands.push_back(
8614 AMDGPUOperand::CreateImm(this, Attr, S, AMDGPUOperand::ImmTyInterpAttr));
8615 Operands.push_back(AMDGPUOperand::CreateImm(
8616 this, AttrChan, SChan, AMDGPUOperand::ImmTyInterpAttrChan));
8617 return ParseStatus::Success;
8618}
8619
8620//===----------------------------------------------------------------------===//
8621// exp
8622//===----------------------------------------------------------------------===//
8623
8624ParseStatus AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) {
8625 using namespace llvm::AMDGPU::Exp;
8626
8627 StringRef Str;
8628 SMLoc S = getLoc();
8629
8630 if (!parseId(Str))
8631 return ParseStatus::NoMatch;
8632
8633 unsigned Id = getTgtId(Str);
8634 if (Id == ET_INVALID || !isSupportedTgtId(Id, getSTI()))
8635 return Error(S, (Id == ET_INVALID)
8636 ? "invalid exp target"
8637 : "exp target is not supported on this GPU");
8638
8639 Operands.push_back(
8640 AMDGPUOperand::CreateImm(this, Id, S, AMDGPUOperand::ImmTyExpTgt));
8641 return ParseStatus::Success;
8642}
8643
8644//===----------------------------------------------------------------------===//
8645// parser helpers
8646//===----------------------------------------------------------------------===//
8647
8648bool AMDGPUAsmParser::isId(const AsmToken &Token, const StringRef Id) const {
8649 return Token.is(AsmToken::Identifier) && Token.getString() == Id;
8650}
8651
8652bool AMDGPUAsmParser::isId(const StringRef Id) const {
8653 return isId(getToken(), Id);
8654}
8655
8656bool AMDGPUAsmParser::isToken(const AsmToken::TokenKind Kind) const {
8657 return getTokenKind() == Kind;
8658}
8659
8660StringRef AMDGPUAsmParser::getId() const {
8661 return isToken(AsmToken::Identifier) ? getTokenStr() : StringRef();
8662}
8663
8664bool AMDGPUAsmParser::trySkipId(const StringRef Id) {
8665 if (isId(Id)) {
8666 lex();
8667 return true;
8668 }
8669 return false;
8670}
8671
8672bool AMDGPUAsmParser::trySkipId(const StringRef Pref, const StringRef Id) {
8673 if (isToken(AsmToken::Identifier)) {
8674 StringRef Tok = getTokenStr();
8675 if (Tok.starts_with(Pref) && Tok.drop_front(Pref.size()) == Id) {
8676 lex();
8677 return true;
8678 }
8679 }
8680 return false;
8681}
8682
8683bool AMDGPUAsmParser::trySkipId(const StringRef Id,
8684 const AsmToken::TokenKind Kind) {
8685 if (isId(Id) && peekToken().is(Kind)) {
8686 lex();
8687 lex();
8688 return true;
8689 }
8690 return false;
8691}
8692
8693bool AMDGPUAsmParser::trySkipToken(const AsmToken::TokenKind Kind) {
8694 if (isToken(Kind)) {
8695 lex();
8696 return true;
8697 }
8698 return false;
8699}
8700
8701bool AMDGPUAsmParser::skipToken(const AsmToken::TokenKind Kind,
8702 const StringRef ErrMsg) {
8703 if (!trySkipToken(Kind)) {
8704 Error(getLoc(), ErrMsg);
8705 return false;
8706 }
8707 return true;
8708}
8709
8710bool AMDGPUAsmParser::parseExpr(int64_t &Imm, StringRef Expected) {
8711 SMLoc S = getLoc();
8712
8713 const MCExpr *Expr;
8714 if (Parser.parseExpression(Expr))
8715 return false;
8716
8717 if (Expr->evaluateAsAbsolute(Imm))
8718 return true;
8719
8720 if (Expected.empty()) {
8721 Error(S, "expected absolute expression");
8722 } else {
8723 Error(S,
8724 Twine("expected ", Expected) + Twine(" or an absolute expression"));
8725 }
8726 return false;
8727}
8728
8729bool AMDGPUAsmParser::parseExpr(OperandVector &Operands) {
8730 SMLoc S = getLoc();
8731
8732 const MCExpr *Expr;
8733 if (Parser.parseExpression(Expr))
8734 return false;
8735
8736 int64_t IntVal;
8737 if (Expr->evaluateAsAbsolute(IntVal)) {
8738 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
8739 } else {
8740 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
8741 }
8742 return true;
8743}
8744
8745bool AMDGPUAsmParser::parseString(StringRef &Val, const StringRef ErrMsg) {
8746 if (isToken(AsmToken::String)) {
8747 Val = getToken().getStringContents();
8748 lex();
8749 return true;
8750 }
8751 Error(getLoc(), ErrMsg);
8752 return false;
8753}
8754
8755bool AMDGPUAsmParser::parseId(StringRef &Val, const StringRef ErrMsg) {
8756 if (isToken(AsmToken::Identifier)) {
8757 Val = getTokenStr();
8758 lex();
8759 return true;
8760 }
8761 if (!ErrMsg.empty())
8762 Error(getLoc(), ErrMsg);
8763 return false;
8764}
8765
8766AsmToken AMDGPUAsmParser::getToken() const { return Parser.getTok(); }
8767
8768AsmToken AMDGPUAsmParser::peekToken(bool ShouldSkipSpace) {
8769 return isToken(AsmToken::EndOfStatement)
8770 ? getToken()
8771 : getLexer().peekTok(ShouldSkipSpace);
8772}
8773
8774void AMDGPUAsmParser::peekTokens(MutableArrayRef<AsmToken> Tokens) {
8775 auto TokCount = getLexer().peekTokens(Tokens);
8776
8777 for (auto Idx = TokCount; Idx < Tokens.size(); ++Idx)
8778 Tokens[Idx] = AsmToken(AsmToken::Error, "");
8779}
8780
8781AsmToken::TokenKind AMDGPUAsmParser::getTokenKind() const {
8782 return getLexer().getKind();
8783}
8784
8785SMLoc AMDGPUAsmParser::getLoc() const { return getToken().getLoc(); }
8786
8787StringRef AMDGPUAsmParser::getTokenStr() const {
8788 return getToken().getString();
8789}
8790
8791void AMDGPUAsmParser::lex() { Parser.Lex(); }
8792
8793const AMDGPUOperand &
8794AMDGPUAsmParser::findMCOperand(const OperandVector &Operands,
8795 int MCOpIdx) const {
8796 for (const auto &Op : Operands) {
8797 const AMDGPUOperand &TargetOp = static_cast<AMDGPUOperand &>(*Op);
8798 if (TargetOp.getMCOpIdx() == MCOpIdx)
8799 return TargetOp;
8800 }
8801 llvm_unreachable("no such MC operand!");
8802}
8803
8804SMLoc AMDGPUAsmParser::getInstLoc(const OperandVector &Operands) const {
8805 return ((AMDGPUOperand &)*Operands[0]).getStartLoc();
8806}
8807
8808// Returns one of the given locations that comes later in the source.
8809SMLoc AMDGPUAsmParser::getLaterLoc(SMLoc a, SMLoc b) {
8810 return a.getPointer() < b.getPointer() ? b : a;
8811}
8812
8813SMLoc AMDGPUAsmParser::getOperandLoc(const OperandVector &Operands,
8814 int MCOpIdx) const {
8815 return findMCOperand(Operands, MCOpIdx).getStartLoc();
8816}
8817
8818SMLoc AMDGPUAsmParser::getOperandLoc(
8819 std::function<bool(const AMDGPUOperand &)> Test,
8820 const OperandVector &Operands) const {
8821 for (unsigned i = Operands.size() - 1; i > 0; --i) {
8822 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
8823 if (Test(Op))
8824 return Op.getStartLoc();
8825 }
8826 return getInstLoc(Operands);
8827}
8828
8829SMLoc AMDGPUAsmParser::getImmLoc(AMDGPUOperand::ImmTy Type,
8830 const OperandVector &Operands) const {
8831 auto Test = [=](const AMDGPUOperand &Op) { return Op.isImmTy(Type); };
8832 return getOperandLoc(Test, Operands);
8833}
8834
8835ParseStatus
8836AMDGPUAsmParser::parseStructuredOpFields(ArrayRef<StructuredOpField *> Fields) {
8837 if (!trySkipToken(AsmToken::LCurly))
8838 return ParseStatus::NoMatch;
8839
8840 bool First = true;
8841 while (!trySkipToken(AsmToken::RCurly)) {
8842 if (!First &&
8843 !skipToken(AsmToken::Comma, "comma or closing brace expected"))
8844 return ParseStatus::Failure;
8845
8846 StringRef Id = getTokenStr();
8847 SMLoc IdLoc = getLoc();
8848 if (!skipToken(AsmToken::Identifier, "field name expected") ||
8849 !skipToken(AsmToken::Colon, "colon expected"))
8850 return ParseStatus::Failure;
8851
8852 const auto *I =
8853 find_if(Fields, [Id](StructuredOpField *F) { return F->Id == Id; });
8854 if (I == Fields.end())
8855 return Error(IdLoc, "unknown field");
8856 if ((*I)->IsDefined)
8857 return Error(IdLoc, "duplicate field");
8858
8859 // TODO: Support symbolic values.
8860 (*I)->Loc = getLoc();
8861 if (!parseExpr((*I)->Val))
8862 return ParseStatus::Failure;
8863 (*I)->IsDefined = true;
8864
8865 First = false;
8866 }
8867 return ParseStatus::Success;
8868}
8869
8870bool AMDGPUAsmParser::validateStructuredOpFields(
8872 return all_of(Fields, [this](const StructuredOpField *F) {
8873 return F->validate(*this);
8874 });
8875}
8876
8877//===----------------------------------------------------------------------===//
8878// swizzle
8879//===----------------------------------------------------------------------===//
8880
8882static unsigned encodeBitmaskPerm(const unsigned AndMask, const unsigned OrMask,
8883 const unsigned XorMask) {
8884 using namespace llvm::AMDGPU::Swizzle;
8885
8886 return BITMASK_PERM_ENC | (AndMask << BITMASK_AND_SHIFT) |
8887 (OrMask << BITMASK_OR_SHIFT) | (XorMask << BITMASK_XOR_SHIFT);
8888}
8889
8890bool AMDGPUAsmParser::parseSwizzleOperand(int64_t &Op, const unsigned MinVal,
8891 const unsigned MaxVal,
8892 const Twine &ErrMsg, SMLoc &Loc) {
8893 if (!skipToken(AsmToken::Comma, "expected a comma")) {
8894 return false;
8895 }
8896 Loc = getLoc();
8897 if (!parseExpr(Op)) {
8898 return false;
8899 }
8900 if (Op < MinVal || Op > MaxVal) {
8901 Error(Loc, ErrMsg);
8902 return false;
8903 }
8904
8905 return true;
8906}
8907
8908bool AMDGPUAsmParser::parseSwizzleOperands(const unsigned OpNum, int64_t *Op,
8909 const unsigned MinVal,
8910 const unsigned MaxVal,
8911 const StringRef ErrMsg) {
8912 SMLoc Loc;
8913 for (unsigned i = 0; i < OpNum; ++i) {
8914 if (!parseSwizzleOperand(Op[i], MinVal, MaxVal, ErrMsg, Loc))
8915 return false;
8916 }
8917
8918 return true;
8919}
8920
8921bool AMDGPUAsmParser::parseSwizzleQuadPerm(int64_t &Imm) {
8922 using namespace llvm::AMDGPU::Swizzle;
8923
8924 int64_t Lane[LANE_NUM];
8925 if (parseSwizzleOperands(LANE_NUM, Lane, 0, LANE_MAX,
8926 "expected a 2-bit lane id")) {
8928 for (unsigned I = 0; I < LANE_NUM; ++I) {
8929 Imm |= Lane[I] << (LANE_SHIFT * I);
8930 }
8931 return true;
8932 }
8933 return false;
8934}
8935
8936bool AMDGPUAsmParser::parseSwizzleBroadcast(int64_t &Imm) {
8937 using namespace llvm::AMDGPU::Swizzle;
8938
8939 SMLoc Loc;
8940 int64_t GroupSize;
8941 int64_t LaneIdx;
8942
8943 if (!parseSwizzleOperand(GroupSize, 2, 32,
8944 "group size must be in the interval [2,32]", Loc)) {
8945 return false;
8946 }
8947 if (!isPowerOf2_64(GroupSize)) {
8948 Error(Loc, "group size must be a power of two");
8949 return false;
8950 }
8951 if (parseSwizzleOperand(LaneIdx, 0, GroupSize - 1,
8952 "lane id must be in the interval [0,group size - 1]",
8953 Loc)) {
8954 Imm = encodeBitmaskPerm(BITMASK_MAX - GroupSize + 1, LaneIdx, 0);
8955 return true;
8956 }
8957 return false;
8958}
8959
8960bool AMDGPUAsmParser::parseSwizzleReverse(int64_t &Imm) {
8961 using namespace llvm::AMDGPU::Swizzle;
8962
8963 SMLoc Loc;
8964 int64_t GroupSize;
8965
8966 if (!parseSwizzleOperand(GroupSize, 2, 32,
8967 "group size must be in the interval [2,32]", Loc)) {
8968 return false;
8969 }
8970 if (!isPowerOf2_64(GroupSize)) {
8971 Error(Loc, "group size must be a power of two");
8972 return false;
8973 }
8974
8975 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize - 1);
8976 return true;
8977}
8978
8979bool AMDGPUAsmParser::parseSwizzleSwap(int64_t &Imm) {
8980 using namespace llvm::AMDGPU::Swizzle;
8981
8982 SMLoc Loc;
8983 int64_t GroupSize;
8984
8985 if (!parseSwizzleOperand(GroupSize, 1, 16,
8986 "group size must be in the interval [1,16]", Loc)) {
8987 return false;
8988 }
8989 if (!isPowerOf2_64(GroupSize)) {
8990 Error(Loc, "group size must be a power of two");
8991 return false;
8992 }
8993
8994 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize);
8995 return true;
8996}
8997
8998bool AMDGPUAsmParser::parseSwizzleBitmaskPerm(int64_t &Imm) {
8999 using namespace llvm::AMDGPU::Swizzle;
9000
9001 if (!skipToken(AsmToken::Comma, "expected a comma")) {
9002 return false;
9003 }
9004
9005 StringRef Ctl;
9006 SMLoc StrLoc = getLoc();
9007 if (!parseString(Ctl)) {
9008 return false;
9009 }
9010 if (Ctl.size() != BITMASK_WIDTH) {
9011 Error(StrLoc, "expected a 5-character mask");
9012 return false;
9013 }
9014
9015 unsigned AndMask = 0;
9016 unsigned OrMask = 0;
9017 unsigned XorMask = 0;
9018
9019 for (size_t i = 0; i < Ctl.size(); ++i) {
9020 unsigned Mask = 1 << (BITMASK_WIDTH - 1 - i);
9021 switch (Ctl[i]) {
9022 default:
9023 Error(StrLoc, "invalid mask");
9024 return false;
9025 case '0':
9026 break;
9027 case '1':
9028 OrMask |= Mask;
9029 break;
9030 case 'p':
9031 AndMask |= Mask;
9032 break;
9033 case 'i':
9034 AndMask |= Mask;
9035 XorMask |= Mask;
9036 break;
9037 }
9038 }
9039
9040 Imm = encodeBitmaskPerm(AndMask, OrMask, XorMask);
9041 return true;
9042}
9043
9044bool AMDGPUAsmParser::parseSwizzleFFT(int64_t &Imm) {
9045 using namespace llvm::AMDGPU::Swizzle;
9046
9047 if (!AMDGPU::isGFX9Plus(getSTI())) {
9048 Error(getLoc(), "FFT mode swizzle not supported on this GPU");
9049 return false;
9050 }
9051
9052 int64_t Swizzle;
9053 SMLoc Loc;
9054 if (!parseSwizzleOperand(Swizzle, 0, FFT_SWIZZLE_MAX,
9055 "FFT swizzle must be in the interval [0," +
9056 Twine(FFT_SWIZZLE_MAX) + Twine(']'),
9057 Loc))
9058 return false;
9059
9060 Imm = FFT_MODE_ENC | Swizzle;
9061 return true;
9062}
9063
9064bool AMDGPUAsmParser::parseSwizzleRotate(int64_t &Imm) {
9065 using namespace llvm::AMDGPU::Swizzle;
9066
9067 if (!AMDGPU::isGFX9Plus(getSTI())) {
9068 Error(getLoc(), "Rotate mode swizzle not supported on this GPU");
9069 return false;
9070 }
9071
9072 SMLoc Loc;
9073 int64_t Direction;
9074
9075 if (!parseSwizzleOperand(Direction, 0, 1,
9076 "direction must be 0 (left) or 1 (right)", Loc))
9077 return false;
9078
9079 int64_t RotateSize;
9080 if (!parseSwizzleOperand(
9081 RotateSize, 0, ROTATE_MAX_SIZE,
9082 "number of threads to rotate must be in the interval [0," +
9083 Twine(ROTATE_MAX_SIZE) + Twine(']'),
9084 Loc))
9085 return false;
9086
9088 (RotateSize << ROTATE_SIZE_SHIFT);
9089 return true;
9090}
9091
9092bool AMDGPUAsmParser::parseSwizzleOffset(int64_t &Imm) {
9093
9094 SMLoc OffsetLoc = getLoc();
9095
9096 if (!parseExpr(Imm, "a swizzle macro")) {
9097 return false;
9098 }
9099 if (!isUInt<16>(Imm)) {
9100 Error(OffsetLoc, "expected a 16-bit offset");
9101 return false;
9102 }
9103 return true;
9104}
9105
9106bool AMDGPUAsmParser::parseSwizzleMacro(int64_t &Imm) {
9107 using namespace llvm::AMDGPU::Swizzle;
9108
9109 if (skipToken(AsmToken::LParen, "expected a left parentheses")) {
9110
9111 SMLoc ModeLoc = getLoc();
9112 bool Ok = false;
9113
9114 if (trySkipId(IdSymbolic[ID_QUAD_PERM])) {
9115 Ok = parseSwizzleQuadPerm(Imm);
9116 } else if (trySkipId(IdSymbolic[ID_BITMASK_PERM])) {
9117 Ok = parseSwizzleBitmaskPerm(Imm);
9118 } else if (trySkipId(IdSymbolic[ID_BROADCAST])) {
9119 Ok = parseSwizzleBroadcast(Imm);
9120 } else if (trySkipId(IdSymbolic[ID_SWAP])) {
9121 Ok = parseSwizzleSwap(Imm);
9122 } else if (trySkipId(IdSymbolic[ID_REVERSE])) {
9123 Ok = parseSwizzleReverse(Imm);
9124 } else if (trySkipId(IdSymbolic[ID_FFT])) {
9125 Ok = parseSwizzleFFT(Imm);
9126 } else if (trySkipId(IdSymbolic[ID_ROTATE])) {
9127 Ok = parseSwizzleRotate(Imm);
9128 } else {
9129 Error(ModeLoc, "expected a swizzle mode");
9130 }
9131
9132 return Ok && skipToken(AsmToken::RParen, "expected a closing parentheses");
9133 }
9134
9135 return false;
9136}
9137
9138ParseStatus AMDGPUAsmParser::parseSwizzle(OperandVector &Operands) {
9139 SMLoc S = getLoc();
9140 int64_t Imm = 0;
9141
9142 if (trySkipId("offset")) {
9143
9144 bool Ok = false;
9145 if (skipToken(AsmToken::Colon, "expected a colon")) {
9146 if (trySkipId("swizzle")) {
9147 Ok = parseSwizzleMacro(Imm);
9148 } else {
9149 Ok = parseSwizzleOffset(Imm);
9150 }
9151 }
9152
9153 Operands.push_back(
9154 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTySwizzle));
9155
9157 }
9158 return ParseStatus::NoMatch;
9159}
9160
9161bool AMDGPUOperand::isSwizzle() const { return isImmTy(ImmTySwizzle); }
9162
9163//===----------------------------------------------------------------------===//
9164// VGPR Index Mode
9165//===----------------------------------------------------------------------===//
9166
9167int64_t AMDGPUAsmParser::parseGPRIdxMacro() {
9168
9169 using namespace llvm::AMDGPU::VGPRIndexMode;
9170
9171 if (trySkipToken(AsmToken::RParen)) {
9172 return OFF;
9173 }
9174
9175 int64_t Imm = 0;
9176
9177 while (true) {
9178 unsigned Mode = 0;
9179 SMLoc S = getLoc();
9180
9181 for (unsigned ModeId = ID_MIN; ModeId <= ID_MAX; ++ModeId) {
9182 if (trySkipId(IdSymbolic[ModeId])) {
9183 Mode = 1 << ModeId;
9184 break;
9185 }
9186 }
9187
9188 if (Mode == 0) {
9189 Error(S, (Imm == 0)
9190 ? "expected a VGPR index mode or a closing parenthesis"
9191 : "expected a VGPR index mode");
9192 return UNDEF;
9193 }
9194
9195 if (Imm & Mode) {
9196 Error(S, "duplicate VGPR index mode");
9197 return UNDEF;
9198 }
9199 Imm |= Mode;
9200
9201 if (trySkipToken(AsmToken::RParen))
9202 break;
9203 if (!skipToken(AsmToken::Comma,
9204 "expected a comma or a closing parenthesis"))
9205 return UNDEF;
9206 }
9207
9208 return Imm;
9209}
9210
9211ParseStatus AMDGPUAsmParser::parseGPRIdxMode(OperandVector &Operands) {
9212
9213 using namespace llvm::AMDGPU::VGPRIndexMode;
9214
9215 int64_t Imm = 0;
9216 SMLoc S = getLoc();
9217
9218 if (trySkipId("gpr_idx", AsmToken::LParen)) {
9219 Imm = parseGPRIdxMacro();
9220 if (Imm == UNDEF)
9221 return ParseStatus::Failure;
9222 } else {
9223 if (getParser().parseAbsoluteExpression(Imm))
9224 return ParseStatus::Failure;
9225 if (Imm < 0 || !isUInt<4>(Imm))
9226 return Error(S, "invalid immediate: only 4-bit values are legal");
9227 }
9228
9229 Operands.push_back(
9230 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyGprIdxMode));
9231 return ParseStatus::Success;
9232}
9233
9234bool AMDGPUOperand::isGPRIdxMode() const { return isImmTy(ImmTyGprIdxMode); }
9235
9236//===----------------------------------------------------------------------===//
9237// sopp branch targets
9238//===----------------------------------------------------------------------===//
9239
9240ParseStatus AMDGPUAsmParser::parseSOPPBrTarget(OperandVector &Operands) {
9241
9242 // Make sure we are not parsing something
9243 // that looks like a label or an expression but is not.
9244 // This will improve error messages.
9245 if (isRegister() || isModifier())
9246 return ParseStatus::NoMatch;
9247
9248 if (!parseExpr(Operands))
9249 return ParseStatus::Failure;
9250
9251 AMDGPUOperand &Opr = ((AMDGPUOperand &)*Operands[Operands.size() - 1]);
9252 assert(Opr.isImm() || Opr.isExpr());
9253 SMLoc Loc = Opr.getStartLoc();
9254
9255 // Currently we do not support arbitrary expressions as branch targets.
9256 // Only labels and absolute expressions are accepted.
9257 if (Opr.isExpr() && !Opr.isSymbolRefExpr()) {
9258 Error(Loc, "expected an absolute expression or a label");
9259 } else if (Opr.isImm() && !Opr.isS16Imm()) {
9260 Error(Loc, "expected a 16-bit signed jump offset");
9261 }
9262
9263 return ParseStatus::Success;
9264}
9265
9266//===----------------------------------------------------------------------===//
9267// Boolean holding registers
9268//===----------------------------------------------------------------------===//
9269
9270ParseStatus AMDGPUAsmParser::parseBoolReg(OperandVector &Operands) {
9271 return parseReg(Operands);
9272}
9273
9274//===----------------------------------------------------------------------===//
9275// mubuf
9276//===----------------------------------------------------------------------===//
9277
9278void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst, const OperandVector &Operands,
9279 bool IsAtomic) {
9280 OptionalImmIndexMap OptionalIdx;
9281 unsigned FirstOperandIdx = 1;
9282 bool IsAtomicReturn = false;
9283
9284 if (IsAtomic) {
9285 IsAtomicReturn = SIInstrFlags::isAtomicRet(MII, Inst);
9286 }
9287
9288 for (unsigned i = FirstOperandIdx, e = Operands.size(); i != e; ++i) {
9289 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
9290
9291 // Add the register arguments
9292 if (Op.isReg()) {
9293 Op.addRegOperands(Inst, 1);
9294 // Insert a tied src for atomic return dst.
9295 // This cannot be postponed as subsequent calls to
9296 // addImmOperands rely on correct number of MC operands.
9297 if (IsAtomicReturn && i == FirstOperandIdx)
9298 Op.addRegOperands(Inst, 1);
9299 continue;
9300 }
9301
9302 // Handle the case where soffset is an immediate
9303 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
9304 Op.addImmOperands(Inst, 1);
9305 continue;
9306 }
9307
9308 // Handle tokens like 'offen' which are sometimes hard-coded into the
9309 // asm string. There are no MCInst operands for these.
9310 if (Op.isToken()) {
9311 continue;
9312 }
9313 assert(Op.isImm());
9314
9315 // Handle optional arguments
9316 OptionalIdx[Op.getImmTy()] = i;
9317 }
9318
9319 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9320 AMDGPUOperand::ImmTyOffset);
9321 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyCPol,
9322 0);
9323 // Parse a dummy operand as a placeholder for the SWZ operand. This enforces
9324 // agreement between MCInstrDesc.getNumOperands and MCInst.getNumOperands.
9326}
9327
9328//===----------------------------------------------------------------------===//
9329// smrd
9330//===----------------------------------------------------------------------===//
9331
9332bool AMDGPUOperand::isSMRDOffset8() const {
9333 return isImmLiteral() && isUInt<8>(getImm());
9334}
9335
9336bool AMDGPUOperand::isSMEMOffset() const {
9337 // Offset range is checked later by validator.
9338 return isImmLiteral();
9339}
9340
9341bool AMDGPUOperand::isSMRDLiteralOffset() const {
9342 // 32-bit literals are only supported on CI and we only want to use them
9343 // when the offset is > 8-bits.
9344 return isImmLiteral() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
9345}
9346
9347//===----------------------------------------------------------------------===//
9348// vop3
9349//===----------------------------------------------------------------------===//
9350
9351static bool ConvertOmodMul(int64_t &Mul) {
9352 if (Mul != 1 && Mul != 2 && Mul != 4)
9353 return false;
9354
9355 Mul >>= 1;
9356 return true;
9357}
9358
9359static bool ConvertOmodDiv(int64_t &Div) {
9360 if (Div == 1) {
9361 Div = 0;
9362 return true;
9363 }
9364
9365 if (Div == 2) {
9366 Div = 3;
9367 return true;
9368 }
9369
9370 return false;
9371}
9372
9373// For pre-gfx11 targets, both bound_ctrl:0 and bound_ctrl:1 are encoded as 1.
9374// This is intentional and ensures compatibility with sp3.
9375// See bug 35397 for details.
9376bool AMDGPUAsmParser::convertDppBoundCtrl(int64_t &BoundCtrl) {
9377 if (BoundCtrl == 0 || BoundCtrl == 1) {
9378 if (!isGFX11Plus())
9379 BoundCtrl = 1;
9380 return true;
9381 }
9382 return false;
9383}
9384
9385void AMDGPUAsmParser::onBeginOfFile() {
9386 if (!getParser().getStreamer().getTargetStreamer())
9387 return;
9388
9389 if (!getTargetStreamer().getTargetID())
9390 getTargetStreamer().initializeTargetID(getSTI(),
9391 /*ApplyFeatureString=*/true);
9392}
9393
9394void AMDGPUAsmParser::emitTargetDirective() {
9395 if (TargetDirectiveEmitted)
9396 return;
9397 TargetDirectiveEmitted = true;
9398
9399 if (!getParser().getStreamer().getTargetStreamer() ||
9400 getSTI().getTargetTriple().getArch() == Triple::r600)
9401 return;
9402
9403 if (isHsaAbi(getSTI()))
9404 getTargetStreamer().EmitDirectiveAMDGCNTarget();
9405}
9406
9407/// Parse AMDGPU specific expressions.
9408///
9409/// expr ::= or(expr, ...) |
9410/// max(expr, ...) |
9411/// min(expr, ...)
9412///
9413bool AMDGPUAsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
9414 using AGVK = AMDGPUMCExpr::VariantKind;
9415
9416 if (isToken(AsmToken::Identifier)) {
9417 StringRef TokenId = getTokenStr();
9418 AGVK VK = StringSwitch<AGVK>(TokenId)
9419 .Case("max", AGVK::AGVK_Max)
9420 .Case("min", AGVK::AGVK_Min)
9421 .Case("or", AGVK::AGVK_Or)
9422 .Case("extrasgprs", AGVK::AGVK_ExtraSGPRs)
9423 .Case("totalnumvgprs", AGVK::AGVK_TotalNumVGPRs)
9424 .Case("alignto", AGVK::AGVK_AlignTo)
9425 .Case("occupancy", AGVK::AGVK_Occupancy)
9426 .Case("instprefsize", AGVK::AGVK_InstPrefSize)
9427 .Default(AGVK::AGVK_None);
9428
9429 if (VK != AGVK::AGVK_None && peekToken().is(AsmToken::LParen)) {
9431 uint64_t CommaCount = 0;
9432 lex(); // Eat Arg ('or', 'max', 'occupancy', etc.)
9433 lex(); // Eat '('
9434 while (true) {
9435 if (trySkipToken(AsmToken::RParen)) {
9436 if (Exprs.empty()) {
9437 Error(getToken().getLoc(),
9438 "empty " + Twine(TokenId) + " expression");
9439 return true;
9440 }
9441 if (CommaCount + 1 != Exprs.size()) {
9442 Error(getToken().getLoc(),
9443 "mismatch of commas in " + Twine(TokenId) + " expression");
9444 return true;
9445 }
9446 if (unsigned Expected = AMDGPUMCExpr::getNumExpectedArgs(VK);
9447 Expected && Exprs.size() != Expected) {
9448 Error(getToken().getLoc(), Twine(TokenId) + " expression expects " +
9449 Twine(Expected) + " operands");
9450 return true;
9451 }
9452 Res = AMDGPUMCExpr::create(VK, Exprs, getContext());
9453 return false;
9454 }
9455 const MCExpr *Expr;
9456 if (getParser().parseExpression(Expr, EndLoc))
9457 return true;
9458 Exprs.push_back(Expr);
9459 bool LastTokenWasComma = trySkipToken(AsmToken::Comma);
9460 if (LastTokenWasComma)
9461 CommaCount++;
9462 if (!LastTokenWasComma && !isToken(AsmToken::RParen)) {
9463 Error(getToken().getLoc(),
9464 "unexpected token in " + Twine(TokenId) + " expression");
9465 return true;
9466 }
9467 }
9468 }
9469 }
9470 return getParser().parsePrimaryExpr(Res, EndLoc, nullptr);
9471}
9472
9473ParseStatus AMDGPUAsmParser::parseOModSI(OperandVector &Operands) {
9474 StringRef Name = getTokenStr();
9475 if (Name == "mul") {
9476 return parseIntWithPrefix("mul", Operands, AMDGPUOperand::ImmTyOModSI,
9478 }
9479
9480 if (Name == "div") {
9481 return parseIntWithPrefix("div", Operands, AMDGPUOperand::ImmTyOModSI,
9483 }
9484
9485 return ParseStatus::NoMatch;
9486}
9487
9488// Determines which bit DST_OP_SEL occupies in the op_sel operand according to
9489// the number of src operands present, then copies that bit into src0_modifiers.
9490static void cvtVOP3DstOpSelOnly(MCInst &Inst, const MCRegisterInfo &MRI) {
9491 int Opc = Inst.getOpcode();
9492 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
9493 if (OpSelIdx == -1)
9494 return;
9495
9496 int SrcNum;
9497 const AMDGPU::OpName Ops[] = {AMDGPU::OpName::src0, AMDGPU::OpName::src1,
9498 AMDGPU::OpName::src2};
9499 for (SrcNum = 0; SrcNum < 3 && AMDGPU::hasNamedOperand(Opc, Ops[SrcNum]);
9500 ++SrcNum)
9501 ;
9502 assert(SrcNum > 0);
9503
9504 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
9505
9506 int DstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
9507 if (DstIdx == -1)
9508 return;
9509
9510 const MCOperand &DstOp = Inst.getOperand(DstIdx);
9511 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers);
9512 uint32_t ModVal = Inst.getOperand(ModIdx).getImm();
9513 if (DstOp.isReg() &&
9514 MRI.getRegClass(AMDGPU::VGPR_16RegClassID).contains(DstOp.getReg())) {
9515 if (AMDGPU::isHi16Reg(DstOp.getReg(), MRI))
9516 ModVal |= SISrcMods::DST_OP_SEL;
9517 } else {
9518 if ((OpSel & (1 << SrcNum)) != 0)
9519 ModVal |= SISrcMods::DST_OP_SEL;
9520 }
9521 Inst.getOperand(ModIdx).setImm(ModVal);
9522}
9523
9524void AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst,
9525 const OperandVector &Operands) {
9526 cvtVOP3P(Inst, Operands);
9527 cvtVOP3DstOpSelOnly(Inst, *getMRI());
9528}
9529
9530void AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands,
9531 OptionalImmIndexMap &OptionalIdx) {
9532 cvtVOP3P(Inst, Operands, OptionalIdx);
9533 cvtVOP3DstOpSelOnly(Inst, *getMRI());
9534}
9535
9536static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) {
9537 return
9538 // 1. This operand is input modifiers
9539 Desc.operands()[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS
9540 // 2. This is not last operand
9541 && Desc.NumOperands > (OpNum + 1)
9542 // 3. Next operand is register class
9543 && Desc.operands()[OpNum + 1].RegClass != -1
9544 // 4. Next register is not tied to any other operand
9545 && Desc.getOperandConstraint(OpNum + 1,
9547}
9548
9549void AMDGPUAsmParser::cvtOpSelHelper(MCInst &Inst, unsigned OpSel) {
9550 unsigned Opc = Inst.getOpcode();
9551 constexpr AMDGPU::OpName Ops[] = {AMDGPU::OpName::src0, AMDGPU::OpName::src1,
9552 AMDGPU::OpName::src2};
9553 constexpr AMDGPU::OpName ModOps[] = {AMDGPU::OpName::src0_modifiers,
9554 AMDGPU::OpName::src1_modifiers,
9555 AMDGPU::OpName::src2_modifiers};
9556 for (int J = 0; J < 3; ++J) {
9557 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]);
9558 if (OpIdx == -1)
9559 // Some instructions, e.g. v_interp_p2_f16 in GFX9, have src0, src2, but
9560 // no src1. So continue instead of break.
9561 continue;
9562
9563 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
9564 uint32_t ModVal = Inst.getOperand(ModIdx).getImm();
9565
9566 if ((OpSel & (1 << J)) != 0)
9567 ModVal |= SISrcMods::OP_SEL_0;
9568 // op_sel[3] is encoded in src0_modifiers.
9569 if (ModOps[J] == AMDGPU::OpName::src0_modifiers && (OpSel & (1 << 3)) != 0)
9570 ModVal |= SISrcMods::DST_OP_SEL;
9571
9572 Inst.getOperand(ModIdx).setImm(ModVal);
9573 }
9574}
9575
9576void AMDGPUAsmParser::cvtVOP3Interp(MCInst &Inst,
9577 const OperandVector &Operands) {
9578 OptionalImmIndexMap OptionalIdx;
9579 unsigned Opc = Inst.getOpcode();
9580
9581 unsigned I = 1;
9582 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
9583 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
9584 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
9585 }
9586
9587 for (unsigned E = Operands.size(); I != E; ++I) {
9588 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
9590 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
9591 } else if (Op.isInterpSlot() || Op.isInterpAttr() ||
9592 Op.isInterpAttrChan()) {
9593 Inst.addOperand(MCOperand::createImm(Op.getImm()));
9594 } else if (Op.isImmModifier()) {
9595 OptionalIdx[Op.getImmTy()] = I;
9596 } else {
9597 llvm_unreachable("unhandled operand type");
9598 }
9599 }
9600
9601 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::high))
9602 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9603 AMDGPUOperand::ImmTyHigh);
9604
9605 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp))
9606 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9607 AMDGPUOperand::ImmTyClamp);
9608
9609 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod))
9610 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9611 AMDGPUOperand::ImmTyOModSI);
9612
9613 // Some v_interp instructions use op_sel[3] for dst.
9614 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) {
9615 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9616 AMDGPUOperand::ImmTyOpSel);
9617 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
9618 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
9619
9620 cvtOpSelHelper(Inst, OpSel);
9621 }
9622}
9623
9624void AMDGPUAsmParser::cvtVINTERP(MCInst &Inst, const OperandVector &Operands) {
9625 OptionalImmIndexMap OptionalIdx;
9626 unsigned Opc = Inst.getOpcode();
9627
9628 unsigned I = 1;
9629 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
9630 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
9631 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
9632 }
9633
9634 for (unsigned E = Operands.size(); I != E; ++I) {
9635 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
9637 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
9638 } else if (Op.isImmModifier()) {
9639 OptionalIdx[Op.getImmTy()] = I;
9640 } else {
9641 llvm_unreachable("unhandled operand type");
9642 }
9643 }
9644
9645 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClamp);
9646
9647 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
9648 if (OpSelIdx != -1)
9649 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9650 AMDGPUOperand::ImmTyOpSel);
9651
9652 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9653 AMDGPUOperand::ImmTyWaitEXP);
9654
9655 if (OpSelIdx == -1)
9656 return;
9657
9658 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
9659 cvtOpSelHelper(Inst, OpSel);
9660}
9661
9662void AMDGPUAsmParser::cvtScaledMFMA(MCInst &Inst,
9663 const OperandVector &Operands) {
9664 OptionalImmIndexMap OptionalIdx;
9665 unsigned Opc = Inst.getOpcode();
9666 unsigned I = 1;
9667 int CbszOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::cbsz);
9668
9669 const MCInstrDesc &Desc = MII.get(Opc);
9670
9671 for (unsigned J = 0; J < Desc.getNumDefs(); ++J)
9672 static_cast<AMDGPUOperand &>(*Operands[I++]).addRegOperands(Inst, 1);
9673
9674 for (unsigned E = Operands.size(); I != E; ++I) {
9675 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands[I]);
9676 int NumOperands = Inst.getNumOperands();
9677 // The order of operands in MCInst and parsed operands are different.
9678 // Adding dummy cbsz and blgp operands at corresponding MCInst operand
9679 // indices for parsing scale values correctly.
9680 if (NumOperands == CbszOpIdx) {
9683 }
9684 if (isRegOrImmWithInputMods(Desc, NumOperands)) {
9685 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
9686 } else if (Op.isImmModifier()) {
9687 OptionalIdx[Op.getImmTy()] = I;
9688 } else {
9689 Op.addRegOrImmOperands(Inst, 1);
9690 }
9691 }
9692
9693 // Insert CBSZ and BLGP operands for F8F6F4 variants
9694 auto CbszIdx = OptionalIdx.find(AMDGPUOperand::ImmTyCBSZ);
9695 if (CbszIdx != OptionalIdx.end()) {
9696 int CbszVal = ((AMDGPUOperand &)*Operands[CbszIdx->second]).getImm();
9697 Inst.getOperand(CbszOpIdx).setImm(CbszVal);
9698 }
9699
9700 int BlgpOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::blgp);
9701 auto BlgpIdx = OptionalIdx.find(AMDGPUOperand::ImmTyBLGP);
9702 if (BlgpIdx != OptionalIdx.end()) {
9703 int BlgpVal = ((AMDGPUOperand &)*Operands[BlgpIdx->second]).getImm();
9704 Inst.getOperand(BlgpOpIdx).setImm(BlgpVal);
9705 }
9706
9707 // Add dummy src_modifiers
9710
9711 // Handle op_sel fields
9712
9713 unsigned OpSel = 0;
9714 auto OpselIdx = OptionalIdx.find(AMDGPUOperand::ImmTyOpSel);
9715 if (OpselIdx != OptionalIdx.end()) {
9716 OpSel = static_cast<const AMDGPUOperand &>(*Operands[OpselIdx->second])
9717 .getImm();
9718 }
9719
9720 unsigned OpSelHi = 0;
9721 auto OpselHiIdx = OptionalIdx.find(AMDGPUOperand::ImmTyOpSelHi);
9722 if (OpselHiIdx != OptionalIdx.end()) {
9723 OpSelHi = static_cast<const AMDGPUOperand &>(*Operands[OpselHiIdx->second])
9724 .getImm();
9725 }
9726 const AMDGPU::OpName ModOps[] = {AMDGPU::OpName::src0_modifiers,
9727 AMDGPU::OpName::src1_modifiers};
9728
9729 for (unsigned J = 0; J < 2; ++J) {
9730 unsigned ModVal = 0;
9731 if (OpSel & (1 << J))
9732 ModVal |= SISrcMods::OP_SEL_0;
9733 if (OpSelHi & (1 << J))
9734 ModVal |= SISrcMods::OP_SEL_1;
9735
9736 const int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
9737 Inst.getOperand(ModIdx).setImm(ModVal);
9738 }
9739}
9740
9741void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands,
9742 OptionalImmIndexMap &OptionalIdx) {
9743 unsigned Opc = Inst.getOpcode();
9744
9745 unsigned I = 1;
9746 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
9747 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
9748 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
9749 }
9750
9751 for (unsigned E = Operands.size(); I != E; ++I) {
9752 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
9754 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
9755 } else if (Op.isImmModifier()) {
9756 OptionalIdx[Op.getImmTy()] = I;
9757 } else {
9758 Op.addRegOrImmOperands(Inst, 1);
9759 }
9760 }
9761
9762 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::scale_sel))
9763 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9764 AMDGPUOperand::ImmTyScaleSel);
9765
9766 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp))
9767 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9768 AMDGPUOperand::ImmTyClamp);
9769
9770 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::byte_sel)) {
9771 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::vdst_in))
9772 Inst.addOperand(Inst.getOperand(0));
9773 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9774 AMDGPUOperand::ImmTyByteSel);
9775 }
9776
9777 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod))
9778 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9779 AMDGPUOperand::ImmTyOModSI);
9780
9781 // Special case v_mac_{f16, f32} and v_fmac_{f16, f32} (gfx906/gfx10+):
9782 // it has src2 register operand that is tied to dst operand
9783 // we don't allow modifiers for this operand in assembler so src2_modifiers
9784 // should be 0.
9785 if (isMAC(Opc)) {
9786 auto *it = Inst.begin();
9787 std::advance(
9788 it, AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers));
9789 it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2
9790 ++it;
9791 // Copy the operand to ensure it's not invalidated when Inst grows.
9792 Inst.insert(it, MCOperand(Inst.getOperand(0))); // src2 = dst
9793 }
9794}
9795
9796void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
9797 OptionalImmIndexMap OptionalIdx;
9798 cvtVOP3(Inst, Operands, OptionalIdx);
9799}
9800
9801void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst, const OperandVector &Operands,
9802 OptionalImmIndexMap &OptIdx) {
9803 const int Opc = Inst.getOpcode();
9804
9805 const bool IsPacked = SIInstrFlags::isPacked(MII, Inst);
9806
9807 if (Opc == AMDGPU::V_CVT_SCALEF32_PK_FP4_F16_vi ||
9808 Opc == AMDGPU::V_CVT_SCALEF32_PK_FP4_BF16_vi ||
9809 Opc == AMDGPU::V_CVT_SR_BF8_F32_vi ||
9810 Opc == AMDGPU::V_CVT_SR_FP8_F32_vi ||
9811 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_gfx11 ||
9812 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_gfx11 ||
9813 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_gfx12 ||
9814 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_gfx12 ||
9815 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_gfx13 ||
9816 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_gfx13) {
9817 Inst.addOperand(MCOperand::createImm(0)); // Placeholder for src2_mods
9818 Inst.addOperand(Inst.getOperand(0));
9819 }
9820
9821 // Append vdst_in only if a previous converter (cvtVOP3DPP for DPP variants,
9822 // cvtVOP3 for byte_sel variants) hasn't already placed it. Use the position
9823 // of the named operand to detect that, the same way cvtVOP3DPP does
9824 // internally.
9825 int VdstInIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
9826 if (VdstInIdx != -1 && VdstInIdx == static_cast<int>(Inst.getNumOperands()))
9827 Inst.addOperand(Inst.getOperand(0));
9828
9829 int BitOp3Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::bitop3);
9830 if (BitOp3Idx != -1) {
9831 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyBitOp3);
9832 }
9833
9834 // FIXME: This is messy. Parse the modifiers as if it was a normal VOP3
9835 // instruction, and then figure out where to actually put the modifiers
9836
9837 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
9838 if (OpSelIdx != -1) {
9839 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSel);
9840 }
9841
9842 int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi);
9843 if (OpSelHiIdx != -1) {
9844 int DefaultVal = IsPacked ? -1 : 0;
9845 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSelHi,
9846 DefaultVal);
9847 }
9848
9849 int MatrixAFMTIdx =
9850 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_a_fmt);
9851 if (MatrixAFMTIdx != -1) {
9852 addOptionalImmOperand(Inst, Operands, OptIdx,
9853 AMDGPUOperand::ImmTyMatrixAFMT, 0);
9854 }
9855
9856 int MatrixBFMTIdx =
9857 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_b_fmt);
9858 if (MatrixBFMTIdx != -1) {
9859 addOptionalImmOperand(Inst, Operands, OptIdx,
9860 AMDGPUOperand::ImmTyMatrixBFMT, 0);
9861 }
9862
9863 int MatrixAScaleIdx =
9864 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_a_scale);
9865 if (MatrixAScaleIdx != -1) {
9866 addOptionalImmOperand(Inst, Operands, OptIdx,
9867 AMDGPUOperand::ImmTyMatrixAScale, 0);
9868 }
9869
9870 int MatrixBScaleIdx =
9871 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_b_scale);
9872 if (MatrixBScaleIdx != -1) {
9873 addOptionalImmOperand(Inst, Operands, OptIdx,
9874 AMDGPUOperand::ImmTyMatrixBScale, 0);
9875 }
9876
9877 int MatrixAScaleFmtIdx =
9878 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_a_scale_fmt);
9879 if (MatrixAScaleFmtIdx != -1) {
9880 addOptionalImmOperand(Inst, Operands, OptIdx,
9881 AMDGPUOperand::ImmTyMatrixAScaleFmt, 0);
9882 }
9883
9884 int MatrixBScaleFmtIdx =
9885 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_b_scale_fmt);
9886 if (MatrixBScaleFmtIdx != -1) {
9887 addOptionalImmOperand(Inst, Operands, OptIdx,
9888 AMDGPUOperand::ImmTyMatrixBScaleFmt, 0);
9889 }
9890
9891 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::matrix_a_reuse))
9892 addOptionalImmOperand(Inst, Operands, OptIdx,
9893 AMDGPUOperand::ImmTyMatrixAReuse, 0);
9894
9895 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::matrix_b_reuse))
9896 addOptionalImmOperand(Inst, Operands, OptIdx,
9897 AMDGPUOperand::ImmTyMatrixBReuse, 0);
9898
9899 int NegLoIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_lo);
9900 if (NegLoIdx != -1)
9901 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegLo);
9902
9903 int NegHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_hi);
9904 if (NegHiIdx != -1)
9905 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegHi);
9906
9907 const AMDGPU::OpName Ops[] = {AMDGPU::OpName::src0, AMDGPU::OpName::src1,
9908 AMDGPU::OpName::src2};
9909 const AMDGPU::OpName ModOps[] = {AMDGPU::OpName::src0_modifiers,
9910 AMDGPU::OpName::src1_modifiers,
9911 AMDGPU::OpName::src2_modifiers};
9912
9913 unsigned OpSel = 0;
9914 unsigned OpSelHi = 0;
9915 unsigned NegLo = 0;
9916 unsigned NegHi = 0;
9917
9918 if (OpSelIdx != -1)
9919 OpSel = Inst.getOperand(OpSelIdx).getImm();
9920
9921 if (OpSelHiIdx != -1)
9922 OpSelHi = Inst.getOperand(OpSelHiIdx).getImm();
9923
9924 if (NegLoIdx != -1)
9925 NegLo = Inst.getOperand(NegLoIdx).getImm();
9926
9927 if (NegHiIdx != -1)
9928 NegHi = Inst.getOperand(NegHiIdx).getImm();
9929
9930 for (int J = 0; J < 3; ++J) {
9931 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]);
9932 if (OpIdx == -1)
9933 break;
9934
9935 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
9936
9937 if (ModIdx == -1)
9938 continue;
9939
9940 // For MAC instructions, src2 is tied to vdst and its op_sel bit
9941 // is not encoded.
9942 if (AMDGPU::isMAC(Opc) && ModOps[J] == AMDGPU::OpName::src2_modifiers)
9943 continue;
9944
9945 uint32_t ModVal = 0;
9946
9947 const MCOperand &SrcOp = Inst.getOperand(OpIdx);
9948 if (SrcOp.isReg() && getMRI()
9949 ->getRegClass(AMDGPU::VGPR_16RegClassID)
9950 .contains(SrcOp.getReg())) {
9951 bool VGPRSuffixIsHi = AMDGPU::isHi16Reg(SrcOp.getReg(), *getMRI());
9952 if (VGPRSuffixIsHi)
9953 ModVal |= SISrcMods::OP_SEL_0;
9954 } else {
9955 if ((OpSel & (1 << J)) != 0)
9956 ModVal |= SISrcMods::OP_SEL_0;
9957 }
9958
9959 if ((OpSelHi & (1 << J)) != 0)
9960 ModVal |= SISrcMods::OP_SEL_1;
9961
9962 if ((NegLo & (1 << J)) != 0)
9963 ModVal |= SISrcMods::NEG;
9964
9965 if ((NegHi & (1 << J)) != 0)
9966 ModVal |= SISrcMods::NEG_HI;
9967
9968 Inst.getOperand(ModIdx).setImm(Inst.getOperand(ModIdx).getImm() | ModVal);
9969 }
9970}
9971
9972void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst, const OperandVector &Operands) {
9973 OptionalImmIndexMap OptIdx;
9974 cvtVOP3(Inst, Operands, OptIdx);
9975 cvtVOP3P(Inst, Operands, OptIdx);
9976}
9977
9979 unsigned i, unsigned Opc,
9980 AMDGPU::OpName OpName) {
9981 if (AMDGPU::getNamedOperandIdx(Opc, OpName) != -1)
9982 ((AMDGPUOperand &)*Operands[i]).addRegOrImmWithFPInputModsOperands(Inst, 2);
9983 else
9984 ((AMDGPUOperand &)*Operands[i]).addRegOperands(Inst, 1);
9985}
9986
9987void AMDGPUAsmParser::cvtSWMMAC(MCInst &Inst, const OperandVector &Operands) {
9988 unsigned Opc = Inst.getOpcode();
9989
9990 ((AMDGPUOperand &)*Operands[1]).addRegOperands(Inst, 1);
9991 addSrcModifiersAndSrc(Inst, Operands, 2, Opc, AMDGPU::OpName::src0_modifiers);
9992 addSrcModifiersAndSrc(Inst, Operands, 3, Opc, AMDGPU::OpName::src1_modifiers);
9993 ((AMDGPUOperand &)*Operands[1]).addRegOperands(Inst, 1); // srcTiedDef
9994 ((AMDGPUOperand &)*Operands[4]).addRegOperands(Inst, 1); // src2
9995
9996 OptionalImmIndexMap OptIdx;
9997 for (unsigned i = 5; i < Operands.size(); ++i) {
9998 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
9999 OptIdx[Op.getImmTy()] = i;
10000 }
10001
10002 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::index_key_8bit))
10003 addOptionalImmOperand(Inst, Operands, OptIdx,
10004 AMDGPUOperand::ImmTyIndexKey8bit);
10005
10006 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::index_key_16bit))
10007 addOptionalImmOperand(Inst, Operands, OptIdx,
10008 AMDGPUOperand::ImmTyIndexKey16bit);
10009
10010 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::index_key_32bit))
10011 addOptionalImmOperand(Inst, Operands, OptIdx,
10012 AMDGPUOperand::ImmTyIndexKey32bit);
10013
10014 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp))
10015 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyClamp);
10016
10017 cvtVOP3P(Inst, Operands, OptIdx);
10018}
10019
10020//===----------------------------------------------------------------------===//
10021// VOPD
10022//===----------------------------------------------------------------------===//
10023
10024ParseStatus AMDGPUAsmParser::parseVOPD(OperandVector &Operands) {
10025 if (!hasVOPD(getSTI()))
10026 return ParseStatus::NoMatch;
10027
10028 if (isToken(AsmToken::Colon) && peekToken(false).is(AsmToken::Colon)) {
10029 SMLoc S = getLoc();
10030 lex();
10031 lex();
10032 Operands.push_back(AMDGPUOperand::CreateToken(this, "::", S));
10033 SMLoc OpYLoc = getLoc();
10034 StringRef OpYName;
10035 if (isToken(AsmToken::Identifier) && !Parser.parseIdentifier(OpYName)) {
10036 Operands.push_back(AMDGPUOperand::CreateToken(this, OpYName, OpYLoc));
10037 return ParseStatus::Success;
10038 }
10039 return Error(OpYLoc, "expected a VOPDY instruction after ::");
10040 }
10041 return ParseStatus::NoMatch;
10042}
10043
10044// Create VOPD MCInst operands using parsed assembler operands.
10045void AMDGPUAsmParser::cvtVOPD(MCInst &Inst, const OperandVector &Operands) {
10046 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
10047
10048 auto addOp = [&](uint16_t ParsedOprIdx) { // NOLINT:function pointer
10049 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[ParsedOprIdx]);
10051 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
10052 return;
10053 }
10054 if (Op.isReg()) {
10055 Op.addRegOperands(Inst, 1);
10056 return;
10057 }
10058 if (Op.isImm()) {
10059 Op.addImmOperands(Inst, 1);
10060 return;
10061 }
10062 llvm_unreachable("Unhandled operand type in cvtVOPD");
10063 };
10064
10065 const auto &InstInfo = getVOPDInstInfo(Inst.getOpcode(), &MII);
10066
10067 // MCInst operands are ordered as follows:
10068 // dstX, dstY, src0X [, other OpX operands], src0Y [, other OpY operands]
10069
10070 for (auto CompIdx : VOPD::COMPONENTS) {
10071 addOp(InstInfo[CompIdx].getIndexOfDstInParsedOperands());
10072 }
10073
10074 for (auto CompIdx : VOPD::COMPONENTS) {
10075 const auto &CInfo = InstInfo[CompIdx];
10076 auto CompSrcOperandsNum = InstInfo[CompIdx].getCompParsedSrcOperandsNum();
10077 for (unsigned CompSrcIdx = 0; CompSrcIdx < CompSrcOperandsNum; ++CompSrcIdx)
10078 addOp(CInfo.getIndexOfSrcInParsedOperands(CompSrcIdx));
10079 if (CInfo.hasSrc2Acc())
10080 addOp(CInfo.getIndexOfDstInParsedOperands());
10081 }
10082
10083 int BitOp3Idx =
10084 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::bitop3);
10085 if (BitOp3Idx != -1) {
10086 OptionalImmIndexMap OptIdx;
10087 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands.back());
10088 if (Op.isImm())
10089 OptIdx[Op.getImmTy()] = Operands.size() - 1;
10090
10091 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyBitOp3);
10092 }
10093}
10094
10095//===----------------------------------------------------------------------===//
10096// dpp
10097//===----------------------------------------------------------------------===//
10098
10099bool AMDGPUOperand::isDPP8() const { return isImmTy(ImmTyDPP8); }
10100
10101bool AMDGPUOperand::isDPPCtrl() const {
10102 using namespace AMDGPU::DPP;
10103
10104 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
10105 if (result) {
10106 int64_t Imm = getImm();
10107 return (Imm >= DppCtrl::QUAD_PERM_FIRST &&
10108 Imm <= DppCtrl::QUAD_PERM_LAST) ||
10109 (Imm >= DppCtrl::ROW_SHL_FIRST && Imm <= DppCtrl::ROW_SHL_LAST) ||
10110 (Imm >= DppCtrl::ROW_SHR_FIRST && Imm <= DppCtrl::ROW_SHR_LAST) ||
10111 (Imm >= DppCtrl::ROW_ROR_FIRST && Imm <= DppCtrl::ROW_ROR_LAST) ||
10112 (Imm == DppCtrl::WAVE_SHL1) || (Imm == DppCtrl::WAVE_ROL1) ||
10113 (Imm == DppCtrl::WAVE_SHR1) || (Imm == DppCtrl::WAVE_ROR1) ||
10114 (Imm == DppCtrl::ROW_MIRROR) || (Imm == DppCtrl::ROW_HALF_MIRROR) ||
10115 (Imm == DppCtrl::BCAST15) || (Imm == DppCtrl::BCAST31) ||
10116 (Imm >= DppCtrl::ROW_SHARE_FIRST &&
10117 Imm <= DppCtrl::ROW_SHARE_LAST) ||
10118 (Imm >= DppCtrl::ROW_XMASK_FIRST && Imm <= DppCtrl::ROW_XMASK_LAST);
10119 }
10120 return false;
10121}
10122
10123//===----------------------------------------------------------------------===//
10124// mAI
10125//===----------------------------------------------------------------------===//
10126
10127bool AMDGPUOperand::isBLGP() const {
10128 return isImm() && getImmTy() == ImmTyBLGP && isUInt<3>(getImm());
10129}
10130
10131bool AMDGPUOperand::isS16Imm() const {
10132 return isImmLiteral() && (isInt<16>(getImm()) || isUInt<16>(getImm()));
10133}
10134
10135bool AMDGPUOperand::isU16Imm() const {
10136 return isImmLiteral() && isUInt<16>(getImm());
10137}
10138
10139//===----------------------------------------------------------------------===//
10140// dim
10141//===----------------------------------------------------------------------===//
10142
10143bool AMDGPUAsmParser::parseDimId(unsigned &Encoding) {
10144 // We want to allow "dim:1D" etc.,
10145 // but the initial 1 is tokenized as an integer.
10146 std::string Token;
10147 if (isToken(AsmToken::Integer)) {
10148 SMLoc Loc = getToken().getEndLoc();
10149 Token = std::string(getTokenStr());
10150 lex();
10151 if (getLoc() != Loc)
10152 return false;
10153 }
10154
10155 StringRef Suffix;
10156 if (!parseId(Suffix))
10157 return false;
10158 Token += Suffix;
10159
10160 StringRef DimId = Token;
10161 DimId.consume_front("SQ_RSRC_IMG_");
10162
10163 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByAsmSuffix(DimId);
10164 if (!DimInfo)
10165 return false;
10166
10167 Encoding = DimInfo->Encoding;
10168 return true;
10169}
10170
10171ParseStatus AMDGPUAsmParser::parseDim(OperandVector &Operands) {
10172 if (!isGFX10Plus())
10173 return ParseStatus::NoMatch;
10174
10175 SMLoc S = getLoc();
10176
10177 if (!trySkipId("dim", AsmToken::Colon))
10178 return ParseStatus::NoMatch;
10179
10180 unsigned Encoding;
10181 SMLoc Loc = getLoc();
10182 if (!parseDimId(Encoding))
10183 return Error(Loc, "invalid dim value");
10184
10185 Operands.push_back(
10186 AMDGPUOperand::CreateImm(this, Encoding, S, AMDGPUOperand::ImmTyDim));
10187 return ParseStatus::Success;
10188}
10189
10190//===----------------------------------------------------------------------===//
10191// dpp
10192//===----------------------------------------------------------------------===//
10193
10194ParseStatus AMDGPUAsmParser::parseDPP8(OperandVector &Operands) {
10195 SMLoc S = getLoc();
10196
10197 if (!isGFX10Plus() || !trySkipId("dpp8", AsmToken::Colon))
10198 return ParseStatus::NoMatch;
10199
10200 // dpp8:[%d,%d,%d,%d,%d,%d,%d,%d]
10201
10202 int64_t Sels[8];
10203
10204 if (!skipToken(AsmToken::LBrac, "expected an opening square bracket"))
10205 return ParseStatus::Failure;
10206
10207 for (size_t i = 0; i < 8; ++i) {
10208 if (i > 0 && !skipToken(AsmToken::Comma, "expected a comma"))
10209 return ParseStatus::Failure;
10210
10211 SMLoc Loc = getLoc();
10212 if (getParser().parseAbsoluteExpression(Sels[i]))
10213 return ParseStatus::Failure;
10214 if (0 > Sels[i] || 7 < Sels[i])
10215 return Error(Loc, "expected a 3-bit value");
10216 }
10217
10218 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket"))
10219 return ParseStatus::Failure;
10220
10221 unsigned DPP8 = 0;
10222 for (size_t i = 0; i < 8; ++i)
10223 DPP8 |= (Sels[i] << (i * 3));
10224
10225 Operands.push_back(
10226 AMDGPUOperand::CreateImm(this, DPP8, S, AMDGPUOperand::ImmTyDPP8));
10227 return ParseStatus::Success;
10228}
10229
10230bool AMDGPUAsmParser::isSupportedDPPCtrl(StringRef Ctrl,
10231 const OperandVector &Operands) {
10232 if (Ctrl == "row_newbcast")
10233 return isGFX90A();
10234
10235 if (Ctrl == "row_share" || Ctrl == "row_xmask")
10236 return isGFX10Plus();
10237
10238 if (Ctrl == "wave_shl" || Ctrl == "wave_shr" || Ctrl == "wave_rol" ||
10239 Ctrl == "wave_ror" || Ctrl == "row_bcast")
10240 return isVI() || isGFX9();
10241
10242 return Ctrl == "row_mirror" || Ctrl == "row_half_mirror" ||
10243 Ctrl == "quad_perm" || Ctrl == "row_shl" || Ctrl == "row_shr" ||
10244 Ctrl == "row_ror";
10245}
10246
10247int64_t AMDGPUAsmParser::parseDPPCtrlPerm() {
10248 // quad_perm:[%d,%d,%d,%d]
10249
10250 if (!skipToken(AsmToken::LBrac, "expected an opening square bracket"))
10251 return -1;
10252
10253 int64_t Val = 0;
10254 for (int i = 0; i < 4; ++i) {
10255 if (i > 0 && !skipToken(AsmToken::Comma, "expected a comma"))
10256 return -1;
10257
10258 int64_t Temp;
10259 SMLoc Loc = getLoc();
10260 if (getParser().parseAbsoluteExpression(Temp))
10261 return -1;
10262 if (Temp < 0 || Temp > 3) {
10263 Error(Loc, "expected a 2-bit value");
10264 return -1;
10265 }
10266
10267 Val += (Temp << i * 2);
10268 }
10269
10270 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket"))
10271 return -1;
10272
10273 return Val;
10274}
10275
10276int64_t AMDGPUAsmParser::parseDPPCtrlSel(StringRef Ctrl) {
10277 using namespace AMDGPU::DPP;
10278
10279 // sel:%d
10280
10281 int64_t Val;
10282 SMLoc Loc = getLoc();
10283
10284 if (getParser().parseAbsoluteExpression(Val))
10285 return -1;
10286
10287 struct DppCtrlCheck {
10288 int64_t Ctrl;
10289 int Lo;
10290 int Hi;
10291 };
10292
10293 DppCtrlCheck Check =
10294 StringSwitch<DppCtrlCheck>(Ctrl)
10295 .Case("wave_shl", {DppCtrl::WAVE_SHL1, 1, 1})
10296 .Case("wave_rol", {DppCtrl::WAVE_ROL1, 1, 1})
10297 .Case("wave_shr", {DppCtrl::WAVE_SHR1, 1, 1})
10298 .Case("wave_ror", {DppCtrl::WAVE_ROR1, 1, 1})
10299 .Case("row_shl", {DppCtrl::ROW_SHL0, 1, 15})
10300 .Case("row_shr", {DppCtrl::ROW_SHR0, 1, 15})
10301 .Case("row_ror", {DppCtrl::ROW_ROR0, 1, 15})
10302 .Case("row_share", {DppCtrl::ROW_SHARE_FIRST, 0, 15})
10303 .Case("row_xmask", {DppCtrl::ROW_XMASK_FIRST, 0, 15})
10304 .Case("row_newbcast", {DppCtrl::ROW_NEWBCAST_FIRST, 0, 15})
10305 .Default({-1, 0, 0});
10306
10307 bool Valid;
10308 if (Check.Ctrl == -1) {
10309 Valid = (Ctrl == "row_bcast" && (Val == 15 || Val == 31));
10310 Val = (Val == 15) ? DppCtrl::BCAST15 : DppCtrl::BCAST31;
10311 } else {
10312 Valid = Check.Lo <= Val && Val <= Check.Hi;
10313 Val = (Check.Lo == Check.Hi) ? Check.Ctrl : (Check.Ctrl | Val);
10314 }
10315
10316 if (!Valid) {
10317 Error(Loc, Twine("invalid ", Ctrl) + Twine(" value"));
10318 return -1;
10319 }
10320
10321 return Val;
10322}
10323
10324ParseStatus AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
10325 using namespace AMDGPU::DPP;
10326
10327 if (!isToken(AsmToken::Identifier) ||
10328 !isSupportedDPPCtrl(getTokenStr(), Operands))
10329 return ParseStatus::NoMatch;
10330
10331 SMLoc S = getLoc();
10332 int64_t Val = -1;
10333 StringRef Ctrl;
10334
10335 parseId(Ctrl);
10336
10337 if (Ctrl == "row_mirror") {
10338 Val = DppCtrl::ROW_MIRROR;
10339 } else if (Ctrl == "row_half_mirror") {
10340 Val = DppCtrl::ROW_HALF_MIRROR;
10341 } else {
10342 if (skipToken(AsmToken::Colon, "expected a colon")) {
10343 if (Ctrl == "quad_perm") {
10344 Val = parseDPPCtrlPerm();
10345 } else {
10346 Val = parseDPPCtrlSel(Ctrl);
10347 }
10348 }
10349 }
10350
10351 if (Val == -1)
10352 return ParseStatus::Failure;
10353
10354 Operands.push_back(
10355 AMDGPUOperand::CreateImm(this, Val, S, AMDGPUOperand::ImmTyDppCtrl));
10356 return ParseStatus::Success;
10357}
10358
10359void AMDGPUAsmParser::cvtVOP3DPP(MCInst &Inst, const OperandVector &Operands,
10360 bool IsDPP8) {
10361 OptionalImmIndexMap OptionalIdx;
10362 unsigned Opc = Inst.getOpcode();
10363 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
10364
10365 // MAC instructions are special because they have 'old'
10366 // operand which is not tied to dst (but assumed to be).
10367 // They also have dummy unused src2_modifiers.
10368 int OldIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::old);
10369 int Src2ModIdx =
10370 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers);
10371 bool IsMAC = OldIdx != -1 && Src2ModIdx != -1 &&
10372 Desc.getOperandConstraint(OldIdx, MCOI::TIED_TO) == -1;
10373
10374 unsigned I = 1;
10375 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
10376 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
10377 }
10378
10379 int Fi = 0;
10380 int VdstInIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
10381 bool IsVOP3CvtSrDpp = Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_dpp8_gfx12 ||
10382 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_dpp8_gfx13 ||
10383 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_dpp8_gfx12 ||
10384 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_dpp8_gfx13 ||
10385 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_dpp_gfx12 ||
10386 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_dpp_gfx13 ||
10387 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_dpp_gfx12 ||
10388 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_dpp_gfx13;
10389
10390 for (unsigned E = Operands.size(); I != E; ++I) {
10391
10392 if (IsMAC) {
10393 int NumOperands = Inst.getNumOperands();
10394 if (OldIdx == NumOperands) {
10395 // Handle old operand
10396 constexpr int DST_IDX = 0;
10397 Inst.addOperand(Inst.getOperand(DST_IDX));
10398 } else if (Src2ModIdx == NumOperands) {
10399 // Add unused dummy src2_modifiers
10401 }
10402 }
10403
10404 if (VdstInIdx == static_cast<int>(Inst.getNumOperands())) {
10405 Inst.addOperand(Inst.getOperand(0));
10406 }
10407
10408 if (IsVOP3CvtSrDpp) {
10409 if (Src2ModIdx == static_cast<int>(Inst.getNumOperands())) {
10411 Inst.addOperand(MCOperand::createReg(MCRegister()));
10412 }
10413 }
10414
10415 auto TiedTo =
10416 Desc.getOperandConstraint(Inst.getNumOperands(), MCOI::TIED_TO);
10417 if (TiedTo != -1) {
10418 assert((unsigned)TiedTo < Inst.getNumOperands());
10419 // handle tied old or src2 for MAC instructions
10420 Inst.addOperand(Inst.getOperand(TiedTo));
10421 }
10422 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
10423 // Add the register arguments
10424 if (IsDPP8 && Op.isDppFI()) {
10425 Fi = Op.getImm();
10426 } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
10427 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
10428 } else if (Op.isReg()) {
10429 Op.addRegOperands(Inst, 1);
10430 } else if (Op.isImm() &&
10431 Desc.operands()[Inst.getNumOperands()].RegClass != -1) {
10432 Op.addImmOperands(Inst, 1);
10433 } else if (Op.isImm()) {
10434 OptionalIdx[Op.getImmTy()] = I;
10435 } else {
10436 llvm_unreachable("unhandled operand type");
10437 }
10438 }
10439
10440 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp) && !IsVOP3CvtSrDpp)
10441 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10442 AMDGPUOperand::ImmTyClamp);
10443
10444 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::byte_sel)) {
10445 if (VdstInIdx == static_cast<int>(Inst.getNumOperands()))
10446 Inst.addOperand(Inst.getOperand(0));
10447 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10448 AMDGPUOperand::ImmTyByteSel);
10449 }
10450
10451 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod))
10452 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10453 AMDGPUOperand::ImmTyOModSI);
10454
10456 cvtVOP3P(Inst, Operands, OptionalIdx);
10457 else if (SIInstrFlags::isVOP3(Desc))
10458 cvtVOP3OpSel(Inst, Operands, OptionalIdx);
10459 else if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) {
10460 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10461 AMDGPUOperand::ImmTyOpSel);
10462 }
10463
10464 if (IsDPP8) {
10465 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10466 AMDGPUOperand::ImmTyDPP8);
10467 using namespace llvm::AMDGPU::DPP;
10468 Inst.addOperand(MCOperand::createImm(Fi ? DPP8_FI_1 : DPP8_FI_0));
10469 } else {
10470 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10471 AMDGPUOperand::ImmTyDppCtrl, 0xe4);
10472 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10473 AMDGPUOperand::ImmTyDppRowMask, 0xf);
10474 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10475 AMDGPUOperand::ImmTyDppBankMask, 0xf);
10476 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10477 AMDGPUOperand::ImmTyDppBoundCtrl);
10478
10479 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::fi))
10480 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10481 AMDGPUOperand::ImmTyDppFI);
10482 }
10483}
10484
10485void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands,
10486 bool IsDPP8) {
10487 OptionalImmIndexMap OptionalIdx;
10488
10489 unsigned I = 1;
10490 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
10491 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
10492 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
10493 }
10494
10495 int Fi = 0;
10496 for (unsigned E = Operands.size(); I != E; ++I) {
10497 auto TiedTo =
10498 Desc.getOperandConstraint(Inst.getNumOperands(), MCOI::TIED_TO);
10499 if (TiedTo != -1) {
10500 assert((unsigned)TiedTo < Inst.getNumOperands());
10501 // handle tied old or src2 for MAC instructions
10502 Inst.addOperand(Inst.getOperand(TiedTo));
10503 }
10504 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
10505 // Add the register arguments
10506 if (Op.isReg() && validateVccOperand(Op.getReg())) {
10507 // VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token.
10508 // Skip it.
10509 continue;
10510 }
10511
10512 if (IsDPP8) {
10513 if (Op.isDPP8()) {
10514 Op.addImmOperands(Inst, 1);
10515 } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
10516 Op.addRegWithFPInputModsOperands(Inst, 2);
10517 } else if (Op.isDppFI()) {
10518 Fi = Op.getImm();
10519 } else if (Op.isReg()) {
10520 Op.addRegOperands(Inst, 1);
10521 } else {
10522 llvm_unreachable("Invalid operand type");
10523 }
10524 } else {
10526 Op.addRegWithFPInputModsOperands(Inst, 2);
10527 } else if (Op.isReg()) {
10528 Op.addRegOperands(Inst, 1);
10529 } else if (Op.isDPPCtrl()) {
10530 Op.addImmOperands(Inst, 1);
10531 } else if (Op.isImm()) {
10532 // Handle optional arguments
10533 OptionalIdx[Op.getImmTy()] = I;
10534 } else {
10535 llvm_unreachable("Invalid operand type");
10536 }
10537 }
10538 }
10539
10540 if (IsDPP8) {
10541 using namespace llvm::AMDGPU::DPP;
10542 Inst.addOperand(MCOperand::createImm(Fi ? DPP8_FI_1 : DPP8_FI_0));
10543 } else {
10544 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10545 AMDGPUOperand::ImmTyDppRowMask, 0xf);
10546 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10547 AMDGPUOperand::ImmTyDppBankMask, 0xf);
10548 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10549 AMDGPUOperand::ImmTyDppBoundCtrl);
10550 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::fi)) {
10551 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10552 AMDGPUOperand::ImmTyDppFI);
10553 }
10554 }
10555}
10556
10557//===----------------------------------------------------------------------===//
10558// sdwa
10559//===----------------------------------------------------------------------===//
10560
10561ParseStatus AMDGPUAsmParser::parseSDWASel(OperandVector &Operands,
10562 StringRef Prefix,
10563 AMDGPUOperand::ImmTy Type) {
10564 return parseStringOrIntWithPrefix(
10565 Operands, Prefix,
10566 {"BYTE_0", "BYTE_1", "BYTE_2", "BYTE_3", "WORD_0", "WORD_1", "DWORD"},
10567 Type);
10568}
10569
10570ParseStatus AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
10571 return parseStringOrIntWithPrefix(
10572 Operands, "dst_unused", {"UNUSED_PAD", "UNUSED_SEXT", "UNUSED_PRESERVE"},
10573 AMDGPUOperand::ImmTySDWADstUnused);
10574}
10575
10576void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
10577 cvtSDWA(Inst, Operands, SDWAInstType::VOP1);
10578}
10579
10580void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
10581 cvtSDWA(Inst, Operands, SDWAInstType::VOP2);
10582}
10583
10584void AMDGPUAsmParser::cvtSdwaVOP2b(MCInst &Inst,
10585 const OperandVector &Operands) {
10586 cvtSDWA(Inst, Operands, SDWAInstType::VOP2, true, true);
10587}
10588
10589void AMDGPUAsmParser::cvtSdwaVOP2e(MCInst &Inst,
10590 const OperandVector &Operands) {
10591 cvtSDWA(Inst, Operands, SDWAInstType::VOP2, false, true);
10592}
10593
10594void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
10595 cvtSDWA(Inst, Operands, SDWAInstType::VOPC, isVI());
10596}
10597
10598void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
10599 SDWAInstType BasicInstType, bool SkipDstVcc,
10600 bool SkipSrcVcc) {
10601 using namespace llvm::AMDGPU::SDWA;
10602
10603 OptionalImmIndexMap OptionalIdx;
10604 bool SkipVcc = SkipDstVcc || SkipSrcVcc;
10605 bool SkippedVcc = false;
10606
10607 unsigned I = 1;
10608 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
10609 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
10610 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
10611 }
10612
10613 for (unsigned E = Operands.size(); I != E; ++I) {
10614 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
10615 if (SkipVcc && !SkippedVcc && Op.isReg() &&
10616 (Op.getReg() == AMDGPU::VCC || Op.getReg() == AMDGPU::VCC_LO)) {
10617 // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst.
10618 // Skip it if it's 2nd (e.g. v_add_i32_sdwa v1, vcc, v2, v3)
10619 // or 4th (v_addc_u32_sdwa v1, vcc, v2, v3, vcc) operand.
10620 // Skip VCC only if we didn't skip it on previous iteration.
10621 // Note that src0 and src1 occupy 2 slots each because of modifiers.
10622 if (BasicInstType == SDWAInstType::VOP2 &&
10623 ((SkipDstVcc && Inst.getNumOperands() == 1) ||
10624 (SkipSrcVcc && Inst.getNumOperands() == 5))) {
10625 SkippedVcc = true;
10626 continue;
10627 }
10628 if (BasicInstType == SDWAInstType::VOPC && Inst.getNumOperands() == 0) {
10629 SkippedVcc = true;
10630 continue;
10631 }
10632 }
10634 Op.addRegOrImmWithInputModsOperands(Inst, 2);
10635 } else if (Op.isImm()) {
10636 // Handle optional arguments
10637 OptionalIdx[Op.getImmTy()] = I;
10638 } else {
10639 llvm_unreachable("Invalid operand type");
10640 }
10641 SkippedVcc = false;
10642 }
10643
10644 const unsigned Opc = Inst.getOpcode();
10645 if (Opc != AMDGPU::V_NOP_sdwa_gfx10 && Opc != AMDGPU::V_NOP_sdwa_gfx9 &&
10646 Opc != AMDGPU::V_NOP_sdwa_vi) {
10647 // v_nop_sdwa_sdwa_vi/gfx9 has no optional sdwa arguments
10648 switch (BasicInstType) {
10649 case SDWAInstType::VOP1:
10650 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp))
10651 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10652 AMDGPUOperand::ImmTyClamp, 0);
10653
10654 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod))
10655 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10656 AMDGPUOperand::ImmTyOModSI, 0);
10657
10658 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::dst_sel))
10659 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10660 AMDGPUOperand::ImmTySDWADstSel, SdwaSel::DWORD);
10661
10662 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::dst_unused))
10663 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10664 AMDGPUOperand::ImmTySDWADstUnused,
10665 DstUnused::UNUSED_PRESERVE);
10666
10667 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10668 AMDGPUOperand::ImmTySDWASrc0Sel, SdwaSel::DWORD);
10669 break;
10670
10671 case SDWAInstType::VOP2:
10672 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10673 AMDGPUOperand::ImmTyClamp, 0);
10674
10675 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::omod))
10676 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10677 AMDGPUOperand::ImmTyOModSI, 0);
10678
10679 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10680 AMDGPUOperand::ImmTySDWADstSel, SdwaSel::DWORD);
10681 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10682 AMDGPUOperand::ImmTySDWADstUnused,
10683 DstUnused::UNUSED_PRESERVE);
10684 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10685 AMDGPUOperand::ImmTySDWASrc0Sel, SdwaSel::DWORD);
10686 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10687 AMDGPUOperand::ImmTySDWASrc1Sel, SdwaSel::DWORD);
10688 break;
10689
10690 case SDWAInstType::VOPC:
10691 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::clamp))
10692 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10693 AMDGPUOperand::ImmTyClamp, 0);
10694 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10695 AMDGPUOperand::ImmTySDWASrc0Sel, SdwaSel::DWORD);
10696 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10697 AMDGPUOperand::ImmTySDWASrc1Sel, SdwaSel::DWORD);
10698 break;
10699 }
10700 }
10701
10702 // special case v_mac_{f16, f32}:
10703 // it has src2 register operand that is tied to dst operand
10704 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
10705 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
10706 auto *it = Inst.begin();
10707 std::advance(
10708 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
10709 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
10710 }
10711}
10712
10713/// Force static initialization.
10714extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
10720
10721#define GET_MATCHER_IMPLEMENTATION
10722#define GET_MNEMONIC_SPELL_CHECKER
10723#define GET_MNEMONIC_CHECKER
10724#include "AMDGPUGenAsmMatcher.inc"
10725
10726ParseStatus AMDGPUAsmParser::parseCustomOperand(OperandVector &Operands,
10727 unsigned MCK) {
10728 switch (MCK) {
10729 case MCK_addr64:
10730 return parseTokenOp("addr64", Operands);
10731 case MCK_done:
10732 return parseNamedBit("done", Operands, AMDGPUOperand::ImmTyDone, true);
10733 case MCK_idxen:
10734 return parseTokenOp("idxen", Operands);
10735 case MCK_lds:
10736 return parseNamedBit("lds", Operands, AMDGPUOperand::ImmTyLDS,
10737 /*IgnoreNegative=*/true);
10738 case MCK_offen:
10739 return parseTokenOp("offen", Operands);
10740 case MCK_off:
10741 return parseTokenOp("off", Operands);
10742 case MCK_row_95_en:
10743 return parseNamedBit("row_en", Operands, AMDGPUOperand::ImmTyRowEn, true);
10744 case MCK_gds:
10745 return parseNamedBit("gds", Operands, AMDGPUOperand::ImmTyGDS);
10746 case MCK_tfe:
10747 return parseNamedBit("tfe", Operands, AMDGPUOperand::ImmTyTFE);
10748 }
10749 return tryCustomParseOperand(Operands, MCK);
10750}
10751
10752// This function should be defined after auto-generated include so that we have
10753// MatchClassKind enum defined
10754unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
10755 unsigned Kind) {
10756 // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
10757 // But MatchInstructionImpl() expects to meet token and fails to validate
10758 // operand. This method checks if we are given immediate operand but expect to
10759 // get corresponding token.
10760 AMDGPUOperand &Operand = (AMDGPUOperand &)Op;
10761 switch (Kind) {
10762 case MCK_addr64:
10763 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
10764 case MCK_gds:
10765 return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
10766 case MCK_lds:
10767 return Operand.isLDS() ? Match_Success : Match_InvalidOperand;
10768 case MCK_idxen:
10769 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
10770 case MCK_offen:
10771 return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
10772 case MCK_tfe:
10773 return Operand.isTFE() ? Match_Success : Match_InvalidOperand;
10774 case MCK_done:
10775 return Operand.isDone() ? Match_Success : Match_InvalidOperand;
10776 case MCK_row_95_en:
10777 return Operand.isRowEn() ? Match_Success : Match_InvalidOperand;
10778 case MCK_SSrc_b32:
10779 // When operands have expression values, they will return true for isToken,
10780 // because it is not possible to distinguish between a token and an
10781 // expression at parse time. MatchInstructionImpl() will always try to
10782 // match an operand as a token, when isToken returns true, and when the
10783 // name of the expression is not a valid token, the match will fail,
10784 // so we need to handle it here.
10785 return Operand.isSSrc_b32() ? Match_Success : Match_InvalidOperand;
10786 case MCK_SSrc_f32:
10787 return Operand.isSSrc_f32() ? Match_Success : Match_InvalidOperand;
10788 case MCK_SOPPBrTarget:
10789 return Operand.isSOPPBrTarget() ? Match_Success : Match_InvalidOperand;
10790 case MCK_VReg32OrOff:
10791 return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand;
10792 case MCK_InterpSlot:
10793 return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand;
10794 case MCK_InterpAttr:
10795 return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
10796 case MCK_InterpAttrChan:
10797 return Operand.isInterpAttrChan() ? Match_Success : Match_InvalidOperand;
10798 case MCK_SReg_64:
10799 case MCK_SReg_64_XEXEC:
10800 // Null is defined as a 32-bit register but
10801 // it should also be enabled with 64-bit operands or larger.
10802 // The following code enables it for SReg_64 and larger operands
10803 // used as source and destination. Remaining source
10804 // operands are handled in isInlinableImm.
10805 case MCK_SReg_96:
10806 case MCK_SReg_128:
10807 case MCK_SReg_256:
10808 case MCK_SReg_512:
10809 return Operand.isNull() ? Match_Success : Match_InvalidOperand;
10810 default:
10811 return Match_InvalidOperand;
10812 }
10813}
10814
10815//===----------------------------------------------------------------------===//
10816// endpgm
10817//===----------------------------------------------------------------------===//
10818
10819ParseStatus AMDGPUAsmParser::parseEndpgm(OperandVector &Operands) {
10820 SMLoc S = getLoc();
10821 int64_t Imm = 0;
10822
10823 if (!parseExpr(Imm)) {
10824 // The operand is optional, if not present default to 0
10825 Imm = 0;
10826 }
10827
10828 if (!isUInt<16>(Imm))
10829 return Error(S, "expected a 16-bit value");
10830
10831 Operands.push_back(
10832 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyEndpgm));
10833 return ParseStatus::Success;
10834}
10835
10836bool AMDGPUOperand::isEndpgm() const { return isImmTy(ImmTyEndpgm); }
10837
10838//===----------------------------------------------------------------------===//
10839// Split Barrier
10840//===----------------------------------------------------------------------===//
10841
10842bool AMDGPUOperand::isSplitBarrier() const { return isInlinableImm(MVT::i32); }
#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)
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< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_READNONE
Definition Compiler.h:317
#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)
MachineInstr unsigned OpIdx
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")))
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
TargetIDSetting getSramEccSetting() const
static const fltSemantics & IEEEsingle()
Definition APFloat.h:297
static const fltSemantics & BFloat()
Definition APFloat.h:296
static const fltSemantics & IEEEdouble()
Definition APFloat.h:298
static constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:345
static const fltSemantics & IEEEhalf()
Definition APFloat.h:295
opStatus
IEEE-754R 7: Default exception handling.
Definition APFloat.h:361
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Definition APFloat.cpp:5920
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
iterator end() const
Definition ArrayRef.h:130
size_t size() const
Get the array size.
Definition ArrayRef.h:141
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)
iterator insert(iterator I, T &&Elt)
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)
static constexpr CustomOperand Operands[]
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 isPackedFP32Inst(unsigned Opc)
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.
GPUKind
GPU kinds supported by the AMDGPU target.
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 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)
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?
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:439
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
Definition SIDefines.h:457
@ OPERAND_REG_IMM_INT64
Definition SIDefines.h:425
@ OPERAND_REG_IMM_V2FP16
Definition SIDefines.h:432
@ OPERAND_REG_INLINE_C_FP64
Definition SIDefines.h:448
@ OPERAND_REG_INLINE_C_BF16
Definition SIDefines.h:445
@ OPERAND_REG_INLINE_C_V2BF16
Definition SIDefines.h:450
@ OPERAND_REG_IMM_V2INT64
Definition SIDefines.h:435
@ OPERAND_REG_IMM_V2INT16
Definition SIDefines.h:434
@ OPERAND_REG_IMM_BF16
Definition SIDefines.h:429
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
Definition SIDefines.h:424
@ OPERAND_REG_IMM_V2BF16
Definition SIDefines.h:431
@ OPERAND_REG_IMM_FP16
Definition SIDefines.h:430
@ OPERAND_REG_IMM_V2FP16_SPLAT
Definition SIDefines.h:433
@ OPERAND_REG_INLINE_C_INT64
Definition SIDefines.h:444
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
Definition SIDefines.h:442
@ OPERAND_REG_IMM_NOINLINE_V2FP16
Definition SIDefines.h:436
@ OPERAND_REG_IMM_FP64
Definition SIDefines.h:428
@ OPERAND_REG_INLINE_C_V2FP16
Definition SIDefines.h:451
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
Definition SIDefines.h:462
@ OPERAND_REG_INLINE_AC_FP32
Definition SIDefines.h:463
@ OPERAND_REG_IMM_V2INT32
Definition SIDefines.h:437
@ OPERAND_REG_IMM_FP32
Definition SIDefines.h:427
@ OPERAND_REG_INLINE_C_FP32
Definition SIDefines.h:447
@ OPERAND_REG_INLINE_C_INT32
Definition SIDefines.h:443
@ OPERAND_REG_INLINE_C_V2INT16
Definition SIDefines.h:449
@ OPERAND_REG_IMM_V2FP32
Definition SIDefines.h:438
@ OPERAND_REG_INLINE_AC_FP64
Definition SIDefines.h:464
@ OPERAND_REG_INLINE_C_FP16
Definition SIDefines.h:446
@ OPERAND_REG_IMM_INT16
Definition SIDefines.h:426
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
Definition SIDefines.h:454
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)
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ STT_AMDGPU_HSA_KERNEL
Definition ELF.h:1438
@ 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:360
constexpr bool isVOPC(const T &...O)
Definition SIDefines.h:231
constexpr bool isVOP3(const T &...O)
Definition SIDefines.h:234
constexpr bool isVOP1(const T &...O)
Definition SIDefines.h:225
constexpr bool usesTENSOR_CNT(const T &...O)
Definition SIDefines.h:303
constexpr bool isMAI(const T &...O)
Definition SIDefines.h:348
constexpr bool isVOP2(const T &...O)
Definition SIDefines.h:228
constexpr bool isSWMMAC(const T &...O)
Definition SIDefines.h:375
constexpr bool isSOP2(const T &...O)
Definition SIDefines.h:213
constexpr bool isFLAT(const T &...O)
Definition SIDefines.h:279
constexpr bool isVOP3P(const T &...O)
Definition SIDefines.h:237
constexpr bool isBuffer(const T &...O)
Definition SIDefines.h:261
constexpr bool hasIntClamp(const T &...O)
Definition SIDefines.h:324
constexpr bool isAtomicNoRet(const T &...O)
Definition SIDefines.h:357
constexpr bool isSMRD(const T &...O)
Definition SIDefines.h:264
constexpr bool isVOP3Like(const T &...O)
Definition SIDefines.h:240
constexpr bool isMIMG(const T &...O)
Definition SIDefines.h:267
constexpr bool isVMEM(const T &...O)
Definition SIDefines.h:400
constexpr bool isImage(const T &...O)
Definition SIDefines.h:396
constexpr bool isWMMA(const T &...O)
Definition SIDefines.h:363
constexpr bool isVOPD3(const T &...O)
Definition SIDefines.h:378
constexpr bool isGWS(const T &...O)
Definition SIDefines.h:372
constexpr bool isMUBUF(const T &...O)
Definition SIDefines.h:255
constexpr bool isSDWA(const T &...O)
Definition SIDefines.h:246
constexpr bool isSOPC(const T &...O)
Definition SIDefines.h:216
constexpr bool isDOT(const T &...O)
Definition SIDefines.h:351
constexpr bool isVSAMPLE(const T &...O)
Definition SIDefines.h:273
constexpr bool isDS(const T &...O)
Definition SIDefines.h:282
constexpr bool isAtomic(const T &...O)
Definition SIDefines.h:389
constexpr bool isGather4(const T &...O)
Definition SIDefines.h:300
constexpr bool isPacked(const T &...O)
Definition SIDefines.h:333
constexpr bool isDPP(const T &...O)
Definition SIDefines.h:249
constexpr bool isSegmentSpecificFLAT(const T &...O)
Definition SIDefines.h:392
@ 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:395
@ 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,...