[llvm] 2e1e2f5 - [CodeGen] Improve large stack frame diagnostic

Paul Kirth via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 26 17:51:54 PDT 2022


Author: Paul Kirth
Date: 2022-10-27T00:51:45Z
New Revision: 2e1e2f52f357768186ecfcc5ac53d5fa53d1b094

URL: https://github.com/llvm/llvm-project/commit/2e1e2f52f357768186ecfcc5ac53d5fa53d1b094
DIFF: https://github.com/llvm/llvm-project/commit/2e1e2f52f357768186ecfcc5ac53d5fa53d1b094.diff

LOG: [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

Added: 
    

Modified: 
    llvm/lib/CodeGen/PrologEpilogInserter.cpp
    llvm/test/CodeGen/ARM/warn-stack.ll
    llvm/test/CodeGen/X86/warn-stack.ll

Removed: 
    


################################################################################
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<float>(SpillSize) / static_cast<float>(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<float>(UnsafeStackSize) / static_cast<float>(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)


        


More information about the llvm-commits mailing list