
Now that the GNU and HLASM `InstPrinter` paths are separated in https://github.com/llvm/llvm-project/pull/112975, differentiate between them in `SystemZInstrFormats.td`. The main difference are: - Tabs converted to space - Remove space after comma for instruction operands --------- Co-authored-by: Tony Tao <tonytao@ca.ibm.com>
376 lines
11 KiB
LLVM
376 lines
11 KiB
LLVM
; RUN: llc < %s -mtriple s390x-ibm-zos | FileCheck %s
|
|
; Source to regenerate:
|
|
; struct Foo {
|
|
; int * __ptr32 p32;
|
|
; int *p64;
|
|
; char *cp64;
|
|
; };
|
|
; void use_foo(Foo *f);
|
|
;
|
|
; // Assiging a ptr32 value to a 64-bit pointer
|
|
; void ptr32_to_ptr(Foo *f, int * __ptr32 i) {
|
|
; f->p64 = i;
|
|
; use_foo(f);
|
|
; }
|
|
;
|
|
; // Assigning a 64-bit ptr value to a ptr32
|
|
; void ptr_to_ptr32(Foo *f, int *i) {
|
|
; f->p32 = i;
|
|
; use_foo(f);
|
|
; }
|
|
;
|
|
; // Assigning a ptr32 value to a ptr32 value
|
|
; void ptr32_to_ptr32(Foo *f, int * __ptr32 i) {
|
|
; f->p32 = i;
|
|
; use_foo(f);
|
|
; }
|
|
;
|
|
; void ptr_to_ptr(Foo *f, int *i) {
|
|
; f->p64 = i;
|
|
; use_foo(f);
|
|
; }
|
|
;
|
|
; void test_indexing(Foo *f) {
|
|
; f->cp64 = ((char * __ptr32 *)1028)[1];
|
|
; use_foo(f);
|
|
; }
|
|
;
|
|
; void test_indexing_2(Foo *f) {
|
|
; f->cp64 = ((char *** __ptr32 *)1028)[1][2][3];
|
|
; use_foo(f);
|
|
; }
|
|
;
|
|
; unsigned long* test_misc() {
|
|
; unsigned long* x = (unsigned long*)((char***** __ptr32*)1208)[0][11][1][113][149];
|
|
; return x;
|
|
; }
|
|
;
|
|
; char* __ptr32* __ptr32 test_misc_2() {
|
|
; static char* __ptr32* __ptr32 res = 0;
|
|
; if (res == 0) {
|
|
; res = ((char* __ptr32* __ptr32* __ptr32* __ptr32*)0)[4][136][6];
|
|
; }
|
|
; return res;
|
|
; }
|
|
;
|
|
; unsigned short test_misc_3() {
|
|
; unsigned short this_asid = ((unsigned short*)(*(char* __ptr32*)(0x224)))[18];
|
|
; return this_asid;
|
|
; }
|
|
;
|
|
; int test_misc_4() {
|
|
; int a = (*(int*)(80 + ((char**** __ptr32*)1208)[0][11][1][123]) > 0x040202FF);
|
|
; return a;
|
|
; }
|
|
;
|
|
; void test_misc_5(struct Foo *f) {
|
|
; f->cp64 = *(char* __ptr32 *)(PSA_PTR + PSAAOLD);
|
|
; use_foo(f);
|
|
; }
|
|
;
|
|
; int get_processor_count() {
|
|
; return ((char * __ptr32 * __ptr32 *)0)[4][165][53];
|
|
; }
|
|
;
|
|
; void spill_ptr32_args_to_registers( char *__ptr32 p ) {
|
|
; void g ( int, ... );
|
|
; g ( 5, p, p, p, p, p );
|
|
; }
|
|
;
|
|
; $ clang -cc1 -triple s390x-ibm-zos -fzos-extensions -O2 -S t.cpp
|
|
;
|
|
; For the last test case:
|
|
;
|
|
;#include <stdlib.h>
|
|
;
|
|
;int foo();
|
|
;
|
|
;typedef struct qa_area {/* Area descriptor */
|
|
; char* __ptr32 text; /* Start address of area */
|
|
; int length; /* Size of area in bytes */
|
|
;} qa_area;
|
|
;
|
|
;int main() {
|
|
; qa_area* __ptr32 fap_asm_option_a = (qa_area*)__malloc31(sizeof(qa_area));
|
|
;
|
|
; //((qa_area*)fap_asm_option_a)->length = foo(); //PASSES
|
|
; fap_asm_option_a->length = foo(); //CRASHES
|
|
; return 0;
|
|
;}
|
|
|
|
%struct.Foo = type { ptr addrspace(1), ptr, ptr }
|
|
declare void @use_foo(ptr)
|
|
|
|
define void @ptr32_to_ptr(ptr %f, ptr addrspace(1) %i) {
|
|
entry:
|
|
; CHECK-LABEL: ptr32_to_ptr:
|
|
; CHECK: llgtr 0,2
|
|
; CHECK-NEXT: stg 0,8(1)
|
|
%0 = addrspacecast ptr addrspace(1) %i to ptr
|
|
%p64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 1
|
|
store ptr %0, ptr %p64, align 8
|
|
tail call void @use_foo(ptr %f)
|
|
ret void
|
|
}
|
|
|
|
define void @ptr_to_ptr32(ptr %f, ptr %i) {
|
|
entry:
|
|
; CHECK-LABEL: ptr_to_ptr32:
|
|
; CHECK: nilh 2,32767
|
|
; CHECK-NEXT: st 2,0(1)
|
|
%0 = addrspacecast ptr %i to ptr addrspace(1)
|
|
%p32 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 0
|
|
store ptr addrspace(1) %0, ptr %p32, align 8
|
|
tail call void @use_foo(ptr %f)
|
|
ret void
|
|
}
|
|
|
|
define void @ptr32_to_ptr32(ptr %f, ptr addrspace(1) %i) {
|
|
entry:
|
|
; CHECK-LABEL: ptr32_to_ptr32:
|
|
; CHECK: st 2,0(1)
|
|
%p32 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 0
|
|
store ptr addrspace(1) %i, ptr %p32, align 8
|
|
tail call void @use_foo(ptr %f)
|
|
ret void
|
|
}
|
|
|
|
define void @ptr_to_ptr(ptr %f, ptr %i) {
|
|
; CHECK-LABEL: ptr_to_ptr:
|
|
; CHECK: stg 2,8(1)
|
|
%p64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 1
|
|
store ptr %i, ptr %p64, align 8
|
|
tail call void @use_foo(ptr %f)
|
|
ret void
|
|
}
|
|
|
|
define void @test_indexing(ptr %f) {
|
|
entry:
|
|
; CHECK-LABEL: test_indexing:
|
|
; CHECK: l 0,1032
|
|
; CHECK: llgtr 0,0
|
|
; CHECK: stg 0,16(1)
|
|
%0 = load ptr addrspace(1), ptr inttoptr (i64 1032 to ptr), align 8
|
|
%1 = addrspacecast ptr addrspace(1) %0 to ptr
|
|
%cp64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 2
|
|
store ptr %1, ptr %cp64, align 8
|
|
tail call void @use_foo(ptr %f)
|
|
ret void
|
|
}
|
|
|
|
define void @test_indexing_2(ptr %f) {
|
|
entry:
|
|
; CHECK-LABEL: test_indexing_2:
|
|
; CHECK: lhi 0,16
|
|
; CHECK-NEXT: a 0,1032
|
|
; CHECK-NEXT: llgtr 2,0
|
|
; CHECK: lg 0,24(2)
|
|
; CHECK: stg 0,16(1)
|
|
%0 = load ptr addrspace(1), ptr inttoptr (i64 1032 to ptr), align 8
|
|
%arrayidx = getelementptr inbounds ptr, ptr addrspace(1) %0, i32 2
|
|
%1 = load ptr, ptr addrspace(1) %arrayidx, align 8
|
|
%arrayidx1 = getelementptr inbounds ptr, ptr %1, i64 3
|
|
%2 = bitcast ptr %arrayidx1 to ptr
|
|
%3 = load i64, ptr %2, align 8
|
|
%cp64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 2
|
|
%4 = bitcast ptr %cp64 to ptr
|
|
store i64 %3, ptr %4, align 8
|
|
tail call void @use_foo(ptr %f)
|
|
ret void
|
|
}
|
|
|
|
define ptr @test_misc() {
|
|
entry:
|
|
; CHECK-LABEL: test_misc:
|
|
; CHECK: lhi 0,88
|
|
; CHECK-NEXT: a 0,1208
|
|
; CHECK-NEXT: llgtr 1,0
|
|
; CHECK-NEXT: lg 1,0(1)
|
|
; CHECK-NEXT: lg 1,8(1)
|
|
; CHECK-NEXT: lg 1,904(1)
|
|
; CHECK-NEXT: lg 3,1192(1)
|
|
%0 = load ptr addrspace(1), ptr inttoptr (i64 1208 to ptr), align 8
|
|
%arrayidx = getelementptr inbounds ptr, ptr addrspace(1) %0, i32 11
|
|
%1 = load ptr, ptr addrspace(1) %arrayidx, align 8
|
|
%arrayidx1 = getelementptr inbounds ptr, ptr %1, i64 1
|
|
%2 = load ptr, ptr %arrayidx1, align 8
|
|
%arrayidx2 = getelementptr inbounds ptr, ptr %2, i64 113
|
|
%3 = load ptr, ptr %arrayidx2, align 8
|
|
%arrayidx3 = getelementptr inbounds ptr, ptr %3, i64 149
|
|
%4 = bitcast ptr %arrayidx3 to ptr
|
|
%5 = load ptr, ptr %4, align 8
|
|
ret ptr %5
|
|
}
|
|
|
|
define ptr addrspace(1) @test_misc_2() {
|
|
entry:
|
|
; CHECK-LABEL: test_misc_2:
|
|
; CHECK: lhi 0,544
|
|
; CHECK: a 0,16
|
|
; CHECK: llgtr 1,0
|
|
; CHECK: lhi 0,24
|
|
; CHECK: a 0,0(1)
|
|
; CHECK: llgtr 1,0
|
|
%0 = load ptr addrspace(1), ptr inttoptr (i64 16 to ptr), align 16
|
|
%arrayidx = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) %0, i32 136
|
|
%1 = load ptr addrspace(1), ptr addrspace(1) %arrayidx, align 4
|
|
%arrayidx1 = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) %1, i32 6
|
|
%2 = load ptr addrspace(1), ptr addrspace(1) %arrayidx1, align 4
|
|
ret ptr addrspace(1) %2
|
|
}
|
|
|
|
define zeroext i16 @test_misc_3() {
|
|
entry:
|
|
; CHECK-LABEL: test_misc_3:
|
|
; CHECK: a 0,548
|
|
; CHECK-NEXT: llgtr 1,0
|
|
; CHECK-NEXT: llgh 3,0(1)
|
|
; CHECK-NEXT: b 2(7)
|
|
%0 = load ptr addrspace(1), ptr inttoptr (i64 548 to ptr), align 4
|
|
%arrayidx2 = getelementptr inbounds i16, ptr addrspace(1) %0, i32 18
|
|
%arrayidx = addrspacecast ptr addrspace(1) %arrayidx2 to ptr
|
|
%1 = load i16, ptr %arrayidx, align 2
|
|
ret i16 %1
|
|
}
|
|
|
|
define signext i32 @test_misc_4() {
|
|
entry:
|
|
; CHECK-LABEL: test_misc_4:
|
|
; CHECK: lhi 0,88
|
|
; CHECK-NEXT: a 0,1208
|
|
; CHECK-NEXT: llgtr 1,0
|
|
; CHECK-NEXT: lg 1,0(1)
|
|
; CHECK-NEXT: lg 1,8(1)
|
|
; CHECK-NEXT: lg 1,984(1)
|
|
; CHECK-NEXT: iilf 0,67240703
|
|
; CHECK-NEXT: c 0,80(1)
|
|
%0 = load ptr addrspace(1), ptr inttoptr (i64 1208 to ptr), align 8
|
|
%arrayidx = getelementptr inbounds ptr, ptr addrspace(1) %0, i32 11
|
|
%1 = load ptr, ptr addrspace(1) %arrayidx, align 8
|
|
%arrayidx1 = getelementptr inbounds ptr, ptr %1, i64 1
|
|
%2 = load ptr, ptr %arrayidx1, align 8
|
|
%arrayidx2 = getelementptr inbounds ptr, ptr %2, i64 123
|
|
%3 = load ptr, ptr %arrayidx2, align 8
|
|
%add.ptr = getelementptr inbounds i8, ptr %3, i64 80
|
|
%4 = bitcast ptr %add.ptr to ptr
|
|
%5 = load i32, ptr %4, align 4
|
|
%cmp = icmp sgt i32 %5, 67240703
|
|
%conv = zext i1 %cmp to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
define void @test_misc_5(ptr %f) {
|
|
entry:
|
|
; CHECK-LABEL: test_misc_5:
|
|
; CHECK: l 0,548
|
|
; CHECK-NEXT: lg 6,8(5)
|
|
; CHECK-NEXT: lg 5,0(5)
|
|
; CHECK-NEXT: llgtr 0,0
|
|
; CHECK-NEXT: stg 0,16(1)
|
|
%0 = load ptr addrspace(1), ptr inttoptr (i64 548 to ptr), align 4
|
|
%1 = addrspacecast ptr addrspace(1) %0 to ptr
|
|
%cp64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 2
|
|
store ptr %1, ptr %cp64, align 8
|
|
tail call void @use_foo(ptr %f)
|
|
ret void
|
|
}
|
|
|
|
define signext i32 @get_processor_count() {
|
|
entry:
|
|
; CHECK-LABEL: get_processor_count:
|
|
; CHECK: lhi 0,660
|
|
; CHECK-NEXT: a 0,16
|
|
; CHECK-NEXT: llgtr 1,0
|
|
; CHECK-NEXT: lhi 0,53
|
|
; CHECK-NEXT: a 0,0(1)
|
|
; CHECK-NEXT: llgtr 1,0
|
|
; CHECK-NEXT: lgb 3,0(1)
|
|
%0 = load ptr addrspace(1), ptr inttoptr (i64 16 to ptr), align 16
|
|
%arrayidx = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) %0, i32 165
|
|
%1 = load ptr addrspace(1), ptr addrspace(1) %arrayidx, align 4
|
|
%arrayidx1 = getelementptr inbounds i8, ptr addrspace(1) %1, i32 53
|
|
%2 = load i8, ptr addrspace(1) %arrayidx1, align 1
|
|
%conv = sext i8 %2 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
define void @spill_ptr32_args_to_registers(i8 addrspace(1)* %p) {
|
|
entry:
|
|
; CHECK-LABEL: spill_ptr32_args_to_registers:
|
|
; CHECK: stmg 6,7,1872(4)
|
|
; CHECK-NEXT: aghi 4,-192
|
|
; CHECK-NEXT: lgr 2,1
|
|
; CHECK-NEXT: lg 6,24(5)
|
|
; CHECK-NEXT: lg 5,16(5)
|
|
; CHECK-NEXT: stg 1,2216(4)
|
|
; CHECK-NEXT: stg 1,2208(4)
|
|
; CHECK-NEXT: lghi 1,5
|
|
; CHECK-NEXT: stg 2,2200(4)
|
|
; CHECK-NEXT: lgr 3,2
|
|
; CHECK-NEXT: basr 7,6
|
|
; CHECK-NEXT: bcr 0,0
|
|
; CHECK-NEXT: lg 7,2072(4)
|
|
; CHECK-NEXT: aghi 4,192
|
|
; CHECK-NEXT: b 2(7)
|
|
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)
|
|
ret void
|
|
}
|
|
declare void @g(i32 signext, ...)
|
|
|
|
; The resulting instructions may look odd on first view but it is a result of
|
|
; the C code. __malloc31() returns a 64 bit pointer, thus the sequence
|
|
;
|
|
; la 1, 4(8)
|
|
; llgtr 1, 1
|
|
;
|
|
; references the length attribute via the 64 bit pointer, and performs the
|
|
; cast to __ptr32, setting the upper 32 bit to zero.
|
|
;
|
|
define signext i32 @setlength() {
|
|
; CHECK-LABEL: setlength:
|
|
; CHECK: basr 7,6
|
|
; CHECK: lgr [[MALLOC:[0-9]+]],3
|
|
; CHECK: basr 7,6
|
|
; CHECK: lgr [[LENGTH:[0-9]+]],3
|
|
; CHECK: la [[ADDR:[0-9]+]],4([[MALLOC]])
|
|
; CHECK: llgtr [[ADDR]],[[ADDR]]
|
|
; CHECK: stg [[LENGTH]],0([[ADDR]])
|
|
entry:
|
|
%call = tail call ptr @__malloc31(i64 noundef 8)
|
|
%call1 = tail call signext i32 @foo()
|
|
%length = getelementptr inbounds i8, ptr %call, i64 4
|
|
%0 = bitcast ptr %length to ptr
|
|
%1 = addrspacecast ptr %0 to ptr addrspace(1)
|
|
store i32 %call1, ptr addrspace(1) %1, align 4
|
|
ret i32 0
|
|
}
|
|
|
|
; Same as test before, but this time calling
|
|
; extern char* __ptr32 domalloc(unsigned long);
|
|
; instead of __malloc31(). Note the different instruction sequence, because
|
|
; the function now returns a __ptr32.
|
|
;
|
|
define signext i32 @setlength2() {
|
|
; CHECK-LABEL: setlength2:
|
|
; CHECK: basr 7,6
|
|
; CHECK: lgr [[MALLOC:[0-9]+]],3
|
|
; CHECK: basr 7,6
|
|
; CHECK: lgr [[LENGTH:[0-9]+]],3
|
|
; CHECK: ahi [[MALLOC]],4
|
|
; CHECK: llgtr [[ADDR]],[[MALLOC]]
|
|
; CHECK: stg [[LENGTH]],0([[ADDR]])
|
|
entry:
|
|
%call = tail call ptr addrspace(1) @domalloc(i64 noundef 8)
|
|
%call1 = tail call signext i32 @foo()
|
|
%length = getelementptr inbounds i8, ptr addrspace(1) %call, i32 4
|
|
%0 = bitcast ptr addrspace(1) %length to ptr addrspace(1)
|
|
store i32 %call1, ptr addrspace(1) %0, align 4
|
|
ret i32 0
|
|
}
|
|
|
|
declare ptr @__malloc31(i64)
|
|
|
|
declare signext i32 @foo(...)
|
|
|
|
declare ptr addrspace(1) @domalloc(i64)
|