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
6 declare i1 @cond() readonly
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.
13 define 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
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:%.*]]
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]+]]
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:%.*]]
76 ; BRANCH_FORM-NEXT: ret void
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
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
134 declare void @llvm.experimental.guard(i1, ...)