Skip to content

Commit 6854f6f

Browse files
[TableGen] Add PreferSmallerInstructions for Targets. (#83587)
This option means that in assembly matching instructions with smaller encodings will be preferred. This will be used for the ARM instruction set where this is the correct behavior after some other refactoring.
1 parent 3128c20 commit 6854f6f

File tree

2 files changed

+48
-11
lines changed

2 files changed

+48
-11
lines changed

llvm/include/llvm/Target/Target.td

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,6 +1564,20 @@ class AsmParser {
15641564
// method shall be called for all operands as opposed to only those
15651565
// that have their own specified custom parsers.
15661566
bit CallCustomParserForAllOperands = false;
1567+
1568+
// PreferSmallerInstructions - Should the assembly matcher prefer the smaller
1569+
// instructions.
1570+
//
1571+
// This is useful for the ARM instructions set where smaller encodings must
1572+
// be preferentially selected.
1573+
//
1574+
// The preference order is:
1575+
// Instrution size (if this option is enabled, smallest first)
1576+
// Number of Operands (least first),
1577+
// Operand Classes (lexicographically by operand),
1578+
// (Optional) Instruction id (see AsmMatcherEmitter.cpp for details),
1579+
// Number of required features (least first)
1580+
bit PreferSmallerInstructions = false;
15671581
}
15681582
def DefaultAsmParser : AsmParser;
15691583

llvm/utils/TableGen/AsmMatcherEmitter.cpp

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,10 @@ class AsmVariantInfo {
375375
int AsmVariantNo;
376376
};
377377

378+
bool getPreferSmallerInstructions(CodeGenTarget const &Target) {
379+
return Target.getAsmParser()->getValueAsBit("PreferSmallerInstructions");
380+
}
381+
378382
/// MatchableInfo - Helper class for storing the necessary information for an
379383
/// instruction or alias which is capable of being matched.
380384
struct MatchableInfo {
@@ -502,6 +506,9 @@ struct MatchableInfo {
502506
/// matchable came from.
503507
Record *const TheDef;
504508

509+
// ResInstSize - The size of the resulting instruction for this matchable.
510+
unsigned ResInstSize;
511+
505512
/// DefRec - This is the definition that it came from.
506513
PointerUnion<const CodeGenInstruction *, const CodeGenInstAlias *> DefRec;
507514

@@ -543,10 +550,12 @@ struct MatchableInfo {
543550

544551
MatchableInfo(const CodeGenInstruction &CGI)
545552
: AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef),
546-
DefRec(&CGI), UseInstAsmMatchConverter(true) {}
553+
ResInstSize(TheDef->getValueAsInt("Size")), DefRec(&CGI),
554+
UseInstAsmMatchConverter(true) {}
547555

548556
MatchableInfo(std::unique_ptr<const CodeGenInstAlias> Alias)
549557
: AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef),
558+
ResInstSize(Alias->ResultInst->TheDef->getValueAsInt("Size")),
550559
DefRec(Alias.release()), UseInstAsmMatchConverter(TheDef->getValueAsBit(
551560
"UseInstAsmMatchConverter")) {}
552561

@@ -555,9 +564,9 @@ struct MatchableInfo {
555564
// where it was copied while being in an owning state.
556565
MatchableInfo(const MatchableInfo &RHS)
557566
: AsmVariantID(RHS.AsmVariantID), AsmString(RHS.AsmString),
558-
TheDef(RHS.TheDef), DefRec(RHS.DefRec), ResOperands(RHS.ResOperands),
559-
Mnemonic(RHS.Mnemonic), AsmOperands(RHS.AsmOperands),
560-
RequiredFeatures(RHS.RequiredFeatures),
567+
TheDef(RHS.TheDef), ResInstSize(RHS.ResInstSize), DefRec(RHS.DefRec),
568+
ResOperands(RHS.ResOperands), Mnemonic(RHS.Mnemonic),
569+
AsmOperands(RHS.AsmOperands), RequiredFeatures(RHS.RequiredFeatures),
561570
ConversionFnKind(RHS.ConversionFnKind),
562571
HasDeprecation(RHS.HasDeprecation),
563572
UseInstAsmMatchConverter(RHS.UseInstAsmMatchConverter) {
@@ -608,12 +617,18 @@ struct MatchableInfo {
608617
void buildInstructionResultOperands();
609618
void buildAliasResultOperands(bool AliasConstraintsAreChecked);
610619

611-
/// operator< - Compare two matchables.
612-
bool operator<(const MatchableInfo &RHS) const {
620+
/// shouldBeMatchedBefore - Compare two matchables for ordering.
621+
bool shouldBeMatchedBefore(const MatchableInfo &RHS,
622+
bool PreferSmallerInstructions) const {
613623
// The primary comparator is the instruction mnemonic.
614624
if (int Cmp = Mnemonic.compare_insensitive(RHS.Mnemonic))
615625
return Cmp == -1;
616626

627+
// (Optionally) Order by the resultant instuctions size.
628+
// eg. for ARM thumb instructions smaller encodings should be preferred.
629+
if (PreferSmallerInstructions && ResInstSize != RHS.ResInstSize)
630+
return ResInstSize < RHS.ResInstSize;
631+
617632
if (AsmOperands.size() != RHS.AsmOperands.size())
618633
return AsmOperands.size() < RHS.AsmOperands.size();
619634

@@ -652,7 +667,8 @@ struct MatchableInfo {
652667
/// couldMatchAmbiguouslyWith - Check whether this matchable could
653668
/// ambiguously match the same set of operands as \p RHS (without being a
654669
/// strictly superior match).
655-
bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS) const {
670+
bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS,
671+
bool PreferSmallerInstructions) const {
656672
// The primary comparator is the instruction mnemonic.
657673
if (Mnemonic != RHS.Mnemonic)
658674
return false;
@@ -661,6 +677,10 @@ struct MatchableInfo {
661677
if (AsmVariantID != RHS.AsmVariantID)
662678
return false;
663679

680+
// The size of instruction is unambiguous.
681+
if (PreferSmallerInstructions && ResInstSize != RHS.ResInstSize)
682+
return false;
683+
664684
// The number of operands is unambiguous.
665685
if (AsmOperands.size() != RHS.AsmOperands.size())
666686
return false;
@@ -3221,20 +3241,23 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
32213241
AsmMatcherInfo Info(AsmParser, Target, Records);
32223242
Info.buildInfo();
32233243

3244+
bool PreferSmallerInstructions = getPreferSmallerInstructions(Target);
32243245
// Sort the instruction table using the partial order on classes. We use
32253246
// stable_sort to ensure that ambiguous instructions are still
32263247
// deterministically ordered.
32273248
llvm::stable_sort(
32283249
Info.Matchables,
3229-
[](const std::unique_ptr<MatchableInfo> &a,
3230-
const std::unique_ptr<MatchableInfo> &b) { return *a < *b; });
3250+
[PreferSmallerInstructions](const std::unique_ptr<MatchableInfo> &A,
3251+
const std::unique_ptr<MatchableInfo> &B) {
3252+
return A->shouldBeMatchedBefore(*B, PreferSmallerInstructions);
3253+
});
32313254

32323255
#ifdef EXPENSIVE_CHECKS
32333256
// Verify that the table is sorted and operator < works transitively.
32343257
for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E;
32353258
++I) {
32363259
for (auto J = I; J != E; ++J) {
3237-
assert(!(**J < **I));
3260+
assert(!(*J)->shouldBeMatchedBefore(**I, PreferSmallerInstructions));
32383261
}
32393262
}
32403263
#endif
@@ -3253,7 +3276,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
32533276
const MatchableInfo &A = **I;
32543277
const MatchableInfo &B = **J;
32553278

3256-
if (A.couldMatchAmbiguouslyWith(B)) {
3279+
if (A.couldMatchAmbiguouslyWith(B, PreferSmallerInstructions)) {
32573280
errs() << "warning: ambiguous matchables:\n";
32583281
A.dump();
32593282
errs() << "\nis incomparable with:\n";

0 commit comments

Comments
 (0)