Skip to content

[NFC][TableGen] Refactor getIntrinsicFnAttributeSet #106587

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 2, 2024
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
136 changes: 77 additions & 59 deletions llvm/utils/TableGen/IntrinsicEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,10 +379,10 @@ static bool compareFnAttributes(const CodeGenIntrinsic *L,
return TieL < TieR;

// Try to order by readonly/readnone attribute.
uint32_t LK = L->ME.toIntValue();
uint32_t RK = R->ME.toIntValue();
if (LK != RK)
return LK > RK;
uint32_t LME = L->ME.toIntValue();
uint32_t RME = R->ME.toIntValue();
if (LME != RME)
return LME > RME;

return Default;
}
Expand All @@ -404,6 +404,54 @@ struct AttributeComparator {
};
} // End anonymous namespace

/// Returns the effective MemoryEffects for intrinsic \p Int.
static MemoryEffects getEffectiveME(const CodeGenIntrinsic &Int) {
MemoryEffects ME = Int.ME;
// TODO: IntrHasSideEffects should affect not only readnone intrinsics.
if (ME.doesNotAccessMemory() && Int.hasSideEffects)
ME = MemoryEffects::unknown();
return ME;
}

/// Returns true if \p Int has a non-empty set of function attributes. Note that
/// NoUnwind = !canThrow, so we need to negate it's sense to test if the
// intrinsic has NoUnwind attribute.
static bool hasFnAttributes(const CodeGenIntrinsic &Int) {
return !Int.canThrow || Int.isNoReturn || Int.isNoCallback || Int.isNoSync ||
Int.isNoFree || Int.isWillReturn || Int.isCold || Int.isNoDuplicate ||
Int.isNoMerge || Int.isConvergent || Int.isSpeculatable ||
Int.isStrictFP || getEffectiveME(Int) != MemoryEffects::unknown();
}

/// Returns the name of the IR enum for argument attribute kind \p Kind.
static StringRef getArgAttrEnumName(CodeGenIntrinsic::ArgAttrKind Kind) {
switch (Kind) {
case CodeGenIntrinsic::NoCapture:
return "NoCapture";
case CodeGenIntrinsic::NoAlias:
return "NoAlias";
case CodeGenIntrinsic::NoUndef:
return "NoUndef";
case CodeGenIntrinsic::NonNull:
return "NonNull";
case CodeGenIntrinsic::Returned:
return "Returned";
case CodeGenIntrinsic::ReadOnly:
return "ReadOnly";
case CodeGenIntrinsic::WriteOnly:
return "WriteOnly";
case CodeGenIntrinsic::ReadNone:
return "ReadNone";
case CodeGenIntrinsic::ImmArg:
return "ImmArg";
case CodeGenIntrinsic::Alignment:
return "Alignment";
case CodeGenIntrinsic::Dereferenceable:
return "Dereferenceable";
}
llvm_unreachable("Unknown CodeGenIntrinsic::ArgAttrKind enum");
}

/// EmitAttributes - This emits the Intrinsic::getAttributes method.
void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
raw_ostream &OS) {
Expand All @@ -425,42 +473,14 @@ static AttributeSet getIntrinsicArgAttributeSet(LLVMContext &C, unsigned ID) {
continue;

assert(is_sorted(Attrs) && "Argument attributes are not sorted");
auto getAttrEnumName =
[](CodeGenIntrinsic::ArgAttrKind Kind) -> StringRef {
switch (Kind) {
case CodeGenIntrinsic::NoCapture:
return "NoCapture";
case CodeGenIntrinsic::NoAlias:
return "NoAlias";
case CodeGenIntrinsic::NoUndef:
return "NoUndef";
case CodeGenIntrinsic::NonNull:
return "NonNull";
case CodeGenIntrinsic::Returned:
return "Returned";
case CodeGenIntrinsic::ReadOnly:
return "ReadOnly";
case CodeGenIntrinsic::WriteOnly:
return "WriteOnly";
case CodeGenIntrinsic::ReadNone:
return "ReadNone";
case CodeGenIntrinsic::ImmArg:
return "ImmArg";
case CodeGenIntrinsic::Alignment:
return "Alignment";
case CodeGenIntrinsic::Dereferenceable:
return "Dereferenceable";
}
llvm_unreachable("Unknown CodeGenIntrinsic::ArgAttrKind enum");
};

OS << formatv(R"(
case {0}:
return AttributeSet::get(C, {{
)",
ID);
for (const CodeGenIntrinsic::ArgAttribute &Attr : Attrs) {
StringRef AttrName = getAttrEnumName(Attr.Kind);
StringRef AttrName = getArgAttrEnumName(Attr.Kind);
if (Attr.Kind == CodeGenIntrinsic::Alignment ||
Attr.Kind == CodeGenIntrinsic::Dereferenceable)
OS << formatv(" Attribute::get(C, Attribute::{0}, {1}),\n",
Expand All @@ -473,7 +493,8 @@ static AttributeSet getIntrinsicArgAttributeSet(LLVMContext &C, unsigned ID) {
}
OS << R"(
}
} // getIntrinsicArgAttributeSet)";
} // getIntrinsicArgAttributeSet
)";

// Compute unique function attribute sets.
std::map<const CodeGenIntrinsic *, unsigned, FnAttributeComparator>
Expand All @@ -482,9 +503,12 @@ static AttributeSet getIntrinsicArgAttributeSet(LLVMContext &C, unsigned ID) {
static AttributeSet getIntrinsicFnAttributeSet(LLVMContext &C, unsigned ID) {
switch (ID) {
default: llvm_unreachable("Invalid attribute set number");)";
for (const CodeGenIntrinsic &Intrinsic : Ints) {

for (const CodeGenIntrinsic &Int : Ints) {
if (!hasFnAttributes(Int))
continue;
unsigned ID = UniqFnAttributes.size();
if (!UniqFnAttributes.try_emplace(&Intrinsic, ID).second)
if (!UniqFnAttributes.try_emplace(&Int, ID).second)
continue;
OS << formatv(R"(
case {0}:
Expand All @@ -494,44 +518,42 @@ static AttributeSet getIntrinsicFnAttributeSet(LLVMContext &C, unsigned ID) {
auto addAttribute = [&OS](StringRef Attr) {
OS << formatv(" Attribute::get(C, Attribute::{0}),\n", Attr);
};
if (!Intrinsic.canThrow)
if (!Int.canThrow)
addAttribute("NoUnwind");
if (Intrinsic.isNoReturn)
if (Int.isNoReturn)
addAttribute("NoReturn");
if (Intrinsic.isNoCallback)
if (Int.isNoCallback)
addAttribute("NoCallback");
if (Intrinsic.isNoSync)
if (Int.isNoSync)
addAttribute("NoSync");
if (Intrinsic.isNoFree)
if (Int.isNoFree)
addAttribute("NoFree");
if (Intrinsic.isWillReturn)
if (Int.isWillReturn)
addAttribute("WillReturn");
if (Intrinsic.isCold)
if (Int.isCold)
addAttribute("Cold");
if (Intrinsic.isNoDuplicate)
if (Int.isNoDuplicate)
addAttribute("NoDuplicate");
if (Intrinsic.isNoMerge)
if (Int.isNoMerge)
addAttribute("NoMerge");
if (Intrinsic.isConvergent)
if (Int.isConvergent)
addAttribute("Convergent");
if (Intrinsic.isSpeculatable)
if (Int.isSpeculatable)
addAttribute("Speculatable");
if (Intrinsic.isStrictFP)
if (Int.isStrictFP)
addAttribute("StrictFP");

MemoryEffects ME = Intrinsic.ME;
// TODO: IntrHasSideEffects should affect not only readnone intrinsics.
if (ME.doesNotAccessMemory() && Intrinsic.hasSideEffects)
ME = MemoryEffects::unknown();
const MemoryEffects ME = getEffectiveME(Int);
if (ME != MemoryEffects::unknown()) {
OS << formatv(" // {0}\n", ME);
OS << formatv(" Attribute::getWithMemoryEffects(C, "
"MemoryEffects::createFromIntValue({0})),\n",
ME.toIntValue());
}
OS << " });\n";
OS << " });";
}
OS << R"(
}
OS << R"( }
} // getIntrinsicFnAttributeSet

AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id) {
Expand Down Expand Up @@ -586,11 +608,7 @@ AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id) {
NumAttrs++, AttrIdx, ArgAttrID);
}

if (!Int.canThrow ||
(Int.ME != MemoryEffects::unknown() && !Int.hasSideEffects) ||
Int.isNoReturn || Int.isNoCallback || Int.isNoSync || Int.isNoFree ||
Int.isWillReturn || Int.isCold || Int.isNoDuplicate || Int.isNoMerge ||
Int.isConvergent || Int.isSpeculatable || Int.isStrictFP) {
if (hasFnAttributes(Int)) {
unsigned FnAttrID = UniqFnAttributes.find(&Int)->second;
OS << formatv(" AS[{0}] = {{AttributeList::FunctionIndex, "
"getIntrinsicFnAttributeSet(C, {1})};\n",
Expand Down
Loading