xref: /llvm-project/llvm/test/CodeGen/SystemZ/mixed-ptr-sizes.ll (revision c17040599666c1f14906a899cabcf545c2c85744)
1; RUN: llc < %s -mtriple s390x-ibm-zos | FileCheck %s
2; Source to regenerate:
3; struct Foo {
4;   int * __ptr32 p32;
5;   int *p64;
6;   char *cp64;
7; };
8; void use_foo(Foo *f);
9;
10; // Assiging a ptr32 value to a 64-bit pointer
11; void ptr32_to_ptr(Foo *f, int * __ptr32 i) {
12;   f->p64 = i;
13;   use_foo(f);
14; }
15;
16; // Assigning a 64-bit ptr value to a ptr32
17; void ptr_to_ptr32(Foo *f, int *i) {
18;   f->p32 = i;
19;   use_foo(f);
20; }
21;
22; // Assigning a ptr32 value to a ptr32 value
23; void ptr32_to_ptr32(Foo *f, int * __ptr32 i) {
24;   f->p32 = i;
25;   use_foo(f);
26; }
27;
28; void ptr_to_ptr(Foo *f, int *i) {
29;   f->p64 = i;
30;   use_foo(f);
31; }
32;
33; void test_indexing(Foo *f) {
34;  f->cp64 = ((char * __ptr32 *)1028)[1];
35;  use_foo(f);
36; }
37;
38; void test_indexing_2(Foo *f) {
39;   f->cp64 = ((char *** __ptr32 *)1028)[1][2][3];
40;   use_foo(f);
41; }
42;
43; unsigned long* test_misc() {
44;   unsigned long* x = (unsigned long*)((char***** __ptr32*)1208)[0][11][1][113][149];
45;   return x;
46; }
47;
48; char* __ptr32* __ptr32 test_misc_2() {
49;   static char* __ptr32* __ptr32 res = 0;
50;   if (res == 0) {
51;     res = ((char* __ptr32* __ptr32* __ptr32* __ptr32*)0)[4][136][6];
52;   }
53;   return res;
54; }
55;
56; unsigned short test_misc_3() {
57;   unsigned short this_asid = ((unsigned short*)(*(char* __ptr32*)(0x224)))[18];
58;   return this_asid;
59; }
60;
61; int test_misc_4() {
62;   int a = (*(int*)(80 + ((char**** __ptr32*)1208)[0][11][1][123]) > 0x040202FF);
63;   return a;
64; }
65;
66; void test_misc_5(struct Foo *f) {
67;   f->cp64  = *(char* __ptr32 *)(PSA_PTR + PSAAOLD);
68;   use_foo(f);
69; }
70;
71; int get_processor_count() {
72;  return ((char * __ptr32 * __ptr32 *)0)[4][165][53];
73; }
74;
75; void spill_ptr32_args_to_registers( char *__ptr32 p ) {
76;   void g ( int, ... );
77;   g ( 5, p, p, p, p, p );
78; }
79;
80; $ clang -cc1 -triple s390x-ibm-zos -fzos-extensions -O2 -S t.cpp
81;
82; For the last test case:
83;
84;#include <stdlib.h>
85;
86;int foo();
87;
88;typedef struct qa_area {/* Area descriptor                */
89;  char* __ptr32 text;           /* Start address of area          */
90;  int length;      /* Size of area in bytes          */
91;} qa_area;
92;
93;int main() {
94;  qa_area* __ptr32 fap_asm_option_a = (qa_area*)__malloc31(sizeof(qa_area));
95;
96;  //((qa_area*)fap_asm_option_a)->length   = foo(); //PASSES
97;  fap_asm_option_a->length = foo();                 //CRASHES
98;  return 0;
99;}
100
101%struct.Foo = type { ptr addrspace(1), ptr, ptr }
102declare void @use_foo(ptr)
103
104define void @ptr32_to_ptr(ptr %f, ptr addrspace(1) %i) {
105entry:
106; CHECK-LABEL: ptr32_to_ptr:
107; CHECK:       llgtr 0,2
108; CHECK-NEXT:  stg   0,8(1)
109  %0 = addrspacecast ptr addrspace(1) %i to ptr
110  %p64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 1
111  store ptr %0, ptr %p64, align 8
112  tail call void @use_foo(ptr %f)
113  ret void
114}
115
116define void @ptr_to_ptr32(ptr %f, ptr %i) {
117entry:
118; CHECK-LABEL: ptr_to_ptr32:
119; CHECK:       nilh 2,32767
120; CHECK-NEXT:  st   2,0(1)
121  %0 = addrspacecast ptr %i to ptr addrspace(1)
122  %p32 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 0
123  store ptr addrspace(1) %0, ptr %p32, align 8
124  tail call void @use_foo(ptr %f)
125  ret void
126}
127
128define void @ptr32_to_ptr32(ptr %f, ptr addrspace(1) %i) {
129entry:
130; CHECK-LABEL: ptr32_to_ptr32:
131; CHECK:       st 2,0(1)
132  %p32 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 0
133  store ptr addrspace(1) %i, ptr %p32, align 8
134  tail call void @use_foo(ptr %f)
135  ret void
136}
137
138define void @ptr_to_ptr(ptr %f, ptr %i) {
139; CHECK-LABEL: ptr_to_ptr:
140; CHECK:       stg 2,8(1)
141  %p64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 1
142  store ptr %i, ptr %p64, align 8
143  tail call void @use_foo(ptr %f)
144  ret void
145}
146
147define void @test_indexing(ptr %f) {
148entry:
149; CHECK-LABEL: test_indexing:
150; CHECK:       l     0,1032
151; CHECK:       llgtr 0,0
152; CHECK:       stg   0,16(1)
153  %0 = load ptr addrspace(1), ptr inttoptr (i64 1032 to ptr), align 8
154  %1 = addrspacecast ptr addrspace(1) %0 to ptr
155  %cp64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 2
156  store ptr %1, ptr %cp64, align 8
157  tail call void @use_foo(ptr %f)
158  ret void
159}
160
161define void @test_indexing_2(ptr %f) {
162entry:
163; CHECK-LABEL: test_indexing_2:
164; CHECK:       lhi   0,16
165; CHECK-NEXT:  a     0,1032
166; CHECK-NEXT:  llgtr 2,0
167; CHECK:       lg    0,24(2)
168; CHECK:       stg   0,16(1)
169  %0 = load ptr addrspace(1), ptr inttoptr (i64 1032 to ptr), align 8
170  %arrayidx = getelementptr inbounds ptr, ptr addrspace(1) %0, i32 2
171  %1 = load ptr, ptr addrspace(1) %arrayidx, align 8
172  %arrayidx1 = getelementptr inbounds ptr, ptr %1, i64 3
173  %2 = bitcast ptr %arrayidx1 to ptr
174  %3 = load i64, ptr %2, align 8
175  %cp64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 2
176  %4 = bitcast ptr %cp64 to ptr
177  store i64 %3, ptr %4, align 8
178  tail call void @use_foo(ptr %f)
179  ret void
180}
181
182define ptr @test_misc() {
183entry:
184; CHECK-LABEL: test_misc:
185; CHECK:       lhi   0,88
186; CHECK-NEXT:  a     0,1208
187; CHECK-NEXT:  llgtr 1,0
188; CHECK-NEXT:  lg    1,0(1)
189; CHECK-NEXT:  lg    1,8(1)
190; CHECK-NEXT:  lg    1,904(1)
191; CHECK-NEXT:  lg    3,1192(1)
192  %0 = load ptr addrspace(1), ptr inttoptr (i64 1208 to ptr), align 8
193  %arrayidx = getelementptr inbounds ptr, ptr addrspace(1) %0, i32 11
194  %1 = load ptr, ptr addrspace(1) %arrayidx, align 8
195  %arrayidx1 = getelementptr inbounds ptr, ptr %1, i64 1
196  %2 = load ptr, ptr %arrayidx1, align 8
197  %arrayidx2 = getelementptr inbounds ptr, ptr %2, i64 113
198  %3 = load ptr, ptr %arrayidx2, align 8
199  %arrayidx3 = getelementptr inbounds ptr, ptr %3, i64 149
200  %4 = bitcast ptr %arrayidx3 to ptr
201  %5 = load ptr, ptr %4, align 8
202  ret ptr %5
203}
204
205define ptr addrspace(1) @test_misc_2() {
206entry:
207; CHECK-LABEL: test_misc_2:
208; CHECK:       lhi   0,544
209; CHECK:       a     0,16
210; CHECK:       llgtr 1,0
211; CHECK:       lhi   0,24
212; CHECK:       a     0,0(1)
213; CHECK:       llgtr 1,0
214  %0 = load ptr addrspace(1), ptr inttoptr (i64 16 to ptr), align 16
215  %arrayidx = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) %0, i32 136
216  %1 = load ptr addrspace(1), ptr addrspace(1) %arrayidx, align 4
217  %arrayidx1 = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) %1, i32 6
218  %2 = load ptr addrspace(1), ptr addrspace(1) %arrayidx1, align 4
219  ret ptr addrspace(1) %2
220}
221
222define zeroext i16 @test_misc_3() {
223entry:
224; CHECK-LABEL: test_misc_3:
225; CHECK:       a     0,548
226; CHECK-NEXT:  llgtr 1,0
227; CHECK-NEXT:  llgh  3,0(1)
228; CHECK-NEXT:  b     2(7)
229  %0 = load ptr addrspace(1), ptr inttoptr (i64 548 to ptr), align 4
230  %arrayidx2 = getelementptr inbounds i16, ptr addrspace(1) %0, i32 18
231  %arrayidx = addrspacecast ptr addrspace(1) %arrayidx2 to ptr
232  %1 = load i16, ptr %arrayidx, align 2
233  ret i16 %1
234}
235
236define signext i32 @test_misc_4() {
237entry:
238; CHECK-LABEL: test_misc_4:
239; CHECK:       lhi   0,88
240; CHECK-NEXT:  a     0,1208
241; CHECK-NEXT:  llgtr 1,0
242; CHECK-NEXT:  lg    1,0(1)
243; CHECK-NEXT:  lg    1,8(1)
244; CHECK-NEXT:  lg    1,984(1)
245; CHECK-NEXT:  iilf  0,67240703
246; CHECK-NEXT:  c     0,80(1)
247  %0 = load ptr addrspace(1), ptr inttoptr (i64 1208 to ptr), align 8
248  %arrayidx = getelementptr inbounds ptr, ptr addrspace(1) %0, i32 11
249  %1 = load ptr, ptr addrspace(1) %arrayidx, align 8
250  %arrayidx1 = getelementptr inbounds ptr, ptr %1, i64 1
251  %2 = load ptr, ptr %arrayidx1, align 8
252  %arrayidx2 = getelementptr inbounds ptr, ptr %2, i64 123
253  %3 = load ptr, ptr %arrayidx2, align 8
254  %add.ptr = getelementptr inbounds i8, ptr %3, i64 80
255  %4 = bitcast ptr %add.ptr to ptr
256  %5 = load i32, ptr %4, align 4
257  %cmp = icmp sgt i32 %5, 67240703
258  %conv = zext i1 %cmp to i32
259  ret i32 %conv
260}
261
262define void @test_misc_5(ptr %f) {
263entry:
264; CHECK-LABEL: test_misc_5:
265; CHECK:       l     0,548
266; CHECK-NEXT:  lg  6,8(5)
267; CHECK-NEXT:  lg  5,0(5)
268; CHECK-NEXT:  llgtr 0,0
269; CHECK-NEXT:  stg   0,16(1)
270  %0 = load ptr addrspace(1), ptr inttoptr (i64 548 to ptr), align 4
271  %1 = addrspacecast ptr addrspace(1) %0 to ptr
272  %cp64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 2
273  store ptr %1, ptr %cp64, align 8
274  tail call void @use_foo(ptr %f)
275  ret void
276}
277
278define signext i32 @get_processor_count() {
279entry:
280; CHECK-LABEL: get_processor_count:
281; CHECK: lhi 0,660
282; CHECK-NEXT: a 0,16
283; CHECK-NEXT: llgtr 1,0
284; CHECK-NEXT: lhi 0,53
285; CHECK-NEXT: a 0,0(1)
286; CHECK-NEXT: llgtr 1,0
287; CHECK-NEXT: lgb 3,0(1)
288  %0 = load ptr addrspace(1), ptr inttoptr (i64 16 to ptr), align 16
289  %arrayidx = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) %0, i32 165
290  %1 = load ptr addrspace(1), ptr addrspace(1) %arrayidx, align 4
291  %arrayidx1 = getelementptr inbounds i8, ptr addrspace(1) %1, i32 53
292  %2 = load i8, ptr addrspace(1) %arrayidx1, align 1
293  %conv = sext i8 %2 to i32
294  ret i32 %conv
295}
296
297define void @spill_ptr32_args_to_registers(i8 addrspace(1)* %p) {
298entry:
299; CHECK-LABEL: spill_ptr32_args_to_registers:
300; CHECK:         stmg 6,7,1872(4)
301; CHECK-NEXT:    aghi 4,-192
302; CHECK-NEXT:    lgr 2,1
303; CHECK-NEXT:    lg 6,24(5)
304; CHECK-NEXT:    lg 5,16(5)
305; CHECK-NEXT:    stg 1,2216(4)
306; CHECK-NEXT:    stg 1,2208(4)
307; CHECK-NEXT:    lghi 1,5
308; CHECK-NEXT:    stg 2,2200(4)
309; CHECK-NEXT:    lgr 3,2
310; CHECK-NEXT:    basr 7,6
311; CHECK-NEXT:    bcr 0,0
312; CHECK-NEXT:    lg 7,2072(4)
313; CHECK-NEXT:    aghi 4,192
314; CHECK-NEXT:    b 2(7)
315  tail call void (i32, ...) @g(i32 noundef signext 5, ptr addrspace(1) noundef %p, ptr addrspace(1) noundef %p, ptr addrspace(1) noundef %p, ptr addrspace(1) noundef %p, ptr addrspace(1) noundef %p)
316  ret void
317}
318declare void @g(i32 signext, ...)
319
320; The resulting instructions may look odd on first view but it is a result of
321; the C code. __malloc31() returns a 64 bit pointer, thus the sequence
322;
323;        la      1, 4(8)
324;        llgtr   1, 1
325;
326; references the length attribute via the 64 bit pointer, and performs the
327; cast to __ptr32, setting the upper 32 bit to zero.
328;
329define signext i32 @setlength() {
330; CHECK-LABEL: setlength:
331; CHECK: basr    7,6
332; CHECK: lgr     [[MALLOC:[0-9]+]],3
333; CHECK: basr    7,6
334; CHECK: lgr     [[LENGTH:[0-9]+]],3
335; CHECK: la      [[ADDR:[0-9]+]],4([[MALLOC]])
336; CHECK: llgtr   [[ADDR]],[[ADDR]]
337; CHECK: stg     [[LENGTH]],0([[ADDR]])
338entry:
339  %call = tail call ptr @__malloc31(i64 noundef 8)
340  %call1 = tail call signext i32 @foo()
341  %length = getelementptr inbounds i8, ptr %call, i64 4
342  %0 = bitcast ptr %length to ptr
343  %1 = addrspacecast ptr %0 to ptr addrspace(1)
344  store i32 %call1, ptr addrspace(1) %1, align 4
345  ret i32 0
346}
347
348; Same as test before, but this time calling
349;  extern char* __ptr32 domalloc(unsigned long);
350; instead of __malloc31(). Note the different instruction sequence, because
351; the function now returns a __ptr32.
352;
353define signext i32 @setlength2() {
354; CHECK-LABEL: setlength2:
355; CHECK: basr    7,6
356; CHECK: lgr     [[MALLOC:[0-9]+]],3
357; CHECK: basr    7,6
358; CHECK: lgr     [[LENGTH:[0-9]+]],3
359; CHECK: ahi     [[MALLOC]],4
360; CHECK: llgtr   [[ADDR]],[[MALLOC]]
361; CHECK: stg     [[LENGTH]],0([[ADDR]])
362entry:
363  %call = tail call ptr addrspace(1) @domalloc(i64 noundef 8)
364  %call1 = tail call signext i32 @foo()
365  %length = getelementptr inbounds i8, ptr addrspace(1) %call, i32 4
366  %0 = bitcast ptr addrspace(1) %length to ptr addrspace(1)
367  store i32 %call1, ptr addrspace(1) %0, align 4
368  ret i32 0
369}
370
371declare ptr @__malloc31(i64)
372
373declare signext i32 @foo(...)
374
375declare ptr addrspace(1) @domalloc(i64)
376