Skip to content

Commit cb5f81d

Browse files
authored
[LLVM][TableGen] Use range for loops in AsmMatcherEmitter (#108914)
Use range for loops in AsmMatcherEmitter. Convert some Record pointers to const.
1 parent cb47b45 commit cb5f81d

File tree

1 file changed

+64
-83
lines changed

1 file changed

+64
-83
lines changed

llvm/utils/TableGen/AsmMatcherEmitter.cpp

Lines changed: 64 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -634,10 +634,10 @@ struct MatchableInfo {
634634

635635
// Compare lexicographically by operand. The matcher validates that other
636636
// orderings wouldn't be ambiguous using \see couldMatchAmbiguouslyWith().
637-
for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
638-
if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class)
637+
for (const auto &[LHSOp, RHSOp] : zip_equal(AsmOperands, RHS.AsmOperands)) {
638+
if (*LHSOp.Class < *RHSOp.Class)
639639
return true;
640-
if (*RHS.AsmOperands[i].Class < *AsmOperands[i].Class)
640+
if (*RHSOp.Class < *LHSOp.Class)
641641
return false;
642642
}
643643

@@ -692,21 +692,21 @@ struct MatchableInfo {
692692

693693
// Tokens and operand kinds are unambiguous (assuming a correct target
694694
// specific parser).
695-
for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i)
696-
if (AsmOperands[i].Class->Kind != RHS.AsmOperands[i].Class->Kind ||
697-
AsmOperands[i].Class->Kind == ClassInfo::Token)
698-
if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class ||
699-
*RHS.AsmOperands[i].Class < *AsmOperands[i].Class)
695+
for (const auto &[LHSOp, RHSOp] : zip_equal(AsmOperands, RHS.AsmOperands)) {
696+
if (LHSOp.Class->Kind != RHSOp.Class->Kind ||
697+
LHSOp.Class->Kind == ClassInfo::Token)
698+
if (*LHSOp.Class < *RHSOp.Class || *RHSOp.Class < *LHSOp.Class)
700699
return false;
700+
}
701701

702702
// Otherwise, this operand could commute if all operands are equivalent, or
703703
// there is a pair of operands that compare less than and a pair that
704704
// compare greater than.
705705
bool HasLT = false, HasGT = false;
706-
for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
707-
if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class)
706+
for (const auto &[LHSOp, RHSOp] : zip_equal(AsmOperands, RHS.AsmOperands)) {
707+
if (*LHSOp.Class < *RHSOp.Class)
708708
HasLT = true;
709-
if (*RHS.AsmOperands[i].Class < *AsmOperands[i].Class)
709+
if (*RHSOp.Class < *LHSOp.Class)
710710
HasGT = true;
711711
}
712712

@@ -810,7 +810,7 @@ class AsmMatcherInfo {
810810

811811
/// getSubtargetFeature - Lookup or create the subtarget feature info for the
812812
/// given operand.
813-
const SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const {
813+
const SubtargetFeatureInfo *getSubtargetFeature(const Record *Def) const {
814814
assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!");
815815
const auto &I = SubtargetFeatures.find(Def);
816816
return I == SubtargetFeatures.end() ? nullptr : &I->second;
@@ -833,9 +833,8 @@ LLVM_DUMP_METHOD void MatchableInfo::dump() const {
833833

834834
errs() << " variant: " << AsmVariantID << "\n";
835835

836-
for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
837-
const AsmOperand &Op = AsmOperands[i];
838-
errs() << " op[" << i << "] = " << Op.Class->ClassName << " - ";
836+
for (const auto &[Idx, Op] : enumerate(AsmOperands)) {
837+
errs() << " op[" << Idx << "] = " << Op.Class->ClassName << " - ";
839838
errs() << '\"' << Op.Token << "\"\n";
840839
}
841840
}
@@ -1490,21 +1489,18 @@ void AsmMatcherInfo::buildOperandMatchInfo() {
14901489
// Keep track of all operands of this instructions which belong to the
14911490
// same class.
14921491
unsigned NumOptionalOps = 0;
1493-
for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) {
1494-
const MatchableInfo::AsmOperand &Op = MI->AsmOperands[i];
1492+
for (const auto &[Idx, Op] : enumerate(MI->AsmOperands)) {
14951493
if (CallCustomParserForAllOperands || !Op.Class->ParserMethod.empty()) {
14961494
unsigned &OperandMask = OpClassMask[Op.Class];
14971495
OperandMask |= maskTrailingOnes<unsigned>(NumOptionalOps + 1)
1498-
<< (i - NumOptionalOps);
1496+
<< (Idx - NumOptionalOps);
14991497
}
15001498
if (Op.Class->IsOptional)
15011499
++NumOptionalOps;
15021500
}
15031501

15041502
// Generate operand match info for each mnemonic/operand class pair.
1505-
for (const auto &OCM : OpClassMask) {
1506-
unsigned OpMask = OCM.second;
1507-
ClassInfo *CI = OCM.first;
1503+
for (const auto [CI, OpMask] : OpClassMask) {
15081504
OperandMatchInfo.push_back(
15091505
OperandMatchEntry::create(MI.get(), CI, OpMask));
15101506
}
@@ -1613,11 +1609,11 @@ void AsmMatcherInfo::buildInfo() {
16131609
for (auto &II : Matchables) {
16141610
// Parse the tokens after the mnemonic.
16151611
// Note: buildInstructionOperandReference may insert new AsmOperands, so
1616-
// don't precompute the loop bound.
1617-
for (unsigned i = 0; i != II->AsmOperands.size(); ++i) {
1618-
MatchableInfo::AsmOperand &Op = II->AsmOperands[i];
1612+
// don't precompute the loop bound, i.e., cannot use range based for loop
1613+
// here.
1614+
for (size_t Idx = 0; Idx < II->AsmOperands.size(); ++Idx) {
1615+
MatchableInfo::AsmOperand &Op = II->AsmOperands[Idx];
16191616
StringRef Token = Op.Token;
1620-
16211617
// Check for singleton registers.
16221618
if (const Record *RegRecord = Op.SingletonReg) {
16231619
Op.Class = RegisterClasses[RegRecord];
@@ -1645,7 +1641,7 @@ void AsmMatcherInfo::buildInfo() {
16451641
OperandName = Token.substr(1);
16461642

16471643
if (isa<const CodeGenInstruction *>(II->DefRec))
1648-
buildInstructionOperandReference(II.get(), OperandName, i);
1644+
buildInstructionOperandReference(II.get(), OperandName, Idx);
16491645
else
16501646
buildAliasOperandReference(II.get(), OperandName, Op);
16511647
}
@@ -1779,21 +1775,21 @@ void AsmMatcherInfo::buildAliasOperandReference(MatchableInfo *II,
17791775
const CodeGenInstAlias &CGA = *cast<const CodeGenInstAlias *>(II->DefRec);
17801776

17811777
// Set up the operand class.
1782-
for (unsigned i = 0, e = CGA.ResultOperands.size(); i != e; ++i)
1783-
if (CGA.ResultOperands[i].isRecord() &&
1784-
CGA.ResultOperands[i].getName() == OperandName) {
1778+
for (const auto &[ResultOp, SubOpIdx] :
1779+
zip_equal(CGA.ResultOperands, CGA.ResultInstOperandIndex)) {
1780+
if (ResultOp.isRecord() && ResultOp.getName() == OperandName) {
17851781
// It's safe to go with the first one we find, because CodeGenInstAlias
17861782
// validates that all operands with the same name have the same record.
1787-
Op.SubOpIdx = CGA.ResultInstOperandIndex[i].second;
1783+
Op.SubOpIdx = SubOpIdx.second;
17881784
// Use the match class from the Alias definition, not the
17891785
// destination instruction, as we may have an immediate that's
17901786
// being munged by the match class.
1791-
Op.Class =
1792-
getOperandClass(CGA.ResultOperands[i].getRecord(), Op.SubOpIdx);
1787+
Op.Class = getOperandClass(ResultOp.getRecord(), Op.SubOpIdx);
17931788
Op.SrcOpName = OperandName;
17941789
Op.OrigSrcOpName = OperandName;
17951790
return;
17961791
}
1792+
}
17971793

17981794
PrintFatalError(II->TheDef->getLoc(),
17991795
"error: unable to find operand: '" + OperandName + "'");
@@ -1862,13 +1858,11 @@ void MatchableInfo::buildAliasResultOperands(bool AliasConstraintsAreChecked) {
18621858
// populate them.
18631859
unsigned AliasOpNo = 0;
18641860
unsigned LastOpNo = CGA.ResultInstOperandIndex.size();
1865-
for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
1866-
const CGIOperandList::OperandInfo *OpInfo = &ResultInst->Operands[i];
1867-
1861+
for (const auto &[Idx, OpInfo] : enumerate(ResultInst->Operands)) {
18681862
// If this is a tied operand, just copy from the previously handled operand.
18691863
int TiedOp = -1;
1870-
if (OpInfo->MINumOperands == 1)
1871-
TiedOp = OpInfo->getTiedRegister();
1864+
if (OpInfo.MINumOperands == 1)
1865+
TiedOp = OpInfo.getTiedRegister();
18721866
if (TiedOp != -1) {
18731867
unsigned SrcOp1 = 0;
18741868
unsigned SrcOp2 = 0;
@@ -1898,7 +1892,7 @@ void MatchableInfo::buildAliasResultOperands(bool AliasConstraintsAreChecked) {
18981892
// to benefit from the tied-operands check and just match the operand
18991893
// as a normal, but not copy the original (TiedOp) to the result
19001894
// instruction. We do this by passing -1 as the tied operand to copy.
1901-
if (ResultInst->Operands[i].Rec->getName() !=
1895+
if (OpInfo.Rec->getName() !=
19021896
ResultInst->Operands[TiedOp].Rec->getName()) {
19031897
SrcOp1 = ResOperands[TiedOp].AsmOperandNum;
19041898
int SubIdx = CGA.ResultInstOperandIndex[AliasOpNo].second;
@@ -1913,9 +1907,9 @@ void MatchableInfo::buildAliasResultOperands(bool AliasConstraintsAreChecked) {
19131907
}
19141908

19151909
// Handle all the suboperands for this operand.
1916-
const std::string &OpName = OpInfo->Name;
1910+
const std::string &OpName = OpInfo.Name;
19171911
for (; AliasOpNo < LastOpNo &&
1918-
CGA.ResultInstOperandIndex[AliasOpNo].first == i;
1912+
CGA.ResultInstOperandIndex[AliasOpNo].first == Idx;
19191913
++AliasOpNo) {
19201914
int SubIdx = CGA.ResultInstOperandIndex[AliasOpNo].second;
19211915

@@ -1935,7 +1929,7 @@ void MatchableInfo::buildAliasResultOperands(bool AliasConstraintsAreChecked) {
19351929
// record won't be updated and it will fail later on.
19361930
OperandRefs.try_emplace(Name, SrcOperand);
19371931

1938-
unsigned NumOperands = (SubIdx == -1 ? OpInfo->MINumOperands : 1);
1932+
unsigned NumOperands = (SubIdx == -1 ? OpInfo.MINumOperands : 1);
19391933
ResOperands.push_back(
19401934
ResOperand::getRenderedOp(SrcOperand, NumOperands));
19411935
break;
@@ -2110,9 +2104,7 @@ emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
21102104
// Compute the convert enum and the case body.
21112105
MaxRowLength = std::max(MaxRowLength, II->ResOperands.size() * 2 + 1);
21122106

2113-
for (unsigned i = 0, e = II->ResOperands.size(); i != e; ++i) {
2114-
const MatchableInfo::ResOperand &OpInfo = II->ResOperands[i];
2115-
2107+
for (const auto &[Idx, OpInfo] : enumerate(II->ResOperands)) {
21162108
// Generate code to populate each result operand.
21172109
switch (OpInfo.Kind) {
21182110
case MatchableInfo::ResOperand::RenderAsmOperand: {
@@ -2194,7 +2186,7 @@ emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
21942186
uint8_t TiedOp = OpInfo.TiedOperands.ResOpnd;
21952187
uint8_t SrcOp1 = OpInfo.TiedOperands.SrcOpnd1Idx + HasMnemonicFirst;
21962188
uint8_t SrcOp2 = OpInfo.TiedOperands.SrcOpnd2Idx + HasMnemonicFirst;
2197-
assert((i > TiedOp || TiedOp == (uint8_t)-1) &&
2189+
assert((Idx > TiedOp || TiedOp == (uint8_t)-1) &&
21982190
"Tied operand precedes its target!");
21992191
auto TiedTupleName = std::string("Tie") + utostr(TiedOp) + '_' +
22002192
utostr(SrcOp1) + '_' + utostr(SrcOp2);
@@ -2730,26 +2722,21 @@ static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) {
27302722
OS << "}\n\n";
27312723
}
27322724

2733-
static std::string GetAliasRequiredFeatures(Record *R,
2725+
static std::string GetAliasRequiredFeatures(const Record *R,
27342726
const AsmMatcherInfo &Info) {
2735-
std::vector<Record *> ReqFeatures = R->getValueAsListOfDefs("Predicates");
27362727
std::string Result;
27372728

2738-
if (ReqFeatures.empty())
2739-
return Result;
2740-
2741-
for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) {
2742-
const SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]);
2743-
2729+
bool First = true;
2730+
for (const Record *RF : R->getValueAsListOfDefs("Predicates")) {
2731+
const SubtargetFeatureInfo *F = Info.getSubtargetFeature(RF);
27442732
if (!F)
27452733
PrintFatalError(R->getLoc(),
2746-
"Predicate '" + ReqFeatures[i]->getName() +
2734+
"Predicate '" + RF->getName() +
27472735
"' is not marked as an AssemblerPredicate!");
2748-
2749-
if (i)
2736+
if (!First)
27502737
Result += " && ";
2751-
27522738
Result += "Features.test(" + F->getEnumBitName() + ')';
2739+
First = false;
27532740
}
27542741

27552742
return Result;
@@ -2778,16 +2765,14 @@ emitMnemonicAliasVariant(raw_ostream &OS, const AsmMatcherInfo &Info,
27782765
// by the string remapper.
27792766
std::vector<StringMatcher::StringPair> Cases;
27802767
for (const auto &AliasEntry : AliasesFromMnemonic) {
2781-
const std::vector<Record *> &ToVec = AliasEntry.second;
2782-
27832768
// Loop through each alias and emit code that handles each case. If there
27842769
// are two instructions without predicates, emit an error. If there is one,
27852770
// emit it last.
27862771
std::string MatchCode;
27872772
int AliasWithNoPredicate = -1;
27882773

2789-
for (unsigned i = 0, e = ToVec.size(); i != e; ++i) {
2790-
Record *R = ToVec[i];
2774+
ArrayRef<const Record *> ToVec = AliasEntry.second;
2775+
for (const auto &[Idx, R] : enumerate(ToVec)) {
27912776
std::string FeatureMask = GetAliasRequiredFeatures(R, Info);
27922777

27932778
// If this unconditionally matches, remember it for later and diagnose
@@ -2804,7 +2789,7 @@ emitMnemonicAliasVariant(raw_ostream &OS, const AsmMatcherInfo &Info,
28042789
PrintFatalError(R->getLoc(), "this is the other MnemonicAlias.");
28052790
}
28062791

2807-
AliasWithNoPredicate = i;
2792+
AliasWithNoPredicate = Idx;
28082793
continue;
28092794
}
28102795
if (R->getValueAsString("ToMnemonic") == AliasEntry.first)
@@ -2819,7 +2804,7 @@ emitMnemonicAliasVariant(raw_ostream &OS, const AsmMatcherInfo &Info,
28192804
}
28202805

28212806
if (AliasWithNoPredicate != -1) {
2822-
Record *R = ToVec[AliasWithNoPredicate];
2807+
const Record *R = ToVec[AliasWithNoPredicate];
28232808
if (!MatchCode.empty())
28242809
MatchCode += "else\n ";
28252810
MatchCode += "Mnemonic = \"";
@@ -2955,8 +2940,8 @@ emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
29552940
if (II.RequiredFeatures.empty())
29562941
OS << "_None";
29572942
else
2958-
for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i)
2959-
OS << '_' << II.RequiredFeatures[i]->TheDef->getName();
2943+
for (const auto &F : II.RequiredFeatures)
2944+
OS << '_' << F->TheDef->getName();
29602945

29612946
OS << " },\n";
29622947
}
@@ -3467,24 +3452,20 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
34673452
if (MI->RequiredFeatures.empty())
34683453
continue;
34693454
FeatureBitsets.emplace_back();
3470-
for (unsigned I = 0, E = MI->RequiredFeatures.size(); I != E; ++I)
3471-
FeatureBitsets.back().push_back(MI->RequiredFeatures[I]->TheDef);
3455+
for (const auto *F : MI->RequiredFeatures)
3456+
FeatureBitsets.back().push_back(F->TheDef);
34723457
}
34733458

3474-
llvm::sort(FeatureBitsets, [&](const std::vector<const Record *> &A,
3475-
const std::vector<const Record *> &B) {
3476-
if (A.size() < B.size())
3477-
return true;
3478-
if (A.size() > B.size())
3479-
return false;
3480-
for (auto Pair : zip(A, B)) {
3481-
if (std::get<0>(Pair)->getName() < std::get<1>(Pair)->getName())
3482-
return true;
3483-
if (std::get<0>(Pair)->getName() > std::get<1>(Pair)->getName())
3484-
return false;
3485-
}
3486-
return false;
3487-
});
3459+
llvm::sort(FeatureBitsets,
3460+
[&](ArrayRef<const Record *> A, ArrayRef<const Record *> B) {
3461+
if (A.size() != B.size())
3462+
return A.size() < B.size();
3463+
for (const auto [ARec, BRec] : zip_equal(A, B)) {
3464+
if (ARec->getName() != BRec->getName())
3465+
return ARec->getName() < BRec->getName();
3466+
}
3467+
return false;
3468+
});
34883469
FeatureBitsets.erase(llvm::unique(FeatureBitsets), FeatureBitsets.end());
34893470
OS << "// Feature bitsets.\n"
34903471
<< "enum : " << getMinimalTypeForRange(FeatureBitsets.size()) << " {\n"
@@ -3577,8 +3558,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
35773558
if (MI->RequiredFeatures.empty())
35783559
OS << "_None";
35793560
else
3580-
for (unsigned i = 0, e = MI->RequiredFeatures.size(); i != e; ++i)
3581-
OS << '_' << MI->RequiredFeatures[i]->TheDef->getName();
3561+
for (const auto &F : MI->RequiredFeatures)
3562+
OS << '_' << F->TheDef->getName();
35823563

35833564
OS << ", { ";
35843565
ListSeparator LS;

0 commit comments

Comments
 (0)