1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 2; RUN: opt -S -passes="guard-widening,make-guards-explicit,simplifycfg" < %s | FileCheck %s --check-prefixes=INTRINSIC_FORM 3; RUN: opt -S -passes="make-guards-explicit,guard-widening,simplifycfg" < %s | FileCheck %s --check-prefixes=BRANCH_FORM 4; RUN: opt -S -passes="make-guards-explicit,loop-mssa(licm),guard-widening,simplifycfg" < %s | FileCheck %s --check-prefixes=BRANCH_FORM_LICM 5 6declare i1 @cond() readonly 7 8; FIXME We want to make sure that guard widening works in the same way, no matter what form of 9; guards it is dealing with. 10; We also want to make sure that LICM doesn't mess with widenable conditions, what might 11; make things more complex. 12 13define void @test_01(i32 %a, i32 %b, i32 %c, i32 %d) { 14; INTRINSIC_FORM-LABEL: define void @test_01 15; INTRINSIC_FORM-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]]) { 16; INTRINSIC_FORM-NEXT: entry: 17; INTRINSIC_FORM-NEXT: [[D_GW_FR:%.*]] = freeze i32 [[D]] 18; INTRINSIC_FORM-NEXT: [[C_GW_FR:%.*]] = freeze i32 [[C]] 19; INTRINSIC_FORM-NEXT: [[B_GW_FR:%.*]] = freeze i32 [[B]] 20; INTRINSIC_FORM-NEXT: br label [[LOOP:%.*]] 21; INTRINSIC_FORM: loop: 22; INTRINSIC_FORM-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[GUARDED:%.*]] ] 23; INTRINSIC_FORM-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 24; INTRINSIC_FORM-NEXT: [[C1:%.*]] = icmp ult i32 [[IV]], [[A]] 25; INTRINSIC_FORM-NEXT: [[C2:%.*]] = icmp ult i32 [[IV]], [[B_GW_FR]] 26; INTRINSIC_FORM-NEXT: [[WIDE_CHK:%.*]] = and i1 [[C1]], [[C2]] 27; INTRINSIC_FORM-NEXT: [[C3:%.*]] = icmp ult i32 [[IV]], [[C_GW_FR]] 28; INTRINSIC_FORM-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[C3]] 29; INTRINSIC_FORM-NEXT: [[C4:%.*]] = icmp ult i32 [[IV]], [[D_GW_FR]] 30; INTRINSIC_FORM-NEXT: [[WIDE_CHK2:%.*]] = and i1 [[WIDE_CHK1]], [[C4]] 31; INTRINSIC_FORM-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 32; INTRINSIC_FORM-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK2]], [[WIDENABLE_COND]] 33; INTRINSIC_FORM-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]] 34; INTRINSIC_FORM: deopt: 35; INTRINSIC_FORM-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 36; INTRINSIC_FORM-NEXT: ret void 37; INTRINSIC_FORM: guarded: 38; INTRINSIC_FORM-NEXT: [[LOOP_COND:%.*]] = call i1 @cond() 39; INTRINSIC_FORM-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 40; INTRINSIC_FORM: exit: 41; INTRINSIC_FORM-NEXT: ret void 42; 43; BRANCH_FORM-LABEL: define void @test_01 44; BRANCH_FORM-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]]) { 45; BRANCH_FORM-NEXT: entry: 46; BRANCH_FORM-NEXT: [[D_GW_FR:%.*]] = freeze i32 [[D]] 47; BRANCH_FORM-NEXT: [[C_GW_FR:%.*]] = freeze i32 [[C]] 48; BRANCH_FORM-NEXT: [[B_GW_FR:%.*]] = freeze i32 [[B]] 49; BRANCH_FORM-NEXT: br label [[LOOP:%.*]] 50; BRANCH_FORM: loop: 51; BRANCH_FORM-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[GUARDED:%.*]] ] 52; BRANCH_FORM-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 53; BRANCH_FORM-NEXT: [[C1:%.*]] = icmp ult i32 [[IV]], [[A]] 54; BRANCH_FORM-NEXT: [[C2:%.*]] = icmp ult i32 [[IV]], [[B_GW_FR]] 55; BRANCH_FORM-NEXT: [[WIDE_CHK:%.*]] = and i1 [[C1]], [[C2]] 56; BRANCH_FORM-NEXT: [[C3:%.*]] = icmp ult i32 [[IV]], [[C_GW_FR]] 57; BRANCH_FORM-NEXT: [[WIDE_CHK13:%.*]] = and i1 [[WIDE_CHK]], [[C3]] 58; BRANCH_FORM-NEXT: [[C4:%.*]] = icmp ult i32 [[IV]], [[D_GW_FR]] 59; BRANCH_FORM-NEXT: [[WIDE_CHK14:%.*]] = and i1 [[WIDE_CHK13]], [[C4]] 60; BRANCH_FORM-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 61; BRANCH_FORM-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK14]], [[WIDENABLE_COND]] 62; BRANCH_FORM-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]] 63; BRANCH_FORM: deopt: 64; BRANCH_FORM-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 65; BRANCH_FORM-NEXT: ret void 66; BRANCH_FORM: guarded: 67; BRANCH_FORM-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 68; BRANCH_FORM-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[C2]], [[WIDENABLE_COND3]] 69; BRANCH_FORM-NEXT: [[WIDENABLE_COND7:%.*]] = call i1 @llvm.experimental.widenable.condition() 70; BRANCH_FORM-NEXT: [[EXIPLICIT_GUARD_COND8:%.*]] = and i1 [[C3]], [[WIDENABLE_COND7]] 71; BRANCH_FORM-NEXT: [[WIDENABLE_COND11:%.*]] = call i1 @llvm.experimental.widenable.condition() 72; BRANCH_FORM-NEXT: [[EXIPLICIT_GUARD_COND12:%.*]] = and i1 [[C4]], [[WIDENABLE_COND11]] 73; BRANCH_FORM-NEXT: [[LOOP_COND:%.*]] = call i1 @cond() 74; BRANCH_FORM-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 75; BRANCH_FORM: exit: 76; BRANCH_FORM-NEXT: ret void 77; 78; BRANCH_FORM_LICM-LABEL: define void @test_01 79; BRANCH_FORM_LICM-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]]) { 80; BRANCH_FORM_LICM-NEXT: entry: 81; BRANCH_FORM_LICM-NEXT: [[D_GW_FR:%.*]] = freeze i32 [[D]] 82; BRANCH_FORM_LICM-NEXT: [[C_GW_FR:%.*]] = freeze i32 [[C]] 83; BRANCH_FORM_LICM-NEXT: [[B_GW_FR:%.*]] = freeze i32 [[B]] 84; BRANCH_FORM_LICM-NEXT: br label [[LOOP:%.*]] 85; BRANCH_FORM_LICM: loop: 86; BRANCH_FORM_LICM-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[GUARDED:%.*]] ] 87; BRANCH_FORM_LICM-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 88; BRANCH_FORM_LICM-NEXT: [[C1:%.*]] = icmp ult i32 [[IV]], [[A]] 89; BRANCH_FORM_LICM-NEXT: [[C2:%.*]] = icmp ult i32 [[IV]], [[B_GW_FR]] 90; BRANCH_FORM_LICM-NEXT: [[WIDE_CHK:%.*]] = and i1 [[C1]], [[C2]] 91; BRANCH_FORM_LICM-NEXT: [[C3:%.*]] = icmp ult i32 [[IV]], [[C_GW_FR]] 92; BRANCH_FORM_LICM-NEXT: [[WIDE_CHK13:%.*]] = and i1 [[WIDE_CHK]], [[C3]] 93; BRANCH_FORM_LICM-NEXT: [[C4:%.*]] = icmp ult i32 [[IV]], [[D_GW_FR]] 94; BRANCH_FORM_LICM-NEXT: [[WIDE_CHK14:%.*]] = and i1 [[WIDE_CHK13]], [[C4]] 95; BRANCH_FORM_LICM-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 96; BRANCH_FORM_LICM-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK14]], [[WIDENABLE_COND]] 97; BRANCH_FORM_LICM-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]] 98; BRANCH_FORM_LICM: deopt: 99; BRANCH_FORM_LICM-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 100; BRANCH_FORM_LICM-NEXT: ret void 101; BRANCH_FORM_LICM: guarded: 102; BRANCH_FORM_LICM-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 103; BRANCH_FORM_LICM-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[C2]], [[WIDENABLE_COND3]] 104; BRANCH_FORM_LICM-NEXT: [[WIDENABLE_COND7:%.*]] = call i1 @llvm.experimental.widenable.condition() 105; BRANCH_FORM_LICM-NEXT: [[EXIPLICIT_GUARD_COND8:%.*]] = and i1 [[C3]], [[WIDENABLE_COND7]] 106; BRANCH_FORM_LICM-NEXT: [[WIDENABLE_COND11:%.*]] = call i1 @llvm.experimental.widenable.condition() 107; BRANCH_FORM_LICM-NEXT: [[EXIPLICIT_GUARD_COND12:%.*]] = and i1 [[C4]], [[WIDENABLE_COND11]] 108; BRANCH_FORM_LICM-NEXT: [[LOOP_COND:%.*]] = call i1 @cond() 109; BRANCH_FORM_LICM-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 110; BRANCH_FORM_LICM: exit: 111; BRANCH_FORM_LICM-NEXT: ret void 112; 113entry: 114 br label %loop 115 116loop: 117 %iv = phi i32 [0, %entry], [%iv.next, %loop] 118 %iv.next = add i32 %iv, 1 119 %c1 = icmp ult i32 %iv, %a 120 call void(i1, ...) @llvm.experimental.guard(i1 %c1) [ "deopt"() ] 121 %c2 = icmp ult i32 %iv, %b 122 call void(i1, ...) @llvm.experimental.guard(i1 %c2) [ "deopt"() ] 123 %c3 = icmp ult i32 %iv, %c 124 call void(i1, ...) @llvm.experimental.guard(i1 %c3) [ "deopt"() ] 125 %c4 = icmp ult i32 %iv, %d 126 call void(i1, ...) @llvm.experimental.guard(i1 %c4) [ "deopt"() ] 127 %loop_cond = call i1 @cond() 128 br i1 %loop_cond, label %loop, label %exit 129 130exit: 131 ret void 132} 133 134declare void @llvm.experimental.guard(i1, ...) 135