LLVM 24.0.0git
AMDGPUAsmParser.cpp
Go to the documentation of this file.
1//===- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "AMDKernelCodeT.h"
16#include "SIDefines.h"
17#include "SIInstrInfo.h"
22#include "llvm/ADT/APFloat.h"
24#include "llvm/ADT/StringSet.h"
25#include "llvm/ADT/Twine.h"
28#include "llvm/MC/MCAsmInfo.h"
29#include "llvm/MC/MCContext.h"
30#include "llvm/MC/MCExpr.h"
31#include "llvm/MC/MCInst.h"
32#include "llvm/MC/MCInstrDesc.h"
38#include "llvm/MC/MCSymbol.h"
47#include <optional>
48
49using namespace llvm;
50using namespace llvm::AMDGPU;
51using namespace llvm::amdhsa;
52
53namespace {
54
55class AMDGPUAsmParser;
56
57enum RegisterKind {
58 IS_UNKNOWN,
59 IS_VGPR,
60 IS_SGPR,
61 IS_AGPR,
62 IS_TTMP,
63 IS_SPECIAL
64};
65
66//===----------------------------------------------------------------------===//
67// Operand
68//===----------------------------------------------------------------------===//
69
70class AMDGPUOperand : public MCParsedAsmOperand {
71 enum KindTy { Token, Immediate, Register, Expression } Kind;
72
73 SMLoc StartLoc, EndLoc;
74 const AMDGPUAsmParser *AsmParser;
75
76public:
77 AMDGPUOperand(KindTy Kind_, const AMDGPUAsmParser *AsmParser_)
78 : Kind(Kind_), AsmParser(AsmParser_) {}
79
80 using Ptr = std::unique_ptr<AMDGPUOperand>;
81
82 struct Modifiers {
83 bool Abs = false;
84 bool Neg = false;
85 bool Sext = false;
86 LitModifier Lit = LitModifier::None;
87
88 bool hasFPModifiers() const { return Abs || Neg; }
89 bool hasIntModifiers() const { return Sext; }
90 bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); }
91 bool isForcedLit() const { return Lit == LitModifier::Lit; }
92 bool isForcedLit64() const { return Lit == LitModifier::Lit64; }
93
94 int64_t getFPModifiersOperand() const {
95 int64_t Operand = 0;
96 Operand |= Abs ? SISrcMods::ABS : 0u;
97 Operand |= Neg ? SISrcMods::NEG : 0u;
98 return Operand;
99 }
100
101 int64_t getIntModifiersOperand() const {
102 int64_t Operand = 0;
103 Operand |= Sext ? SISrcMods::SEXT : 0u;
104 return Operand;
105 }
106
107 int64_t getModifiersOperand() const {
108 assert(!(hasFPModifiers() && hasIntModifiers()) &&
109 "fp and int modifiers should not be used simultaneously");
110 if (hasFPModifiers())
111 return getFPModifiersOperand();
112 if (hasIntModifiers())
113 return getIntModifiersOperand();
114 return 0;
115 }
116
117 friend raw_ostream &operator<<(raw_ostream &OS,
118 AMDGPUOperand::Modifiers Mods);
119 };
120
121 enum ImmTy {
122 ImmTyNone,
123 ImmTyGDS,
124 ImmTyLDS,
125 ImmTyOffen,
126 ImmTyIdxen,
127 ImmTyAddr64,
128 ImmTyOffset,
129 ImmTyInstOffset,
130 ImmTyOffset0,
131 ImmTyOffset1,
132 ImmTySMEMOffsetMod,
133 ImmTyCPol,
134 ImmTyTFE,
135 ImmTyIsAsync,
136 ImmTyD16,
137 ImmTyClamp,
138 ImmTyOModSI,
139 ImmTySDWADstSel,
140 ImmTySDWASrc0Sel,
141 ImmTySDWASrc1Sel,
142 ImmTySDWADstUnused,
143 ImmTyDMask,
144 ImmTyDim,
145 ImmTyUNorm,
146 ImmTyDA,
147 ImmTyR128A16,
148 ImmTyA16,
149 ImmTyLWE,
150 ImmTyExpTgt,
151 ImmTyExpCompr,
152 ImmTyExpVM,
153 ImmTyDone,
154 ImmTyRowEn,
155 ImmTyFORMAT,
156 ImmTyHwreg,
157 ImmTyOff,
158 ImmTySendMsg,
159 ImmTyWaitEvent,
160 ImmTyInterpSlot,
161 ImmTyInterpAttr,
162 ImmTyInterpAttrChan,
163 ImmTyOpSel,
164 ImmTyOpSelHi,
165 ImmTyNegLo,
166 ImmTyNegHi,
167 ImmTyIndexKey8bit,
168 ImmTyIndexKey16bit,
169 ImmTyIndexKey32bit,
170 ImmTyDPP8,
171 ImmTyDppCtrl,
172 ImmTyDppRowMask,
173 ImmTyDppBankMask,
174 ImmTyDppBoundCtrl,
175 ImmTyDppFI,
176 ImmTySwizzle,
177 ImmTyGprIdxMode,
178 ImmTyHigh,
179 ImmTyBLGP,
180 ImmTyCBSZ,
181 ImmTyABID,
182 ImmTyEndpgm,
183 ImmTyWaitVDST,
184 ImmTyWaitEXP,
185 ImmTyWaitVAVDst,
186 ImmTyWaitVMVSrc,
187 ImmTyBitOp3,
188 ImmTyMatrixAFMT,
189 ImmTyMatrixBFMT,
190 ImmTyMatrixAScale,
191 ImmTyMatrixBScale,
192 ImmTyMatrixAScaleFmt,
193 ImmTyMatrixBScaleFmt,
194 ImmTyMatrixAReuse,
195 ImmTyMatrixBReuse,
196 ImmTyScaleSel,
197 ImmTyByteSel,
198 };
199
200private:
201 struct TokOp {
202 const char *Data;
203 unsigned Length;
204 };
205
206 struct ImmOp {
207 int64_t Val;
208 ImmTy Type;
209 bool IsFPImm;
210 Modifiers Mods;
211 };
212
213 struct RegOp {
214 MCRegister RegNo;
215 Modifiers Mods;
216 };
217
218 union {
219 TokOp Tok;
220 ImmOp Imm;
221 RegOp Reg;
222 const MCExpr *Expr;
223 };
224
225 // The index of the associated MCInst operand.
226 mutable int MCOpIdx = -1;
227
228public:
229 bool isToken() const override { return Kind == Token; }
230
231 bool isSymbolRefExpr() const {
232 return isExpr() && Expr && isa<MCSymbolRefExpr>(Expr);
233 }
234
235 bool isImm() const override { return Kind == Immediate; }
236
237 bool isInlinableImm(MVT type) const;
238 bool isLiteralImm(MVT type) const;
239
240 bool isRegKind() const { return Kind == Register; }
241
242 bool isReg() const override { return isRegKind() && !hasModifiers(); }
243
244 bool isRegOrInline(unsigned RCID, MVT type) const {
245 return isRegClass(RCID) || isInlinableImm(type);
246 }
247
248 bool isRegOrImmWithInputMods(unsigned RCID, MVT type) const {
249 return isRegOrInline(RCID, type) || isLiteralImm(type);
250 }
251
252 bool isRegOrImmWithInt16InputMods() const {
253 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::i16);
254 }
255
256 template <bool IsFake16> bool isRegOrImmWithIntT16InputMods() const {
258 IsFake16 ? AMDGPU::VS_32RegClassID : AMDGPU::VS_16RegClassID, MVT::i16);
259 }
260
261 bool isRegOrImmWithInt32InputMods() const {
262 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::i32);
263 }
264
265 bool isRegOrInlineImmWithInt16InputMods() const {
266 return isRegOrInline(AMDGPU::VS_32RegClassID, MVT::i16);
267 }
268
269 template <bool IsFake16> bool isRegOrInlineImmWithIntT16InputMods() const {
270 return isRegOrInline(
271 IsFake16 ? AMDGPU::VS_32RegClassID : AMDGPU::VS_16RegClassID, MVT::i16);
272 }
273
274 bool isRegOrInlineImmWithInt32InputMods() const {
275 return isRegOrInline(AMDGPU::VS_32RegClassID, MVT::i32);
276 }
277
278 bool isRegOrImmWithInt64InputMods() const {
279 return isRegOrImmWithInputMods(AMDGPU::VS_64RegClassID, MVT::i64);
280 }
281
282 bool isRegOrImmWithFP16InputMods() const {
283 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::f16);
284 }
285
286 template <bool IsFake16> bool isRegOrImmWithFPT16InputMods() const {
288 IsFake16 ? AMDGPU::VS_32RegClassID : AMDGPU::VS_16RegClassID, MVT::f16);
289 }
290
291 bool isRegOrImmWithFP32InputMods() const {
292 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::f32);
293 }
294
295 bool isRegOrImmWithFP64InputMods() const {
296 return isRegOrImmWithInputMods(AMDGPU::VS_64RegClassID, MVT::f64);
297 }
298
299 template <bool IsFake16> bool isRegOrInlineImmWithFP16InputMods() const {
300 return isRegOrInline(
301 IsFake16 ? AMDGPU::VS_32RegClassID : AMDGPU::VS_16RegClassID, MVT::f16);
302 }
303
304 bool isRegOrInlineImmWithFP32InputMods() const {
305 return isRegOrInline(AMDGPU::VS_32RegClassID, MVT::f32);
306 }
307
308 bool isRegOrInlineImmWithFP64InputMods() const {
309 return isRegOrInline(AMDGPU::VS_64RegClassID, MVT::f64);
310 }
311
312 bool isVRegWithInputMods(unsigned RCID) const { return isRegClass(RCID); }
313
314 bool isVRegWithFP32InputMods() const {
315 return isVRegWithInputMods(AMDGPU::VGPR_32RegClassID);
316 }
317
318 bool isVRegWithFP64InputMods() const {
319 return isVRegWithInputMods(AMDGPU::VReg_64RegClassID);
320 }
321
322 bool isPackedFP16InputMods() const {
323 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::v2f16);
324 }
325
326 bool isPackedVGPRFP32InputMods() const {
327 return isRegOrImmWithInputMods(AMDGPU::VReg_64RegClassID, MVT::v2f32);
328 }
329
330 bool isVReg() const {
331 return isRegClass(AMDGPU::VGPR_32RegClassID) ||
332 isRegClass(AMDGPU::VReg_64RegClassID) ||
333 isRegClass(AMDGPU::VReg_96RegClassID) ||
334 isRegClass(AMDGPU::VReg_128RegClassID) ||
335 isRegClass(AMDGPU::VReg_160RegClassID) ||
336 isRegClass(AMDGPU::VReg_192RegClassID) ||
337 isRegClass(AMDGPU::VReg_256RegClassID) ||
338 isRegClass(AMDGPU::VReg_512RegClassID) ||
339 isRegClass(AMDGPU::VReg_1024RegClassID);
340 }
341
342 bool isVReg32() const { return isRegClass(AMDGPU::VGPR_32RegClassID); }
343
344 bool isVReg32OrOff() const { return isOff() || isVReg32(); }
345
346 bool isNull() const { return isRegKind() && getReg() == AMDGPU::SGPR_NULL; }
347
348 bool isAV_LdSt_32_Align2_RegOp() const {
349 return isRegClass(AMDGPU::VGPR_32RegClassID) ||
350 isRegClass(AMDGPU::AGPR_32RegClassID);
351 }
352
353 bool isVRegWithInputMods() const;
354 template <bool IsFake16> bool isT16_Lo128VRegWithInputMods() const;
355 template <bool IsFake16> bool isT16VRegWithInputMods() const;
356
357 bool isSDWAOperand(MVT type) const;
358 bool isSDWAFP16Operand() const;
359 bool isSDWAFP32Operand() const;
360 bool isSDWAInt16Operand() const;
361 bool isSDWAInt32Operand() const;
362
363 bool isImmTy(ImmTy ImmT) const { return isImm() && Imm.Type == ImmT; }
364
365 template <ImmTy Ty> bool isImmTy() const { return isImmTy(Ty); }
366
367 bool isImmLiteral() const { return isImmTy(ImmTyNone); }
368
369 bool isImmModifier() const { return isImm() && Imm.Type != ImmTyNone; }
370
371 bool isOModSI() const { return isImmTy(ImmTyOModSI); }
372 bool isDim() const { return isImmTy(ImmTyDim); }
373 bool isR128A16() const { return isImmTy(ImmTyR128A16); }
374 bool isOff() const { return isImmTy(ImmTyOff); }
375 bool isExpTgt() const { return isImmTy(ImmTyExpTgt); }
376 bool isOffen() const { return isImmTy(ImmTyOffen); }
377 bool isIdxen() const { return isImmTy(ImmTyIdxen); }
378 bool isAddr64() const { return isImmTy(ImmTyAddr64); }
379 bool isSMEMOffsetMod() const { return isImmTy(ImmTySMEMOffsetMod); }
380 bool isFlatOffset() const {
381 return isImmTy(ImmTyOffset) || isImmTy(ImmTyInstOffset);
382 }
383 bool isGDS() const { return isImmTy(ImmTyGDS); }
384 bool isLDS() const { return isImmTy(ImmTyLDS); }
385 bool isCPol() const { return isImmTy(ImmTyCPol); }
386 bool isIndexKey8bit() const { return isImmTy(ImmTyIndexKey8bit); }
387 bool isIndexKey16bit() const { return isImmTy(ImmTyIndexKey16bit); }
388 bool isIndexKey32bit() const { return isImmTy(ImmTyIndexKey32bit); }
389 bool isMatrixAFMT() const { return isImmTy(ImmTyMatrixAFMT); }
390 bool isMatrixBFMT() const { return isImmTy(ImmTyMatrixBFMT); }
391 bool isMatrixAScale() const { return isImmTy(ImmTyMatrixAScale); }
392 bool isMatrixBScale() const { return isImmTy(ImmTyMatrixBScale); }
393 bool isMatrixAScaleFmt() const { return isImmTy(ImmTyMatrixAScaleFmt); }
394 bool isMatrixBScaleFmt() const { return isImmTy(ImmTyMatrixBScaleFmt); }
395 bool isMatrixAReuse() const { return isImmTy(ImmTyMatrixAReuse); }
396 bool isMatrixBReuse() const { return isImmTy(ImmTyMatrixBReuse); }
397 bool isTFE() const { return isImmTy(ImmTyTFE); }
398 bool isFORMAT() const { return isImmTy(ImmTyFORMAT) && isUInt<7>(getImm()); }
399 bool isDppFI() const { return isImmTy(ImmTyDppFI); }
400 bool isSDWADstSel() const { return isImmTy(ImmTySDWADstSel); }
401 bool isSDWASrc0Sel() const { return isImmTy(ImmTySDWASrc0Sel); }
402 bool isSDWASrc1Sel() const { return isImmTy(ImmTySDWASrc1Sel); }
403 bool isSDWADstUnused() const { return isImmTy(ImmTySDWADstUnused); }
404 bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); }
405 bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); }
406 bool isInterpAttrChan() const { return isImmTy(ImmTyInterpAttrChan); }
407 bool isOpSel() const { return isImmTy(ImmTyOpSel); }
408 bool isOpSelHi() const { return isImmTy(ImmTyOpSelHi); }
409 bool isNegLo() const { return isImmTy(ImmTyNegLo); }
410 bool isNegHi() const { return isImmTy(ImmTyNegHi); }
411 bool isBitOp3() const { return isImmTy(ImmTyBitOp3) && isUInt<8>(getImm()); }
412 bool isDone() const { return isImmTy(ImmTyDone); }
413 bool isRowEn() const { return isImmTy(ImmTyRowEn); }
414
415 bool isRegOrImm() const { return isReg() || isImm(); }
416
417 bool isRegClass(unsigned RCID) const;
418
419 bool isInlineValue() const;
420
421 bool isRegOrInlineNoMods(unsigned RCID, MVT type) const {
422 return isRegOrInline(RCID, type) && !hasModifiers();
423 }
424
425 bool isSCSrcB16() const {
426 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i16);
427 }
428
429 bool isSCSrcV2B16() const { return isSCSrcB16(); }
430
431 bool isSCSrc_b32() const {
432 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i32);
433 }
434
435 bool isSCSrc_b64() const {
436 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::i64);
437 }
438
439 bool isBoolReg() const;
440
441 bool isSCSrcF16() const {
442 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f16);
443 }
444
445 bool isSCSrcV2F16() const { return isSCSrcF16(); }
446
447 bool isSCSrcF32() const {
448 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f32);
449 }
450
451 bool isSCSrcF64() const {
452 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::f64);
453 }
454
455 bool isSSrc_b32() const {
456 return isSCSrc_b32() || isLiteralImm(MVT::i32) || isExpr();
457 }
458
459 bool isSSrc_b16() const { return isSCSrcB16() || isLiteralImm(MVT::i16); }
460
461 bool isSSrcV2B16() const {
462 llvm_unreachable("cannot happen");
463 return isSSrc_b16();
464 }
465
466 bool isSSrc_b64() const {
467 // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits.
468 // See isVSrc64().
469 return isSCSrc_b64() || isLiteralImm(MVT::i64) ||
470 (((const MCTargetAsmParser *)AsmParser)
471 ->getAvailableFeatures()[AMDGPU::Feature64BitLiterals] &&
472 isExpr());
473 }
474
475 bool isSSrc_f32() const {
476 return isSCSrc_b32() || isLiteralImm(MVT::f32) || isExpr();
477 }
478
479 bool isSSrcF64() const { return isSCSrc_b64() || isLiteralImm(MVT::f64); }
480
481 bool isSSrc_bf16() const { return isSCSrcB16() || isLiteralImm(MVT::bf16); }
482
483 bool isSSrc_f16() const { return isSCSrcB16() || isLiteralImm(MVT::f16); }
484
485 bool isSSrcV2F16() const {
486 llvm_unreachable("cannot happen");
487 return isSSrc_f16();
488 }
489
490 bool isSSrcV2FP32() const {
491 llvm_unreachable("cannot happen");
492 return isSSrc_f32();
493 }
494
495 bool isSCSrcV2FP32() const {
496 llvm_unreachable("cannot happen");
497 return isSCSrcF32();
498 }
499
500 bool isSSrcV2INT32() const {
501 llvm_unreachable("cannot happen");
502 return isSSrc_b32();
503 }
504
505 bool isSCSrcV2INT32() const {
506 llvm_unreachable("cannot happen");
507 return isSCSrc_b32();
508 }
509
510 bool isSSrcOrLds_b32() const {
511 return isRegOrInlineNoMods(AMDGPU::SRegOrLds_32RegClassID, MVT::i32) ||
512 isLiteralImm(MVT::i32) || isExpr();
513 }
514
515 bool isVCSrc_b32() const {
516 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i32);
517 }
518
519 bool isVCSrc_b32_Lo256() const {
520 return isRegOrInlineNoMods(AMDGPU::VS_32_Lo256RegClassID, MVT::i32);
521 }
522
523 bool isVCSrc_b64_Lo256() const {
524 return isRegOrInlineNoMods(AMDGPU::VS_64_Lo256RegClassID, MVT::i64);
525 }
526
527 bool isVCSrc_b64() const {
528 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::i64);
529 }
530
531 bool isVCSrcT_b16() const {
532 return isRegOrInlineNoMods(AMDGPU::VS_16RegClassID, MVT::i16);
533 }
534
535 bool isVCSrcTB16_Lo128() const {
536 return isRegOrInlineNoMods(AMDGPU::VS_16_Lo128RegClassID, MVT::i16);
537 }
538
539 bool isVCSrcFake16B16_Lo128() const {
540 return isRegOrInlineNoMods(AMDGPU::VS_32_Lo128RegClassID, MVT::i16);
541 }
542
543 bool isVCSrc_b16() const {
544 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i16);
545 }
546
547 bool isVCSrc_v2b16() const { return isVCSrc_b16(); }
548
549 bool isVCSrc_f32() const {
550 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f32);
551 }
552
553 bool isVCSrc_f64() const {
554 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::f64);
555 }
556
557 bool isVCSrcTBF16() const {
558 return isRegOrInlineNoMods(AMDGPU::VS_16RegClassID, MVT::bf16);
559 }
560
561 bool isVCSrcT_f16() const {
562 return isRegOrInlineNoMods(AMDGPU::VS_16RegClassID, MVT::f16);
563 }
564
565 bool isVCSrcT_bf16() const {
566 return isRegOrInlineNoMods(AMDGPU::VS_16RegClassID, MVT::f16);
567 }
568
569 bool isVCSrcTBF16_Lo128() const {
570 return isRegOrInlineNoMods(AMDGPU::VS_16_Lo128RegClassID, MVT::bf16);
571 }
572
573 bool isVCSrcTF16_Lo128() const {
574 return isRegOrInlineNoMods(AMDGPU::VS_16_Lo128RegClassID, MVT::f16);
575 }
576
577 bool isVCSrcFake16BF16_Lo128() const {
578 return isRegOrInlineNoMods(AMDGPU::VS_32_Lo128RegClassID, MVT::bf16);
579 }
580
581 bool isVCSrcFake16F16_Lo128() const {
582 return isRegOrInlineNoMods(AMDGPU::VS_32_Lo128RegClassID, MVT::f16);
583 }
584
585 bool isVCSrc_bf16() const {
586 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::bf16);
587 }
588
589 bool isVCSrc_f16() const {
590 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f16);
591 }
592
593 bool isVCSrc_v2bf16() const { return isVCSrc_bf16(); }
594
595 bool isVCSrc_v2f16() const { return isVCSrc_f16(); }
596
597 bool isVSrc_b32() const {
598 return isVCSrc_f32() || isLiteralImm(MVT::i32) || isExpr();
599 }
600
601 bool isVSrc_b64() const { return isVCSrc_f64() || isLiteralImm(MVT::i64); }
602
603 bool isVSrc_v2b64() const {
604 return isRegOrInlineNoMods(AMDGPU::VS_128RegClassID, MVT::i64) ||
605 isLiteralImm(MVT::i64);
606 }
607
608 bool isVSrc_v2f64() const {
609 return isRegOrInlineNoMods(AMDGPU::VS_128RegClassID, MVT::f64) ||
610 isLiteralImm(MVT::f64);
611 }
612
613 bool isVSrcT_b16() const { return isVCSrcT_b16() || isLiteralImm(MVT::i16); }
614
615 bool isVSrcT_b16_Lo128() const {
616 return isVCSrcTB16_Lo128() || isLiteralImm(MVT::i16);
617 }
618
619 bool isVSrcFake16_b16_Lo128() const {
620 return isVCSrcFake16B16_Lo128() || isLiteralImm(MVT::i16);
621 }
622
623 bool isVSrc_b16() const { return isVCSrc_b16() || isLiteralImm(MVT::i16); }
624
625 bool isVSrc_v2b16() const { return isVSrc_b16() || isLiteralImm(MVT::v2i16); }
626
627 bool isVCSrcV2FP32() const { return isVCSrc_f64(); }
628
629 bool isVSrc_v2f32() const { return isVSrc_f64() || isLiteralImm(MVT::v2f32); }
630
631 bool isVCSrc_v2b32() const { return isVCSrc_b64(); }
632
633 bool isVSrc_v2b32() const { return isVSrc_b64() || isLiteralImm(MVT::v2i32); }
634
635 bool isVSrc_f32() const {
636 return isVCSrc_f32() || isLiteralImm(MVT::f32) || isExpr();
637 }
638
639 bool isVSrc_f64() const { return isVCSrc_f64() || isLiteralImm(MVT::f64); }
640
641 bool isVSrcT_bf16() const {
642 return isVCSrcTBF16() || isLiteralImm(MVT::bf16);
643 }
644
645 bool isVSrcT_f16() const { return isVCSrcT_f16() || isLiteralImm(MVT::f16); }
646
647 bool isVSrcT_bf16_Lo128() const {
648 return isVCSrcTBF16_Lo128() || isLiteralImm(MVT::bf16);
649 }
650
651 bool isVSrcT_f16_Lo128() const {
652 return isVCSrcTF16_Lo128() || isLiteralImm(MVT::f16);
653 }
654
655 bool isVSrcFake16_bf16_Lo128() const {
656 return isVCSrcFake16BF16_Lo128() || isLiteralImm(MVT::bf16);
657 }
658
659 bool isVSrcFake16_f16_Lo128() const {
660 return isVCSrcFake16F16_Lo128() || isLiteralImm(MVT::f16);
661 }
662
663 bool isVSrc_bf16() const { return isVCSrc_bf16() || isLiteralImm(MVT::bf16); }
664
665 bool isVSrc_f16() const { return isVCSrc_f16() || isLiteralImm(MVT::f16); }
666
667 bool isVSrc_v2bf16() const {
668 return isVSrc_bf16() || isLiteralImm(MVT::v2bf16);
669 }
670
671 bool isVSrc_v2f16() const { return isVSrc_f16() || isLiteralImm(MVT::v2f16); }
672
673 bool isVSrc_v2f16_splat() const { return isVSrc_v2f16(); }
674
675 bool isVSrc_NoInline_v2f16() const { return isVSrc_v2f16(); }
676
677 bool isVISrcB32() const {
678 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::i32);
679 }
680
681 bool isVISrcB16() const {
682 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::i16);
683 }
684
685 bool isVISrcV2B16() const { return isVISrcB16(); }
686
687 bool isVISrcF32() const {
688 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::f32);
689 }
690
691 bool isVISrcF16() const {
692 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::f16);
693 }
694
695 bool isVISrcV2F16() const { return isVISrcF16() || isVISrcB32(); }
696
697 bool isVISrc_64_bf16() const {
698 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::bf16);
699 }
700
701 bool isVISrc_64_f16() const {
702 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::f16);
703 }
704
705 bool isVISrc_64_b32() const {
706 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::i32);
707 }
708
709 bool isVISrc_64B64() const {
710 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::i64);
711 }
712
713 bool isVISrc_64_f64() const {
714 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::f64);
715 }
716
717 bool isVISrc_64V2FP32() const {
718 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::f32);
719 }
720
721 bool isVISrc_64V2INT32() const {
722 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::i32);
723 }
724
725 bool isVISrc_256_b32() const {
726 return isRegOrInlineNoMods(AMDGPU::VReg_256RegClassID, MVT::i32);
727 }
728
729 bool isVISrc_256_f32() const {
730 return isRegOrInlineNoMods(AMDGPU::VReg_256RegClassID, MVT::f32);
731 }
732
733 bool isVISrc_256B64() const {
734 return isRegOrInlineNoMods(AMDGPU::VReg_256RegClassID, MVT::i64);
735 }
736
737 bool isVISrc_256_f64() const {
738 return isRegOrInlineNoMods(AMDGPU::VReg_256RegClassID, MVT::f64);
739 }
740
741 bool isVISrc_512_f64() const {
742 return isRegOrInlineNoMods(AMDGPU::VReg_512RegClassID, MVT::f64);
743 }
744
745 bool isVISrc_128B16() const {
746 return isRegOrInlineNoMods(AMDGPU::VReg_128RegClassID, MVT::i16);
747 }
748
749 bool isVISrc_128V2B16() const { return isVISrc_128B16(); }
750
751 bool isVISrc_128_b32() const {
752 return isRegOrInlineNoMods(AMDGPU::VReg_128RegClassID, MVT::i32);
753 }
754
755 bool isVISrc_128_f32() const {
756 return isRegOrInlineNoMods(AMDGPU::VReg_128RegClassID, MVT::f32);
757 }
758
759 bool isVISrc_256V2FP32() const {
760 return isRegOrInlineNoMods(AMDGPU::VReg_256RegClassID, MVT::f32);
761 }
762
763 bool isVISrc_256V2INT32() const {
764 return isRegOrInlineNoMods(AMDGPU::VReg_256RegClassID, MVT::i32);
765 }
766
767 bool isVISrc_512_b32() const {
768 return isRegOrInlineNoMods(AMDGPU::VReg_512RegClassID, MVT::i32);
769 }
770
771 bool isVISrc_512B16() const {
772 return isRegOrInlineNoMods(AMDGPU::VReg_512RegClassID, MVT::i16);
773 }
774
775 bool isVISrc_512V2B16() const { return isVISrc_512B16(); }
776
777 bool isVISrc_512_f32() const {
778 return isRegOrInlineNoMods(AMDGPU::VReg_512RegClassID, MVT::f32);
779 }
780
781 bool isVISrc_512F16() const {
782 return isRegOrInlineNoMods(AMDGPU::VReg_512RegClassID, MVT::f16);
783 }
784
785 bool isVISrc_512V2F16() const {
786 return isVISrc_512F16() || isVISrc_512_b32();
787 }
788
789 bool isVISrc_1024_b32() const {
790 return isRegOrInlineNoMods(AMDGPU::VReg_1024RegClassID, MVT::i32);
791 }
792
793 bool isVISrc_1024B16() const {
794 return isRegOrInlineNoMods(AMDGPU::VReg_1024RegClassID, MVT::i16);
795 }
796
797 bool isVISrc_1024V2B16() const { return isVISrc_1024B16(); }
798
799 bool isVISrc_1024_f32() const {
800 return isRegOrInlineNoMods(AMDGPU::VReg_1024RegClassID, MVT::f32);
801 }
802
803 bool isVISrc_1024F16() const {
804 return isRegOrInlineNoMods(AMDGPU::VReg_1024RegClassID, MVT::f16);
805 }
806
807 bool isVISrc_1024V2F16() const {
808 return isVISrc_1024F16() || isVISrc_1024_b32();
809 }
810
811 bool isAISrcB32() const {
812 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::i32);
813 }
814
815 bool isAISrcB16() const {
816 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::i16);
817 }
818
819 bool isAISrcV2B16() const { return isAISrcB16(); }
820
821 bool isAISrcF32() const {
822 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::f32);
823 }
824
825 bool isAISrcF16() const {
826 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::f16);
827 }
828
829 bool isAISrcV2F16() const { return isAISrcF16() || isAISrcB32(); }
830
831 bool isAISrc_64B64() const {
832 return isRegOrInlineNoMods(AMDGPU::AReg_64RegClassID, MVT::i64);
833 }
834
835 bool isAISrc_64_f64() const {
836 return isRegOrInlineNoMods(AMDGPU::AReg_64RegClassID, MVT::f64);
837 }
838
839 bool isAISrc_128_b32() const {
840 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::i32);
841 }
842
843 bool isAISrc_128B16() const {
844 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::i16);
845 }
846
847 bool isAISrc_128V2B16() const { return isAISrc_128B16(); }
848
849 bool isAISrc_128_f32() const {
850 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::f32);
851 }
852
853 bool isAISrc_128F16() const {
854 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::f16);
855 }
856
857 bool isAISrc_128V2F16() const {
858 return isAISrc_128F16() || isAISrc_128_b32();
859 }
860
861 bool isVISrc_128_bf16() const {
862 return isRegOrInlineNoMods(AMDGPU::VReg_128RegClassID, MVT::bf16);
863 }
864
865 bool isVISrc_128_f16() const {
866 return isRegOrInlineNoMods(AMDGPU::VReg_128RegClassID, MVT::f16);
867 }
868
869 bool isVISrc_128V2F16() const {
870 return isVISrc_128_f16() || isVISrc_128_b32();
871 }
872
873 bool isAISrc_256B64() const {
874 return isRegOrInlineNoMods(AMDGPU::AReg_256RegClassID, MVT::i64);
875 }
876
877 bool isAISrc_256_f64() const {
878 return isRegOrInlineNoMods(AMDGPU::AReg_256RegClassID, MVT::f64);
879 }
880
881 bool isAISrc_512_b32() const {
882 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::i32);
883 }
884
885 bool isAISrc_512B16() const {
886 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::i16);
887 }
888
889 bool isAISrc_512V2B16() const { return isAISrc_512B16(); }
890
891 bool isAISrc_512_f32() const {
892 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::f32);
893 }
894
895 bool isAISrc_512F16() const {
896 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::f16);
897 }
898
899 bool isAISrc_512V2F16() const {
900 return isAISrc_512F16() || isAISrc_512_b32();
901 }
902
903 bool isAISrc_1024_b32() const {
904 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::i32);
905 }
906
907 bool isAISrc_1024B16() const {
908 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::i16);
909 }
910
911 bool isAISrc_1024V2B16() const { return isAISrc_1024B16(); }
912
913 bool isAISrc_1024_f32() const {
914 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::f32);
915 }
916
917 bool isAISrc_1024F16() const {
918 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::f16);
919 }
920
921 bool isAISrc_1024V2F16() const {
922 return isAISrc_1024F16() || isAISrc_1024_b32();
923 }
924
925 bool isKImmFP32() const { return isLiteralImm(MVT::f32); }
926
927 bool isKImmFP16() const { return isLiteralImm(MVT::f16); }
928
929 bool isKImmFP64() const { return isLiteralImm(MVT::f64); }
930
931 bool isMem() const override { return false; }
932
933 bool isExpr() const { return Kind == Expression; }
934
935 bool isSOPPBrTarget() const { return isExpr() || isImm(); }
936
937 bool isSWaitCnt() const;
938 bool isDepCtr() const;
939 bool isSDelayALU() const;
940 bool isHwreg() const;
941 bool isSendMsg() const;
942 bool isWaitEvent() const;
943 bool isSplitBarrier() const;
944 bool isSwizzle() const;
945 bool isSMRDOffset8() const;
946 bool isSMEMOffset() const;
947 bool isSMRDLiteralOffset() const;
948 bool isDPP8() const;
949 bool isDPPCtrl() const;
950 bool isBLGP() const;
951 bool isGPRIdxMode() const;
952 bool isS16Imm() const;
953 bool isU16Imm() const;
954 bool isEndpgm() const;
955
956 auto getPredicate(std::function<bool(const AMDGPUOperand &Op)> P) const {
957 return [this, P]() { return P(*this); };
958 }
959
960 StringRef getToken() const {
961 assert(isToken());
962 return StringRef(Tok.Data, Tok.Length);
963 }
964
965 int64_t getImm() const {
966 assert(isImm());
967 return Imm.Val;
968 }
969
970 void setImm(int64_t Val) {
971 assert(isImm());
972 Imm.Val = Val;
973 }
974
975 ImmTy getImmTy() const {
976 assert(isImm());
977 return Imm.Type;
978 }
979
980 MCRegister getReg() const override {
981 assert(isRegKind());
982 return Reg.RegNo;
983 }
984
985 SMLoc getStartLoc() const override { return StartLoc; }
986
987 SMLoc getEndLoc() const override { return EndLoc; }
988
989 SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
990
991 int getMCOpIdx() const { return MCOpIdx; }
992
993 Modifiers getModifiers() const {
994 assert(isRegKind() || isImmTy(ImmTyNone));
995 return isRegKind() ? Reg.Mods : Imm.Mods;
996 }
997
998 void setModifiers(Modifiers Mods) {
999 assert(isRegKind() || isImmTy(ImmTyNone));
1000 if (isRegKind())
1001 Reg.Mods = Mods;
1002 else
1003 Imm.Mods = Mods;
1004 }
1005
1006 bool hasModifiers() const { return getModifiers().hasModifiers(); }
1007
1008 bool hasFPModifiers() const { return getModifiers().hasFPModifiers(); }
1009
1010 bool hasIntModifiers() const { return getModifiers().hasIntModifiers(); }
1011
1012 bool isForcedLit() const {
1013 return isImmLiteral() && getModifiers().isForcedLit();
1014 }
1015
1016 bool isForcedLit64() const {
1017 return isImmLiteral() && getModifiers().isForcedLit64();
1018 }
1019
1020 uint64_t applyInputFPModifiers(uint64_t Val, unsigned Size) const;
1021
1022 void addImmOperands(MCInst &Inst, unsigned N,
1023 bool ApplyModifiers = true) const;
1024
1025 void addLiteralImmOperand(MCInst &Inst, int64_t Val,
1026 bool ApplyModifiers) const;
1027
1028 void addRegOperands(MCInst &Inst, unsigned N) const;
1029
1030 void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
1031 if (isRegKind())
1032 addRegOperands(Inst, N);
1033 else
1034 addImmOperands(Inst, N);
1035 }
1036
1037 void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const {
1038 Modifiers Mods = getModifiers();
1039 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
1040 if (isRegKind()) {
1041 addRegOperands(Inst, N);
1042 } else {
1043 addImmOperands(Inst, N, false);
1044 }
1045 }
1046
1047 void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
1048 assert(!hasIntModifiers());
1049 addRegOrImmWithInputModsOperands(Inst, N);
1050 }
1051
1052 void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
1053 assert(!hasFPModifiers());
1054 addRegOrImmWithInputModsOperands(Inst, N);
1055 }
1056
1057 void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const {
1058 Modifiers Mods = getModifiers();
1059 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
1060 assert(isRegKind());
1061 addRegOperands(Inst, N);
1062 }
1063
1064 void addRegWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
1065 assert(!hasIntModifiers());
1066 addRegWithInputModsOperands(Inst, N);
1067 }
1068
1069 void addRegWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
1070 assert(!hasFPModifiers());
1071 addRegWithInputModsOperands(Inst, N);
1072 }
1073
1074 static void printImmTy(raw_ostream &OS, ImmTy Type) {
1075 // clang-format off
1076 switch (Type) {
1077 case ImmTyNone: OS << "None"; break;
1078 case ImmTyGDS: OS << "GDS"; break;
1079 case ImmTyLDS: OS << "LDS"; break;
1080 case ImmTyOffen: OS << "Offen"; break;
1081 case ImmTyIdxen: OS << "Idxen"; break;
1082 case ImmTyAddr64: OS << "Addr64"; break;
1083 case ImmTyOffset: OS << "Offset"; break;
1084 case ImmTyInstOffset: OS << "InstOffset"; break;
1085 case ImmTyOffset0: OS << "Offset0"; break;
1086 case ImmTyOffset1: OS << "Offset1"; break;
1087 case ImmTySMEMOffsetMod: OS << "SMEMOffsetMod"; break;
1088 case ImmTyCPol: OS << "CPol"; break;
1089 case ImmTyIndexKey8bit: OS << "index_key"; break;
1090 case ImmTyIndexKey16bit: OS << "index_key"; break;
1091 case ImmTyIndexKey32bit: OS << "index_key"; break;
1092 case ImmTyTFE: OS << "TFE"; break;
1093 case ImmTyIsAsync: OS << "IsAsync"; break;
1094 case ImmTyD16: OS << "D16"; break;
1095 case ImmTyFORMAT: OS << "FORMAT"; break;
1096 case ImmTyClamp: OS << "Clamp"; break;
1097 case ImmTyOModSI: OS << "OModSI"; break;
1098 case ImmTyDPP8: OS << "DPP8"; break;
1099 case ImmTyDppCtrl: OS << "DppCtrl"; break;
1100 case ImmTyDppRowMask: OS << "DppRowMask"; break;
1101 case ImmTyDppBankMask: OS << "DppBankMask"; break;
1102 case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break;
1103 case ImmTyDppFI: OS << "DppFI"; break;
1104 case ImmTySDWADstSel: OS << "SDWADstSel"; break;
1105 case ImmTySDWASrc0Sel: OS << "SDWASrc0Sel"; break;
1106 case ImmTySDWASrc1Sel: OS << "SDWASrc1Sel"; break;
1107 case ImmTySDWADstUnused: OS << "SDWADstUnused"; break;
1108 case ImmTyDMask: OS << "DMask"; break;
1109 case ImmTyDim: OS << "Dim"; break;
1110 case ImmTyUNorm: OS << "UNorm"; break;
1111 case ImmTyDA: OS << "DA"; break;
1112 case ImmTyR128A16: OS << "R128A16"; break;
1113 case ImmTyA16: OS << "A16"; break;
1114 case ImmTyLWE: OS << "LWE"; break;
1115 case ImmTyOff: OS << "Off"; break;
1116 case ImmTyExpTgt: OS << "ExpTgt"; break;
1117 case ImmTyExpCompr: OS << "ExpCompr"; break;
1118 case ImmTyExpVM: OS << "ExpVM"; break;
1119 case ImmTyDone: OS << "Done"; break;
1120 case ImmTyRowEn: OS << "RowEn"; break;
1121 case ImmTyHwreg: OS << "Hwreg"; break;
1122 case ImmTySendMsg: OS << "SendMsg"; break;
1123 case ImmTyWaitEvent: OS << "WaitEvent"; break;
1124 case ImmTyInterpSlot: OS << "InterpSlot"; break;
1125 case ImmTyInterpAttr: OS << "InterpAttr"; break;
1126 case ImmTyInterpAttrChan: OS << "InterpAttrChan"; break;
1127 case ImmTyOpSel: OS << "OpSel"; break;
1128 case ImmTyOpSelHi: OS << "OpSelHi"; break;
1129 case ImmTyNegLo: OS << "NegLo"; break;
1130 case ImmTyNegHi: OS << "NegHi"; break;
1131 case ImmTySwizzle: OS << "Swizzle"; break;
1132 case ImmTyGprIdxMode: OS << "GprIdxMode"; break;
1133 case ImmTyHigh: OS << "High"; break;
1134 case ImmTyBLGP: OS << "BLGP"; break;
1135 case ImmTyCBSZ: OS << "CBSZ"; break;
1136 case ImmTyABID: OS << "ABID"; break;
1137 case ImmTyEndpgm: OS << "Endpgm"; break;
1138 case ImmTyWaitVDST: OS << "WaitVDST"; break;
1139 case ImmTyWaitEXP: OS << "WaitEXP"; break;
1140 case ImmTyWaitVAVDst: OS << "WaitVAVDst"; break;
1141 case ImmTyWaitVMVSrc: OS << "WaitVMVSrc"; break;
1142 case ImmTyBitOp3: OS << "BitOp3"; break;
1143 case ImmTyMatrixAFMT: OS << "ImmTyMatrixAFMT"; break;
1144 case ImmTyMatrixBFMT: OS << "ImmTyMatrixBFMT"; break;
1145 case ImmTyMatrixAScale: OS << "ImmTyMatrixAScale"; break;
1146 case ImmTyMatrixBScale: OS << "ImmTyMatrixBScale"; break;
1147 case ImmTyMatrixAScaleFmt: OS << "ImmTyMatrixAScaleFmt"; break;
1148 case ImmTyMatrixBScaleFmt: OS << "ImmTyMatrixBScaleFmt"; break;
1149 case ImmTyMatrixAReuse: OS << "ImmTyMatrixAReuse"; break;
1150 case ImmTyMatrixBReuse: OS << "ImmTyMatrixBReuse"; break;
1151 case ImmTyScaleSel: OS << "ScaleSel" ; break;
1152 case ImmTyByteSel: OS << "ByteSel" ; break;
1153 }
1154 // clang-format on
1155 }
1156
1157 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override {
1158 switch (Kind) {
1159 case Register:
1160 OS << "<register " << AMDGPUInstPrinter::getRegisterName(getReg())
1161 << " mods: " << Reg.Mods << '>';
1162 break;
1163 case Immediate:
1164 OS << '<' << getImm();
1165 if (getImmTy() != ImmTyNone) {
1166 OS << " type: ";
1167 printImmTy(OS, getImmTy());
1168 }
1169 OS << " mods: " << Imm.Mods << '>';
1170 break;
1171 case Token:
1172 OS << '\'' << getToken() << '\'';
1173 break;
1174 case Expression:
1175 OS << "<expr ";
1176 MAI.printExpr(OS, *Expr);
1177 OS << '>';
1178 break;
1179 }
1180 }
1181
1182 static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser,
1183 int64_t Val, SMLoc Loc,
1184 ImmTy Type = ImmTyNone,
1185 bool IsFPImm = false) {
1186 auto Op = std::make_unique<AMDGPUOperand>(Immediate, AsmParser);
1187 Op->Imm.Val = Val;
1188 Op->Imm.IsFPImm = IsFPImm;
1189 Op->Imm.Type = Type;
1190 Op->Imm.Mods = Modifiers();
1191 Op->StartLoc = Loc;
1192 Op->EndLoc = Loc;
1193 return Op;
1194 }
1195
1196 static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser,
1197 StringRef Str, SMLoc Loc,
1198 bool HasExplicitEncodingSize = true) {
1199 auto Res = std::make_unique<AMDGPUOperand>(Token, AsmParser);
1200 Res->Tok.Data = Str.data();
1201 Res->Tok.Length = Str.size();
1202 Res->StartLoc = Loc;
1203 Res->EndLoc = Loc;
1204 return Res;
1205 }
1206
1207 static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser,
1208 MCRegister Reg, SMLoc S, SMLoc E) {
1209 auto Op = std::make_unique<AMDGPUOperand>(Register, AsmParser);
1210 Op->Reg.RegNo = Reg;
1211 Op->Reg.Mods = Modifiers();
1212 Op->StartLoc = S;
1213 Op->EndLoc = E;
1214 return Op;
1215 }
1216
1217 static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser,
1218 const class MCExpr *Expr, SMLoc S) {
1219 auto Op = std::make_unique<AMDGPUOperand>(Expression, AsmParser);
1220 Op->Expr = Expr;
1221 Op->StartLoc = S;
1222 Op->EndLoc = S;
1223 return Op;
1224 }
1225};
1226
1227raw_ostream &operator<<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) {
1228 OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext;
1229 return OS;
1230}
1231
1232//===----------------------------------------------------------------------===//
1233// AsmParser
1234//===----------------------------------------------------------------------===//
1235
1236// TODO: define GET_SUBTARGET_FEATURE_NAME
1237#define GET_REGISTER_MATCHER
1238#include "AMDGPUGenAsmMatcher.inc"
1239#undef GET_REGISTER_MATCHER
1240#undef GET_SUBTARGET_FEATURE_NAME
1241
1242// Holds info related to the current kernel, e.g. count of SGPRs used.
1243// Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next
1244// .amdgpu_hsa_kernel or at EOF.
1245class KernelScopeInfo {
1246 int SgprIndexUnusedMin = -1;
1247 int VgprIndexUnusedMin = -1;
1248 int AgprIndexUnusedMin = -1;
1249 MCContext *Ctx = nullptr;
1250 MCSubtargetInfo const *MSTI = nullptr;
1251
1252 void usesSgprAt(int i) {
1253 if (i >= SgprIndexUnusedMin) {
1254 SgprIndexUnusedMin = ++i;
1255 if (Ctx) {
1256 MCSymbol *const Sym =
1257 Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count"));
1258 Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx));
1259 }
1260 }
1261 }
1262
1263 void usesVgprAt(int i) {
1264 if (i >= VgprIndexUnusedMin) {
1265 VgprIndexUnusedMin = ++i;
1266 if (Ctx) {
1267 MCSymbol *const Sym =
1268 Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count"));
1269 int totalVGPR = getTotalNumVGPRs(isGFX90A(*MSTI), AgprIndexUnusedMin,
1270 VgprIndexUnusedMin);
1271 Sym->setVariableValue(MCConstantExpr::create(totalVGPR, *Ctx));
1272 }
1273 }
1274 }
1275
1276 void usesAgprAt(int i) {
1277 // Instruction will error in AMDGPUAsmParser::matchAndEmitInstruction
1278 if (!hasMAIInsts(*MSTI))
1279 return;
1280
1281 if (i >= AgprIndexUnusedMin) {
1282 AgprIndexUnusedMin = ++i;
1283 if (Ctx) {
1284 MCSymbol *const Sym =
1285 Ctx->getOrCreateSymbol(Twine(".kernel.agpr_count"));
1286 Sym->setVariableValue(MCConstantExpr::create(AgprIndexUnusedMin, *Ctx));
1287
1288 // Also update vgpr_count (dependent on agpr_count for gfx908/gfx90a)
1289 MCSymbol *const vSym =
1290 Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count"));
1291 int totalVGPR = getTotalNumVGPRs(isGFX90A(*MSTI), AgprIndexUnusedMin,
1292 VgprIndexUnusedMin);
1293 vSym->setVariableValue(MCConstantExpr::create(totalVGPR, *Ctx));
1294 }
1295 }
1296 }
1297
1298public:
1299 KernelScopeInfo() = default;
1300
1301 void initialize(MCContext &Context) {
1302 Ctx = &Context;
1303 MSTI = Ctx->getSubtargetInfo();
1304
1305 usesSgprAt(SgprIndexUnusedMin = -1);
1306 usesVgprAt(VgprIndexUnusedMin = -1);
1307 if (hasMAIInsts(*MSTI)) {
1308 usesAgprAt(AgprIndexUnusedMin = -1);
1309 }
1310 }
1311
1312 void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex,
1313 unsigned RegWidth) {
1314 switch (RegKind) {
1315 case IS_SGPR:
1316 usesSgprAt(DwordRegIndex + divideCeil(RegWidth, 32) - 1);
1317 break;
1318 case IS_AGPR:
1319 usesAgprAt(DwordRegIndex + divideCeil(RegWidth, 32) - 1);
1320 break;
1321 case IS_VGPR:
1322 usesVgprAt(DwordRegIndex + divideCeil(RegWidth, 32) - 1);
1323 break;
1324 default:
1325 break;
1326 }
1327 }
1328};
1329
1330class AMDGPUAsmParser : public MCTargetAsmParser {
1331 MCAsmParser &Parser;
1332
1333 unsigned ForcedEncodingSize = 0;
1334 bool ForcedDPP = false;
1335 bool ForcedSDWA = false;
1336 KernelScopeInfo KernelScope;
1337 const unsigned HwMode;
1338 const AMDGPU::GPUKind Gfx;
1339 const AMDGPU::IsaVersion ISA;
1340
1341 /// @name Auto-generated Match Functions
1342 /// {
1343
1344#define GET_ASSEMBLER_HEADER
1345#include "AMDGPUGenAsmMatcher.inc"
1346
1347 /// }
1348
1349 /// Get size of register operand
1350 unsigned getRegOperandSize(const MCInstrDesc &Desc, unsigned OpNo) const {
1351 assert(OpNo < Desc.NumOperands);
1352 int16_t RCID = MII.getOpRegClassID(Desc.operands()[OpNo], HwMode);
1353 return getRegBitWidth(RCID) / 8;
1354 }
1355
1356 std::optional<AMDGPU::InfoSectionData> InfoData;
1357
1358 /// Whether the leading .amdgcn_target directive has been emitted to the
1359 /// output streamer yet. The emission is deferred until the first piece of
1360 /// content (instruction or kernel descriptor) so that any leading
1361 /// .amdgcn_target/.amd_amdgpu_isa directive in the source has had a chance to
1362 /// update the target ID first.
1363 bool TargetDirectiveEmitted = false;
1364
1365 /// State for checking that every kernel named in a .amdhsa_kernel directive
1366 /// begins with the required prologue instruction sequence. Because the
1367 /// directive may appear either before or after the kernel's label (it is
1368 /// normally emitted after the function body, in .rodata), validation is
1369 /// deferred to onEndOfFile(). We record an order-independent timeline of
1370 /// parsed labels and emitted instruction opcodes, plus the set of symbols
1371 /// named by .amdhsa_kernel directives, and match them up at end of file.
1372 SmallVector<unsigned> OpcodeStream;
1374 OpcodeStreamSymbols;
1375 SmallPtrSet<const MCSymbol *, 8> AMDHSAKernelSymbols;
1376
1377 /// Verify recorded kernel prologues.
1378 void checkKernelPrologues();
1379
1380private:
1381 void createConstantSymbol(StringRef Id, int64_t Val);
1382
1383 bool ParseAsAbsoluteExpression(uint32_t &Ret);
1384 bool OutOfRangeError(SMRange Range);
1385 /// Calculate VGPR/SGPR blocks required for given target, reserved
1386 /// registers, and user-specified NextFreeXGPR values.
1387 ///
1388 /// \param Features [in] Target features, used for bug corrections.
1389 /// \param VCCUsed [in] Whether VCC special SGPR is reserved.
1390 /// \param FlatScrUsed [in] Whether FLAT_SCRATCH special SGPR is reserved.
1391 /// \param XNACKUsed [in] Whether XNACK_MASK special SGPR is reserved.
1392 /// \param EnableWavefrontSize32 [in] Value of ENABLE_WAVEFRONT_SIZE32 kernel
1393 /// descriptor field, if valid.
1394 /// \param NextFreeVGPR [in] Max VGPR number referenced, plus one.
1395 /// \param VGPRRange [in] Token range, used for VGPR diagnostics.
1396 /// \param NextFreeSGPR [in] Max SGPR number referenced, plus one.
1397 /// \param SGPRRange [in] Token range, used for SGPR diagnostics.
1398 /// \param VGPRBlocks [out] Result VGPR block count.
1399 /// \param SGPRBlocks [out] Result SGPR block count.
1400 bool calculateGPRBlocks(const FeatureBitset &Features, const MCExpr *VCCUsed,
1401 const MCExpr *FlatScrUsed, bool XNACKUsed,
1402 std::optional<bool> EnableWavefrontSize32,
1403 const MCExpr *NextFreeVGPR, SMRange VGPRRange,
1404 const MCExpr *NextFreeSGPR, SMRange SGPRRange,
1405 const MCExpr *&VGPRBlocks, const MCExpr *&SGPRBlocks);
1406 bool ParseDirectiveAMDGCNTarget();
1407 bool ParseDirectiveAMDHSACodeObjectVersion();
1408 bool ParseDirectiveAMDHSAKernel();
1409 bool ParseAMDKernelCodeTValue(StringRef ID, AMDGPUMCKernelCodeT &Header);
1410 bool ParseDirectiveAMDKernelCodeT();
1411 // TODO: Possibly make subtargetHasRegister const.
1412 bool subtargetHasRegister(const MCRegisterInfo &MRI, MCRegister Reg);
1413 bool ParseDirectiveAMDGPUHsaKernel();
1414
1415 bool ParseDirectiveISAVersion();
1416 bool ParseDirectiveHSAMetadata();
1417 bool ParseDirectivePALMetadataBegin();
1418 bool ParseDirectivePALMetadata();
1419 bool ParseDirectiveAMDGPULDS();
1420 bool ParseDirectiveAMDGPUInfo();
1421
1422 /// Common code to parse out a block of text (typically YAML) between start
1423 /// and end directives.
1424 bool ParseToEndDirective(const char *AssemblerDirectiveBegin,
1425 const char *AssemblerDirectiveEnd,
1426 std::string &CollectString);
1427
1428 bool AddNextRegisterToList(MCRegister &Reg, unsigned &RegWidth,
1429 RegisterKind RegKind, MCRegister Reg1,
1430 RegisterKind RegKind1, SMLoc Loc);
1431 bool ParseAMDGPURegister(RegisterKind &RegKind, MCRegister &Reg,
1432 unsigned &RegNum, unsigned &RegWidth,
1433 bool RestoreOnFailure = false);
1434 bool ParseAMDGPURegister(RegisterKind &RegKind, MCRegister &Reg,
1435 unsigned &RegNum, unsigned &RegWidth,
1436 SmallVectorImpl<AsmToken> &Tokens);
1437 MCRegister ParseRegularReg(RegisterKind &RegKind, unsigned &RegNum,
1438 unsigned &RegWidth,
1439 SmallVectorImpl<AsmToken> &Tokens);
1440 MCRegister ParseSpecialReg(RegisterKind &RegKind, unsigned &RegNum,
1441 unsigned &RegWidth,
1442 SmallVectorImpl<AsmToken> &Tokens);
1443 MCRegister ParseRegList(RegisterKind &RegKind, unsigned &RegNum,
1444 unsigned &RegWidth,
1445 SmallVectorImpl<AsmToken> &Tokens);
1446 bool ParseRegRange(unsigned &Num, unsigned &Width, unsigned &SubReg);
1447 MCRegister getRegularReg(RegisterKind RegKind, unsigned RegNum,
1448 unsigned SubReg, unsigned RegWidth, SMLoc Loc);
1449
1450 bool isRegister();
1451 bool isRegister(const AsmToken &Token, const AsmToken &NextToken) const;
1452 std::optional<StringRef> getGprCountSymbolName(RegisterKind RegKind);
1453 void initializeGprCountSymbol(RegisterKind RegKind);
1454 bool updateGprCountSymbols(RegisterKind RegKind, unsigned DwordRegIndex,
1455 unsigned RegWidth);
1456 void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands, bool IsAtomic);
1457
1458public:
1459 enum OperandMode {
1460 OperandMode_Default,
1461 OperandMode_NSA,
1462 };
1463
1464 using OptionalImmIndexMap = std::map<AMDGPUOperand::ImmTy, unsigned>;
1465
1466 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
1467 const MCInstrInfo &MII)
1468 : MCTargetAsmParser(STI, MII), Parser(_Parser),
1469 HwMode(STI.getHwMode(MCSubtargetInfo::HwMode_RegInfo)),
1470 Gfx(AMDGPU::parseArchAMDGCN(STI.getCPU())),
1471 ISA(AMDGPU::getIsaVersion(STI.getCPU())) {
1473
1474 setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits()));
1475
1476 if (ISA.Major >= 6 && isHsaAbi(getSTI())) {
1477 createConstantSymbol(".amdgcn.gfx_generation_number", ISA.Major);
1478 createConstantSymbol(".amdgcn.gfx_generation_minor", ISA.Minor);
1479 createConstantSymbol(".amdgcn.gfx_generation_stepping", ISA.Stepping);
1480 } else {
1481 createConstantSymbol(".option.machine_version_major", ISA.Major);
1482 createConstantSymbol(".option.machine_version_minor", ISA.Minor);
1483 createConstantSymbol(".option.machine_version_stepping", ISA.Stepping);
1484 }
1485 if (ISA.Major >= 6 && isHsaAbi(getSTI())) {
1486 initializeGprCountSymbol(IS_VGPR);
1487 initializeGprCountSymbol(IS_SGPR);
1488 } else
1489 KernelScope.initialize(getContext());
1490
1491 for (auto [Symbol, Code] : AMDGPU::UCVersion::getGFXVersions())
1492 createConstantSymbol(Symbol, Code);
1493
1494 createConstantSymbol("UC_VERSION_W64_BIT", 0x2000);
1495 createConstantSymbol("UC_VERSION_W32_BIT", 0x4000);
1496 createConstantSymbol("UC_VERSION_MDP_BIT", 0x8000);
1497 }
1498
1499 bool hasMIMG_R128() const { return AMDGPU::hasMIMG_R128(getSTI()); }
1500
1501 bool hasPackedD16() const { return AMDGPU::hasPackedD16(getSTI()); }
1502
1503 bool hasA16() const { return AMDGPU::hasA16(getSTI()); }
1504
1505 bool hasG16() const { return AMDGPU::hasG16(getSTI()); }
1506
1507 bool hasGDS() const { return AMDGPU::hasGDS(getSTI()); }
1508
1509 bool isSI() const { return AMDGPU::isSI(getSTI()); }
1510
1511 bool isCI() const { return AMDGPU::isCI(getSTI()); }
1512
1513 bool isVI() const { return AMDGPU::isVI(getSTI()); }
1514
1515 bool isGFX9() const { return AMDGPU::isGFX9(getSTI()); }
1516
1517 // TODO: isGFX90A is also true for GFX940. We need to clean it.
1518 bool isGFX90A() const { return AMDGPU::isGFX90A(getSTI()); }
1519
1520 bool isGFX940() const { return AMDGPU::isGFX940(getSTI()); }
1521
1522 bool isGFX9Plus() const { return AMDGPU::isGFX9Plus(getSTI()); }
1523
1524 bool isGFX10() const { return AMDGPU::isGFX10(getSTI()); }
1525
1526 bool isGFX10Plus() const { return AMDGPU::isGFX10Plus(getSTI()); }
1527
1528 bool isGFX11() const { return AMDGPU::isGFX11(getSTI()); }
1529
1530 bool isGFX11Plus() const { return AMDGPU::isGFX11Plus(getSTI()); }
1531
1532 bool isGFX12() const { return AMDGPU::isGFX12(getSTI()); }
1533
1534 bool isGFX12Plus() const { return AMDGPU::isGFX12Plus(getSTI()); }
1535
1536 bool isGFX1250() const { return AMDGPU::isGFX1250(getSTI()); }
1537
1538 bool isGFX1250Plus() const { return AMDGPU::isGFX1250Plus(getSTI()); }
1539
1540 bool isGFX13() const { return AMDGPU::isGFX13(getSTI()); }
1541
1542 bool isGFX13Plus() const { return AMDGPU::isGFX13Plus(getSTI()); }
1543
1544 bool hasBVHRayTracingInsts() const {
1545 return getFeatureBits()[AMDGPU::FeatureBVHRayTracingInsts];
1546 }
1547
1548 bool isGFX10_BEncoding() const { return AMDGPU::isGFX10_BEncoding(getSTI()); }
1549
1550 bool isWave32() const { return getAvailableFeatures()[Feature_isWave32Bit]; }
1551
1552 bool isWave64() const { return getAvailableFeatures()[Feature_isWave64Bit]; }
1553
1554 bool hasInv2PiInlineImm() const {
1555 return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm];
1556 }
1557
1558 bool has64BitLiterals() const {
1559 return getFeatureBits()[AMDGPU::Feature64BitLiterals];
1560 }
1561
1562 bool hasFlatOffsets() const {
1563 return getFeatureBits()[AMDGPU::FeatureFlatInstOffsets];
1564 }
1565
1566 bool hasTrue16Insts() const {
1567 return getFeatureBits()[AMDGPU::FeatureTrue16BitInsts];
1568 }
1569
1570 bool hasArchitectedFlatScratch() const {
1571 return getFeatureBits()[AMDGPU::FeatureArchitectedFlatScratch];
1572 }
1573
1574 bool hasSGPR102_SGPR103() const { return !isVI() && !isGFX9(); }
1575
1576 bool hasSGPR104_SGPR105() const { return isGFX10Plus(); }
1577
1578 bool hasIntClamp() const { return getFeatureBits()[AMDGPU::FeatureIntClamp]; }
1579
1580 bool hasPartialNSAEncoding() const {
1581 return getFeatureBits()[AMDGPU::FeaturePartialNSAEncoding];
1582 }
1583
1584 bool hasGloballyAddressableScratch() const {
1585 return getFeatureBits()[AMDGPU::FeatureGloballyAddressableScratch];
1586 }
1587
1588 unsigned getNSAMaxSize(bool HasSampler = false) const {
1589 return AMDGPU::getNSAMaxSize(getSTI(), HasSampler);
1590 }
1591
1592 unsigned getMaxNumUserSGPRs() const {
1593 return AMDGPU::getMaxNumUserSGPRs(getSTI());
1594 }
1595
1596 bool hasKernargPreload() const { return AMDGPU::hasKernargPreload(getSTI()); }
1597
1598 AMDGPUTargetStreamer &getTargetStreamer() {
1599 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
1600 return static_cast<AMDGPUTargetStreamer &>(TS);
1601 }
1602
1603 MCContext &getContext() const {
1604 // We need this const_cast because for some reason getContext() is not const
1605 // in MCAsmParser.
1606 return const_cast<AMDGPUAsmParser *>(this)->MCTargetAsmParser::getContext();
1607 }
1608
1609 const MCRegisterInfo *getMRI() const {
1610 return getContext().getRegisterInfo();
1611 }
1612
1613 const MCInstrInfo *getMII() const { return &MII; }
1614
1615 // FIXME: This should not be used. Instead, should use queries derived from
1616 // getAvailableFeatures().
1617 const FeatureBitset &getFeatureBits() const {
1618 return getSTI().getFeatureBits();
1619 }
1620
1621 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
1622 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
1623 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
1624
1625 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
1626 bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
1627 bool isForcedDPP() const { return ForcedDPP; }
1628 bool isForcedSDWA() const { return ForcedSDWA; }
1629 ArrayRef<unsigned> getMatchedVariants() const;
1630 StringRef getMatchedVariantName() const;
1631
1632 std::unique_ptr<AMDGPUOperand> parseRegister(bool RestoreOnFailure = false);
1633 bool ParseRegister(MCRegister &RegNo, SMLoc &StartLoc, SMLoc &EndLoc,
1634 bool RestoreOnFailure);
1635 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
1636 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1637 SMLoc &EndLoc) override;
1638 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
1639 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
1640 unsigned Kind) override;
1641 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1642 OperandVector &Operands, MCStreamer &Out,
1643 uint64_t &ErrorInfo,
1644 bool MatchingInlineAsm) override;
1645 bool ParseDirective(AsmToken DirectiveID) override;
1646 void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) override;
1647 void onEndOfFile() override;
1648 ParseStatus parseOperand(OperandVector &Operands, StringRef Mnemonic,
1649 OperandMode Mode = OperandMode_Default);
1650 StringRef parseMnemonicSuffix(StringRef Name);
1651 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
1652 SMLoc NameLoc, OperandVector &Operands) override;
1653 // bool ProcessInstruction(MCInst &Inst);
1654
1655 ParseStatus parseTokenOp(StringRef Name, OperandVector &Operands);
1656
1657 ParseStatus parseIntWithPrefix(const char *Prefix, int64_t &Int);
1658
1659 ParseStatus
1660 parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
1661 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1662 std::function<bool(int64_t &)> ConvertResult = nullptr);
1663
1664 ParseStatus parseOperandArrayWithPrefix(
1665 const char *Prefix, OperandVector &Operands,
1666 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1667 bool (*ConvertResult)(int64_t &) = nullptr);
1668
1669 ParseStatus
1670 parseNamedBit(StringRef Name, OperandVector &Operands,
1671 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1672 bool IgnoreNegative = false);
1673 unsigned getCPolKind(StringRef Id, StringRef Mnemo, bool &Disabling) const;
1674 ParseStatus parseCPol(OperandVector &Operands);
1675 ParseStatus parseScope(OperandVector &Operands, int64_t &Scope);
1676 ParseStatus parseTH(OperandVector &Operands, int64_t &TH);
1677 ParseStatus parseStringWithPrefix(StringRef Prefix, StringRef &Value,
1678 SMLoc &StringLoc);
1679 ParseStatus parseStringOrIntWithPrefix(OperandVector &Operands,
1680 StringRef Name,
1681 ArrayRef<const char *> Ids,
1682 int64_t &IntVal);
1683 ParseStatus parseStringOrIntWithPrefix(OperandVector &Operands,
1684 StringRef Name,
1685 ArrayRef<const char *> Ids,
1686 AMDGPUOperand::ImmTy Type);
1687
1688 bool isModifier();
1689 bool isOperandModifier(const AsmToken &Token,
1690 const AsmToken &NextToken) const;
1691 bool isRegOrOperandModifier(const AsmToken &Token,
1692 const AsmToken &NextToken) const;
1693 bool isNamedOperandModifier(const AsmToken &Token,
1694 const AsmToken &NextToken) const;
1695 bool isOpcodeModifierWithVal(const AsmToken &Token,
1696 const AsmToken &NextToken) const;
1697 bool parseSP3NegModifier();
1698 ParseStatus parseImm(OperandVector &Operands, bool HasSP3AbsModifier = false,
1699 LitModifier Lit = LitModifier::None);
1700 ParseStatus parseReg(OperandVector &Operands);
1701 ParseStatus parseRegOrImm(OperandVector &Operands, bool HasSP3AbsMod = false,
1702 LitModifier Lit = LitModifier::None);
1703 ParseStatus parseRegOrImmWithFPInputMods(OperandVector &Operands,
1704 bool AllowImm = true);
1705 ParseStatus parseRegOrImmWithIntInputMods(OperandVector &Operands,
1706 bool AllowImm = true);
1707 ParseStatus parseRegWithFPInputMods(OperandVector &Operands);
1708 ParseStatus parseRegWithIntInputMods(OperandVector &Operands);
1709 ParseStatus parseVReg32OrOff(OperandVector &Operands);
1710 ParseStatus tryParseIndexKey(OperandVector &Operands,
1711 AMDGPUOperand::ImmTy ImmTy);
1712 ParseStatus parseIndexKey8bit(OperandVector &Operands);
1713 ParseStatus parseIndexKey16bit(OperandVector &Operands);
1714 ParseStatus parseIndexKey32bit(OperandVector &Operands);
1715 ParseStatus tryParseMatrixFMT(OperandVector &Operands, StringRef Name,
1716 AMDGPUOperand::ImmTy Type);
1717 ParseStatus parseMatrixAFMT(OperandVector &Operands);
1718 ParseStatus parseMatrixBFMT(OperandVector &Operands);
1719 ParseStatus tryParseMatrixScale(OperandVector &Operands, StringRef Name,
1720 AMDGPUOperand::ImmTy Type);
1721 ParseStatus parseMatrixAScale(OperandVector &Operands);
1722 ParseStatus parseMatrixBScale(OperandVector &Operands);
1723 ParseStatus tryParseMatrixScaleFmt(OperandVector &Operands, StringRef Name,
1724 AMDGPUOperand::ImmTy Type);
1725 ParseStatus parseMatrixAScaleFmt(OperandVector &Operands);
1726 ParseStatus parseMatrixBScaleFmt(OperandVector &Operands);
1727
1728 ParseStatus parseDfmtNfmt(int64_t &Format);
1729 ParseStatus parseUfmt(int64_t &Format);
1730 ParseStatus parseSymbolicSplitFormat(StringRef FormatStr, SMLoc Loc,
1731 int64_t &Format);
1732 ParseStatus parseSymbolicUnifiedFormat(StringRef FormatStr, SMLoc Loc,
1733 int64_t &Format);
1734 ParseStatus parseFORMAT(OperandVector &Operands);
1735 ParseStatus parseSymbolicOrNumericFormat(int64_t &Format);
1736 ParseStatus parseNumericFormat(int64_t &Format);
1737 ParseStatus parseFlatOffset(OperandVector &Operands);
1738 ParseStatus parseR128A16(OperandVector &Operands);
1739 ParseStatus parseBLGP(OperandVector &Operands);
1740 bool tryParseFmt(const char *Pref, int64_t MaxVal, int64_t &Val);
1741 bool matchDfmtNfmt(int64_t &Dfmt, int64_t &Nfmt, StringRef FormatStr,
1742 SMLoc Loc);
1743
1744 void cvtExp(MCInst &Inst, const OperandVector &Operands);
1745
1746 bool parseCnt(int64_t &IntVal);
1747 ParseStatus parseSWaitCnt(OperandVector &Operands);
1748
1749 bool parseDepCtr(int64_t &IntVal, unsigned &Mask);
1750 void depCtrError(SMLoc Loc, int ErrorId, StringRef DepCtrName);
1751 ParseStatus parseDepCtr(OperandVector &Operands);
1752
1753 bool parseDelay(int64_t &Delay);
1754 ParseStatus parseSDelayALU(OperandVector &Operands);
1755
1756 ParseStatus parseHwreg(OperandVector &Operands);
1757
1758private:
1759 struct OperandInfoTy {
1760 SMLoc Loc;
1761 int64_t Val;
1762 bool IsSymbolic = false;
1763 bool IsDefined = false;
1764
1765 constexpr OperandInfoTy(int64_t Val) : Val(Val) {}
1766 };
1767
1768 struct StructuredOpField : OperandInfoTy {
1769 StringLiteral Id;
1770 StringLiteral Desc;
1771 unsigned Width;
1772 bool IsDefined = false;
1773
1774 constexpr StructuredOpField(StringLiteral Id, StringLiteral Desc,
1775 unsigned Width, int64_t Default)
1776 : OperandInfoTy(Default), Id(Id), Desc(Desc), Width(Width) {}
1777 virtual ~StructuredOpField() = default;
1778
1779 bool Error(AMDGPUAsmParser &Parser, const Twine &Err) const {
1780 Parser.Error(Loc, "invalid " + Desc + ": " + Err);
1781 return false;
1782 }
1783
1784 virtual bool validate(AMDGPUAsmParser &Parser) const {
1785 if (IsSymbolic && Val == OPR_ID_UNSUPPORTED)
1786 return Error(Parser, "not supported on this GPU");
1787 if (!isUIntN(Width, Val))
1788 return Error(Parser, "only " + Twine(Width) + "-bit values are legal");
1789 return true;
1790 }
1791 };
1792
1793 ParseStatus parseStructuredOpFields(ArrayRef<StructuredOpField *> Fields);
1794 bool validateStructuredOpFields(ArrayRef<const StructuredOpField *> Fields);
1795
1796 bool parseSendMsgBody(OperandInfoTy &Msg, OperandInfoTy &Op,
1797 OperandInfoTy &Stream);
1798 bool validateSendMsg(const OperandInfoTy &Msg, const OperandInfoTy &Op,
1799 const OperandInfoTy &Stream);
1800
1801 ParseStatus parseHwregFunc(OperandInfoTy &HwReg, OperandInfoTy &Offset,
1802 OperandInfoTy &Width);
1803
1804 const AMDGPUOperand &findMCOperand(const OperandVector &Operands,
1805 int MCOpIdx) const;
1806
1807 static SMLoc getLaterLoc(SMLoc a, SMLoc b);
1808
1809 SMLoc getFlatOffsetLoc(const OperandVector &Operands) const;
1810 SMLoc getSMEMOffsetLoc(const OperandVector &Operands) const;
1811 SMLoc getBLGPLoc(const OperandVector &Operands) const;
1812
1813 SMLoc getOperandLoc(const OperandVector &Operands, int MCOpIdx) const;
1814 SMLoc getOperandLoc(std::function<bool(const AMDGPUOperand &)> Test,
1815 const OperandVector &Operands) const;
1816 SMLoc getImmLoc(AMDGPUOperand::ImmTy Type,
1817 const OperandVector &Operands) const;
1818 SMLoc getInstLoc(const OperandVector &Operands) const;
1819
1820 bool validateInstruction(const MCInst &Inst, SMLoc IDLoc,
1821 const OperandVector &Operands);
1822 bool validateOffset(const MCInst &Inst, const OperandVector &Operands);
1823 bool validateFlatOffset(const MCInst &Inst, const OperandVector &Operands);
1824 bool validateSMEMOffset(const MCInst &Inst, const OperandVector &Operands);
1825 bool validateSOPLiteral(const MCInst &Inst, const OperandVector &Operands);
1826 bool validateConstantBusLimitations(const MCInst &Inst,
1827 const OperandVector &Operands);
1828 std::optional<unsigned> checkVOPDRegBankConstraints(const MCInst &Inst,
1829 bool AsVOPD3);
1830 bool validateVOPD(const MCInst &Inst, const OperandVector &Operands);
1831 bool tryVOPD(const MCInst &Inst);
1832 bool tryVOPD3(const MCInst &Inst);
1833 bool tryAnotherVOPDEncoding(const MCInst &Inst);
1834
1835 bool validateIntClampSupported(const MCInst &Inst);
1836 bool validateMIMGAtomicDMask(const MCInst &Inst);
1837 bool validateMIMGGatherDMask(const MCInst &Inst);
1838 bool validateMovrels(const MCInst &Inst, const OperandVector &Operands);
1839 bool validateMIMGDataSize(const MCInst &Inst, SMLoc IDLoc);
1840 bool validateMIMGAddrSize(const MCInst &Inst, SMLoc IDLoc);
1841 bool validateMIMGD16(const MCInst &Inst);
1842 bool validateMIMGDim(const MCInst &Inst, const OperandVector &Operands);
1843 bool validateTensorR128(const MCInst &Inst);
1844 bool validateMIMGMSAA(const MCInst &Inst);
1845 bool validateOpSel(const MCInst &Inst);
1846 bool validateTrue16OpSel(const MCInst &Inst);
1847 bool validateNeg(const MCInst &Inst, AMDGPU::OpName OpName);
1848 bool validateDPP(const MCInst &Inst, const OperandVector &Operands);
1849 bool validateVccOperand(MCRegister Reg) const;
1850 bool validateVOPLiteral(const MCInst &Inst, const OperandVector &Operands);
1851 bool validateMAIAccWrite(const MCInst &Inst, const OperandVector &Operands);
1852 bool validateMAISrc2(const MCInst &Inst, const OperandVector &Operands);
1853 bool validateMFMA(const MCInst &Inst, const OperandVector &Operands);
1854 bool validateAGPRLdSt(const MCInst &Inst) const;
1855 bool validateVGPRAlign(const MCInst &Inst) const;
1856 bool validateBLGP(const MCInst &Inst, const OperandVector &Operands);
1857 bool validateDS(const MCInst &Inst, const OperandVector &Operands);
1858 bool validateGWS(const MCInst &Inst, const OperandVector &Operands);
1859 bool validateDivScale(const MCInst &Inst);
1860 bool validateWaitCnt(const MCInst &Inst, const OperandVector &Operands);
1861 bool validateCoherencyBits(const MCInst &Inst, const OperandVector &Operands,
1862 SMLoc IDLoc);
1863 bool validateTHAndScopeBits(const MCInst &Inst, const OperandVector &Operands,
1864 const unsigned CPol);
1865 bool validateTFE(const MCInst &Inst, const OperandVector &Operands);
1866 bool validateLdsDirect(const MCInst &Inst, const OperandVector &Operands);
1867 bool validateWMMA(const MCInst &Inst, const OperandVector &Operands);
1868 unsigned getConstantBusLimit(unsigned Opcode) const;
1869 bool usesConstantBus(const MCInst &Inst, unsigned OpIdx);
1870 bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
1871 MCRegister findImplicitSGPRReadInVOP(const MCInst &Inst) const;
1872
1873 bool isSupportedMnemo(StringRef Mnemo, const FeatureBitset &FBS);
1874 bool isSupportedMnemo(StringRef Mnemo, const FeatureBitset &FBS,
1875 ArrayRef<unsigned> Variants);
1876 bool checkUnsupportedInstruction(StringRef Name, SMLoc IDLoc);
1877
1878 bool isId(const StringRef Id) const;
1879 bool isId(const AsmToken &Token, const StringRef Id) const;
1880 bool isToken(const AsmToken::TokenKind Kind) const;
1881 StringRef getId() const;
1882 bool trySkipId(const StringRef Id);
1883 bool trySkipId(const StringRef Pref, const StringRef Id);
1884 bool trySkipId(const StringRef Id, const AsmToken::TokenKind Kind);
1885 bool trySkipToken(const AsmToken::TokenKind Kind);
1886 bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg);
1887 bool parseString(StringRef &Val,
1888 const StringRef ErrMsg = "expected a string");
1889 bool parseId(StringRef &Val, const StringRef ErrMsg = "");
1890
1891 void peekTokens(MutableArrayRef<AsmToken> Tokens);
1892 AsmToken::TokenKind getTokenKind() const;
1893 bool parseExpr(int64_t &Imm, StringRef Expected = "");
1895 StringRef getTokenStr() const;
1896 AsmToken peekToken(bool ShouldSkipSpace = true);
1897 AsmToken getToken() const;
1898 SMLoc getLoc() const;
1899 void lex();
1900
1901public:
1902 void onBeginOfFile() override;
1903 /// Emit the deferred leading .amdgcn_target directive if it has not been
1904 /// emitted yet. Called before emitting the first instruction or kernel
1905 /// descriptor.
1906 void emitTargetDirective();
1907 bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
1908
1909 ParseStatus parseCustomOperand(OperandVector &Operands, unsigned MCK);
1910
1911 ParseStatus parseExpTgt(OperandVector &Operands);
1912 ParseStatus parseSendMsg(OperandVector &Operands);
1913 ParseStatus parseWaitEvent(OperandVector &Operands);
1914 ParseStatus parseInterpSlot(OperandVector &Operands);
1915 ParseStatus parseInterpAttr(OperandVector &Operands);
1916 ParseStatus parseSOPPBrTarget(OperandVector &Operands);
1917 ParseStatus parseBoolReg(OperandVector &Operands);
1918
1919 bool parseSwizzleOperand(int64_t &Op, const unsigned MinVal,
1920 const unsigned MaxVal, const Twine &ErrMsg,
1921 SMLoc &Loc);
1922 bool parseSwizzleOperands(const unsigned OpNum, int64_t *Op,
1923 const unsigned MinVal, const unsigned MaxVal,
1924 const StringRef ErrMsg);
1925 ParseStatus parseSwizzle(OperandVector &Operands);
1926 bool parseSwizzleOffset(int64_t &Imm);
1927 bool parseSwizzleMacro(int64_t &Imm);
1928 bool parseSwizzleQuadPerm(int64_t &Imm);
1929 bool parseSwizzleBitmaskPerm(int64_t &Imm);
1930 bool parseSwizzleBroadcast(int64_t &Imm);
1931 bool parseSwizzleSwap(int64_t &Imm);
1932 bool parseSwizzleReverse(int64_t &Imm);
1933 bool parseSwizzleFFT(int64_t &Imm);
1934 bool parseSwizzleRotate(int64_t &Imm);
1935
1936 ParseStatus parseGPRIdxMode(OperandVector &Operands);
1937 int64_t parseGPRIdxMacro();
1938
1939 void cvtMubuf(MCInst &Inst, const OperandVector &Operands) {
1940 cvtMubufImpl(Inst, Operands, false);
1941 }
1942 void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) {
1943 cvtMubufImpl(Inst, Operands, true);
1944 }
1945
1946 ParseStatus parseOModSI(OperandVector &Operands);
1947
1948 void cvtVOP3(MCInst &Inst, const OperandVector &Operands,
1949 OptionalImmIndexMap &OptionalIdx);
1950 void cvtScaledMFMA(MCInst &Inst, const OperandVector &Operands);
1951 void cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands);
1952 void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
1953 void cvtVOP3P(MCInst &Inst, const OperandVector &Operands);
1954 void cvtSWMMAC(MCInst &Inst, const OperandVector &Operands);
1955
1956 void cvtVOPD(MCInst &Inst, const OperandVector &Operands);
1957 void cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands,
1958 OptionalImmIndexMap &OptionalIdx);
1959 void cvtVOP3P(MCInst &Inst, const OperandVector &Operands,
1960 OptionalImmIndexMap &OptionalIdx);
1961
1962 void cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands);
1963 void cvtVINTERP(MCInst &Inst, const OperandVector &Operands);
1964 void cvtOpSelHelper(MCInst &Inst, unsigned OpSel);
1965
1966 bool parseDimId(unsigned &Encoding);
1967 ParseStatus parseDim(OperandVector &Operands);
1968 bool convertDppBoundCtrl(int64_t &BoundCtrl);
1969 ParseStatus parseDPP8(OperandVector &Operands);
1970 ParseStatus parseDPPCtrl(OperandVector &Operands);
1971 bool isSupportedDPPCtrl(StringRef Ctrl, const OperandVector &Operands);
1972 int64_t parseDPPCtrlSel(StringRef Ctrl);
1973 int64_t parseDPPCtrlPerm();
1974 void cvtDPP(MCInst &Inst, const OperandVector &Operands, bool IsDPP8 = false);
1975 void cvtDPP8(MCInst &Inst, const OperandVector &Operands) {
1976 cvtDPP(Inst, Operands, true);
1977 }
1978 void cvtVOP3DPP(MCInst &Inst, const OperandVector &Operands,
1979 bool IsDPP8 = false);
1980 void cvtVOP3DPP8(MCInst &Inst, const OperandVector &Operands) {
1981 cvtVOP3DPP(Inst, Operands, true);
1982 }
1983
1984 ParseStatus parseSDWASel(OperandVector &Operands, StringRef Prefix,
1985 AMDGPUOperand::ImmTy Type);
1986 ParseStatus parseSDWADstUnused(OperandVector &Operands);
1987 void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands);
1988 void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands);
1989 void cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands);
1990 void cvtSdwaVOP2e(MCInst &Inst, const OperandVector &Operands);
1991 void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands);
1992
1993 enum class SDWAInstType : unsigned { VOP1 = 0, VOP2 = 1, VOPC = 2 };
1994
1995 void cvtSDWA(MCInst &Inst, const OperandVector &Operands,
1996 SDWAInstType BasicInstType, bool SkipDstVcc = false,
1997 bool SkipSrcVcc = false);
1998
1999 ParseStatus parseEndpgm(OperandVector &Operands);
2000
2001 ParseStatus parseVOPD(OperandVector &Operands);
2002};
2003
2004} // end anonymous namespace
2005
2006// May be called with integer type with equivalent bitwidth.
2007static const fltSemantics *getFltSemantics(unsigned Size) {
2008 switch (Size) {
2009 case 4:
2010 return &APFloat::IEEEsingle();
2011 case 8:
2012 return &APFloat::IEEEdouble();
2013 case 2:
2014 return &APFloat::IEEEhalf();
2015 default:
2016 llvm_unreachable("unsupported fp type");
2017 }
2018}
2019
2021 return getFltSemantics(VT.getScalarSizeInBits() / 8);
2022}
2023
2025 switch (OperandType) {
2026 // When floating-point immediate is used as operand of type i16, the 32-bit
2027 // representation of the constant truncated to the 16 LSBs should be used.
2042 return &APFloat::IEEEsingle();
2051 return &APFloat::IEEEdouble();
2059 return &APFloat::IEEEhalf();
2064 return &APFloat::BFloat();
2065 default:
2066 llvm_unreachable("unsupported fp type");
2067 }
2068}
2069
2070//===----------------------------------------------------------------------===//
2071// Operand
2072//===----------------------------------------------------------------------===//
2073
2074static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) {
2075 bool Lost;
2076
2077 // Convert literal to single precision
2078 APFloat::opStatus Status = FPLiteral.convert(
2080 // We allow precision lost but not overflow or underflow
2081 if (Status != APFloat::opOK && Lost &&
2082 ((Status & APFloat::opOverflow) != 0 ||
2083 (Status & APFloat::opUnderflow) != 0)) {
2084 return false;
2085 }
2086
2087 return true;
2088}
2089
2090static bool isSafeTruncation(int64_t Val, unsigned Size) {
2091 return isUIntN(Size, Val) || isIntN(Size, Val);
2092}
2093
2094static bool isInlineableLiteralOp16(int64_t Val, MVT VT, bool HasInv2Pi) {
2095 if (VT.getScalarType() == MVT::i16)
2096 return isInlinableLiteral32(Val, HasInv2Pi);
2097
2098 if (VT.getScalarType() == MVT::f16)
2099 return AMDGPU::isInlinableLiteralFP16(Val, HasInv2Pi);
2100
2101 assert(VT.getScalarType() == MVT::bf16);
2102
2103 return AMDGPU::isInlinableLiteralBF16(Val, HasInv2Pi);
2104}
2105
2106bool AMDGPUOperand::isInlinableImm(MVT type) const {
2107
2108 // This is a hack to enable named inline values like
2109 // shared_base with both 32-bit and 64-bit operands.
2110 // Note that these values are defined as
2111 // 32-bit operands only.
2112 if (isInlineValue()) {
2113 return true;
2114 }
2115
2116 if (!isImmTy(ImmTyNone)) {
2117 // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
2118 return false;
2119 }
2120
2121 if (getModifiers().Lit != LitModifier::None)
2122 return false;
2123
2124 // TODO: We should avoid using host float here. It would be better to
2125 // check the float bit values which is what a few other places do.
2126 // We've had bot failures before due to weird NaN support on mips hosts.
2127
2128 APInt Literal(64, Imm.Val);
2129
2130 if (Imm.IsFPImm) { // We got fp literal token
2131 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
2133 AsmParser->hasInv2PiInlineImm());
2134 }
2135
2136 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
2137 if (!canLosslesslyConvertToFPType(FPLiteral, type))
2138 return false;
2139
2140 if (type.getScalarSizeInBits() == 16) {
2141 bool Lost = false;
2142 switch (type.getScalarType().SimpleTy) {
2143 default:
2144 llvm_unreachable("unknown 16-bit type");
2145 case MVT::bf16:
2146 FPLiteral.convert(APFloatBase::BFloat(), APFloat::rmNearestTiesToEven,
2147 &Lost);
2148 break;
2149 case MVT::f16:
2150 FPLiteral.convert(APFloatBase::IEEEhalf(), APFloat::rmNearestTiesToEven,
2151 &Lost);
2152 break;
2153 case MVT::i16:
2154 FPLiteral.convert(APFloatBase::IEEEsingle(),
2155 APFloat::rmNearestTiesToEven, &Lost);
2156 break;
2157 }
2158 // We need to use 32-bit representation here because when a floating-point
2159 // inline constant is used as an i16 operand, its 32-bit representation
2160 // representation will be used. We will need the 32-bit value to check if
2161 // it is FP inline constant.
2162 uint32_t ImmVal = FPLiteral.bitcastToAPInt().getZExtValue();
2163 return isInlineableLiteralOp16(ImmVal, type,
2164 AsmParser->hasInv2PiInlineImm());
2165 }
2166
2167 // Check if single precision literal is inlinable
2169 static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
2170 AsmParser->hasInv2PiInlineImm());
2171 }
2172
2173 // We got int literal token.
2174 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
2176 AsmParser->hasInv2PiInlineImm());
2177 }
2178
2179 if (!isSafeTruncation(Imm.Val, type.getScalarSizeInBits())) {
2180 return false;
2181 }
2182
2183 if (type.getScalarSizeInBits() == 16) {
2185 static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()), type,
2186 AsmParser->hasInv2PiInlineImm());
2187 }
2188
2190 static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()),
2191 AsmParser->hasInv2PiInlineImm());
2192}
2193
2194bool AMDGPUOperand::isLiteralImm(MVT type) const {
2195 // Check that this immediate can be added as literal
2196 if (!isImmTy(ImmTyNone)) {
2197 return false;
2198 }
2199
2200 bool Allow64Bit =
2201 (type == MVT::i64 || type == MVT::f64) && AsmParser->has64BitLiterals();
2202
2203 if (!Imm.IsFPImm) {
2204 // We got int literal token.
2205
2206 if (type == MVT::f64 && hasFPModifiers()) {
2207 // Cannot apply fp modifiers to int literals preserving the same semantics
2208 // for VOP1/2/C and VOP3 because of integer truncation. To avoid
2209 // ambiguity, disable these cases.
2210 return false;
2211 }
2212
2213 unsigned Size = type.getSizeInBits();
2214 if (Size == 64) {
2215 if (Allow64Bit && !AMDGPU::isValid32BitLiteral(Imm.Val, false))
2216 return true;
2217 Size = 32;
2218 }
2219
2220 // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP
2221 // types.
2222 return isSafeTruncation(Imm.Val, Size);
2223 }
2224
2225 // We got fp literal token
2226 if (type == MVT::f64) { // Expected 64-bit fp operand
2227 // We would set low 64-bits of literal to zeroes but we accept this literals
2228 return true;
2229 }
2230
2231 if (type == MVT::i64) { // Expected 64-bit int operand
2232 // We don't allow fp literals in 64-bit integer instructions. It is
2233 // unclear how we should encode them.
2234 return false;
2235 }
2236
2237 // We allow fp literals with f16x2 operands assuming that the specified
2238 // literal goes into the lower half and the upper half is zero. We also
2239 // require that the literal may be losslessly converted to f16.
2240 //
2241 // For i16x2 operands, we assume that the specified literal is encoded as a
2242 // single-precision float. This is pretty odd, but it matches SP3 and what
2243 // happens in hardware.
2244 MVT ExpectedType = (type == MVT::v2f16) ? MVT::f16
2245 : (type == MVT::v2i16) ? MVT::f32
2246 : (type == MVT::v2f32) ? MVT::f32
2247 : type;
2248
2249 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
2250 return canLosslesslyConvertToFPType(FPLiteral, ExpectedType);
2251}
2252
2253bool AMDGPUOperand::isRegClass(unsigned RCID) const {
2254 return isRegKind() &&
2255 AsmParser->getMRI()->getRegClass(RCID).contains(getReg());
2256}
2257
2258bool AMDGPUOperand::isVRegWithInputMods() const {
2259 return isRegClass(AMDGPU::VGPR_32RegClassID) ||
2260 // GFX90A allows DPP on 64-bit operands.
2261 (isRegClass(AMDGPU::VReg_64RegClassID) &&
2262 AsmParser->getFeatureBits()[AMDGPU::FeatureDPALU_DPP]);
2263}
2264
2265template <bool IsFake16>
2266bool AMDGPUOperand::isT16_Lo128VRegWithInputMods() const {
2267 return isRegClass(IsFake16 ? AMDGPU::VGPR_32_Lo128RegClassID
2268 : AMDGPU::VGPR_16_Lo128RegClassID);
2269}
2270
2271template <bool IsFake16> bool AMDGPUOperand::isT16VRegWithInputMods() const {
2272 return isRegClass(IsFake16 ? AMDGPU::VGPR_32RegClassID
2273 : AMDGPU::VGPR_16RegClassID);
2274}
2275
2276bool AMDGPUOperand::isSDWAOperand(MVT type) const {
2277 if (AsmParser->isVI())
2278 return isVReg32();
2279 if (AsmParser->isGFX9Plus())
2280 return isRegClass(AMDGPU::VS_32RegClassID) || isInlinableImm(type);
2281 return false;
2282}
2283
2284bool AMDGPUOperand::isSDWAFP16Operand() const {
2285 return isSDWAOperand(MVT::f16);
2286}
2287
2288bool AMDGPUOperand::isSDWAFP32Operand() const {
2289 return isSDWAOperand(MVT::f32);
2290}
2291
2292bool AMDGPUOperand::isSDWAInt16Operand() const {
2293 return isSDWAOperand(MVT::i16);
2294}
2295
2296bool AMDGPUOperand::isSDWAInt32Operand() const {
2297 return isSDWAOperand(MVT::i32);
2298}
2299
2300bool AMDGPUOperand::isBoolReg() const {
2301 return isReg() && ((AsmParser->isWave64() && isSCSrc_b64()) ||
2302 (AsmParser->isWave32() && isSCSrc_b32()));
2303}
2304
2305uint64_t AMDGPUOperand::applyInputFPModifiers(uint64_t Val,
2306 unsigned Size) const {
2307 assert(isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
2308 assert(Size == 2 || Size == 4 || Size == 8);
2309
2310 const uint64_t FpSignMask = (1ULL << (Size * 8 - 1));
2311
2312 if (Imm.Mods.Abs) {
2313 Val &= ~FpSignMask;
2314 }
2315 if (Imm.Mods.Neg) {
2316 Val ^= FpSignMask;
2317 }
2318
2319 return Val;
2320}
2321
2322void AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N,
2323 bool ApplyModifiers) const {
2324 MCOpIdx = Inst.getNumOperands();
2325
2326 if (isExpr()) {
2328 return;
2329 }
2330
2331 if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()),
2332 Inst.getNumOperands())) {
2333 addLiteralImmOperand(Inst, Imm.Val,
2334 ApplyModifiers & isImmTy(ImmTyNone) &&
2335 Imm.Mods.hasFPModifiers());
2336 } else {
2337 assert(!isImmTy(ImmTyNone) || !hasModifiers());
2339 }
2340}
2341
2342void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val,
2343 bool ApplyModifiers) const {
2344 const auto &InstDesc = AsmParser->getMII()->get(Inst.getOpcode());
2345 auto OpNum = Inst.getNumOperands();
2346 // Check that this operand accepts literals
2347 assert(AMDGPU::isSISrcOperand(InstDesc, OpNum));
2348
2349 if (ApplyModifiers) {
2350 assert(AMDGPU::isSISrcFPOperand(InstDesc, OpNum));
2351 const unsigned Size =
2352 Imm.IsFPImm ? sizeof(double) : getOperandSize(InstDesc, OpNum);
2353 Val = applyInputFPModifiers(Val, Size);
2354 }
2355
2356 APInt Literal(64, Val);
2357 uint8_t OpTy = InstDesc.operands()[OpNum].OperandType;
2358
2359 bool CanUse64BitLiterals =
2360 AsmParser->has64BitLiterals() && !SIInstrFlags::isVOP3Like(InstDesc);
2361 LitModifier Lit = getModifiers().Lit;
2362 MCContext &Ctx = AsmParser->getContext();
2363
2364 if (Imm.IsFPImm) { // We got fp literal token
2365 switch (OpTy) {
2373 if (Lit == LitModifier::None &&
2375 AsmParser->hasInv2PiInlineImm())) {
2376 Inst.addOperand(MCOperand::createImm(Literal.getZExtValue()));
2377 return;
2378 }
2379
2380 // Non-inlineable
2381 if (AMDGPU::isSISrcFPOperand(InstDesc,
2382 OpNum)) { // Expected 64-bit fp operand
2383 bool HasMandatoryLiteral =
2384 AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::imm);
2385 // For fp operands we check if low 32 bits are zeros
2386 if (Literal.getLoBits(32) != 0 &&
2387 (InstDesc.getSize() != 4 || !AsmParser->has64BitLiterals()) &&
2388 !HasMandatoryLiteral) {
2389 const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(
2390 Inst.getLoc(),
2391 "Can't encode literal as exact 64-bit floating-point operand. "
2392 "Low 32-bits will be set to zero");
2393 Val &= 0xffffffff00000000u;
2394 }
2395
2396 if ((OpTy == AMDGPU::OPERAND_REG_IMM_FP64 ||
2399 if (CanUse64BitLiterals && Lit == LitModifier::None &&
2400 (isInt<32>(Val) || isUInt<32>(Val))) {
2401 // The floating-point operand will be verbalized as an
2402 // integer one. If that integer happens to fit 32 bits, on
2403 // re-assembling it will be intepreted as the high half of
2404 // the actual value, so we have to wrap it into lit64().
2405 Lit = LitModifier::Lit64;
2406 } else if (Lit == LitModifier::Lit) {
2407 // For FP64 operands lit() specifies the high half of the value.
2408 Val = Hi_32(Val);
2409 }
2410 }
2411 break;
2412 }
2413
2414 // We don't allow fp literals in 64-bit integer instructions. It is
2415 // unclear how we should encode them. This case should be checked earlier
2416 // in predicate methods (isLiteralImm())
2417 llvm_unreachable("fp literal in 64-bit integer instruction.");
2418
2420 if (CanUse64BitLiterals && Lit == LitModifier::None &&
2421 (isInt<32>(Val) || isUInt<32>(Val)))
2422 Lit = LitModifier::Lit64;
2423 break;
2424
2429 if (Lit == LitModifier::None && AsmParser->hasInv2PiInlineImm() &&
2430 Literal == 0x3fc45f306725feed) {
2431 // This is the 1/(2*pi) which is going to be truncated to bf16 with the
2432 // loss of precision. The constant represents ideomatic fp32 value of
2433 // 1/(2*pi) = 0.15915494 since bf16 is in fact fp32 with cleared low 16
2434 // bits. Prevent rounding below.
2435 Inst.addOperand(MCOperand::createImm(0x3e22));
2436 return;
2437 }
2438 [[fallthrough]];
2439
2461 bool lost;
2462 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
2463 // Convert literal to single precision
2464 FPLiteral.convert(*getOpFltSemantics(OpTy), APFloat::rmNearestTiesToEven,
2465 &lost);
2466 // We allow precision lost but not overflow or underflow. This should be
2467 // checked earlier in isLiteralImm()
2468
2469 Val = FPLiteral.bitcastToAPInt().getZExtValue();
2470 break;
2471 }
2472 default:
2473 llvm_unreachable("invalid operand size");
2474 }
2475
2476 if (Lit != LitModifier::None) {
2477 Inst.addOperand(
2479 } else {
2481 }
2482 return;
2483 }
2484
2485 // We got int literal token.
2486 // Only sign extend inline immediates.
2487 switch (OpTy) {
2502 break;
2503
2507 if (Lit == LitModifier::None &&
2508 AMDGPU::isInlinableLiteral64(Val, AsmParser->hasInv2PiInlineImm())) {
2510 return;
2511 }
2512
2513 // When the 32 MSBs are not zero (effectively means it can't be safely
2514 // truncated to uint32_t), if the target doesn't support 64-bit literals, or
2515 // the lit modifier is explicitly used, we need to truncate it to the 32
2516 // LSBs.
2517 if (!AsmParser->has64BitLiterals() || Lit == LitModifier::Lit)
2518 Val = Lo_32(Val);
2519 break;
2520
2525 if (Lit == LitModifier::None &&
2526 AMDGPU::isInlinableLiteral64(Val, AsmParser->hasInv2PiInlineImm())) {
2528 return;
2529 }
2530
2531 // If the target doesn't support 64-bit literals, we need to use the
2532 // constant as the high 32 MSBs of a double-precision floating point value.
2533 if (!AsmParser->has64BitLiterals()) {
2534 Val = static_cast<uint64_t>(Val) << 32;
2535 } else {
2536 // Now the target does support 64-bit literals, there are two cases
2537 // where we still want to use src_literal encoding:
2538 // 1) explicitly forced by using lit modifier;
2539 // 2) the value is a valid 32-bit representation (signed or unsigned),
2540 // meanwhile not forced by lit64 modifier.
2541 if (Lit == LitModifier::Lit ||
2542 (Lit != LitModifier::Lit64 && (isInt<32>(Val) || isUInt<32>(Val))))
2543 Val = static_cast<uint64_t>(Val) << 32;
2544 }
2545
2546 // For FP64 operands lit() specifies the high half of the value.
2547 if (Lit == LitModifier::Lit)
2548 Val = Hi_32(Val);
2549 break;
2550
2562 break;
2563
2565 if ((isInt<32>(Val) || isUInt<32>(Val)) && Lit != LitModifier::Lit64)
2566 Val <<= 32;
2567 break;
2568
2569 default:
2570 llvm_unreachable("invalid operand type");
2571 }
2572
2573 if (Lit != LitModifier::None) {
2574 Inst.addOperand(
2576 } else {
2578 }
2579}
2580
2581void AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const {
2582 MCOpIdx = Inst.getNumOperands();
2583 Inst.addOperand(
2584 MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI())));
2585}
2586
2587bool AMDGPUOperand::isInlineValue() const {
2588 return isRegKind() && ::isInlineValue(getReg());
2589}
2590
2591//===----------------------------------------------------------------------===//
2592// AsmParser
2593//===----------------------------------------------------------------------===//
2594
2595void AMDGPUAsmParser::createConstantSymbol(StringRef Id, int64_t Val) {
2596 // TODO: make those pre-defined variables read-only.
2597 // Currently there is none suitable machinery in the core llvm-mc for this.
2598 // MCSymbol::isRedefinable is intended for another purpose, and
2599 // AsmParser::parseDirectiveSet() cannot be specialized for specific target.
2600 MCContext &Ctx = getContext();
2601 MCSymbol *Sym = Ctx.getOrCreateSymbol(Id);
2603}
2604
2605static int getRegClass(RegisterKind Is, unsigned RegWidth) {
2606 if (Is == IS_VGPR) {
2607 switch (RegWidth) {
2608 default:
2609 return -1;
2610 case 32:
2611 return AMDGPU::VGPR_32RegClassID;
2612 case 64:
2613 return AMDGPU::VReg_64RegClassID;
2614 case 96:
2615 return AMDGPU::VReg_96RegClassID;
2616 case 128:
2617 return AMDGPU::VReg_128RegClassID;
2618 case 160:
2619 return AMDGPU::VReg_160RegClassID;
2620 case 192:
2621 return AMDGPU::VReg_192RegClassID;
2622 case 224:
2623 return AMDGPU::VReg_224RegClassID;
2624 case 256:
2625 return AMDGPU::VReg_256RegClassID;
2626 case 288:
2627 return AMDGPU::VReg_288RegClassID;
2628 case 320:
2629 return AMDGPU::VReg_320RegClassID;
2630 case 352:
2631 return AMDGPU::VReg_352RegClassID;
2632 case 384:
2633 return AMDGPU::VReg_384RegClassID;
2634 case 512:
2635 return AMDGPU::VReg_512RegClassID;
2636 case 1024:
2637 return AMDGPU::VReg_1024RegClassID;
2638 }
2639 } else if (Is == IS_TTMP) {
2640 switch (RegWidth) {
2641 default:
2642 return -1;
2643 case 32:
2644 return AMDGPU::TTMP_32RegClassID;
2645 case 64:
2646 return AMDGPU::TTMP_64RegClassID;
2647 case 128:
2648 return AMDGPU::TTMP_128RegClassID;
2649 case 256:
2650 return AMDGPU::TTMP_256RegClassID;
2651 case 512:
2652 return AMDGPU::TTMP_512RegClassID;
2653 }
2654 } else if (Is == IS_SGPR) {
2655 switch (RegWidth) {
2656 default:
2657 return -1;
2658 case 32:
2659 return AMDGPU::SGPR_32RegClassID;
2660 case 64:
2661 return AMDGPU::SGPR_64RegClassID;
2662 case 96:
2663 return AMDGPU::SGPR_96RegClassID;
2664 case 128:
2665 return AMDGPU::SGPR_128RegClassID;
2666 case 160:
2667 return AMDGPU::SGPR_160RegClassID;
2668 case 192:
2669 return AMDGPU::SGPR_192RegClassID;
2670 case 224:
2671 return AMDGPU::SGPR_224RegClassID;
2672 case 256:
2673 return AMDGPU::SGPR_256RegClassID;
2674 case 288:
2675 return AMDGPU::SGPR_288RegClassID;
2676 case 320:
2677 return AMDGPU::SGPR_320RegClassID;
2678 case 352:
2679 return AMDGPU::SGPR_352RegClassID;
2680 case 384:
2681 return AMDGPU::SGPR_384RegClassID;
2682 case 512:
2683 return AMDGPU::SGPR_512RegClassID;
2684 }
2685 } else if (Is == IS_AGPR) {
2686 switch (RegWidth) {
2687 default:
2688 return -1;
2689 case 32:
2690 return AMDGPU::AGPR_32RegClassID;
2691 case 64:
2692 return AMDGPU::AReg_64RegClassID;
2693 case 96:
2694 return AMDGPU::AReg_96RegClassID;
2695 case 128:
2696 return AMDGPU::AReg_128RegClassID;
2697 case 160:
2698 return AMDGPU::AReg_160RegClassID;
2699 case 192:
2700 return AMDGPU::AReg_192RegClassID;
2701 case 224:
2702 return AMDGPU::AReg_224RegClassID;
2703 case 256:
2704 return AMDGPU::AReg_256RegClassID;
2705 case 288:
2706 return AMDGPU::AReg_288RegClassID;
2707 case 320:
2708 return AMDGPU::AReg_320RegClassID;
2709 case 352:
2710 return AMDGPU::AReg_352RegClassID;
2711 case 384:
2712 return AMDGPU::AReg_384RegClassID;
2713 case 512:
2714 return AMDGPU::AReg_512RegClassID;
2715 case 1024:
2716 return AMDGPU::AReg_1024RegClassID;
2717 }
2718 }
2719 return -1;
2720}
2721
2724 .Case("exec", AMDGPU::EXEC)
2725 .Case("vcc", AMDGPU::VCC)
2726 .Case("flat_scratch", AMDGPU::FLAT_SCR)
2727 .Case("xnack_mask", AMDGPU::XNACK_MASK)
2728 .Case("shared_base", AMDGPU::SRC_SHARED_BASE)
2729 .Case("src_shared_base", AMDGPU::SRC_SHARED_BASE)
2730 .Case("shared_limit", AMDGPU::SRC_SHARED_LIMIT)
2731 .Case("src_shared_limit", AMDGPU::SRC_SHARED_LIMIT)
2732 .Case("private_base", AMDGPU::SRC_PRIVATE_BASE)
2733 .Case("src_private_base", AMDGPU::SRC_PRIVATE_BASE)
2734 .Case("private_limit", AMDGPU::SRC_PRIVATE_LIMIT)
2735 .Case("src_private_limit", AMDGPU::SRC_PRIVATE_LIMIT)
2736 .Case("src_flat_scratch_base_lo", AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)
2737 .Case("src_flat_scratch_base_hi", AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)
2738 .Case("pops_exiting_wave_id", AMDGPU::SRC_POPS_EXITING_WAVE_ID)
2739 .Case("src_pops_exiting_wave_id", AMDGPU::SRC_POPS_EXITING_WAVE_ID)
2740 .Case("lds_direct", AMDGPU::LDS_DIRECT)
2741 .Case("src_lds_direct", AMDGPU::LDS_DIRECT)
2742 .Case("m0", AMDGPU::M0)
2743 .Case("vccz", AMDGPU::SRC_VCCZ)
2744 .Case("src_vccz", AMDGPU::SRC_VCCZ)
2745 .Case("execz", AMDGPU::SRC_EXECZ)
2746 .Case("src_execz", AMDGPU::SRC_EXECZ)
2747 .Case("scc", AMDGPU::SRC_SCC)
2748 .Case("src_scc", AMDGPU::SRC_SCC)
2749 .Case("tba", AMDGPU::TBA)
2750 .Case("tma", AMDGPU::TMA)
2751 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
2752 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
2753 .Case("xnack_mask_lo", AMDGPU::XNACK_MASK_LO)
2754 .Case("xnack_mask_hi", AMDGPU::XNACK_MASK_HI)
2755 .Case("vcc_lo", AMDGPU::VCC_LO)
2756 .Case("vcc_hi", AMDGPU::VCC_HI)
2757 .Case("exec_lo", AMDGPU::EXEC_LO)
2758 .Case("exec_hi", AMDGPU::EXEC_HI)
2759 .Case("tma_lo", AMDGPU::TMA_LO)
2760 .Case("tma_hi", AMDGPU::TMA_HI)
2761 .Case("tba_lo", AMDGPU::TBA_LO)
2762 .Case("tba_hi", AMDGPU::TBA_HI)
2763 .Case("pc", AMDGPU::PC_REG)
2764 .Case("null", AMDGPU::SGPR_NULL)
2765 .Default(AMDGPU::NoRegister);
2766}
2767
2768bool AMDGPUAsmParser::ParseRegister(MCRegister &RegNo, SMLoc &StartLoc,
2769 SMLoc &EndLoc, bool RestoreOnFailure) {
2770 auto R = parseRegister();
2771 if (!R)
2772 return true;
2773 assert(R->isReg());
2774 RegNo = R->getReg();
2775 StartLoc = R->getStartLoc();
2776 EndLoc = R->getEndLoc();
2777 return false;
2778}
2779
2780bool AMDGPUAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
2781 SMLoc &EndLoc) {
2782 return ParseRegister(Reg, StartLoc, EndLoc, /*RestoreOnFailure=*/false);
2783}
2784
2785ParseStatus AMDGPUAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
2786 SMLoc &EndLoc) {
2787 bool Result = ParseRegister(Reg, StartLoc, EndLoc, /*RestoreOnFailure=*/true);
2788 bool PendingErrors = getParser().hasPendingError();
2789 getParser().clearPendingErrors();
2790 if (PendingErrors)
2791 return ParseStatus::Failure;
2792 if (Result)
2793 return ParseStatus::NoMatch;
2794 return ParseStatus::Success;
2795}
2796
2797bool AMDGPUAsmParser::AddNextRegisterToList(MCRegister &Reg, unsigned &RegWidth,
2798 RegisterKind RegKind,
2799 MCRegister Reg1,
2800 RegisterKind RegKind1, SMLoc Loc) {
2801 // Allow VCC_LO/HI at the end of SGPR lists.
2802 if (RegKind == IS_SGPR) {
2803 unsigned RegIdx = (Reg - AMDGPU::SGPR0) + RegWidth / 32;
2804 if ((RegIdx == 106 && Reg1 == AMDGPU::VCC_LO) ||
2805 (RegIdx == 107 && Reg1 == AMDGPU::VCC_HI)) {
2806 RegWidth += 32;
2807 return true;
2808 }
2809 }
2810
2811 if (RegKind != RegKind1) {
2812 Error(Loc, "registers in a list must be of the same kind");
2813 return 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.
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
5794 uint64_t InvalidOprIdx) {
5795 assert(InvalidOprIdx < Operands.size());
5796 const auto &Op = ((AMDGPUOperand &)*Operands[InvalidOprIdx]);
5797 if (Op.isToken() && InvalidOprIdx > 1) {
5798 const auto &PrevOp = ((AMDGPUOperand &)*Operands[InvalidOprIdx - 1]);
5799 return PrevOp.isToken() && PrevOp.getToken() == "::";
5800 }
5801 return false;
5802}
5803
5804bool AMDGPUAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5806 MCStreamer &Out,
5807 uint64_t &ErrorInfo,
5808 bool MatchingInlineAsm) {
5809 MCInst Inst;
5810 Inst.setLoc(IDLoc);
5811 unsigned Result = Match_Success;
5812 for (auto Variant : getMatchedVariants()) {
5813 uint64_t EI;
5814 auto R =
5815 MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm, Variant);
5816 // We order match statuses from least to most specific. We use most specific
5817 // status as resulting
5818 // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature
5819 if (R == Match_Success || R == Match_MissingFeature ||
5820 (R == Match_InvalidOperand && Result != Match_MissingFeature) ||
5821 (R == Match_MnemonicFail && Result != Match_InvalidOperand &&
5822 Result != Match_MissingFeature)) {
5823 Result = R;
5824 ErrorInfo = EI;
5825 }
5826 if (R == Match_Success)
5827 break;
5828 }
5829
5830 if (Result == Match_Success) {
5831 if (!validateInstruction(Inst, IDLoc, Operands)) {
5832 return true;
5833 }
5834 emitTargetDirective();
5835 Out.emitInstruction(Inst, getSTI());
5836 // Record for kernel prologue checking.
5837 OpcodeStream.push_back(Inst.getOpcode());
5838 return false;
5839 }
5840
5841 StringRef Mnemo = ((AMDGPUOperand &)*Operands[0]).getToken();
5842 if (checkUnsupportedInstruction(Mnemo, IDLoc)) {
5843 return true;
5844 }
5845
5846 switch (Result) {
5847 default:
5848 break;
5849 case Match_MissingFeature:
5850 // It has been verified that the specified instruction
5851 // mnemonic is valid. A match was found but it requires
5852 // features which are not supported on this GPU.
5853 return Error(IDLoc, "operands are not valid for this GPU or mode");
5854
5855 case Match_InvalidOperand: {
5856 SMLoc ErrorLoc = IDLoc;
5857 if (ErrorInfo != ~0ULL) {
5858 if (ErrorInfo >= Operands.size()) {
5859 return Error(IDLoc, "too few operands for instruction");
5860 }
5861 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
5862 if (ErrorLoc == SMLoc())
5863 ErrorLoc = IDLoc;
5864
5865 if (isInvalidVOPDY(Operands, ErrorInfo))
5866 return Error(ErrorLoc, "invalid VOPDY instruction");
5867 }
5868 return Error(ErrorLoc, "invalid operand for instruction");
5869 }
5870
5871 case Match_MnemonicFail:
5872 llvm_unreachable("Invalid instructions should have been handled already");
5873 }
5874 llvm_unreachable("Implement any new match types added!");
5875}
5876
5877bool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) {
5878 int64_t Tmp = -1;
5879 if (!isToken(AsmToken::Integer) && !isToken(AsmToken::Identifier)) {
5880 return true;
5881 }
5882 if (getParser().parseAbsoluteExpression(Tmp)) {
5883 return true;
5884 }
5885 Ret = static_cast<uint32_t>(Tmp);
5886 return false;
5887}
5888
5889bool AMDGPUAsmParser::ParseDirectiveAMDGCNTarget() {
5890 if (!getSTI().getTargetTriple().isAMDGCN())
5891 return TokError("directive only supported for amdgcn architecture");
5892
5893 std::string TargetIDDirective;
5894 SMLoc TargetStart = getTok().getLoc();
5895 if (getParser().parseEscapedString(TargetIDDirective))
5896 return true;
5897
5898 std::optional<AMDGPU::TargetID> MaybeParsed =
5899 AMDGPU::TargetID::parseTargetIDString(TargetIDDirective);
5900 if (!MaybeParsed)
5901 return getParser().Error(TargetStart,
5902 "malformed target id '" + TargetIDDirective + "'");
5903
5904 const AMDGPU::TargetID &ParsedTargetID = *MaybeParsed;
5905 const Triple &TT = getSTI().getTargetTriple();
5906
5907 // The processor named in the target id must be covered by the triple's
5908 // subarch.
5909 if (!AMDGPU::isCPUValidForSubArch(TT.getSubArch(),
5910 ParsedTargetID.getGPUKind())) {
5911 return getParser().Error(
5912 TargetStart, "target id '" + TargetIDDirective +
5913 "' specifies a processor that is not valid for "
5914 "subarch '" +
5915 TT.getArchName() + "'");
5916 }
5917
5918 const std::optional<AMDGPU::TargetID> &CurrentTargetID =
5919 getTargetStreamer().getTargetID();
5920
5921 Triple DirectiveTriple(ParsedTargetID.getTargetTripleString());
5922 const Triple &STITriple = getSTI().getTargetTriple();
5923 if (!DirectiveTriple.isCompatibleWith(STITriple)) {
5924 return getParser().Error(
5925 TargetStart, ".amdgcn_target " + Twine(ParsedTargetID.toString()) +
5926 " is incompatible with " +
5927 Twine(CurrentTargetID->toString()));
5928 }
5929
5930 // Error if the ISA version doesn't match
5931 StringRef DirectiveProcessor =
5932 AMDGPU::getArchNameAMDGCN(ParsedTargetID.getGPUKind());
5933 AMDGPU::IsaVersion DirectiveISA = AMDGPU::getIsaVersion(DirectiveProcessor);
5934 if (DirectiveISA != ISA) {
5935 return getParser().Error(TargetStart,
5936 ".amdgcn_target directive processor " +
5937 Twine(DirectiveProcessor) +
5938 " does not match the specified processor " +
5939 Twine(getSTI().getCPU()));
5940 }
5941
5942 // Warn if sramecc or xnack mismatch. These do not change the encoding.
5944 ParsedTargetID.getXnackSetting(),
5945 CurrentTargetID->getXnackSetting())) {
5946 Warning(TargetStart,
5947 ".amdgcn_target directive has conflicting xnack settings");
5948 }
5950 ParsedTargetID.getSramEccSetting(),
5951 CurrentTargetID->getSramEccSetting())) {
5952 Warning(TargetStart,
5953 ".amdgcn_target directive has conflicting sramecc settings");
5954 }
5955
5956 // Update the target streamer's TargetID with settings from the directive.
5957 // We don't update the MCSubtargetInfo because we've already validated
5958 // that the directive matches the command-line CPU.
5959 getTargetStreamer().getTargetID()->setXnackSetting(
5960 ParsedTargetID.getXnackSetting());
5961 getTargetStreamer().getTargetID()->setSramEccSetting(
5962 ParsedTargetID.getSramEccSetting());
5963
5964 return false;
5965}
5966
5967bool AMDGPUAsmParser::OutOfRangeError(SMRange Range) {
5968 return Error(Range.Start, "value out of range", Range);
5969}
5970
5971bool AMDGPUAsmParser::calculateGPRBlocks(
5972 const FeatureBitset &Features, const MCExpr *VCCUsed,
5973 const MCExpr *FlatScrUsed, bool XNACKUsed,
5974 std::optional<bool> EnableWavefrontSize32, const MCExpr *NextFreeVGPR,
5975 SMRange VGPRRange, const MCExpr *NextFreeSGPR, SMRange SGPRRange,
5976 const MCExpr *&VGPRBlocks, const MCExpr *&SGPRBlocks) {
5977 // TODO(scott.linder): These calculations are duplicated from
5978 // AMDGPUAsmPrinter::getSIProgramInfo and could be unified.
5979 MCContext &Ctx = getContext();
5980
5981 const MCExpr *NumSGPRs = NextFreeSGPR;
5982 int64_t EvaluatedSGPRs;
5983
5984 if (ISA.Major >= 10)
5986 else {
5987 unsigned MaxAddressableNumSGPRs = AMDGPU::getAddressableNumSGPRs(Gfx);
5988
5989 if (NumSGPRs->evaluateAsAbsolute(EvaluatedSGPRs) && ISA.Major >= 8 &&
5990 !Features.test(FeatureSGPRInitBug) &&
5991 static_cast<uint64_t>(EvaluatedSGPRs) > MaxAddressableNumSGPRs)
5992 return OutOfRangeError(SGPRRange);
5993
5994 const MCExpr *ExtraSGPRs =
5995 AMDGPUMCExpr::createExtraSGPRs(VCCUsed, FlatScrUsed, XNACKUsed, Ctx);
5996 NumSGPRs = MCBinaryExpr::createAdd(NumSGPRs, ExtraSGPRs, Ctx);
5997
5998 if (NumSGPRs->evaluateAsAbsolute(EvaluatedSGPRs) &&
5999 (ISA.Major <= 7 || Features.test(FeatureSGPRInitBug)) &&
6000 static_cast<uint64_t>(EvaluatedSGPRs) > MaxAddressableNumSGPRs)
6001 return OutOfRangeError(SGPRRange);
6002
6003 if (Features.test(FeatureSGPRInitBug))
6004 NumSGPRs =
6006 }
6007
6008 // The MCExpr equivalent of getNumSGPRBlocks/getNumVGPRBlocks:
6009 // (alignTo(max(1u, NumGPR), GPREncodingGranule) / GPREncodingGranule) - 1
6010 auto GetNumGPRBlocks = [&Ctx](const MCExpr *NumGPR,
6011 unsigned Granule) -> const MCExpr * {
6012 const MCExpr *OneConst = MCConstantExpr::create(1ul, Ctx);
6013 const MCExpr *GranuleConst = MCConstantExpr::create(Granule, Ctx);
6014 const MCExpr *MaxNumGPR = AMDGPUMCExpr::createMax({NumGPR, OneConst}, Ctx);
6015 const MCExpr *AlignToGPR =
6016 AMDGPUMCExpr::createAlignTo(MaxNumGPR, GranuleConst, Ctx);
6017 const MCExpr *DivGPR =
6018 MCBinaryExpr::createDiv(AlignToGPR, GranuleConst, Ctx);
6019 const MCExpr *SubGPR = MCBinaryExpr::createSub(DivGPR, OneConst, Ctx);
6020 return SubGPR;
6021 };
6022
6023 VGPRBlocks = GetNumGPRBlocks(
6024 NextFreeVGPR,
6025 IsaInfo::getVGPREncodingGranule(getSTI(), EnableWavefrontSize32));
6026 SGPRBlocks =
6027 GetNumGPRBlocks(NumSGPRs, IsaInfo::getSGPREncodingGranule(getSTI()));
6028
6029 return false;
6030}
6031
6032bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() {
6033 if (!getSTI().getTargetTriple().isAMDGCN())
6034 return TokError("directive only supported for amdgcn architecture");
6035
6036 if (!isHsaAbi(getSTI()))
6037 return TokError("directive only supported for amdhsa OS");
6038
6039 StringRef KernelName;
6040 if (getParser().parseIdentifier(KernelName))
6041 return true;
6042
6043 // Remember the kernel name so its prologue can be checked at end of file.
6044 // The matching label may have been parsed already or may follow later.
6045 AMDHSAKernelSymbols.insert(getContext().getOrCreateSymbol(KernelName));
6046
6047 AMDGPU::MCKernelDescriptor KD =
6049 &getSTI(), getContext());
6050
6051 StringSet<> Seen;
6052
6053 const MCExpr *ZeroExpr = MCConstantExpr::create(0, getContext());
6054 const MCExpr *OneExpr = MCConstantExpr::create(1, getContext());
6055
6056 SMRange VGPRRange;
6057 const MCExpr *NextFreeVGPR = ZeroExpr;
6058 const MCExpr *AccumOffset = MCConstantExpr::create(0, getContext());
6059 const MCExpr *NamedBarCnt = ZeroExpr;
6060 uint64_t SharedVGPRCount = 0;
6061 uint64_t PreloadLength = 0;
6062 uint64_t PreloadOffset = 0;
6063 SMRange SGPRRange;
6064 const MCExpr *NextFreeSGPR = ZeroExpr;
6065
6066 // Count the number of user SGPRs implied from the enabled feature bits.
6067 unsigned ImpliedUserSGPRCount = 0;
6068
6069 // Track if the asm explicitly contains the directive for the user SGPR
6070 // count.
6071 std::optional<unsigned> ExplicitUserSGPRCount;
6072 const MCExpr *ReserveVCC = OneExpr;
6073 const MCExpr *ReserveFlatScr = OneExpr;
6074 std::optional<bool> EnableWavefrontSize32;
6075
6076 while (true) {
6077 while (trySkipToken(AsmToken::EndOfStatement))
6078 ;
6079
6080 StringRef ID;
6081 SMRange IDRange = getTok().getLocRange();
6082 if (!parseId(ID, "expected .amdhsa_ directive or .end_amdhsa_kernel"))
6083 return true;
6084
6085 if (ID == ".end_amdhsa_kernel")
6086 break;
6087
6088 if (!Seen.insert(ID).second)
6089 return TokError(".amdhsa_ directives cannot be repeated");
6090
6091 SMLoc ValStart = getLoc();
6092 const MCExpr *ExprVal;
6093 if (getParser().parseExpression(ExprVal))
6094 return true;
6095 SMLoc ValEnd = getLoc();
6096 SMRange ValRange = SMRange(ValStart, ValEnd);
6097
6098 int64_t IVal = 0;
6099 uint64_t Val = IVal;
6100 bool EvaluatableExpr;
6101 if ((EvaluatableExpr = ExprVal->evaluateAsAbsolute(IVal))) {
6102 if (IVal < 0)
6103 return OutOfRangeError(ValRange);
6104 Val = IVal;
6105 }
6106
6107#define PARSE_BITS_ENTRY(FIELD, ENTRY, VALUE, RANGE) \
6108 if (!isUInt<ENTRY##_WIDTH>(Val)) \
6109 return OutOfRangeError(RANGE); \
6110 AMDGPU::MCKernelDescriptor::bits_set(FIELD, VALUE, ENTRY##_SHIFT, ENTRY, \
6111 getContext());
6112
6113// Some fields use the parsed value immediately which requires the expression to
6114// be solvable.
6115#define EXPR_RESOLVE_OR_ERROR(RESOLVED) \
6116 if (!(RESOLVED)) \
6117 return Error(IDRange.Start, "directive should have resolvable expression", \
6118 IDRange);
6119
6120 if (ID == ".amdhsa_group_segment_fixed_size") {
6122 CHAR_BIT>(Val))
6123 return OutOfRangeError(ValRange);
6124 KD.group_segment_fixed_size = ExprVal;
6125 } else if (ID == ".amdhsa_private_segment_fixed_size") {
6127 CHAR_BIT>(Val))
6128 return OutOfRangeError(ValRange);
6129 KD.private_segment_fixed_size = ExprVal;
6130 } else if (ID == ".amdhsa_kernarg_size") {
6131 if (!isUInt<sizeof(kernel_descriptor_t::kernarg_size) * CHAR_BIT>(Val))
6132 return OutOfRangeError(ValRange);
6133 KD.kernarg_size = ExprVal;
6134 } else if (ID == ".amdhsa_user_sgpr_count") {
6135 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6136 ExplicitUserSGPRCount = Val;
6137 } else if (ID == ".amdhsa_user_sgpr_private_segment_buffer") {
6138 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6140 return Error(IDRange.Start,
6141 "directive is not supported with architected flat scratch",
6142 IDRange);
6144 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER,
6145 ExprVal, ValRange);
6146 if (Val)
6147 ImpliedUserSGPRCount += 4;
6148 } else if (ID == ".amdhsa_user_sgpr_kernarg_preload_length") {
6149 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6150 if (!hasKernargPreload())
6151 return Error(IDRange.Start, "directive requires gfx90a+", IDRange);
6152
6153 if (Val > getMaxNumUserSGPRs())
6154 return OutOfRangeError(ValRange);
6155 PARSE_BITS_ENTRY(KD.kernarg_preload, KERNARG_PRELOAD_SPEC_LENGTH, ExprVal,
6156 ValRange);
6157 if (Val) {
6158 ImpliedUserSGPRCount += Val;
6159 PreloadLength = Val;
6160 }
6161 } else if (ID == ".amdhsa_user_sgpr_kernarg_preload_offset") {
6162 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6163 if (!hasKernargPreload())
6164 return Error(IDRange.Start, "directive requires gfx90a+", IDRange);
6165
6166 if (Val >= 1024)
6167 return OutOfRangeError(ValRange);
6168 PARSE_BITS_ENTRY(KD.kernarg_preload, KERNARG_PRELOAD_SPEC_OFFSET, ExprVal,
6169 ValRange);
6170 if (Val)
6171 PreloadOffset = Val;
6172 } else if (ID == ".amdhsa_user_sgpr_dispatch_ptr") {
6173 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6175 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR, ExprVal,
6176 ValRange);
6177 if (Val)
6178 ImpliedUserSGPRCount += 2;
6179 } else if (ID == ".amdhsa_user_sgpr_queue_ptr") {
6180 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6182 KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR, ExprVal,
6183 ValRange);
6184 if (Val)
6185 ImpliedUserSGPRCount += 2;
6186 } else if (ID == ".amdhsa_user_sgpr_kernarg_segment_ptr") {
6187 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6189 KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR,
6190 ExprVal, ValRange);
6191 if (Val)
6192 ImpliedUserSGPRCount += 2;
6193 } else if (ID == ".amdhsa_user_sgpr_dispatch_id") {
6194 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6196 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID, ExprVal,
6197 ValRange);
6198 if (Val)
6199 ImpliedUserSGPRCount += 2;
6200 } else if (ID == ".amdhsa_user_sgpr_flat_scratch_init") {
6202 return Error(IDRange.Start,
6203 "directive is not supported with architected flat scratch",
6204 IDRange);
6205 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6207 KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT,
6208 ExprVal, ValRange);
6209 if (Val)
6210 ImpliedUserSGPRCount += 2;
6211 } else if (ID == ".amdhsa_user_sgpr_private_segment_size") {
6212 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6214 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE,
6215 ExprVal, ValRange);
6216 if (Val)
6217 ImpliedUserSGPRCount += 1;
6218 } else if (ID == ".amdhsa_wavefront_size32") {
6219 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6220 if (ISA.Major < 10)
6221 return Error(IDRange.Start, "directive requires gfx10+", IDRange);
6222 EnableWavefrontSize32 = Val;
6224 KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, ExprVal,
6225 ValRange);
6226 } else if (ID == ".amdhsa_uses_dynamic_stack") {
6228 KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK, ExprVal,
6229 ValRange);
6230 } else if (ID == ".amdhsa_system_sgpr_private_segment_wavefront_offset") {
6232 return Error(IDRange.Start,
6233 "directive is not supported with architected flat scratch",
6234 IDRange);
6236 COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, ExprVal,
6237 ValRange);
6238 } else if (ID == ".amdhsa_enable_private_segment") {
6240 return Error(
6241 IDRange.Start,
6242 "directive is not supported without architected flat scratch",
6243 IDRange);
6245 COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, ExprVal,
6246 ValRange);
6247 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_x") {
6249 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, ExprVal,
6250 ValRange);
6251 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_y") {
6253 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y, ExprVal,
6254 ValRange);
6255 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_z") {
6257 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z, ExprVal,
6258 ValRange);
6259 } else if (ID == ".amdhsa_system_sgpr_workgroup_info") {
6261 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO, ExprVal,
6262 ValRange);
6263 } else if (ID == ".amdhsa_system_vgpr_workitem_id") {
6265 COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID, ExprVal,
6266 ValRange);
6267 } else if (ID == ".amdhsa_next_free_vgpr") {
6268 VGPRRange = ValRange;
6269 NextFreeVGPR = ExprVal;
6270 } else if (ID == ".amdhsa_next_free_sgpr") {
6271 SGPRRange = ValRange;
6272 NextFreeSGPR = ExprVal;
6273 } else if (ID == ".amdhsa_accum_offset") {
6274 if (!isGFX90A())
6275 return Error(IDRange.Start, "directive requires gfx90a+", IDRange);
6276 AccumOffset = ExprVal;
6277 } else if (ID == ".amdhsa_named_barrier_count") {
6278 if (!isGFX1250Plus())
6279 return Error(IDRange.Start, "directive requires gfx1250+", IDRange);
6280 NamedBarCnt = ExprVal;
6281 } else if (ID == ".amdhsa_reserve_vcc") {
6282 if (EvaluatableExpr && !isUInt<1>(Val))
6283 return OutOfRangeError(ValRange);
6284 ReserveVCC = ExprVal;
6285 } else if (ID == ".amdhsa_reserve_flat_scratch") {
6286 if (ISA.Major < 7)
6287 return Error(IDRange.Start, "directive requires gfx7+", IDRange);
6289 return Error(IDRange.Start,
6290 "directive is not supported with architected flat scratch",
6291 IDRange);
6292 if (EvaluatableExpr && !isUInt<1>(Val))
6293 return OutOfRangeError(ValRange);
6294 ReserveFlatScr = ExprVal;
6295 } else if (ID == ".amdhsa_reserve_xnack_mask") {
6296 if (ISA.Major < 8)
6297 return Error(IDRange.Start, "directive requires gfx8+", IDRange);
6298 if (!isUInt<1>(Val))
6299 return OutOfRangeError(ValRange);
6300 bool XnackOn = getTargetStreamer().getTargetID()->isXnackOnOrAny() ||
6301 getSTI().hasFeature(AMDGPU::FeatureXNACK);
6302 if (Val != XnackOn) {
6303 return getParser().Error(
6304 IDRange.Start,
6305 ".amdhsa_reserve_xnack_mask does not match target id", IDRange);
6306 }
6307 } else if (ID == ".amdhsa_float_round_mode_32") {
6309 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32, ExprVal,
6310 ValRange);
6311 } else if (ID == ".amdhsa_float_round_mode_16_64") {
6313 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64, ExprVal,
6314 ValRange);
6315 } else if (ID == ".amdhsa_float_denorm_mode_32") {
6317 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32, ExprVal,
6318 ValRange);
6319 } else if (ID == ".amdhsa_float_denorm_mode_16_64") {
6321 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, ExprVal,
6322 ValRange);
6323 } else if (ID == ".amdhsa_dx10_clamp") {
6324 if (!getSTI().hasFeature(AMDGPU::FeatureDX10ClampAndIEEEMode))
6325 return Error(IDRange.Start, "directive unsupported on gfx1170+",
6326 IDRange);
6328 COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP, ExprVal,
6329 ValRange);
6330 } else if (ID == ".amdhsa_ieee_mode") {
6331 if (!getSTI().hasFeature(AMDGPU::FeatureDX10ClampAndIEEEMode))
6332 return Error(IDRange.Start, "directive unsupported on gfx1170+",
6333 IDRange);
6335 COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE, ExprVal,
6336 ValRange);
6337 } else if (ID == ".amdhsa_fp16_overflow") {
6338 if (ISA.Major < 9)
6339 return Error(IDRange.Start, "directive requires gfx9+", IDRange);
6341 COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL, ExprVal,
6342 ValRange);
6343 } else if (ID == ".amdhsa_tg_split") {
6344 if (!isGFX90A())
6345 return Error(IDRange.Start, "directive requires gfx90a+", IDRange);
6346 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc3, COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT,
6347 ExprVal, ValRange);
6348 } else if (ID == ".amdhsa_workgroup_processor_mode") {
6349 if (!supportsWGP(getSTI()))
6350 return Error(IDRange.Start,
6351 "directive unsupported on " + getSTI().getCPU(), IDRange);
6353 COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE, ExprVal,
6354 ValRange);
6355 } else if (ID == ".amdhsa_memory_ordered") {
6356 if (ISA.Major < 10)
6357 return Error(IDRange.Start, "directive requires gfx10+", IDRange);
6359 COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED, ExprVal,
6360 ValRange);
6361 } else if (ID == ".amdhsa_forward_progress") {
6362 if (ISA.Major < 10)
6363 return Error(IDRange.Start, "directive requires gfx10+", IDRange);
6365 COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS, ExprVal,
6366 ValRange);
6367 } else if (ID == ".amdhsa_shared_vgpr_count") {
6368 EXPR_RESOLVE_OR_ERROR(EvaluatableExpr);
6369 if (ISA.Major < 10 || ISA.Major >= 12)
6370 return Error(IDRange.Start, "directive requires gfx10 or gfx11",
6371 IDRange);
6372 SharedVGPRCount = Val;
6374 COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT, ExprVal,
6375 ValRange);
6376 } else if (ID == ".amdhsa_inst_pref_size") {
6377 if (ISA.Major < 11)
6378 return Error(IDRange.Start, "directive requires gfx11+", IDRange);
6379 if (ISA.Major == 11) {
6381 COMPUTE_PGM_RSRC3_GFX11_INST_PREF_SIZE, ExprVal,
6382 ValRange);
6383 } else {
6385 COMPUTE_PGM_RSRC3_GFX12_PLUS_INST_PREF_SIZE, ExprVal,
6386 ValRange);
6387 }
6388 } else if (ID == ".amdhsa_exception_fp_ieee_invalid_op") {
6391 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION,
6392 ExprVal, ValRange);
6393 } else if (ID == ".amdhsa_exception_fp_denorm_src") {
6395 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE,
6396 ExprVal, ValRange);
6397 } else if (ID == ".amdhsa_exception_fp_ieee_div_zero") {
6400 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO,
6401 ExprVal, ValRange);
6402 } else if (ID == ".amdhsa_exception_fp_ieee_overflow") {
6404 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW,
6405 ExprVal, ValRange);
6406 } else if (ID == ".amdhsa_exception_fp_ieee_underflow") {
6408 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW,
6409 ExprVal, ValRange);
6410 } else if (ID == ".amdhsa_exception_fp_ieee_inexact") {
6412 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT,
6413 ExprVal, ValRange);
6414 } else if (ID == ".amdhsa_exception_int_div_zero") {
6416 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO,
6417 ExprVal, ValRange);
6418 } else if (ID == ".amdhsa_round_robin_scheduling") {
6419 if (ISA.Major < 12)
6420 return Error(IDRange.Start, "directive requires gfx12+", IDRange);
6422 COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN, ExprVal,
6423 ValRange);
6424 } else {
6425 return Error(IDRange.Start, "unknown .amdhsa_kernel directive", IDRange);
6426 }
6427
6428#undef PARSE_BITS_ENTRY
6429 }
6430
6431 if (!Seen.contains(".amdhsa_next_free_vgpr"))
6432 return TokError(".amdhsa_next_free_vgpr directive is required");
6433
6434 if (!Seen.contains(".amdhsa_next_free_sgpr"))
6435 return TokError(".amdhsa_next_free_sgpr directive is required");
6436
6437 unsigned UserSGPRCount = ExplicitUserSGPRCount.value_or(ImpliedUserSGPRCount);
6438 if (UserSGPRCount > getMaxNumUserSGPRs())
6439 return TokError("too many user SGPRs enabled, found " +
6440 Twine(UserSGPRCount) + ", but only " +
6441 Twine(getMaxNumUserSGPRs()) + " are supported.");
6442
6443 // Consider the case where the total number of UserSGPRs with trailing
6444 // allocated preload SGPRs, is greater than the number of explicitly
6445 // referenced SGPRs.
6446 if (PreloadLength) {
6447 MCContext &Ctx = getContext();
6448 NextFreeSGPR = AMDGPUMCExpr::createMax(
6449 {NextFreeSGPR, MCConstantExpr::create(UserSGPRCount, Ctx)}, Ctx);
6450 }
6451
6452 const MCExpr *VGPRBlocks;
6453 const MCExpr *SGPRBlocks;
6454 if (calculateGPRBlocks(getFeatureBits(), ReserveVCC, ReserveFlatScr,
6455 getTargetStreamer().getTargetID()->isXnackOnOrAny(),
6456 EnableWavefrontSize32, NextFreeVGPR, VGPRRange,
6457 NextFreeSGPR, SGPRRange, VGPRBlocks, SGPRBlocks))
6458 return true;
6459
6460 int64_t EvaluatedVGPRBlocks;
6461 bool VGPRBlocksEvaluatable =
6462 VGPRBlocks->evaluateAsAbsolute(EvaluatedVGPRBlocks);
6463 if (VGPRBlocksEvaluatable &&
6465 static_cast<uint64_t>(EvaluatedVGPRBlocks))) {
6466 return OutOfRangeError(VGPRRange);
6467 }
6469 KD.compute_pgm_rsrc1, VGPRBlocks,
6470 COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT_SHIFT,
6471 COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT, getContext());
6472
6473 int64_t EvaluatedSGPRBlocks;
6474 if (SGPRBlocks->evaluateAsAbsolute(EvaluatedSGPRBlocks) &&
6476 static_cast<uint64_t>(EvaluatedSGPRBlocks)))
6477 return OutOfRangeError(SGPRRange);
6479 KD.compute_pgm_rsrc1, SGPRBlocks,
6480 COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT_SHIFT,
6481 COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT, getContext());
6482
6483 if (ExplicitUserSGPRCount && ImpliedUserSGPRCount > *ExplicitUserSGPRCount)
6484 return TokError("amdgpu_user_sgpr_count smaller than implied by "
6485 "enabled user SGPRs");
6486
6487 if (isGFX1250Plus()) {
6490 MCConstantExpr::create(UserSGPRCount, getContext()),
6491 COMPUTE_PGM_RSRC2_GFX125_USER_SGPR_COUNT_SHIFT,
6492 COMPUTE_PGM_RSRC2_GFX125_USER_SGPR_COUNT, getContext());
6493 } else {
6496 MCConstantExpr::create(UserSGPRCount, getContext()),
6497 COMPUTE_PGM_RSRC2_GFX6_GFX120_USER_SGPR_COUNT_SHIFT,
6498 COMPUTE_PGM_RSRC2_GFX6_GFX120_USER_SGPR_COUNT, getContext());
6499 }
6500
6501 int64_t IVal = 0;
6502 if (!KD.kernarg_size->evaluateAsAbsolute(IVal))
6503 return TokError("Kernarg size should be resolvable");
6504 uint64_t kernarg_size = IVal;
6505 if (PreloadLength && kernarg_size &&
6506 (PreloadLength * 4 + PreloadOffset * 4 > kernarg_size))
6507 return TokError("Kernarg preload length + offset is larger than the "
6508 "kernarg segment size");
6509
6510 if (isGFX90A()) {
6511 if (!Seen.contains(".amdhsa_accum_offset"))
6512 return TokError(".amdhsa_accum_offset directive is required");
6513 int64_t EvaluatedAccum;
6514 bool AccumEvaluatable = AccumOffset->evaluateAsAbsolute(EvaluatedAccum);
6515 uint64_t UEvaluatedAccum = EvaluatedAccum;
6516 if (AccumEvaluatable &&
6517 (UEvaluatedAccum < 4 || UEvaluatedAccum > 256 || (UEvaluatedAccum & 3)))
6518 return TokError("accum_offset should be in range [4..256] in "
6519 "increments of 4");
6520
6521 int64_t EvaluatedNumVGPR;
6522 if (NextFreeVGPR->evaluateAsAbsolute(EvaluatedNumVGPR) &&
6523 AccumEvaluatable &&
6524 UEvaluatedAccum >
6525 alignTo(std::max((uint64_t)1, (uint64_t)EvaluatedNumVGPR), 4))
6526 return TokError("accum_offset exceeds total VGPR allocation");
6527 const MCExpr *AdjustedAccum = MCBinaryExpr::createSub(
6529 AccumOffset, MCConstantExpr::create(4, getContext()), getContext()),
6532 COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT,
6533 COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET,
6534 getContext());
6535 }
6536
6537 if (isGFX1250Plus())
6539 COMPUTE_PGM_RSRC3_GFX125_NAMED_BAR_CNT_SHIFT,
6540 COMPUTE_PGM_RSRC3_GFX125_NAMED_BAR_CNT,
6541 getContext());
6542
6543 if (ISA.Major >= 10 && ISA.Major < 12) {
6544 // SharedVGPRCount < 16 checked by PARSE_ENTRY_BITS
6545 if (SharedVGPRCount && EnableWavefrontSize32 && *EnableWavefrontSize32) {
6546 return TokError("shared_vgpr_count directive not valid on "
6547 "wavefront size 32");
6548 }
6549
6550 if (VGPRBlocksEvaluatable &&
6551 (SharedVGPRCount * 2 + static_cast<uint64_t>(EvaluatedVGPRBlocks) >
6552 63)) {
6553 return TokError("shared_vgpr_count*2 + "
6554 "compute_pgm_rsrc1.GRANULATED_WORKITEM_VGPR_COUNT cannot "
6555 "exceed 63\n");
6556 }
6557 }
6558
6559 emitTargetDirective();
6560 getTargetStreamer().EmitAmdhsaKernelDescriptor(getSTI(), KernelName, KD,
6561 NextFreeVGPR, NextFreeSGPR,
6562 ReserveVCC, ReserveFlatScr);
6563 return false;
6564}
6565
6566bool AMDGPUAsmParser::ParseDirectiveAMDHSACodeObjectVersion() {
6567 uint32_t Version;
6568 if (ParseAsAbsoluteExpression(Version))
6569 return true;
6570
6571 getTargetStreamer().EmitDirectiveAMDHSACodeObjectVersion(Version);
6572 emitTargetDirective();
6573 return false;
6574}
6575
6576bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
6577 AMDGPUMCKernelCodeT &C) {
6578 // max_scratch_backing_memory_byte_size is deprecated. Ignore it while parsing
6579 // assembly for backwards compatibility.
6580 if (ID == "max_scratch_backing_memory_byte_size") {
6581 Parser.eatToEndOfStatement();
6582 return false;
6583 }
6584
6585 SmallString<40> ErrStr;
6586 raw_svector_ostream Err(ErrStr);
6587 if (!C.ParseKernelCodeT(ID, getParser(), Err)) {
6588 return TokError(Err.str());
6589 }
6590 Lex();
6591
6592 if (ID == "enable_wavefront_size32") {
6593 if (C.code_properties & AMD_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32) {
6594 if (!isGFX10Plus())
6595 return TokError("enable_wavefront_size32=1 is only allowed on GFX10+");
6596 if (!isWave32())
6597 return TokError("enable_wavefront_size32=1 requires +WavefrontSize32");
6598 } else {
6599 if (!isWave64())
6600 return TokError("enable_wavefront_size32=0 requires +WavefrontSize64");
6601 }
6602 }
6603
6604 if (ID == "wavefront_size") {
6605 if (C.wavefront_size == 5) {
6606 if (!isGFX10Plus())
6607 return TokError("wavefront_size=5 is only allowed on GFX10+");
6608 if (!isWave32())
6609 return TokError("wavefront_size=5 requires +WavefrontSize32");
6610 } else if (C.wavefront_size == 6) {
6611 if (!isWave64())
6612 return TokError("wavefront_size=6 requires +WavefrontSize64");
6613 }
6614 }
6615
6616 return false;
6617}
6618
6619bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
6620 AMDGPUMCKernelCodeT KernelCode;
6621 KernelCode.initDefault(getSTI(), getContext());
6622
6623 while (true) {
6624 // Lex EndOfStatement. This is in a while loop, because lexing a comment
6625 // will set the current token to EndOfStatement.
6626 while (trySkipToken(AsmToken::EndOfStatement))
6627 ;
6628
6629 StringRef ID;
6630 if (!parseId(ID, "expected value identifier or .end_amd_kernel_code_t"))
6631 return true;
6632
6633 if (ID == ".end_amd_kernel_code_t")
6634 break;
6635
6636 if (ParseAMDKernelCodeTValue(ID, KernelCode))
6637 return true;
6638 }
6639
6640 KernelCode.validate(&getSTI(), getContext());
6641 getTargetStreamer().EmitAMDKernelCodeT(KernelCode);
6642
6643 return false;
6644}
6645
6646bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
6647 StringRef KernelName;
6648 if (!parseId(KernelName, "expected symbol name"))
6649 return true;
6650
6651 getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
6653
6654 KernelScope.initialize(getContext());
6655 return false;
6656}
6657
6658bool AMDGPUAsmParser::ParseDirectiveISAVersion() {
6659 if (!getSTI().getTargetTriple().isAMDGCN()) {
6660 return Error(getLoc(),
6661 ".amd_amdgpu_isa directive is not available on non-amdgcn "
6662 "architectures");
6663 }
6664
6665 StringRef TargetIDDirective = getLexer().getTok().getStringContents();
6666
6667 std::optional<AMDGPU::TargetID> MaybeParsed =
6668 AMDGPU::TargetID::parseTargetIDString(TargetIDDirective);
6669 if (!MaybeParsed)
6670 return Error(getParser().getTok().getLoc(),
6671 "malformed target id '" + TargetIDDirective + "'");
6672
6673 const AMDGPU::TargetID &ParsedTargetID = *MaybeParsed;
6674 const Triple &TT = getSTI().getTargetTriple();
6675
6676 // The processor named in the target id must be covered by the triple's
6677 // subarch.
6678 if (!AMDGPU::isCPUValidForSubArch(TT.getSubArch(),
6679 ParsedTargetID.getGPUKind())) {
6680 return Error(getParser().getTok().getLoc(),
6681 "target id '" + TargetIDDirective +
6682 "' specifies a processor that is not valid for subarch '" +
6683 TT.getArchName() + "'");
6684 }
6685
6686 const std::optional<AMDGPU::TargetID> &CurrentTargetID =
6687 getTargetStreamer().getTargetID();
6688
6689 Triple DirectiveTriple(ParsedTargetID.getTargetTripleString());
6690 const Triple &STITriple = getSTI().getTargetTriple();
6691 if (!DirectiveTriple.isCompatibleWith(STITriple)) {
6692 return Error(getParser().getTok().getLoc(),
6693 ".amd_amdgpu_isa " + Twine(ParsedTargetID.toString()) +
6694 " is incompatible with " +
6695 Twine(CurrentTargetID->toString()));
6696 }
6697
6698 // Error if the ISA version doesn't match
6699 StringRef DirectiveProcessor =
6700 AMDGPU::getArchNameAMDGCN(ParsedTargetID.getGPUKind());
6701 AMDGPU::IsaVersion DirectiveISA = AMDGPU::getIsaVersion(DirectiveProcessor);
6702 if (DirectiveISA != ISA) {
6703 return Error(getParser().getTok().getLoc(),
6704 ".amd_amdgpu_isa directive processor " +
6705 Twine(DirectiveProcessor) +
6706 " does not match the specified processor " +
6707 Twine(getSTI().getCPU()));
6708 }
6709
6710 getTargetStreamer().EmitISAVersion();
6711 Lex();
6712
6713 return false;
6714}
6715
6716bool AMDGPUAsmParser::ParseDirectiveHSAMetadata() {
6717 assert(isHsaAbi(getSTI()));
6718
6719 std::string HSAMetadataString;
6720 if (ParseToEndDirective(HSAMD::V3::AssemblerDirectiveBegin,
6721 HSAMD::V3::AssemblerDirectiveEnd, HSAMetadataString))
6722 return true;
6723
6724 if (!getTargetStreamer().EmitHSAMetadataV3(HSAMetadataString))
6725 return Error(getLoc(), "invalid HSA metadata");
6726
6727 return false;
6728}
6729
6730/// Common code to parse out a block of text (typically YAML) between start and
6731/// end directives.
6732bool AMDGPUAsmParser::ParseToEndDirective(const char *AssemblerDirectiveBegin,
6733 const char *AssemblerDirectiveEnd,
6734 std::string &CollectString) {
6735
6736 raw_string_ostream CollectStream(CollectString);
6737
6738 getLexer().setSkipSpace(false);
6739
6740 bool FoundEnd = false;
6741 while (!isToken(AsmToken::Eof)) {
6742 while (isToken(AsmToken::Space)) {
6743 CollectStream << getTokenStr();
6744 Lex();
6745 }
6746
6747 if (trySkipId(AssemblerDirectiveEnd)) {
6748 FoundEnd = true;
6749 break;
6750 }
6751
6752 CollectStream << Parser.parseStringToEndOfStatement()
6753 << getContext().getAsmInfo().getSeparatorString();
6754
6755 Parser.eatToEndOfStatement();
6756 }
6757
6758 getLexer().setSkipSpace(true);
6759
6760 if (isToken(AsmToken::Eof) && !FoundEnd) {
6761 return TokError(Twine("expected directive ") +
6762 Twine(AssemblerDirectiveEnd) + Twine(" not found"));
6763 }
6764
6765 return false;
6766}
6767
6768/// Parse the assembler directive for new MsgPack-format PAL metadata.
6769bool AMDGPUAsmParser::ParseDirectivePALMetadataBegin() {
6770 std::string String;
6771 if (ParseToEndDirective(AMDGPU::PALMD::AssemblerDirectiveBegin,
6773 return true;
6774
6775 auto *PALMetadata = getTargetStreamer().getPALMetadata();
6776 if (!PALMetadata->setFromString(String))
6777 return Error(getLoc(), "invalid PAL metadata");
6778 return false;
6779}
6780
6781/// Parse the assembler directive for old linear-format PAL metadata.
6782bool AMDGPUAsmParser::ParseDirectivePALMetadata() {
6783 if (getSTI().getTargetTriple().getOS() != Triple::AMDPAL) {
6784 return Error(getLoc(), (Twine(PALMD::AssemblerDirective) +
6785 Twine(" directive is "
6786 "not available on non-amdpal OSes"))
6787 .str());
6788 }
6789
6790 auto *PALMetadata = getTargetStreamer().getPALMetadata();
6791 PALMetadata->setLegacy();
6792 for (;;) {
6793 uint32_t Key, Value;
6794 if (ParseAsAbsoluteExpression(Key)) {
6795 return TokError(Twine("invalid value in ") +
6797 }
6798 if (!trySkipToken(AsmToken::Comma)) {
6799 return TokError(Twine("expected an even number of values in ") +
6801 }
6802 if (ParseAsAbsoluteExpression(Value)) {
6803 return TokError(Twine("invalid value in ") +
6805 }
6806 PALMetadata->setRegister(Key, Value);
6807 if (!trySkipToken(AsmToken::Comma))
6808 break;
6809 }
6810 return false;
6811}
6812
6813/// ParseDirectiveAMDGPULDS
6814/// ::= .amdgpu_lds identifier ',' size_expression [',' align_expression]
6815bool AMDGPUAsmParser::ParseDirectiveAMDGPULDS() {
6816 if (getParser().checkForValidSection())
6817 return true;
6818
6819 StringRef Name;
6820 SMLoc NameLoc = getLoc();
6821 if (getParser().parseIdentifier(Name))
6822 return TokError("expected identifier in directive");
6823
6824 MCSymbol *Symbol = getContext().getOrCreateSymbol(Name);
6825 if (getParser().parseComma())
6826 return true;
6827
6828 unsigned LocalMemorySize = AMDGPU::IsaInfo::getLocalMemorySize(getSTI());
6829
6830 int64_t Size;
6831 SMLoc SizeLoc = getLoc();
6832 if (getParser().parseAbsoluteExpression(Size))
6833 return true;
6834 if (Size < 0)
6835 return Error(SizeLoc, "size must be non-negative");
6836 if (Size > LocalMemorySize)
6837 return Error(SizeLoc, "size is too large");
6838
6839 int64_t Alignment = 4;
6840 if (trySkipToken(AsmToken::Comma)) {
6841 SMLoc AlignLoc = getLoc();
6842 if (getParser().parseAbsoluteExpression(Alignment))
6843 return true;
6844 if (Alignment < 0 || !isPowerOf2_64(Alignment))
6845 return Error(AlignLoc, "alignment must be a power of two");
6846
6847 // Alignment larger than the size of LDS is possible in theory, as long
6848 // as the linker manages to place to symbol at address 0, but we do want
6849 // to make sure the alignment fits nicely into a 32-bit integer.
6850 if (Alignment >= 1u << 31)
6851 return Error(AlignLoc, "alignment is too large");
6852 }
6853
6854 if (parseEOL())
6855 return true;
6856
6857 Symbol->redefineIfPossible();
6858 if (!Symbol->isUndefined())
6859 return Error(NameLoc, "invalid symbol redefinition");
6860
6861 getTargetStreamer().emitAMDGPULDS(Symbol, Size, Align(Alignment));
6862 return false;
6863}
6864
6865bool AMDGPUAsmParser::ParseDirectiveAMDGPUInfo() {
6866 if (getParser().checkForValidSection())
6867 return true;
6868
6869 StringRef FuncName;
6870 if (getParser().parseIdentifier(FuncName))
6871 return TokError("expected symbol name after .amdgpu_info");
6872
6873 MCSymbol *FuncSym = getContext().getOrCreateSymbol(FuncName);
6874 AMDGPU::InfoSectionData ParsedInfoData;
6875 AMDGPU::FuncInfo FI;
6876 FI.Sym = FuncSym;
6877 bool HasScalarAttrs = false;
6878
6879 while (true) {
6880 while (trySkipToken(AsmToken::EndOfStatement))
6881 ;
6882
6883 StringRef ID;
6884 SMLoc IDLoc = getLoc();
6885 if (!parseId(ID, "expected directive or .end_amdgpu_info"))
6886 return true;
6887
6888 if (ID == ".end_amdgpu_info")
6889 break;
6890
6891 // Every per-entry directive shares the `.amdgpu_` namespace prefix; strip
6892 // it once and dispatch on the distinguishing suffix below. The unstripped
6893 // ID is preserved for diagnostics.
6894 StringRef Dir = ID;
6895 if (!Dir.consume_front(".amdgpu_"))
6896 return Error(IDLoc, "unknown .amdgpu_info directive '" + ID + "'");
6897
6898 if (Dir == "flags") {
6899 int64_t Val;
6900 if (getParser().parseAbsoluteExpression(Val))
6901 return true;
6902 auto Flags = static_cast<AMDGPU::FuncInfoFlags>(Val);
6903 FI.UsesVCC = !!(Flags & AMDGPU::FuncInfoFlags::FUNC_USES_VCC);
6904 FI.UsesFlatScratch =
6905 !!(Flags & AMDGPU::FuncInfoFlags::FUNC_USES_FLAT_SCRATCH);
6906 FI.HasDynStack = !!(Flags & AMDGPU::FuncInfoFlags::FUNC_HAS_DYN_STACK);
6907 HasScalarAttrs = true;
6908 } else if (Dir == "num_sgpr") {
6909 int64_t Val;
6910 if (getParser().parseAbsoluteExpression(Val))
6911 return true;
6912 FI.NumSGPR = static_cast<uint32_t>(Val);
6913 HasScalarAttrs = true;
6914 } else if (Dir == "num_vgpr") {
6915 int64_t Val;
6916 if (getParser().parseAbsoluteExpression(Val))
6917 return true;
6918 FI.NumArchVGPR = static_cast<uint32_t>(Val);
6919 HasScalarAttrs = true;
6920 } else if (Dir == "num_agpr") {
6921 int64_t Val;
6922 if (getParser().parseAbsoluteExpression(Val))
6923 return true;
6924 FI.NumAccVGPR = static_cast<uint32_t>(Val);
6925 HasScalarAttrs = true;
6926 } else if (Dir == "private_segment_size") {
6927 int64_t Val;
6928 if (getParser().parseAbsoluteExpression(Val))
6929 return true;
6930 FI.PrivateSegmentSize = static_cast<uint32_t>(Val);
6931 HasScalarAttrs = true;
6932 } else if (Dir == "use") {
6933 StringRef ResName;
6934 if (getParser().parseIdentifier(ResName))
6935 return TokError("expected resource symbol for .amdgpu_use");
6936 ParsedInfoData.Uses.push_back(
6937 {FuncSym, getContext().getOrCreateSymbol(ResName)});
6938 } else if (Dir == "call") {
6939 StringRef DstName;
6940 if (getParser().parseIdentifier(DstName))
6941 return TokError("expected callee symbol for .amdgpu_call");
6942 ParsedInfoData.Calls.push_back(
6943 {FuncSym, getContext().getOrCreateSymbol(DstName)});
6944 } else if (Dir == "indirect_call") {
6945 std::string TypeId;
6946 if (getParser().parseEscapedString(TypeId))
6947 return TokError("expected type ID string for .amdgpu_indirect_call");
6948 ParsedInfoData.IndirectCalls.push_back({FuncSym, std::move(TypeId)});
6949 } else if (Dir == "typeid") {
6950 std::string TypeId;
6951 if (getParser().parseEscapedString(TypeId))
6952 return TokError("expected type ID string for .amdgpu_typeid");
6953 ParsedInfoData.TypeIds.push_back({FuncSym, std::move(TypeId)});
6954 } else {
6955 return Error(IDLoc, "unknown .amdgpu_info directive '" + ID + "'");
6956 }
6957 }
6958
6959 if (HasScalarAttrs)
6960 ParsedInfoData.Funcs.push_back(std::move(FI));
6961
6962 AMDGPU::InfoSectionData &Data = InfoData ? *InfoData : InfoData.emplace();
6963 for (AMDGPU::FuncInfo &Func : ParsedInfoData.Funcs)
6964 Data.Funcs.push_back(std::move(Func));
6965 for (std::pair<MCSymbol *, MCSymbol *> &Use : ParsedInfoData.Uses)
6966 Data.Uses.push_back(Use);
6967 for (std::pair<MCSymbol *, MCSymbol *> &Call : ParsedInfoData.Calls)
6968 Data.Calls.push_back(Call);
6969 for (std::pair<MCSymbol *, std::string> &IndirectCall :
6970 ParsedInfoData.IndirectCalls)
6971 Data.IndirectCalls.push_back(std::move(IndirectCall));
6972 for (std::pair<MCSymbol *, std::string> &TypeId : ParsedInfoData.TypeIds)
6973 Data.TypeIds.push_back(std::move(TypeId));
6974
6975 return false;
6976}
6977
6978void AMDGPUAsmParser::doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) {
6979 // Record every parsed label in the timeline so that, at end of file, the
6980 // instructions following a kernel's label can be located regardless of
6981 // whether the .amdhsa_kernel directive came before or after the label.
6982 OpcodeStreamSymbols.emplace_back(Symbol, IDLoc, OpcodeStream.size());
6983}
6984
6985void AMDGPUAsmParser::checkKernelPrologues() {
6986 if (getFeatureBits()[AMDGPU::FeatureRequiresInitialUnclausedVmem]) {
6987 static const unsigned Required[] = {S_MOV_B64_gfx12, V_NOP_e32_gfx12,
6988 GLOBAL_PREFETCH_B8_SADDR_gfx1250};
6989 for (auto [Sym, Loc, Offset] : OpcodeStreamSymbols) {
6990 if (!AMDHSAKernelSymbols.contains(Sym))
6991 continue;
6992 ArrayRef<unsigned> Prologue = ArrayRef(OpcodeStream).drop_front(Offset);
6993 if (Prologue.take_front(std::size(Required)) != ArrayRef(Required)) {
6994 Warning(Loc, "kernel '" + Sym->getName() +
6995 "' does not begin with the required prologue "
6996 "sequence: S_MOV_B64 followed by V_NOP and "
6997 "GLOBAL_PREFETCH_B8");
6998 }
6999 }
7000 }
7001 OpcodeStream.clear();
7002 OpcodeStreamSymbols.clear();
7003 AMDHSAKernelSymbols.clear();
7004}
7005
7006void AMDGPUAsmParser::onEndOfFile() {
7007 emitTargetDirective();
7008 checkKernelPrologues();
7009 if (InfoData)
7010 getTargetStreamer().emitAMDGPUInfo(*InfoData);
7011}
7012
7013bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
7014 StringRef IDVal = DirectiveID.getString();
7015
7016 if (isHsaAbi(getSTI())) {
7017 if (IDVal == ".amdhsa_kernel")
7018 return ParseDirectiveAMDHSAKernel();
7019
7020 if (IDVal == ".amdhsa_code_object_version")
7021 return ParseDirectiveAMDHSACodeObjectVersion();
7022
7023 // TODO: Restructure/combine with PAL metadata directive.
7025 return ParseDirectiveHSAMetadata();
7026 } else {
7027 if (IDVal == ".amd_kernel_code_t")
7028 return ParseDirectiveAMDKernelCodeT();
7029
7030 if (IDVal == ".amdgpu_hsa_kernel")
7031 return ParseDirectiveAMDGPUHsaKernel();
7032
7033 if (IDVal == ".amd_amdgpu_isa")
7034 return ParseDirectiveISAVersion();
7035
7037 return Error(getLoc(), (Twine(HSAMD::AssemblerDirectiveBegin) +
7038 Twine(" directive is "
7039 "not available on non-amdhsa OSes"))
7040 .str());
7041 }
7042 }
7043
7044 if (IDVal == ".amdgcn_target")
7045 return ParseDirectiveAMDGCNTarget();
7046
7047 if (IDVal == ".amdgpu_lds")
7048 return ParseDirectiveAMDGPULDS();
7049
7050 if (IDVal == ".amdgpu_info")
7051 return ParseDirectiveAMDGPUInfo();
7052
7053 if (IDVal == PALMD::AssemblerDirectiveBegin)
7054 return ParseDirectivePALMetadataBegin();
7055
7056 if (IDVal == PALMD::AssemblerDirective)
7057 return ParseDirectivePALMetadata();
7058
7059 return true;
7060}
7061
7062bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
7063 MCRegister Reg) {
7064 if (MRI.regsOverlap(TTMP12_TTMP13_TTMP14_TTMP15, Reg))
7065 return isGFX9Plus();
7066
7067 // GFX10+ has 2 more SGPRs 104 and 105.
7068 if (MRI.regsOverlap(SGPR104_SGPR105, Reg))
7069 return hasSGPR104_SGPR105();
7070
7071 switch (Reg.id()) {
7072 case SRC_SHARED_BASE_LO:
7073 case SRC_SHARED_BASE:
7074 case SRC_SHARED_LIMIT_LO:
7075 case SRC_SHARED_LIMIT:
7076 return isGFX9Plus();
7077 case SRC_PRIVATE_BASE_LO:
7078 case SRC_PRIVATE_BASE:
7079 case SRC_PRIVATE_LIMIT_LO:
7080 case SRC_PRIVATE_LIMIT:
7081 return AMDGPU::hasPrivateApertureRegs(getSTI());
7082 case SRC_FLAT_SCRATCH_BASE_LO:
7083 case SRC_FLAT_SCRATCH_BASE_HI:
7084 return hasGloballyAddressableScratch();
7085 case SRC_POPS_EXITING_WAVE_ID:
7086 return hasPopsExitingWaveID(getSTI());
7087 case TBA:
7088 case TBA_LO:
7089 case TBA_HI:
7090 case TMA:
7091 case TMA_LO:
7092 case TMA_HI:
7093 return !isGFX9Plus();
7094 case XNACK_MASK:
7095 case XNACK_MASK_LO:
7096 case XNACK_MASK_HI:
7097 return (isVI() || isGFX9()) &&
7098 getTargetStreamer().getTargetID()->isXnackSupported();
7099 case SGPR_NULL:
7100 return isGFX10Plus();
7101 case SRC_EXECZ:
7102 case SRC_VCCZ:
7103 return !isGFX11Plus();
7104 default:
7105 break;
7106 }
7107
7108 if (isCI())
7109 return true;
7110
7111 if (isSI() || isGFX10Plus()) {
7112 // No flat_scr on SI.
7113 // On GFX10Plus flat scratch is not a valid register operand and can only be
7114 // accessed with s_setreg/s_getreg.
7115 switch (Reg.id()) {
7116 case FLAT_SCR:
7117 case FLAT_SCR_LO:
7118 case FLAT_SCR_HI:
7119 return false;
7120 default:
7121 return true;
7122 }
7123 }
7124
7125 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
7126 // SI/CI have.
7127 if (MRI.regsOverlap(SGPR102_SGPR103, Reg))
7128 return hasSGPR102_SGPR103();
7129
7130 return true;
7131}
7132
7133ParseStatus AMDGPUAsmParser::parseOperand(OperandVector &Operands,
7134 StringRef Mnemonic,
7135 OperandMode Mode) {
7136 ParseStatus Res = parseVOPD(Operands);
7137 if (Res.isSuccess() || Res.isFailure() || isToken(AsmToken::EndOfStatement))
7138 return Res;
7139
7140 // Try to parse with a custom parser
7141 Res = MatchOperandParserImpl(Operands, Mnemonic);
7142
7143 // If we successfully parsed the operand or if there as an error parsing,
7144 // we are done.
7145 //
7146 // If we are parsing after we reach EndOfStatement then this means we
7147 // are appending default values to the Operands list. This is only done
7148 // by custom parser, so we shouldn't continue on to the generic parsing.
7149 if (Res.isSuccess() || Res.isFailure() || isToken(AsmToken::EndOfStatement))
7150 return Res;
7151
7152 SMLoc RBraceLoc;
7153 SMLoc LBraceLoc = getLoc();
7154 if (Mode == OperandMode_NSA && trySkipToken(AsmToken::LBrac)) {
7155 unsigned Prefix = Operands.size();
7156
7157 for (;;) {
7158 auto Loc = getLoc();
7159 Res = parseReg(Operands);
7160 if (Res.isNoMatch())
7161 Error(Loc, "expected a register");
7162 if (!Res.isSuccess())
7163 return ParseStatus::Failure;
7164
7165 RBraceLoc = getLoc();
7166 if (trySkipToken(AsmToken::RBrac))
7167 break;
7168
7169 if (!skipToken(AsmToken::Comma,
7170 "expected a comma or a closing square bracket"))
7171 return ParseStatus::Failure;
7172 }
7173
7174 if (Operands.size() - Prefix > 1) {
7175 Operands.insert(Operands.begin() + Prefix,
7176 AMDGPUOperand::CreateToken(this, "[", LBraceLoc));
7177 Operands.push_back(AMDGPUOperand::CreateToken(this, "]", RBraceLoc));
7178 }
7179
7180 return ParseStatus::Success;
7181 }
7182
7183 return parseRegOrImm(Operands);
7184}
7185
7186StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
7187 // Clear any forced encodings from the previous instruction.
7188 setForcedEncodingSize(0);
7189 setForcedDPP(false);
7190 setForcedSDWA(false);
7191
7192 if (Name.consume_back("_e64_dpp")) {
7193 setForcedDPP(true);
7194 setForcedEncodingSize(64);
7195 return Name;
7196 }
7197 if (Name.consume_back("_e64")) {
7198 setForcedEncodingSize(64);
7199 return Name;
7200 }
7201 if (Name.consume_back("_e32")) {
7202 setForcedEncodingSize(32);
7203 return Name;
7204 }
7205 if (Name.consume_back("_dpp")) {
7206 setForcedDPP(true);
7207 return Name;
7208 }
7209 if (Name.consume_back("_sdwa")) {
7210 setForcedSDWA(true);
7211 return Name;
7212 }
7213 return Name;
7214}
7215
7216static void applyMnemonicAliases(StringRef &Mnemonic,
7217 const FeatureBitset &Features,
7218 unsigned VariantID);
7219
7220bool AMDGPUAsmParser::parseInstruction(ParseInstructionInfo &Info,
7221 StringRef Name, SMLoc NameLoc,
7223 // Add the instruction mnemonic
7224 Name = parseMnemonicSuffix(Name);
7225
7226 // If the target architecture uses MnemonicAlias, call it here to parse
7227 // operands correctly.
7228 applyMnemonicAliases(Name, getAvailableFeatures(), 0);
7229
7230 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc));
7231
7232 bool IsMIMG = Name.starts_with("image_");
7233
7234 while (!trySkipToken(AsmToken::EndOfStatement)) {
7235 OperandMode Mode = OperandMode_Default;
7236 if (IsMIMG && isGFX10Plus() && Operands.size() == 2)
7237 Mode = OperandMode_NSA;
7238 ParseStatus Res = parseOperand(Operands, Name, Mode);
7239
7240 if (!Res.isSuccess()) {
7241 checkUnsupportedInstruction(Name, NameLoc);
7242 if (!Parser.hasPendingError()) {
7243 // FIXME: use real operand location rather than the current location.
7244 StringRef Msg = Res.isFailure() ? "failed parsing operand."
7245 : "not a valid operand.";
7246 Error(getLoc(), Msg);
7247 }
7248 while (!trySkipToken(AsmToken::EndOfStatement)) {
7249 lex();
7250 }
7251 return true;
7252 }
7253
7254 // Eat the comma or space if there is one.
7255 trySkipToken(AsmToken::Comma);
7256 }
7257
7258 return false;
7259}
7260
7261//===----------------------------------------------------------------------===//
7262// Utility functions
7263//===----------------------------------------------------------------------===//
7264
7265ParseStatus AMDGPUAsmParser::parseTokenOp(StringRef Name,
7267 SMLoc S = getLoc();
7268 if (!trySkipId(Name))
7269 return ParseStatus::NoMatch;
7270
7271 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, S));
7272 return ParseStatus::Success;
7273}
7274
7275ParseStatus AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix,
7276 int64_t &IntVal) {
7277
7278 if (!trySkipId(Prefix, AsmToken::Colon))
7279 return ParseStatus::NoMatch;
7280
7282}
7283
7284ParseStatus AMDGPUAsmParser::parseIntWithPrefix(
7285 const char *Prefix, OperandVector &Operands, AMDGPUOperand::ImmTy ImmTy,
7286 std::function<bool(int64_t &)> ConvertResult) {
7287 SMLoc S = getLoc();
7288 int64_t Value = 0;
7289
7290 ParseStatus Res = parseIntWithPrefix(Prefix, Value);
7291 if (!Res.isSuccess())
7292 return Res;
7293
7294 if (ConvertResult && !ConvertResult(Value)) {
7295 Error(S, "invalid " + StringRef(Prefix) + " value.");
7296 }
7297
7298 Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy));
7299 return ParseStatus::Success;
7300}
7301
7302ParseStatus AMDGPUAsmParser::parseOperandArrayWithPrefix(
7303 const char *Prefix, OperandVector &Operands, AMDGPUOperand::ImmTy ImmTy,
7304 bool (*ConvertResult)(int64_t &)) {
7305 SMLoc S = getLoc();
7306 if (!trySkipId(Prefix, AsmToken::Colon))
7307 return ParseStatus::NoMatch;
7308
7309 if (!skipToken(AsmToken::LBrac, "expected a left square bracket"))
7310 return ParseStatus::Failure;
7311
7312 unsigned Val = 0;
7313 const unsigned MaxSize = 4;
7314
7315 // FIXME: How to verify the number of elements matches the number of src
7316 // operands?
7317 for (int I = 0;; ++I) {
7318 int64_t Op;
7319 SMLoc Loc = getLoc();
7320 if (!parseExpr(Op))
7321 return ParseStatus::Failure;
7322
7323 if (Op != 0 && Op != 1)
7324 return Error(Loc, "invalid " + StringRef(Prefix) + " value.");
7325
7326 Val |= (Op << I);
7327
7328 if (trySkipToken(AsmToken::RBrac))
7329 break;
7330
7331 if (I + 1 == MaxSize)
7332 return Error(getLoc(), "expected a closing square bracket");
7333
7334 if (!skipToken(AsmToken::Comma, "expected a comma"))
7335 return ParseStatus::Failure;
7336 }
7337
7338 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, ImmTy));
7339 return ParseStatus::Success;
7340}
7341
7342ParseStatus AMDGPUAsmParser::parseNamedBit(StringRef Name,
7344 AMDGPUOperand::ImmTy ImmTy,
7345 bool IgnoreNegative) {
7346 int64_t Bit;
7347 SMLoc S = getLoc();
7348
7349 if (trySkipId(Name)) {
7350 Bit = 1;
7351 } else if (trySkipId("no", Name)) {
7352 if (IgnoreNegative)
7353 return ParseStatus::Success;
7354 Bit = 0;
7355 } else {
7356 return ParseStatus::NoMatch;
7357 }
7358
7359 if (Name == "r128" && !hasMIMG_R128())
7360 return Error(S, "r128 modifier is not supported on this GPU");
7361 if (Name == "a16" && !hasA16())
7362 return Error(S, "a16 modifier is not supported on this GPU");
7363
7364 if (Bit == 0 && Name == "gds") {
7365 StringRef Mnemo = ((AMDGPUOperand &)*Operands[0]).getToken();
7366 if (Mnemo.starts_with("ds_gws"))
7367 return Error(S, "nogds is not allowed");
7368 }
7369
7370 if (isGFX9() && ImmTy == AMDGPUOperand::ImmTyA16)
7371 ImmTy = AMDGPUOperand::ImmTyR128A16;
7372
7373 Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy));
7374 return ParseStatus::Success;
7375}
7376
7377unsigned AMDGPUAsmParser::getCPolKind(StringRef Id, StringRef Mnemo,
7378 bool &Disabling) const {
7379 Disabling = Id.consume_front("no");
7380
7381 if (isGFX940() && !Mnemo.starts_with("s_")) {
7382 return StringSwitch<unsigned>(Id)
7383 .Case("nt", AMDGPU::CPol::NT)
7384 .Case("sc0", AMDGPU::CPol::SC0)
7385 .Case("sc1", AMDGPU::CPol::SC1)
7386 .Default(0);
7387 }
7388
7389 return StringSwitch<unsigned>(Id)
7390 .Case("dlc", AMDGPU::CPol::DLC)
7391 .Case("glc", AMDGPU::CPol::GLC)
7392 .Case("scc", AMDGPU::CPol::SCC)
7393 .Case("slc", AMDGPU::CPol::SLC)
7394 .Default(0);
7395}
7396
7397ParseStatus AMDGPUAsmParser::parseCPol(OperandVector &Operands) {
7398 if (isGFX12Plus()) {
7399 SMLoc StringLoc = getLoc();
7400
7401 int64_t CPolVal = 0;
7402 ParseStatus ResTH = ParseStatus::NoMatch;
7403 ParseStatus ResScope = ParseStatus::NoMatch;
7404 ParseStatus ResNV = ParseStatus::NoMatch;
7405 ParseStatus ResScal = ParseStatus::NoMatch;
7406
7407 for (;;) {
7408 if (ResTH.isNoMatch()) {
7409 int64_t TH;
7410 ResTH = parseTH(Operands, TH);
7411 if (ResTH.isFailure())
7412 return ResTH;
7413 if (ResTH.isSuccess()) {
7414 CPolVal |= TH;
7415 continue;
7416 }
7417 }
7418
7419 if (ResScope.isNoMatch()) {
7420 int64_t Scope;
7421 ResScope = parseScope(Operands, Scope);
7422 if (ResScope.isFailure())
7423 return ResScope;
7424 if (ResScope.isSuccess()) {
7425 CPolVal |= Scope;
7426 continue;
7427 }
7428 }
7429
7430 // NV bit exists on GFX12+, but does something starting from GFX1250.
7431 // Allow parsing on all GFX12 and fail on validation for better
7432 // diagnostics.
7433 if (ResNV.isNoMatch()) {
7434 if (trySkipId("nv")) {
7435 ResNV = ParseStatus::Success;
7436 CPolVal |= CPol::NV;
7437 continue;
7438 } else if (trySkipId("no", "nv")) {
7439 ResNV = ParseStatus::Success;
7440 continue;
7441 }
7442 }
7443
7444 if (ResScal.isNoMatch()) {
7445 if (trySkipId("scale_offset")) {
7446 ResScal = ParseStatus::Success;
7447 CPolVal |= CPol::SCAL;
7448 continue;
7449 } else if (trySkipId("no", "scale_offset")) {
7450 ResScal = ParseStatus::Success;
7451 continue;
7452 }
7453 }
7454
7455 break;
7456 }
7457
7458 if (ResTH.isNoMatch() && ResScope.isNoMatch() && ResNV.isNoMatch() &&
7459 ResScal.isNoMatch())
7460 return ParseStatus::NoMatch;
7461
7462 Operands.push_back(AMDGPUOperand::CreateImm(this, CPolVal, StringLoc,
7463 AMDGPUOperand::ImmTyCPol));
7464 return ParseStatus::Success;
7465 }
7466
7467 StringRef Mnemo = ((AMDGPUOperand &)*Operands[0]).getToken();
7468 SMLoc OpLoc = getLoc();
7469 unsigned Enabled = 0, Seen = 0;
7470 for (;;) {
7471 SMLoc S = getLoc();
7472 bool Disabling;
7473 unsigned CPol = getCPolKind(getId(), Mnemo, Disabling);
7474 if (!CPol)
7475 break;
7476
7477 lex();
7478
7479 if (!isGFX10Plus() && CPol == AMDGPU::CPol::DLC)
7480 return Error(S, "dlc modifier is not supported on this GPU");
7481
7482 if (!isGFX90A() && CPol == AMDGPU::CPol::SCC)
7483 return Error(S, "scc modifier is not supported on this GPU");
7484
7485 if (Seen & CPol)
7486 return Error(S, "duplicate cache policy modifier");
7487
7488 if (!Disabling)
7489 Enabled |= CPol;
7490
7491 Seen |= CPol;
7492 }
7493
7494 if (!Seen)
7495 return ParseStatus::NoMatch;
7496
7497 Operands.push_back(
7498 AMDGPUOperand::CreateImm(this, Enabled, OpLoc, AMDGPUOperand::ImmTyCPol));
7499 return ParseStatus::Success;
7500}
7501
7502ParseStatus AMDGPUAsmParser::parseScope(OperandVector &Operands,
7503 int64_t &Scope) {
7504 static const unsigned Scopes[] = {CPol::SCOPE_CU, CPol::SCOPE_SE,
7506
7507 ParseStatus Res = parseStringOrIntWithPrefix(
7508 Operands, "scope", {"SCOPE_CU", "SCOPE_SE", "SCOPE_DEV", "SCOPE_SYS"},
7509 Scope);
7510
7511 if (Res.isSuccess())
7512 Scope = Scopes[Scope];
7513
7514 return Res;
7515}
7516
7517ParseStatus AMDGPUAsmParser::parseTH(OperandVector &Operands, int64_t &TH) {
7518 TH = AMDGPU::CPol::TH_RT; // default
7519
7520 StringRef Value;
7521 SMLoc StringLoc;
7522 ParseStatus Res = parseStringWithPrefix("th", Value, StringLoc);
7523 if (!Res.isSuccess())
7524 return Res;
7525
7526 if (Value == "TH_DEFAULT")
7528 else if (Value == "TH_STORE_LU" || Value == "TH_LOAD_WB" ||
7529 Value == "TH_LOAD_NT_WB") {
7530 return Error(StringLoc, "invalid th value");
7531 } else if (Value.consume_front("TH_ATOMIC_")) {
7533 } else if (Value.consume_front("TH_LOAD_")) {
7535 } else if (Value.consume_front("TH_STORE_")) {
7537 } else {
7538 return Error(StringLoc, "invalid th value");
7539 }
7540
7541 if (Value == "BYPASS")
7543
7544 if (TH != 0) {
7546 TH |= StringSwitch<int64_t>(Value)
7547 .Case("RETURN", AMDGPU::CPol::TH_ATOMIC_RETURN)
7548 .Case("RT", AMDGPU::CPol::TH_RT)
7549 .Case("RT_RETURN", AMDGPU::CPol::TH_ATOMIC_RETURN)
7550 .Case("NT", AMDGPU::CPol::TH_ATOMIC_NT)
7551 .Case("NT_RETURN", AMDGPU::CPol::TH_ATOMIC_NT |
7553 .Case("CASCADE_RT", AMDGPU::CPol::TH_ATOMIC_CASCADE)
7554 .Case("CASCADE_NT", AMDGPU::CPol::TH_ATOMIC_CASCADE |
7556 .Default(0xffffffff);
7557 else
7558 TH |= StringSwitch<int64_t>(Value)
7559 .Case("RT", AMDGPU::CPol::TH_RT)
7560 .Case("NT", AMDGPU::CPol::TH_NT)
7561 .Case("HT", AMDGPU::CPol::TH_HT)
7562 .Case("LU", AMDGPU::CPol::TH_LU)
7563 .Case("WB", AMDGPU::CPol::TH_WB)
7564 .Case("NT_RT", AMDGPU::CPol::TH_NT_RT)
7565 .Case("RT_NT", AMDGPU::CPol::TH_RT_NT)
7566 .Case("NT_HT", AMDGPU::CPol::TH_NT_HT)
7567 .Case("NT_WB", AMDGPU::CPol::TH_NT_WB)
7568 .Case("BYPASS", AMDGPU::CPol::TH_BYPASS)
7569 .Default(0xffffffff);
7570 }
7571
7572 if (TH == 0xffffffff)
7573 return Error(StringLoc, "invalid th value");
7574
7575 return ParseStatus::Success;
7576}
7577
7578static void
7580 AMDGPUAsmParser::OptionalImmIndexMap &OptionalIdx,
7581 AMDGPUOperand::ImmTy ImmT, int64_t Default = 0,
7582 std::optional<unsigned> InsertAt = std::nullopt) {
7583 auto i = OptionalIdx.find(ImmT);
7584 if (i != OptionalIdx.end()) {
7585 unsigned Idx = i->second;
7586 const AMDGPUOperand &Op =
7587 static_cast<const AMDGPUOperand &>(*Operands[Idx]);
7588 if (InsertAt)
7589 Inst.insert(Inst.begin() + *InsertAt, MCOperand::createImm(Op.getImm()));
7590 else
7591 Op.addImmOperands(Inst, 1);
7592 } else {
7593 if (InsertAt.has_value())
7594 Inst.insert(Inst.begin() + *InsertAt, MCOperand::createImm(Default));
7595 else
7597 }
7598}
7599
7600ParseStatus AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix,
7601 StringRef &Value,
7602 SMLoc &StringLoc) {
7603 if (!trySkipId(Prefix, AsmToken::Colon))
7604 return ParseStatus::NoMatch;
7605
7606 StringLoc = getLoc();
7607 return parseId(Value, "expected an identifier") ? ParseStatus::Success
7609}
7610
7611ParseStatus AMDGPUAsmParser::parseStringOrIntWithPrefix(
7612 OperandVector &Operands, StringRef Name, ArrayRef<const char *> Ids,
7613 int64_t &IntVal) {
7614 if (!trySkipId(Name, AsmToken::Colon))
7615 return ParseStatus::NoMatch;
7616
7617 SMLoc StringLoc = getLoc();
7618
7619 StringRef Value;
7620 if (isToken(AsmToken::Identifier)) {
7621 Value = getTokenStr();
7622 lex();
7623
7624 for (IntVal = 0; IntVal < (int64_t)Ids.size(); ++IntVal)
7625 if (Value == Ids[IntVal])
7626 break;
7627 } else if (!parseExpr(IntVal))
7628 return ParseStatus::Failure;
7629
7630 if (IntVal < 0 || IntVal >= (int64_t)Ids.size())
7631 return Error(StringLoc, "invalid " + Twine(Name) + " value");
7632
7633 return ParseStatus::Success;
7634}
7635
7636ParseStatus AMDGPUAsmParser::parseStringOrIntWithPrefix(
7637 OperandVector &Operands, StringRef Name, ArrayRef<const char *> Ids,
7638 AMDGPUOperand::ImmTy Type) {
7639 SMLoc S = getLoc();
7640 int64_t IntVal;
7641
7642 ParseStatus Res = parseStringOrIntWithPrefix(Operands, Name, Ids, IntVal);
7643 if (Res.isSuccess())
7644 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S, Type));
7645
7646 return Res;
7647}
7648
7649//===----------------------------------------------------------------------===//
7650// MTBUF format
7651//===----------------------------------------------------------------------===//
7652
7653bool AMDGPUAsmParser::tryParseFmt(const char *Pref, int64_t MaxVal,
7654 int64_t &Fmt) {
7655 int64_t Val;
7656 SMLoc Loc = getLoc();
7657
7658 auto Res = parseIntWithPrefix(Pref, Val);
7659 if (Res.isFailure())
7660 return false;
7661 if (Res.isNoMatch())
7662 return true;
7663
7664 if (Val < 0 || Val > MaxVal) {
7665 Error(Loc, Twine("out of range ", StringRef(Pref)));
7666 return false;
7667 }
7668
7669 Fmt = Val;
7670 return true;
7671}
7672
7673ParseStatus AMDGPUAsmParser::tryParseIndexKey(OperandVector &Operands,
7674 AMDGPUOperand::ImmTy ImmTy) {
7675 const char *Pref = "index_key";
7676 int64_t ImmVal = 0;
7677 SMLoc Loc = getLoc();
7678 auto Res = parseIntWithPrefix(Pref, ImmVal);
7679 if (!Res.isSuccess())
7680 return Res;
7681
7682 if ((ImmTy == AMDGPUOperand::ImmTyIndexKey16bit ||
7683 ImmTy == AMDGPUOperand::ImmTyIndexKey32bit) &&
7684 (ImmVal < 0 || ImmVal > 1))
7685 return Error(Loc, Twine("out of range ", StringRef(Pref)));
7686
7687 if (ImmTy == AMDGPUOperand::ImmTyIndexKey8bit && (ImmVal < 0 || ImmVal > 3))
7688 return Error(Loc, Twine("out of range ", StringRef(Pref)));
7689
7690 Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc, ImmTy));
7691 return ParseStatus::Success;
7692}
7693
7694ParseStatus AMDGPUAsmParser::parseIndexKey8bit(OperandVector &Operands) {
7695 return tryParseIndexKey(Operands, AMDGPUOperand::ImmTyIndexKey8bit);
7696}
7697
7698ParseStatus AMDGPUAsmParser::parseIndexKey16bit(OperandVector &Operands) {
7699 return tryParseIndexKey(Operands, AMDGPUOperand::ImmTyIndexKey16bit);
7700}
7701
7702ParseStatus AMDGPUAsmParser::parseIndexKey32bit(OperandVector &Operands) {
7703 return tryParseIndexKey(Operands, AMDGPUOperand::ImmTyIndexKey32bit);
7704}
7705
7706ParseStatus AMDGPUAsmParser::tryParseMatrixFMT(OperandVector &Operands,
7707 StringRef Name,
7708 AMDGPUOperand::ImmTy Type) {
7709 return parseStringOrIntWithPrefix(Operands, Name, WMMAMods::ModMatrixFmt,
7710 Type);
7711}
7712
7713ParseStatus AMDGPUAsmParser::parseMatrixAFMT(OperandVector &Operands) {
7714 return tryParseMatrixFMT(Operands, "matrix_a_fmt",
7715 AMDGPUOperand::ImmTyMatrixAFMT);
7716}
7717
7718ParseStatus AMDGPUAsmParser::parseMatrixBFMT(OperandVector &Operands) {
7719 return tryParseMatrixFMT(Operands, "matrix_b_fmt",
7720 AMDGPUOperand::ImmTyMatrixBFMT);
7721}
7722
7723ParseStatus AMDGPUAsmParser::tryParseMatrixScale(OperandVector &Operands,
7724 StringRef Name,
7725 AMDGPUOperand::ImmTy Type) {
7726 return parseStringOrIntWithPrefix(Operands, Name, WMMAMods::ModMatrixScale,
7727 Type);
7728}
7729
7730ParseStatus AMDGPUAsmParser::parseMatrixAScale(OperandVector &Operands) {
7731 return tryParseMatrixScale(Operands, "matrix_a_scale",
7732 AMDGPUOperand::ImmTyMatrixAScale);
7733}
7734
7735ParseStatus AMDGPUAsmParser::parseMatrixBScale(OperandVector &Operands) {
7736 return tryParseMatrixScale(Operands, "matrix_b_scale",
7737 AMDGPUOperand::ImmTyMatrixBScale);
7738}
7739
7740ParseStatus AMDGPUAsmParser::tryParseMatrixScaleFmt(OperandVector &Operands,
7741 StringRef Name,
7742 AMDGPUOperand::ImmTy Type) {
7743 return parseStringOrIntWithPrefix(Operands, Name, WMMAMods::ModMatrixScaleFmt,
7744 Type);
7745}
7746
7747ParseStatus AMDGPUAsmParser::parseMatrixAScaleFmt(OperandVector &Operands) {
7748 return tryParseMatrixScaleFmt(Operands, "matrix_a_scale_fmt",
7749 AMDGPUOperand::ImmTyMatrixAScaleFmt);
7750}
7751
7752ParseStatus AMDGPUAsmParser::parseMatrixBScaleFmt(OperandVector &Operands) {
7753 return tryParseMatrixScaleFmt(Operands, "matrix_b_scale_fmt",
7754 AMDGPUOperand::ImmTyMatrixBScaleFmt);
7755}
7756
7757// dfmt and nfmt (in a tbuffer instruction) are parsed as one to allow their
7758// values to live in a joint format operand in the MCInst encoding.
7759ParseStatus AMDGPUAsmParser::parseDfmtNfmt(int64_t &Format) {
7760 using namespace llvm::AMDGPU::MTBUFFormat;
7761
7762 int64_t Dfmt = DFMT_UNDEF;
7763 int64_t Nfmt = NFMT_UNDEF;
7764
7765 // dfmt and nfmt can appear in either order, and each is optional.
7766 for (int I = 0; I < 2; ++I) {
7767 if (Dfmt == DFMT_UNDEF && !tryParseFmt("dfmt", DFMT_MAX, Dfmt))
7768 return ParseStatus::Failure;
7769
7770 if (Nfmt == NFMT_UNDEF && !tryParseFmt("nfmt", NFMT_MAX, Nfmt))
7771 return ParseStatus::Failure;
7772
7773 // Skip optional comma between dfmt/nfmt
7774 // but guard against 2 commas following each other.
7775 if ((Dfmt == DFMT_UNDEF) != (Nfmt == NFMT_UNDEF) &&
7776 !peekToken().is(AsmToken::Comma)) {
7777 trySkipToken(AsmToken::Comma);
7778 }
7779 }
7780
7781 if (Dfmt == DFMT_UNDEF && Nfmt == NFMT_UNDEF)
7782 return ParseStatus::NoMatch;
7783
7784 Dfmt = (Dfmt == DFMT_UNDEF) ? DFMT_DEFAULT : Dfmt;
7785 Nfmt = (Nfmt == NFMT_UNDEF) ? NFMT_DEFAULT : Nfmt;
7786
7787 Format = encodeDfmtNfmt(Dfmt, Nfmt);
7788 return ParseStatus::Success;
7789}
7790
7791ParseStatus AMDGPUAsmParser::parseUfmt(int64_t &Format) {
7792 using namespace llvm::AMDGPU::MTBUFFormat;
7793
7794 int64_t Fmt = UFMT_UNDEF;
7795
7796 if (!tryParseFmt("format", UFMT_MAX, Fmt))
7797 return ParseStatus::Failure;
7798
7799 if (Fmt == UFMT_UNDEF)
7800 return ParseStatus::NoMatch;
7801
7802 Format = Fmt;
7803 return ParseStatus::Success;
7804}
7805
7806bool AMDGPUAsmParser::matchDfmtNfmt(int64_t &Dfmt, int64_t &Nfmt,
7807 StringRef FormatStr, SMLoc Loc) {
7808 using namespace llvm::AMDGPU::MTBUFFormat;
7809 int64_t Format;
7810
7811 Format = getDfmt(FormatStr);
7812 if (Format != DFMT_UNDEF) {
7813 Dfmt = Format;
7814 return true;
7815 }
7816
7817 Format = getNfmt(FormatStr, getSTI());
7818 if (Format != NFMT_UNDEF) {
7819 Nfmt = Format;
7820 return true;
7821 }
7822
7823 Error(Loc, "unsupported format");
7824 return false;
7825}
7826
7827ParseStatus AMDGPUAsmParser::parseSymbolicSplitFormat(StringRef FormatStr,
7828 SMLoc FormatLoc,
7829 int64_t &Format) {
7830 using namespace llvm::AMDGPU::MTBUFFormat;
7831
7832 int64_t Dfmt = DFMT_UNDEF;
7833 int64_t Nfmt = NFMT_UNDEF;
7834 if (!matchDfmtNfmt(Dfmt, Nfmt, FormatStr, FormatLoc))
7835 return ParseStatus::Failure;
7836
7837 if (trySkipToken(AsmToken::Comma)) {
7838 StringRef Str;
7839 SMLoc Loc = getLoc();
7840 if (!parseId(Str, "expected a format string") ||
7841 !matchDfmtNfmt(Dfmt, Nfmt, Str, Loc))
7842 return ParseStatus::Failure;
7843 if (Dfmt == DFMT_UNDEF)
7844 return Error(Loc, "duplicate numeric format");
7845 if (Nfmt == NFMT_UNDEF)
7846 return Error(Loc, "duplicate data format");
7847 }
7848
7849 Dfmt = (Dfmt == DFMT_UNDEF) ? DFMT_DEFAULT : Dfmt;
7850 Nfmt = (Nfmt == NFMT_UNDEF) ? NFMT_DEFAULT : Nfmt;
7851
7852 if (isGFX10Plus()) {
7853 auto Ufmt = convertDfmtNfmt2Ufmt(Dfmt, Nfmt, getSTI());
7854 if (Ufmt == UFMT_UNDEF)
7855 return Error(FormatLoc, "unsupported format");
7856 Format = Ufmt;
7857 } else {
7858 Format = encodeDfmtNfmt(Dfmt, Nfmt);
7859 }
7860
7861 return ParseStatus::Success;
7862}
7863
7864ParseStatus AMDGPUAsmParser::parseSymbolicUnifiedFormat(StringRef FormatStr,
7865 SMLoc Loc,
7866 int64_t &Format) {
7867 using namespace llvm::AMDGPU::MTBUFFormat;
7868
7869 auto Id = getUnifiedFormat(FormatStr, getSTI());
7870 if (Id == UFMT_UNDEF)
7871 return ParseStatus::NoMatch;
7872
7873 if (!isGFX10Plus())
7874 return Error(Loc, "unified format is not supported on this GPU");
7875
7876 Format = Id;
7877 return ParseStatus::Success;
7878}
7879
7880ParseStatus AMDGPUAsmParser::parseNumericFormat(int64_t &Format) {
7881 using namespace llvm::AMDGPU::MTBUFFormat;
7882 SMLoc Loc = getLoc();
7883
7884 if (!parseExpr(Format))
7885 return ParseStatus::Failure;
7886 if (!isValidFormatEncoding(Format, getSTI()))
7887 return Error(Loc, "out of range format");
7888
7889 return ParseStatus::Success;
7890}
7891
7892ParseStatus AMDGPUAsmParser::parseSymbolicOrNumericFormat(int64_t &Format) {
7893 using namespace llvm::AMDGPU::MTBUFFormat;
7894
7895 if (!trySkipId("format", AsmToken::Colon))
7896 return ParseStatus::NoMatch;
7897
7898 if (trySkipToken(AsmToken::LBrac)) {
7899 StringRef FormatStr;
7900 SMLoc Loc = getLoc();
7901 if (!parseId(FormatStr, "expected a format string"))
7902 return ParseStatus::Failure;
7903
7904 auto Res = parseSymbolicUnifiedFormat(FormatStr, Loc, Format);
7905 if (Res.isNoMatch())
7906 Res = parseSymbolicSplitFormat(FormatStr, Loc, Format);
7907 if (!Res.isSuccess())
7908 return Res;
7909
7910 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket"))
7911 return ParseStatus::Failure;
7912
7913 return ParseStatus::Success;
7914 }
7915
7916 return parseNumericFormat(Format);
7917}
7918
7919ParseStatus AMDGPUAsmParser::parseFORMAT(OperandVector &Operands) {
7920 using namespace llvm::AMDGPU::MTBUFFormat;
7921
7922 int64_t Format = getDefaultFormatEncoding(getSTI());
7923 ParseStatus Res;
7924 SMLoc Loc = getLoc();
7925
7926 // Parse legacy format syntax.
7927 Res = isGFX10Plus() ? parseUfmt(Format) : parseDfmtNfmt(Format);
7928 if (Res.isFailure())
7929 return Res;
7930
7931 bool FormatFound = Res.isSuccess();
7932
7933 Operands.push_back(
7934 AMDGPUOperand::CreateImm(this, Format, Loc, AMDGPUOperand::ImmTyFORMAT));
7935
7936 if (FormatFound)
7937 trySkipToken(AsmToken::Comma);
7938
7939 if (isToken(AsmToken::EndOfStatement)) {
7940 // We are expecting an soffset operand,
7941 // but let matcher handle the error.
7942 return ParseStatus::Success;
7943 }
7944
7945 // Parse soffset.
7946 Res = parseRegOrImm(Operands);
7947 if (!Res.isSuccess())
7948 return Res;
7949
7950 trySkipToken(AsmToken::Comma);
7951
7952 if (!FormatFound) {
7953 Res = parseSymbolicOrNumericFormat(Format);
7954 if (Res.isFailure())
7955 return Res;
7956 if (Res.isSuccess()) {
7957 auto Size = Operands.size();
7958 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands[Size - 2]);
7959 assert(Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyFORMAT);
7960 Op.setImm(Format);
7961 }
7962 return ParseStatus::Success;
7963 }
7964
7965 if (isId("format") && peekToken().is(AsmToken::Colon))
7966 return Error(getLoc(), "duplicate format");
7967 return ParseStatus::Success;
7968}
7969
7970ParseStatus AMDGPUAsmParser::parseFlatOffset(OperandVector &Operands) {
7971 ParseStatus Res =
7972 parseIntWithPrefix("offset", Operands, AMDGPUOperand::ImmTyOffset);
7973 if (Res.isNoMatch()) {
7974 Res = parseIntWithPrefix("inst_offset", Operands,
7975 AMDGPUOperand::ImmTyInstOffset);
7976 }
7977 return Res;
7978}
7979
7980ParseStatus AMDGPUAsmParser::parseR128A16(OperandVector &Operands) {
7981 ParseStatus Res =
7982 parseNamedBit("r128", Operands, AMDGPUOperand::ImmTyR128A16);
7983 if (Res.isNoMatch())
7984 Res = parseNamedBit("a16", Operands, AMDGPUOperand::ImmTyA16);
7985 return Res;
7986}
7987
7988ParseStatus AMDGPUAsmParser::parseBLGP(OperandVector &Operands) {
7989 ParseStatus Res =
7990 parseIntWithPrefix("blgp", Operands, AMDGPUOperand::ImmTyBLGP);
7991 if (Res.isNoMatch()) {
7992 Res =
7993 parseOperandArrayWithPrefix("neg", Operands, AMDGPUOperand::ImmTyBLGP);
7994 }
7995 return Res;
7996}
7997
7998//===----------------------------------------------------------------------===//
7999// Exp
8000//===----------------------------------------------------------------------===//
8001
8002void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
8003 OptionalImmIndexMap OptionalIdx;
8004
8005 unsigned OperandIdx[4];
8006 unsigned EnMask = 0;
8007 int SrcIdx = 0;
8008
8009 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
8010 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
8011
8012 // Add the register arguments
8013 if (Op.isReg()) {
8014 assert(SrcIdx < 4);
8015 OperandIdx[SrcIdx] = Inst.size();
8016 Op.addRegOperands(Inst, 1);
8017 ++SrcIdx;
8018 continue;
8019 }
8020
8021 if (Op.isOff()) {
8022 assert(SrcIdx < 4);
8023 OperandIdx[SrcIdx] = Inst.size();
8024 Inst.addOperand(MCOperand::createReg(MCRegister()));
8025 ++SrcIdx;
8026 continue;
8027 }
8028
8029 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) {
8030 Op.addImmOperands(Inst, 1);
8031 continue;
8032 }
8033
8034 if (Op.isToken() && (Op.getToken() == "done" || Op.getToken() == "row_en"))
8035 continue;
8036
8037 // Handle optional arguments
8038 OptionalIdx[Op.getImmTy()] = i;
8039 }
8040
8041 assert(SrcIdx == 4);
8042
8043 bool Compr = false;
8044 if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) {
8045 Compr = true;
8046 Inst.getOperand(OperandIdx[1]) = Inst.getOperand(OperandIdx[2]);
8047 Inst.getOperand(OperandIdx[2]).setReg(MCRegister());
8048 Inst.getOperand(OperandIdx[3]).setReg(MCRegister());
8049 }
8050
8051 for (auto i = 0; i < SrcIdx; ++i) {
8052 if (Inst.getOperand(OperandIdx[i]).getReg()) {
8053 EnMask |= Compr ? (0x3 << i * 2) : (0x1 << i);
8054 }
8055 }
8056
8057 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM);
8058 addOptionalImmOperand(Inst, Operands, OptionalIdx,
8059 AMDGPUOperand::ImmTyExpCompr);
8060
8061 Inst.addOperand(MCOperand::createImm(EnMask));
8062}
8063
8064//===----------------------------------------------------------------------===//
8065// s_waitcnt
8066//===----------------------------------------------------------------------===//
8067
8068static bool encodeCnt(const AMDGPU::IsaVersion ISA, int64_t &IntVal,
8069 int64_t CntVal, bool Saturate,
8070 unsigned (*encode)(const IsaVersion &Version, unsigned,
8071 unsigned),
8072 unsigned (*decode)(const IsaVersion &Version, unsigned)) {
8073 bool Failed = false;
8074
8075 IntVal = encode(ISA, IntVal, CntVal);
8076 if (CntVal != decode(ISA, IntVal)) {
8077 if (Saturate) {
8078 IntVal = encode(ISA, IntVal, -1);
8079 } else {
8080 Failed = true;
8081 }
8082 }
8083 return Failed;
8084}
8085
8086bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
8087
8088 SMLoc CntLoc = getLoc();
8089 StringRef CntName = getTokenStr();
8090
8091 if (!skipToken(AsmToken::Identifier, "expected a counter name") ||
8092 !skipToken(AsmToken::LParen, "expected a left parenthesis"))
8093 return false;
8094
8095 int64_t CntVal;
8096 SMLoc ValLoc = getLoc();
8097 if (!parseExpr(CntVal))
8098 return false;
8099
8100 bool Failed = true;
8101 bool Sat = CntName.ends_with("_sat");
8102
8103 if (CntName == "vmcnt" || CntName == "vmcnt_sat") {
8104 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeVmcnt, decodeVmcnt);
8105 } else if (CntName == "expcnt" || CntName == "expcnt_sat") {
8106 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeExpcnt, decodeExpcnt);
8107 } else if (CntName == "lgkmcnt" || CntName == "lgkmcnt_sat") {
8108 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeLgkmcnt, decodeLgkmcnt);
8109 } else {
8110 Error(CntLoc, "invalid counter name " + CntName);
8111 return false;
8112 }
8113
8114 if (Failed) {
8115 Error(ValLoc, "too large value for " + CntName);
8116 return false;
8117 }
8118
8119 if (!skipToken(AsmToken::RParen, "expected a closing parenthesis"))
8120 return false;
8121
8122 if (trySkipToken(AsmToken::Amp) || trySkipToken(AsmToken::Comma)) {
8123 if (isToken(AsmToken::EndOfStatement)) {
8124 Error(getLoc(), "expected a counter name");
8125 return false;
8126 }
8127 }
8128
8129 return true;
8130}
8131
8132ParseStatus AMDGPUAsmParser::parseSWaitCnt(OperandVector &Operands) {
8133 int64_t Waitcnt = getWaitcntBitMask(ISA);
8134 SMLoc S = getLoc();
8135
8136 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) {
8137 while (!isToken(AsmToken::EndOfStatement)) {
8138 if (!parseCnt(Waitcnt))
8139 return ParseStatus::Failure;
8140 }
8141 } else {
8142 if (!parseExpr(Waitcnt))
8143 return ParseStatus::Failure;
8144 }
8145
8146 Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S));
8147 return ParseStatus::Success;
8148}
8149
8150bool AMDGPUAsmParser::parseDelay(int64_t &Delay) {
8151 SMLoc FieldLoc = getLoc();
8152 StringRef FieldName = getTokenStr();
8153 if (!skipToken(AsmToken::Identifier, "expected a field name") ||
8154 !skipToken(AsmToken::LParen, "expected a left parenthesis"))
8155 return false;
8156
8157 SMLoc ValueLoc = getLoc();
8158 StringRef ValueName = getTokenStr();
8159 if (!skipToken(AsmToken::Identifier, "expected a value name") ||
8160 !skipToken(AsmToken::RParen, "expected a right parenthesis"))
8161 return false;
8162
8163 unsigned Shift;
8164 if (FieldName == "instid0") {
8165 Shift = 0;
8166 } else if (FieldName == "instskip") {
8167 Shift = 4;
8168 } else if (FieldName == "instid1") {
8169 Shift = 7;
8170 } else {
8171 Error(FieldLoc, "invalid field name " + FieldName);
8172 return false;
8173 }
8174
8175 int Value;
8176 if (Shift == 4) {
8177 // Parse values for instskip.
8178 Value = StringSwitch<int>(ValueName)
8179 .Case("SAME", 0)
8180 .Case("NEXT", 1)
8181 .Case("SKIP_1", 2)
8182 .Case("SKIP_2", 3)
8183 .Case("SKIP_3", 4)
8184 .Case("SKIP_4", 5)
8185 .Default(-1);
8186 } else {
8187 // Parse values for instid0 and instid1.
8188 Value = StringSwitch<int>(ValueName)
8189 .Case("NO_DEP", 0)
8190 .Case("VALU_DEP_1", 1)
8191 .Case("VALU_DEP_2", 2)
8192 .Case("VALU_DEP_3", 3)
8193 .Case("VALU_DEP_4", 4)
8194 .Case("TRANS32_DEP_1", 5)
8195 .Case("TRANS32_DEP_2", 6)
8196 .Case("TRANS32_DEP_3", 7)
8197 .Case("FMA_ACCUM_CYCLE_1", 8)
8198 .Case("SALU_CYCLE_1", 9)
8199 .Case("SALU_CYCLE_2", 10)
8200 .Case("SALU_CYCLE_3", 11)
8201 .Default(-1);
8202 }
8203 if (Value < 0) {
8204 Error(ValueLoc, "invalid value name " + ValueName);
8205 return false;
8206 }
8207
8208 Delay |= Value << Shift;
8209 return true;
8210}
8211
8212ParseStatus AMDGPUAsmParser::parseSDelayALU(OperandVector &Operands) {
8213 int64_t Delay = 0;
8214 SMLoc S = getLoc();
8215
8216 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) {
8217 do {
8218 if (!parseDelay(Delay))
8219 return ParseStatus::Failure;
8220 } while (trySkipToken(AsmToken::Pipe));
8221 } else {
8222 if (!parseExpr(Delay))
8223 return ParseStatus::Failure;
8224 }
8225
8226 Operands.push_back(AMDGPUOperand::CreateImm(this, Delay, S));
8227 return ParseStatus::Success;
8228}
8229
8230bool AMDGPUOperand::isSWaitCnt() const { return isImm(); }
8231
8232bool AMDGPUOperand::isSDelayALU() const { return isImm(); }
8233
8234//===----------------------------------------------------------------------===//
8235// DepCtr
8236//===----------------------------------------------------------------------===//
8237
8238void AMDGPUAsmParser::depCtrError(SMLoc Loc, int ErrorId,
8239 StringRef DepCtrName) {
8240 switch (ErrorId) {
8241 case OPR_ID_UNKNOWN:
8242 Error(Loc, Twine("invalid counter name ", DepCtrName));
8243 return;
8244 case OPR_ID_UNSUPPORTED:
8245 Error(Loc, Twine(DepCtrName, " is not supported on this GPU"));
8246 return;
8247 case OPR_ID_DUPLICATE:
8248 Error(Loc, Twine("duplicate counter name ", DepCtrName));
8249 return;
8250 case OPR_VAL_INVALID:
8251 Error(Loc, Twine("invalid value for ", DepCtrName));
8252 return;
8253 default:
8254 assert(false);
8255 }
8256}
8257
8258bool AMDGPUAsmParser::parseDepCtr(int64_t &DepCtr, unsigned &UsedOprMask) {
8259
8260 using namespace llvm::AMDGPU::DepCtr;
8261
8262 SMLoc DepCtrLoc = getLoc();
8263 StringRef DepCtrName = getTokenStr();
8264
8265 if (!skipToken(AsmToken::Identifier, "expected a counter name") ||
8266 !skipToken(AsmToken::LParen, "expected a left parenthesis"))
8267 return false;
8268
8269 int64_t ExprVal;
8270 if (!parseExpr(ExprVal))
8271 return false;
8272
8273 unsigned PrevOprMask = UsedOprMask;
8274 int CntVal = encodeDepCtr(DepCtrName, ExprVal, UsedOprMask, getSTI());
8275
8276 if (CntVal < 0) {
8277 depCtrError(DepCtrLoc, CntVal, DepCtrName);
8278 return false;
8279 }
8280
8281 if (!skipToken(AsmToken::RParen, "expected a closing parenthesis"))
8282 return false;
8283
8284 if (trySkipToken(AsmToken::Amp) || trySkipToken(AsmToken::Comma)) {
8285 if (isToken(AsmToken::EndOfStatement)) {
8286 Error(getLoc(), "expected a counter name");
8287 return false;
8288 }
8289 }
8290
8291 int64_t CntValMask = PrevOprMask ^ UsedOprMask;
8292 DepCtr = (DepCtr & ~CntValMask) | CntVal;
8293 return true;
8294}
8295
8296ParseStatus AMDGPUAsmParser::parseDepCtr(OperandVector &Operands) {
8297 using namespace llvm::AMDGPU::DepCtr;
8298
8299 int64_t DepCtr = getDefaultDepCtrEncoding(getSTI());
8300 SMLoc Loc = getLoc();
8301
8302 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) {
8303 unsigned UsedOprMask = 0;
8304 while (!isToken(AsmToken::EndOfStatement)) {
8305 if (!parseDepCtr(DepCtr, UsedOprMask))
8306 return ParseStatus::Failure;
8307 }
8308 } else {
8309 if (!parseExpr(DepCtr))
8310 return ParseStatus::Failure;
8311 }
8312
8313 Operands.push_back(AMDGPUOperand::CreateImm(this, DepCtr, Loc));
8314 return ParseStatus::Success;
8315}
8316
8317bool AMDGPUOperand::isDepCtr() const { return isS16Imm(); }
8318
8319//===----------------------------------------------------------------------===//
8320// hwreg
8321//===----------------------------------------------------------------------===//
8322
8323ParseStatus AMDGPUAsmParser::parseHwregFunc(OperandInfoTy &HwReg,
8324 OperandInfoTy &Offset,
8325 OperandInfoTy &Width) {
8326 using namespace llvm::AMDGPU::Hwreg;
8327
8328 if (!trySkipId("hwreg", AsmToken::LParen))
8329 return ParseStatus::NoMatch;
8330
8331 // The register may be specified by name or using a numeric code
8332 HwReg.Loc = getLoc();
8333 if (isToken(AsmToken::Identifier) &&
8334 (HwReg.Val = getHwregId(getTokenStr(), getSTI())) != OPR_ID_UNKNOWN) {
8335 HwReg.IsSymbolic = true;
8336 lex(); // skip register name
8337 } else if (!parseExpr(HwReg.Val, "a register name")) {
8338 return ParseStatus::Failure;
8339 }
8340
8341 if (trySkipToken(AsmToken::RParen))
8342 return ParseStatus::Success;
8343
8344 // parse optional params
8345 if (!skipToken(AsmToken::Comma, "expected a comma or a closing parenthesis"))
8346 return ParseStatus::Failure;
8347
8348 Offset.Loc = getLoc();
8349 if (!parseExpr(Offset.Val))
8350 return ParseStatus::Failure;
8351
8352 if (!skipToken(AsmToken::Comma, "expected a comma"))
8353 return ParseStatus::Failure;
8354
8355 Width.Loc = getLoc();
8356 if (!parseExpr(Width.Val) ||
8357 !skipToken(AsmToken::RParen, "expected a closing parenthesis"))
8358 return ParseStatus::Failure;
8359
8360 return ParseStatus::Success;
8361}
8362
8363ParseStatus AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
8364 using namespace llvm::AMDGPU::Hwreg;
8365
8366 int64_t ImmVal = 0;
8367 SMLoc Loc = getLoc();
8368
8369 StructuredOpField HwReg("id", "hardware register", HwregId::Width,
8370 HwregId::Default);
8371 StructuredOpField Offset("offset", "bit offset", HwregOffset::Width,
8372 HwregOffset::Default);
8373 struct : StructuredOpField {
8374 using StructuredOpField::StructuredOpField;
8375 bool validate(AMDGPUAsmParser &Parser) const override {
8376 if (!isUIntN(Width, Val - 1))
8377 return Error(Parser, "only values from 1 to 32 are legal");
8378 return true;
8379 }
8380 } Width("size", "bitfield width", HwregSize::Width, HwregSize::Default);
8381 ParseStatus Res = parseStructuredOpFields({&HwReg, &Offset, &Width});
8382
8383 if (Res.isNoMatch())
8384 Res = parseHwregFunc(HwReg, Offset, Width);
8385
8386 if (Res.isSuccess()) {
8387 if (!validateStructuredOpFields({&HwReg, &Offset, &Width}))
8388 return ParseStatus::Failure;
8389 ImmVal = HwregEncoding::encode(HwReg.Val, Offset.Val, Width.Val);
8390 }
8391
8392 if (Res.isNoMatch() &&
8393 parseExpr(ImmVal, "a hwreg macro, structured immediate"))
8395
8396 if (!Res.isSuccess())
8397 return ParseStatus::Failure;
8398
8399 if (!isUInt<16>(ImmVal))
8400 return Error(Loc, "invalid immediate: only 16-bit values are legal");
8401 Operands.push_back(
8402 AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTyHwreg));
8403 return ParseStatus::Success;
8404}
8405
8406bool AMDGPUOperand::isHwreg() const { return isImmTy(ImmTyHwreg); }
8407
8408//===----------------------------------------------------------------------===//
8409// sendmsg
8410//===----------------------------------------------------------------------===//
8411
8412bool AMDGPUAsmParser::parseSendMsgBody(OperandInfoTy &Msg, OperandInfoTy &Op,
8413 OperandInfoTy &Stream) {
8414 using namespace llvm::AMDGPU::SendMsg;
8415
8416 Msg.Loc = getLoc();
8417 if (isToken(AsmToken::Identifier) &&
8418 (Msg.Val = getMsgId(getTokenStr(), getSTI())) != OPR_ID_UNKNOWN) {
8419 Msg.IsSymbolic = true;
8420 lex(); // skip message name
8421 } else if (!parseExpr(Msg.Val, "a message name")) {
8422 return false;
8423 }
8424
8425 if (trySkipToken(AsmToken::Comma)) {
8426 Op.IsDefined = true;
8427 Op.Loc = getLoc();
8428 if (isToken(AsmToken::Identifier) &&
8429 (Op.Val = getMsgOpId(Msg.Val, getTokenStr(), getSTI())) !=
8431 lex(); // skip operation name
8432 } else if (!parseExpr(Op.Val, "an operation name")) {
8433 return false;
8434 }
8435
8436 if (trySkipToken(AsmToken::Comma)) {
8437 Stream.IsDefined = true;
8438 Stream.Loc = getLoc();
8439 if (!parseExpr(Stream.Val))
8440 return false;
8441 }
8442 }
8443
8444 return skipToken(AsmToken::RParen, "expected a closing parenthesis");
8445}
8446
8447bool AMDGPUAsmParser::validateSendMsg(const OperandInfoTy &Msg,
8448 const OperandInfoTy &Op,
8449 const OperandInfoTy &Stream) {
8450 using namespace llvm::AMDGPU::SendMsg;
8451
8452 // Validation strictness depends on whether message is specified
8453 // in a symbolic or in a numeric form. In the latter case
8454 // only encoding possibility is checked.
8455 bool Strict = Msg.IsSymbolic;
8456
8457 if (Strict) {
8458 if (Msg.Val == OPR_ID_UNSUPPORTED) {
8459 Error(Msg.Loc, "specified message id is not supported on this GPU");
8460 return false;
8461 }
8462 } else {
8463 if (!isValidMsgId(Msg.Val, getSTI())) {
8464 Error(Msg.Loc, "invalid message id");
8465 return false;
8466 }
8467 }
8468 if (Strict && (msgRequiresOp(Msg.Val, getSTI()) != Op.IsDefined)) {
8469 if (Op.IsDefined) {
8470 Error(Op.Loc, "message does not support operations");
8471 } else {
8472 Error(Msg.Loc, "missing message operation");
8473 }
8474 return false;
8475 }
8476 if (!isValidMsgOp(Msg.Val, Op.Val, getSTI(), Strict)) {
8477 if (Op.Val == OPR_ID_UNSUPPORTED)
8478 Error(Op.Loc, "specified operation id is not supported on this GPU");
8479 else
8480 Error(Op.Loc, "invalid operation id");
8481 return false;
8482 }
8483 if (Strict && !msgSupportsStream(Msg.Val, Op.Val, getSTI()) &&
8484 Stream.IsDefined) {
8485 Error(Stream.Loc, "message operation does not support streams");
8486 return false;
8487 }
8488 if (!isValidMsgStream(Msg.Val, Op.Val, Stream.Val, getSTI(), Strict)) {
8489 Error(Stream.Loc, "invalid message stream id");
8490 return false;
8491 }
8492 return true;
8493}
8494
8495ParseStatus AMDGPUAsmParser::parseSendMsg(OperandVector &Operands) {
8496 using namespace llvm::AMDGPU::SendMsg;
8497
8498 int64_t ImmVal = 0;
8499 SMLoc Loc = getLoc();
8500
8501 if (trySkipId("sendmsg", AsmToken::LParen)) {
8502 OperandInfoTy Msg(OPR_ID_UNKNOWN);
8503 OperandInfoTy Op(OP_NONE_);
8504 OperandInfoTy Stream(STREAM_ID_NONE_);
8505 if (parseSendMsgBody(Msg, Op, Stream) && validateSendMsg(Msg, Op, Stream)) {
8506 ImmVal = encodeMsg(Msg.Val, Op.Val, Stream.Val);
8507 } else {
8508 return ParseStatus::Failure;
8509 }
8510 } else if (parseExpr(ImmVal, "a sendmsg macro")) {
8511 if (ImmVal < 0 || !isUInt<16>(ImmVal))
8512 return Error(Loc, "invalid immediate: only 16-bit values are legal");
8513 } else {
8514 return ParseStatus::Failure;
8515 }
8516
8517 Operands.push_back(
8518 AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTySendMsg));
8519 return ParseStatus::Success;
8520}
8521
8522bool AMDGPUOperand::isSendMsg() const { return isImmTy(ImmTySendMsg); }
8523
8524ParseStatus AMDGPUAsmParser::parseWaitEvent(OperandVector &Operands) {
8525 using namespace llvm::AMDGPU::WaitEvent;
8526
8527 SMLoc Loc = getLoc();
8528 int64_t ImmVal = 0;
8529
8530 StructuredOpField DontWaitExportReady("dont_wait_export_ready", "bit value",
8531 1, 0);
8532 StructuredOpField ExportReady("export_ready", "bit value", 1, 0);
8533
8534 StructuredOpField *TargetBitfield =
8535 isGFX11() ? &DontWaitExportReady : &ExportReady;
8536
8537 ParseStatus Res = parseStructuredOpFields({TargetBitfield});
8538 if (Res.isNoMatch() && parseExpr(ImmVal, "structured immediate"))
8540 else if (Res.isSuccess()) {
8541 if (!validateStructuredOpFields({TargetBitfield}))
8542 return ParseStatus::Failure;
8543 ImmVal = TargetBitfield->Val;
8544 }
8545
8546 if (!Res.isSuccess())
8547 return ParseStatus::Failure;
8548
8549 if (!isUInt<16>(ImmVal))
8550 return Error(Loc, "invalid immediate: only 16-bit values are legal");
8551
8552 Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc,
8553 AMDGPUOperand::ImmTyWaitEvent));
8554 return ParseStatus::Success;
8555}
8556
8557bool AMDGPUOperand::isWaitEvent() const { return isImmTy(ImmTyWaitEvent); }
8558
8559//===----------------------------------------------------------------------===//
8560// v_interp
8561//===----------------------------------------------------------------------===//
8562
8563ParseStatus AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) {
8564 StringRef Str;
8565 SMLoc S = getLoc();
8566
8567 if (!parseId(Str))
8568 return ParseStatus::NoMatch;
8569
8570 int Slot = StringSwitch<int>(Str)
8571 .Case("p10", 0)
8572 .Case("p20", 1)
8573 .Case("p0", 2)
8574 .Default(-1);
8575
8576 if (Slot == -1)
8577 return Error(S, "invalid interpolation slot");
8578
8579 Operands.push_back(
8580 AMDGPUOperand::CreateImm(this, Slot, S, AMDGPUOperand::ImmTyInterpSlot));
8581 return ParseStatus::Success;
8582}
8583
8584ParseStatus AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) {
8585 StringRef Str;
8586 SMLoc S = getLoc();
8587
8588 if (!parseId(Str))
8589 return ParseStatus::NoMatch;
8590
8591 if (!Str.starts_with("attr"))
8592 return Error(S, "invalid interpolation attribute");
8593
8594 StringRef Chan = Str.take_back(2);
8595 int AttrChan = StringSwitch<int>(Chan)
8596 .Case(".x", 0)
8597 .Case(".y", 1)
8598 .Case(".z", 2)
8599 .Case(".w", 3)
8600 .Default(-1);
8601 if (AttrChan == -1)
8602 return Error(S, "invalid or missing interpolation attribute channel");
8603
8604 Str = Str.drop_back(2).drop_front(4);
8605
8606 uint8_t Attr;
8607 if (Str.getAsInteger(10, Attr))
8608 return Error(S, "invalid or missing interpolation attribute number");
8609
8610 if (Attr > 32)
8611 return Error(S, "out of bounds interpolation attribute number");
8612
8613 SMLoc SChan = SMLoc::getFromPointer(Chan.data());
8614
8615 Operands.push_back(
8616 AMDGPUOperand::CreateImm(this, Attr, S, AMDGPUOperand::ImmTyInterpAttr));
8617 Operands.push_back(AMDGPUOperand::CreateImm(
8618 this, AttrChan, SChan, AMDGPUOperand::ImmTyInterpAttrChan));
8619 return ParseStatus::Success;
8620}
8621
8622//===----------------------------------------------------------------------===//
8623// exp
8624//===----------------------------------------------------------------------===//
8625
8626ParseStatus AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) {
8627 using namespace llvm::AMDGPU::Exp;
8628
8629 StringRef Str;
8630 SMLoc S = getLoc();
8631
8632 if (!parseId(Str))
8633 return ParseStatus::NoMatch;
8634
8635 unsigned Id = getTgtId(Str);
8636 if (Id == ET_INVALID || !isSupportedTgtId(Id, getSTI()))
8637 return Error(S, (Id == ET_INVALID)
8638 ? "invalid exp target"
8639 : "exp target is not supported on this GPU");
8640
8641 Operands.push_back(
8642 AMDGPUOperand::CreateImm(this, Id, S, AMDGPUOperand::ImmTyExpTgt));
8643 return ParseStatus::Success;
8644}
8645
8646//===----------------------------------------------------------------------===//
8647// parser helpers
8648//===----------------------------------------------------------------------===//
8649
8650bool AMDGPUAsmParser::isId(const AsmToken &Token, const StringRef Id) const {
8651 return Token.is(AsmToken::Identifier) && Token.getString() == Id;
8652}
8653
8654bool AMDGPUAsmParser::isId(const StringRef Id) const {
8655 return isId(getToken(), Id);
8656}
8657
8658bool AMDGPUAsmParser::isToken(const AsmToken::TokenKind Kind) const {
8659 return getTokenKind() == Kind;
8660}
8661
8662StringRef AMDGPUAsmParser::getId() const {
8663 return isToken(AsmToken::Identifier) ? getTokenStr() : StringRef();
8664}
8665
8666bool AMDGPUAsmParser::trySkipId(const StringRef Id) {
8667 if (isId(Id)) {
8668 lex();
8669 return true;
8670 }
8671 return false;
8672}
8673
8674bool AMDGPUAsmParser::trySkipId(const StringRef Pref, const StringRef Id) {
8675 if (isToken(AsmToken::Identifier)) {
8676 StringRef Tok = getTokenStr();
8677 if (Tok.starts_with(Pref) && Tok.drop_front(Pref.size()) == Id) {
8678 lex();
8679 return true;
8680 }
8681 }
8682 return false;
8683}
8684
8685bool AMDGPUAsmParser::trySkipId(const StringRef Id,
8686 const AsmToken::TokenKind Kind) {
8687 if (isId(Id) && peekToken().is(Kind)) {
8688 lex();
8689 lex();
8690 return true;
8691 }
8692 return false;
8693}
8694
8695bool AMDGPUAsmParser::trySkipToken(const AsmToken::TokenKind Kind) {
8696 if (isToken(Kind)) {
8697 lex();
8698 return true;
8699 }
8700 return false;
8701}
8702
8703bool AMDGPUAsmParser::skipToken(const AsmToken::TokenKind Kind,
8704 const StringRef ErrMsg) {
8705 if (!trySkipToken(Kind)) {
8706 Error(getLoc(), ErrMsg);
8707 return false;
8708 }
8709 return true;
8710}
8711
8712bool AMDGPUAsmParser::parseExpr(int64_t &Imm, StringRef Expected) {
8713 SMLoc S = getLoc();
8714
8715 const MCExpr *Expr;
8716 if (Parser.parseExpression(Expr))
8717 return false;
8718
8719 if (Expr->evaluateAsAbsolute(Imm))
8720 return true;
8721
8722 if (Expected.empty()) {
8723 Error(S, "expected absolute expression");
8724 } else {
8725 Error(S,
8726 Twine("expected ", Expected) + Twine(" or an absolute expression"));
8727 }
8728 return false;
8729}
8730
8731bool AMDGPUAsmParser::parseExpr(OperandVector &Operands) {
8732 SMLoc S = getLoc();
8733
8734 const MCExpr *Expr;
8735 if (Parser.parseExpression(Expr))
8736 return false;
8737
8738 int64_t IntVal;
8739 if (Expr->evaluateAsAbsolute(IntVal)) {
8740 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
8741 } else {
8742 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
8743 }
8744 return true;
8745}
8746
8747bool AMDGPUAsmParser::parseString(StringRef &Val, const StringRef ErrMsg) {
8748 if (isToken(AsmToken::String)) {
8749 Val = getToken().getStringContents();
8750 lex();
8751 return true;
8752 }
8753 Error(getLoc(), ErrMsg);
8754 return false;
8755}
8756
8757bool AMDGPUAsmParser::parseId(StringRef &Val, const StringRef ErrMsg) {
8758 if (isToken(AsmToken::Identifier)) {
8759 Val = getTokenStr();
8760 lex();
8761 return true;
8762 }
8763 if (!ErrMsg.empty())
8764 Error(getLoc(), ErrMsg);
8765 return false;
8766}
8767
8768AsmToken AMDGPUAsmParser::getToken() const { return Parser.getTok(); }
8769
8770AsmToken AMDGPUAsmParser::peekToken(bool ShouldSkipSpace) {
8771 return isToken(AsmToken::EndOfStatement)
8772 ? getToken()
8773 : getLexer().peekTok(ShouldSkipSpace);
8774}
8775
8776void AMDGPUAsmParser::peekTokens(MutableArrayRef<AsmToken> Tokens) {
8777 auto TokCount = getLexer().peekTokens(Tokens);
8778
8779 for (auto Idx = TokCount; Idx < Tokens.size(); ++Idx)
8780 Tokens[Idx] = AsmToken(AsmToken::Error, "");
8781}
8782
8783AsmToken::TokenKind AMDGPUAsmParser::getTokenKind() const {
8784 return getLexer().getKind();
8785}
8786
8787SMLoc AMDGPUAsmParser::getLoc() const { return getToken().getLoc(); }
8788
8789StringRef AMDGPUAsmParser::getTokenStr() const {
8790 return getToken().getString();
8791}
8792
8793void AMDGPUAsmParser::lex() { Parser.Lex(); }
8794
8795const AMDGPUOperand &
8796AMDGPUAsmParser::findMCOperand(const OperandVector &Operands,
8797 int MCOpIdx) const {
8798 for (const auto &Op : Operands) {
8799 const AMDGPUOperand &TargetOp = static_cast<AMDGPUOperand &>(*Op);
8800 if (TargetOp.getMCOpIdx() == MCOpIdx)
8801 return TargetOp;
8802 }
8803 llvm_unreachable("no such MC operand!");
8804}
8805
8806SMLoc AMDGPUAsmParser::getInstLoc(const OperandVector &Operands) const {
8807 return ((AMDGPUOperand &)*Operands[0]).getStartLoc();
8808}
8809
8810// Returns one of the given locations that comes later in the source.
8811SMLoc AMDGPUAsmParser::getLaterLoc(SMLoc a, SMLoc b) {
8812 return a.getPointer() < b.getPointer() ? b : a;
8813}
8814
8815SMLoc AMDGPUAsmParser::getOperandLoc(const OperandVector &Operands,
8816 int MCOpIdx) const {
8817 return findMCOperand(Operands, MCOpIdx).getStartLoc();
8818}
8819
8820SMLoc AMDGPUAsmParser::getOperandLoc(
8821 std::function<bool(const AMDGPUOperand &)> Test,
8822 const OperandVector &Operands) const {
8823 for (unsigned i = Operands.size() - 1; i > 0; --i) {
8824 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
8825 if (Test(Op))
8826 return Op.getStartLoc();
8827 }
8828 return getInstLoc(Operands);
8829}
8830
8831SMLoc AMDGPUAsmParser::getImmLoc(AMDGPUOperand::ImmTy Type,
8832 const OperandVector &Operands) const {
8833 auto Test = [=](const AMDGPUOperand &Op) { return Op.isImmTy(Type); };
8834 return getOperandLoc(Test, Operands);
8835}
8836
8837ParseStatus
8838AMDGPUAsmParser::parseStructuredOpFields(ArrayRef<StructuredOpField *> Fields) {
8839 if (!trySkipToken(AsmToken::LCurly))
8840 return ParseStatus::NoMatch;
8841
8842 bool First = true;
8843 while (!trySkipToken(AsmToken::RCurly)) {
8844 if (!First &&
8845 !skipToken(AsmToken::Comma, "comma or closing brace expected"))
8846 return ParseStatus::Failure;
8847
8848 StringRef Id = getTokenStr();
8849 SMLoc IdLoc = getLoc();
8850 if (!skipToken(AsmToken::Identifier, "field name expected") ||
8851 !skipToken(AsmToken::Colon, "colon expected"))
8852 return ParseStatus::Failure;
8853
8854 const auto *I =
8855 find_if(Fields, [Id](StructuredOpField *F) { return F->Id == Id; });
8856 if (I == Fields.end())
8857 return Error(IdLoc, "unknown field");
8858 if ((*I)->IsDefined)
8859 return Error(IdLoc, "duplicate field");
8860
8861 // TODO: Support symbolic values.
8862 (*I)->Loc = getLoc();
8863 if (!parseExpr((*I)->Val))
8864 return ParseStatus::Failure;
8865 (*I)->IsDefined = true;
8866
8867 First = false;
8868 }
8869 return ParseStatus::Success;
8870}
8871
8872bool AMDGPUAsmParser::validateStructuredOpFields(
8874 return all_of(Fields, [this](const StructuredOpField *F) {
8875 return F->validate(*this);
8876 });
8877}
8878
8879//===----------------------------------------------------------------------===//
8880// swizzle
8881//===----------------------------------------------------------------------===//
8882
8884static unsigned encodeBitmaskPerm(const unsigned AndMask, const unsigned OrMask,
8885 const unsigned XorMask) {
8886 using namespace llvm::AMDGPU::Swizzle;
8887
8888 return BITMASK_PERM_ENC | (AndMask << BITMASK_AND_SHIFT) |
8889 (OrMask << BITMASK_OR_SHIFT) | (XorMask << BITMASK_XOR_SHIFT);
8890}
8891
8892bool AMDGPUAsmParser::parseSwizzleOperand(int64_t &Op, const unsigned MinVal,
8893 const unsigned MaxVal,
8894 const Twine &ErrMsg, SMLoc &Loc) {
8895 if (!skipToken(AsmToken::Comma, "expected a comma")) {
8896 return false;
8897 }
8898 Loc = getLoc();
8899 if (!parseExpr(Op)) {
8900 return false;
8901 }
8902 if (Op < MinVal || Op > MaxVal) {
8903 Error(Loc, ErrMsg);
8904 return false;
8905 }
8906
8907 return true;
8908}
8909
8910bool AMDGPUAsmParser::parseSwizzleOperands(const unsigned OpNum, int64_t *Op,
8911 const unsigned MinVal,
8912 const unsigned MaxVal,
8913 const StringRef ErrMsg) {
8914 SMLoc Loc;
8915 for (unsigned i = 0; i < OpNum; ++i) {
8916 if (!parseSwizzleOperand(Op[i], MinVal, MaxVal, ErrMsg, Loc))
8917 return false;
8918 }
8919
8920 return true;
8921}
8922
8923bool AMDGPUAsmParser::parseSwizzleQuadPerm(int64_t &Imm) {
8924 using namespace llvm::AMDGPU::Swizzle;
8925
8926 int64_t Lane[LANE_NUM];
8927 if (parseSwizzleOperands(LANE_NUM, Lane, 0, LANE_MAX,
8928 "expected a 2-bit lane id")) {
8930 for (unsigned I = 0; I < LANE_NUM; ++I) {
8931 Imm |= Lane[I] << (LANE_SHIFT * I);
8932 }
8933 return true;
8934 }
8935 return false;
8936}
8937
8938bool AMDGPUAsmParser::parseSwizzleBroadcast(int64_t &Imm) {
8939 using namespace llvm::AMDGPU::Swizzle;
8940
8941 SMLoc Loc;
8942 int64_t GroupSize;
8943 int64_t LaneIdx;
8944
8945 if (!parseSwizzleOperand(GroupSize, 2, 32,
8946 "group size must be in the interval [2,32]", Loc)) {
8947 return false;
8948 }
8949 if (!isPowerOf2_64(GroupSize)) {
8950 Error(Loc, "group size must be a power of two");
8951 return false;
8952 }
8953 if (parseSwizzleOperand(LaneIdx, 0, GroupSize - 1,
8954 "lane id must be in the interval [0,group size - 1]",
8955 Loc)) {
8956 Imm = encodeBitmaskPerm(BITMASK_MAX - GroupSize + 1, LaneIdx, 0);
8957 return true;
8958 }
8959 return false;
8960}
8961
8962bool AMDGPUAsmParser::parseSwizzleReverse(int64_t &Imm) {
8963 using namespace llvm::AMDGPU::Swizzle;
8964
8965 SMLoc Loc;
8966 int64_t GroupSize;
8967
8968 if (!parseSwizzleOperand(GroupSize, 2, 32,
8969 "group size must be in the interval [2,32]", Loc)) {
8970 return false;
8971 }
8972 if (!isPowerOf2_64(GroupSize)) {
8973 Error(Loc, "group size must be a power of two");
8974 return false;
8975 }
8976
8977 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize - 1);
8978 return true;
8979}
8980
8981bool AMDGPUAsmParser::parseSwizzleSwap(int64_t &Imm) {
8982 using namespace llvm::AMDGPU::Swizzle;
8983
8984 SMLoc Loc;
8985 int64_t GroupSize;
8986
8987 if (!parseSwizzleOperand(GroupSize, 1, 16,
8988 "group size must be in the interval [1,16]", Loc)) {
8989 return false;
8990 }
8991 if (!isPowerOf2_64(GroupSize)) {
8992 Error(Loc, "group size must be a power of two");
8993 return false;
8994 }
8995
8996 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize);
8997 return true;
8998}
8999
9000bool AMDGPUAsmParser::parseSwizzleBitmaskPerm(int64_t &Imm) {
9001 using namespace llvm::AMDGPU::Swizzle;
9002
9003 if (!skipToken(AsmToken::Comma, "expected a comma")) {
9004 return false;
9005 }
9006
9007 StringRef Ctl;
9008 SMLoc StrLoc = getLoc();
9009 if (!parseString(Ctl)) {
9010 return false;
9011 }
9012 if (Ctl.size() != BITMASK_WIDTH) {
9013 Error(StrLoc, "expected a 5-character mask");
9014 return false;
9015 }
9016
9017 unsigned AndMask = 0;
9018 unsigned OrMask = 0;
9019 unsigned XorMask = 0;
9020
9021 for (size_t i = 0; i < Ctl.size(); ++i) {
9022 unsigned Mask = 1 << (BITMASK_WIDTH - 1 - i);
9023 switch (Ctl[i]) {
9024 default:
9025 Error(StrLoc, "invalid mask");
9026 return false;
9027 case '0':
9028 break;
9029 case '1':
9030 OrMask |= Mask;
9031 break;
9032 case 'p':
9033 AndMask |= Mask;
9034 break;
9035 case 'i':
9036 AndMask |= Mask;
9037 XorMask |= Mask;
9038 break;
9039 }
9040 }
9041
9042 Imm = encodeBitmaskPerm(AndMask, OrMask, XorMask);
9043 return true;
9044}
9045
9046bool AMDGPUAsmParser::parseSwizzleFFT(int64_t &Imm) {
9047 using namespace llvm::AMDGPU::Swizzle;
9048
9049 if (!AMDGPU::isGFX9Plus(getSTI())) {
9050 Error(getLoc(), "FFT mode swizzle not supported on this GPU");
9051 return false;
9052 }
9053
9054 int64_t Swizzle;
9055 SMLoc Loc;
9056 if (!parseSwizzleOperand(Swizzle, 0, FFT_SWIZZLE_MAX,
9057 "FFT swizzle must be in the interval [0," +
9058 Twine(FFT_SWIZZLE_MAX) + Twine(']'),
9059 Loc))
9060 return false;
9061
9062 Imm = FFT_MODE_ENC | Swizzle;
9063 return true;
9064}
9065
9066bool AMDGPUAsmParser::parseSwizzleRotate(int64_t &Imm) {
9067 using namespace llvm::AMDGPU::Swizzle;
9068
9069 if (!AMDGPU::isGFX9Plus(getSTI())) {
9070 Error(getLoc(), "Rotate mode swizzle not supported on this GPU");
9071 return false;
9072 }
9073
9074 SMLoc Loc;
9075 int64_t Direction;
9076
9077 if (!parseSwizzleOperand(Direction, 0, 1,
9078 "direction must be 0 (left) or 1 (right)", Loc))
9079 return false;
9080
9081 int64_t RotateSize;
9082 if (!parseSwizzleOperand(
9083 RotateSize, 0, ROTATE_MAX_SIZE,
9084 "number of threads to rotate must be in the interval [0," +
9085 Twine(ROTATE_MAX_SIZE) + Twine(']'),
9086 Loc))
9087 return false;
9088
9090 (RotateSize << ROTATE_SIZE_SHIFT);
9091 return true;
9092}
9093
9094bool AMDGPUAsmParser::parseSwizzleOffset(int64_t &Imm) {
9095
9096 SMLoc OffsetLoc = getLoc();
9097
9098 if (!parseExpr(Imm, "a swizzle macro")) {
9099 return false;
9100 }
9101 if (!isUInt<16>(Imm)) {
9102 Error(OffsetLoc, "expected a 16-bit offset");
9103 return false;
9104 }
9105 return true;
9106}
9107
9108bool AMDGPUAsmParser::parseSwizzleMacro(int64_t &Imm) {
9109 using namespace llvm::AMDGPU::Swizzle;
9110
9111 if (skipToken(AsmToken::LParen, "expected a left parentheses")) {
9112
9113 SMLoc ModeLoc = getLoc();
9114 bool Ok = false;
9115
9116 if (trySkipId(IdSymbolic[ID_QUAD_PERM])) {
9117 Ok = parseSwizzleQuadPerm(Imm);
9118 } else if (trySkipId(IdSymbolic[ID_BITMASK_PERM])) {
9119 Ok = parseSwizzleBitmaskPerm(Imm);
9120 } else if (trySkipId(IdSymbolic[ID_BROADCAST])) {
9121 Ok = parseSwizzleBroadcast(Imm);
9122 } else if (trySkipId(IdSymbolic[ID_SWAP])) {
9123 Ok = parseSwizzleSwap(Imm);
9124 } else if (trySkipId(IdSymbolic[ID_REVERSE])) {
9125 Ok = parseSwizzleReverse(Imm);
9126 } else if (trySkipId(IdSymbolic[ID_FFT])) {
9127 Ok = parseSwizzleFFT(Imm);
9128 } else if (trySkipId(IdSymbolic[ID_ROTATE])) {
9129 Ok = parseSwizzleRotate(Imm);
9130 } else {
9131 Error(ModeLoc, "expected a swizzle mode");
9132 }
9133
9134 return Ok && skipToken(AsmToken::RParen, "expected a closing parentheses");
9135 }
9136
9137 return false;
9138}
9139
9140ParseStatus AMDGPUAsmParser::parseSwizzle(OperandVector &Operands) {
9141 SMLoc S = getLoc();
9142 int64_t Imm = 0;
9143
9144 if (trySkipId("offset")) {
9145
9146 bool Ok = false;
9147 if (skipToken(AsmToken::Colon, "expected a colon")) {
9148 if (trySkipId("swizzle")) {
9149 Ok = parseSwizzleMacro(Imm);
9150 } else {
9151 Ok = parseSwizzleOffset(Imm);
9152 }
9153 }
9154
9155 Operands.push_back(
9156 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTySwizzle));
9157
9159 }
9160 return ParseStatus::NoMatch;
9161}
9162
9163bool AMDGPUOperand::isSwizzle() const { return isImmTy(ImmTySwizzle); }
9164
9165//===----------------------------------------------------------------------===//
9166// VGPR Index Mode
9167//===----------------------------------------------------------------------===//
9168
9169int64_t AMDGPUAsmParser::parseGPRIdxMacro() {
9170
9171 using namespace llvm::AMDGPU::VGPRIndexMode;
9172
9173 if (trySkipToken(AsmToken::RParen)) {
9174 return OFF;
9175 }
9176
9177 int64_t Imm = 0;
9178
9179 while (true) {
9180 unsigned Mode = 0;
9181 SMLoc S = getLoc();
9182
9183 for (unsigned ModeId = ID_MIN; ModeId <= ID_MAX; ++ModeId) {
9184 if (trySkipId(IdSymbolic[ModeId])) {
9185 Mode = 1 << ModeId;
9186 break;
9187 }
9188 }
9189
9190 if (Mode == 0) {
9191 Error(S, (Imm == 0)
9192 ? "expected a VGPR index mode or a closing parenthesis"
9193 : "expected a VGPR index mode");
9194 return UNDEF;
9195 }
9196
9197 if (Imm & Mode) {
9198 Error(S, "duplicate VGPR index mode");
9199 return UNDEF;
9200 }
9201 Imm |= Mode;
9202
9203 if (trySkipToken(AsmToken::RParen))
9204 break;
9205 if (!skipToken(AsmToken::Comma,
9206 "expected a comma or a closing parenthesis"))
9207 return UNDEF;
9208 }
9209
9210 return Imm;
9211}
9212
9213ParseStatus AMDGPUAsmParser::parseGPRIdxMode(OperandVector &Operands) {
9214
9215 using namespace llvm::AMDGPU::VGPRIndexMode;
9216
9217 int64_t Imm = 0;
9218 SMLoc S = getLoc();
9219
9220 if (trySkipId("gpr_idx", AsmToken::LParen)) {
9221 Imm = parseGPRIdxMacro();
9222 if (Imm == UNDEF)
9223 return ParseStatus::Failure;
9224 } else {
9225 if (getParser().parseAbsoluteExpression(Imm))
9226 return ParseStatus::Failure;
9227 if (Imm < 0 || !isUInt<4>(Imm))
9228 return Error(S, "invalid immediate: only 4-bit values are legal");
9229 }
9230
9231 Operands.push_back(
9232 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyGprIdxMode));
9233 return ParseStatus::Success;
9234}
9235
9236bool AMDGPUOperand::isGPRIdxMode() const { return isImmTy(ImmTyGprIdxMode); }
9237
9238//===----------------------------------------------------------------------===//
9239// sopp branch targets
9240//===----------------------------------------------------------------------===//
9241
9242ParseStatus AMDGPUAsmParser::parseSOPPBrTarget(OperandVector &Operands) {
9243
9244 // Make sure we are not parsing something
9245 // that looks like a label or an expression but is not.
9246 // This will improve error messages.
9247 if (isRegister() || isModifier())
9248 return ParseStatus::NoMatch;
9249
9250 if (!parseExpr(Operands))
9251 return ParseStatus::Failure;
9252
9253 AMDGPUOperand &Opr = ((AMDGPUOperand &)*Operands[Operands.size() - 1]);
9254 assert(Opr.isImm() || Opr.isExpr());
9255 SMLoc Loc = Opr.getStartLoc();
9256
9257 // Currently we do not support arbitrary expressions as branch targets.
9258 // Only labels and absolute expressions are accepted.
9259 if (Opr.isExpr() && !Opr.isSymbolRefExpr()) {
9260 Error(Loc, "expected an absolute expression or a label");
9261 } else if (Opr.isImm() && !Opr.isS16Imm()) {
9262 Error(Loc, "expected a 16-bit signed jump offset");
9263 }
9264
9265 return ParseStatus::Success;
9266}
9267
9268//===----------------------------------------------------------------------===//
9269// Boolean holding registers
9270//===----------------------------------------------------------------------===//
9271
9272ParseStatus AMDGPUAsmParser::parseBoolReg(OperandVector &Operands) {
9273 return parseReg(Operands);
9274}
9275
9276//===----------------------------------------------------------------------===//
9277// mubuf
9278//===----------------------------------------------------------------------===//
9279
9280void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst, const OperandVector &Operands,
9281 bool IsAtomic) {
9282 OptionalImmIndexMap OptionalIdx;
9283 unsigned FirstOperandIdx = 1;
9284 bool IsAtomicReturn = false;
9285
9286 if (IsAtomic) {
9287 IsAtomicReturn = SIInstrFlags::isAtomicRet(MII, Inst);
9288 }
9289
9290 for (unsigned i = FirstOperandIdx, e = Operands.size(); i != e; ++i) {
9291 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
9292
9293 // Add the register arguments
9294 if (Op.isReg()) {
9295 Op.addRegOperands(Inst, 1);
9296 // Insert a tied src for atomic return dst.
9297 // This cannot be postponed as subsequent calls to
9298 // addImmOperands rely on correct number of MC operands.
9299 if (IsAtomicReturn && i == FirstOperandIdx)
9300 Op.addRegOperands(Inst, 1);
9301 continue;
9302 }
9303
9304 // Handle the case where soffset is an immediate
9305 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
9306 Op.addImmOperands(Inst, 1);
9307 continue;
9308 }
9309
9310 // Handle tokens like 'offen' which are sometimes hard-coded into the
9311 // asm string. There are no MCInst operands for these.
9312 if (Op.isToken()) {
9313 continue;
9314 }
9315 assert(Op.isImm());
9316
9317 // Handle optional arguments
9318 OptionalIdx[Op.getImmTy()] = i;
9319 }
9320
9321 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9322 AMDGPUOperand::ImmTyOffset);
9323 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyCPol,
9324 0);
9325 // Parse a dummy operand as a placeholder for the SWZ operand. This enforces
9326 // agreement between MCInstrDesc.getNumOperands and MCInst.getNumOperands.
9328}
9329
9330//===----------------------------------------------------------------------===//
9331// smrd
9332//===----------------------------------------------------------------------===//
9333
9334bool AMDGPUOperand::isSMRDOffset8() const {
9335 return isImmLiteral() && isUInt<8>(getImm());
9336}
9337
9338bool AMDGPUOperand::isSMEMOffset() const {
9339 // Offset range is checked later by validator.
9340 return isImmLiteral();
9341}
9342
9343bool AMDGPUOperand::isSMRDLiteralOffset() const {
9344 // 32-bit literals are only supported on CI and we only want to use them
9345 // when the offset is > 8-bits.
9346 return isImmLiteral() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
9347}
9348
9349//===----------------------------------------------------------------------===//
9350// vop3
9351//===----------------------------------------------------------------------===//
9352
9353static bool ConvertOmodMul(int64_t &Mul) {
9354 if (Mul != 1 && Mul != 2 && Mul != 4)
9355 return false;
9356
9357 Mul >>= 1;
9358 return true;
9359}
9360
9361static bool ConvertOmodDiv(int64_t &Div) {
9362 if (Div == 1) {
9363 Div = 0;
9364 return true;
9365 }
9366
9367 if (Div == 2) {
9368 Div = 3;
9369 return true;
9370 }
9371
9372 return false;
9373}
9374
9375// For pre-gfx11 targets, both bound_ctrl:0 and bound_ctrl:1 are encoded as 1.
9376// This is intentional and ensures compatibility with sp3.
9377// See bug 35397 for details.
9378bool AMDGPUAsmParser::convertDppBoundCtrl(int64_t &BoundCtrl) {
9379 if (BoundCtrl == 0 || BoundCtrl == 1) {
9380 if (!isGFX11Plus())
9381 BoundCtrl = 1;
9382 return true;
9383 }
9384 return false;
9385}
9386
9387void AMDGPUAsmParser::onBeginOfFile() {
9388 if (!getParser().getStreamer().getTargetStreamer())
9389 return;
9390
9391 if (!getTargetStreamer().getTargetID())
9392 getTargetStreamer().initializeTargetID(getSTI(),
9393 /*ApplyFeatureString=*/true);
9394}
9395
9396void AMDGPUAsmParser::emitTargetDirective() {
9397 if (TargetDirectiveEmitted)
9398 return;
9399 TargetDirectiveEmitted = true;
9400
9401 if (!getParser().getStreamer().getTargetStreamer() ||
9402 getSTI().getTargetTriple().getArch() == Triple::r600)
9403 return;
9404
9405 if (isHsaAbi(getSTI()))
9406 getTargetStreamer().EmitDirectiveAMDGCNTarget();
9407}
9408
9409/// Parse AMDGPU specific expressions.
9410///
9411/// expr ::= or(expr, ...) |
9412/// max(expr, ...) |
9413/// min(expr, ...)
9414///
9415bool AMDGPUAsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
9416 using AGVK = AMDGPUMCExpr::VariantKind;
9417
9418 if (isToken(AsmToken::Identifier)) {
9419 StringRef TokenId = getTokenStr();
9420 AGVK VK = StringSwitch<AGVK>(TokenId)
9421 .Case("max", AGVK::AGVK_Max)
9422 .Case("min", AGVK::AGVK_Min)
9423 .Case("or", AGVK::AGVK_Or)
9424 .Case("extrasgprs", AGVK::AGVK_ExtraSGPRs)
9425 .Case("totalnumvgprs", AGVK::AGVK_TotalNumVGPRs)
9426 .Case("alignto", AGVK::AGVK_AlignTo)
9427 .Case("occupancy", AGVK::AGVK_Occupancy)
9428 .Case("instprefsize", AGVK::AGVK_InstPrefSize)
9429 .Default(AGVK::AGVK_None);
9430
9431 if (VK != AGVK::AGVK_None && peekToken().is(AsmToken::LParen)) {
9433 uint64_t CommaCount = 0;
9434 lex(); // Eat Arg ('or', 'max', 'occupancy', etc.)
9435 lex(); // Eat '('
9436 while (true) {
9437 if (trySkipToken(AsmToken::RParen)) {
9438 if (Exprs.empty()) {
9439 Error(getToken().getLoc(),
9440 "empty " + Twine(TokenId) + " expression");
9441 return true;
9442 }
9443 if (CommaCount + 1 != Exprs.size()) {
9444 Error(getToken().getLoc(),
9445 "mismatch of commas in " + Twine(TokenId) + " expression");
9446 return true;
9447 }
9448 if (unsigned Expected = AMDGPUMCExpr::getNumExpectedArgs(VK);
9449 Expected && Exprs.size() != Expected) {
9450 Error(getToken().getLoc(), Twine(TokenId) + " expression expects " +
9451 Twine(Expected) + " operands");
9452 return true;
9453 }
9454 Res = AMDGPUMCExpr::create(VK, Exprs, getContext());
9455 return false;
9456 }
9457 const MCExpr *Expr;
9458 if (getParser().parseExpression(Expr, EndLoc))
9459 return true;
9460 Exprs.push_back(Expr);
9461 bool LastTokenWasComma = trySkipToken(AsmToken::Comma);
9462 if (LastTokenWasComma)
9463 CommaCount++;
9464 if (!LastTokenWasComma && !isToken(AsmToken::RParen)) {
9465 Error(getToken().getLoc(),
9466 "unexpected token in " + Twine(TokenId) + " expression");
9467 return true;
9468 }
9469 }
9470 }
9471 }
9472 return getParser().parsePrimaryExpr(Res, EndLoc, nullptr);
9473}
9474
9475ParseStatus AMDGPUAsmParser::parseOModSI(OperandVector &Operands) {
9476 StringRef Name = getTokenStr();
9477 if (Name == "mul") {
9478 return parseIntWithPrefix("mul", Operands, AMDGPUOperand::ImmTyOModSI,
9480 }
9481
9482 if (Name == "div") {
9483 return parseIntWithPrefix("div", Operands, AMDGPUOperand::ImmTyOModSI,
9485 }
9486
9487 return ParseStatus::NoMatch;
9488}
9489
9490// Determines which bit DST_OP_SEL occupies in the op_sel operand according to
9491// the number of src operands present, then copies that bit into src0_modifiers.
9492static void cvtVOP3DstOpSelOnly(MCInst &Inst, const MCRegisterInfo &MRI) {
9493 int Opc = Inst.getOpcode();
9494 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
9495 if (OpSelIdx == -1)
9496 return;
9497
9498 int SrcNum;
9499 const AMDGPU::OpName Ops[] = {AMDGPU::OpName::src0, AMDGPU::OpName::src1,
9500 AMDGPU::OpName::src2};
9501 for (SrcNum = 0; SrcNum < 3 && AMDGPU::hasNamedOperand(Opc, Ops[SrcNum]);
9502 ++SrcNum)
9503 ;
9504 assert(SrcNum > 0);
9505
9506 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
9507
9508 int DstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
9509 if (DstIdx == -1)
9510 return;
9511
9512 const MCOperand &DstOp = Inst.getOperand(DstIdx);
9513 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers);
9514 uint32_t ModVal = Inst.getOperand(ModIdx).getImm();
9515 if (DstOp.isReg() &&
9516 MRI.getRegClass(AMDGPU::VGPR_16RegClassID).contains(DstOp.getReg())) {
9517 if (AMDGPU::isHi16Reg(DstOp.getReg(), MRI))
9518 ModVal |= SISrcMods::DST_OP_SEL;
9519 } else {
9520 if ((OpSel & (1 << SrcNum)) != 0)
9521 ModVal |= SISrcMods::DST_OP_SEL;
9522 }
9523 Inst.getOperand(ModIdx).setImm(ModVal);
9524}
9525
9526void AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst,
9527 const OperandVector &Operands) {
9528 cvtVOP3P(Inst, Operands);
9529 cvtVOP3DstOpSelOnly(Inst, *getMRI());
9530}
9531
9532void AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands,
9533 OptionalImmIndexMap &OptionalIdx) {
9534 cvtVOP3P(Inst, Operands, OptionalIdx);
9535 cvtVOP3DstOpSelOnly(Inst, *getMRI());
9536}
9537
9538static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) {
9539 return
9540 // 1. This operand is input modifiers
9541 Desc.operands()[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS
9542 // 2. This is not last operand
9543 && Desc.NumOperands > (OpNum + 1)
9544 // 3. Next operand is register class
9545 && Desc.operands()[OpNum + 1].RegClass != -1
9546 // 4. Next register is not tied to any other operand
9547 && Desc.getOperandConstraint(OpNum + 1,
9549}
9550
9551void AMDGPUAsmParser::cvtOpSelHelper(MCInst &Inst, unsigned OpSel) {
9552 unsigned Opc = Inst.getOpcode();
9553 constexpr AMDGPU::OpName Ops[] = {AMDGPU::OpName::src0, AMDGPU::OpName::src1,
9554 AMDGPU::OpName::src2};
9555 constexpr AMDGPU::OpName ModOps[] = {AMDGPU::OpName::src0_modifiers,
9556 AMDGPU::OpName::src1_modifiers,
9557 AMDGPU::OpName::src2_modifiers};
9558 for (int J = 0; J < 3; ++J) {
9559 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]);
9560 if (OpIdx == -1)
9561 // Some instructions, e.g. v_interp_p2_f16 in GFX9, have src0, src2, but
9562 // no src1. So continue instead of break.
9563 continue;
9564
9565 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
9566 uint32_t ModVal = Inst.getOperand(ModIdx).getImm();
9567
9568 if ((OpSel & (1 << J)) != 0)
9569 ModVal |= SISrcMods::OP_SEL_0;
9570 // op_sel[3] is encoded in src0_modifiers.
9571 if (ModOps[J] == AMDGPU::OpName::src0_modifiers && (OpSel & (1 << 3)) != 0)
9572 ModVal |= SISrcMods::DST_OP_SEL;
9573
9574 Inst.getOperand(ModIdx).setImm(ModVal);
9575 }
9576}
9577
9578void AMDGPUAsmParser::cvtVOP3Interp(MCInst &Inst,
9579 const OperandVector &Operands) {
9580 OptionalImmIndexMap OptionalIdx;
9581 unsigned Opc = Inst.getOpcode();
9582
9583 unsigned I = 1;
9584 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
9585 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
9586 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
9587 }
9588
9589 for (unsigned E = Operands.size(); I != E; ++I) {
9590 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
9592 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
9593 } else if (Op.isInterpSlot() || Op.isInterpAttr() ||
9594 Op.isInterpAttrChan()) {
9595 Inst.addOperand(MCOperand::createImm(Op.getImm()));
9596 } else if (Op.isImmModifier()) {
9597 OptionalIdx[Op.getImmTy()] = I;
9598 } else {
9599 llvm_unreachable("unhandled operand type");
9600 }
9601 }
9602
9603 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::high))
9604 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9605 AMDGPUOperand::ImmTyHigh);
9606
9607 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp))
9608 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9609 AMDGPUOperand::ImmTyClamp);
9610
9611 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod))
9612 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9613 AMDGPUOperand::ImmTyOModSI);
9614
9615 // Some v_interp instructions use op_sel[3] for dst.
9616 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) {
9617 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9618 AMDGPUOperand::ImmTyOpSel);
9619 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
9620 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
9621
9622 cvtOpSelHelper(Inst, OpSel);
9623 }
9624}
9625
9626void AMDGPUAsmParser::cvtVINTERP(MCInst &Inst, const OperandVector &Operands) {
9627 OptionalImmIndexMap OptionalIdx;
9628 unsigned Opc = Inst.getOpcode();
9629
9630 unsigned I = 1;
9631 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
9632 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
9633 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
9634 }
9635
9636 for (unsigned E = Operands.size(); I != E; ++I) {
9637 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
9639 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
9640 } else if (Op.isImmModifier()) {
9641 OptionalIdx[Op.getImmTy()] = I;
9642 } else {
9643 llvm_unreachable("unhandled operand type");
9644 }
9645 }
9646
9647 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClamp);
9648
9649 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
9650 if (OpSelIdx != -1)
9651 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9652 AMDGPUOperand::ImmTyOpSel);
9653
9654 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9655 AMDGPUOperand::ImmTyWaitEXP);
9656
9657 if (OpSelIdx == -1)
9658 return;
9659
9660 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
9661 cvtOpSelHelper(Inst, OpSel);
9662}
9663
9664void AMDGPUAsmParser::cvtScaledMFMA(MCInst &Inst,
9665 const OperandVector &Operands) {
9666 OptionalImmIndexMap OptionalIdx;
9667 unsigned Opc = Inst.getOpcode();
9668 unsigned I = 1;
9669 int CbszOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::cbsz);
9670
9671 const MCInstrDesc &Desc = MII.get(Opc);
9672
9673 for (unsigned J = 0; J < Desc.getNumDefs(); ++J)
9674 static_cast<AMDGPUOperand &>(*Operands[I++]).addRegOperands(Inst, 1);
9675
9676 for (unsigned E = Operands.size(); I != E; ++I) {
9677 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands[I]);
9678 int NumOperands = Inst.getNumOperands();
9679 // The order of operands in MCInst and parsed operands are different.
9680 // Adding dummy cbsz and blgp operands at corresponding MCInst operand
9681 // indices for parsing scale values correctly.
9682 if (NumOperands == CbszOpIdx) {
9685 }
9686 if (isRegOrImmWithInputMods(Desc, NumOperands)) {
9687 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
9688 } else if (Op.isImmModifier()) {
9689 OptionalIdx[Op.getImmTy()] = I;
9690 } else {
9691 Op.addRegOrImmOperands(Inst, 1);
9692 }
9693 }
9694
9695 // Insert CBSZ and BLGP operands for F8F6F4 variants
9696 auto CbszIdx = OptionalIdx.find(AMDGPUOperand::ImmTyCBSZ);
9697 if (CbszIdx != OptionalIdx.end()) {
9698 int CbszVal = ((AMDGPUOperand &)*Operands[CbszIdx->second]).getImm();
9699 Inst.getOperand(CbszOpIdx).setImm(CbszVal);
9700 }
9701
9702 int BlgpOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::blgp);
9703 auto BlgpIdx = OptionalIdx.find(AMDGPUOperand::ImmTyBLGP);
9704 if (BlgpIdx != OptionalIdx.end()) {
9705 int BlgpVal = ((AMDGPUOperand &)*Operands[BlgpIdx->second]).getImm();
9706 Inst.getOperand(BlgpOpIdx).setImm(BlgpVal);
9707 }
9708
9709 // Add dummy src_modifiers
9712
9713 // Handle op_sel fields
9714
9715 unsigned OpSel = 0;
9716 auto OpselIdx = OptionalIdx.find(AMDGPUOperand::ImmTyOpSel);
9717 if (OpselIdx != OptionalIdx.end()) {
9718 OpSel = static_cast<const AMDGPUOperand &>(*Operands[OpselIdx->second])
9719 .getImm();
9720 }
9721
9722 unsigned OpSelHi = 0;
9723 auto OpselHiIdx = OptionalIdx.find(AMDGPUOperand::ImmTyOpSelHi);
9724 if (OpselHiIdx != OptionalIdx.end()) {
9725 OpSelHi = static_cast<const AMDGPUOperand &>(*Operands[OpselHiIdx->second])
9726 .getImm();
9727 }
9728 const AMDGPU::OpName ModOps[] = {AMDGPU::OpName::src0_modifiers,
9729 AMDGPU::OpName::src1_modifiers};
9730
9731 for (unsigned J = 0; J < 2; ++J) {
9732 unsigned ModVal = 0;
9733 if (OpSel & (1 << J))
9734 ModVal |= SISrcMods::OP_SEL_0;
9735 if (OpSelHi & (1 << J))
9736 ModVal |= SISrcMods::OP_SEL_1;
9737
9738 const int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
9739 Inst.getOperand(ModIdx).setImm(ModVal);
9740 }
9741}
9742
9743void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands,
9744 OptionalImmIndexMap &OptionalIdx) {
9745 unsigned Opc = Inst.getOpcode();
9746
9747 unsigned I = 1;
9748 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
9749 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
9750 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
9751 }
9752
9753 for (unsigned E = Operands.size(); I != E; ++I) {
9754 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
9756 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
9757 } else if (Op.isImmModifier()) {
9758 OptionalIdx[Op.getImmTy()] = I;
9759 } else {
9760 Op.addRegOrImmOperands(Inst, 1);
9761 }
9762 }
9763
9764 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::scale_sel))
9765 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9766 AMDGPUOperand::ImmTyScaleSel);
9767
9768 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp))
9769 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9770 AMDGPUOperand::ImmTyClamp);
9771
9772 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::byte_sel)) {
9773 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::vdst_in))
9774 Inst.addOperand(Inst.getOperand(0));
9775 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9776 AMDGPUOperand::ImmTyByteSel);
9777 }
9778
9779 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod))
9780 addOptionalImmOperand(Inst, Operands, OptionalIdx,
9781 AMDGPUOperand::ImmTyOModSI);
9782
9783 // Special case v_mac_{f16, f32} and v_fmac_{f16, f32} (gfx906/gfx10+):
9784 // it has src2 register operand that is tied to dst operand
9785 // we don't allow modifiers for this operand in assembler so src2_modifiers
9786 // should be 0.
9787 if (isMAC(Opc)) {
9788 auto *it = Inst.begin();
9789 std::advance(
9790 it, AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers));
9791 it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2
9792 ++it;
9793 // Copy the operand to ensure it's not invalidated when Inst grows.
9794 Inst.insert(it, MCOperand(Inst.getOperand(0))); // src2 = dst
9795 }
9796}
9797
9798void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
9799 OptionalImmIndexMap OptionalIdx;
9800 cvtVOP3(Inst, Operands, OptionalIdx);
9801}
9802
9803void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst, const OperandVector &Operands,
9804 OptionalImmIndexMap &OptIdx) {
9805 const int Opc = Inst.getOpcode();
9806
9807 const bool IsPacked = SIInstrFlags::isPacked(MII, Inst);
9808
9809 if (Opc == AMDGPU::V_CVT_SCALEF32_PK_FP4_F16_vi ||
9810 Opc == AMDGPU::V_CVT_SCALEF32_PK_FP4_BF16_vi ||
9811 Opc == AMDGPU::V_CVT_SR_BF8_F32_vi ||
9812 Opc == AMDGPU::V_CVT_SR_FP8_F32_vi ||
9813 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_gfx11 ||
9814 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_gfx11 ||
9815 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_gfx12 ||
9816 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_gfx12 ||
9817 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_gfx13 ||
9818 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_gfx13) {
9819 Inst.addOperand(MCOperand::createImm(0)); // Placeholder for src2_mods
9820 Inst.addOperand(Inst.getOperand(0));
9821 }
9822
9823 // Append vdst_in only if a previous converter (cvtVOP3DPP for DPP variants,
9824 // cvtVOP3 for byte_sel variants) hasn't already placed it. Use the position
9825 // of the named operand to detect that, the same way cvtVOP3DPP does
9826 // internally.
9827 int VdstInIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
9828 if (VdstInIdx != -1 && VdstInIdx == static_cast<int>(Inst.getNumOperands()))
9829 Inst.addOperand(Inst.getOperand(0));
9830
9831 int BitOp3Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::bitop3);
9832 if (BitOp3Idx != -1) {
9833 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyBitOp3);
9834 }
9835
9836 // FIXME: This is messy. Parse the modifiers as if it was a normal VOP3
9837 // instruction, and then figure out where to actually put the modifiers
9838
9839 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
9840 if (OpSelIdx != -1) {
9841 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSel);
9842 }
9843
9844 int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi);
9845 if (OpSelHiIdx != -1) {
9846 int DefaultVal = IsPacked ? -1 : 0;
9847 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSelHi,
9848 DefaultVal);
9849 }
9850
9851 int MatrixAFMTIdx =
9852 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_a_fmt);
9853 if (MatrixAFMTIdx != -1) {
9854 addOptionalImmOperand(Inst, Operands, OptIdx,
9855 AMDGPUOperand::ImmTyMatrixAFMT, 0);
9856 }
9857
9858 int MatrixBFMTIdx =
9859 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_b_fmt);
9860 if (MatrixBFMTIdx != -1) {
9861 addOptionalImmOperand(Inst, Operands, OptIdx,
9862 AMDGPUOperand::ImmTyMatrixBFMT, 0);
9863 }
9864
9865 int MatrixAScaleIdx =
9866 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_a_scale);
9867 if (MatrixAScaleIdx != -1) {
9868 addOptionalImmOperand(Inst, Operands, OptIdx,
9869 AMDGPUOperand::ImmTyMatrixAScale, 0);
9870 }
9871
9872 int MatrixBScaleIdx =
9873 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_b_scale);
9874 if (MatrixBScaleIdx != -1) {
9875 addOptionalImmOperand(Inst, Operands, OptIdx,
9876 AMDGPUOperand::ImmTyMatrixBScale, 0);
9877 }
9878
9879 int MatrixAScaleFmtIdx =
9880 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_a_scale_fmt);
9881 if (MatrixAScaleFmtIdx != -1) {
9882 addOptionalImmOperand(Inst, Operands, OptIdx,
9883 AMDGPUOperand::ImmTyMatrixAScaleFmt, 0);
9884 }
9885
9886 int MatrixBScaleFmtIdx =
9887 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::matrix_b_scale_fmt);
9888 if (MatrixBScaleFmtIdx != -1) {
9889 addOptionalImmOperand(Inst, Operands, OptIdx,
9890 AMDGPUOperand::ImmTyMatrixBScaleFmt, 0);
9891 }
9892
9893 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::matrix_a_reuse))
9894 addOptionalImmOperand(Inst, Operands, OptIdx,
9895 AMDGPUOperand::ImmTyMatrixAReuse, 0);
9896
9897 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::matrix_b_reuse))
9898 addOptionalImmOperand(Inst, Operands, OptIdx,
9899 AMDGPUOperand::ImmTyMatrixBReuse, 0);
9900
9901 int NegLoIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_lo);
9902 if (NegLoIdx != -1)
9903 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegLo);
9904
9905 int NegHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_hi);
9906 if (NegHiIdx != -1)
9907 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegHi);
9908
9909 const AMDGPU::OpName Ops[] = {AMDGPU::OpName::src0, AMDGPU::OpName::src1,
9910 AMDGPU::OpName::src2};
9911 const AMDGPU::OpName ModOps[] = {AMDGPU::OpName::src0_modifiers,
9912 AMDGPU::OpName::src1_modifiers,
9913 AMDGPU::OpName::src2_modifiers};
9914
9915 unsigned OpSel = 0;
9916 unsigned OpSelHi = 0;
9917 unsigned NegLo = 0;
9918 unsigned NegHi = 0;
9919
9920 if (OpSelIdx != -1)
9921 OpSel = Inst.getOperand(OpSelIdx).getImm();
9922
9923 if (OpSelHiIdx != -1)
9924 OpSelHi = Inst.getOperand(OpSelHiIdx).getImm();
9925
9926 if (NegLoIdx != -1)
9927 NegLo = Inst.getOperand(NegLoIdx).getImm();
9928
9929 if (NegHiIdx != -1)
9930 NegHi = Inst.getOperand(NegHiIdx).getImm();
9931
9932 for (int J = 0; J < 3; ++J) {
9933 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]);
9934 if (OpIdx == -1)
9935 break;
9936
9937 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
9938
9939 if (ModIdx == -1)
9940 continue;
9941
9942 // For MAC instructions, src2 is tied to vdst and its op_sel bit
9943 // is not encoded.
9944 if (AMDGPU::isMAC(Opc) && ModOps[J] == AMDGPU::OpName::src2_modifiers)
9945 continue;
9946
9947 uint32_t ModVal = 0;
9948
9949 const MCOperand &SrcOp = Inst.getOperand(OpIdx);
9950 if (SrcOp.isReg() && getMRI()
9951 ->getRegClass(AMDGPU::VGPR_16RegClassID)
9952 .contains(SrcOp.getReg())) {
9953 bool VGPRSuffixIsHi = AMDGPU::isHi16Reg(SrcOp.getReg(), *getMRI());
9954 if (VGPRSuffixIsHi)
9955 ModVal |= SISrcMods::OP_SEL_0;
9956 } else {
9957 if ((OpSel & (1 << J)) != 0)
9958 ModVal |= SISrcMods::OP_SEL_0;
9959 }
9960
9961 if ((OpSelHi & (1 << J)) != 0)
9962 ModVal |= SISrcMods::OP_SEL_1;
9963
9964 if ((NegLo & (1 << J)) != 0)
9965 ModVal |= SISrcMods::NEG;
9966
9967 if ((NegHi & (1 << J)) != 0)
9968 ModVal |= SISrcMods::NEG_HI;
9969
9970 Inst.getOperand(ModIdx).setImm(Inst.getOperand(ModIdx).getImm() | ModVal);
9971 }
9972}
9973
9974void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst, const OperandVector &Operands) {
9975 OptionalImmIndexMap OptIdx;
9976 cvtVOP3(Inst, Operands, OptIdx);
9977 cvtVOP3P(Inst, Operands, OptIdx);
9978}
9979
9981 unsigned i, unsigned Opc,
9982 AMDGPU::OpName OpName) {
9983 if (AMDGPU::getNamedOperandIdx(Opc, OpName) != -1)
9984 ((AMDGPUOperand &)*Operands[i]).addRegOrImmWithFPInputModsOperands(Inst, 2);
9985 else
9986 ((AMDGPUOperand &)*Operands[i]).addRegOperands(Inst, 1);
9987}
9988
9989void AMDGPUAsmParser::cvtSWMMAC(MCInst &Inst, const OperandVector &Operands) {
9990 unsigned Opc = Inst.getOpcode();
9991
9992 ((AMDGPUOperand &)*Operands[1]).addRegOperands(Inst, 1);
9993 addSrcModifiersAndSrc(Inst, Operands, 2, Opc, AMDGPU::OpName::src0_modifiers);
9994 addSrcModifiersAndSrc(Inst, Operands, 3, Opc, AMDGPU::OpName::src1_modifiers);
9995 ((AMDGPUOperand &)*Operands[1]).addRegOperands(Inst, 1); // srcTiedDef
9996 ((AMDGPUOperand &)*Operands[4]).addRegOperands(Inst, 1); // src2
9997
9998 OptionalImmIndexMap OptIdx;
9999 for (unsigned i = 5; i < Operands.size(); ++i) {
10000 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
10001 OptIdx[Op.getImmTy()] = i;
10002 }
10003
10004 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::index_key_8bit))
10005 addOptionalImmOperand(Inst, Operands, OptIdx,
10006 AMDGPUOperand::ImmTyIndexKey8bit);
10007
10008 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::index_key_16bit))
10009 addOptionalImmOperand(Inst, Operands, OptIdx,
10010 AMDGPUOperand::ImmTyIndexKey16bit);
10011
10012 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::index_key_32bit))
10013 addOptionalImmOperand(Inst, Operands, OptIdx,
10014 AMDGPUOperand::ImmTyIndexKey32bit);
10015
10016 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp))
10017 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyClamp);
10018
10019 cvtVOP3P(Inst, Operands, OptIdx);
10020}
10021
10022//===----------------------------------------------------------------------===//
10023// VOPD
10024//===----------------------------------------------------------------------===//
10025
10026ParseStatus AMDGPUAsmParser::parseVOPD(OperandVector &Operands) {
10027 if (!hasVOPD(getSTI()))
10028 return ParseStatus::NoMatch;
10029
10030 if (isToken(AsmToken::Colon) && peekToken(false).is(AsmToken::Colon)) {
10031 SMLoc S = getLoc();
10032 lex();
10033 lex();
10034 Operands.push_back(AMDGPUOperand::CreateToken(this, "::", S));
10035 SMLoc OpYLoc = getLoc();
10036 StringRef OpYName;
10037 if (isToken(AsmToken::Identifier) && !Parser.parseIdentifier(OpYName)) {
10038 Operands.push_back(AMDGPUOperand::CreateToken(this, OpYName, OpYLoc));
10039 return ParseStatus::Success;
10040 }
10041 return Error(OpYLoc, "expected a VOPDY instruction after ::");
10042 }
10043 return ParseStatus::NoMatch;
10044}
10045
10046// Create VOPD MCInst operands using parsed assembler operands.
10047void AMDGPUAsmParser::cvtVOPD(MCInst &Inst, const OperandVector &Operands) {
10048 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
10049
10050 auto addOp = [&](uint16_t ParsedOprIdx) { // NOLINT:function pointer
10051 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[ParsedOprIdx]);
10053 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
10054 return;
10055 }
10056 if (Op.isReg()) {
10057 Op.addRegOperands(Inst, 1);
10058 return;
10059 }
10060 if (Op.isImm()) {
10061 Op.addImmOperands(Inst, 1);
10062 return;
10063 }
10064 llvm_unreachable("Unhandled operand type in cvtVOPD");
10065 };
10066
10067 const auto &InstInfo = getVOPDInstInfo(Inst.getOpcode(), &MII);
10068
10069 // MCInst operands are ordered as follows:
10070 // dstX, dstY, src0X [, other OpX operands], src0Y [, other OpY operands]
10071
10072 for (auto CompIdx : VOPD::COMPONENTS) {
10073 addOp(InstInfo[CompIdx].getIndexOfDstInParsedOperands());
10074 }
10075
10076 for (auto CompIdx : VOPD::COMPONENTS) {
10077 const auto &CInfo = InstInfo[CompIdx];
10078 auto CompSrcOperandsNum = InstInfo[CompIdx].getCompParsedSrcOperandsNum();
10079 for (unsigned CompSrcIdx = 0; CompSrcIdx < CompSrcOperandsNum; ++CompSrcIdx)
10080 addOp(CInfo.getIndexOfSrcInParsedOperands(CompSrcIdx));
10081 if (CInfo.hasSrc2Acc())
10082 addOp(CInfo.getIndexOfDstInParsedOperands());
10083 }
10084
10085 int BitOp3Idx =
10086 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::bitop3);
10087 if (BitOp3Idx != -1) {
10088 OptionalImmIndexMap OptIdx;
10089 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands.back());
10090 if (Op.isImm())
10091 OptIdx[Op.getImmTy()] = Operands.size() - 1;
10092
10093 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyBitOp3);
10094 }
10095}
10096
10097//===----------------------------------------------------------------------===//
10098// dpp
10099//===----------------------------------------------------------------------===//
10100
10101bool AMDGPUOperand::isDPP8() const { return isImmTy(ImmTyDPP8); }
10102
10103bool AMDGPUOperand::isDPPCtrl() const {
10104 using namespace AMDGPU::DPP;
10105
10106 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
10107 if (result) {
10108 int64_t Imm = getImm();
10109 return (Imm >= DppCtrl::QUAD_PERM_FIRST &&
10110 Imm <= DppCtrl::QUAD_PERM_LAST) ||
10111 (Imm >= DppCtrl::ROW_SHL_FIRST && Imm <= DppCtrl::ROW_SHL_LAST) ||
10112 (Imm >= DppCtrl::ROW_SHR_FIRST && Imm <= DppCtrl::ROW_SHR_LAST) ||
10113 (Imm >= DppCtrl::ROW_ROR_FIRST && Imm <= DppCtrl::ROW_ROR_LAST) ||
10114 (Imm == DppCtrl::WAVE_SHL1) || (Imm == DppCtrl::WAVE_ROL1) ||
10115 (Imm == DppCtrl::WAVE_SHR1) || (Imm == DppCtrl::WAVE_ROR1) ||
10116 (Imm == DppCtrl::ROW_MIRROR) || (Imm == DppCtrl::ROW_HALF_MIRROR) ||
10117 (Imm == DppCtrl::BCAST15) || (Imm == DppCtrl::BCAST31) ||
10118 (Imm >= DppCtrl::ROW_SHARE_FIRST &&
10119 Imm <= DppCtrl::ROW_SHARE_LAST) ||
10120 (Imm >= DppCtrl::ROW_XMASK_FIRST && Imm <= DppCtrl::ROW_XMASK_LAST);
10121 }
10122 return false;
10123}
10124
10125//===----------------------------------------------------------------------===//
10126// mAI
10127//===----------------------------------------------------------------------===//
10128
10129bool AMDGPUOperand::isBLGP() const {
10130 return isImm() && getImmTy() == ImmTyBLGP && isUInt<3>(getImm());
10131}
10132
10133bool AMDGPUOperand::isS16Imm() const {
10134 return isImmLiteral() && (isInt<16>(getImm()) || isUInt<16>(getImm()));
10135}
10136
10137bool AMDGPUOperand::isU16Imm() const {
10138 return isImmLiteral() && isUInt<16>(getImm());
10139}
10140
10141//===----------------------------------------------------------------------===//
10142// dim
10143//===----------------------------------------------------------------------===//
10144
10145bool AMDGPUAsmParser::parseDimId(unsigned &Encoding) {
10146 // We want to allow "dim:1D" etc.,
10147 // but the initial 1 is tokenized as an integer.
10148 std::string Token;
10149 if (isToken(AsmToken::Integer)) {
10150 SMLoc Loc = getToken().getEndLoc();
10151 Token = std::string(getTokenStr());
10152 lex();
10153 if (getLoc() != Loc)
10154 return false;
10155 }
10156
10157 StringRef Suffix;
10158 if (!parseId(Suffix))
10159 return false;
10160 Token += Suffix;
10161
10162 StringRef DimId = Token;
10163 DimId.consume_front("SQ_RSRC_IMG_");
10164
10165 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByAsmSuffix(DimId);
10166 if (!DimInfo)
10167 return false;
10168
10169 Encoding = DimInfo->Encoding;
10170 return true;
10171}
10172
10173ParseStatus AMDGPUAsmParser::parseDim(OperandVector &Operands) {
10174 if (!isGFX10Plus())
10175 return ParseStatus::NoMatch;
10176
10177 SMLoc S = getLoc();
10178
10179 if (!trySkipId("dim", AsmToken::Colon))
10180 return ParseStatus::NoMatch;
10181
10182 unsigned Encoding;
10183 SMLoc Loc = getLoc();
10184 if (!parseDimId(Encoding))
10185 return Error(Loc, "invalid dim value");
10186
10187 Operands.push_back(
10188 AMDGPUOperand::CreateImm(this, Encoding, S, AMDGPUOperand::ImmTyDim));
10189 return ParseStatus::Success;
10190}
10191
10192//===----------------------------------------------------------------------===//
10193// dpp
10194//===----------------------------------------------------------------------===//
10195
10196ParseStatus AMDGPUAsmParser::parseDPP8(OperandVector &Operands) {
10197 SMLoc S = getLoc();
10198
10199 if (!isGFX10Plus() || !trySkipId("dpp8", AsmToken::Colon))
10200 return ParseStatus::NoMatch;
10201
10202 // dpp8:[%d,%d,%d,%d,%d,%d,%d,%d]
10203
10204 int64_t Sels[8];
10205
10206 if (!skipToken(AsmToken::LBrac, "expected an opening square bracket"))
10207 return ParseStatus::Failure;
10208
10209 for (size_t i = 0; i < 8; ++i) {
10210 if (i > 0 && !skipToken(AsmToken::Comma, "expected a comma"))
10211 return ParseStatus::Failure;
10212
10213 SMLoc Loc = getLoc();
10214 if (getParser().parseAbsoluteExpression(Sels[i]))
10215 return ParseStatus::Failure;
10216 if (0 > Sels[i] || 7 < Sels[i])
10217 return Error(Loc, "expected a 3-bit value");
10218 }
10219
10220 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket"))
10221 return ParseStatus::Failure;
10222
10223 unsigned DPP8 = 0;
10224 for (size_t i = 0; i < 8; ++i)
10225 DPP8 |= (Sels[i] << (i * 3));
10226
10227 Operands.push_back(
10228 AMDGPUOperand::CreateImm(this, DPP8, S, AMDGPUOperand::ImmTyDPP8));
10229 return ParseStatus::Success;
10230}
10231
10232bool AMDGPUAsmParser::isSupportedDPPCtrl(StringRef Ctrl,
10233 const OperandVector &Operands) {
10234 if (Ctrl == "row_newbcast")
10235 return isGFX90A();
10236
10237 if (Ctrl == "row_share" || Ctrl == "row_xmask")
10238 return isGFX10Plus();
10239
10240 if (Ctrl == "wave_shl" || Ctrl == "wave_shr" || Ctrl == "wave_rol" ||
10241 Ctrl == "wave_ror" || Ctrl == "row_bcast")
10242 return isVI() || isGFX9();
10243
10244 return Ctrl == "row_mirror" || Ctrl == "row_half_mirror" ||
10245 Ctrl == "quad_perm" || Ctrl == "row_shl" || Ctrl == "row_shr" ||
10246 Ctrl == "row_ror";
10247}
10248
10249int64_t AMDGPUAsmParser::parseDPPCtrlPerm() {
10250 // quad_perm:[%d,%d,%d,%d]
10251
10252 if (!skipToken(AsmToken::LBrac, "expected an opening square bracket"))
10253 return -1;
10254
10255 int64_t Val = 0;
10256 for (int i = 0; i < 4; ++i) {
10257 if (i > 0 && !skipToken(AsmToken::Comma, "expected a comma"))
10258 return -1;
10259
10260 int64_t Temp;
10261 SMLoc Loc = getLoc();
10262 if (getParser().parseAbsoluteExpression(Temp))
10263 return -1;
10264 if (Temp < 0 || Temp > 3) {
10265 Error(Loc, "expected a 2-bit value");
10266 return -1;
10267 }
10268
10269 Val += (Temp << i * 2);
10270 }
10271
10272 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket"))
10273 return -1;
10274
10275 return Val;
10276}
10277
10278int64_t AMDGPUAsmParser::parseDPPCtrlSel(StringRef Ctrl) {
10279 using namespace AMDGPU::DPP;
10280
10281 // sel:%d
10282
10283 int64_t Val;
10284 SMLoc Loc = getLoc();
10285
10286 if (getParser().parseAbsoluteExpression(Val))
10287 return -1;
10288
10289 struct DppCtrlCheck {
10290 int64_t Ctrl;
10291 int Lo;
10292 int Hi;
10293 };
10294
10295 DppCtrlCheck Check =
10296 StringSwitch<DppCtrlCheck>(Ctrl)
10297 .Case("wave_shl", {DppCtrl::WAVE_SHL1, 1, 1})
10298 .Case("wave_rol", {DppCtrl::WAVE_ROL1, 1, 1})
10299 .Case("wave_shr", {DppCtrl::WAVE_SHR1, 1, 1})
10300 .Case("wave_ror", {DppCtrl::WAVE_ROR1, 1, 1})
10301 .Case("row_shl", {DppCtrl::ROW_SHL0, 1, 15})
10302 .Case("row_shr", {DppCtrl::ROW_SHR0, 1, 15})
10303 .Case("row_ror", {DppCtrl::ROW_ROR0, 1, 15})
10304 .Case("row_share", {DppCtrl::ROW_SHARE_FIRST, 0, 15})
10305 .Case("row_xmask", {DppCtrl::ROW_XMASK_FIRST, 0, 15})
10306 .Case("row_newbcast", {DppCtrl::ROW_NEWBCAST_FIRST, 0, 15})
10307 .Default({-1, 0, 0});
10308
10309 bool Valid;
10310 if (Check.Ctrl == -1) {
10311 Valid = (Ctrl == "row_bcast" && (Val == 15 || Val == 31));
10312 Val = (Val == 15) ? DppCtrl::BCAST15 : DppCtrl::BCAST31;
10313 } else {
10314 Valid = Check.Lo <= Val && Val <= Check.Hi;
10315 Val = (Check.Lo == Check.Hi) ? Check.Ctrl : (Check.Ctrl | Val);
10316 }
10317
10318 if (!Valid) {
10319 Error(Loc, Twine("invalid ", Ctrl) + Twine(" value"));
10320 return -1;
10321 }
10322
10323 return Val;
10324}
10325
10326ParseStatus AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
10327 using namespace AMDGPU::DPP;
10328
10329 if (!isToken(AsmToken::Identifier) ||
10330 !isSupportedDPPCtrl(getTokenStr(), Operands))
10331 return ParseStatus::NoMatch;
10332
10333 SMLoc S = getLoc();
10334 int64_t Val = -1;
10335 StringRef Ctrl;
10336
10337 parseId(Ctrl);
10338
10339 if (Ctrl == "row_mirror") {
10340 Val = DppCtrl::ROW_MIRROR;
10341 } else if (Ctrl == "row_half_mirror") {
10342 Val = DppCtrl::ROW_HALF_MIRROR;
10343 } else {
10344 if (skipToken(AsmToken::Colon, "expected a colon")) {
10345 if (Ctrl == "quad_perm") {
10346 Val = parseDPPCtrlPerm();
10347 } else {
10348 Val = parseDPPCtrlSel(Ctrl);
10349 }
10350 }
10351 }
10352
10353 if (Val == -1)
10354 return ParseStatus::Failure;
10355
10356 Operands.push_back(
10357 AMDGPUOperand::CreateImm(this, Val, S, AMDGPUOperand::ImmTyDppCtrl));
10358 return ParseStatus::Success;
10359}
10360
10361void AMDGPUAsmParser::cvtVOP3DPP(MCInst &Inst, const OperandVector &Operands,
10362 bool IsDPP8) {
10363 OptionalImmIndexMap OptionalIdx;
10364 unsigned Opc = Inst.getOpcode();
10365 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
10366
10367 // MAC instructions are special because they have 'old'
10368 // operand which is not tied to dst (but assumed to be).
10369 // They also have dummy unused src2_modifiers.
10370 int OldIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::old);
10371 int Src2ModIdx =
10372 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers);
10373 bool IsMAC = OldIdx != -1 && Src2ModIdx != -1 &&
10374 Desc.getOperandConstraint(OldIdx, MCOI::TIED_TO) == -1;
10375
10376 unsigned I = 1;
10377 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
10378 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
10379 }
10380
10381 int Fi = 0;
10382 int VdstInIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
10383 bool IsVOP3CvtSrDpp = Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_dpp8_gfx12 ||
10384 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_dpp8_gfx13 ||
10385 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_dpp8_gfx12 ||
10386 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_dpp8_gfx13 ||
10387 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_dpp_gfx12 ||
10388 Opc == AMDGPU::V_CVT_SR_BF8_F32_gfx12_e64_dpp_gfx13 ||
10389 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_dpp_gfx12 ||
10390 Opc == AMDGPU::V_CVT_SR_FP8_F32_gfx12_e64_dpp_gfx13;
10391
10392 for (unsigned E = Operands.size(); I != E; ++I) {
10393
10394 if (IsMAC) {
10395 int NumOperands = Inst.getNumOperands();
10396 if (OldIdx == NumOperands) {
10397 // Handle old operand
10398 constexpr int DST_IDX = 0;
10399 Inst.addOperand(Inst.getOperand(DST_IDX));
10400 } else if (Src2ModIdx == NumOperands) {
10401 // Add unused dummy src2_modifiers
10403 }
10404 }
10405
10406 if (VdstInIdx == static_cast<int>(Inst.getNumOperands())) {
10407 Inst.addOperand(Inst.getOperand(0));
10408 }
10409
10410 if (IsVOP3CvtSrDpp) {
10411 if (Src2ModIdx == static_cast<int>(Inst.getNumOperands())) {
10413 Inst.addOperand(MCOperand::createReg(MCRegister()));
10414 }
10415 }
10416
10417 auto TiedTo =
10418 Desc.getOperandConstraint(Inst.getNumOperands(), MCOI::TIED_TO);
10419 if (TiedTo != -1) {
10420 assert((unsigned)TiedTo < Inst.getNumOperands());
10421 // handle tied old or src2 for MAC instructions
10422 Inst.addOperand(Inst.getOperand(TiedTo));
10423 }
10424 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
10425 // Add the register arguments
10426 if (IsDPP8 && Op.isDppFI()) {
10427 Fi = Op.getImm();
10428 } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
10429 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
10430 } else if (Op.isReg()) {
10431 Op.addRegOperands(Inst, 1);
10432 } else if (Op.isImm() &&
10433 Desc.operands()[Inst.getNumOperands()].RegClass != -1) {
10434 Op.addImmOperands(Inst, 1);
10435 } else if (Op.isImm()) {
10436 OptionalIdx[Op.getImmTy()] = I;
10437 } else {
10438 llvm_unreachable("unhandled operand type");
10439 }
10440 }
10441
10442 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp) && !IsVOP3CvtSrDpp)
10443 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10444 AMDGPUOperand::ImmTyClamp);
10445
10446 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::byte_sel)) {
10447 if (VdstInIdx == static_cast<int>(Inst.getNumOperands()))
10448 Inst.addOperand(Inst.getOperand(0));
10449 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10450 AMDGPUOperand::ImmTyByteSel);
10451 }
10452
10453 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod))
10454 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10455 AMDGPUOperand::ImmTyOModSI);
10456
10458 cvtVOP3P(Inst, Operands, OptionalIdx);
10459 else if (SIInstrFlags::isVOP3(Desc))
10460 cvtVOP3OpSel(Inst, Operands, OptionalIdx);
10461 else if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) {
10462 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10463 AMDGPUOperand::ImmTyOpSel);
10464 }
10465
10466 if (IsDPP8) {
10467 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10468 AMDGPUOperand::ImmTyDPP8);
10469 using namespace llvm::AMDGPU::DPP;
10470 Inst.addOperand(MCOperand::createImm(Fi ? DPP8_FI_1 : DPP8_FI_0));
10471 } else {
10472 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10473 AMDGPUOperand::ImmTyDppCtrl, 0xe4);
10474 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10475 AMDGPUOperand::ImmTyDppRowMask, 0xf);
10476 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10477 AMDGPUOperand::ImmTyDppBankMask, 0xf);
10478 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10479 AMDGPUOperand::ImmTyDppBoundCtrl);
10480
10481 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::fi))
10482 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10483 AMDGPUOperand::ImmTyDppFI);
10484 }
10485}
10486
10487void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands,
10488 bool IsDPP8) {
10489 OptionalImmIndexMap OptionalIdx;
10490
10491 unsigned I = 1;
10492 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
10493 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
10494 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
10495 }
10496
10497 int Fi = 0;
10498 for (unsigned E = Operands.size(); I != E; ++I) {
10499 auto TiedTo =
10500 Desc.getOperandConstraint(Inst.getNumOperands(), MCOI::TIED_TO);
10501 if (TiedTo != -1) {
10502 assert((unsigned)TiedTo < Inst.getNumOperands());
10503 // handle tied old or src2 for MAC instructions
10504 Inst.addOperand(Inst.getOperand(TiedTo));
10505 }
10506 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
10507 // Add the register arguments
10508 if (Op.isReg() && validateVccOperand(Op.getReg())) {
10509 // VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token.
10510 // Skip it.
10511 continue;
10512 }
10513
10514 if (IsDPP8) {
10515 if (Op.isDPP8()) {
10516 Op.addImmOperands(Inst, 1);
10517 } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
10518 Op.addRegWithFPInputModsOperands(Inst, 2);
10519 } else if (Op.isDppFI()) {
10520 Fi = Op.getImm();
10521 } else if (Op.isReg()) {
10522 Op.addRegOperands(Inst, 1);
10523 } else {
10524 llvm_unreachable("Invalid operand type");
10525 }
10526 } else {
10528 Op.addRegWithFPInputModsOperands(Inst, 2);
10529 } else if (Op.isReg()) {
10530 Op.addRegOperands(Inst, 1);
10531 } else if (Op.isDPPCtrl()) {
10532 Op.addImmOperands(Inst, 1);
10533 } else if (Op.isImm()) {
10534 // Handle optional arguments
10535 OptionalIdx[Op.getImmTy()] = I;
10536 } else {
10537 llvm_unreachable("Invalid operand type");
10538 }
10539 }
10540 }
10541
10542 if (IsDPP8) {
10543 using namespace llvm::AMDGPU::DPP;
10544 Inst.addOperand(MCOperand::createImm(Fi ? DPP8_FI_1 : DPP8_FI_0));
10545 } else {
10546 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10547 AMDGPUOperand::ImmTyDppRowMask, 0xf);
10548 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10549 AMDGPUOperand::ImmTyDppBankMask, 0xf);
10550 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10551 AMDGPUOperand::ImmTyDppBoundCtrl);
10552 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::fi)) {
10553 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10554 AMDGPUOperand::ImmTyDppFI);
10555 }
10556 }
10557}
10558
10559//===----------------------------------------------------------------------===//
10560// sdwa
10561//===----------------------------------------------------------------------===//
10562
10563ParseStatus AMDGPUAsmParser::parseSDWASel(OperandVector &Operands,
10564 StringRef Prefix,
10565 AMDGPUOperand::ImmTy Type) {
10566 return parseStringOrIntWithPrefix(
10567 Operands, Prefix,
10568 {"BYTE_0", "BYTE_1", "BYTE_2", "BYTE_3", "WORD_0", "WORD_1", "DWORD"},
10569 Type);
10570}
10571
10572ParseStatus AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
10573 return parseStringOrIntWithPrefix(
10574 Operands, "dst_unused", {"UNUSED_PAD", "UNUSED_SEXT", "UNUSED_PRESERVE"},
10575 AMDGPUOperand::ImmTySDWADstUnused);
10576}
10577
10578void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
10579 cvtSDWA(Inst, Operands, SDWAInstType::VOP1);
10580}
10581
10582void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
10583 cvtSDWA(Inst, Operands, SDWAInstType::VOP2);
10584}
10585
10586void AMDGPUAsmParser::cvtSdwaVOP2b(MCInst &Inst,
10587 const OperandVector &Operands) {
10588 cvtSDWA(Inst, Operands, SDWAInstType::VOP2, true, true);
10589}
10590
10591void AMDGPUAsmParser::cvtSdwaVOP2e(MCInst &Inst,
10592 const OperandVector &Operands) {
10593 cvtSDWA(Inst, Operands, SDWAInstType::VOP2, false, true);
10594}
10595
10596void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
10597 cvtSDWA(Inst, Operands, SDWAInstType::VOPC, isVI());
10598}
10599
10600void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
10601 SDWAInstType BasicInstType, bool SkipDstVcc,
10602 bool SkipSrcVcc) {
10603 using namespace llvm::AMDGPU::SDWA;
10604
10605 OptionalImmIndexMap OptionalIdx;
10606 bool SkipVcc = SkipDstVcc || SkipSrcVcc;
10607 bool SkippedVcc = false;
10608
10609 unsigned I = 1;
10610 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
10611 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
10612 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
10613 }
10614
10615 for (unsigned E = Operands.size(); I != E; ++I) {
10616 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
10617 if (SkipVcc && !SkippedVcc && Op.isReg() &&
10618 (Op.getReg() == AMDGPU::VCC || Op.getReg() == AMDGPU::VCC_LO)) {
10619 // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst.
10620 // Skip it if it's 2nd (e.g. v_add_i32_sdwa v1, vcc, v2, v3)
10621 // or 4th (v_addc_u32_sdwa v1, vcc, v2, v3, vcc) operand.
10622 // Skip VCC only if we didn't skip it on previous iteration.
10623 // Note that src0 and src1 occupy 2 slots each because of modifiers.
10624 if (BasicInstType == SDWAInstType::VOP2 &&
10625 ((SkipDstVcc && Inst.getNumOperands() == 1) ||
10626 (SkipSrcVcc && Inst.getNumOperands() == 5))) {
10627 SkippedVcc = true;
10628 continue;
10629 }
10630 if (BasicInstType == SDWAInstType::VOPC && Inst.getNumOperands() == 0) {
10631 SkippedVcc = true;
10632 continue;
10633 }
10634 }
10636 Op.addRegOrImmWithInputModsOperands(Inst, 2);
10637 } else if (Op.isImm()) {
10638 // Handle optional arguments
10639 OptionalIdx[Op.getImmTy()] = I;
10640 } else {
10641 llvm_unreachable("Invalid operand type");
10642 }
10643 SkippedVcc = false;
10644 }
10645
10646 const unsigned Opc = Inst.getOpcode();
10647 if (Opc != AMDGPU::V_NOP_sdwa_gfx10 && Opc != AMDGPU::V_NOP_sdwa_gfx9 &&
10648 Opc != AMDGPU::V_NOP_sdwa_vi) {
10649 // v_nop_sdwa_sdwa_vi/gfx9 has no optional sdwa arguments
10650 switch (BasicInstType) {
10651 case SDWAInstType::VOP1:
10652 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp))
10653 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10654 AMDGPUOperand::ImmTyClamp, 0);
10655
10656 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod))
10657 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10658 AMDGPUOperand::ImmTyOModSI, 0);
10659
10660 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::dst_sel))
10661 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10662 AMDGPUOperand::ImmTySDWADstSel, SdwaSel::DWORD);
10663
10664 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::dst_unused))
10665 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10666 AMDGPUOperand::ImmTySDWADstUnused,
10667 DstUnused::UNUSED_PRESERVE);
10668
10669 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10670 AMDGPUOperand::ImmTySDWASrc0Sel, SdwaSel::DWORD);
10671 break;
10672
10673 case SDWAInstType::VOP2:
10674 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10675 AMDGPUOperand::ImmTyClamp, 0);
10676
10677 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::omod))
10678 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10679 AMDGPUOperand::ImmTyOModSI, 0);
10680
10681 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10682 AMDGPUOperand::ImmTySDWADstSel, SdwaSel::DWORD);
10683 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10684 AMDGPUOperand::ImmTySDWADstUnused,
10685 DstUnused::UNUSED_PRESERVE);
10686 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10687 AMDGPUOperand::ImmTySDWASrc0Sel, SdwaSel::DWORD);
10688 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10689 AMDGPUOperand::ImmTySDWASrc1Sel, SdwaSel::DWORD);
10690 break;
10691
10692 case SDWAInstType::VOPC:
10693 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::clamp))
10694 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10695 AMDGPUOperand::ImmTyClamp, 0);
10696 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10697 AMDGPUOperand::ImmTySDWASrc0Sel, SdwaSel::DWORD);
10698 addOptionalImmOperand(Inst, Operands, OptionalIdx,
10699 AMDGPUOperand::ImmTySDWASrc1Sel, SdwaSel::DWORD);
10700 break;
10701 }
10702 }
10703
10704 // special case v_mac_{f16, f32}:
10705 // it has src2 register operand that is tied to dst operand
10706 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
10707 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
10708 auto *it = Inst.begin();
10709 std::advance(
10710 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
10711 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
10712 }
10713}
10714
10715/// Force static initialization.
10716extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
10722
10723#define GET_MATCHER_IMPLEMENTATION
10724#define GET_MNEMONIC_SPELL_CHECKER
10725#define GET_MNEMONIC_CHECKER
10726#include "AMDGPUGenAsmMatcher.inc"
10727
10728ParseStatus AMDGPUAsmParser::parseCustomOperand(OperandVector &Operands,
10729 unsigned MCK) {
10730 switch (MCK) {
10731 case MCK_addr64:
10732 return parseTokenOp("addr64", Operands);
10733 case MCK_done:
10734 return parseNamedBit("done", Operands, AMDGPUOperand::ImmTyDone, true);
10735 case MCK_idxen:
10736 return parseTokenOp("idxen", Operands);
10737 case MCK_lds:
10738 return parseNamedBit("lds", Operands, AMDGPUOperand::ImmTyLDS,
10739 /*IgnoreNegative=*/true);
10740 case MCK_offen:
10741 return parseTokenOp("offen", Operands);
10742 case MCK_off:
10743 return parseTokenOp("off", Operands);
10744 case MCK_row_95_en:
10745 return parseNamedBit("row_en", Operands, AMDGPUOperand::ImmTyRowEn, true);
10746 case MCK_gds:
10747 return parseNamedBit("gds", Operands, AMDGPUOperand::ImmTyGDS);
10748 case MCK_tfe:
10749 return parseNamedBit("tfe", Operands, AMDGPUOperand::ImmTyTFE);
10750 }
10751 return tryCustomParseOperand(Operands, MCK);
10752}
10753
10754// This function should be defined after auto-generated include so that we have
10755// MatchClassKind enum defined
10756unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
10757 unsigned Kind) {
10758 // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
10759 // But MatchInstructionImpl() expects to meet token and fails to validate
10760 // operand. This method checks if we are given immediate operand but expect to
10761 // get corresponding token.
10762 AMDGPUOperand &Operand = (AMDGPUOperand &)Op;
10763 switch (Kind) {
10764 case MCK_addr64:
10765 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
10766 case MCK_gds:
10767 return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
10768 case MCK_lds:
10769 return Operand.isLDS() ? Match_Success : Match_InvalidOperand;
10770 case MCK_idxen:
10771 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
10772 case MCK_offen:
10773 return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
10774 case MCK_tfe:
10775 return Operand.isTFE() ? Match_Success : Match_InvalidOperand;
10776 case MCK_done:
10777 return Operand.isDone() ? Match_Success : Match_InvalidOperand;
10778 case MCK_row_95_en:
10779 return Operand.isRowEn() ? Match_Success : Match_InvalidOperand;
10780 case MCK_SSrc_b32:
10781 // When operands have expression values, they will return true for isToken,
10782 // because it is not possible to distinguish between a token and an
10783 // expression at parse time. MatchInstructionImpl() will always try to
10784 // match an operand as a token, when isToken returns true, and when the
10785 // name of the expression is not a valid token, the match will fail,
10786 // so we need to handle it here.
10787 return Operand.isSSrc_b32() ? Match_Success : Match_InvalidOperand;
10788 case MCK_SSrc_f32:
10789 return Operand.isSSrc_f32() ? Match_Success : Match_InvalidOperand;
10790 case MCK_SOPPBrTarget:
10791 return Operand.isSOPPBrTarget() ? Match_Success : Match_InvalidOperand;
10792 case MCK_VReg32OrOff:
10793 return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand;
10794 case MCK_InterpSlot:
10795 return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand;
10796 case MCK_InterpAttr:
10797 return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
10798 case MCK_InterpAttrChan:
10799 return Operand.isInterpAttrChan() ? Match_Success : Match_InvalidOperand;
10800 case MCK_SReg_64:
10801 case MCK_SReg_64_XEXEC:
10802 // Null is defined as a 32-bit register but
10803 // it should also be enabled with 64-bit operands or larger.
10804 // The following code enables it for SReg_64 and larger operands
10805 // used as source and destination. Remaining source
10806 // operands are handled in isInlinableImm.
10807 case MCK_SReg_96:
10808 case MCK_SReg_128:
10809 case MCK_SReg_256:
10810 case MCK_SReg_512:
10811 return Operand.isNull() ? Match_Success : Match_InvalidOperand;
10812 default:
10813 return Match_InvalidOperand;
10814 }
10815}
10816
10817//===----------------------------------------------------------------------===//
10818// endpgm
10819//===----------------------------------------------------------------------===//
10820
10821ParseStatus AMDGPUAsmParser::parseEndpgm(OperandVector &Operands) {
10822 SMLoc S = getLoc();
10823 int64_t Imm = 0;
10824
10825 if (!parseExpr(Imm)) {
10826 // The operand is optional, if not present default to 0
10827 Imm = 0;
10828 }
10829
10830 if (!isUInt<16>(Imm))
10831 return Error(S, "expected a 16-bit value");
10832
10833 Operands.push_back(
10834 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyEndpgm));
10835 return ParseStatus::Success;
10836}
10837
10838bool AMDGPUOperand::isEndpgm() const { return isImmTy(ImmTyEndpgm); }
10839
10840//===----------------------------------------------------------------------===//
10841// Split Barrier
10842//===----------------------------------------------------------------------===//
10843
10844bool AMDGPUOperand::isSplitBarrier() const {
10845 if (!isImm())
10846 return false;
10847
10848 int64_t Imm = getImm();
10851}
#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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_READNONE
Definition Compiler.h:323
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
@ Default
#define Check(C,...)
static llvm::Expected< InlineInfo > decode(GsymDataExtractor &Data, uint64_t &Offset, uint64_t BaseAddr)
Decode an InlineInfo in Data at the specified offset.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RegName(no)
Loop::LoopBounds::Direction Direction
Definition LoopInfo.cpp:253
static bool hasFeature(StringRef Feature, const FeatureBitset &FeatureBits, ArrayRef< SubtargetFeatureKV > ProcFeatures)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
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")))
SI Fold Operands
Interface definition for SIInstrInfo.
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
const char * Msg
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
This file implements the SmallBitVector class.
StringSet - A set-like wrapper for the StringMap.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
BinaryOperator * Mul
static const char * getRegisterName(MCRegister Reg)
static const AMDGPUMCExpr * createMax(ArrayRef< const MCExpr * > Args, MCContext &Ctx)
static unsigned getNumExpectedArgs(VariantKind Kind)
static const AMDGPUMCExpr * createLit(LitModifier Lit, int64_t Value, MCContext &Ctx)
static const AMDGPUMCExpr * create(VariantKind Kind, ArrayRef< const MCExpr * > Args, MCContext &Ctx)
static const AMDGPUMCExpr * createExtraSGPRs(const MCExpr *VCCUsed, const MCExpr *FlatScrUsed, bool XNACKUsed, MCContext &Ctx)
Allow delayed MCExpr resolve of ExtraSGPRs (in case VCCUsed or FlatScrUsed are unresolvable but neede...
static const AMDGPUMCExpr * createAlignTo(const MCExpr *Value, const MCExpr *Align, MCContext &Ctx)
static std::optional< TargetID > parseTargetIDString(StringRef TargetIDDirective)
Parse and validate a TargetID from a full "<triple>-<processor>:<features>" directive string.
TargetIDSetting getXnackSetting() const
StringRef getTargetTripleString() const
std::string toString() const
TargetIDSetting getSramEccSetting() const
static const fltSemantics & IEEEsingle()
Definition APFloat.h:304
static const fltSemantics & BFloat()
Definition APFloat.h:303
static const fltSemantics & IEEEdouble()
Definition APFloat.h:305
static constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:353
static const fltSemantics & IEEEhalf()
Definition APFloat.h:302
opStatus
IEEE-754R 7: Default exception handling.
Definition APFloat.h:369
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Definition APFloat.cpp:5934
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)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition StringRef.h:888
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
Definition StringRef.h:691
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:597
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition StringRef.h:635
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:138
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition StringRef.h:270
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition StringRef.h:661
bool contains(StringRef key) const
Check if the set contains the given key.
Definition StringSet.h:60
std::pair< typename Base::iterator, bool > insert(StringRef key)
Definition StringSet.h:39
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
Definition Twine.cpp:17
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
int encodeDepCtr(const StringRef Name, int64_t Val, unsigned &UsedOprMask, const MCSubtargetInfo &STI)
int getDefaultDepCtrEncoding(const MCSubtargetInfo &STI)
bool isSupportedTgtId(unsigned Id, const MCSubtargetInfo &STI)
unsigned getTgtId(const StringRef Name)
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char NumSGPRs[]
Key for Kernel::CodeProps::Metadata::mNumSGPRs.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
constexpr char AssemblerDirectiveBegin[]
HSA metadata beginning assembler directive.
constexpr char AssemblerDirectiveEnd[]
HSA metadata ending assembler directive.
constexpr char AssemblerDirectiveBegin[]
Old HSA metadata beginning assembler directive for V2.
int64_t getHwregId(StringRef Name, const MCSubtargetInfo &STI)
unsigned getVGPREncodingGranule(const MCSubtargetInfo &STI, std::optional< bool > EnableWavefrontSize32)
unsigned getSGPREncodingGranule(const MCSubtargetInfo &STI)
bool targetIDSettingsConflict(TargetIDSetting Lhs, TargetIDSetting Rhs)
Returns true if Lhs and Rhs are incompatible (both specific but different).
unsigned getLocalMemorySize(const MCSubtargetInfo &STI)
unsigned getDefaultFormatEncoding(const MCSubtargetInfo &STI)
int64_t convertDfmtNfmt2Ufmt(unsigned Dfmt, unsigned Nfmt, const MCSubtargetInfo &STI)
int64_t encodeDfmtNfmt(unsigned Dfmt, unsigned Nfmt)
int64_t getUnifiedFormat(const StringRef Name, const MCSubtargetInfo &STI)
bool isValidFormatEncoding(unsigned Val, const MCSubtargetInfo &STI)
int64_t getNfmt(const StringRef Name, const MCSubtargetInfo &STI)
int64_t getDfmt(const StringRef Name)
constexpr char AssemblerDirective[]
PAL metadata (old linear format) assembler directive.
constexpr char AssemblerDirectiveBegin[]
PAL metadata (new MsgPack format) beginning assembler directive.
constexpr char AssemblerDirectiveEnd[]
PAL metadata (new MsgPack format) ending assembler directive.
int64_t getMsgOpId(int64_t MsgId, StringRef Name, const MCSubtargetInfo &STI)
Map from a symbolic name for a sendmsg operation to the operation portion of the immediate encoding.
int64_t getMsgId(StringRef Name, const MCSubtargetInfo &STI)
Map from a symbolic name for a msg_id to the message portion of the immediate encoding.
uint64_t encodeMsg(uint64_t MsgId, uint64_t OpId, uint64_t StreamId)
bool msgSupportsStream(int64_t MsgId, int64_t OpId, const MCSubtargetInfo &STI)
bool isValidMsgId(int64_t MsgId, const MCSubtargetInfo &STI)
bool isValidMsgStream(int64_t MsgId, int64_t OpId, int64_t StreamId, const MCSubtargetInfo &STI, bool Strict)
bool msgRequiresOp(int64_t MsgId, const MCSubtargetInfo &STI)
bool isValidMsgOp(int64_t MsgId, int64_t OpId, const MCSubtargetInfo &STI, bool Strict)
ArrayRef< GFXVersion > getGFXVersions()
constexpr unsigned COMPONENTS[]
constexpr const char *const ModMatrixFmt[]
constexpr const char *const ModMatrixScaleFmt[]
constexpr const char *const ModMatrixScale[]
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
bool isGFX10_BEncoding(const MCSubtargetInfo &STI)
bool isInlineValue(MCRegister Reg)
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool isSGPR(MCRegister Reg, const MCRegisterInfo *TRI)
Is Reg - scalar register.
MCRegister getMCReg(MCRegister Reg, const MCSubtargetInfo &STI)
If Reg is a pseudo reg, return the correct hardware register given STI otherwise return Reg.
FuncInfoFlags
Per-function flags packed into INFO_FLAGS entries.
uint8_t wmmaScaleF8F6F4FormatToNumRegs(unsigned Fmt)
const int OPR_ID_UNSUPPORTED
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
unsigned getTemporalHintType(const MCInstrDesc TID)
int32_t getTotalNumVGPRs(bool has90AInsts, int32_t ArgNumAGPR, int32_t ArgNumVGPR)
bool isGFX10(const MCSubtargetInfo &STI)
LLVM_READONLY bool isLitExpr(const MCExpr *Expr)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_ABI bool isCPUValidForSubArch(Triple::SubArchType SubArch, GPUKind AK)
Return true if the GPU AK is usable with the triple subarch SubArch.
unsigned getMaxNumUserSGPRs(const MCSubtargetInfo &STI)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool hasA16(const MCSubtargetInfo &STI)
bool isLegalSMRDEncodedSignedOffset(const MCSubtargetInfo &ST, int64_t EncodedOffset, bool IsBuffer)
bool isGFX12Plus(const MCSubtargetInfo &STI)
unsigned getNSAMaxSize(const MCSubtargetInfo &STI, bool HasSampler)
bool hasPackedD16(const MCSubtargetInfo &STI)
bool isGFX940(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
bool isHsaAbi(const MCSubtargetInfo &STI)
bool isGFX11(const MCSubtargetInfo &STI)
const int OPR_VAL_INVALID
bool getSMEMIsBuffer(unsigned Opc)
bool isPackedSingleSGPRFP32Inst(unsigned Opc)
The opcode is a packed fp32 instruction which only reads low 32 bits of a scalar operand and propagat...
bool isGFX13(const MCSubtargetInfo &STI)
LLVM_ABI unsigned getAddressableNumSGPRs(GPUKind AK)
uint8_t mfmaScaleF8F6F4FormatToNumRegs(unsigned EncodingVal)
LLVM_ABI IsaVersion getIsaVersion(StringRef GPU)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
CanBeVOPD getCanBeVOPD(unsigned Opc, unsigned EncodingFamily, bool VOPD3)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
bool isSI(const MCSubtargetInfo &STI)
bool hasPrivateApertureRegs(const MCSubtargetInfo &STI)
unsigned decodeLgkmcnt(const IsaVersion &Version, unsigned Waitcnt)
unsigned getWaitcntBitMask(const IsaVersion &Version)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
bool isGFX9(const MCSubtargetInfo &STI)
unsigned getVOPDEncodingFamily(const MCSubtargetInfo &ST)
bool isKImmOperand(const MCInstrDesc &Desc, unsigned OpNo)
Is this a KImm operand?
GPUKind
GPU kinds supported by the AMDGPU target.
bool isGFX90A(const MCSubtargetInfo &STI)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
bool isGFX12(const MCSubtargetInfo &STI)
unsigned encodeExpcnt(const IsaVersion &Version, unsigned Waitcnt, unsigned Expcnt)
bool hasMAIInsts(const MCSubtargetInfo &STI)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByAsmSuffix(StringRef AsmSuffix)
bool hasMIMG_R128(const MCSubtargetInfo &STI)
LLVM_ABI GPUKind parseArchAMDGCN(StringRef CPU)
bool hasG16(const MCSubtargetInfo &STI)
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
bool isGFX13Plus(const MCSubtargetInfo &STI)
bool hasArchitectedFlatScratch(const MCSubtargetInfo &STI)
LLVM_READONLY int64_t getLitValue(const MCExpr *Expr)
bool isGFX11Plus(const MCSubtargetInfo &STI)
bool isSISrcFPOperand(const MCInstrDesc &Desc, unsigned OpNo)
Is this floating-point operand?
bool isGFX10Plus(const MCSubtargetInfo &STI)
AMDGPU::TargetID TargetID
int64_t encode32BitLiteral(int64_t Imm, OperandType Type, bool IsLit)
bool isValidWMMAScaleFmtCombination(unsigned AFmt, unsigned AScale, unsigned BFmt, unsigned BScale)
@ OPERAND_REG_IMM_V2FP64
Definition SIDefines.h: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)
bool hasPopsExitingWaveID(const MCSubtargetInfo &STI)
unsigned decodeVmcnt(const IsaVersion &Version, unsigned Waitcnt)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
bool hasVOPD(const MCSubtargetInfo &STI)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
bool isPermlane16(unsigned Opc)
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ STT_AMDGPU_HSA_KERNEL
Definition ELF.h:1440
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:233
@ OPERAND_IMMEDIATE
Definition MCInstrDesc.h:61
Predicate getPredicate(unsigned Condition, unsigned Hint)
Return predicate consisting of specified condition and hint bits.
void validate(const Triple &TT, const FeatureBitset &FeatureBits)
constexpr bool isAtomicRet(const T &...O)
Definition SIDefines.h: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,...