1; RUN: llc -mtriple=hexagon-unknown--elf -hexagon-initial-cfg-cleanup=false < %s | FileCheck %s 2; RUN: llc -mtriple=hexagon-unknown--elf -hexagon-initial-cfg-cleanup=false -mattr=+noreturn-stack-elim < %s | FileCheck %s --check-prefix=CHECK-FLAG 3 4; Test the noreturn stack elimination feature. We've added a new flag/feature 5; that attempts to eliminate the local stack for noreturn nounwind functions. 6; The optimization eliminates the need to save callee saved registers, and 7; eliminates the allocframe, when no local stack space is needed. 8 9%struct.A = type { i32, i32 } 10 11; Test the case when noreturn-stack-elim determins that both callee saved 12; register do not need to be saved, and the allocframe can be eliminated. 13 14; CHECK-LABEL: test1 15; CHECK: memd(r29+#-16) = r17:16 16; CHECK: allocframe 17 18; CHECK-FLAG-LABEL: test1 19; CHECK-FLAG-NOT: memd(r29+#-16) = r17:16 20; CHECK-FLAG-NOT: allocframe 21 22define dso_local void @test1(i32 %a, ptr %b) local_unnamed_addr #0 { 23entry: 24 store i32 %a, ptr %b, align 4 25 tail call void @f1() #3 26 tail call void @nrf1(ptr %b) #4 27 unreachable 28} 29 30; Test that noreturn-stack-elim doesn't eliminate the local stack, when 31; a function needs to allocate a local variable. 32 33; CHECK-LABEL: test2 34; CHECK: allocframe 35 36; CHECK-FLAG-LABEL: test2 37; CHECK-FLAG: allocframe 38 39define dso_local void @test2() local_unnamed_addr #0 { 40entry: 41 %a = alloca i32, align 4 42 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %a) #4 43 call void @f3(ptr nonnull %a) #4 44 unreachable 45} 46 47; Test that noreturn-stack-elim can elimnate the allocframe when no locals 48; are allocated on the stack. 49 50; CHECK-LABEL: test3 51; CHECK: allocframe 52 53; CHECK-FLAG-LABEL: test3 54; CHECK-FLAG-NOT: allocframe 55 56define dso_local void @test3(i32 %a) local_unnamed_addr #0 { 57entry: 58 %add = add nsw i32 %a, 5 59 call void @f2(i32 %add) 60 unreachable 61} 62 63; Test that nothing is optimized when an alloca is needed for local stack. 64 65; CHECK-LABEL: test4 66; CHECK: allocframe 67 68; CHECK-FLAG-LABEL: test4 69; CHECK-FLAG: allocframe 70 71define dso_local void @test4(i32 %n) local_unnamed_addr #0 { 72entry: 73 %vla = alloca i32, i32 %n, align 8 74 call void @f3(ptr nonnull %vla) #4 75 unreachable 76} 77 78 79declare dso_local void @f1() local_unnamed_addr 80declare dso_local void @f2(i32) local_unnamed_addr 81declare dso_local void @f3(ptr) local_unnamed_addr 82 83declare dso_local void @nrf1(ptr) local_unnamed_addr #2 84 85declare void @llvm.lifetime.start.p0(i64, ptr nocapture) #5 86 87attributes #0 = { noreturn nounwind } 88attributes #2 = { noreturn } 89attributes #3 = { nounwind } 90attributes #4 = { noreturn nounwind } 91attributes #5 = { argmemonly nounwind } 92 93