Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 51 additions & 57 deletions llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -455,15 +455,9 @@ struct FnAttributeComparator {

struct AttributeComparator {
bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const {
// Order all intrinsics with no functiona attributes before all intrinsics
// with function attributes.
bool HasFnAttrLHS = hasFnAttributes(*L);
bool HasFnAttrRHS = hasFnAttributes(*R);

// Order by argument attributes if function `hasFnAttributes` is equal.
// This is reliable because each side is already sorted internally.
return std::tie(HasFnAttrLHS, L->ArgumentAttributes) <
std::tie(HasFnAttrRHS, R->ArgumentAttributes);
// This comparator is used to unique just the argument attributes of an
// intrinsic without considering any function attributes.
return L->ArgumentAttributes < R->ArgumentAttributes;
}
};
} // End anonymous namespace
Expand Down Expand Up @@ -659,87 +653,85 @@ static constexpr uint16_t IntrinsicsToAttributesMap[] = {)";
//
// getIntrinsicArgAttributeSet(C, ArgAttrID, FT->getContainedType(ArgNo));
//
// Create a table that records, for each argument attributes, the set of
// Create a table that records, for each argument attributes, the list of
// <ArgNo, ArgAttrID> pairs that are needed to construct its argument
// attributes. These tables for all intrinsics will be concatenated into one
// large table and then for each intrinsic, we remember the Staring index and
// number of size of its slice of entries (i.e., number of arguments with
// non-empty attributes), so that we can build the attribute list for an
// intrinsic without using a switch-case.

// Find the max number of attributes to create the local array and create
// a concatenated list of <ArgNo, AttrID> pairs.
struct ArgNoAttrIDPair {
uint16_t ArgNo, ArgAttrID;
ArgNoAttrIDPair(uint16_t ArgNo, uint16_t ArgAttrID)
: ArgNo(ArgNo), ArgAttrID(ArgAttrID) {}
};
using ArgNoAttrIDPair = std::pair<uint16_t, uint16_t>;

// For each unique ID in UniqAttributes, reacord the starting index in the
// flattened ArgNoAttrIDPair table, and the number of non-empty arg
// attributes.
struct ArgAttributesInfo {
uint16_t StartIndex;
uint16_t NumAttrs;
ArgAttributesInfo(uint16_t StartIndex, uint16_t NumAttrs)
: StartIndex(StartIndex), NumAttrs(NumAttrs) {}
};
SmallVector<ArgNoAttrIDPair> ArgAttrIdTable;
SmallVector<ArgAttributesInfo> ArgAttributesInfoTable(UniqAttributes.size(),
{0, 0});
// Emit the table of concatenated <ArgNo, AttrId> using SequenceToOffsetTable
// so that entries can be reused if possible. Individual sequences in this
// table do not have any terminator.
using ArgAttrIDSubTable = SmallVector<ArgNoAttrIDPair>;
SequenceToOffsetTable<ArgAttrIDSubTable> ArgAttrIdSequenceTable(std::nullopt);
SmallVector<ArgAttrIDSubTable> ArgAttrIdSubTables(
UniqAttributes.size()); // Indexed by UniqueID.

// Find the max number of attributes to create the local array.
unsigned MaxNumAttrs = 0;
for (const auto [IntPtr, UniqueID] : UniqAttributes) {
const CodeGenIntrinsic &Int = *IntPtr;
unsigned NumAttrs = 0;
unsigned StartIndex = ArgAttrIdTable.size();
ArgAttrIDSubTable SubTable;

for (const auto &[ArgNo, Attrs] : enumerate(Int.ArgumentAttributes)) {
if (Attrs.empty())
continue;

uint16_t ArgAttrID = UniqArgAttributes.find(Attrs)->second;
ArgAttrIdTable.emplace_back((uint16_t)ArgNo, ArgAttrID);
++NumAttrs;
SubTable.emplace_back((uint16_t)ArgNo, ArgAttrID);
}

// Record the start index and size of the list for this unique ID.
if (NumAttrs)
ArgAttributesInfoTable[UniqueID] =
ArgAttributesInfo(StartIndex, NumAttrs);

NumAttrs += hasFnAttributes(Int);
ArgAttrIdSubTables[UniqueID] = SubTable;
if (!SubTable.empty())
ArgAttrIdSequenceTable.add(SubTable);
unsigned NumAttrs = SubTable.size() + hasFnAttributes(Int);
MaxNumAttrs = std::max(MaxNumAttrs, NumAttrs);
}

if (ArgAttrIdTable.size() >= std::numeric_limits<uint16_t>::max())
ArgAttrIdSequenceTable.layout();

if (ArgAttrIdSequenceTable.size() >= std::numeric_limits<uint16_t>::max())
PrintFatalError("Size of ArgAttrIdTable exceeds supported limit");

// Emit the 2 tables (flattened ArgNo, ArgAttrID) and ArgAttrIdTableIndex
OS << R"(
namespace {
struct ArgNoAttrIDPair {
// Emit the 2 tables (flattened ArgNo, ArgAttrID) and ArgAttributesInfoTable.
OS << formatv(R"(
namespace {{
struct ArgNoAttrIDPair {{
uint16_t ArgNo, ArgAttrID;
};
} // namespace

static constexpr ArgNoAttrIDPair ArgAttrIdTable[] = {
)";
for (const auto &[ArgNo, ArgAttrID] : ArgAttrIdTable)
OS << formatv(" {{{}, {}},\n", ArgNo, ArgAttrID);
OS << R"(}; // ArgAttrIdTable
// Number of entries: {}
static constexpr ArgNoAttrIDPair ArgAttrIdTable[] = {{
)",
ArgAttrIdSequenceTable.size());

namespace {
struct ArgAttributesInfo {
ArgAttrIdSequenceTable.emit(OS, [](raw_ostream &OS, ArgNoAttrIDPair Elem) {
OS << formatv("{{{}, {}}", Elem.first, Elem.second);
});

OS << formatv(R"(}; // ArgAttrIdTable

namespace {{
struct ArgAttributesInfo {{
uint16_t StartIndex;
uint16_t NumAttrs;
};
} // namespace

static constexpr ArgAttributesInfo ArgAttributesInfoTable[] = {
)";
for (const auto &[StartIndex, NumAttrs] : ArgAttributesInfoTable)

// Number of entries: {}
static constexpr ArgAttributesInfo ArgAttributesInfoTable[] = {{
)",
ArgAttrIdSubTables.size());

for (const auto &SubTable : ArgAttrIdSubTables) {
unsigned NumAttrs = SubTable.size();
unsigned StartIndex = NumAttrs ? ArgAttrIdSequenceTable.get(SubTable) : 0;
OS << formatv(" {{{}, {}},\n", StartIndex, NumAttrs);
}
OS << "}; // ArgAttributesInfoTable\n";

// Now emit the Intrinsic::getAttributes function. This will first map
Expand All @@ -756,7 +748,9 @@ AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id,
uint16_t PackedID = IntrinsicsToAttributesMap[id - 1];
uint8_t FnAttrID = PackedID >> 8;
uint8_t ArgAttrID = PackedID & 0xFF;
std::pair<unsigned, AttributeSet> AS[{}];
using PairTy = std::pair<unsigned, AttributeSet>;
alignas(PairTy) char ASStorage[sizeof(PairTy) * {}];
PairTy *AS = reinterpret_cast<PairTy *>(ASStorage);

// Construct an ArrayRef for easier range checking.
ArrayRef<ArgAttributesInfo> ArgAttributesInfoTableAR(ArgAttributesInfoTable);
Expand Down