@@ -455,15 +455,9 @@ struct FnAttributeComparator {
455
455
456
456
struct AttributeComparator {
457
457
bool operator ()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const {
458
- // Order all intrinsics with no functiona attributes before all intrinsics
459
- // with function attributes.
460
- bool HasFnAttrLHS = hasFnAttributes (*L);
461
- bool HasFnAttrRHS = hasFnAttributes (*R);
462
-
463
- // Order by argument attributes if function `hasFnAttributes` is equal.
464
- // This is reliable because each side is already sorted internally.
465
- return std::tie (HasFnAttrLHS, L->ArgumentAttributes ) <
466
- std::tie (HasFnAttrRHS, R->ArgumentAttributes );
458
+ // This comparator is used to unique just the argument attributes of an
459
+ // intrinsic without considering any function attributes.
460
+ return L->ArgumentAttributes < R->ArgumentAttributes ;
467
461
}
468
462
};
469
463
} // End anonymous namespace
@@ -659,87 +653,85 @@ static constexpr uint16_t IntrinsicsToAttributesMap[] = {)";
659
653
//
660
654
// getIntrinsicArgAttributeSet(C, ArgAttrID, FT->getContainedType(ArgNo));
661
655
//
662
- // Create a table that records, for each argument attributes, the set of
656
+ // Create a table that records, for each argument attributes, the list of
663
657
// <ArgNo, ArgAttrID> pairs that are needed to construct its argument
664
658
// attributes. These tables for all intrinsics will be concatenated into one
665
659
// large table and then for each intrinsic, we remember the Staring index and
666
660
// number of size of its slice of entries (i.e., number of arguments with
667
661
// non-empty attributes), so that we can build the attribute list for an
668
662
// intrinsic without using a switch-case.
669
663
670
- // Find the max number of attributes to create the local array and create
671
- // a concatenated list of <ArgNo, AttrID> pairs.
672
- struct ArgNoAttrIDPair {
673
- uint16_t ArgNo, ArgAttrID;
674
- ArgNoAttrIDPair (uint16_t ArgNo, uint16_t ArgAttrID)
675
- : ArgNo(ArgNo), ArgAttrID(ArgAttrID) {}
676
- };
664
+ using ArgNoAttrIDPair = std::pair<uint16_t , uint16_t >;
677
665
678
- // For each unique ID in UniqAttributes, reacord the starting index in the
679
- // flattened ArgNoAttrIDPair table, and the number of non-empty arg
680
- // attributes.
681
- struct ArgAttributesInfo {
682
- uint16_t StartIndex;
683
- uint16_t NumAttrs;
684
- ArgAttributesInfo (uint16_t StartIndex, uint16_t NumAttrs)
685
- : StartIndex(StartIndex), NumAttrs(NumAttrs) {}
686
- };
687
- SmallVector<ArgNoAttrIDPair> ArgAttrIdTable;
688
- SmallVector<ArgAttributesInfo> ArgAttributesInfoTable (UniqAttributes.size (),
689
- {0 , 0 });
666
+ // Emit the table of concatenated <ArgNo, AttrId> using SequenceToOffsetTable
667
+ // so that entries can be reused if possible. Individual sequences in this
668
+ // table do not have any terminator.
669
+ using ArgAttrIDSubTable = SmallVector<ArgNoAttrIDPair>;
670
+ SequenceToOffsetTable<ArgAttrIDSubTable> ArgAttrIdSequenceTable (std::nullopt);
671
+ SmallVector<ArgAttrIDSubTable> ArgAttrIdSubTables (
672
+ UniqAttributes.size ()); // Indexed by UniqueID.
690
673
674
+ // Find the max number of attributes to create the local array.
691
675
unsigned MaxNumAttrs = 0 ;
692
676
for (const auto [IntPtr, UniqueID] : UniqAttributes) {
693
677
const CodeGenIntrinsic &Int = *IntPtr;
694
- unsigned NumAttrs = 0 ;
695
- unsigned StartIndex = ArgAttrIdTable.size ();
678
+ ArgAttrIDSubTable SubTable;
696
679
697
680
for (const auto &[ArgNo, Attrs] : enumerate(Int.ArgumentAttributes )) {
698
681
if (Attrs.empty ())
699
682
continue ;
700
683
701
684
uint16_t ArgAttrID = UniqArgAttributes.find (Attrs)->second ;
702
- ArgAttrIdTable.emplace_back ((uint16_t )ArgNo, ArgAttrID);
703
- ++NumAttrs;
685
+ SubTable.emplace_back ((uint16_t )ArgNo, ArgAttrID);
704
686
}
705
-
706
- // Record the start index and size of the list for this unique ID.
707
- if (NumAttrs)
708
- ArgAttributesInfoTable[UniqueID] =
709
- ArgAttributesInfo (StartIndex, NumAttrs);
710
-
711
- NumAttrs += hasFnAttributes (Int);
687
+ ArgAttrIdSubTables[UniqueID] = SubTable;
688
+ if (!SubTable.empty ())
689
+ ArgAttrIdSequenceTable.add (SubTable);
690
+ unsigned NumAttrs = SubTable.size () + hasFnAttributes (Int);
712
691
MaxNumAttrs = std::max (MaxNumAttrs, NumAttrs);
713
692
}
714
693
715
- if (ArgAttrIdTable.size () >= std::numeric_limits<uint16_t >::max ())
694
+ ArgAttrIdSequenceTable.layout ();
695
+
696
+ if (ArgAttrIdSequenceTable.size () >= std::numeric_limits<uint16_t >::max ())
716
697
PrintFatalError (" Size of ArgAttrIdTable exceeds supported limit" );
717
698
718
- // Emit the 2 tables (flattened ArgNo, ArgAttrID) and ArgAttrIdTableIndex
719
- OS << R"(
720
- namespace {
721
- struct ArgNoAttrIDPair {
699
+ // Emit the 2 tables (flattened ArgNo, ArgAttrID) and ArgAttributesInfoTable.
700
+ OS << formatv ( R"(
701
+ namespace {{
702
+ struct ArgNoAttrIDPair {{
722
703
uint16_t ArgNo, ArgAttrID;
723
704
};
724
705
} // namespace
725
706
726
- static constexpr ArgNoAttrIDPair ArgAttrIdTable[] = {
727
- )" ;
728
- for (const auto &[ArgNo, ArgAttrID] : ArgAttrIdTable)
729
- OS << formatv (" {{{}, {}},\n " , ArgNo, ArgAttrID);
730
- OS << R"( }; // ArgAttrIdTable
707
+ // Number of entries: {}
708
+ static constexpr ArgNoAttrIDPair ArgAttrIdTable[] = {{
709
+ )" ,
710
+ ArgAttrIdSequenceTable.size ());
731
711
732
- namespace {
733
- struct ArgAttributesInfo {
712
+ ArgAttrIdSequenceTable.emit (OS, [](raw_ostream &OS, ArgNoAttrIDPair Elem) {
713
+ OS << formatv (" {{{}, {}}" , Elem.first , Elem.second );
714
+ });
715
+
716
+ OS << formatv (R"( }; // ArgAttrIdTable
717
+
718
+ namespace {{
719
+ struct ArgAttributesInfo {{
734
720
uint16_t StartIndex;
735
721
uint16_t NumAttrs;
736
722
};
737
723
} // namespace
738
-
739
- static constexpr ArgAttributesInfo ArgAttributesInfoTable[] = {
740
- )" ;
741
- for (const auto &[StartIndex, NumAttrs] : ArgAttributesInfoTable)
724
+
725
+ // Number of entries: {}
726
+ static constexpr ArgAttributesInfo ArgAttributesInfoTable[] = {{
727
+ )" ,
728
+ ArgAttrIdSubTables.size ());
729
+
730
+ for (const auto &SubTable : ArgAttrIdSubTables) {
731
+ unsigned NumAttrs = SubTable.size ();
732
+ unsigned StartIndex = NumAttrs ? ArgAttrIdSequenceTable.get (SubTable) : 0 ;
742
733
OS << formatv (" {{{}, {}},\n " , StartIndex, NumAttrs);
734
+ }
743
735
OS << " }; // ArgAttributesInfoTable\n " ;
744
736
745
737
// Now emit the Intrinsic::getAttributes function. This will first map
@@ -756,7 +748,9 @@ AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id,
756
748
uint16_t PackedID = IntrinsicsToAttributesMap[id - 1];
757
749
uint8_t FnAttrID = PackedID >> 8;
758
750
uint8_t ArgAttrID = PackedID & 0xFF;
759
- std::pair<unsigned, AttributeSet> AS[{}];
751
+ using PairTy = std::pair<unsigned, AttributeSet>;
752
+ alignas(PairTy) char ASStorage[sizeof(PairTy) * {}];
753
+ PairTy *AS = reinterpret_cast<PairTy *>(ASStorage);
760
754
761
755
// Construct an ArrayRef for easier range checking.
762
756
ArrayRef<ArgAttributesInfo> ArgAttributesInfoTableAR(ArgAttributesInfoTable);
0 commit comments