xref: /llvm-project/llvm/test/Transforms/SimplifyCFG/guards.ll (revision 8979ae42769e529b0f6fce3268492ffb49bd54b9)
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