@@ -455,15 +455,9 @@ struct FnAttributeComparator {
455455
456456struct AttributeComparator {
457457 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 ;
467461 }
468462};
469463} // End anonymous namespace
@@ -659,87 +653,85 @@ static constexpr uint16_t IntrinsicsToAttributesMap[] = {)";
659653 //
660654 // getIntrinsicArgAttributeSet(C, ArgAttrID, FT->getContainedType(ArgNo));
661655 //
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
663657 // <ArgNo, ArgAttrID> pairs that are needed to construct its argument
664658 // attributes. These tables for all intrinsics will be concatenated into one
665659 // large table and then for each intrinsic, we remember the Staring index and
666660 // number of size of its slice of entries (i.e., number of arguments with
667661 // non-empty attributes), so that we can build the attribute list for an
668662 // intrinsic without using a switch-case.
669663
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 >;
677665
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.
690673
674+ // Find the max number of attributes to create the local array.
691675 unsigned MaxNumAttrs = 0 ;
692676 for (const auto [IntPtr, UniqueID] : UniqAttributes) {
693677 const CodeGenIntrinsic &Int = *IntPtr;
694- unsigned NumAttrs = 0 ;
695- unsigned StartIndex = ArgAttrIdTable.size ();
678+ ArgAttrIDSubTable SubTable;
696679
697680 for (const auto &[ArgNo, Attrs] : enumerate(Int.ArgumentAttributes )) {
698681 if (Attrs.empty ())
699682 continue ;
700683
701684 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);
704686 }
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);
712691 MaxNumAttrs = std::max (MaxNumAttrs, NumAttrs);
713692 }
714693
715- if (ArgAttrIdTable.size () >= std::numeric_limits<uint16_t >::max ())
694+ ArgAttrIdSequenceTable.layout ();
695+
696+ if (ArgAttrIdSequenceTable.size () >= std::numeric_limits<uint16_t >::max ())
716697 PrintFatalError (" Size of ArgAttrIdTable exceeds supported limit" );
717698
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 {{
722703 uint16_t ArgNo, ArgAttrID;
723704};
724705} // namespace
725706
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 ());
731711
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 {{
734720 uint16_t StartIndex;
735721 uint16_t NumAttrs;
736722};
737723} // 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 ;
742733 OS << formatv (" {{{}, {}},\n " , StartIndex, NumAttrs);
734+ }
743735 OS << " }; // ArgAttributesInfoTable\n " ;
744736
745737 // Now emit the Intrinsic::getAttributes function. This will first map
@@ -756,7 +748,9 @@ AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id,
756748 uint16_t PackedID = IntrinsicsToAttributesMap[id - 1];
757749 uint8_t FnAttrID = PackedID >> 8;
758750 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);
760754
761755 // Construct an ArrayRef for easier range checking.
762756 ArrayRef<ArgAttributesInfo> ArgAttributesInfoTableAR(ArgAttributesInfoTable);
0 commit comments