xref: /llvm-project/llvm/test/Transforms/LoopFlatten/loop-flatten-gep.ll (revision 4d1ecf192313b612090d60181937eff03c1a966b)
1ae978baaSJohn Brawn; RUN: opt < %s -S -passes='loop(loop-flatten),verify' -verify-loop-info -verify-dom-info -verify-scev | FileCheck %s
2ae978baaSJohn Brawn
3ae978baaSJohn Brawntarget datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
4ae978baaSJohn Brawn
5ae978baaSJohn Brawn; We should be able to flatten the loops and turn the two geps into one.
6ae978baaSJohn Brawn; CHECK-LABEL: test1
7ae978baaSJohn Brawndefine void @test1(i32 %N, ptr %A) {
8ae978baaSJohn Brawnentry:
9ae978baaSJohn Brawn  %cmp3 = icmp ult i32 0, %N
10ae978baaSJohn Brawn  br i1 %cmp3, label %for.outer.preheader, label %for.end
11ae978baaSJohn Brawn
12ae978baaSJohn Brawn; CHECK-LABEL: for.outer.preheader:
13ae978baaSJohn Brawn; CHECK: %flatten.tripcount = mul i32 %N, %N
14ae978baaSJohn Brawnfor.outer.preheader:
15ae978baaSJohn Brawn  br label %for.inner.preheader
16ae978baaSJohn Brawn
17ae978baaSJohn Brawn; CHECK-LABEL: for.inner.preheader:
18*4d1ecf19SAtariDreams; CHECK: %flatten.arrayidx = getelementptr inbounds i32, ptr %A, i32 %i
19ae978baaSJohn Brawnfor.inner.preheader:
20ae978baaSJohn Brawn  %i = phi i32 [ 0, %for.outer.preheader ], [ %inc2, %for.outer ]
21ae978baaSJohn Brawn  br label %for.inner
22ae978baaSJohn Brawn
23ae978baaSJohn Brawn; CHECK-LABEL: for.inner:
24ae978baaSJohn Brawn; CHECK: store i32 0, ptr %flatten.arrayidx, align 4
25ae978baaSJohn Brawn; CHECK: br label %for.outer
26ae978baaSJohn Brawnfor.inner:
27ae978baaSJohn Brawn  %j = phi i32 [ 0, %for.inner.preheader ], [ %inc1, %for.inner ]
28ae978baaSJohn Brawn  %mul = mul i32 %i, %N
29ae978baaSJohn Brawn  %gep = getelementptr inbounds i32, ptr %A, i32 %mul
30ae978baaSJohn Brawn  %arrayidx = getelementptr inbounds i32, ptr %gep, i32 %j
31ae978baaSJohn Brawn  store i32 0, ptr %arrayidx, align 4
32ae978baaSJohn Brawn  %inc1 = add nuw i32 %j, 1
33ae978baaSJohn Brawn  %cmp2 = icmp ult i32 %inc1, %N
34ae978baaSJohn Brawn  br i1 %cmp2, label %for.inner, label %for.outer
35ae978baaSJohn Brawn
36ae978baaSJohn Brawn; CHECK-LABEL: for.outer:
37ae978baaSJohn Brawn; CHECK: %cmp1 = icmp ult i32 %inc2, %flatten.tripcount
38ae978baaSJohn Brawnfor.outer:
39ae978baaSJohn Brawn  %inc2 = add i32 %i, 1
40ae978baaSJohn Brawn  %cmp1 = icmp ult i32 %inc2, %N
41ae978baaSJohn Brawn  br i1 %cmp1, label %for.inner.preheader, label %for.end.loopexit
42ae978baaSJohn Brawn
43ae978baaSJohn Brawnfor.end.loopexit:
44ae978baaSJohn Brawn  br label %for.end
45ae978baaSJohn Brawn
46ae978baaSJohn Brawnfor.end:
47ae978baaSJohn Brawn  ret void
48ae978baaSJohn Brawn}
49ae978baaSJohn Brawn
50ae978baaSJohn Brawn; We can flatten, but the flattened gep has to be inserted after the load it
51ae978baaSJohn Brawn; depends on.
52ae978baaSJohn Brawn; CHECK-LABEL: test2
53ae978baaSJohn Brawndefine void @test2(i32 %N, ptr %A) {
54ae978baaSJohn Brawnentry:
55ae978baaSJohn Brawn  %cmp3 = icmp ult i32 0, %N
56ae978baaSJohn Brawn  br i1 %cmp3, label %for.outer.preheader, label %for.end
57ae978baaSJohn Brawn
58ae978baaSJohn Brawn; CHECK-LABEL: for.outer.preheader:
59ae978baaSJohn Brawn; CHECK: %flatten.tripcount = mul i32 %N, %N
60ae978baaSJohn Brawnfor.outer.preheader:
61ae978baaSJohn Brawn  br label %for.inner.preheader
62ae978baaSJohn Brawn
63ae978baaSJohn Brawn; CHECK-LABEL: for.inner.preheader:
64*4d1ecf19SAtariDreams; CHECK-NOT: getelementptr inbounds i32, ptr %ptr, i32 %i
65ae978baaSJohn Brawnfor.inner.preheader:
66ae978baaSJohn Brawn  %i = phi i32 [ 0, %for.outer.preheader ], [ %inc2, %for.outer ]
67ae978baaSJohn Brawn  br label %for.inner
68ae978baaSJohn Brawn
69ae978baaSJohn Brawn; CHECK-LABEL: for.inner:
70*4d1ecf19SAtariDreams; CHECK: %flatten.arrayidx = getelementptr inbounds i32, ptr %ptr, i32 %i
71ae978baaSJohn Brawn; CHECK: store i32 0, ptr %flatten.arrayidx, align 4
72ae978baaSJohn Brawn; CHECK: br label %for.outer
73ae978baaSJohn Brawnfor.inner:
74ae978baaSJohn Brawn  %j = phi i32 [ 0, %for.inner.preheader ], [ %inc1, %for.inner ]
75ae978baaSJohn Brawn  %ptr = load volatile ptr, ptr %A, align 4
76ae978baaSJohn Brawn  %mul = mul i32 %i, %N
77ae978baaSJohn Brawn  %gep = getelementptr inbounds i32, ptr %ptr, i32 %mul
78ae978baaSJohn Brawn  %arrayidx = getelementptr inbounds i32, ptr %gep, i32 %j
79ae978baaSJohn Brawn  store i32 0, ptr %arrayidx, align 4
80ae978baaSJohn Brawn  %inc1 = add nuw i32 %j, 1
81ae978baaSJohn Brawn  %cmp2 = icmp ult i32 %inc1, %N
82ae978baaSJohn Brawn  br i1 %cmp2, label %for.inner, label %for.outer
83ae978baaSJohn Brawn
84ae978baaSJohn Brawn; CHECK-LABEL: for.outer:
85ae978baaSJohn Brawn; CHECK: %cmp1 = icmp ult i32 %inc2, %flatten.tripcount
86ae978baaSJohn Brawnfor.outer:
87ae978baaSJohn Brawn  %inc2 = add i32 %i, 1
88ae978baaSJohn Brawn  %cmp1 = icmp ult i32 %inc2, %N
89ae978baaSJohn Brawn  br i1 %cmp1, label %for.inner.preheader, label %for.end.loopexit
90ae978baaSJohn Brawn
91ae978baaSJohn Brawnfor.end.loopexit:
92ae978baaSJohn Brawn  br label %for.end
93ae978baaSJohn Brawn
94ae978baaSJohn Brawnfor.end:
95ae978baaSJohn Brawn  ret void
96ae978baaSJohn Brawn}
97ae978baaSJohn Brawn
98ae978baaSJohn Brawn; We can't flatten if the gep offset is smaller than the pointer size.
99ae978baaSJohn Brawn; CHECK-LABEL: test3
100ae978baaSJohn Brawndefine void @test3(i16 %N, ptr %A) {
101ae978baaSJohn Brawnentry:
102ae978baaSJohn Brawn  %cmp3 = icmp ult i16 0, %N
103ae978baaSJohn Brawn  br i1 %cmp3, label %for.outer.preheader, label %for.end
104ae978baaSJohn Brawn
105ae978baaSJohn Brawnfor.outer.preheader:
106ae978baaSJohn Brawn  br label %for.inner.preheader
107ae978baaSJohn Brawn
108ae978baaSJohn Brawn; CHECK-LABEL: for.inner.preheader:
109ae978baaSJohn Brawn; CHECK-NOT: getelementptr i32, ptr %A, i16 %i
110ae978baaSJohn Brawnfor.inner.preheader:
111ae978baaSJohn Brawn  %i = phi i16 [ 0, %for.outer.preheader ], [ %inc2, %for.outer ]
112ae978baaSJohn Brawn  br label %for.inner
113ae978baaSJohn Brawn
114ae978baaSJohn Brawn; CHECK-LABEL: for.inner:
115ae978baaSJohn Brawn; CHECK-NOT: getelementptr i32, ptr %A, i16 %i
116ae978baaSJohn Brawn; CHECK: br i1 %cmp2, label %for.inner, label %for.outer
117ae978baaSJohn Brawnfor.inner:
118ae978baaSJohn Brawn  %j = phi i16 [ 0, %for.inner.preheader ], [ %inc1, %for.inner ]
119ae978baaSJohn Brawn  %mul = mul i16 %i, %N
120ae978baaSJohn Brawn  %gep = getelementptr inbounds i32, ptr %A, i16 %mul
121ae978baaSJohn Brawn  %arrayidx = getelementptr inbounds i32, ptr %gep, i16 %j
122ae978baaSJohn Brawn  store i32 0, ptr %arrayidx, align 4
123ae978baaSJohn Brawn  %inc1 = add nuw i16 %j, 1
124ae978baaSJohn Brawn  %cmp2 = icmp ult i16 %inc1, %N
125ae978baaSJohn Brawn  br i1 %cmp2, label %for.inner, label %for.outer
126ae978baaSJohn Brawn
127ae978baaSJohn Brawnfor.outer:
128ae978baaSJohn Brawn  %inc2 = add i16 %i, 1
129ae978baaSJohn Brawn  %cmp1 = icmp ult i16 %inc2, %N
130ae978baaSJohn Brawn  br i1 %cmp1, label %for.inner.preheader, label %for.end.loopexit
131ae978baaSJohn Brawn
132ae978baaSJohn Brawnfor.end.loopexit:
133ae978baaSJohn Brawn  br label %for.end
134ae978baaSJohn Brawn
135ae978baaSJohn Brawnfor.end:
136ae978baaSJohn Brawn  ret void
137ae978baaSJohn Brawn}
138