Skip to content

Commit 22af0cd

Browse files
authored
[LLVM][Intrinsics] Reduce stack size for Intrinsic::getAttributes (#152219)
This change fixes a stack size regression that got introduced in 0de0354. That change did 2 independent things: 1. Uniquify argument and function attributes separately so that we generate a smaller number of unique sets as opposed to uniquifying them together. This is beneficial for code size. 2. Eliminate the fixed size array `AS` and `NumAttrs` variable and instead build the returned AttribteList in each case using an initializer list. The second part seems to have caused a regression in the stack size usage of this function for Windows. This change essentially undoes part 2 and reinstates the use of the fixed size array `AS` which fixes this stack size regression. The actual measured stack frame size for this function before/after this change is as follows: ``` Current trunk data for release build (x86_64 builds for Linux, x86 build for Windows): Compiler gcc-13.3.0 clang-18.1.3 MSVC 19.43.34810.0 DLLVM_ENABLE_ASSERTIONS=OFF 0x120 0x110 0x54B0 DLLVM_ENABLE_ASSERTIONS=ON 0x2880 0x110 0x5250 After applying the fix: Compiler gcc-13.3.0 clang-18.1.3 MSVC 19.43.34810.0 DLLVM_ENABLE_ASSERTIONS=OFF 0x120 0x118 0x1240h DLLVM_ENABLE_ASSERTIONS=ON 0x120 0x118 0x1240h ``` Note that for Windows builds with assertions disabled, the stack frame size for this function reduces from 21680 to 4672 which is a 4.6x reduction. Stack frame size for GCC build with assertions also improved and clang builds are unimpacted. The speculation is that clang and gcc is able to reuse the stack space across these switch cases better with existing code, but MSVC is not, and re-introducing the `AS` variable forces all cases to use the same local variable, addressing the stack space regression.
1 parent 0b16395 commit 22af0cd

File tree

2 files changed

+37
-30
lines changed

2 files changed

+37
-30
lines changed

llvm/test/TableGen/intrinsic-attrs.td

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,11 @@ def int_deref_ptr_ret : Intrinsic<[llvm_ptr_ty], [], [Dereferenceable<RetIndex,
3030

3131
// CHECK: getAttributes(LLVMContext &C, ID id,
3232
// CHECK-NEXT: FunctionType *FT) {
33-
// CHECK: case 1:
34-
// CHECK-NEXT: return AttributeList::get(C, {
35-
// CHECK-NEXT: {AttributeList::FunctionIndex, getIntrinsicFnAttributeSet(C, FnAttrID)}
36-
// CHECK-NEXT: });
33+
// CHECK: case 1:
34+
// CHECK-NEXT: HasFnAttr = true;
35+
// CHECK-NEXT: break;
3736
// CHECK-NEXT: case 0:
38-
// CHECK-NEXT: return AttributeList::get(C, {
39-
// CHECK-NEXT: {0, getIntrinsicArgAttributeSet(C, 0, FT->getContainedType(0))},
40-
// CHECK-NEXT: {AttributeList::FunctionIndex, getIntrinsicFnAttributeSet(C, FnAttrID)}
41-
// CHECK-NEXT: });
37+
// CHECK-NEXT: AS[0] = {0, getIntrinsicArgAttributeSet(C, 0, FT->getContainedType(0))};
38+
// CHECK-NEXT: HasFnAttr = true;
39+
// CHECK-NEXT: NumAttrs = 1
40+
// CHECK-NEXT: break;

llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -652,53 +652,61 @@ static constexpr uint16_t IntrinsicsToAttributesMap[] = {)";
652652
653653
AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id,
654654
FunctionType *FT) {)";
655+
// Find the max number of attributes to create the local array.
656+
unsigned MaxNumAttrs = 0;
657+
for (const auto [IntPtr, UniqueID] : UniqAttributes) {
658+
const CodeGenIntrinsic &Int = *IntPtr;
659+
unsigned NumAttrs =
660+
llvm::count_if(Int.ArgumentAttributes,
661+
[](const auto &Attrs) { return !Attrs.empty(); });
662+
NumAttrs += hasFnAttributes(Int);
663+
MaxNumAttrs = std::max(MaxNumAttrs, NumAttrs);
664+
}
655665

656666
OS << formatv(R"(
657667
if (id == 0)
658668
return AttributeList();
659669
660670
uint16_t PackedID = IntrinsicsToAttributesMap[id - 1];
661671
uint8_t FnAttrID = PackedID >> 8;
672+
std::pair<unsigned, AttributeSet> AS[{}];
673+
unsigned NumAttrs = 0;
674+
bool HasFnAttr = false;
662675
switch(PackedID & 0xFF) {{
663676
default: llvm_unreachable("Invalid attribute number");
664-
)");
677+
)",
678+
MaxNumAttrs);
665679

666680
for (const auto [IntPtr, UniqueID] : UniqAttributes) {
667681
OS << formatv(" case {}:\n", UniqueID);
668682
const CodeGenIntrinsic &Int = *IntPtr;
669683

670-
// Keep track of the number of attributes we're writing out.
671-
unsigned NumAttrs =
672-
llvm::count_if(Int.ArgumentAttributes,
673-
[](const auto &Attrs) { return !Attrs.empty(); });
674-
NumAttrs += hasFnAttributes(Int);
675-
if (NumAttrs == 0) {
676-
OS << " return AttributeList();\n";
677-
continue;
678-
}
684+
unsigned NumAttrs = 0;
679685

680-
OS << " return AttributeList::get(C, {\n";
681-
ListSeparator LS(",\n");
682686
for (const auto &[AttrIdx, Attrs] : enumerate(Int.ArgumentAttributes)) {
683687
if (Attrs.empty())
684688
continue;
685689

686690
unsigned ArgAttrID = UniqArgAttributes.find(Attrs)->second;
687-
OS << LS
688-
<< formatv(" {{{}, getIntrinsicArgAttributeSet(C, {}, "
689-
"FT->getContainedType({}))}",
690-
AttrIdx, ArgAttrID, AttrIdx);
691+
OS << formatv(" AS[{}] = {{{}, getIntrinsicArgAttributeSet(C, {}, "
692+
"FT->getContainedType({}))};\n",
693+
NumAttrs++, AttrIdx, ArgAttrID, AttrIdx);
691694
}
692695

693-
if (hasFnAttributes(Int)) {
694-
OS << LS
695-
<< " {AttributeList::FunctionIndex, "
696-
"getIntrinsicFnAttributeSet(C, FnAttrID)}";
697-
}
698-
OS << "\n });\n";
696+
if (hasFnAttributes(Int))
697+
OS << " HasFnAttr = true;\n";
698+
699+
if (NumAttrs)
700+
OS << formatv(" NumAttrs = {};\n", NumAttrs);
701+
OS << " break;\n";
699702
}
700703

701704
OS << R"( }
705+
if (HasFnAttr) {
706+
AS[NumAttrs++] = {AttributeList::FunctionIndex,
707+
getIntrinsicFnAttributeSet(C, FnAttrID)};
708+
}
709+
return AttributeList::get(C, ArrayRef(AS, NumAttrs));
702710
}
703711
#endif // GET_INTRINSIC_ATTRIBUTES
704712

0 commit comments

Comments
 (0)