@@ -87,6 +87,17 @@ const char* const OpGsSymbolic[] = {
87
87
88
88
using namespace llvm ;
89
89
90
+ // In some cases (e.g. buffer atomic instructions) MatchOperandParserImpl()
91
+ // may invoke tryCustomParseOperand() multiple times with the same MCK value.
92
+ // That leads to adding of the same "default" operand multiple times in a row,
93
+ // which is wrong. The workaround adds only the 1st default operand, while for
94
+ // the rest the "dummy" operands being added. The reason for dummies is that if
95
+ // we just skip adding an operand, then parser would get stuck in endless loop.
96
+ // Dummies shall be removed prior matching & emitting MCInsts.
97
+ //
98
+ // Comment out this macro to disable the workaround.
99
+ #define WORKAROUND_USE_DUMMY_OPERANDS_INSTEAD_MUTIPLE_DEFAULT_OPERANDS
100
+
90
101
namespace {
91
102
92
103
struct OptionalOperand ;
@@ -99,6 +110,9 @@ class AMDGPUOperand : public MCParsedAsmOperand {
99
110
Immediate,
100
111
Register,
101
112
Expression
113
+ #ifdef WORKAROUND_USE_DUMMY_OPERANDS_INSTEAD_MUTIPLE_DEFAULT_OPERANDS
114
+ ,Dummy
115
+ #endif
102
116
} Kind;
103
117
104
118
SMLoc StartLoc, EndLoc;
@@ -204,6 +218,12 @@ class AMDGPUOperand : public MCParsedAsmOperand {
204
218
}
205
219
}
206
220
221
+ #ifdef WORKAROUND_USE_DUMMY_OPERANDS_INSTEAD_MUTIPLE_DEFAULT_OPERANDS
222
+ bool isDummy () const {
223
+ return Kind == Dummy;
224
+ }
225
+ #endif
226
+
207
227
bool isToken () const override {
208
228
return Kind == Token;
209
229
}
@@ -440,6 +460,11 @@ class AMDGPUOperand : public MCParsedAsmOperand {
440
460
case Expression:
441
461
OS << " <expr " << *Expr << ' >' ;
442
462
break ;
463
+ #ifdef WORKAROUND_USE_DUMMY_OPERANDS_INSTEAD_MUTIPLE_DEFAULT_OPERANDS
464
+ case Dummy:
465
+ OS << " <dummy>" ;
466
+ break ;
467
+ #endif
443
468
}
444
469
}
445
470
@@ -490,6 +515,15 @@ class AMDGPUOperand : public MCParsedAsmOperand {
490
515
return Op;
491
516
}
492
517
518
+ #ifdef WORKAROUND_USE_DUMMY_OPERANDS_INSTEAD_MUTIPLE_DEFAULT_OPERANDS
519
+ static AMDGPUOperand::Ptr CreateDummy (SMLoc S) {
520
+ auto Op = llvm::make_unique<AMDGPUOperand>(Dummy);
521
+ Op->StartLoc = S;
522
+ Op->EndLoc = S;
523
+ return Op;
524
+ }
525
+ #endif
526
+
493
527
bool isSWaitCnt () const ;
494
528
bool isHwreg () const ;
495
529
bool isSendMsg () const ;
@@ -545,6 +579,7 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
545
579
bool ParseSectionDirectiveHSARodataReadonlyAgent ();
546
580
bool AddNextRegisterToList (unsigned & Reg, unsigned & RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum);
547
581
bool ParseAMDGPURegister (RegisterKind& RegKind, unsigned & Reg, unsigned & RegNum, unsigned & RegWidth);
582
+ void cvtMubufImpl (MCInst &Inst, const OperandVector &Operands, bool IsAtomic, bool IsAtomicReturn);
548
583
549
584
public:
550
585
enum AMDGPUMatchResultTy {
@@ -633,8 +668,9 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
633
668
OperandMatchResultTy parseSOppBrTarget (OperandVector &Operands);
634
669
AMDGPUOperand::Ptr defaultHwreg () const ;
635
670
636
-
637
- void cvtMubuf (MCInst &Inst, const OperandVector &Operands);
671
+ void cvtMubuf (MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl (Inst, Operands, false , false ); }
672
+ void cvtMubufAtomic (MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl (Inst, Operands, true , false ); }
673
+ void cvtMubufAtomicReturn (MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl (Inst, Operands, true , true ); }
638
674
AMDGPUOperand::Ptr defaultMubufOffset () const ;
639
675
AMDGPUOperand::Ptr defaultGLC () const ;
640
676
AMDGPUOperand::Ptr defaultSLC () const ;
@@ -926,6 +962,17 @@ bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
926
962
bool MatchingInlineAsm) {
927
963
MCInst Inst;
928
964
965
+ #ifdef WORKAROUND_USE_DUMMY_OPERANDS_INSTEAD_MUTIPLE_DEFAULT_OPERANDS
966
+ // Remove dummies prior matching. Iterate backwards becase vector::erase()
967
+ // invalidates all iterators which refer after erase point.
968
+ for (auto I = Operands.rbegin (), E = Operands.rend (); I != E; ) {
969
+ auto X = I++;
970
+ if (static_cast <AMDGPUOperand*>(X->get ())->isDummy ()) {
971
+ Operands.erase (X.base () -1 );
972
+ }
973
+ }
974
+ #endif
975
+
929
976
switch (MatchInstructionImpl (Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
930
977
default : break ;
931
978
case Match_Success:
@@ -1430,6 +1477,25 @@ AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
1430
1477
}
1431
1478
1432
1479
Operands.push_back (AMDGPUOperand::CreateImm (Value, S, ImmTy));
1480
+
1481
+ #ifdef WORKAROUND_USE_DUMMY_OPERANDS_INSTEAD_MUTIPLE_DEFAULT_OPERANDS
1482
+ if (Value == Default && AddDefault) {
1483
+ // Reverse lookup in previously added operands (skip just added one)
1484
+ // for the first non-dummy operand. If it is of the same type,
1485
+ // then replace just added default operand with dummy.
1486
+ for (auto I = Operands.rbegin (), E = Operands.rend (); I != E; ++I) {
1487
+ if (I == Operands.rbegin ())
1488
+ continue ;
1489
+ if (static_cast <AMDGPUOperand*>(I->get ())->isDummy ())
1490
+ continue ;
1491
+ if (static_cast <AMDGPUOperand*>(I->get ())->isImmTy (ImmTy)) {
1492
+ Operands.pop_back ();
1493
+ Operands.push_back (AMDGPUOperand::CreateDummy (S)); // invalidates iterators
1494
+ break ;
1495
+ }
1496
+ }
1497
+ }
1498
+ #endif
1433
1499
return MatchOperand_Success;
1434
1500
}
1435
1501
@@ -2047,9 +2113,11 @@ AMDGPUOperand::Ptr AMDGPUAsmParser::defaultTFE() const {
2047
2113
return AMDGPUOperand::CreateImm (0 , SMLoc (), AMDGPUOperand::ImmTyTFE);
2048
2114
}
2049
2115
2050
- void AMDGPUAsmParser::cvtMubuf (MCInst &Inst,
2051
- const OperandVector &Operands) {
2116
+ void AMDGPUAsmParser::cvtMubufImpl (MCInst &Inst,
2117
+ const OperandVector &Operands,
2118
+ bool IsAtomic, bool IsAtomicReturn) {
2052
2119
OptionalImmIndexMap OptionalIdx;
2120
+ assert (IsAtomicReturn ? IsAtomic : true );
2053
2121
2054
2122
for (unsigned i = 1 , e = Operands.size (); i != e; ++i) {
2055
2123
AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
@@ -2077,8 +2145,16 @@ void AMDGPUAsmParser::cvtMubuf(MCInst &Inst,
2077
2145
OptionalIdx[Op.getImmTy ()] = i;
2078
2146
}
2079
2147
2148
+ // Copy $vdata_in operand and insert as $vdata for MUBUF_Atomic RTN insns.
2149
+ if (IsAtomicReturn) {
2150
+ MCInst::iterator I = Inst.begin (); // $vdata_in is always at the beginning.
2151
+ Inst.insert (I, *I);
2152
+ }
2153
+
2080
2154
addOptionalImmOperand (Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
2081
- addOptionalImmOperand (Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
2155
+ if (!IsAtomic) { // glc is hard-coded.
2156
+ addOptionalImmOperand (Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
2157
+ }
2082
2158
addOptionalImmOperand (Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
2083
2159
addOptionalImmOperand (Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
2084
2160
}
0 commit comments