xref: /llvm-project/llvm/test/Transforms/GuardWidening/two_forms_behavior_consistency.ll (revision 0b5bb6923f09ebc257ebed4ace1d8b6b113b2bf5)
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