1 /// Test LoongArch64 ABI rewrite of struct passed by value (BIND(C), VALUE derived types).
2 /// This test test cases where the struct can be passed in registers.
3 /// Test cases can be roughly divided into two categories:
4 /// - struct with a single intrinsic component;
5 /// - sturct with more than one field;
6 /// Since the argument marshalling logic is largely the same within each category,
7 /// only the first example in each category checks the entire invocation process,
8 /// while the other examples only check the signatures.
10 // REQUIRES: loongarch-registered-target
11 // RUN: fir-opt --split-input-file --target-rewrite="target=loongarch64-unknown-linux-gnu" %s | FileCheck %s
14 /// *********************** Struct with a single intrinsic component *********************** ///
16 !ty_i16 = !fir.type<ti16{i:i16}>
17 !ty_i32 = !fir.type<ti32{i:i32}>
18 !ty_i64 = !fir.type<ti64{i:i64}>
19 !ty_i128 = !fir.type<ti128{i:i128}>
20 !ty_f16 = !fir.type<tf16{i:f16}>
21 !ty_f32 = !fir.type<tf32{i:f32}>
22 !ty_f64 = !fir.type<tf64{i:f64}>
23 !ty_f128 = !fir.type<tf128{i:f128}>
24 !ty_bf16 = !fir.type<tbf16{i:bf16}>
25 !ty_char1 = !fir.type<tchar1{i:!fir.char<1>}>
26 !ty_char2 = !fir.type<tchar2{i:!fir.char<1,2>}>
27 !ty_log1 = !fir.type<tlog1{i:!fir.logical<1>}>
28 !ty_log2 = !fir.type<tlog2{i:!fir.logical<2>}>
29 !ty_log4 = !fir.type<tlog4{i:!fir.logical<4>}>
30 !ty_log8 = !fir.type<tlog8{i:!fir.logical<8>}>
31 !ty_log16 = !fir.type<tlog16{i:!fir.logical<16>}>
32 !ty_cmplx_f32 = !fir.type<tcmplx_f32{i:complex<f32>}>
33 !ty_cmplx_f64 = !fir.type<tcmplx_f64{i:complex<f64>}>
35 module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", llvm.target_triple = "loongarch64-unknown-linux-gnu"} {
37 // CHECK-LABEL: func.func private @test_func_i16(i64)
38 func.func private @test_func_i16(%arg0: !ty_i16)
39 // CHECK-LABEL: func.func @test_call_i16(
40 // CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<ti16{i:i16}>>) {
41 func.func @test_call_i16(%arg0: !fir.ref<!ty_i16>) {
42 // CHECK: %[[IN:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.type<ti16{i:i16}>>
43 // CHECK: %[[STACK:.*]] = llvm.intr.stacksave : !llvm.ptr
44 // CHECK: %[[ARR:.*]] = fir.alloca i64
45 // CHECK: %[[CVT:.*]] = fir.convert %[[ARR]] : (!fir.ref<i64>) -> !fir.ref<!fir.type<ti16{i:i16}>>
46 // CHECK: fir.store %[[IN]] to %[[CVT]] : !fir.ref<!fir.type<ti16{i:i16}>>
47 // CHECK: %[[LD:.*]] = fir.load %[[ARR]] : !fir.ref<i64>
48 %in = fir.load %arg0 : !fir.ref<!ty_i16>
49 // CHECK: fir.call @test_func_i16(%[[LD]]) : (i64) -> ()
50 // CHECK: llvm.intr.stackrestore %[[STACK]] : !llvm.ptr
51 fir.call @test_func_i16(%in) : (!ty_i16) -> ()
56 // CHECK-LABEL: func.func private @test_func_i32(i64)
57 func.func private @test_func_i32(%arg0: !ty_i32)
59 // CHECK-LABEL: func.func private @test_func_i64(i64)
60 func.func private @test_func_i64(%arg0: !ty_i64)
62 // CHECK-LABEL: func.func private @test_func_i128(i128)
63 func.func private @test_func_i128(%arg0: !ty_i128)
65 // CHECK-LABEL: func.func private @test_func_f16(i64)
66 func.func private @test_func_f16(%arg0: !ty_f16)
68 // CHECK-LABEL: func.func private @test_func_f32(f32)
69 func.func private @test_func_f32(%arg0: !ty_f32)
71 // CHECK-LABEL: func.func private @test_func_f64(f64)
72 func.func private @test_func_f64(%arg0: !ty_f64)
74 // CHECK-LABEL: func.func private @test_func_f128(i128)
75 func.func private @test_func_f128(%arg0: !ty_f128)
77 // CHECK-LABEL: func.func private @test_func_bf16(i64)
78 func.func private @test_func_bf16(%arg0: !ty_bf16)
80 // CHECK-LABEL: func.func private @test_func_char1(i64)
81 func.func private @test_func_char1(%arg0: !ty_char1)
83 // CHECK-LABEL: func.func private @test_func_char2(i64)
84 func.func private @test_func_char2(%arg0: !ty_char2)
86 // CHECK-LABEL: func.func private @test_func_log1(i64)
87 func.func private @test_func_log1(%arg0: !ty_log1)
89 // CHECK-LABEL: func.func private @test_func_log2(i64)
90 func.func private @test_func_log2(%arg0: !ty_log2)
92 // CHECK-LABEL: func.func private @test_func_log4(i64)
93 func.func private @test_func_log4(%arg0: !ty_log4)
95 // CHECK-LABEL: func.func private @test_func_log8(i64)
96 func.func private @test_func_log8(%arg0: !ty_log8)
98 // CHECK-LABEL: func.func private @test_func_log16(i128)
99 func.func private @test_func_log16(%arg0: !ty_log16)
101 // CHECK-LABEL: func.func private @test_func_cmplx_f32(f32, f32)
102 func.func private @test_func_cmplx_f32(%arg0: !ty_cmplx_f32)
104 // CHECK-LABEL: func.func private @test_func_cmplx_f64(f64, f64)
105 func.func private @test_func_cmplx_f64(%arg0: !ty_cmplx_f64)
109 /// *************************** Struct with more than one field **************************** ///
113 !ty_i32_f32 = !fir.type<ti32_f32{i:i32,j:f32}>
114 !ty_i32_f64 = !fir.type<ti32_f64{i:i32,j:f64}>
115 !ty_i64_f32 = !fir.type<ti64_f32{i:i64,j:f32}>
116 !ty_i64_f64 = !fir.type<ti64_f64{i:i64,j:f64}>
117 !ty_f64_i64 = !fir.type<tf64_i64{i:f64,j:i64}>
118 !ty_f16_f16 = !fir.type<tf16_f16{i:f16,j:f16}>
119 !ty_f32_f32 = !fir.type<tf32_f32{i:f32,j:f32}>
120 !ty_f64_f64 = !fir.type<tf64_f64{i:f64,j:f64}>
121 !ty_f32_i32_i32 = !fir.type<tf32_i32_i32{i:f32,j:i32,k:i32}>
122 !ty_f32_f32_i32 = !fir.type<tf32_f32_i32{i:f32,j:f32,k:i32}>
123 !ty_f32_f32_f32 = !fir.type<tf32_f32_f32{i:f32,j:f32,k:f32}>
125 !ty_i8_a8 = !fir.type<ti8_a8{i:!fir.array<8xi8>}>
126 !ty_i8_a16 = !fir.type<ti8_a16{i:!fir.array<16xi8>}>
127 !ty_f32_a2 = !fir.type<tf32_a2{i:!fir.array<2xf32>}>
128 !ty_f64_a2 = !fir.type<tf64_a2{i:!fir.array<2xf64>}>
129 !ty_nested_i32_f32 = !fir.type<t11{i:!ty_i32_f32}>
130 !ty_nested_i8_a8_i32 = !fir.type<t12{i:!ty_i8_a8, j:i32}>
131 !ty_char1_a8 = !fir.type<t_char_a8{i:!fir.array<8x!fir.char<1>>}>
133 module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", llvm.target_triple = "loongarch64-unknown-linux-gnu"} {
135 // CHECK-LABEL: func.func private @test_func_i32_f32(i32, f32)
136 func.func private @test_func_i32_f32(%arg0: !ty_i32_f32)
137 // CHECK-LABEL: func.func @test_call_i32_f32(
138 // CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<ti32_f32{i:i32,j:f32}>>) {
139 func.func @test_call_i32_f32(%arg0: !fir.ref<!ty_i32_f32>) {
140 // CHECK: %[[IN:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.type<ti32_f32{i:i32,j:f32}>>
141 // CHECK: %[[STACK:.*]] = llvm.intr.stacksave : !llvm.ptr
142 // CHECK: %[[ARR:.*]] = fir.alloca tuple<i32, f32>
143 // CHECK: %[[CVT:.*]] = fir.convert %[[ARR]] : (!fir.ref<tuple<i32, f32>>) -> !fir.ref<!fir.type<ti32_f32{i:i32,j:f32}>>
144 // CHECK: fir.store %[[IN]] to %[[CVT]] : !fir.ref<!fir.type<ti32_f32{i:i32,j:f32}>>
145 // CHECK: %[[LD:.*]] = fir.load %[[ARR]] : !fir.ref<tuple<i32, f32>>
146 // CHECK: %[[VAL_0:.*]] = fir.extract_value %[[LD]], [0 : i32] : (tuple<i32, f32>) -> i32
147 // CHECK: %[[VAL_1:.*]] = fir.extract_value %[[LD]], [1 : i32] : (tuple<i32, f32>) -> f32
148 %in = fir.load %arg0 : !fir.ref<!ty_i32_f32>
149 // CHECK: fir.call @test_func_i32_f32(%[[VAL_0]], %[[VAL_1]]) : (i32, f32) -> ()
150 // CHECK: llvm.intr.stackrestore %[[STACK]] : !llvm.ptr
151 fir.call @test_func_i32_f32(%in) : (!ty_i32_f32) -> ()
156 // CHECK-LABEL: func.func private @test_func_i32_f64(i32, f64)
157 func.func private @test_func_i32_f64(%arg0: !ty_i32_f64)
159 // CHECK-LABEL: func.func private @test_func_i64_f32(i64, f32)
160 func.func private @test_func_i64_f32(%arg0: !ty_i64_f32)
162 // CHECK-LABEL: func.func private @test_func_i64_f64(i64, f64)
163 func.func private @test_func_i64_f64(%arg0: !ty_i64_f64)
165 // CHECK-LABEL: func.func private @test_func_f64_i64(f64, i64)
166 func.func private @test_func_f64_i64(%arg0: !ty_f64_i64)
168 // CHECK-LABEL: func.func private @test_func_f16_f16(i64)
169 func.func private @test_func_f16_f16(%arg0: !ty_f16_f16)
171 // CHECK-LABEL: func.func private @test_func_f32_f32(f32, f32)
172 func.func private @test_func_f32_f32(%arg0: !ty_f32_f32)
174 // CHECK-LABEL: func.func private @test_func_f64_f64(f64, f64)
175 func.func private @test_func_f64_f64(%arg0: !ty_f64_f64)
177 // CHECK-LABEL: func.func private @test_func_f32_i32_i32(!fir.array<2xi64>)
178 func.func private @test_func_f32_i32_i32(%arg0: !ty_f32_i32_i32)
180 // CHECK-LABEL: func.func private @test_func_f32_f32_i32(!fir.array<2xi64>)
181 func.func private @test_func_f32_f32_i32(%arg0: !ty_f32_f32_i32)
183 // CHECK-LABEL: func.func private @test_func_f32_f32_f32(!fir.array<2xi64>)
184 func.func private @test_func_f32_f32_f32(%arg0: !ty_f32_f32_f32)
186 // CHECK-LABEL: func.func private @test_func_i8_a8(i64)
187 func.func private @test_func_i8_a8(%arg0: !ty_i8_a8)
189 // CHECK-LABEL: func.func private @test_func_i8_a16(!fir.array<2xi64>)
190 func.func private @test_func_i8_a16(%arg0: !ty_i8_a16)
192 // CHECK-LABEL: func.func private @test_func_f32_a2(f32, f32)
193 func.func private @test_func_f32_a2(%arg0: !ty_f32_a2)
195 // CHECK-LABEL: func.func private @test_func_f64_a2(f64, f64)
196 func.func private @test_func_f64_a2(%arg0: !ty_f64_a2)
198 // CHECK-LABEL: func.func private @test_func_nested_i32_f32(i32, f32)
199 func.func private @test_func_nested_i32_f32(%arg0: !ty_nested_i32_f32)
201 // CHECK-LABEL: func.func private @test_func_nested_i8_a8_i32(!fir.array<2xi64>)
202 func.func private @test_func_nested_i8_a8_i32(%arg0: !ty_nested_i8_a8_i32)
205 // CHECK: func.func private @not_enough_int_reg_1(i32, i32, i32, i32, i32, i32, i32, i32, i64)
206 func.func private @not_enough_int_reg_1(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32, %arg4: i32,
207 %arg5: i32, %arg6: i32, %arg7: i32, %arg8: !ty_i32_f32)
209 // CHECK: func.func private @not_enough_int_reg_1b(!fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, i64)
210 func.func private @not_enough_int_reg_1b(%arg0: !fir.ref<i32>, %arg1: !fir.ref<i32>, %arg2: !fir.ref<i32>, %arg3: !fir.ref<i32>, %arg4: !fir.ref<i32>,
211 %arg5: !fir.ref<i32>, %arg6: !fir.ref<i32>, %arg7: !fir.ref<i32>, %arg8: !ty_i32_f32)
213 // CHECK: func.func private @not_enough_int_reg_2(i32, i32, i32, i32, i32, i32, i32, i32, !fir.array<2xi64>)
214 func.func private @not_enough_int_reg_2(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32, %arg4: i32,
215 %arg5: i32, %arg6: i32, %arg7: i32, %arg8: !ty_i64_f64)
217 // CHECK: func.func private @not_enough_fp_reg_1(f32, f32, f32, f32, f32, f32, f32, f32, i64)
218 func.func private @not_enough_fp_reg_1(%arg0: f32, %arg1: f32, %arg2: f32, %arg3: f32, %arg4: f32,
219 %arg5: f32, %arg6: f32, %arg7: f32, %arg8: !ty_i32_f32)
221 // CHECK: func.func private @not_enough_fp_reg_1b(!fir.ref<f32>, !fir.ref<f32>, !fir.ref<f32>, !fir.ref<f32>, !fir.ref<f32>, !fir.ref<f32>, !fir.ref<f32>, !fir.ref<f32>, i64)
222 func.func private @not_enough_fp_reg_1b(%arg0: !fir.ref<f32>, %arg1: !fir.ref<f32>, %arg2: !fir.ref<f32>, %arg3: !fir.ref<f32>, %arg4: !fir.ref<f32>,
223 %arg5: !fir.ref<f32>, %arg6: !fir.ref<f32>, %arg7: !fir.ref<f32>, %arg8: !ty_i32_f32)
225 // CHECK: func.func private @not_enough_fp_reg_2(f32, f32, f32, f32, f32, f32, f32, f32, !fir.array<2xi64>)
226 func.func private @not_enough_fp_reg_2(%arg0: f32, %arg1: f32, %arg2: f32, %arg3: f32, %arg4: f32,
227 %arg5: f32, %arg6: f32, %arg7: f32, %arg8: !ty_i64_f64)
229 // CHECK: func.func private @char_not_enough_int_reg(i32, i32, i32, i32, i32, i32, i32, i32, i64)
230 func.func private @char_not_enough_int_reg(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32, %arg4: i32,
231 %arg5: i32, %arg6: i32, %arg7: i32, %arg8: !ty_char1_a8)