Skip to content

Commit 2e1e2f5

Browse files
committed
[CodeGen] Improve large stack frame diagnostic
Add statistics about how much memory is used, in variables, spills, and unsafestack. Issue #58168 describes some of the difficulty diagnosing stack size issues identified by -Wframe-larger-than. D135488 addresses some of those issues by giving developers a method to view the stack layout and thereby understand where and how stack memory is used. However, that solution requires an additional pass, when a short summary about how the compiler has allocated stack memory can inform developers about where they should investigate. When they need the complete context, D135488 can provide them with a more comprehensive set of diagnostics. Reviewed By: nickdesaulniers Differential Revision: https://reviews.llvm.org/D136484
1 parent 70324cd commit 2e1e2f5

File tree

3 files changed

+58
-15
lines changed

3 files changed

+58
-15
lines changed

llvm/lib/CodeGen/PrologEpilogInserter.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include "llvm/Support/CodeGen.h"
5858
#include "llvm/Support/Debug.h"
5959
#include "llvm/Support/ErrorHandling.h"
60+
#include "llvm/Support/FormatVariadic.h"
6061
#include "llvm/Support/raw_ostream.h"
6162
#include "llvm/Target/TargetMachine.h"
6263
#include "llvm/Target/TargetOptions.h"
@@ -283,13 +284,35 @@ bool PEI::runOnMachineFunction(MachineFunction &MF) {
283284
assert(!Failed && "Invalid warn-stack-size fn attr value");
284285
(void)Failed;
285286
}
286-
if (MF.getFunction().hasFnAttribute(Attribute::SafeStack)) {
287-
StackSize += MFI.getUnsafeStackSize();
288-
}
287+
uint64_t UnsafeStackSize = MFI.getUnsafeStackSize();
288+
if (MF.getFunction().hasFnAttribute(Attribute::SafeStack))
289+
StackSize += UnsafeStackSize;
290+
289291
if (StackSize > Threshold) {
290292
DiagnosticInfoStackSize DiagStackSize(F, StackSize, Threshold, DS_Warning);
291293
F.getContext().diagnose(DiagStackSize);
294+
int64_t SpillSize = 0;
295+
for (int Idx = MFI.getObjectIndexBegin(), End = MFI.getObjectIndexEnd();
296+
Idx != End; ++Idx) {
297+
if (MFI.isSpillSlotObjectIndex(Idx))
298+
SpillSize += MFI.getObjectSize(Idx);
299+
}
300+
301+
float SpillPct =
302+
static_cast<float>(SpillSize) / static_cast<float>(StackSize);
303+
float VarPct = 1.0f - SpillPct;
304+
int64_t VariableSize = StackSize - SpillSize;
305+
dbgs() << formatv("{0}/{1} ({3:P}) spills, {2}/{1} ({4:P}) variables",
306+
SpillSize, StackSize, VariableSize, SpillPct, VarPct);
307+
if (UnsafeStackSize != 0) {
308+
float UnsafePct =
309+
static_cast<float>(UnsafeStackSize) / static_cast<float>(StackSize);
310+
dbgs() << formatv(", {0}/{2} ({1:P}) unsafe stack", UnsafeStackSize,
311+
UnsafePct, StackSize);
312+
}
313+
dbgs() << "\n";
292314
}
315+
293316
ORE->emit([&]() {
294317
return MachineOptimizationRemarkAnalysis(DEBUG_TYPE, "StackSize",
295318
MF.getFunction().getSubprogram(),

llvm/test/CodeGen/ARM/warn-stack.ll

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,33 @@
77
define void @nowarn() nounwind ssp "frame-pointer"="all" "warn-stack-size"="80" {
88
entry:
99
%buffer = alloca [12 x i8], align 1
10-
%arraydecay = getelementptr inbounds [12 x i8], [12 x i8]* %buffer, i64 0, i64 0
11-
call void @doit(i8* %arraydecay) nounwind
10+
call void @doit(ptr %buffer) nounwind
1211
ret void
1312
}
1413

15-
; CHECK: warning: stack frame size (92) exceeds limit (80) in function 'warn'
16-
define void @warn() nounwind ssp "frame-pointer"="all" "warn-stack-size"="80" {
14+
; CHECK: warning: stack frame size ([[STCK:[0-9]+]]) exceeds limit (80) in function 'warn'
15+
; CHECK: {{[0-9]+}}/[[STCK]] ({{.*}}%) spills, {{[0-9]+}}/[[STCK]] ({{.*}}%) variables
16+
define i32 @warn() nounwind ssp "frame-pointer"="all" "warn-stack-size"="80" {
1717
entry:
18+
%var = alloca i32, align 4
1819
%buffer = alloca [80 x i8], align 1
19-
%arraydecay = getelementptr inbounds [80 x i8], [80 x i8]* %buffer, i64 0, i64 0
20-
call void @doit(i8* %arraydecay) nounwind
21-
ret void
20+
call void @doit(ptr %buffer) nounwind
21+
call void @doit(ptr %var) nounwind
22+
%val = load i32, ptr %var
23+
ret i32 %val
24+
}
25+
26+
; CHECK: warning: stack frame size ([[STCK:[0-9]+]]) exceeds limit (80) in function 'warn_safestack'
27+
; CHECK: {{[0-9]+}}/[[STCK]] ({{.*}}%) spills, {{[0-9]+}}/[[STCK]] ({{.*}}%) variables, {{[0-9]+}}/[[STCK]] ({{.*}}%) unsafe stack
28+
define i32 @warn_safestack() nounwind ssp safestack "warn-stack-size"="80" {
29+
entry:
30+
%var = alloca i32, align 4
31+
%a = alloca i32, align 4
32+
%buffer = alloca [80 x i8], align 1
33+
call void @doit(ptr %buffer) nounwind
34+
call void @doit(ptr %var) nounwind
35+
%val = load i32, ptr %var
36+
ret i32 %val
2237
}
2338

24-
declare void @doit(i8*)
39+
declare void @doit(ptr)

llvm/test/CodeGen/X86/warn-stack.ll

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ entry:
1111
ret void
1212
}
1313

14-
; CHECK: warning: stack frame size (88) exceeds limit (80) in function 'warn'
14+
; CHECK: warning: stack frame size ([[STCK:[0-9]+]]) exceeds limit (80) in function 'warn'
15+
; CHECK: {{[0-9]+}}/[[STCK]] ({{.*}}%) spills, {{[0-9]+}}/[[STCK]] ({{.*}}%) variables
1516
define void @warn() nounwind ssp "warn-stack-size"="80" {
1617
entry:
1718
%buffer = alloca [80 x i8], align 1
@@ -24,11 +25,15 @@ entry:
2425
; combined stack size of the machine stack and unsafe stack will exceed the
2526
; warning threshold
2627

27-
; CHECK: warning: stack frame size (120) exceeds limit (80) in function 'warn_safestack'
28-
define void @warn_safestack() nounwind ssp safestack "warn-stack-size"="80" {
28+
; CHECK: warning: stack frame size ([[STCK:[0-9]+]]) exceeds limit (80) in function 'warn_safestack'
29+
; CHECK: {{[0-9]+}}/[[STCK]] ({{.*}}%) spills, {{[0-9]+}}/[[STCK]] ({{.*}}%) variables, {{[0-9]+}}/[[STCK]] ({{.*}}%) unsafe stack
30+
define i32 @warn_safestack() nounwind ssp safestack "warn-stack-size"="80" {
2931
entry:
32+
%var = alloca i32, align 4
3033
%buffer = alloca [80 x i8], align 1
3134
call void @doit(ptr %buffer) nounwind
32-
ret void
35+
call void @doit(ptr %var) nounwind
36+
%val = load i32, ptr %var
37+
ret i32 %val
3338
}
3439
declare void @doit(ptr)

0 commit comments

Comments
 (0)