1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -loop-guard-widening -enable-new-pm=0 < %s | FileCheck %s 3; RUN: opt -S -passes="loop(guard-widening)" < %s | FileCheck %s 4 5declare void @llvm.experimental.guard(i1,...) 6 7@G = external global i32 8 9; Show that we can widen into early checks within a loop, and in the process 10; expose optimization oppurtunities. 11define void @widen_within_loop(i1 %cond_0, i1 %cond_1, i1 %cond_2) { 12; CHECK-LABEL: @widen_within_loop( 13; CHECK-NEXT: entry: 14; CHECK-NEXT: br label [[LOOP:%.*]] 15; CHECK: loop: 16; CHECK-NEXT: store i32 0, i32* @G 17; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]] 18; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[COND_2:%.*]] 19; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK1]]) [ "deopt"(i32 0) ] 20; CHECK-NEXT: store i32 1, i32* @G 21; CHECK-NEXT: store i32 2, i32* @G 22; CHECK-NEXT: store i32 3, i32* @G 23; CHECK-NEXT: br label [[LOOP]] 24; 25entry: 26 br label %loop 27 28loop: 29 store i32 0, i32* @G 30 call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"(i32 0) ] 31 store i32 1, i32* @G 32 call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"(i32 1) ] 33 store i32 2, i32* @G 34 call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"(i32 2) ] 35 store i32 3, i32* @G 36 br label %loop 37} 38 39define void @widen_into_preheader(i1 %cond_0, i1 %cond_1, i1 %cond_2) { 40; CHECK-LABEL: @widen_into_preheader( 41; CHECK-NEXT: entry: 42; CHECK-NEXT: store i32 0, i32* @G 43; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]] 44; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[COND_2:%.*]] 45; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK1]]) [ "deopt"(i32 0) ] 46; CHECK-NEXT: br label [[LOOP:%.*]] 47; CHECK: loop: 48; CHECK-NEXT: store i32 1, i32* @G 49; CHECK-NEXT: store i32 2, i32* @G 50; CHECK-NEXT: store i32 3, i32* @G 51; CHECK-NEXT: br label [[LOOP]] 52; 53entry: 54 store i32 0, i32* @G 55 call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"(i32 0) ] 56 br label %loop 57 58loop: 59 store i32 1, i32* @G 60 call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"(i32 1) ] 61 store i32 2, i32* @G 62 call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"(i32 2) ] 63 store i32 3, i32* @G 64 br label %loop 65} 66 67define void @dont_widen_over_common_exit(i1 %cond_0, i1 %cond_1, i1 %cond_2) { 68; CHECK-LABEL: @dont_widen_over_common_exit( 69; CHECK-NEXT: entry: 70; CHECK-NEXT: br label [[LOOP:%.*]] 71; CHECK: loop: 72; CHECK-NEXT: store i32 0, i32* @G 73; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"(i32 0) ] 74; CHECK-NEXT: store i32 1, i32* @G 75; CHECK-NEXT: br i1 [[COND_1:%.*]], label [[BACKEDGE:%.*]], label [[EXIT:%.*]] 76; CHECK: backedge: 77; CHECK-NEXT: store i32 2, i32* @G 78; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_2:%.*]]) [ "deopt"(i32 2) ] 79; CHECK-NEXT: store i32 3, i32* @G 80; CHECK-NEXT: br label [[LOOP]] 81; CHECK: exit: 82; CHECK-NEXT: ret void 83; 84entry: 85 br label %loop 86 87loop: 88 store i32 0, i32* @G 89 call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"(i32 0) ] 90 store i32 1, i32* @G 91 br i1 %cond_1, label %backedge, label %exit 92 93backedge: 94 store i32 2, i32* @G 95 call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"(i32 2) ] 96 store i32 3, i32* @G 97 br label %loop 98 99exit: 100 ret void 101} 102 103define void @widen_over_common_exit_to_ph(i1 %cond_0, i1 %cond_1, i1 %cond_2) { 104; CHECK-LABEL: @widen_over_common_exit_to_ph( 105; CHECK-NEXT: entry: 106; CHECK-NEXT: store i32 0, i32* @G 107; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_2:%.*]] 108; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"(i32 0) ] 109; CHECK-NEXT: br label [[LOOP:%.*]] 110; CHECK: loop: 111; CHECK-NEXT: store i32 1, i32* @G 112; CHECK-NEXT: br i1 [[COND_1:%.*]], label [[BACKEDGE:%.*]], label [[EXIT:%.*]] 113; CHECK: backedge: 114; CHECK-NEXT: store i32 2, i32* @G 115; CHECK-NEXT: store i32 3, i32* @G 116; CHECK-NEXT: br label [[LOOP]] 117; CHECK: exit: 118; CHECK-NEXT: ret void 119; 120entry: 121 store i32 0, i32* @G 122 call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"(i32 0) ] 123 br label %loop 124 125loop: 126 store i32 1, i32* @G 127 br i1 %cond_1, label %backedge, label %exit 128 129backedge: 130 store i32 2, i32* @G 131 call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"(i32 2) ] 132 store i32 3, i32* @G 133 br label %loop 134 135exit: 136 ret void 137} 138 139