Index: llvm/test/CodeGen/AArch64/shrinkwrap-split-restore-point.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/shrinkwrap-split-restore-point.ll @@ -0,0 +1,192 @@ +; RUN: llc -mtriple=aarch64 < %s | FileCheck %s + +define void @shrink_test1(i32 %a) { +; CHECK-LABEL: shrink_test1: +; CHECK-LABEL: %bb.0: +; CHECK: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK: cmp w0, #1 +; CHECK: b.lt .LBB0_2 +; CHECK-LABEL: .LBB0_2: +; CHECK: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-LABEL: .LBB0_3: +; CHECK: ldr x30, [sp], #16 // 8-byte Folded Reload + +entry: + %cmp5 = icmp sgt i32 %a, 0 + br i1 %cmp5, label %BB0, label %exit + +BB0: + %call = call i32 @fun() + %c = icmp eq i32 %call, 0 + br i1 %c, label %BB1, label %exit + +BB1: + %call2 = call i32 @fun() + br label %exit + +exit: + ret void +} + +define void @shrink_test2(i32 %a, ptr %P1, ptr %P2) { +; CHECK-LABEL: shrink_test2: +; CHECK-LABEL: %bb.0: +; CHECK: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK: cmp w0, #1 +; CHECK: b.lt .LBB1_5 +; CHECK-LABEL: .LBB1_5: +; CHECK: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-LABEL: .LBB1_8: +; CHECK: ldr x30, [sp], #16 // 8-byte Folded Reload + +BB00: + %cmp5 = icmp sgt i32 %a, 0 + br i1 %cmp5, label %BB01, label %exit + +BB01: + store i32 %a, ptr %P1 + %c1 = icmp sgt i32 %a, 1 + br i1 %c1, label %BB02, label %BB03 + +BB02: + store i32 %a, ptr %P2 + br label %BB03 + +BB03: + %call03 = call i32 @fun() + %c03 = icmp eq i32 %call03, 0 + br i1 %c03, label %BB04, label %BB05 + +BB04: + %call04 = call i32 @fun() + br label %BB05 + +BB05: + %call05 = call i32 @fun() + %c05 = icmp eq i32 %call05, 0 + br i1 %c05, label %BB06, label %BB07 + +BB06: + %call06 = call i32 @fun() + br label %exit + +BB07: + %call07 = call i32 @fun2() + br label %exit + +exit: + ret void +} + +; BB1 cannot be a new save point because it has a clean path to Exit. +define void @noshrink_test1(i32 %a, i32 %v, i32 %v2) { +; CHECK-LABEL: noshrink_test1: +; CHECK-LABEL: %bb.0: // %entry +; CHECK: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-LABEL: %bb.3: +; CHECK: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-LABEL: .LBB2_6: +; CHECK: ldr x30, [sp], #16 // 8-byte Folded Reload + +entry: + %cmp5 = icmp sgt i32 %a, 0 + br i1 %cmp5, label %BB0, label %exit + +BB0: + %c = icmp eq i32 %a, 10 + br i1 %c, label %BB1, label %BB2 + +BB1: + %c1 = icmp eq i32 %v, 10 + br i1 %c1, label %BB3, label %BB2 + +BB2: + %c2 = icmp eq i32 %v2, 10 + br i1 %c2, label %BB4, label %exit + +BB3: + %call3 = call i32 @fun() + %c3 = icmp eq i32 %call3, 0 + br label %exit + +BB4: + %call4 = call i32 @fun2() + br label %exit + +exit: + ret void +} + +; No further shrinking when calling in an infinite loop. +define void @noshrink_test2(i32 %a) { +; CHECK-LABEL: noshrink_test2: +; CHECK-LABEL: %bb.0: +; CHECK: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-LABEL: %bb.2: +; CHECK: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-LABEL: .LBB3_4: +; CHECK: ldr x30, [sp], #16 // 8-byte Folded Reload + +BB00: + %cmp5 = icmp sgt i32 %a, 0 + br i1 %cmp5, label %BB01, label %InfLoop + +BB01: + %call = call i32 @fun() + %c = icmp eq i32 %call, 0 + br i1 %c, label %BB02, label %exit + +BB02: + %call2 = call i32 @fun() + br label %exit + +InfLoop: + %call3 = call i32 @fun() + br label %InfLoop + +exit: + ret void +} + +; No further shrinking if save cannot dominate restore. +define void @noshrink_test3(i32 %a) { +; CHECK-LABEL: noshrink_test3: +; CHECK-LABEL: %bb.0: +; CHECK: stp x30, x19, [sp, #-16]! // 16-byte Folded Spill +; CHECK-LABEL: .LBB4_6: +; CHECK: ldp x30, x19, [sp], #16 // 16-byte Folded Reload + +BB00: + %cmp5 = icmp sgt i32 %a, 0 + br i1 %cmp5, label %BB02, label %BB01 + +BB01: ; dirty + %call01 = call i32 @fun() + %c01 = icmp eq i32 %call01, 0 + br i1 %c01, label %BB01.1, label %exit + +BB01.1: + call void @abort() noreturn + unreachable + +BB02: + %call02 = call i32 @fun() + %c02 = icmp eq i32 %call02, 0 + br i1 %c02, label %BB03, label %BB04 + +BB03: + %call03 = call i32 @fun() + %c03 = icmp eq i32 %call03, 0 + br i1 %c03, label %BB04, label %exit + +BB04: + %call04 = call i32 @fun() + br label %exit + +exit: + ret void +} + +declare i32 @fun() +declare i32 @fun2() +declare void @abort() noreturn