xref: /llvm-project/llvm/test/CodeGen/SystemZ/int-move-10.ll (revision 0a76f7d9d8c1fc693568ed26420c47d92a6ba0e7)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
2; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
3;
4; Test PC-relative memory accesses of globals with packed struct types.
5; PC-relative memory accesses cannot be used when the address is not
6; aligned. This can happen with programs like the following (which are not
7; strictly correct):
8;
9; #pragma pack(1)
10; struct  {
11;   short a;
12;   int b;
13; } c;
14;
15; void main()    {
16;   int *e = &c.b;
17;   *e = 0;
18; }
19;
20
21%packed.i16i32 = type <{ i16, i32 }>
22%packed.i16i32i16i32 = type <{ i16, i32, i16, i32 }>
23%packed.i16i64 = type <{ i16, i64 }>
24%packed.i8i16 = type <{ i8, i16 }>
25
26@A_align2 = dso_local global %packed.i16i32 zeroinitializer, align 2
27@B_align2 = dso_local global %packed.i16i32i16i32 zeroinitializer, align 2
28@C_align2 = dso_local global %packed.i16i64 zeroinitializer, align 2
29@D_align4 = dso_local global %packed.i16i32 zeroinitializer, align 4
30@E_align4 = dso_local global %packed.i16i32i16i32 zeroinitializer, align 4
31@F_align2 = dso_local global %packed.i8i16 zeroinitializer, align 2
32
33;;; Stores
34
35; unaligned packed struct + 2  -> unaligned address
36define dso_local void @f1() {
37; CHECK-LABEL: f1:
38; CHECK:       # %bb.0:
39; CHECK-NEXT:    larl %r1, A_align2
40; CHECK-NEXT:    mvhi 2(%r1), 0
41; CHECK-NEXT:    br %r14
42  store i32 0, ptr getelementptr inbounds (%packed.i16i32, ptr @A_align2, i64 0, i32 1), align 4
43  ret void
44}
45
46; unaligned packed struct  + 8  -> unaligned address
47define dso_local void @f2() {
48; CHECK-LABEL: f2:
49; CHECK:       # %bb.0:
50; CHECK-NEXT:    larl %r1, B_align2
51; CHECK-NEXT:    mvhi 8(%r1), 0
52; CHECK-NEXT:    br %r14
53  store i32 0, ptr getelementptr inbounds (%packed.i16i32i16i32, ptr @B_align2, i64 0, i32 3), align 4
54  ret void
55}
56
57; aligned packed struct + 2  -> unaligned address
58define dso_local void @f3() {
59; CHECK-LABEL: f3:
60; CHECK:       # %bb.0:
61; CHECK-NEXT:    larl %r1, D_align4
62; CHECK-NEXT:    mvhi 2(%r1), 0
63; CHECK-NEXT:    br %r14
64  store i32 0, ptr getelementptr inbounds (%packed.i16i32, ptr @D_align4, i64 0, i32 1), align 4
65  ret void
66}
67
68; aligned packed struct + 8  -> aligned address
69define dso_local void @f4() {
70; CHECK-LABEL: f4:
71; CHECK:       # %bb.0:
72; CHECK-NEXT:    lhi %r0, 0
73; CHECK-NEXT:    strl %r0, E_align4+8
74; CHECK-NEXT:    br %r14
75  store i32 0, ptr getelementptr inbounds (%packed.i16i32i16i32, ptr @E_align4, i64 0, i32 3), align 4
76  ret void
77}
78
79define dso_local void @f5() {
80; CHECK-LABEL: f5:
81; CHECK:       # %bb.0:
82; CHECK-NEXT:    larl %r1, C_align2
83; CHECK-NEXT:    mvghi 2(%r1), 0
84; CHECK-NEXT:    br %r14
85  store i64 0, ptr getelementptr inbounds (%packed.i16i64, ptr @C_align2, i64 0, i32 1), align 8
86  ret void
87}
88
89define dso_local void @f6() {
90; CHECK-LABEL: f6:
91; CHECK:       # %bb.0:
92; CHECK-NEXT:    larl %r1, F_align2
93; CHECK-NEXT:    mvhhi 1(%r1), 0
94; CHECK-NEXT:    br %r14
95  store i16 0, ptr getelementptr inbounds (%packed.i8i16, ptr @F_align2, i64 0, i32 1), align 2
96  ret void
97}
98
99define dso_local void @f7(ptr %Src) {
100; CHECK-LABEL: f7:
101; CHECK:       # %bb.0:
102; CHECK-NEXT:    lg %r0, 0(%r2)
103; CHECK-NEXT:    larl %r1, D_align4
104; CHECK-NEXT:    st %r0, 2(%r1)
105; CHECK-NEXT:    br %r14
106  %L = load i64, ptr %Src
107  %T = trunc i64 %L to i32
108  store i32 %T, ptr getelementptr inbounds (%packed.i16i32, ptr @D_align4, i64 0, i32 1), align 4
109  ret void
110}
111
112define dso_local void @f8(ptr %Src) {
113; CHECK-LABEL: f8:
114; CHECK:       # %bb.0:
115; CHECK-NEXT:    lg %r0, 0(%r2)
116; CHECK-NEXT:    larl %r1, F_align2
117; CHECK-NEXT:    sth %r0, 1(%r1)
118; CHECK-NEXT:    br %r14
119  %L = load i64, ptr %Src
120  %T = trunc i64 %L to i16
121  store i16 %T, ptr getelementptr inbounds (%packed.i8i16, ptr @F_align2, i64 0, i32 1), align 2
122  ret void
123}
124
125;;; Loads
126
127; unaligned packed struct + 2  -> unaligned address
128define dso_local i32 @f9() {
129; CHECK-LABEL: f9:
130; CHECK:       # %bb.0:
131; CHECK-NEXT:    larl %r1, A_align2
132; CHECK-NEXT:    l %r2, 2(%r1)
133; CHECK-NEXT:    br %r14
134  %L = load i32, ptr getelementptr inbounds (%packed.i16i32, ptr @A_align2, i64 0, i32 1), align 4
135  ret i32 %L
136}
137
138; unaligned packed struct  + 8  -> unaligned address
139define dso_local i32 @f10() {
140; CHECK-LABEL: f10:
141; CHECK:       # %bb.0:
142; CHECK-NEXT:    larl %r1, B_align2
143; CHECK-NEXT:    l %r2, 8(%r1)
144; CHECK-NEXT:    br %r14
145  %L = load i32, ptr getelementptr inbounds (%packed.i16i32i16i32, ptr @B_align2, i64 0, i32 3), align 4
146  ret i32 %L
147}
148
149; aligned packed struct + 2  -> unaligned address
150define dso_local i32 @f11() {
151; CHECK-LABEL: f11:
152; CHECK:       # %bb.0:
153; CHECK-NEXT:    larl %r1, D_align4
154; CHECK-NEXT:    l %r2, 2(%r1)
155; CHECK-NEXT:    br %r14
156  %L = load i32, ptr getelementptr inbounds (%packed.i16i32, ptr @D_align4, i64 0, i32 1), align 4
157  ret i32 %L
158}
159
160; aligned packed struct + 8  -> aligned address
161define dso_local i32 @f12() {
162; CHECK-LABEL: f12:
163; CHECK:       # %bb.0:
164; CHECK-NEXT:    lrl %r2, E_align4+8
165; CHECK-NEXT:    br %r14
166  %L = load i32, ptr getelementptr inbounds (%packed.i16i32i16i32, ptr @E_align4, i64 0, i32 3), align 4
167  ret i32 %L
168}
169
170define dso_local i64 @f13() {
171; CHECK-LABEL: f13:
172; CHECK:       # %bb.0:
173; CHECK-NEXT:    larl %r1, C_align2
174; CHECK-NEXT:    lg %r2, 2(%r1)
175; CHECK-NEXT:    br %r14
176  %L = load i64, ptr getelementptr inbounds (%packed.i16i64, ptr @C_align2, i64 0, i32 1), align 8
177  ret i64 %L
178}
179
180define dso_local i32 @f14() {
181; CHECK-LABEL: f14:
182; CHECK:       # %bb.0:
183; CHECK-NEXT:    larl %r1, F_align2
184; CHECK-NEXT:    lh %r2, 1(%r1)
185; CHECK-NEXT:    br %r14
186  %L = load i16, ptr getelementptr inbounds (%packed.i8i16, ptr @F_align2, i64 0, i32 1), align 2
187  %ext = sext i16 %L to i32
188  ret i32 %ext
189}
190
191define dso_local i64 @f15() {
192; CHECK-LABEL: f15:
193; CHECK:       # %bb.0:
194; CHECK-NEXT:    larl %r1, F_align2
195; CHECK-NEXT:    llgh %r2, 1(%r1)
196; CHECK-NEXT:    br %r14
197  %L = load i16, ptr getelementptr inbounds (%packed.i8i16, ptr @F_align2, i64 0, i32 1), align 2
198  %ext = zext i16 %L to i64
199  ret i64 %ext
200}
201
202;;; Loads folded into compare instructions
203
204define dso_local i32 @f16(i32 %src1) {
205; CHECK-LABEL: f16:
206; CHECK:       # %bb.0: # %entry
207; CHECK-NEXT:    larl %r1, A_align2
208; CHECK-NEXT:    c %r2, 2(%r1)
209; CHECK-NEXT:    blr %r14
210; CHECK-NEXT:  .LBB15_1: # %mulb
211; CHECK-NEXT:    msr %r2, %r2
212; CHECK-NEXT:    br %r14
213entry:
214  %src2 = load i32, ptr getelementptr inbounds (%packed.i16i32, ptr @A_align2, i64 0, i32 1), align 4
215  %cond = icmp slt i32 %src1, %src2
216  br i1 %cond, label %exit, label %mulb
217mulb:
218  %mul = mul i32 %src1, %src1
219  br label %exit
220exit:
221  %res = phi i32 [ %src1, %entry ], [ %mul, %mulb ]
222  ret i32 %res
223}
224
225define dso_local i64 @f17(i64 %src1) {
226; CHECK-LABEL: f17:
227; CHECK:       # %bb.0: # %entry
228; CHECK-NEXT:    larl %r1, C_align2
229; CHECK-NEXT:    clg %r2, 2(%r1)
230; CHECK-NEXT:    blr %r14
231; CHECK-NEXT:  .LBB16_1: # %mulb
232; CHECK-NEXT:    msgr %r2, %r2
233; CHECK-NEXT:    br %r14
234entry:
235  %src2 = load i64, ptr getelementptr inbounds (%packed.i16i64, ptr @C_align2, i64 0, i32 1), align 8
236  %cond = icmp ult i64 %src1, %src2
237  br i1 %cond, label %exit, label %mulb
238mulb:
239  %mul = mul i64 %src1, %src1
240  br label %exit
241exit:
242  %res = phi i64 [ %src1, %entry ], [ %mul, %mulb ]
243  ret i64 %res
244}
245