xref: /llvm-project/llvm/test/CodeGen/PowerPC/peephole-align.ll (revision 69b056d5638bbe3c8098b5d3a4980eb9929b9bbe)
1; RUN: llc -relocation-model=static -verify-machineinstrs -mcpu=pwr7 -O1 -code-model=medium <%s | FileCheck %s
2; RUN: llc -relocation-model=static -verify-machineinstrs -mcpu=pwr8 -O1 -code-model=medium <%s | FileCheck %s
3
4; Test peephole optimization for medium code model (32-bit TOC offsets)
5; for loading and storing small offsets within aligned values.
6
7target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v128:128:128-n32:64"
8target triple = "powerpc64-unknown-linux-gnu"
9
10%struct.b4 = type<{ i8, i8, i8, i8 }>
11%struct.h2 = type<{ i16, i16 }>
12
13%struct.b8 = type<{ i8, i8, i8, i8, i8, i8, i8, i8 }>
14%struct.h4 = type<{ i16, i16, i16, i16 }>
15%struct.w2 = type<{ i32, i32 }>
16
17%struct.d2 = type<{ i64, i64 }>
18%struct.misalign = type<{ i8, i64 }>
19
20@b4v = dso_local global %struct.b4 <{ i8 1, i8 2, i8 3, i8 4 }>, align 4
21@h2v = dso_local global %struct.h2 <{ i16 1, i16 2 }>, align 4
22
23@b8v = dso_local global %struct.b8 <{ i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8 }>, align 8
24@h4v = dso_local global %struct.h4 <{ i16 1, i16 2, i16 3, i16 4 }>, align 8
25@w2v = dso_local global %struct.w2 <{ i32 1, i32 2 }>, align 8
26
27@d2v = dso_local global %struct.d2 <{ i64 1, i64 2 }>, align 16
28@misalign_v = dso_local global %struct.misalign <{ i8 1, i64 2 }>, align 16
29
30; CHECK-LABEL: test_b4:
31; CHECK: addis [[REGSTRUCT:[0-9]+]], 2, b4v@toc@ha
32; CHECK-DAG: lbz [[REG0_0:[0-9]+]], b4v@toc@l([[REGSTRUCT]])
33; CHECK-DAG: lbz [[REG1_0:[0-9]+]], b4v@toc@l+1([[REGSTRUCT]])
34; CHECK-DAG: lbz [[REG2_0:[0-9]+]], b4v@toc@l+2([[REGSTRUCT]])
35; CHECK-DAG: lbz [[REG3_0:[0-9]+]], b4v@toc@l+3([[REGSTRUCT]])
36; CHECK-DAG: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
37; CHECK-DAG: addi [[REG1_1:[0-9]+]], [[REG1_0]], 2
38; CHECK-DAG: addi [[REG2_1:[0-9]+]], [[REG2_0]], 3
39; CHECK-DAG: addi [[REG3_1:[0-9]+]], [[REG3_0]], 4
40; CHECK-DAG: stb [[REG0_1]], b4v@toc@l([[REGSTRUCT]])
41; CHECK-DAG: stb [[REG1_1]], b4v@toc@l+1([[REGSTRUCT]])
42; CHECK-DAG: stb [[REG2_1]], b4v@toc@l+2([[REGSTRUCT]])
43; CHECK-DAG: stb [[REG3_1]], b4v@toc@l+3([[REGSTRUCT]])
44
45define dso_local void @test_b4() nounwind {
46entry:
47  %0 = load i8, ptr @b4v, align 1
48  %inc0 = add nsw i8 %0, 1
49  store i8 %inc0, ptr @b4v, align 1
50  %1 = load i8, ptr getelementptr inbounds (%struct.b4, ptr @b4v, i32 0, i32 1), align 1
51  %inc1 = add nsw i8 %1, 2
52  store i8 %inc1, ptr getelementptr inbounds (%struct.b4, ptr @b4v, i32 0, i32 1), align 1
53  %2 = load i8, ptr getelementptr inbounds (%struct.b4, ptr @b4v, i32 0, i32 2), align 1
54  %inc2 = add nsw i8 %2, 3
55  store i8 %inc2, ptr getelementptr inbounds (%struct.b4, ptr @b4v, i32 0, i32 2), align 1
56  %3 = load i8, ptr getelementptr inbounds (%struct.b4, ptr @b4v, i32 0, i32 3), align 1
57  %inc3 = add nsw i8 %3, 4
58  store i8 %inc3, ptr getelementptr inbounds (%struct.b4, ptr @b4v, i32 0, i32 3), align 1
59  ret void
60}
61
62; CHECK-LABEL: test_h2:
63; CHECK: addis [[REGSTRUCT:[0-9]+]], 2, h2v@toc@ha
64; CHECK-DAG: lhz [[REG0_0:[0-9]+]], h2v@toc@l([[REGSTRUCT]])
65; CHECK-DAG: lhz [[REG1_0:[0-9]+]], h2v@toc@l+2([[REGSTRUCT]])
66; CHECK-DAG: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
67; CHECK-DAG: addi [[REG1_1:[0-9]+]], [[REG1_0]], 2
68; CHECK-DAG: sth [[REG0_1]], h2v@toc@l([[REGSTRUCT]])
69; CHECK-DAG: sth [[REG1_1]], h2v@toc@l+2([[REGSTRUCT]])
70
71define dso_local void @test_h2() nounwind {
72entry:
73  %0 = load i16, ptr @h2v, align 2
74  %inc0 = add nsw i16 %0, 1
75  store i16 %inc0, ptr @h2v, align 2
76  %1 = load i16, ptr getelementptr inbounds (%struct.h2, ptr @h2v, i32 0, i32 1), align 2
77  %inc1 = add nsw i16 %1, 2
78  store i16 %inc1, ptr getelementptr inbounds (%struct.h2, ptr @h2v, i32 0, i32 1), align 2
79  ret void
80}
81
82; CHECK-LABEL: test_h2_optsize:
83; CHECK: addis [[REGSTRUCT:[0-9]+]], 2, h2v@toc@ha
84; CHECK-DAG: lhz [[REG0_0:[0-9]+]], h2v@toc@l([[REGSTRUCT]])
85; CHECK-DAG: lhz [[REG1_0:[0-9]+]], h2v@toc@l+2([[REGSTRUCT]])
86; CHECK-DAG: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
87; CHECK-DAG: addi [[REG1_1:[0-9]+]], [[REG1_0]], 2
88; CHECK-DAG: sth [[REG0_1]], h2v@toc@l([[REGSTRUCT]])
89; CHECK-DAG: sth [[REG1_1]], h2v@toc@l+2([[REGSTRUCT]])
90define dso_local void @test_h2_optsize() optsize nounwind {
91entry:
92  %0 = load i16, ptr @h2v, align 2
93  %inc0 = add nsw i16 %0, 1
94  store i16 %inc0, ptr @h2v, align 2
95  %1 = load i16, ptr getelementptr inbounds (%struct.h2, ptr @h2v, i32 0, i32 1), align 2
96  %inc1 = add nsw i16 %1, 2
97  store i16 %inc1, ptr getelementptr inbounds (%struct.h2, ptr @h2v, i32 0, i32 1), align 2
98  ret void
99}
100
101; CHECK-LABEL: test_b8:
102; CHECK: addis [[REGSTRUCT:[0-9]+]], 2, b8v@toc@ha
103; CHECK-DAG: lbz [[REG0_0:[0-9]+]], b8v@toc@l([[REGSTRUCT]])
104; CHECK-DAG: lbz [[REG1_0:[0-9]+]], b8v@toc@l+1([[REGSTRUCT]])
105; CHECK-DAG: lbz [[REG2_0:[0-9]+]], b8v@toc@l+2([[REGSTRUCT]])
106; CHECK-DAG: lbz [[REG3_0:[0-9]+]], b8v@toc@l+3([[REGSTRUCT]])
107; CHECK-DAG: lbz [[REG4_0:[0-9]+]], b8v@toc@l+4([[REGSTRUCT]])
108; CHECK-DAG: lbz [[REG5_0:[0-9]+]], b8v@toc@l+5([[REGSTRUCT]])
109; CHECK-DAG: lbz [[REG6_0:[0-9]+]], b8v@toc@l+6([[REGSTRUCT]])
110; CHECK-DAG: lbz [[REG7_0:[0-9]+]], b8v@toc@l+7([[REGSTRUCT]])
111; CHECK-DAG: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
112; CHECK-DAG: addi [[REG1_1:[0-9]+]], [[REG1_0]], 2
113; CHECK-DAG: addi [[REG2_1:[0-9]+]], [[REG2_0]], 3
114; CHECK-DAG: addi [[REG3_1:[0-9]+]], [[REG3_0]], 4
115; CHECK-DAG: addi [[REG4_1:[0-9]+]], [[REG4_0]], 5
116; CHECK-DAG: addi [[REG5_1:[0-9]+]], [[REG5_0]], 6
117; CHECK-DAG: addi [[REG6_1:[0-9]+]], [[REG6_0]], 7
118; CHECK-DAG: addi [[REG7_1:[0-9]+]], [[REG7_0]], 8
119; CHECK-DAG: stb [[REG0_1]], b8v@toc@l([[REGSTRUCT]])
120; CHECK-DAG: stb [[REG1_1]], b8v@toc@l+1([[REGSTRUCT]])
121; CHECK-DAG: stb [[REG2_1]], b8v@toc@l+2([[REGSTRUCT]])
122; CHECK-DAG: stb [[REG3_1]], b8v@toc@l+3([[REGSTRUCT]])
123; CHECK-DAG: stb [[REG4_1]], b8v@toc@l+4([[REGSTRUCT]])
124; CHECK-DAG: stb [[REG5_1]], b8v@toc@l+5([[REGSTRUCT]])
125; CHECK-DAG: stb [[REG6_1]], b8v@toc@l+6([[REGSTRUCT]])
126; CHECK-DAG: stb [[REG7_1]], b8v@toc@l+7([[REGSTRUCT]])
127
128define dso_local void @test_b8() nounwind {
129entry:
130  %0 = load i8, ptr @b8v, align 1
131  %inc0 = add nsw i8 %0, 1
132  store i8 %inc0, ptr @b8v, align 1
133  %1 = load i8, ptr getelementptr inbounds (%struct.b8, ptr @b8v, i32 0, i32 1), align 1
134  %inc1 = add nsw i8 %1, 2
135  store i8 %inc1, ptr getelementptr inbounds (%struct.b8, ptr @b8v, i32 0, i32 1), align 1
136  %2 = load i8, ptr getelementptr inbounds (%struct.b8, ptr @b8v, i32 0, i32 2), align 1
137  %inc2 = add nsw i8 %2, 3
138  store i8 %inc2, ptr getelementptr inbounds (%struct.b8, ptr @b8v, i32 0, i32 2), align 1
139  %3 = load i8, ptr getelementptr inbounds (%struct.b8, ptr @b8v, i32 0, i32 3), align 1
140  %inc3 = add nsw i8 %3, 4
141  store i8 %inc3, ptr getelementptr inbounds (%struct.b8, ptr @b8v, i32 0, i32 3), align 1
142  %4 = load i8, ptr getelementptr inbounds (%struct.b8, ptr @b8v, i32 0, i32 4), align 1
143  %inc4 = add nsw i8 %4, 5
144  store i8 %inc4, ptr getelementptr inbounds (%struct.b8, ptr @b8v, i32 0, i32 4), align 1
145  %5 = load i8, ptr getelementptr inbounds (%struct.b8, ptr @b8v, i32 0, i32 5), align 1
146  %inc5 = add nsw i8 %5, 6
147  store i8 %inc5, ptr getelementptr inbounds (%struct.b8, ptr @b8v, i32 0, i32 5), align 1
148  %6 = load i8, ptr getelementptr inbounds (%struct.b8, ptr @b8v, i32 0, i32 6), align 1
149  %inc6 = add nsw i8 %6, 7
150  store i8 %inc6, ptr getelementptr inbounds (%struct.b8, ptr @b8v, i32 0, i32 6), align 1
151  %7 = load i8, ptr getelementptr inbounds (%struct.b8, ptr @b8v, i32 0, i32 7), align 1
152  %inc7 = add nsw i8 %7, 8
153  store i8 %inc7, ptr getelementptr inbounds (%struct.b8, ptr @b8v, i32 0, i32 7), align 1
154  ret void
155}
156
157; CHECK-LABEL: test_h4:
158; CHECK: addis [[REGSTRUCT:[0-9]+]], 2, h4v@toc@ha
159; CHECK-DAG: lhz [[REG0_0:[0-9]+]], h4v@toc@l([[REGSTRUCT]])
160; CHECK-DAG: lhz [[REG1_0:[0-9]+]], h4v@toc@l+2([[REGSTRUCT]])
161; CHECK-DAG: lhz [[REG2_0:[0-9]+]], h4v@toc@l+4([[REGSTRUCT]])
162; CHECK-DAG: lhz [[REG3_0:[0-9]+]], h4v@toc@l+6([[REGSTRUCT]])
163; CHECK-DAG: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
164; CHECK-DAG: addi [[REG1_1:[0-9]+]], [[REG1_0]], 2
165; CHECK-DAG: addi [[REG2_1:[0-9]+]], [[REG2_0]], 3
166; CHECK-DAG: addi [[REG3_1:[0-9]+]], [[REG3_0]], 4
167; CHECK-DAG: sth [[REG0_1]], h4v@toc@l([[REGSTRUCT]])
168; CHECK-DAG: sth [[REG1_1]], h4v@toc@l+2([[REGSTRUCT]])
169; CHECK-DAG: sth [[REG2_1]], h4v@toc@l+4([[REGSTRUCT]])
170; CHECK-DAG: sth [[REG3_1]], h4v@toc@l+6([[REGSTRUCT]])
171
172define dso_local void @test_h4() nounwind {
173entry:
174  %0 = load i16, ptr @h4v, align 2
175  %inc0 = add nsw i16 %0, 1
176  store i16 %inc0, ptr @h4v, align 2
177  %1 = load i16, ptr getelementptr inbounds (%struct.h4, ptr @h4v, i32 0, i32 1), align 2
178  %inc1 = add nsw i16 %1, 2
179  store i16 %inc1, ptr getelementptr inbounds (%struct.h4, ptr @h4v, i32 0, i32 1), align 2
180  %2 = load i16, ptr getelementptr inbounds (%struct.h4, ptr @h4v, i32 0, i32 2), align 2
181  %inc2 = add nsw i16 %2, 3
182  store i16 %inc2, ptr getelementptr inbounds (%struct.h4, ptr @h4v, i32 0, i32 2), align 2
183  %3 = load i16, ptr getelementptr inbounds (%struct.h4, ptr @h4v, i32 0, i32 3), align 2
184  %inc3 = add nsw i16 %3, 4
185  store i16 %inc3, ptr getelementptr inbounds (%struct.h4, ptr @h4v, i32 0, i32 3), align 2
186  ret void
187}
188
189; CHECK-LABEL: test_w2:
190; CHECK: addis [[REGSTRUCT:[0-9]+]], 2, w2v@toc@ha
191; CHECK-DAG: lwz [[REG0_0:[0-9]+]], w2v@toc@l([[REGSTRUCT]])
192; CHECK-DAG: lwz [[REG1_0:[0-9]+]], w2v@toc@l+4([[REGSTRUCT]])
193; CHECK-DAG: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
194; CHECK-DAG: addi [[REG1_1:[0-9]+]], [[REG1_0]], 2
195; CHECK-DAG: stw [[REG0_1]], w2v@toc@l([[REGSTRUCT]])
196; CHECK-DAG: stw [[REG1_1]], w2v@toc@l+4([[REGSTRUCT]])
197
198define dso_local void @test_w2() nounwind {
199entry:
200  %0 = load i32, ptr @w2v, align 4
201  %inc0 = add nsw i32 %0, 1
202  store i32 %inc0, ptr @w2v, align 4
203  %1 = load i32, ptr getelementptr inbounds (%struct.w2, ptr @w2v, i32 0, i32 1), align 4
204  %inc1 = add nsw i32 %1, 2
205  store i32 %inc1, ptr getelementptr inbounds (%struct.w2, ptr @w2v, i32 0, i32 1), align 4
206  ret void
207}
208
209; CHECK-LABEL: test_d2:
210; CHECK: addis [[REGSTRUCT:[0-9]+]], 2, d2v@toc@ha
211; CHECK: ld [[REG0_0:[0-9]+]], d2v@toc@l([[REGSTRUCT]])
212; CHECK: addi [[BASEV:[0-9]+]], [[REGSTRUCT]], d2v@toc@l
213; CHECK-DAG: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
214; CHECK-DAG: ld [[REG1_0:[0-9]+]], 8([[BASEV]])
215; CHECK-DAG: addi [[REG1_1:[0-9]+]], [[REG1_0]], 2
216; CHECK-DAG: std [[REG0_1]], d2v@toc@l([[REGSTRUCT]])
217; CHECK-DAG: std [[REG1_1]], 8([[BASEV]])
218
219define dso_local void @test_d2() nounwind {
220entry:
221  %0 = load i64, ptr @d2v, align 8
222  %inc0 = add nsw i64 %0, 1
223  store i64 %inc0, ptr @d2v, align 8
224  %1 = load i64, ptr getelementptr inbounds (%struct.d2, ptr @d2v, i32 0, i32 1), align 8
225  %inc1 = add nsw i64 %1, 2
226  store i64 %inc1, ptr getelementptr inbounds (%struct.d2, ptr @d2v, i32 0, i32 1), align 8
227  ret void
228}
229
230; CHECK-LABEL: test_singleuse:
231; CHECK: addis [[REG:[0-9]+]], 2, d2v@toc@ha+8
232; CHECK: ld 3, d2v@toc@l+8([[REG]])
233define i64 @test_singleuse() nounwind {
234entry:
235  %0 = load i64, ptr getelementptr inbounds (%struct.d2, ptr @d2v, i32 0, i32 1), align 8
236  ret i64 %0
237}
238
239; Make sure the optimization fails to fire if the symbol is aligned, but the offset is not.
240; CHECK-LABEL: test_misalign
241; CHECK: addis [[REGSTRUCT_0:[0-9]+]], 2, misalign_v@toc@ha
242; CHECK-DAG: addi [[REGSTRUCT:[0-9]+]], [[REGSTRUCT_0]], misalign_v@toc@l
243; CHECK-DAG: li [[OFFSET_REG:[0-9]+]], 1
244; CHECK: ldx [[REG0_0:[0-9]+]], [[REGSTRUCT]], [[OFFSET_REG]]
245; CHECK: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
246; CHECK: stdx [[REG0_1]], [[REGSTRUCT]], [[OFFSET_REG]]
247define dso_local void @test_misalign() nounwind {
248entry:
249  %0 = load i64, ptr getelementptr inbounds (%struct.misalign, ptr @misalign_v, i32 0, i32 1), align 1
250  %inc0 = add nsw i64 %0, 1
251  store i64 %inc0, ptr getelementptr inbounds (%struct.misalign, ptr @misalign_v, i32 0, i32 1), align 1
252  ret void
253}
254