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