1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=guard-widening -S < %s | FileCheck %s 3 4declare i32 @llvm.experimental.deoptimize.i32(...) 5 6; Make sure the two loop-invariant conditions can be widened together, 7; and the widening point is outside the loop. 8define i32 @test_01(i32 %start, i32 %x) { 9; CHECK-LABEL: @test_01( 10; CHECK-NEXT: entry: 11; CHECK-NEXT: [[START_GW_FR:%.*]] = freeze i32 [[START:%.*]] 12; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]] 13; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[START_GW_FR]], [[X_GW_FR]] 14; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[COND]] 15; CHECK-NEXT: [[WC1:%.*]] = call i1 @llvm.experimental.widenable.condition() 16; CHECK-NEXT: br label [[LOOP:%.*]] 17; CHECK: loop: 18; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START_GW_FR]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 19; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[WIDE_CHK]], [[WC1]] 20; CHECK-NEXT: br i1 [[TMP0]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]] 21; CHECK: exit_by_wc: 22; CHECK-NEXT: [[RVAL1:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ] 23; CHECK-NEXT: ret i32 [[RVAL1]] 24; CHECK: guard_block: 25; CHECK-NEXT: [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition() 26; CHECK-NEXT: [[GUARD:%.*]] = and i1 [[COND]], [[WC2]] 27; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAILURE:%.*]] 28; CHECK: backedge: 29; CHECK-NEXT: call void @side_effect() 30; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 31; CHECK-NEXT: br label [[LOOP]] 32; CHECK: exit: 33; CHECK-NEXT: ret i32 -1 34; CHECK: failure: 35; CHECK-NEXT: [[RVAL2:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ] 36; CHECK-NEXT: ret i32 [[RVAL2]] 37; 38entry: 39 %cond = icmp eq i32 %start, %x 40 %wc1 = call i1 @llvm.experimental.widenable.condition() 41 br label %loop 42 43loop: 44 %iv = phi i32 [ %start, %entry ], [ %iv.next, %backedge ] 45 br i1 %wc1, label %guard_block, label %exit_by_wc 46 47exit_by_wc: 48 %rval1 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ] 49 ret i32 %rval1 50 51guard_block: 52 %wc2 = call i1 @llvm.experimental.widenable.condition() 53 %guard = and i1 %cond, %wc2 54 br i1 %guard, label %backedge, label %failure 55 56backedge: 57 call void @side_effect() 58 %iv.next = add i32 %iv, 1 59 br label %loop 60 61exit: 62 ret i32 -1 63 64failure: 65 %rval2 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ] 66 ret i32 %rval2 67} 68 69 70; Make sure the loop-variant condition is not widened into loop-invariant. 71define i32 @test_02(i32 %start, i32 %x) { 72; CHECK-LABEL: @test_02( 73; CHECK-NEXT: entry: 74; CHECK-NEXT: [[WC1:%.*]] = call i1 @llvm.experimental.widenable.condition() 75; CHECK-NEXT: br label [[LOOP:%.*]] 76; CHECK: loop: 77; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 78; CHECK-NEXT: br i1 [[WC1]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]] 79; CHECK: exit_by_wc: 80; CHECK-NEXT: [[RVAL1:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ] 81; CHECK-NEXT: ret i32 [[RVAL1]] 82; CHECK: guard_block: 83; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV]], [[X:%.*]] 84; CHECK-NEXT: [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition() 85; CHECK-NEXT: [[GUARD:%.*]] = and i1 [[COND]], [[WC2]] 86; CHECK-NEXT: br i1 [[GUARD]], label [[BACKEDGE]], label [[FAILURE:%.*]] 87; CHECK: backedge: 88; CHECK-NEXT: call void @side_effect() 89; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 90; CHECK-NEXT: br label [[LOOP]] 91; CHECK: exit: 92; CHECK-NEXT: ret i32 -1 93; CHECK: failure: 94; CHECK-NEXT: [[RVAL2:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ] 95; CHECK-NEXT: ret i32 [[RVAL2]] 96; 97entry: 98 %wc1 = call i1 @llvm.experimental.widenable.condition() 99 br label %loop 100 101loop: 102 %iv = phi i32 [ %start, %entry ], [ %iv.next, %backedge ] 103 br i1 %wc1, label %guard_block, label %exit_by_wc 104 105exit_by_wc: 106 %rval1 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ] 107 ret i32 %rval1 108 109guard_block: 110 %cond = icmp eq i32 %iv, %x 111 %wc2 = call i1 @llvm.experimental.widenable.condition() 112 %guard = and i1 %cond, %wc2 113 br i1 %guard, label %backedge, label %failure 114 115backedge: 116 call void @side_effect() 117 %iv.next = add i32 %iv, 1 118 br label %loop 119 120exit: 121 ret i32 -1 122 123failure: 124 %rval2 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ] 125 ret i32 %rval2 126} 127 128; Same as test_01, but the initial condition is not immediately WC. 129define i32 @test_03(i32 %start, i32 %x, i1 %c) { 130; CHECK-LABEL: @test_03( 131; CHECK-NEXT: entry: 132; CHECK-NEXT: [[START_GW_FR:%.*]] = freeze i32 [[START:%.*]] 133; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]] 134; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[START_GW_FR]], [[X_GW_FR]] 135; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[C:%.*]], [[COND]] 136; CHECK-NEXT: [[WC1:%.*]] = call i1 @llvm.experimental.widenable.condition() 137; CHECK-NEXT: br label [[LOOP:%.*]] 138; CHECK: loop: 139; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START_GW_FR]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 140; CHECK-NEXT: [[INVARIANT:%.*]] = and i1 [[WIDE_CHK]], [[WC1]] 141; CHECK-NEXT: br i1 [[INVARIANT]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]] 142; CHECK: exit_by_wc: 143; CHECK-NEXT: [[RVAL1:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ] 144; CHECK-NEXT: ret i32 [[RVAL1]] 145; CHECK: guard_block: 146; CHECK-NEXT: [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition() 147; CHECK-NEXT: [[GUARD:%.*]] = and i1 [[COND]], [[WC2]] 148; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAILURE:%.*]] 149; CHECK: backedge: 150; CHECK-NEXT: call void @side_effect() 151; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 152; CHECK-NEXT: br label [[LOOP]] 153; CHECK: exit: 154; CHECK-NEXT: ret i32 -1 155; CHECK: failure: 156; CHECK-NEXT: [[RVAL2:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ] 157; CHECK-NEXT: ret i32 [[RVAL2]] 158; CHECK: early_failure: 159; CHECK-NEXT: [[RVAL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[X_GW_FR]]) ] 160; CHECK-NEXT: ret i32 [[RVAL3]] 161; 162entry: 163 %cond = icmp eq i32 %start, %x 164 %wc1 = call i1 @llvm.experimental.widenable.condition() 165 %invariant = and i1 %c, %wc1 166 br label %loop 167 168loop: 169 %iv = phi i32 [ %start, %entry ], [ %iv.next, %backedge ] 170 br i1 %invariant, label %guard_block, label %exit_by_wc 171 172exit_by_wc: 173 %rval1 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ] 174 ret i32 %rval1 175 176guard_block: 177 %wc2 = call i1 @llvm.experimental.widenable.condition() 178 %guard = and i1 %cond, %wc2 179 br i1 %guard, label %backedge, label %failure 180 181backedge: 182 call void @side_effect() 183 %iv.next = add i32 %iv, 1 184 br label %loop 185 186exit: 187 ret i32 -1 188 189failure: 190 %rval2 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ] 191 ret i32 %rval2 192 193early_failure: 194 %rval3 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %x) ] 195 ret i32 %rval3 196} 197 198; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite) 199declare i1 @llvm.experimental.widenable.condition() 200 201declare void @side_effect() 202