[ARM] More MVE compare vector splat combines for ANDs
[llvm-complete.git] / test / Transforms / LoopRotate / loopexitinglatch.ll
blobdee29ec958e197c72dc86fe45614a6f98c74991f
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -loop-rotate < %s -verify-loop-info -verify-dom-info | FileCheck %s
3 ; RUN: opt -S -loop-rotate < %s -verify-loop-info -verify-dom-info -enable-mssa-loop-dependency=true -verify-memoryssa | FileCheck %s
5 target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
6 target triple = "thumbv8m.base-arm-none-eabi"
8 %struct.List = type { %struct.List*, i32 }
10 define void @list_add(%struct.List** nocapture %list, %struct.List* %data) {
11 ; CHECK-LABEL: @list_add(
12 ; CHECK-NEXT:  entry:
13 ; CHECK-NEXT:    [[TMP0:%.*]] = load %struct.List*, %struct.List** [[LIST:%.*]], align 4
14 ; CHECK-NEXT:    [[VAL2:%.*]] = getelementptr inbounds [[STRUCT_LIST:%.*]], %struct.List* [[TMP0]], i32 0, i32 1
15 ; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* [[VAL2]], align 4
16 ; CHECK-NEXT:    [[VAL1:%.*]] = getelementptr inbounds [[STRUCT_LIST]], %struct.List* [[DATA:%.*]], i32 0, i32 1
17 ; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[VAL1]], align 4
18 ; CHECK-NEXT:    [[CMP3:%.*]] = icmp slt i32 [[TMP1]], [[TMP2]]
19 ; CHECK-NEXT:    br i1 [[CMP3]], label [[IF_THEN_LR_PH:%.*]], label [[IF_ELSE6:%.*]]
20 ; CHECK:       if.then.lr.ph:
21 ; CHECK-NEXT:    br label [[IF_THEN:%.*]]
22 ; CHECK:       for.cond:
23 ; CHECK-NEXT:    [[CURR_0:%.*]] = phi %struct.List* [ [[TMP5:%.*]], [[IF_THEN]] ]
24 ; CHECK-NEXT:    [[PREV_0:%.*]] = phi %struct.List* [ [[CURR_04:%.*]], [[IF_THEN]] ]
25 ; CHECK-NEXT:    [[VAL:%.*]] = getelementptr inbounds [[STRUCT_LIST]], %struct.List* [[CURR_0]], i32 0, i32 1
26 ; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[VAL]], align 4
27 ; CHECK-NEXT:    [[TMP4:%.*]] = load i32, i32* [[VAL1]], align 4
28 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP3]], [[TMP4]]
29 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN]], label [[FOR_COND_IF_ELSE6_CRIT_EDGE:%.*]]
30 ; CHECK:       if.then:
31 ; CHECK-NEXT:    [[CURR_04]] = phi %struct.List* [ [[TMP0]], [[IF_THEN_LR_PH]] ], [ [[CURR_0]], [[FOR_COND:%.*]] ]
32 ; CHECK-NEXT:    [[NEXT:%.*]] = getelementptr inbounds [[STRUCT_LIST]], %struct.List* [[CURR_04]], i32 0, i32 0
33 ; CHECK-NEXT:    [[TMP5]] = load %struct.List*, %struct.List** [[NEXT]], align 4
34 ; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq %struct.List* [[TMP5]], null
35 ; CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_ELSE:%.*]], label [[FOR_COND]]
36 ; CHECK:       if.else:
37 ; CHECK-NEXT:    [[NEXT_LCSSA:%.*]] = phi %struct.List** [ [[NEXT]], [[IF_THEN]] ]
38 ; CHECK-NEXT:    store %struct.List* [[DATA]], %struct.List** [[NEXT_LCSSA]], align 4
39 ; CHECK-NEXT:    [[NEXT5:%.*]] = getelementptr inbounds [[STRUCT_LIST]], %struct.List* [[DATA]], i32 0, i32 0
40 ; CHECK-NEXT:    store %struct.List* null, %struct.List** [[NEXT5]], align 4
41 ; CHECK-NEXT:    br label [[FOR_END:%.*]]
42 ; CHECK:       for.cond.if.else6_crit_edge:
43 ; CHECK-NEXT:    [[SPLIT:%.*]] = phi %struct.List* [ [[PREV_0]], [[FOR_COND]] ]
44 ; CHECK-NEXT:    br label [[IF_ELSE6]]
45 ; CHECK:       if.else6:
46 ; CHECK-NEXT:    [[PREV_0_LCSSA:%.*]] = phi %struct.List* [ [[SPLIT]], [[FOR_COND_IF_ELSE6_CRIT_EDGE]] ], [ null, [[ENTRY:%.*]] ]
47 ; CHECK-NEXT:    [[TOBOOL7:%.*]] = icmp eq %struct.List* [[PREV_0_LCSSA]], null
48 ; CHECK-NEXT:    br i1 [[TOBOOL7]], label [[IF_ELSE12:%.*]], label [[IF_THEN8:%.*]]
49 ; CHECK:       if.then8:
50 ; CHECK-NEXT:    [[NEXT9:%.*]] = getelementptr inbounds [[STRUCT_LIST]], %struct.List* [[PREV_0_LCSSA]], i32 0, i32 0
51 ; CHECK-NEXT:    [[TMP6:%.*]] = bitcast %struct.List* [[PREV_0_LCSSA]] to i32*
52 ; CHECK-NEXT:    [[TMP7:%.*]] = load i32, i32* [[TMP6]], align 4
53 ; CHECK-NEXT:    [[TMP8:%.*]] = bitcast %struct.List* [[DATA]] to i32*
54 ; CHECK-NEXT:    store i32 [[TMP7]], i32* [[TMP8]], align 4
55 ; CHECK-NEXT:    store %struct.List* [[DATA]], %struct.List** [[NEXT9]], align 4
56 ; CHECK-NEXT:    br label [[FOR_END]]
57 ; CHECK:       if.else12:
58 ; CHECK-NEXT:    [[TMP9:%.*]] = bitcast %struct.List** [[LIST]] to i32*
59 ; CHECK-NEXT:    [[TMP10:%.*]] = load i32, i32* [[TMP9]], align 4
60 ; CHECK-NEXT:    [[TMP11:%.*]] = bitcast %struct.List* [[DATA]] to i32*
61 ; CHECK-NEXT:    store i32 [[TMP10]], i32* [[TMP11]], align 4
62 ; CHECK-NEXT:    store %struct.List* [[DATA]], %struct.List** [[LIST]], align 4
63 ; CHECK-NEXT:    br label [[FOR_END]]
64 ; CHECK:       for.end:
65 ; CHECK-NEXT:    ret void
67 entry:
68   %0 = load %struct.List*, %struct.List** %list, align 4
69   br label %for.cond
71 for.cond:                                         ; preds = %if.then, %entry
72   %curr.0 = phi %struct.List* [ %0, %entry ], [ %3, %if.then ]
73   %prev.0 = phi %struct.List* [ null, %entry ], [ %curr.0, %if.then ]
74   %val = getelementptr inbounds %struct.List, %struct.List* %curr.0, i32 0, i32 1
75   %1 = load i32, i32* %val, align 4
76   %val1 = getelementptr inbounds %struct.List, %struct.List* %data, i32 0, i32 1
77   %2 = load i32, i32* %val1, align 4
78   %cmp = icmp slt i32 %1, %2
79   br i1 %cmp, label %if.then, label %if.else6
81 if.then:                                          ; preds = %for.cond
82   %next = getelementptr inbounds %struct.List, %struct.List* %curr.0, i32 0, i32 0
83   %3 = load %struct.List*, %struct.List** %next, align 4
84   %tobool = icmp eq %struct.List* %3, null
85   br i1 %tobool, label %if.else, label %for.cond
87 if.else:                                          ; preds = %if.then
88   %next.lcssa = phi %struct.List** [ %next, %if.then ]
89   store %struct.List* %data, %struct.List** %next.lcssa, align 4
90   %next5 = getelementptr inbounds %struct.List, %struct.List* %data, i32 0, i32 0
91   store %struct.List* null, %struct.List** %next5, align 4
92   br label %for.end
94 if.else6:                                         ; preds = %for.cond
95   %prev.0.lcssa = phi %struct.List* [ %prev.0, %for.cond ]
96   %tobool7 = icmp eq %struct.List* %prev.0.lcssa, null
97   br i1 %tobool7, label %if.else12, label %if.then8
99 if.then8:                                         ; preds = %if.else6
100   %next9 = getelementptr inbounds %struct.List, %struct.List* %prev.0.lcssa, i32 0, i32 0
101   %4 = bitcast %struct.List* %prev.0.lcssa to i32*
102   %5 = load i32, i32* %4, align 4
103   %6 = bitcast %struct.List* %data to i32*
104   store i32 %5, i32* %6, align 4
105   store %struct.List* %data, %struct.List** %next9, align 4
106   br label %for.end
108 if.else12:                                        ; preds = %if.else6
109   %7 = bitcast %struct.List** %list to i32*
110   %8 = load i32, i32* %7, align 4
111   %9 = bitcast %struct.List* %data to i32*
112   store i32 %8, i32* %9, align 4
113   store %struct.List* %data, %struct.List** %list, align 4
114   br label %for.end
116 for.end:                                          ; preds = %if.else12, %if.then8, %if.else
117   ret void
120 define i32 @test2(i32* %l) {
121 ; CHECK-LABEL: @test2(
122 ; CHECK-NEXT:  entry:
123 ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[L:%.*]], align 4
124 ; CHECK-NEXT:    [[TOBOOL2:%.*]] = icmp eq i32 [[TMP0]], 0
125 ; CHECK-NEXT:    br i1 [[TOBOOL2]], label [[CLEANUP:%.*]], label [[DO_COND_LR_PH:%.*]]
126 ; CHECK:       do.cond.lr.ph:
127 ; CHECK-NEXT:    br label [[DO_COND:%.*]]
128 ; CHECK:       do.body:
129 ; CHECK-NEXT:    [[A_0:%.*]] = phi i32 [ [[REM:%.*]], [[DO_COND]] ]
130 ; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* [[L]], align 4
131 ; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[TMP1]], 0
132 ; CHECK-NEXT:    br i1 [[TOBOOL]], label [[DO_BODY_CLEANUP_CRIT_EDGE:%.*]], label [[DO_COND]]
133 ; CHECK:       do.body.cleanup_crit_edge:
134 ; CHECK-NEXT:    [[SPLIT:%.*]] = phi i32 [ [[A_0]], [[DO_BODY:%.*]] ]
135 ; CHECK-NEXT:    br label [[CLEANUP]]
136 ; CHECK:       cleanup:
137 ; CHECK-NEXT:    [[A_0_LCSSA:%.*]] = phi i32 [ [[SPLIT]], [[DO_BODY_CLEANUP_CRIT_EDGE]] ], [ 100, [[ENTRY:%.*]] ]
138 ; CHECK-NEXT:    store i32 10, i32* [[L]], align 4
139 ; CHECK-NEXT:    br label [[CLEANUP2:%.*]]
140 ; CHECK:       do.cond:
141 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP0]], [[DO_COND_LR_PH]] ], [ [[TMP1]], [[DO_BODY]] ]
142 ; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[TMP2]], 13
143 ; CHECK-NEXT:    [[REM]] = srem i32 [[MUL]], 27
144 ; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[L]], align 4
145 ; CHECK-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[TMP3]], 0
146 ; CHECK-NEXT:    br i1 [[TOBOOL1]], label [[CLEANUP2_LOOPEXIT:%.*]], label [[DO_BODY]]
147 ; CHECK:       cleanup2.loopexit:
148 ; CHECK-NEXT:    br label [[CLEANUP2]]
149 ; CHECK:       cleanup2:
150 ; CHECK-NEXT:    [[RETVAL_2:%.*]] = phi i32 [ [[A_0_LCSSA]], [[CLEANUP]] ], [ 0, [[CLEANUP2_LOOPEXIT]] ]
151 ; CHECK-NEXT:    ret i32 [[RETVAL_2]]
153 entry:
154   br label %do.body
156 do.body:                                          ; preds = %do.cond, %entry
157   %a.0 = phi i32 [ 100, %entry ], [ %rem, %do.cond ]
158   %0 = load i32, i32* %l, align 4
159   %tobool = icmp eq i32 %0, 0
160   br i1 %tobool, label %cleanup, label %do.cond
162 cleanup:                                          ; preds = %do.body
163   %a.0.lcssa = phi i32 [ %a.0, %do.body ]
164   store i32 10, i32* %l, align 4
165   br label %cleanup2
167 do.cond:                                          ; preds = %do.body
168   %mul = mul nsw i32 %0, 13
169   %rem = srem i32 %mul, 27
170   %1 = load i32, i32* %l, align 4
171   %tobool1 = icmp eq i32 %1, 0
172   br i1 %tobool1, label %cleanup2.loopexit, label %do.body
174 cleanup2.loopexit:                                ; preds = %do.cond
175   br label %cleanup2
177 cleanup2:                                         ; preds = %cleanup2.loopexit, %cleanup
178   %retval.2 = phi i32 [ %a.0.lcssa, %cleanup ], [ 0, %cleanup2.loopexit ]
179   ret i32 %retval.2
182 define i32 @no_rotate(i32* %l) {
183 ; CHECK-LABEL: @no_rotate(
184 ; CHECK-NEXT:  entry:
185 ; CHECK-NEXT:    br label [[DO_BODY:%.*]]
186 ; CHECK:       do.body:
187 ; CHECK-NEXT:    [[A_0:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[REM:%.*]], [[DO_COND:%.*]] ]
188 ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[L:%.*]], align 4
189 ; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0
190 ; CHECK-NEXT:    br i1 [[TOBOOL]], label [[CLEANUP:%.*]], label [[DO_COND]]
191 ; CHECK:       cleanup:
192 ; CHECK-NEXT:    [[A_0_LCSSA:%.*]] = phi i32 [ [[A_0]], [[DO_BODY]] ]
193 ; CHECK-NEXT:    store i32 10, i32* [[L]], align 4
194 ; CHECK-NEXT:    br label [[CLEANUP2:%.*]]
195 ; CHECK:       do.cond:
196 ; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[A_0]], 13
197 ; CHECK-NEXT:    [[REM]] = srem i32 [[MUL]], 27
198 ; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* [[L]], align 4
199 ; CHECK-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[TMP1]], 0
200 ; CHECK-NEXT:    br i1 [[TOBOOL1]], label [[CLEANUP2_LOOPEXIT:%.*]], label [[DO_BODY]]
201 ; CHECK:       cleanup2.loopexit:
202 ; CHECK-NEXT:    br label [[CLEANUP2]]
203 ; CHECK:       cleanup2:
204 ; CHECK-NEXT:    [[RETVAL_2:%.*]] = phi i32 [ [[A_0_LCSSA]], [[CLEANUP]] ], [ 0, [[CLEANUP2_LOOPEXIT]] ]
205 ; CHECK-NEXT:    ret i32 [[RETVAL_2]]
207 entry:
208   br label %do.body
210 do.body:                                          ; preds = %do.cond, %entry
211   %a.0 = phi i32 [ 100, %entry ], [ %rem, %do.cond ]
212   %0 = load i32, i32* %l, align 4
213   %tobool = icmp eq i32 %0, 0
214   br i1 %tobool, label %cleanup, label %do.cond
216 cleanup:                                          ; preds = %do.body
217   %a.0.lcssa = phi i32 [ %a.0, %do.body ]
218   store i32 10, i32* %l, align 4
219   br label %cleanup2
221 do.cond:                                          ; preds = %do.body
222   %mul = mul nsw i32 %a.0, 13
223   %rem = srem i32 %mul, 27
224   %1 = load i32, i32* %l, align 4
225   %tobool1 = icmp eq i32 %1, 0
226   br i1 %tobool1, label %cleanup2.loopexit, label %do.body
228 cleanup2.loopexit:                                ; preds = %do.cond
229   br label %cleanup2
231 cleanup2:                                         ; preds = %cleanup2.loopexit, %cleanup
232   %retval.2 = phi i32 [ %a.0.lcssa, %cleanup ], [ 0, %cleanup2.loopexit ]
233   ret i32 %retval.2