1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck %s 3 4define void @assume_false_to_unreachable1() { 5; CHECK-LABEL: @assume_false_to_unreachable1( 6; CHECK-NEXT: unreachable 7; 8 call void @llvm.assume(i1 0) 9 ret void 10 11} 12 13define void @assume_undef_to_unreachable() { 14; CHECK-LABEL: @assume_undef_to_unreachable( 15; CHECK-NEXT: unreachable 16; 17 call void @llvm.assume(i1 undef) 18 ret void 19 20} 21 22define i32 @speculate_block_with_assume_basic(i1 %c, i32 %x) { 23; CHECK-LABEL: @speculate_block_with_assume_basic( 24; CHECK-NEXT: entry: 25; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], i32 1, i32 0 26; CHECK-NEXT: ret i32 [[SPEC_SELECT]] 27; 28entry: 29 br i1 %c, label %if, label %join 30 31if: 32 %cmp = icmp ne i32 %x, 0 33 call void @llvm.assume(i1 %cmp) 34 br label %join 35 36join: 37 %phi = phi i32 [ 0, %entry ], [ 1, %if ] 38 ret i32 %phi 39} 40 41define i32 @speculate_block_with_assume_extra_instr(i1 %c, i32 %x) { 42; CHECK-LABEL: @speculate_block_with_assume_extra_instr( 43; CHECK-NEXT: entry: 44; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X:%.*]], 1 45; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], i32 [[ADD]], i32 0 46; CHECK-NEXT: ret i32 [[SPEC_SELECT]] 47; 48entry: 49 br i1 %c, label %if, label %join 50 51if: 52 %add = add i32 %x, 1 53 %cmp = icmp ne i32 %add, 0 54 call void @llvm.assume(i1 %cmp) 55 br label %join 56 57join: 58 %phi = phi i32 [ 0, %entry ], [ %add, %if ] 59 ret i32 %phi 60} 61 62; We only allow speculating one instruction. Here %add and %add2 are used by 63; the assume, but not ephemeral, because they are also used by %phi. 64define i32 @speculate_block_with_assume_extra_instrs_too_many(i1 %c, i32 %x) { 65; CHECK-LABEL: @speculate_block_with_assume_extra_instrs_too_many( 66; CHECK-NEXT: entry: 67; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[JOIN:%.*]] 68; CHECK: if: 69; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X:%.*]], 1 70; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD]], 1 71; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[ADD2]], 0 72; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 73; CHECK-NEXT: br label [[JOIN]] 74; CHECK: join: 75; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD2]], [[IF]] ] 76; CHECK-NEXT: ret i32 [[PHI]] 77; 78entry: 79 br i1 %c, label %if, label %join 80 81if: 82 %add = add i32 %x, 1 83 %add2 = add i32 %add, 1 84 %cmp = icmp ne i32 %add2, 0 85 call void @llvm.assume(i1 %cmp) 86 br label %join 87 88join: 89 %phi = phi i32 [ 0, %entry ], [ %add2, %if ] 90 ret i32 %phi 91} 92 93define i32 @speculate_block_with_assume_extra_instrs_okay(i1 %c, i32 %x) { 94; CHECK-LABEL: @speculate_block_with_assume_extra_instrs_okay( 95; CHECK-NEXT: entry: 96; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X:%.*]], 1 97; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], i32 [[ADD]], i32 0 98; CHECK-NEXT: ret i32 [[SPEC_SELECT]] 99; 100entry: 101 br i1 %c, label %if, label %join 102 103if: 104 %add = add i32 %x, 1 105 %add2 = add i32 %add, 1 106 %cmp = icmp ne i32 %add2, 0 107 call void @llvm.assume(i1 %cmp) 108 br label %join 109 110join: 111 %phi = phi i32 [ 0, %entry ], [ %add, %if ] 112 ret i32 %phi 113} 114 115define i32 @speculate_block_with_assume_operand_bundle(i1 %c, ptr %p) { 116; CHECK-LABEL: @speculate_block_with_assume_operand_bundle( 117; CHECK-NEXT: entry: 118; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], i32 1, i32 0 119; CHECK-NEXT: ret i32 [[SPEC_SELECT]] 120; 121entry: 122 br i1 %c, label %if, label %join 123 124if: 125 call void @llvm.assume(i1 true) ["nonnull"(ptr %p)] 126 br label %join 127 128join: 129 %phi = phi i32 [ 0, %entry ], [ 1, %if ] 130 ret i32 %phi 131} 132 133define void @empty_block_with_assume(i1 %c, i32 %x) { 134; CHECK-LABEL: @empty_block_with_assume( 135; CHECK-NEXT: entry: 136; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 137; CHECK: if: 138; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X:%.*]], 0 139; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 140; CHECK-NEXT: br label [[JOIN:%.*]] 141; CHECK: else: 142; CHECK-NEXT: call void @dummy() 143; CHECK-NEXT: br label [[JOIN]] 144; CHECK: join: 145; CHECK-NEXT: ret void 146; 147entry: 148 br i1 %c, label %if, label %else 149 150if: 151 %cmp = icmp ne i32 %x, 0 152 call void @llvm.assume(i1 %cmp) 153 br label %join 154 155else: 156 call void @dummy() 157 br label %join 158 159join: 160 ret void 161} 162 163define void @not_empty_block_with_assume(i1 %c) { 164; CHECK-LABEL: @not_empty_block_with_assume( 165; CHECK-NEXT: entry: 166; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 167; CHECK: if: 168; CHECK-NEXT: [[X:%.*]] = call i32 @may_have_side_effect() 169; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X]], 0 170; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 171; CHECK-NEXT: br label [[JOIN:%.*]] 172; CHECK: else: 173; CHECK-NEXT: call void @dummy() 174; CHECK-NEXT: br label [[JOIN]] 175; CHECK: join: 176; CHECK-NEXT: ret void 177; 178entry: 179 br i1 %c, label %if, label %else 180 181if: 182 %x = call i32 @may_have_side_effect() 183 %cmp = icmp ne i32 %x, 0 184 call void @llvm.assume(i1 %cmp) 185 br label %join 186 187else: 188 call void @dummy() 189 br label %join 190 191join: 192 ret void 193} 194 195declare void @dummy() 196declare i32 @may_have_side_effect() 197declare void @llvm.assume(i1) nounwind 198 199