Follow up to d0858bffa11, add missing REQUIRES x86
[llvm-project.git] / llvm / test / Transforms / GuardWidening / basic-loop.ll
blob956d920501c2cab50a06be53715dbdc9b8a57580
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes="loop-mssa(guard-widening)" -verify-memoryssa < %s | FileCheck %s
4 declare void @llvm.experimental.guard(i1,...)
6 @G = external global i32
8 ; Show that we can widen into early checks within a loop, and in the process
9 ; expose optimization oppurtunities.
10 define void @widen_within_loop(i1 %cond_0, i1 %cond_1, i1 %cond_2) {
11 ; CHECK-LABEL: @widen_within_loop(
12 ; CHECK-NEXT:  entry:
13 ; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2:%.*]]
14 ; CHECK-NEXT:    [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
15 ; CHECK-NEXT:    br label [[LOOP:%.*]]
16 ; CHECK:       loop:
17 ; CHECK-NEXT:    store i32 0, ptr @G, align 4
18 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
19 ; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[COND_2_GW_FR]]
20 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK1]]) [ "deopt"(i32 0) ]
21 ; CHECK-NEXT:    store i32 1, ptr @G, align 4
22 ; CHECK-NEXT:    store i32 2, ptr @G, align 4
23 ; CHECK-NEXT:    store i32 3, ptr @G, align 4
24 ; CHECK-NEXT:    br label [[LOOP]]
26 entry:
27   br label %loop
29 loop:
30   store i32 0, ptr @G
31   call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"(i32 0) ]
32   store i32 1, ptr @G
33   call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"(i32 1) ]
34   store i32 2, ptr @G
35   call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"(i32 2) ]
36   store i32 3, ptr @G
37   br label %loop
40 define void @widen_into_preheader(i1 %cond_0, i1 %cond_1, i1 %cond_2) {
41 ; CHECK-LABEL: @widen_into_preheader(
42 ; CHECK-NEXT:  entry:
43 ; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2:%.*]]
44 ; CHECK-NEXT:    [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
45 ; CHECK-NEXT:    store i32 0, ptr @G, align 4
46 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
47 ; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[COND_2_GW_FR]]
48 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK1]]) [ "deopt"(i32 0) ]
49 ; CHECK-NEXT:    br label [[LOOP:%.*]]
50 ; CHECK:       loop:
51 ; CHECK-NEXT:    store i32 1, ptr @G, align 4
52 ; CHECK-NEXT:    store i32 2, ptr @G, align 4
53 ; CHECK-NEXT:    store i32 3, ptr @G, align 4
54 ; CHECK-NEXT:    br label [[LOOP]]
56 entry:
57   store i32 0, ptr @G
58   call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"(i32 0) ]
59   br label %loop
61 loop:
62   store i32 1, ptr @G
63   call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"(i32 1) ]
64   store i32 2, ptr @G
65   call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"(i32 2) ]
66   store i32 3, ptr @G
67   br label %loop
70 define void @dont_widen_over_common_exit(i1 %cond_0, i1 %cond_1, i1 %cond_2) {
71 ; CHECK-LABEL: @dont_widen_over_common_exit(
72 ; CHECK-NEXT:  entry:
73 ; CHECK-NEXT:    br label [[LOOP:%.*]]
74 ; CHECK:       loop:
75 ; CHECK-NEXT:    store i32 0, ptr @G, align 4
76 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"(i32 0) ]
77 ; CHECK-NEXT:    store i32 1, ptr @G, align 4
78 ; CHECK-NEXT:    br i1 [[COND_1:%.*]], label [[BACKEDGE:%.*]], label [[EXIT:%.*]]
79 ; CHECK:       backedge:
80 ; CHECK-NEXT:    store i32 2, ptr @G, align 4
81 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_2:%.*]]) [ "deopt"(i32 2) ]
82 ; CHECK-NEXT:    store i32 3, ptr @G, align 4
83 ; CHECK-NEXT:    br label [[LOOP]]
84 ; CHECK:       exit:
85 ; CHECK-NEXT:    ret void
87 entry:
88   br label %loop
90 loop:
91   store i32 0, ptr @G
92   call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"(i32 0) ]
93   store i32 1, ptr @G
94   br i1 %cond_1, label %backedge, label %exit
96 backedge:
97   store i32 2, ptr @G
98   call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"(i32 2) ]
99   store i32 3, ptr @G
100   br label %loop
102 exit:
103   ret void
106 define void @widen_over_common_exit_to_ph(i1 %cond_0, i1 %cond_1, i1 %cond_2) {
107 ; CHECK-LABEL: @widen_over_common_exit_to_ph(
108 ; CHECK-NEXT:  entry:
109 ; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2:%.*]]
110 ; CHECK-NEXT:    store i32 0, ptr @G, align 4
111 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_2_GW_FR]]
112 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"(i32 0) ]
113 ; CHECK-NEXT:    br label [[LOOP:%.*]]
114 ; CHECK:       loop:
115 ; CHECK-NEXT:    store i32 1, ptr @G, align 4
116 ; CHECK-NEXT:    br i1 [[COND_1:%.*]], label [[BACKEDGE:%.*]], label [[EXIT:%.*]]
117 ; CHECK:       backedge:
118 ; CHECK-NEXT:    store i32 2, ptr @G, align 4
119 ; CHECK-NEXT:    store i32 3, ptr @G, align 4
120 ; CHECK-NEXT:    br label [[LOOP]]
121 ; CHECK:       exit:
122 ; CHECK-NEXT:    ret void
124 entry:
125   store i32 0, ptr @G
126   call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"(i32 0) ]
127   br label %loop
129 loop:
130   store i32 1, ptr @G
131   br i1 %cond_1, label %backedge, label %exit
133 backedge:
134   store i32 2, ptr @G
135   call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"(i32 2) ]
136   store i32 3, ptr @G
137   br label %loop
139 exit:
140   ret void