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