1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s 3 4declare void @llvm.experimental.guard(i1, ...) 5 6define i32 @f_0(i1 %c) { 7; CHECK-LABEL: @f_0( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ] 10; CHECK-NEXT: unreachable 11; 12entry: 13 call void(i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ] 14 ret i32 10 15} 16 17define i32 @f_1(i1 %c) { 18; Demonstrate that we (intentionally) do not simplify a guard on undef 19; CHECK-LABEL: @f_1( 20; CHECK-NEXT: entry: 21; CHECK-NEXT: br i1 [[C:%.*]], label [[TRUE:%.*]], label [[COMMON_RET:%.*]] 22; CHECK: common.ret: 23; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 10, [[TRUE]] ], [ 20, [[ENTRY:%.*]] ] 24; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] 25; CHECK: true: 26; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 undef) [ "deopt"() ] 27; CHECK-NEXT: br label [[COMMON_RET]] 28; 29 30entry: 31 br i1 %c, label %true, label %false 32 33true: 34 call void(i1, ...) @llvm.experimental.guard(i1 undef) [ "deopt"() ] 35 ret i32 10 36 37false: 38 ret i32 20 39} 40 41define i32 @f_2(i1 %c, ptr %buf) { 42; CHECK-LABEL: @f_2( 43; CHECK-NEXT: entry: 44; CHECK-NEXT: br i1 [[C:%.*]], label [[GUARD_BLOCK:%.*]], label [[MERGE_BLOCK:%.*]] 45; CHECK: guard_block: 46; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ] 47; CHECK-NEXT: unreachable 48; CHECK: merge_block: 49; CHECK-NEXT: ret i32 50 50; 51entry: 52 br i1 %c, label %guard_block, label %merge_block 53 54guard_block: 55 call void(i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ] 56 %val = load i32, ptr %buf 57 br label %merge_block 58 59merge_block: 60 %to.return = phi i32 [ %val, %guard_block ], [ 50, %entry ] 61 ret i32 %to.return 62 63} 64 65define i32 @f_3(ptr %c, ptr %buf) { 66; CHECK-LABEL: @f_3( 67; CHECK-NEXT: entry: 68; CHECK-NEXT: [[C0:%.*]] = load volatile i1, ptr [[C:%.*]], align 1 69; CHECK-NEXT: br i1 [[C0]], label [[GUARD_BLOCK:%.*]], label [[MERGE_BLOCK:%.*]] 70; CHECK: guard_block: 71; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ] 72; CHECK-NEXT: unreachable 73; CHECK: merge_block: 74; CHECK-NEXT: [[C1:%.*]] = load volatile i1, ptr [[C]], align 1 75; CHECK-NEXT: [[DOT:%.*]] = select i1 [[C1]], i32 50, i32 100 76; CHECK-NEXT: ret i32 [[DOT]] 77; 78entry: 79 %c0 = load volatile i1, ptr %c 80 br i1 %c0, label %guard_block, label %merge_block 81 82guard_block: 83 call void(i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ] 84 %val = load i32, ptr %buf 85 %c2 = load volatile i1, ptr %c 86 br i1 %c2, label %left, label %right 87 88merge_block: 89 %c1 = load volatile i1, ptr %c 90 br i1 %c1, label %left, label %right 91 92left: 93 %val.left = phi i32 [ %val, %guard_block ], [ 50, %merge_block ] 94 ret i32 %val.left 95 96right: 97 %val.right = phi i32 [ %val, %guard_block ], [ 100, %merge_block ] 98 ret i32 %val.right 99 100 101} 102