diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp index b7f764cc552a0..4f85499e49d80 100644 --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -57,6 +57,7 @@ #include "llvm/Support/CodeGen.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" @@ -283,13 +284,35 @@ bool PEI::runOnMachineFunction(MachineFunction &MF) { assert(!Failed && "Invalid warn-stack-size fn attr value"); (void)Failed; } - if (MF.getFunction().hasFnAttribute(Attribute::SafeStack)) { - StackSize += MFI.getUnsafeStackSize(); - } + uint64_t UnsafeStackSize = MFI.getUnsafeStackSize(); + if (MF.getFunction().hasFnAttribute(Attribute::SafeStack)) + StackSize += UnsafeStackSize; + if (StackSize > Threshold) { DiagnosticInfoStackSize DiagStackSize(F, StackSize, Threshold, DS_Warning); F.getContext().diagnose(DiagStackSize); + int64_t SpillSize = 0; + for (int Idx = MFI.getObjectIndexBegin(), End = MFI.getObjectIndexEnd(); + Idx != End; ++Idx) { + if (MFI.isSpillSlotObjectIndex(Idx)) + SpillSize += MFI.getObjectSize(Idx); + } + + float SpillPct = + static_cast(SpillSize) / static_cast(StackSize); + float VarPct = 1.0f - SpillPct; + int64_t VariableSize = StackSize - SpillSize; + dbgs() << formatv("{0}/{1} ({3:P}) spills, {2}/{1} ({4:P}) variables", + SpillSize, StackSize, VariableSize, SpillPct, VarPct); + if (UnsafeStackSize != 0) { + float UnsafePct = + static_cast(UnsafeStackSize) / static_cast(StackSize); + dbgs() << formatv(", {0}/{2} ({1:P}) unsafe stack", UnsafeStackSize, + UnsafePct, StackSize); + } + dbgs() << "\n"; } + ORE->emit([&]() { return MachineOptimizationRemarkAnalysis(DEBUG_TYPE, "StackSize", MF.getFunction().getSubprogram(), diff --git a/llvm/test/CodeGen/ARM/warn-stack.ll b/llvm/test/CodeGen/ARM/warn-stack.ll index fbea89d8b81d0..4f23ec8db5cba 100644 --- a/llvm/test/CodeGen/ARM/warn-stack.ll +++ b/llvm/test/CodeGen/ARM/warn-stack.ll @@ -7,18 +7,33 @@ define void @nowarn() nounwind ssp "frame-pointer"="all" "warn-stack-size"="80" { entry: %buffer = alloca [12 x i8], align 1 - %arraydecay = getelementptr inbounds [12 x i8], [12 x i8]* %buffer, i64 0, i64 0 - call void @doit(i8* %arraydecay) nounwind + call void @doit(ptr %buffer) nounwind ret void } -; CHECK: warning: stack frame size (92) exceeds limit (80) in function 'warn' -define void @warn() nounwind ssp "frame-pointer"="all" "warn-stack-size"="80" { +; CHECK: warning: stack frame size ([[STCK:[0-9]+]]) exceeds limit (80) in function 'warn' +; CHECK: {{[0-9]+}}/[[STCK]] ({{.*}}%) spills, {{[0-9]+}}/[[STCK]] ({{.*}}%) variables +define i32 @warn() nounwind ssp "frame-pointer"="all" "warn-stack-size"="80" { entry: + %var = alloca i32, align 4 %buffer = alloca [80 x i8], align 1 - %arraydecay = getelementptr inbounds [80 x i8], [80 x i8]* %buffer, i64 0, i64 0 - call void @doit(i8* %arraydecay) nounwind - ret void + call void @doit(ptr %buffer) nounwind + call void @doit(ptr %var) nounwind + %val = load i32, ptr %var + ret i32 %val +} + +; CHECK: warning: stack frame size ([[STCK:[0-9]+]]) exceeds limit (80) in function 'warn_safestack' +; CHECK: {{[0-9]+}}/[[STCK]] ({{.*}}%) spills, {{[0-9]+}}/[[STCK]] ({{.*}}%) variables, {{[0-9]+}}/[[STCK]] ({{.*}}%) unsafe stack +define i32 @warn_safestack() nounwind ssp safestack "warn-stack-size"="80" { +entry: + %var = alloca i32, align 4 + %a = alloca i32, align 4 + %buffer = alloca [80 x i8], align 1 + call void @doit(ptr %buffer) nounwind + call void @doit(ptr %var) nounwind + %val = load i32, ptr %var + ret i32 %val } -declare void @doit(i8*) +declare void @doit(ptr) diff --git a/llvm/test/CodeGen/X86/warn-stack.ll b/llvm/test/CodeGen/X86/warn-stack.ll index 3164dc4680029..29c5216cf39ff 100644 --- a/llvm/test/CodeGen/X86/warn-stack.ll +++ b/llvm/test/CodeGen/X86/warn-stack.ll @@ -11,7 +11,8 @@ entry: ret void } -; CHECK: warning: stack frame size (88) exceeds limit (80) in function 'warn' +; CHECK: warning: stack frame size ([[STCK:[0-9]+]]) exceeds limit (80) in function 'warn' +; CHECK: {{[0-9]+}}/[[STCK]] ({{.*}}%) spills, {{[0-9]+}}/[[STCK]] ({{.*}}%) variables define void @warn() nounwind ssp "warn-stack-size"="80" { entry: %buffer = alloca [80 x i8], align 1 @@ -24,11 +25,15 @@ entry: ; combined stack size of the machine stack and unsafe stack will exceed the ; warning threshold -; CHECK: warning: stack frame size (120) exceeds limit (80) in function 'warn_safestack' -define void @warn_safestack() nounwind ssp safestack "warn-stack-size"="80" { +; CHECK: warning: stack frame size ([[STCK:[0-9]+]]) exceeds limit (80) in function 'warn_safestack' +; CHECK: {{[0-9]+}}/[[STCK]] ({{.*}}%) spills, {{[0-9]+}}/[[STCK]] ({{.*}}%) variables, {{[0-9]+}}/[[STCK]] ({{.*}}%) unsafe stack +define i32 @warn_safestack() nounwind ssp safestack "warn-stack-size"="80" { entry: + %var = alloca i32, align 4 %buffer = alloca [80 x i8], align 1 call void @doit(ptr %buffer) nounwind - ret void + call void @doit(ptr %var) nounwind + %val = load i32, ptr %var + ret i32 %val } declare void @doit(ptr)