Skip to content

Commit

Permalink
[NFC][TableGen] Refactor getIntrinsicFnAttributeSet (llvm#106587)
Browse files Browse the repository at this point in the history
Fix intrinsic function attributes to not generate attribute sets that
are empty in `getIntrinsicFnAttributeSet`. Refactor the code to use
helper functions to get effective memory effects for an intrinsic and to
check if it has non-default attributes.

This eliminates one case statement in `getIntrinsicFnAttributeSet` that
we generate today for the case when intrinsic attributes are default
ones.

Also rename `Intrinsic` to `Int` to follow the naming convention used in
this file and adjust emission code to not emit unnecessary empty line
between cases generated.
  • Loading branch information
jurahul authored Sep 2, 2024
1 parent ad30a05 commit e5c7cde
Showing 1 changed file with 77 additions and 59 deletions.
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

0 comments on commit e5c7cde

Please sign in to comment.