@@ -375,6 +375,10 @@ class AsmVariantInfo {
375
375
int AsmVariantNo;
376
376
};
377
377
378
+ bool getPreferSmallerInstructions (CodeGenTarget const &Target) {
379
+ return Target.getAsmParser ()->getValueAsBit (" PreferSmallerInstructions" );
380
+ }
381
+
378
382
// / MatchableInfo - Helper class for storing the necessary information for an
379
383
// / instruction or alias which is capable of being matched.
380
384
struct MatchableInfo {
@@ -502,6 +506,9 @@ struct MatchableInfo {
502
506
// / matchable came from.
503
507
Record *const TheDef;
504
508
509
+ // ResInstSize - The size of the resulting instruction for this matchable.
510
+ unsigned ResInstSize;
511
+
505
512
// / DefRec - This is the definition that it came from.
506
513
PointerUnion<const CodeGenInstruction *, const CodeGenInstAlias *> DefRec;
507
514
@@ -543,10 +550,12 @@ struct MatchableInfo {
543
550
544
551
MatchableInfo (const CodeGenInstruction &CGI)
545
552
: AsmVariantID(0 ), AsmString(CGI.AsmString), TheDef(CGI.TheDef),
546
- DefRec (&CGI), UseInstAsmMatchConverter(true ) {}
553
+ ResInstSize (TheDef->getValueAsInt (" Size" )), DefRec(&CGI),
554
+ UseInstAsmMatchConverter(true ) {}
547
555
548
556
MatchableInfo (std::unique_ptr<const CodeGenInstAlias> Alias)
549
557
: AsmVariantID(0 ), AsmString(Alias->AsmString), TheDef(Alias->TheDef),
558
+ ResInstSize(Alias->ResultInst->TheDef->getValueAsInt (" Size" )),
550
559
DefRec(Alias.release()), UseInstAsmMatchConverter(TheDef->getValueAsBit (
551
560
" UseInstAsmMatchConverter" )) {}
552
561
@@ -555,9 +564,9 @@ struct MatchableInfo {
555
564
// where it was copied while being in an owning state.
556
565
MatchableInfo (const MatchableInfo &RHS)
557
566
: 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),
561
570
ConversionFnKind(RHS.ConversionFnKind),
562
571
HasDeprecation(RHS.HasDeprecation),
563
572
UseInstAsmMatchConverter(RHS.UseInstAsmMatchConverter) {
@@ -608,12 +617,18 @@ struct MatchableInfo {
608
617
void buildInstructionResultOperands ();
609
618
void buildAliasResultOperands (bool AliasConstraintsAreChecked);
610
619
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 {
613
623
// The primary comparator is the instruction mnemonic.
614
624
if (int Cmp = Mnemonic.compare_insensitive (RHS.Mnemonic ))
615
625
return Cmp == -1 ;
616
626
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
+
617
632
if (AsmOperands.size () != RHS.AsmOperands .size ())
618
633
return AsmOperands.size () < RHS.AsmOperands .size ();
619
634
@@ -652,7 +667,8 @@ struct MatchableInfo {
652
667
// / couldMatchAmbiguouslyWith - Check whether this matchable could
653
668
// / ambiguously match the same set of operands as \p RHS (without being a
654
669
// / strictly superior match).
655
- bool couldMatchAmbiguouslyWith (const MatchableInfo &RHS) const {
670
+ bool couldMatchAmbiguouslyWith (const MatchableInfo &RHS,
671
+ bool PreferSmallerInstructions) const {
656
672
// The primary comparator is the instruction mnemonic.
657
673
if (Mnemonic != RHS.Mnemonic )
658
674
return false ;
@@ -661,6 +677,10 @@ struct MatchableInfo {
661
677
if (AsmVariantID != RHS.AsmVariantID )
662
678
return false ;
663
679
680
+ // The size of instruction is unambiguous.
681
+ if (PreferSmallerInstructions && ResInstSize != RHS.ResInstSize )
682
+ return false ;
683
+
664
684
// The number of operands is unambiguous.
665
685
if (AsmOperands.size () != RHS.AsmOperands .size ())
666
686
return false ;
@@ -3221,20 +3241,23 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
3221
3241
AsmMatcherInfo Info (AsmParser, Target, Records);
3222
3242
Info.buildInfo ();
3223
3243
3244
+ bool PreferSmallerInstructions = getPreferSmallerInstructions (Target);
3224
3245
// Sort the instruction table using the partial order on classes. We use
3225
3246
// stable_sort to ensure that ambiguous instructions are still
3226
3247
// deterministically ordered.
3227
3248
llvm::stable_sort (
3228
3249
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
+ });
3231
3254
3232
3255
#ifdef EXPENSIVE_CHECKS
3233
3256
// Verify that the table is sorted and operator < works transitively.
3234
3257
for (auto I = Info.Matchables .begin (), E = Info.Matchables .end (); I != E;
3235
3258
++I) {
3236
3259
for (auto J = I; J != E; ++J) {
3237
- assert (!(**J < **I));
3260
+ assert (!(*J)-> shouldBeMatchedBefore ( **I, PreferSmallerInstructions ));
3238
3261
}
3239
3262
}
3240
3263
#endif
@@ -3253,7 +3276,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
3253
3276
const MatchableInfo &A = **I;
3254
3277
const MatchableInfo &B = **J;
3255
3278
3256
- if (A.couldMatchAmbiguouslyWith (B)) {
3279
+ if (A.couldMatchAmbiguouslyWith (B, PreferSmallerInstructions )) {
3257
3280
errs () << " warning: ambiguous matchables:\n " ;
3258
3281
A.dump ();
3259
3282
errs () << " \n is incomparable with:\n " ;
0 commit comments