paulkirth updated this revision to Diff 469446.
paulkirth added a comment.

Code Cleanups and Test Cases

- Replace SmallVector with SmallPtrSet
- Add some comments/clarification
- Add a larger, more flexible test case

There's still room for improvement for both testing and documentation.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D135488/new/

https://reviews.llvm.org/D135488

Files:
  llvm/include/llvm/CodeGen/MachineFrameInfo.h
  llvm/include/llvm/CodeGen/Passes.h
  llvm/include/llvm/InitializePasses.h
  llvm/lib/CodeGen/CMakeLists.txt
  llvm/lib/CodeGen/CodeGen.cpp
  llvm/lib/CodeGen/MachineFrameInfo.cpp
  llvm/lib/CodeGen/PrologEpilogInserter.cpp
  llvm/lib/CodeGen/StackFramePrinterPass.cpp
  llvm/lib/CodeGen/TargetPassConfig.cpp
  llvm/test/CodeGen/X86/stack-frame-printer.ll
  llvm/test/CodeGen/X86/stack-frame-printer2.ll

Index: llvm/test/CodeGen/X86/stack-frame-printer2.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/X86/stack-frame-printer2.ll
@@ -0,0 +1,764 @@
+
+; RUN: llc %s -print-stack-frame -o /dev/null --march=x86 -mcpu=i386 2>&1 | FileCheck %s --check-prefix=BOTH --check-prefix=DEBUG
+; RUN: opt %s -strip -S | llc  -print-stack-frame -o /dev/null --march=x86 -mcpu=i386 2>&1 | FileCheck %s --check-prefix=BOTH --check-prefix=STRIPPED
+
+
+; BOTH: # Stack Layout: cleanup_array
+; BOTH:  Offset{{.*}}Align{{.*}}Size
+; BOTH:  [SP+4]{{.+}}16{{.+}}4
+; DEBUG: a @ dot.c:13
+; STRIPPED-NOT: a @ dot.c:13
+; BOTH:  [SP-4]{{.+}}Spill 8{{.+}}4
+
+; BOTH: # Stack Layout: cleanup_result
+; BOTH:  Offset{{.+}}Align{{.+}}Size
+; BOTH:  [SP+4]{{.+}}16{{.+}}4
+; DEBUG: res @ dot.c:21
+; STRIPPED-NOT: res @ dot.c:21
+; BOTH:  [SP-4]{{.+}}Spill 8{{.+}}4
+
+; BOTH: # Stack Layout: do_work
+; BOTH:  Offset{{.+}}Align{{.+}}Size
+; BOTH:  [SP+12]{{.+}}8{{.+}}4
+; DEBUG: out @ dot.c:32
+; STRIPPED-NOT: out @ dot.c:32
+; BOTH:  [SP+8]{{.+}}4{{.+}}4
+; BOTH:  [SP+4]{{.+}}16{{.+}}4
+; DEBUG: A @ dot.c:32
+; STRIPPED-NOT: A @ dot.c:32
+; BOTH:  [SP-4]{{.+}}Spill 8{{.+}}4
+; BOTH:  [SP-12]{{.+}}8{{.+}}4
+; DEBUG: AB @ dot.c:38
+; STRIPPED-NOT: AB @ dot.c:38
+; BOTH:  [SP-16]{{.+}}4{{.+}}4
+; DEBUG: i @ dot.c:55
+; STRIPPED-NOT: i @ dot.c:55
+; BOTH:  [SP-20]{{.+}}8{{.+}}4
+; DEBUG: B @ dot.c:32
+; STRIPPED-NOT: B @ dot.c:32
+; BOTH:  [SP-24]{{.+}}4{{.+}}4
+; DEBUG: len @ dot.c:37
+; STRIPPED-NOT: len @ dot.c:37
+; BOTH:  [SP-28]{{.+}}4{{.+}}4
+; BOTH:  [SP-32]{{.+}}4{{.+}}4
+; DEBUG: sum @ dot.c:54
+; STRIPPED-NOT: sum @ dot.c:54
+
+; BOTH: # Stack Layout: gen_array
+; BOTH:  Offset{{.+}}Align{{.+}}Size
+; BOTH:  [SP+4]{{.+}}16{{.+}}4
+; DEBUG: size @ dot.c:62
+; STRIPPED-NOT: size @ dot.c:62
+; BOTH:  [SP-4]{{.+}}Spill 8{{.+}}4
+; BOTH:  [SP-12]{{.+}}8{{.+}}4
+; DEBUG: res @ dot.c:65
+; STRIPPED-NOT: res @ dot.c:65
+; BOTH:  [SP-16]{{.+}}4{{.+}}4
+; DEBUG: i @ dot.c:69
+; STRIPPED-NOT: i @ dot.c:69
+; BOTH:  [SP-20]{{.+}}8 4
+
+; BOTH: # Stack Layout: caller
+; BOTH:  Offset{{.+}}Align{{.+}}Size
+; BOTH:  [SP-4]{{.+}}Spill 8{{.+}}4
+; BOTH:  [SP-12]{{.+}}8{{.+}}4
+; DEBUG: res @ dot.c:80
+; STRIPPED-NOT: res @ dot.c:80
+; BOTH:  [SP-20]{{.+}}8{{.+}}4
+; DEBUG: B @ dot.c:79
+; STRIPPED-NOT: B @ dot.c:79
+; BOTH:  [SP-28]{{.+}}8{{.+}}4
+; DEBUG: A @ dot.c:78
+; STRIPPED-NOT: A @ dot.c:78
+; BOTH:  [SP-32]{{.+}}4{{.+}}4
+; DEBUG: ret @ dot.c:81
+; STRIPPED-NOT: ret @ dot.c:81
+; BOTH:  [SP-36]{{.+}}4{{.+}}4
+; BOTH:  [SP-40]{{.+}}4{{.+}}4
+; DEBUG: err @ dot.c:83
+; STRIPPED-NOT: err @ dot.c:83
+; BOTH:  [SP-44]{{.+}}4{{.+}}4
+; DEBUG:  size @ dot.c:77
+; STRIPPED-NOT: size @ dot.c:77
+
+
+
+
+; ModuleID = 'dot.c'
+source_filename = "dot.c"
+
+%struct.Array = type { ptr, i32 }
+%struct.Result = type { ptr, i32 }
+
+; Function Attrs: noinline nounwind uwtable
+define dso_local void @cleanup_array(ptr noundef %0) #0 !dbg !24 {
+  %2 = alloca ptr, align 8
+  store ptr %0, ptr %2, align 8
+  call void @llvm.dbg.declare(metadata ptr %2, metadata !28, metadata !DIExpression()), !dbg !29
+  %3 = load ptr, ptr %2, align 8, !dbg !30
+  %4 = icmp ne ptr %3, null, !dbg !30
+  br i1 %4, label %6, label %5, !dbg !32
+
+5:                                                ; preds = %1
+  br label %16, !dbg !33
+
+6:                                                ; preds = %1
+  %7 = load ptr, ptr %2, align 8, !dbg !34
+  %8 = getelementptr inbounds %struct.Array, ptr %7, i32 0, i32 0, !dbg !36
+  %9 = load ptr, ptr %8, align 8, !dbg !36
+  %10 = icmp ne ptr %9, null, !dbg !34
+  br i1 %10, label %12, label %11, !dbg !37
+
+11:                                               ; preds = %6
+  br label %16, !dbg !38
+
+12:                                               ; preds = %6
+  %13 = load ptr, ptr %2, align 8, !dbg !39
+  %14 = getelementptr inbounds %struct.Array, ptr %13, i32 0, i32 0, !dbg !40
+  %15 = load ptr, ptr %14, align 8, !dbg !40
+  call void @free(ptr noundef %15) #5, !dbg !41
+  br label %16, !dbg !42
+
+16:                                               ; preds = %12, %11, %5
+  ret void, !dbg !42
+}
+
+; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+; Function Attrs: nounwind
+declare void @free(ptr noundef) #2
+
+; Function Attrs: noinline nounwind uwtable
+define dso_local void @cleanup_result(ptr noundef %0) #0 !dbg !43 {
+  %2 = alloca ptr, align 8
+  store ptr %0, ptr %2, align 8
+  call void @llvm.dbg.declare(metadata ptr %2, metadata !46, metadata !DIExpression()), !dbg !47
+  %3 = load ptr, ptr %2, align 8, !dbg !48
+  %4 = icmp ne ptr %3, null, !dbg !48
+  br i1 %4, label %6, label %5, !dbg !50
+
+5:                                                ; preds = %1
+  br label %19, !dbg !51
+
+6:                                                ; preds = %1
+  %7 = load ptr, ptr %2, align 8, !dbg !52
+  %8 = getelementptr inbounds %struct.Result, ptr %7, i32 0, i32 0, !dbg !54
+  %9 = load ptr, ptr %8, align 8, !dbg !54
+  %10 = icmp ne ptr %9, null, !dbg !52
+  br i1 %10, label %12, label %11, !dbg !55
+
+11:                                               ; preds = %6
+  br label %19, !dbg !56
+
+12:                                               ; preds = %6
+  %13 = load ptr, ptr %2, align 8, !dbg !57
+  %14 = getelementptr inbounds %struct.Result, ptr %13, i32 0, i32 0, !dbg !58
+  %15 = load ptr, ptr %14, align 8, !dbg !58
+  call void @cleanup_array(ptr noundef %15), !dbg !59
+  %16 = load ptr, ptr %2, align 8, !dbg !60
+  %17 = getelementptr inbounds %struct.Result, ptr %16, i32 0, i32 0, !dbg !61
+  %18 = load ptr, ptr %17, align 8, !dbg !61
+  call void @free(ptr noundef %18) #5, !dbg !62
+  br label %19, !dbg !63
+
+19:                                               ; preds = %12, %11, %5
+  ret void, !dbg !63
+}
+
+; Function Attrs: noinline nounwind uwtable
+define dso_local i32 @do_work(ptr noundef %0, ptr noundef %1, ptr noundef %2) #0 !dbg !64 {
+  %4 = alloca i32, align 4
+  %5 = alloca ptr, align 8
+  %6 = alloca ptr, align 8
+  %7 = alloca ptr, align 8
+  %8 = alloca i32, align 4
+  %9 = alloca ptr, align 8
+  %10 = alloca i32, align 4
+  %11 = alloca i32, align 4
+  store ptr %0, ptr %5, align 8
+  call void @llvm.dbg.declare(metadata ptr %5, metadata !67, metadata !DIExpression()), !dbg !68
+  store ptr %1, ptr %6, align 8
+  call void @llvm.dbg.declare(metadata ptr %6, metadata !69, metadata !DIExpression()), !dbg !70
+  store ptr %2, ptr %7, align 8
+  call void @llvm.dbg.declare(metadata ptr %7, metadata !71, metadata !DIExpression()), !dbg !72
+  %12 = load ptr, ptr %5, align 8, !dbg !73
+  %13 = icmp ne ptr %12, null, !dbg !73
+  br i1 %13, label %14, label %17, !dbg !75
+
+14:                                               ; preds = %3
+  %15 = load ptr, ptr %6, align 8, !dbg !76
+  %16 = icmp ne ptr %15, null, !dbg !76
+  br i1 %16, label %18, label %17, !dbg !77
+
+17:                                               ; preds = %14, %3
+  store i32 -1, ptr %4, align 4, !dbg !78
+  br label %106, !dbg !78
+
+18:                                               ; preds = %14
+  %19 = load ptr, ptr %5, align 8, !dbg !79
+  %20 = getelementptr inbounds %struct.Array, ptr %19, i32 0, i32 1, !dbg !81
+  %21 = load i32, ptr %20, align 8, !dbg !81
+  %22 = load ptr, ptr %6, align 8, !dbg !82
+  %23 = getelementptr inbounds %struct.Array, ptr %22, i32 0, i32 1, !dbg !83
+  %24 = load i32, ptr %23, align 8, !dbg !83
+  %25 = icmp ne i32 %21, %24, !dbg !84
+  br i1 %25, label %26, label %27, !dbg !85
+
+26:                                               ; preds = %18
+  store i32 -1, ptr %4, align 4, !dbg !86
+  br label %106, !dbg !86
+
+27:                                               ; preds = %18
+  call void @llvm.dbg.declare(metadata ptr %8, metadata !87, metadata !DIExpression()), !dbg !89
+  %28 = load ptr, ptr %5, align 8, !dbg !90
+  %29 = getelementptr inbounds %struct.Array, ptr %28, i32 0, i32 1, !dbg !91
+  %30 = load i32, ptr %29, align 8, !dbg !91
+  store i32 %30, ptr %8, align 4, !dbg !89
+  call void @llvm.dbg.declare(metadata ptr %9, metadata !92, metadata !DIExpression()), !dbg !93
+  %31 = load ptr, ptr %7, align 8, !dbg !94
+  %32 = getelementptr inbounds %struct.Result, ptr %31, i32 0, i32 0, !dbg !96
+  %33 = load ptr, ptr %32, align 8, !dbg !96
+  %34 = icmp eq ptr %33, null, !dbg !97
+  br i1 %34, label %35, label %44, !dbg !98
+
+35:                                               ; preds = %27
+  %36 = call noalias ptr @malloc(i64 noundef 16) #6, !dbg !99
+  store ptr %36, ptr %9, align 8, !dbg !101
+  %37 = load ptr, ptr %9, align 8, !dbg !102
+  %38 = getelementptr inbounds %struct.Array, ptr %37, i32 0, i32 0, !dbg !103
+  store ptr null, ptr %38, align 8, !dbg !104
+  %39 = load ptr, ptr %9, align 8, !dbg !105
+  %40 = getelementptr inbounds %struct.Array, ptr %39, i32 0, i32 1, !dbg !106
+  store i32 0, ptr %40, align 8, !dbg !107
+  %41 = load ptr, ptr %9, align 8, !dbg !108
+  %42 = load ptr, ptr %7, align 8, !dbg !109
+  %43 = getelementptr inbounds %struct.Result, ptr %42, i32 0, i32 0, !dbg !110
+  store ptr %41, ptr %43, align 8, !dbg !111
+  br label %48, !dbg !112
+
+44:                                               ; preds = %27
+  %45 = load ptr, ptr %7, align 8, !dbg !113
+  %46 = getelementptr inbounds %struct.Result, ptr %45, i32 0, i32 0, !dbg !115
+  %47 = load ptr, ptr %46, align 8, !dbg !115
+  store ptr %47, ptr %9, align 8, !dbg !116
+  br label %48
+
+48:                                               ; preds = %44, %35
+  %49 = load ptr, ptr %9, align 8, !dbg !117
+  %50 = getelementptr inbounds %struct.Array, ptr %49, i32 0, i32 0, !dbg !119
+  %51 = load ptr, ptr %50, align 8, !dbg !119
+  %52 = icmp ne ptr %51, null, !dbg !117
+  br i1 %52, label %53, label %57, !dbg !120
+
+53:                                               ; preds = %48
+  %54 = load ptr, ptr %9, align 8, !dbg !121
+  %55 = getelementptr inbounds %struct.Array, ptr %54, i32 0, i32 0, !dbg !122
+  %56 = load ptr, ptr %55, align 8, !dbg !122
+  call void @free(ptr noundef %56) #5, !dbg !123
+  br label %57, !dbg !123
+
+57:                                               ; preds = %53, %48
+  %58 = load i32, ptr %8, align 4, !dbg !124
+  %59 = sext i32 %58 to i64, !dbg !124
+  %60 = mul i64 %59, 4, !dbg !125
+  %61 = call noalias ptr @malloc(i64 noundef %60) #6, !dbg !126
+  %62 = load ptr, ptr %9, align 8, !dbg !127
+  %63 = getelementptr inbounds %struct.Array, ptr %62, i32 0, i32 0, !dbg !128
+  store ptr %61, ptr %63, align 8, !dbg !129
+  %64 = load i32, ptr %8, align 4, !dbg !130
+  %65 = load ptr, ptr %9, align 8, !dbg !131
+  %66 = getelementptr inbounds %struct.Array, ptr %65, i32 0, i32 1, !dbg !132
+  store i32 %64, ptr %66, align 8, !dbg !133
+  call void @llvm.dbg.declare(metadata ptr %10, metadata !134, metadata !DIExpression()), !dbg !135
+  store i32 0, ptr %10, align 4, !dbg !135
+  call void @llvm.dbg.declare(metadata ptr %11, metadata !136, metadata !DIExpression()), !dbg !138
+  store i32 0, ptr %11, align 4, !dbg !138
+  br label %67, !dbg !139
+
+67:                                               ; preds = %102, %57
+  %68 = load i32, ptr %11, align 4, !dbg !140
+  %69 = load i32, ptr %8, align 4, !dbg !142
+  %70 = icmp slt i32 %68, %69, !dbg !143
+  br i1 %70, label %71, label %105, !dbg !144
+
+71:                                               ; preds = %67
+  %72 = load ptr, ptr %5, align 8, !dbg !145
+  %73 = getelementptr inbounds %struct.Array, ptr %72, i32 0, i32 0, !dbg !147
+  %74 = load ptr, ptr %73, align 8, !dbg !147
+  %75 = load i32, ptr %11, align 4, !dbg !148
+  %76 = sext i32 %75 to i64, !dbg !145
+  %77 = getelementptr inbounds i32, ptr %74, i64 %76, !dbg !145
+  %78 = load i32, ptr %77, align 4, !dbg !145
+  %79 = load ptr, ptr %6, align 8, !dbg !149
+  %80 = getelementptr inbounds %struct.Array, ptr %79, i32 0, i32 0, !dbg !150
+  %81 = load ptr, ptr %80, align 8, !dbg !150
+  %82 = load i32, ptr %11, align 4, !dbg !151
+  %83 = sext i32 %82 to i64, !dbg !149
+  %84 = getelementptr inbounds i32, ptr %81, i64 %83, !dbg !149
+  %85 = load i32, ptr %84, align 4, !dbg !149
+  %86 = mul nsw i32 %78, %85, !dbg !152
+  %87 = load ptr, ptr %9, align 8, !dbg !153
+  %88 = getelementptr inbounds %struct.Array, ptr %87, i32 0, i32 0, !dbg !154
+  %89 = load ptr, ptr %88, align 8, !dbg !154
+  %90 = load i32, ptr %11, align 4, !dbg !155
+  %91 = sext i32 %90 to i64, !dbg !153
+  %92 = getelementptr inbounds i32, ptr %89, i64 %91, !dbg !153
+  store i32 %86, ptr %92, align 4, !dbg !156
+  %93 = load ptr, ptr %9, align 8, !dbg !157
+  %94 = getelementptr inbounds %struct.Array, ptr %93, i32 0, i32 0, !dbg !158
+  %95 = load ptr, ptr %94, align 8, !dbg !158
+  %96 = load i32, ptr %11, align 4, !dbg !159
+  %97 = sext i32 %96 to i64, !dbg !157
+  %98 = getelementptr inbounds i32, ptr %95, i64 %97, !dbg !157
+  %99 = load i32, ptr %98, align 4, !dbg !157
+  %100 = load i32, ptr %10, align 4, !dbg !160
+  %101 = add nsw i32 %100, %99, !dbg !160
+  store i32 %101, ptr %10, align 4, !dbg !160
+  br label %102, !dbg !161
+
+102:                                              ; preds = %71
+  %103 = load i32, ptr %11, align 4, !dbg !162
+  %104 = add nsw i32 %103, 1, !dbg !162
+  store i32 %104, ptr %11, align 4, !dbg !162
+  br label %67, !dbg !163, !llvm.loop !164
+
+105:                                              ; preds = %67
+  store i32 0, ptr %4, align 4, !dbg !167
+  br label %106, !dbg !167
+
+106:                                              ; preds = %105, %26, %17
+  %107 = load i32, ptr %4, align 4, !dbg !168
+  ret i32 %107, !dbg !168
+}
+
+; Function Attrs: nounwind allocsize(0)
+declare noalias ptr @malloc(i64 noundef) #3
+
+; Function Attrs: noinline nounwind uwtable
+define dso_local ptr @gen_array(i32 noundef %0) #0 !dbg !169 {
+  %2 = alloca ptr, align 8
+  %3 = alloca i32, align 4
+  %4 = alloca ptr, align 8
+  %5 = alloca i32, align 4
+  store i32 %0, ptr %3, align 4
+  call void @llvm.dbg.declare(metadata ptr %3, metadata !172, metadata !DIExpression()), !dbg !173
+  %6 = load i32, ptr %3, align 4, !dbg !174
+  %7 = icmp slt i32 %6, 0, !dbg !176
+  br i1 %7, label %8, label %9, !dbg !177
+
+8:                                                ; preds = %1
+  store ptr null, ptr %2, align 8, !dbg !178
+  br label %37, !dbg !178
+
+9:                                                ; preds = %1
+  call void @llvm.dbg.declare(metadata ptr %4, metadata !179, metadata !DIExpression()), !dbg !180
+  %10 = call noalias ptr @malloc(i64 noundef 16) #6, !dbg !181
+  store ptr %10, ptr %4, align 8, !dbg !180
+  %11 = load i32, ptr %3, align 4, !dbg !182
+  %12 = load ptr, ptr %4, align 8, !dbg !183
+  %13 = getelementptr inbounds %struct.Array, ptr %12, i32 0, i32 1, !dbg !184
+  store i32 %11, ptr %13, align 8, !dbg !185
+  %14 = load i32, ptr %3, align 4, !dbg !186
+  %15 = sext i32 %14 to i64, !dbg !186
+  %16 = mul i64 %15, 4, !dbg !187
+  %17 = call noalias ptr @malloc(i64 noundef %16) #6, !dbg !188
+  %18 = load ptr, ptr %4, align 8, !dbg !189
+  %19 = getelementptr inbounds %struct.Array, ptr %18, i32 0, i32 0, !dbg !190
+  store ptr %17, ptr %19, align 8, !dbg !191
+  call void @llvm.dbg.declare(metadata ptr %5, metadata !192, metadata !DIExpression()), !dbg !194
+  store i32 0, ptr %5, align 4, !dbg !194
+  br label %20, !dbg !195
+
+20:                                               ; preds = %32, %9
+  %21 = load i32, ptr %5, align 4, !dbg !196
+  %22 = load i32, ptr %3, align 4, !dbg !198
+  %23 = icmp slt i32 %21, %22, !dbg !199
+  br i1 %23, label %24, label %35, !dbg !200
+
+24:                                               ; preds = %20
+  %25 = call i32 @rand() #5, !dbg !201
+  %26 = load ptr, ptr %4, align 8, !dbg !203
+  %27 = getelementptr inbounds %struct.Array, ptr %26, i32 0, i32 0, !dbg !204
+  %28 = load ptr, ptr %27, align 8, !dbg !204
+  %29 = load i32, ptr %5, align 4, !dbg !205
+  %30 = sext i32 %29 to i64, !dbg !203
+  %31 = getelementptr inbounds i32, ptr %28, i64 %30, !dbg !203
+  store i32 %25, ptr %31, align 4, !dbg !206
+  br label %32, !dbg !207
+
+32:                                               ; preds = %24
+  %33 = load i32, ptr %5, align 4, !dbg !208
+  %34 = add nsw i32 %33, 1, !dbg !208
+  store i32 %34, ptr %5, align 4, !dbg !208
+  br label %20, !dbg !209, !llvm.loop !210
+
+35:                                               ; preds = %20
+  %36 = load ptr, ptr %4, align 8, !dbg !212
+  store ptr %36, ptr %2, align 8, !dbg !213
+  br label %37, !dbg !213
+
+37:                                               ; preds = %35, %8
+  %38 = load ptr, ptr %2, align 8, !dbg !214
+  ret ptr %38, !dbg !214
+}
+
+; Function Attrs: nounwind
+declare i32 @rand() #2
+
+; Function Attrs: noinline nounwind uwtable
+define dso_local i32 @caller() #0 !dbg !215 {
+  %1 = alloca i32, align 4
+  %2 = alloca i32, align 4
+  %3 = alloca ptr, align 8
+  %4 = alloca ptr, align 8
+  %5 = alloca ptr, align 8
+  %6 = alloca i32, align 4
+  %7 = alloca i32, align 4
+  call void @llvm.dbg.declare(metadata ptr %2, metadata !218, metadata !DIExpression()), !dbg !219
+  store i32 100, ptr %2, align 4, !dbg !219
+  call void @llvm.dbg.declare(metadata ptr %3, metadata !220, metadata !DIExpression()), !dbg !221
+  %8 = call ptr @gen_array(i32 noundef 100), !dbg !222
+  store ptr %8, ptr %3, align 8, !dbg !221
+  call void @llvm.dbg.declare(metadata ptr %4, metadata !223, metadata !DIExpression()), !dbg !224
+  %9 = call ptr @gen_array(i32 noundef 100), !dbg !225
+  store ptr %9, ptr %4, align 8, !dbg !224
+  call void @llvm.dbg.declare(metadata ptr %5, metadata !226, metadata !DIExpression()), !dbg !227
+  %10 = call noalias ptr @malloc(i64 noundef 16) #6, !dbg !228
+  store ptr %10, ptr %5, align 8, !dbg !227
+  call void @llvm.dbg.declare(metadata ptr %6, metadata !229, metadata !DIExpression()), !dbg !230
+  store i32 -1, ptr %6, align 4, !dbg !230
+  call void @llvm.dbg.declare(metadata ptr %7, metadata !231, metadata !DIExpression()), !dbg !232
+  %11 = load ptr, ptr %3, align 8, !dbg !233
+  %12 = load ptr, ptr %4, align 8, !dbg !234
+  %13 = load ptr, ptr %5, align 8, !dbg !235
+  %14 = call i32 @do_work(ptr noundef %11, ptr noundef %12, ptr noundef %13), !dbg !236
+  store i32 %14, ptr %7, align 4, !dbg !232
+  %15 = load i32, ptr %7, align 4, !dbg !237
+  %16 = icmp eq i32 %15, -1, !dbg !239
+  br i1 %16, label %17, label %18, !dbg !240
+
+17:                                               ; preds = %0
+  br label %30, !dbg !241
+
+18:                                               ; preds = %0
+  %19 = load ptr, ptr %5, align 8, !dbg !243
+  %20 = getelementptr inbounds %struct.Result, ptr %19, i32 0, i32 1, !dbg !244
+  %21 = load i32, ptr %20, align 8, !dbg !244
+  store i32 %21, ptr %6, align 4, !dbg !245
+  %22 = load i32, ptr %6, align 4, !dbg !246
+  %23 = icmp eq i32 %22, -1, !dbg !248
+  br i1 %23, label %24, label %26, !dbg !249
+
+24:                                               ; preds = %18
+  %25 = call i32 @caller(), !dbg !250
+  store i32 %25, ptr %1, align 4, !dbg !251
+  br label %35, !dbg !251
+
+26:                                               ; preds = %18
+  %27 = load ptr, ptr %5, align 8, !dbg !252
+  %28 = getelementptr inbounds %struct.Result, ptr %27, i32 0, i32 0, !dbg !253
+  %29 = load ptr, ptr %28, align 8, !dbg !253
+  call void @use_dot_vector(ptr noundef %29), !dbg !254
+  br label %30, !dbg !254
+
+30:                                               ; preds = %26, %17
+  call void @llvm.dbg.label(metadata !255), !dbg !256
+  %31 = load ptr, ptr %3, align 8, !dbg !257
+  call void @cleanup_array(ptr noundef %31), !dbg !258
+  %32 = load ptr, ptr %4, align 8, !dbg !259
+  call void @cleanup_array(ptr noundef %32), !dbg !260
+  %33 = load ptr, ptr %5, align 8, !dbg !261
+  call void @cleanup_result(ptr noundef %33), !dbg !262
+  %34 = load i32, ptr %6, align 4, !dbg !263
+  store i32 %34, ptr %1, align 4, !dbg !264
+  br label %35, !dbg !264
+
+35:                                               ; preds = %30, %24
+  %36 = load i32, ptr %1, align 4, !dbg !265
+  ret i32 %36, !dbg !265
+}
+
+declare void @use_dot_vector(ptr noundef) #4
+
+; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
+declare void @llvm.dbg.label(metadata) #1
+
+attributes #0 = { noinline nounwind uwtable "frame-pointer"="all"   }
+attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn }
+attributes #2 = { nounwind "frame-pointer"="all" }
+attributes #3 = { nounwind allocsize(0) "frame-pointer"="all" }
+attributes #4 = { "frame-pointer"="all" }
+attributes #5 = { nounwind }
+attributes #6 = { nounwind allocsize(0) }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!16, !17, !18, !19, !20, !21, !22}
+!llvm.ident = !{!23}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Fuchsia clang version 16.0.0 (https://llvm.googlesource.com/llvm-project f85c1f3b7c0bda64aef12201e2f5bbad6028582d)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "dot.c", directory: "/usr/local/google/home/paulkirth/test/stack-frame-dump", checksumkind: CSK_MD5, checksum: "bd8ba1fe67914c5427978672a19a51d2")
+!2 = !{!3, !4, !8, !11}
+!3 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64)
+!5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Array", file: !1, line: 3, size: 128, elements: !6)
+!6 = !{!7, !10}
+!7 = !DIDerivedType(tag: DW_TAG_member, name: "data", scope: !5, file: !1, line: 4, baseType: !8, size: 64)
+!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64)
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "size", scope: !5, file: !1, line: 5, baseType: !9, size: 32, offset: 64)
+!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
+!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Result", file: !1, line: 8, size: 128, elements: !13)
+!13 = !{!14, !15}
+!14 = !DIDerivedType(tag: DW_TAG_member, name: "data", scope: !12, file: !1, line: 9, baseType: !4, size: 64)
+!15 = !DIDerivedType(tag: DW_TAG_member, name: "sum", scope: !12, file: !1, line: 10, baseType: !9, size: 32, offset: 64)
+!16 = !{i32 7, !"Dwarf Version", i32 5}
+!17 = !{i32 2, !"Debug Info Version", i32 3}
+!18 = !{i32 1, !"wchar_size", i32 4}
+!19 = !{i32 8, !"PIC Level", i32 2}
+!20 = !{i32 7, !"PIE Level", i32 2}
+!21 = !{i32 7, !"uwtable", i32 2}
+!22 = !{i32 7, !"frame-pointer", i32 2}
+!23 = !{!"Fuchsia clang version 16.0.0 (https://llvm.googlesource.com/llvm-project f85c1f3b7c0bda64aef12201e2f5bbad6028582d)"}
+!24 = distinct !DISubprogram(name: "cleanup_array", scope: !1, file: !1, line: 13, type: !25, scopeLine: 13, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !27)
+!25 = !DISubroutineType(types: !26)
+!26 = !{null, !4}
+!27 = !{}
+!28 = !DILocalVariable(name: "a", arg: 1, scope: !24, file: !1, line: 13, type: !4)
+!29 = !DILocation(line: 13, column: 34, scope: !24)
+!30 = !DILocation(line: 14, column: 8, scope: !31)
+!31 = distinct !DILexicalBlock(scope: !24, file: !1, line: 14, column: 7)
+!32 = !DILocation(line: 14, column: 7, scope: !24)
+!33 = !DILocation(line: 15, column: 5, scope: !31)
+!34 = !DILocation(line: 16, column: 8, scope: !35)
+!35 = distinct !DILexicalBlock(scope: !24, file: !1, line: 16, column: 7)
+!36 = !DILocation(line: 16, column: 11, scope: !35)
+!37 = !DILocation(line: 16, column: 7, scope: !24)
+!38 = !DILocation(line: 17, column: 5, scope: !35)
+!39 = !DILocation(line: 18, column: 8, scope: !24)
+!40 = !DILocation(line: 18, column: 11, scope: !24)
+!41 = !DILocation(line: 18, column: 3, scope: !24)
+!42 = !DILocation(line: 19, column: 1, scope: !24)
+!43 = distinct !DISubprogram(name: "cleanup_result", scope: !1, file: !1, line: 21, type: !44, scopeLine: 21, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !27)
+!44 = !DISubroutineType(types: !45)
+!45 = !{null, !11}
+!46 = !DILocalVariable(name: "res", arg: 1, scope: !43, file: !1, line: 21, type: !11)
+!47 = !DILocation(line: 21, column: 36, scope: !43)
+!48 = !DILocation(line: 22, column: 8, scope: !49)
+!49 = distinct !DILexicalBlock(scope: !43, file: !1, line: 22, column: 7)
+!50 = !DILocation(line: 22, column: 7, scope: !43)
+!51 = !DILocation(line: 23, column: 5, scope: !49)
+!52 = !DILocation(line: 24, column: 8, scope: !53)
+!53 = distinct !DILexicalBlock(scope: !43, file: !1, line: 24, column: 7)
+!54 = !DILocation(line: 24, column: 13, scope: !53)
+!55 = !DILocation(line: 24, column: 7, scope: !43)
+!56 = !DILocation(line: 25, column: 5, scope: !53)
+!57 = !DILocation(line: 26, column: 17, scope: !43)
+!58 = !DILocation(line: 26, column: 22, scope: !43)
+!59 = !DILocation(line: 26, column: 3, scope: !43)
+!60 = !DILocation(line: 27, column: 8, scope: !43)
+!61 = !DILocation(line: 27, column: 13, scope: !43)
+!62 = !DILocation(line: 27, column: 3, scope: !43)
+!63 = !DILocation(line: 28, column: 1, scope: !43)
+!64 = distinct !DISubprogram(name: "do_work", scope: !1, file: !1, line: 32, type: !65, scopeLine: 32, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !27)
+!65 = !DISubroutineType(types: !66)
+!66 = !{!9, !4, !4, !11}
+!67 = !DILocalVariable(name: "A", arg: 1, scope: !64, file: !1, line: 32, type: !4)
+!68 = !DILocation(line: 32, column: 27, scope: !64)
+!69 = !DILocalVariable(name: "B", arg: 2, scope: !64, file: !1, line: 32, type: !4)
+!70 = !DILocation(line: 32, column: 44, scope: !64)
+!71 = !DILocalVariable(name: "out", arg: 3, scope: !64, file: !1, line: 32, type: !11)
+!72 = !DILocation(line: 32, column: 62, scope: !64)
+!73 = !DILocation(line: 33, column: 8, scope: !74)
+!74 = distinct !DILexicalBlock(scope: !64, file: !1, line: 33, column: 7)
+!75 = !DILocation(line: 33, column: 10, scope: !74)
+!76 = !DILocation(line: 33, column: 14, scope: !74)
+!77 = !DILocation(line: 33, column: 7, scope: !64)
+!78 = !DILocation(line: 34, column: 5, scope: !74)
+!79 = !DILocation(line: 35, column: 7, scope: !80)
+!80 = distinct !DILexicalBlock(scope: !64, file: !1, line: 35, column: 7)
+!81 = !DILocation(line: 35, column: 10, scope: !80)
+!82 = !DILocation(line: 35, column: 18, scope: !80)
+!83 = !DILocation(line: 35, column: 21, scope: !80)
+!84 = !DILocation(line: 35, column: 15, scope: !80)
+!85 = !DILocation(line: 35, column: 7, scope: !64)
+!86 = !DILocation(line: 36, column: 5, scope: !80)
+!87 = !DILocalVariable(name: "len", scope: !64, file: !1, line: 37, type: !88)
+!88 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !9)
+!89 = !DILocation(line: 37, column: 13, scope: !64)
+!90 = !DILocation(line: 37, column: 19, scope: !64)
+!91 = !DILocation(line: 37, column: 22, scope: !64)
+!92 = !DILocalVariable(name: "AB", scope: !64, file: !1, line: 38, type: !4)
+!93 = !DILocation(line: 38, column: 17, scope: !64)
+!94 = !DILocation(line: 39, column: 7, scope: !95)
+!95 = distinct !DILexicalBlock(scope: !64, file: !1, line: 39, column: 7)
+!96 = !DILocation(line: 39, column: 12, scope: !95)
+!97 = !DILocation(line: 39, column: 17, scope: !95)
+!98 = !DILocation(line: 39, column: 7, scope: !64)
+!99 = !DILocation(line: 40, column: 26, scope: !100)
+!100 = distinct !DILexicalBlock(scope: !95, file: !1, line: 39, column: 26)
+!101 = !DILocation(line: 40, column: 8, scope: !100)
+!102 = !DILocation(line: 41, column: 5, scope: !100)
+!103 = !DILocation(line: 41, column: 9, scope: !100)
+!104 = !DILocation(line: 41, column: 14, scope: !100)
+!105 = !DILocation(line: 42, column: 5, scope: !100)
+!106 = !DILocation(line: 42, column: 9, scope: !100)
+!107 = !DILocation(line: 42, column: 14, scope: !100)
+!108 = !DILocation(line: 43, column: 17, scope: !100)
+!109 = !DILocation(line: 43, column: 5, scope: !100)
+!110 = !DILocation(line: 43, column: 10, scope: !100)
+!111 = !DILocation(line: 43, column: 15, scope: !100)
+!112 = !DILocation(line: 44, column: 3, scope: !100)
+!113 = !DILocation(line: 45, column: 10, scope: !114)
+!114 = distinct !DILexicalBlock(scope: !95, file: !1, line: 44, column: 10)
+!115 = !DILocation(line: 45, column: 15, scope: !114)
+!116 = !DILocation(line: 45, column: 8, scope: !114)
+!117 = !DILocation(line: 48, column: 7, scope: !118)
+!118 = distinct !DILexicalBlock(scope: !64, file: !1, line: 48, column: 7)
+!119 = !DILocation(line: 48, column: 11, scope: !118)
+!120 = !DILocation(line: 48, column: 7, scope: !64)
+!121 = !DILocation(line: 49, column: 10, scope: !118)
+!122 = !DILocation(line: 49, column: 14, scope: !118)
+!123 = !DILocation(line: 49, column: 5, scope: !118)
+!124 = !DILocation(line: 51, column: 28, scope: !64)
+!125 = !DILocation(line: 51, column: 32, scope: !64)
+!126 = !DILocation(line: 51, column: 21, scope: !64)
+!127 = !DILocation(line: 51, column: 3, scope: !64)
+!128 = !DILocation(line: 51, column: 7, scope: !64)
+!129 = !DILocation(line: 51, column: 12, scope: !64)
+!130 = !DILocation(line: 52, column: 14, scope: !64)
+!131 = !DILocation(line: 52, column: 3, scope: !64)
+!132 = !DILocation(line: 52, column: 7, scope: !64)
+!133 = !DILocation(line: 52, column: 12, scope: !64)
+!134 = !DILocalVariable(name: "sum", scope: !64, file: !1, line: 54, type: !9)
+!135 = !DILocation(line: 54, column: 7, scope: !64)
+!136 = !DILocalVariable(name: "i", scope: !137, file: !1, line: 55, type: !9)
+!137 = distinct !DILexicalBlock(scope: !64, file: !1, line: 55, column: 3)
+!138 = !DILocation(line: 55, column: 12, scope: !137)
+!139 = !DILocation(line: 55, column: 8, scope: !137)
+!140 = !DILocation(line: 55, column: 19, scope: !141)
+!141 = distinct !DILexicalBlock(scope: !137, file: !1, line: 55, column: 3)
+!142 = !DILocation(line: 55, column: 23, scope: !141)
+!143 = !DILocation(line: 55, column: 21, scope: !141)
+!144 = !DILocation(line: 55, column: 3, scope: !137)
+!145 = !DILocation(line: 56, column: 19, scope: !146)
+!146 = distinct !DILexicalBlock(scope: !141, file: !1, line: 55, column: 33)
+!147 = !DILocation(line: 56, column: 22, scope: !146)
+!148 = !DILocation(line: 56, column: 27, scope: !146)
+!149 = !DILocation(line: 56, column: 32, scope: !146)
+!150 = !DILocation(line: 56, column: 35, scope: !146)
+!151 = !DILocation(line: 56, column: 40, scope: !146)
+!152 = !DILocation(line: 56, column: 30, scope: !146)
+!153 = !DILocation(line: 56, column: 5, scope: !146)
+!154 = !DILocation(line: 56, column: 9, scope: !146)
+!155 = !DILocation(line: 56, column: 14, scope: !146)
+!156 = !DILocation(line: 56, column: 17, scope: !146)
+!157 = !DILocation(line: 57, column: 12, scope: !146)
+!158 = !DILocation(line: 57, column: 16, scope: !146)
+!159 = !DILocation(line: 57, column: 21, scope: !146)
+!160 = !DILocation(line: 57, column: 9, scope: !146)
+!161 = !DILocation(line: 58, column: 3, scope: !146)
+!162 = !DILocation(line: 55, column: 28, scope: !141)
+!163 = !DILocation(line: 55, column: 3, scope: !141)
+!164 = distinct !{!164, !144, !165, !166}
+!165 = !DILocation(line: 58, column: 3, scope: !137)
+!166 = !{!"llvm.loop.mustprogress"}
+!167 = !DILocation(line: 59, column: 3, scope: !64)
+!168 = !DILocation(line: 60, column: 1, scope: !64)
+!169 = distinct !DISubprogram(name: "gen_array", scope: !1, file: !1, line: 62, type: !170, scopeLine: 62, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !27)
+!170 = !DISubroutineType(types: !171)
+!171 = !{!4, !9}
+!172 = !DILocalVariable(name: "size", arg: 1, scope: !169, file: !1, line: 62, type: !9)
+!173 = !DILocation(line: 62, column: 29, scope: !169)
+!174 = !DILocation(line: 63, column: 7, scope: !175)
+!175 = distinct !DILexicalBlock(scope: !169, file: !1, line: 63, column: 7)
+!176 = !DILocation(line: 63, column: 12, scope: !175)
+!177 = !DILocation(line: 63, column: 7, scope: !169)
+!178 = !DILocation(line: 64, column: 5, scope: !175)
+!179 = !DILocalVariable(name: "res", scope: !169, file: !1, line: 65, type: !4)
+!180 = !DILocation(line: 65, column: 17, scope: !169)
+!181 = !DILocation(line: 65, column: 39, scope: !169)
+!182 = !DILocation(line: 66, column: 15, scope: !169)
+!183 = !DILocation(line: 66, column: 3, scope: !169)
+!184 = !DILocation(line: 66, column: 8, scope: !169)
+!185 = !DILocation(line: 66, column: 13, scope: !169)
+!186 = !DILocation(line: 67, column: 29, scope: !169)
+!187 = !DILocation(line: 67, column: 34, scope: !169)
+!188 = !DILocation(line: 67, column: 22, scope: !169)
+!189 = !DILocation(line: 67, column: 3, scope: !169)
+!190 = !DILocation(line: 67, column: 8, scope: !169)
+!191 = !DILocation(line: 67, column: 13, scope: !169)
+!192 = !DILocalVariable(name: "i", scope: !193, file: !1, line: 69, type: !9)
+!193 = distinct !DILexicalBlock(scope: !169, file: !1, line: 69, column: 3)
+!194 = !DILocation(line: 69, column: 12, scope: !193)
+!195 = !DILocation(line: 69, column: 8, scope: !193)
+!196 = !DILocation(line: 69, column: 19, scope: !197)
+!197 = distinct !DILexicalBlock(scope: !193, file: !1, line: 69, column: 3)
+!198 = !DILocation(line: 69, column: 23, scope: !197)
+!199 = !DILocation(line: 69, column: 21, scope: !197)
+!200 = !DILocation(line: 69, column: 3, scope: !193)
+!201 = !DILocation(line: 70, column: 20, scope: !202)
+!202 = distinct !DILexicalBlock(scope: !197, file: !1, line: 69, column: 34)
+!203 = !DILocation(line: 70, column: 5, scope: !202)
+!204 = !DILocation(line: 70, column: 10, scope: !202)
+!205 = !DILocation(line: 70, column: 15, scope: !202)
+!206 = !DILocation(line: 70, column: 18, scope: !202)
+!207 = !DILocation(line: 71, column: 3, scope: !202)
+!208 = !DILocation(line: 69, column: 29, scope: !197)
+!209 = !DILocation(line: 69, column: 3, scope: !197)
+!210 = distinct !{!210, !200, !211, !166}
+!211 = !DILocation(line: 71, column: 3, scope: !193)
+!212 = !DILocation(line: 73, column: 10, scope: !169)
+!213 = !DILocation(line: 73, column: 3, scope: !169)
+!214 = !DILocation(line: 74, column: 1, scope: !169)
+!215 = distinct !DISubprogram(name: "caller", scope: !1, file: !1, line: 76, type: !216, scopeLine: 76, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !27)
+!216 = !DISubroutineType(types: !217)
+!217 = !{!9}
+!218 = !DILocalVariable(name: "size", scope: !215, file: !1, line: 77, type: !88)
+!219 = !DILocation(line: 77, column: 13, scope: !215)
+!220 = !DILocalVariable(name: "A", scope: !215, file: !1, line: 78, type: !4)
+!221 = !DILocation(line: 78, column: 17, scope: !215)
+!222 = !DILocation(line: 78, column: 21, scope: !215)
+!223 = !DILocalVariable(name: "B", scope: !215, file: !1, line: 79, type: !4)
+!224 = !DILocation(line: 79, column: 17, scope: !215)
+!225 = !DILocation(line: 79, column: 21, scope: !215)
+!226 = !DILocalVariable(name: "res", scope: !215, file: !1, line: 80, type: !11)
+!227 = !DILocation(line: 80, column: 18, scope: !215)
+!228 = !DILocation(line: 80, column: 41, scope: !215)
+!229 = !DILocalVariable(name: "ret", scope: !215, file: !1, line: 81, type: !9)
+!230 = !DILocation(line: 81, column: 7, scope: !215)
+!231 = !DILocalVariable(name: "err", scope: !215, file: !1, line: 83, type: !9)
+!232 = !DILocation(line: 83, column: 7, scope: !215)
+!233 = !DILocation(line: 83, column: 21, scope: !215)
+!234 = !DILocation(line: 83, column: 24, scope: !215)
+!235 = !DILocation(line: 83, column: 27, scope: !215)
+!236 = !DILocation(line: 83, column: 13, scope: !215)
+!237 = !DILocation(line: 84, column: 7, scope: !238)
+!238 = distinct !DILexicalBlock(scope: !215, file: !1, line: 84, column: 7)
+!239 = !DILocation(line: 84, column: 11, scope: !238)
+!240 = !DILocation(line: 84, column: 7, scope: !215)
+!241 = !DILocation(line: 85, column: 5, scope: !242)
+!242 = distinct !DILexicalBlock(scope: !238, file: !1, line: 84, column: 18)
+!243 = !DILocation(line: 88, column: 9, scope: !215)
+!244 = !DILocation(line: 88, column: 14, scope: !215)
+!245 = !DILocation(line: 88, column: 7, scope: !215)
+!246 = !DILocation(line: 89, column: 7, scope: !247)
+!247 = distinct !DILexicalBlock(scope: !215, file: !1, line: 89, column: 7)
+!248 = !DILocation(line: 89, column: 11, scope: !247)
+!249 = !DILocation(line: 89, column: 7, scope: !215)
+!250 = !DILocation(line: 90, column: 12, scope: !247)
+!251 = !DILocation(line: 90, column: 5, scope: !247)
+!252 = !DILocation(line: 92, column: 18, scope: !215)
+!253 = !DILocation(line: 92, column: 23, scope: !215)
+!254 = !DILocation(line: 92, column: 3, scope: !215)
+!255 = !DILabel(scope: !215, name: "cleanup", file: !1, line: 94)
+!256 = !DILocation(line: 94, column: 1, scope: !215)
+!257 = !DILocation(line: 95, column: 17, scope: !215)
+!258 = !DILocation(line: 95, column: 3, scope: !215)
+!259 = !DILocation(line: 96, column: 17, scope: !215)
+!260 = !DILocation(line: 96, column: 3, scope: !215)
+!261 = !DILocation(line: 97, column: 18, scope: !215)
+!262 = !DILocation(line: 97, column: 3, scope: !215)
+!263 = !DILocation(line: 99, column: 10, scope: !215)
+!264 = !DILocation(line: 99, column: 3, scope: !215)
+!265 = !DILocation(line: 100, column: 1, scope: !215)
Index: llvm/test/CodeGen/X86/stack-frame-printer.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/X86/stack-frame-printer.ll
@@ -0,0 +1,107 @@
+; Test basic output of the -print-stack-frame pass
+
+; RUN: llc -mcpu=corei7 -O1 -print-stack-frame < %s 2>&1 >/dev/null | FileCheck %s
+; RUN: llc -mcpu=corei7 -O0 -print-stack-frame < %s 2>&1 >/dev/null | FileCheck %s --check-prefix=NO_COLORING
+
+
+; CHECK: Offset{{.*}}Align{{.*}}Size
+; CHECK: [SP-88]{{.*}}16{{.*}}80
+; CHECK:    buffer @ frame-diags.c:30
+; NO_COLORING: [SP-168]{{.*}}16{{.*}}80
+; CHECK:    buffer2 @ frame-diags.c:33
+
+; ModuleID = 'frame-diags.c'
+source_filename = "frame-diags.c"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind uwtable
+define dso_local void @stackSizeWarning() local_unnamed_addr #0 !dbg !9 {
+entry:
+  %buffer = alloca [80 x i8], align 16
+  %buffer2 = alloca [80 x i8], align 16
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %buffer) #5, !dbg !24
+  call void @llvm.dbg.declare(metadata ptr %buffer, metadata !13, metadata !DIExpression()), !dbg !25
+  call void @doIt(ptr noundef nonnull %buffer) #5, !dbg !26
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %buffer) #5, !dbg !27
+  call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %buffer2) #5, !dbg !28
+  call void @llvm.dbg.declare(metadata ptr %buffer2, metadata !19, metadata !DIExpression()), !dbg !29
+  call void @llvm.dbg.value(metadata i32 0, metadata !20, metadata !DIExpression()), !dbg !30
+  call void @llvm.dbg.value(metadata i64 1, metadata !22, metadata !DIExpression()), !dbg !30
+  call void @doIt(ptr noundef nonnull %buffer2) #5, !dbg !31
+  %call = call i32 @getNum(i64 noundef 0) #5, !dbg !32
+  %call2 = call i32 @getNum(i64 noundef 1) #5, !dbg !33
+  call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %buffer2) #5, !dbg !34
+  ret void, !dbg !34
+}
+
+; Function Attrs: argmemonly mustprogress nocallback nofree nosync nounwind willreturn
+declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #2
+
+declare !dbg !35 void @doIt(ptr noundef) local_unnamed_addr #3
+
+; Function Attrs: argmemonly mustprogress nocallback nofree nosync nounwind willreturn
+declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1
+
+declare !dbg !40 i32 @getNum(i64 noundef) local_unnamed_addr #3
+
+; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
+declare void @llvm.dbg.value(metadata, metadata, metadata) #4
+
+attributes #0 = { nounwind uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #1 = { argmemonly mustprogress nocallback nofree nosync nounwind willreturn }
+attributes #2 = { mustprogress nocallback nofree nosync nounwind readnone speculatable willreturn }
+attributes #3 = { "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #4 = { nocallback nofree nosync nounwind readnone speculatable willreturn }
+attributes #5 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5, !6, !7}
+!llvm.ident = !{!8}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Fuchsia clang version 16.0.0 (g...@github.com:llvm/llvm-project.git bb51a99e67747be81c9b523fd5ddcc8bf91a1ffb)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "frame-diags.c", directory: "/usr/local/google/home/paulkirth/llvm-sysroot/clang/test/Frontend", checksumkind: CSK_MD5, checksum: "01b5d69ce5387b02de2d1191b28a0b7f")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 8, !"PIC Level", i32 2}
+!6 = !{i32 7, !"PIE Level", i32 2}
+!7 = !{i32 7, !"uwtable", i32 2}
+!8 = !{!"Fuchsia clang version 16.0.0 (g...@github.com:llvm/llvm-project.git bb51a99e67747be81c9b523fd5ddcc8bf91a1ffb)"}
+!9 = distinct !DISubprogram(name: "stackSizeWarning", scope: !1, file: !1, line: 28, type: !10, scopeLine: 28, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+!10 = !DISubroutineType(types: !11)
+!11 = !{null}
+!12 = !{!13, !19, !20, !22}
+!13 = !DILocalVariable(name: "buffer", scope: !14, file: !1, line: 30, type: !15)
+!14 = distinct !DILexicalBlock(scope: !9, file: !1, line: 29, column: 3)
+!15 = !DICompositeType(tag: DW_TAG_array_type, baseType: !16, size: 640, elements: !17)
+!16 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!17 = !{!18}
+!18 = !DISubrange(count: 80)
+!19 = !DILocalVariable(name: "buffer2", scope: !9, file: !1, line: 33, type: !15)
+!20 = !DILocalVariable(name: "a", scope: !9, file: !1, line: 34, type: !21)
+!21 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!22 = !DILocalVariable(name: "b", scope: !9, file: !1, line: 35, type: !23)
+!23 = !DIBasicType(name: "long", size: 64, encoding: DW_ATE_signed)
+!24 = !DILocation(line: 30, column: 5, scope: !14)
+!25 = !DILocation(line: 30, column: 10, scope: !14)
+!26 = !DILocation(line: 31, column: 5, scope: !14)
+!27 = !DILocation(line: 32, column: 3, scope: !9)
+!28 = !DILocation(line: 33, column: 3, scope: !9)
+!29 = !DILocation(line: 33, column: 8, scope: !9)
+!30 = !DILocation(line: 0, scope: !9)
+!31 = !DILocation(line: 36, column: 3, scope: !9)
+!32 = !DILocation(line: 38, column: 3, scope: !9)
+!33 = !DILocation(line: 39, column: 3, scope: !9)
+!34 = !DILocation(line: 40, column: 1, scope: !9)
+!35 = !DISubprogram(name: "doIt", scope: !1, file: !1, line: 21, type: !36, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !39)
+!36 = !DISubroutineType(types: !37)
+!37 = !{null, !38}
+!38 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !16, size: 64)
+!39 = !{}
+!40 = !DISubprogram(name: "getNum", scope: !1, file: !1, line: 23, type: !41, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !39)
+!41 = !DISubroutineType(types: !42)
+!42 = !{!21, !23}
Index: llvm/lib/CodeGen/TargetPassConfig.cpp
===================================================================
--- llvm/lib/CodeGen/TargetPassConfig.cpp
+++ llvm/lib/CodeGen/TargetPassConfig.cpp
@@ -159,6 +159,10 @@
     PrintAfterISel("print-after-isel", cl::init(false), cl::Hidden,
                    cl::desc("Print machine instrs after ISel"));
 
+static cl::opt<bool>
+    PrintStackFrame("print-stack-frame", cl::init(false), cl::Hidden,
+                   cl::desc("Print Stack Frame"));
+
 static cl::opt<GlobalISelAbortMode> EnableGlobalISelAbort(
     "global-isel-abort", cl::Hidden,
     cl::desc("Enable abort calls when \"global\" instruction selection "
@@ -1297,6 +1301,9 @@
   if (!DisableCFIFixup && TM->Options.EnableCFIFixup)
     addPass(createCFIFixup());
 
+  if(PrintStackFrame)
+    PM->add(createStackFramePrinterPass(dbgs(), "Stack Layout"));
+
   // Add passes that directly emit MI after all other MI passes.
   addPreEmitPass2();
 
Index: llvm/lib/CodeGen/StackFramePrinterPass.cpp
===================================================================
--- /dev/null
+++ llvm/lib/CodeGen/StackFramePrinterPass.cpp
@@ -0,0 +1,254 @@
+//===-- MachineFunctionPrinterPass.cpp ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// StackFramePrinterPass implementation. Prints a textual representation of
+// the stack frame. When possible it prints the values that occupy a stack slot
+// using any available debug information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/SlotIndexes.h"
+#include "llvm/CodeGen/TargetFrameLowering.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/PrintPasses.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <iomanip>
+#include <sstream>
+
+using namespace llvm;
+
+namespace {
+
+constexpr int OffsetWidth = 4 + 7;
+constexpr int SpillWidth = 5;
+constexpr int AlignWidth = 9;
+constexpr int SizeWidth = 10;
+
+constexpr size_t MaxLine =
+    std::min(75, OffsetWidth + SpillWidth + AlignWidth + SizeWidth + 3);
+
+/// StackFramePrinterPass - This is a pass to dump the stack frame of a
+/// MachineFunction.
+///
+struct StackFramePrinterPass : public MachineFunctionPass {
+  using SlotDbgMap =
+      SmallDenseMap<int, SmallPtrSet<const DILocalVariable *, 4>>;
+  static char ID;
+
+  raw_ostream &OS;
+  const std::string Banner;
+
+  struct SlotData {
+    int Slot;
+    int Size;
+    int Align;
+    int Offset;
+    bool IsSpillSlot;
+    bool Fixed;
+  };
+
+  StackFramePrinterPass() : MachineFunctionPass(ID), OS(dbgs()) {}
+  StackFramePrinterPass(raw_ostream &OS, const std::string &Banner)
+      : MachineFunctionPass(ID), OS(OS), Banner(Banner) {}
+
+  StringRef getPassName() const override { return "StackFrame Printer"; }
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.setPreservesAll();
+    MachineFunctionPass::getAnalysisUsage(AU);
+  }
+
+  bool runOnMachineFunction(MachineFunction &MF) override {
+    if (!isFunctionInPrintList(MF.getName()))
+      return false;
+
+    OS << "# " << Banner << ": " << MF.getName() << "\n";
+
+    auto SlotMap = genSlotDbgMapping(MF);
+    printFrame(MF, OS, SlotMap);
+
+    return false;
+  }
+
+  std::string genFieldInt(int Width, int I) const {
+    std::stringstream SS;
+    SS.setf(std::ios_base::left);
+    SS << std::setw(Width) << I;
+    return SS.str();
+  }
+
+  std::string genFieldString(int Width, std::string S) const {
+    std::stringstream SS;
+    SS.setf(std::ios_base::left);
+    SS << std::setw(Width) << S;
+    return SS.str();
+  }
+
+  std::string genFieldOffset(int I) const {
+    std::stringstream SS;
+    SS.setf(std::ios_base::left);
+    SS << "[SP";
+    const auto *Op = (I < 0) ? "" : "+";
+    SS << Op << I << "]";
+    return SS.str();
+  }
+
+  std::string genBody(int Idx, SlotData &D) const {
+    std::stringstream SS;
+    SS.setf(std::ios_base::left);
+
+    SS << std::setw(OffsetWidth) << genFieldOffset(D.Offset) << " ";
+    SS << genFieldString(SpillWidth, D.IsSpillSlot ? "Spill" : "") << " ";
+    SS << genFieldInt(AlignWidth, D.Align) << " ";
+    SS << genFieldInt(SizeWidth, D.Size);
+    return SS.str();
+  };
+
+  std::string genHeader() const {
+    std::stringstream SS;
+    SS.setf(std::ios_base::left);
+    SS << genFieldString(OffsetWidth, "Offset") << " ";
+    SS << genFieldString(SpillWidth, "") << " ";
+    SS << genFieldString(AlignWidth, "Align") << " ";
+    SS << genFieldString(SizeWidth, "Size");
+    return SS.str();
+  };
+
+  void printSourceLoc(raw_ostream &OS, const llvm::DILocalVariable *N) const {
+    OS << "    " << N->getName().str() << " @ " << N->getFilename() << ":"
+       << N->getLine();
+    OS << "\n";
+  }
+
+  void printRow(raw_ostream &OS, std::string S) const {
+    std::stringstream SS;
+    SS.setf(std::ios_base::left);
+    SS << std::setw(MaxLine) << S;
+    OS << " " << SS.str() << " \n";
+  };
+
+  void printFrame(const MachineFunction &MF, raw_ostream &OS,
+                  SlotDbgMap &SlotMap) const {
+    auto &MFI = MF.getFrameInfo();
+
+    if (!MFI.hasStackObjects())
+      return;
+
+    const TargetFrameLowering *FI = MF.getSubtarget().getFrameLowering();
+    int ValOffset = (FI ? FI->getOffsetOfLocalArea() : 0);
+
+    std::vector<SlotData> SlotInfo;
+    SmallDenseMap<int, int> SlotOffsetMap;
+    auto NumObj = MFI.getNumObjects();
+    auto ObjBeg = MFI.getObjectIndexBegin();
+    auto ObjEnd = MFI.getObjectIndexEnd();
+    int NumFixed = MFI.getNumFixedObjects();
+
+    SlotInfo.reserve(NumObj);
+    SlotOffsetMap.reserve(NumObj);
+    // initialize slot info
+    for (auto Idx = ObjBeg, EndIdx = ObjEnd; Idx != EndIdx; ++Idx) {
+      SlotData D;
+      uint64_t Size = MFI.getObjectSize(Idx);
+
+      // This is a dead slot, so skip it
+      if (Size == ~0ULL) {
+        continue;
+      }
+
+      D.Slot = (int)(Idx);
+      // If Size == 0, then its a variable size object...
+      D.Size = Size;
+      D.Align = MFI.getObjectAlign(Idx).value();
+      D.Fixed = (Idx < NumFixed);
+      D.IsSpillSlot = MFI.isSpillSlotObjectIndex(Idx);
+      D.Offset = MFI.getObjectOffset(Idx) - ValOffset;
+      SlotInfo.push_back(D);
+      SlotOffsetMap[D.Slot] = D.Offset;
+    }
+
+    // sort the ordering, to match the actual layout in memory
+    std::sort(SlotInfo.begin(), SlotInfo.end(),
+              [](SlotData &A, SlotData &B) { return A.Offset > B.Offset; });
+
+    printRow(OS, genHeader());
+
+    int Idx = 0;
+    for (auto L : SlotInfo) {
+      std::stringstream SS;
+      auto Body = genBody(Idx++, L);
+      printRow(OS, Body);
+      for (auto *N : SlotMap[L.Slot])
+        printSourceLoc(OS, N);
+    }
+    OS << "\n";
+  }
+
+  // We need to generate a mapping of slots to the values that are stored to
+  // them This infomation is lost by the time we need to print out the frame, so
+  // we reconstruct it here by walking the CFG, and generating the mapping.
+  SlotDbgMap genSlotDbgMapping(MachineFunction &MF) {
+    SlotDbgMap SlotDebugMap;
+    SmallVector<MachineInstr *> Dbg;
+
+    // add variables to the map
+    for (auto &DI : MF.getVariableDbgInfo()) {
+      SlotDebugMap[DI.Slot].insert(DI.Var);
+    }
+
+    // Then add all the spills that have debug data
+    for (auto &MBB : MF) {
+      for (auto &MI : MBB) {
+        if (MI.getNumMemOperands() == 0)
+          continue;
+        for (MachineMemOperand *MO : MI.memoperands()) {
+          if (!MO->isStore())
+            continue;
+          auto *FI = dyn_cast_or_null<FixedStackPseudoSourceValue>(
+              MO->getPseudoValue());
+          if (!FI)
+            continue;
+          auto FrameIdx = FI->getFrameIndex();
+          Dbg.clear();
+          MI.collectDebugValues(Dbg);
+
+          for (auto *MI : Dbg)
+            SlotDebugMap[FrameIdx].insert(MI->getDebugVariable());
+        }
+      }
+    }
+
+    return SlotDebugMap;
+  }
+};
+
+char StackFramePrinterPass::ID = 0;
+} // namespace
+
+char &llvm::StackFramePrinterPassID = StackFramePrinterPass::ID;
+INITIALIZE_PASS(StackFramePrinterPass, "stackframe-printer",
+                "Stack Frame Printer", false, false)
+
+namespace llvm {
+/// Returns a newly-created MachineFunction Printer pass. The
+/// default banner is empty.
+///
+MachineFunctionPass *createStackFramePrinterPass(raw_ostream &OS,
+                                                 const std::string &Banner) {
+  return new StackFramePrinterPass(OS, Banner);
+}
+
+} // namespace llvm
Index: llvm/lib/CodeGen/PrologEpilogInserter.cpp
===================================================================
--- llvm/lib/CodeGen/PrologEpilogInserter.cpp
+++ llvm/lib/CodeGen/PrologEpilogInserter.cpp
@@ -51,6 +51,7 @@
 #include "llvm/IR/Function.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/ModuleSlotTracker.h"
 #include "llvm/InitializePasses.h"
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/Pass.h"
@@ -289,6 +290,9 @@
   if (StackSize > Threshold) {
     DiagnosticInfoStackSize DiagStackSize(F, StackSize, Threshold, DS_Warning);
     F.getContext().diagnose(DiagStackSize);
+    //TODO: print stats here about stack usage:
+    //   How much total memory
+    //   What % are locals vs spills
   }
   ORE->emit([&]() {
     return MachineOptimizationRemarkAnalysis(DEBUG_TYPE, "StackSize",
Index: llvm/lib/CodeGen/MachineFrameInfo.cpp
===================================================================
--- llvm/lib/CodeGen/MachineFrameInfo.cpp
+++ llvm/lib/CodeGen/MachineFrameInfo.cpp
@@ -20,9 +20,12 @@
 #include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/Config/llvm-config.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
+#include <iomanip>
+#include <sstream>
 
 #define DEBUG_TYPE "codegen"
 
Index: llvm/lib/CodeGen/CodeGen.cpp
===================================================================
--- llvm/lib/CodeGen/CodeGen.cpp
+++ llvm/lib/CodeGen/CodeGen.cpp
@@ -115,6 +115,7 @@
   initializeSjLjEHPreparePass(Registry);
   initializeSlotIndexesPass(Registry);
   initializeStackColoringPass(Registry);
+  initializeStackFramePrinterPassPass(Registry);
   initializeStackMapLivenessPass(Registry);
   initializeStackProtectorPass(Registry);
   initializeStackSlotColoringPass(Registry);
Index: llvm/lib/CodeGen/CMakeLists.txt
===================================================================
--- llvm/lib/CodeGen/CMakeLists.txt
+++ llvm/lib/CodeGen/CMakeLists.txt
@@ -207,6 +207,7 @@
   SpillPlacement.cpp
   SplitKit.cpp
   StackColoring.cpp
+  StackFramePrinterPass.cpp
   StackMapLivenessAnalysis.cpp
   StackMaps.cpp
   StackProtector.cpp
Index: llvm/include/llvm/InitializePasses.h
===================================================================
--- llvm/include/llvm/InitializePasses.h
+++ llvm/include/llvm/InitializePasses.h
@@ -402,6 +402,7 @@
 void initializeSpeculativeExecutionLegacyPassPass(PassRegistry&);
 void initializeSpillPlacementPass(PassRegistry&);
 void initializeStackColoringPass(PassRegistry&);
+void initializeStackFramePrinterPassPass(PassRegistry&);
 void initializeStackMapLivenessPass(PassRegistry&);
 void initializeStackProtectorPass(PassRegistry&);
 void initializeStackSafetyGlobalInfoWrapperPassPass(PassRegistry &);
Index: llvm/include/llvm/CodeGen/Passes.h
===================================================================
--- llvm/include/llvm/CodeGen/Passes.h
+++ llvm/include/llvm/CodeGen/Passes.h
@@ -63,6 +63,12 @@
   createMachineFunctionPrinterPass(raw_ostream &OS,
                                    const std::string &Banner ="");
 
+  /// StackFramePrinter pass - This pass prints out the machine function's
+  /// stack frame to the given stream as a debugging tool.
+  MachineFunctionPass *
+  createStackFramePrinterPass(raw_ostream &OS,
+                                   const std::string &Banner ="");
+
   /// MIRPrinting pass - this pass prints out the LLVM IR into the given stream
   /// using the MIR serialization format.
   MachineFunctionPass *createPrintMIRPass(raw_ostream &OS);
@@ -260,6 +266,10 @@
   /// It merges disjoint allocas to reduce the stack size.
   extern char &StackColoringID;
 
+  /// StackFramePrinter - This pass prints the stack frame layout and variable 
+  /// mappings.
+  extern char &StackFramePrinterPassID;
+
   /// IfConverter - This pass performs machine code if conversion.
   extern char &IfConverterID;
 
Index: llvm/include/llvm/CodeGen/MachineFrameInfo.h
===================================================================
--- llvm/include/llvm/CodeGen/MachineFrameInfo.h
+++ llvm/include/llvm/CodeGen/MachineFrameInfo.h
@@ -14,6 +14,7 @@
 #define LLVM_CODEGEN_MACHINEFRAMEINFO_H
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/Register.h"
 #include "llvm/Support/Alignment.h"
 #include <cassert>
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to