xref: /llvm-project/flang/test/Fir/convert-to-llvm.fir (revision 0b80491cd5e7dcb6d5432727d0a2c746a9a9438e)
1// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT,GENERIC
2// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT,GENERIC
3// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=i386-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT,GENERIC
4// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=powerpc64le-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT,GENERIC
5// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=x86_64-pc-win32" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT,GENERIC
6// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=aarch64-apple-darwin" %s | FileCheck %s --check-prefixes=CHECK,CHECK-NO-COMDAT,GENERIC
7// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=amdgcn-amd-amdhsa, datalayout=e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-P0" %s | FileCheck -check-prefixes=CHECK,AMDGPU %s
8
9//===================================================
10// SUMMARY: Tests for FIR --> LLVM MLIR conversion
11//===================================================
12
13// Test simple global LLVM conversion
14
15fir.global @g_i0 : i32 {
16  %1 = arith.constant 0 : i32
17  fir.has_value %1 : i32
18}
19
20// CHECK: llvm.mlir.global external @g_i0() {addr_space = 0 : i32} : i32 {
21// CHECK:   %[[C0:.*]] = llvm.mlir.constant(0 : i32) : i32
22// CHECK:   llvm.return %[[C0]] : i32
23// CHECK: }
24
25// -----
26
27fir.global @g_ci5 constant : i32 {
28  %c = arith.constant 5 : i32
29  fir.has_value %c : i32
30}
31
32// CHECK: llvm.mlir.global external constant @g_ci5() {addr_space = 0 : i32} : i32 {
33// CHECK:   %[[C5:.*]] = llvm.mlir.constant(5 : i32) : i32
34// CHECK:   llvm.return %[[C5]] : i32
35// CHECK: }
36
37// -----
38
39fir.global internal @i_i515 (515:i32) : i32
40// CHECK: llvm.mlir.global internal @i_i515(515 : i32) {addr_space = 0 : i32} : i32
41
42// -----
43
44fir.global common @C_i511 (0:i32) : i32
45// CHECK: llvm.mlir.global common @C_i511(0 : i32) {addr_space = 0 : i32} : i32
46
47// -----
48
49fir.global weak @w_i86 (86:i32) : i32
50// CHECK: llvm.mlir.global weak @w_i86(86 : i32) {addr_space = 0 : i32} : i32
51
52// -----
53
54fir.global linkonce @w_i86 (86:i32) : i32
55// CHECK-COMDAT: llvm.mlir.global linkonce @w_i86(86 : i32) comdat(@__llvm_comdat::@w_i86) {addr_space = 0 : i32} : i32
56// CHECK-NO-COMDAT: llvm.mlir.global linkonce @w_i86(86 : i32) {addr_space = 0 : i32} : i32
57
58// -----
59
60// Test conversion of fir.address_of with fir.global
61
62func.func @f1() {
63  %0 = fir.address_of(@symbol) : !fir.ref<i64>
64  return
65}
66
67fir.global @symbol : i64 {
68  %0 = arith.constant 1 : i64
69  fir.has_value %0 : i64
70}
71
72// CHECK: %{{.*}} = llvm.mlir.addressof @[[SYMBOL:.*]] : !llvm.ptr
73
74// CHECK: llvm.mlir.global external @[[SYMBOL]]() {addr_space = 0 : i32} : i64 {
75// CHECK:   %{{.*}} = llvm.mlir.constant(1 : i64) : i64
76// CHECK:   llvm.return %{{.*}} : i64
77// CHECK: }
78
79// -----
80
81// Test global with insert_on_range operation covering the full array
82// in initializer region.
83
84fir.global internal @_QEmultiarray : !fir.array<32x32xi32> {
85  %c0_i32 = arith.constant 1 : i32
86  %0 = fir.undefined !fir.array<32x32xi32>
87  %2 = fir.insert_on_range %0, %c0_i32 from (0, 0) to (31, 31) : (!fir.array<32x32xi32>, i32) -> !fir.array<32x32xi32>
88  fir.has_value %2 : !fir.array<32x32xi32>
89}
90
91// CHECK: llvm.mlir.global internal @_QEmultiarray() {addr_space = 0 : i32} : !llvm.array<32 x array<32 x i32>> {
92// CHECK:   %[[CST:.*]] = llvm.mlir.constant(dense<1> : vector<32x32xi32>) : !llvm.array<32 x array<32 x i32>>
93// CHECK:   llvm.return %[[CST]] : !llvm.array<32 x array<32 x i32>>
94// CHECK: }
95
96// -----
97
98// Test global with insert_on_range operation not covering the full array
99// in initializer region.
100
101fir.global internal @_QEmultiarray : !fir.array<32xi32> {
102  %c0_i32 = arith.constant 1 : i32
103  %0 = fir.undefined !fir.array<32xi32>
104  %2 = fir.insert_on_range %0, %c0_i32 from (5) to (31) : (!fir.array<32xi32>, i32) -> !fir.array<32xi32>
105  fir.has_value %2 : !fir.array<32xi32>
106}
107
108// CHECK:          llvm.mlir.global internal @_QEmultiarray() {addr_space = 0 : i32} : !llvm.array<32 x i32> {
109// CHECK:            %[[CST:.*]] = llvm.mlir.constant(1 : i32) : i32
110// CHECK:            %{{.*}} = llvm.mlir.undef : !llvm.array<32 x i32>
111// CHECK:            %{{.*}} = llvm.insertvalue %[[CST]], %{{.*}}[5] : !llvm.array<32 x i32>
112// CHECK-COUNT-24:   %{{.*}} = llvm.insertvalue %[[CST]], %{{.*}}[{{.*}}] : !llvm.array<32 x i32>
113// CHECK:            %{{.*}} = llvm.insertvalue %[[CST]], %{{.*}}[31] : !llvm.array<32 x i32>
114// CHECK-NOT:        llvm.insertvalue
115// CHECK:            llvm.return %{{.*}} : !llvm.array<32 x i32>
116// CHECK:          }
117
118// -----
119
120// Test global with box
121
122fir.global internal @_QFEx : !fir.box<!fir.ptr<i32>> {
123  %0 = fir.zero_bits !fir.ptr<i32>
124  %1 = fir.embox %0 : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>>
125  fir.has_value %1 : !fir.box<!fir.ptr<i32>>
126}
127
128// CHECK-LABEL: llvm.mlir.global internal @_QFEx()
129// CHECK-SAME:  !llvm.struct<([[DES_FIELDS:.*]])>
130// CHECK:         %[[T0:.*]] = llvm.mlir.undef : !llvm.struct<([[DES_FIELDS]])>
131// CHECK:         %[[T1:.*]] = llvm.insertvalue %{{.*}}, %[[T0]][1] : !llvm.struct<([[DES_FIELDS]])>
132// CHECK:         %[[T2:.*]] = llvm.insertvalue %{{.*}}, %[[T1]][2] : !llvm.struct<([[DES_FIELDS]])>
133// CHECK:         %[[T3:.*]] = llvm.insertvalue %{{.*}}, %[[T2]][3] : !llvm.struct<([[DES_FIELDS]])>
134// CHECK:         %[[T4:.*]] = llvm.insertvalue %{{.*}}, %[[T3]][4] : !llvm.struct<([[DES_FIELDS]])>
135// CHECK:         %[[T5:.*]] = llvm.insertvalue %{{.*}}, %[[T4]][5] : !llvm.struct<([[DES_FIELDS]])>
136// CHECK:         %[[T6:.*]] = llvm.insertvalue %{{.*}}, %[[T5]][6] : !llvm.struct<([[DES_FIELDS]])>
137// CHECK:         %[[GDES:.*]] = llvm.insertvalue %{{.*}}, %[[T6]][0] : !llvm.struct<([[DES_FIELDS]])>
138// CHECK:         llvm.return %[[GDES]] : !llvm.struct<([[DES_FIELDS]])>
139
140// -----
141
142// Test fir.zero_bits operation with LLVM ptr type
143
144func.func @zero_test_ptr() {
145  %z = fir.zero_bits !llvm.ptr
146  return
147}
148
149// CHECK: %{{.*}} = llvm.mlir.zero : !llvm.ptr
150// CHECK-NOT: fir.zero_bits
151
152// -----
153
154// Test fir.zero_bits operation with integer type.
155
156func.func @zero_test_integer() {
157  %z0 = fir.zero_bits i8
158  %z1 = fir.zero_bits i16
159  %z2 = fir.zero_bits i32
160  %z3 = fir.zero_bits i64
161  return
162}
163
164// CHECK: %{{.*}} = llvm.mlir.zero : i8
165// CHECK: %{{.*}} = llvm.mlir.zero : i16
166// CHECK: %{{.*}} = llvm.mlir.zero : i32
167// CHECK: %{{.*}} = llvm.mlir.zero : i64
168// CHECK-NOT: fir.zero_bits
169
170// -----
171
172// Test fir.zero_bits operation with floating points types.
173
174func.func @zero_test_float() {
175  %z0 = fir.zero_bits f16
176  %z1 = fir.zero_bits bf16
177  %z2 = fir.zero_bits f32
178  %z3 = fir.zero_bits f64
179  %z4 = fir.zero_bits f80
180  %z5 = fir.zero_bits f128
181  return
182}
183
184// CHECK: %{{.*}} = llvm.mlir.zero : f16
185// CHECK: %{{.*}} = llvm.mlir.zero : bf16
186// CHECK: %{{.*}} = llvm.mlir.zero : f32
187// CHECK: %{{.*}} = llvm.mlir.zero : f64
188// CHECK: %{{.*}} = llvm.mlir.zero : f80
189// CHECK: %{{.*}} = llvm.mlir.zero : f128
190// CHECK-NOT: fir.zero_bits
191
192// -----
193
194// Test fir.zero_bits with aggregate types.
195
196func.func @zero_aggregate() {
197  %a = fir.zero_bits !fir.array<10xf32>
198  %b = fir.zero_bits !fir.type<a{i:i32,j:f32}>
199  return
200}
201// CHECK: %{{.*}} = llvm.mlir.zero : !llvm.array<10 x f32>
202// CHECK: %{{.*}} = llvm.mlir.zero : !llvm.struct<"a", (i32, f32)>
203// CHECK-NOT: fir.zero_bits
204
205// -----
206
207
208// Verify that fir.allocmem is transformed to a call to malloc
209// and that fir.freemem is transformed to a call to free
210// Single item case
211
212func.func @test_alloc_and_freemem_one() {
213  %z0 = fir.allocmem i32
214  fir.freemem %z0 : !fir.heap<i32>
215  return
216}
217
218// CHECK-LABEL:  llvm.func @test_alloc_and_freemem_one() {
219// CHECK-NEXT:    %[[NULL:.*]] = llvm.mlir.zero : !llvm.ptr
220// CHECK-NEXT:    %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
221// CHECK-NEXT:    %[[N:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64
222// CHECK-NEXT:    llvm.call @malloc(%[[N]])
223// CHECK:         llvm.call @free(%{{.*}})
224// CHECK-NEXT:    llvm.return
225
226// -----
227// Verify that fir.allocmem is transformed to a call to malloc
228// and that fir.freemem is transformed to a call to free
229// Several item case
230
231func.func @test_alloc_and_freemem_several() {
232  %z0 = fir.allocmem !fir.array<100xf32>
233  fir.freemem %z0 : !fir.heap<!fir.array<100xf32>>
234  return
235}
236
237// CHECK-LABEL:  llvm.func @test_alloc_and_freemem_several() {
238// CHECK: [[NULL:%.*]]  = llvm.mlir.zero : !llvm.ptr
239// CHECK: [[PTR:%.*]]  = llvm.getelementptr [[NULL]][{{.*}}] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<100 x f32>
240// CHECK: [[N:%.*]]  = llvm.ptrtoint [[PTR]] : !llvm.ptr to i64
241// CHECK: [[MALLOC:%.*]] = llvm.call @malloc([[N]])
242// CHECK:              llvm.call @free([[MALLOC]])
243// CHECK:              llvm.return
244
245
246func.func @test_with_shape(%ncols: index, %nrows: index) {
247  %1 = fir.allocmem !fir.array<?x?xf32>, %ncols, %nrows
248  fir.freemem %1 : !fir.heap<!fir.array<?x?xf32>>
249  return
250}
251
252// CHECK-LABEL: llvm.func @test_with_shape
253// CHECK-SAME: %[[NCOLS:.*]]: i64, %[[NROWS:.*]]: i64
254// CHECK:   %[[NULL:.*]] = llvm.mlir.zero : !llvm.ptr
255// CHECK:   %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
256// CHECK:   %[[FOUR:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64
257// CHECK:   %[[DIM1_SIZE:.*]] = llvm.mul %[[FOUR]], %[[NCOLS]]  : i64
258// CHECK:   %[[TOTAL_SIZE:.*]] = llvm.mul %[[DIM1_SIZE]], %[[NROWS]]  : i64
259// CHECK:   %[[MEM:.*]] = llvm.call @malloc(%[[TOTAL_SIZE]])
260// CHECK:   llvm.call @free(%[[MEM]]) : (!llvm.ptr) -> ()
261// CHECK:   llvm.return
262// CHECK: }
263
264func.func @test_string_with_shape(%len: index, %nelems: index) {
265  %1 = fir.allocmem !fir.array<?x!fir.char<1,?>>(%len : index), %nelems
266  fir.freemem %1 : !fir.heap<!fir.array<?x!fir.char<1,?>>>
267  return
268}
269
270// CHECK-LABEL: llvm.func @test_string_with_shape
271// CHECK-SAME: %[[LEN:.*]]: i64, %[[NELEMS:.*]]: i64)
272// CHECK:   %[[NULL:.*]] = llvm.mlir.zero : !llvm.ptr
273// CHECK:   %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
274// CHECK:   %[[ONE:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64
275// CHECK:   %[[LEN_SIZE:.*]] = llvm.mul %[[ONE]], %[[LEN]]  : i64
276// CHECK:   %[[TOTAL_SIZE:.*]] = llvm.mul %[[LEN_SIZE]], %[[NELEMS]]  : i64
277// CHECK:   %[[MEM:.*]] = llvm.call @malloc(%[[TOTAL_SIZE]])
278// CHECK:   llvm.call @free(%[[MEM]]) : (!llvm.ptr) -> ()
279// CHECK:   llvm.return
280// CHECK: }
281
282// -----
283
284// Verify that fir.unreachable is transformed to llvm.unreachable
285
286func.func @test_unreachable() {
287  fir.unreachable
288}
289
290// CHECK:  llvm.func @test_unreachable() {
291// CHECK-NEXT:    llvm.unreachable
292// CHECK-NEXT:  }
293
294// -----
295
296// Test `fir.select` operation conversion pattern.
297// Check that the if-then-else ladder is correctly constructed and that we
298// branch to the correct block.
299
300func.func @select(%arg : index, %arg2 : i32) -> i32 {
301  %0 = arith.constant 1 : i32
302  %1 = arith.constant 2 : i32
303  %2 = arith.constant 3 : i32
304  %3 = arith.constant 4 : i32
305  fir.select %arg:index [ 1, ^bb1(%0:i32),
306                          2, ^bb2(%2,%arg,%arg2:i32,index,i32),
307                          3, ^bb3(%arg2,%2:i32,i32),
308                          4, ^bb4(%1:i32),
309                          unit, ^bb5 ]
310  ^bb1(%a : i32) :
311    return %a : i32
312  ^bb2(%b : i32, %b2 : index, %b3:i32) :
313    %castidx = arith.index_cast %b2 : index to i32
314    %4 = arith.addi %b, %castidx : i32
315    %5 = arith.addi %4, %b3 : i32
316    return %5 : i32
317  ^bb3(%c:i32, %c2:i32) :
318    %6 = arith.addi %c, %c2 : i32
319    return %6 : i32
320  ^bb4(%d : i32) :
321    return %d : i32
322  ^bb5 :
323    %zero = arith.constant 0 : i32
324    return %zero : i32
325}
326
327// CHECK-LABEL: func @select(
328// CHECK-SAME:               %[[SELECTVALUE:.*]]: [[IDX:.*]],
329// CHECK-SAME:               %[[ARG1:.*]]: i32)
330// CHECK:         %[[C0:.*]] = llvm.mlir.constant(1 : i32) : i32
331// CHECK:         %[[C1:.*]] = llvm.mlir.constant(2 : i32) : i32
332// CHECK:         %[[C2:.*]] = llvm.mlir.constant(3 : i32) : i32
333// CHECK:         %[[SELECTOR:.*]] = llvm.trunc %[[SELECTVALUE]] : i{{.*}} to i32
334// CHECK:         llvm.switch %[[SELECTOR]] : i32, ^bb5 [
335// CHECK:           1: ^bb1(%[[C0]] : i32),
336// CHECK:           2: ^bb2(%[[C2]], %[[SELECTVALUE]], %[[ARG1]] : i32, [[IDX]], i32),
337// CHECK:           3: ^bb3(%[[ARG1]], %[[C2]] : i32, i32),
338// CHECK:           4: ^bb4(%[[C1]] : i32)
339// CHECK:         ]
340
341// -----
342
343// Test `fir.select_rank` operation conversion pattern.
344// Check that the if-then-else ladder is correctly constructed and that we
345// branch to the correct block.
346
347func.func @select_rank(%arg : i32, %arg2 : i32) -> i32 {
348  %0 = arith.constant 1 : i32
349  %1 = arith.constant 2 : i32
350  %2 = arith.constant 3 : i32
351  %3 = arith.constant 4 : i32
352  fir.select_rank %arg:i32 [ 1, ^bb1(%0:i32),
353                             2, ^bb2(%2,%arg,%arg2:i32,i32,i32),
354                             3, ^bb3(%arg2,%2:i32,i32),
355                             4, ^bb4(%1:i32),
356                             unit, ^bb5 ]
357  ^bb1(%a : i32) :
358    return %a : i32
359  ^bb2(%b : i32, %b2 : i32, %b3:i32) :
360    %4 = arith.addi %b, %b2 : i32
361    %5 = arith.addi %4, %b3 : i32
362    return %5 : i32
363  ^bb3(%c:i32, %c2:i32) :
364    %6 = arith.addi %c, %c2 : i32
365    return %6 : i32
366  ^bb4(%d : i32) :
367    return %d : i32
368  ^bb5 :
369    %zero = arith.constant 0 : i32
370    return %zero : i32
371}
372
373// CHECK-LABEL: func @select_rank(
374// CHECK-SAME:                    %[[SELECTVALUE:.*]]: i32,
375// CHECK-SAME:                    %[[ARG1:.*]]: i32)
376// CHECK:         %[[C0:.*]] = llvm.mlir.constant(1 : i32) : i32
377// CHECK:         %[[C1:.*]] = llvm.mlir.constant(2 : i32) : i32
378// CHECK:         %[[C2:.*]] = llvm.mlir.constant(3 : i32) : i32
379// CHECK:         llvm.switch %[[SELECTVALUE]] : i32, ^bb5 [
380// CHECK:           1: ^bb1(%[[C0]] : i32),
381// CHECK:           2: ^bb2(%[[C2]], %[[SELECTVALUE]], %[[ARG1]] : i32, i32, i32),
382// CHECK:           3: ^bb3(%[[ARG1]], %[[C2]] : i32, i32),
383// CHECK:           4: ^bb4(%[[C1]] : i32)
384// CHECK:         ]
385
386// -----
387
388// Test fir.extract_value operation conversion with derived type.
389
390func.func @extract_derived_type() -> f32 {
391  %0 = fir.undefined !fir.type<derived{f:f32}>
392  %1 = fir.extract_value %0, ["f", !fir.type<derived{f:f32}>] : (!fir.type<derived{f:f32}>) -> f32
393  return %1 : f32
394}
395
396// CHECK-LABEL: llvm.func @extract_derived_type
397// CHECK:         %[[STRUCT:.*]] = llvm.mlir.undef : !llvm.struct<"derived", (f32)>
398// CHECK:         %[[VALUE:.*]] = llvm.extractvalue %[[STRUCT]][0] : !llvm.struct<"derived", (f32)>
399// CHECK:         llvm.return %[[VALUE]] : f32
400
401// -----
402
403// Test fir.extract_value operation conversion with a multi-dimensional array
404// of tuple.
405
406func.func @extract_array(%a : !fir.array<10x10xtuple<i32, f32>>) -> f32 {
407  %0 = fir.extract_value %a, [5 : index, 4 : index, 1 : index] : (!fir.array<10x10xtuple<i32, f32>>) -> f32
408  return %0 : f32
409}
410
411// CHECK-LABEL: llvm.func @extract_array(
412// CHECK-SAME:                           %[[ARR:.*]]: !llvm.array<10 x array<10 x struct<(i32, f32)>>>
413// CHECK:         %[[VALUE:.*]] = llvm.extractvalue %[[ARR]][4, 5, 1] : !llvm.array<10 x array<10 x struct<(i32, f32)>>>
414// CHECK:         llvm.return %[[VALUE]] : f32
415
416// -----
417
418// Test fir.insert_value operation conversion with a multi-dimensional array
419// of tuple.
420
421func.func @extract_array(%a : !fir.array<10x10xtuple<i32, f32>>) {
422  %f = arith.constant 2.0 : f32
423  %i = arith.constant 1 : i32
424  %0 = fir.insert_value %a, %i, [5 : index, 4 : index, 0 : index] : (!fir.array<10x10xtuple<i32, f32>>, i32) -> !fir.array<10x10xtuple<i32, f32>>
425  %1 = fir.insert_value %a, %f, [5 : index, 4 : index, 1 : index] : (!fir.array<10x10xtuple<i32, f32>>, f32) -> !fir.array<10x10xtuple<i32, f32>>
426  return
427}
428
429// CHECK-LABEL: llvm.func @extract_array(
430// CHECK-SAME:                           %[[ARR:.*]]: !llvm.array<10 x array<10 x struct<(i32, f32)>>>
431// CHECK:         %{{.*}} = llvm.insertvalue %{{.*}}, %[[ARR]][4, 5, 0] : !llvm.array<10 x array<10 x struct<(i32, f32)>>>
432// CHECK:         %{{.*}} = llvm.insertvalue %{{.*}}, %[[ARR]][4, 5, 1] : !llvm.array<10 x array<10 x struct<(i32, f32)>>>
433// CHECK:         llvm.return
434
435// -----
436
437// Test fir.insert_value operation conversion with derived type.
438
439func.func @insert_tuple(%a : tuple<i32, f32>) {
440  %f = arith.constant 2.0 : f32
441  %1 = fir.insert_value %a, %f, [1 : index] : (tuple<i32, f32>, f32) -> tuple<i32, f32>
442  return
443}
444
445// CHECK-LABEL: func @insert_tuple(
446// CHECK-SAME:                     %[[TUPLE:.*]]: !llvm.struct<(i32, f32)>
447// CHECK:         %{{.*}} = llvm.insertvalue %{{.*}}, %[[TUPLE]][1] : !llvm.struct<(i32, f32)>
448// CHECK:         llvm.return
449
450// -----
451
452// Test `fir.call` -> `llvm.call` conversion for functions that take no arguments
453// and return nothing
454
455func.func @dummy_basic() {
456  return
457}
458
459func.func @test_call_basic() {
460  fir.call @dummy_basic() : () -> ()
461  return
462}
463
464// CHECK-LABEL: func @test_call_basic() {
465// CHECK-NEXT:  llvm.call @dummy_basic() : () -> ()
466// CHECK-NEXT:  return
467// CHECK-NEXT: }
468
469// Test `fir.call` -> `llvm.call` conversion for functions that take one
470// argument and return nothing
471
472func.func @dummy_with_arg(%arg0 : i32) {
473  return
474}
475
476func.func @test_call_with_arg(%arg0 : i32) {
477  fir.call @dummy_with_arg(%arg0) : (i32) -> ()
478  return
479}
480
481// CHECK-LABEL:  llvm.func @test_call_with_arg(%arg0: i32) {
482// CHECK-NEXT:    llvm.call @dummy_with_arg(%arg0) : (i32) -> ()
483// CHECK-NEXT:    llvm.return
484// CHECK-NEXT:  }
485
486// Test `fir.call` -> `llvm.call` conversion for functions that take no
487// arguments, but return a value
488
489func.func @dummy_return_val() -> i32 {
490  %1 = arith.constant 123 : i32
491  return %1 : i32
492}
493
494func.func @test_call_return_val() -> i32 {
495  %1 = fir.call @dummy_return_val() : () -> (i32)
496  return %1 : i32
497}
498
499// CHECK-LABEL:  llvm.func @test_call_return_val() -> i32 {
500// CHECK-NEXT:    %0 = llvm.call @dummy_return_val() : () -> i32
501// CHECK-NEXT:    llvm.return %0 : i32
502// CHECK-NEXT:  }
503
504// -----
505
506// Test FIR complex addition conversion
507// given: (x + iy) + (x' + iy')
508// result: (x + x') + i(y + y')
509
510func.func @fir_complex_add(%a: complex<f128>, %b: complex<f128>) -> complex<f128> {
511  %c = fir.addc %a, %b {fastmath = #arith.fastmath<fast>} : complex<f128>
512  return %c : complex<f128>
513}
514
515// CHECK-LABEL: llvm.func @fir_complex_add(
516// CHECK-SAME:                             %[[ARG0:.*]]: !llvm.struct<(f128, f128)>,
517// CHECK-SAME:                             %[[ARG1:.*]]: !llvm.struct<(f128, f128)>) -> !llvm.struct<(f128, f128)> {
518// CHECK:         %[[X0:.*]] = llvm.extractvalue %[[ARG0]][0] : !llvm.struct<(f128, f128)>
519// CHECK:         %[[Y0:.*]] = llvm.extractvalue %[[ARG0]][1] : !llvm.struct<(f128, f128)>
520// CHECK:         %[[X1:.*]] = llvm.extractvalue %[[ARG1]][0] : !llvm.struct<(f128, f128)>
521// CHECK:         %[[Y1:.*]] = llvm.extractvalue %[[ARG1]][1] : !llvm.struct<(f128, f128)>
522// CHECK:         %[[ADD_X0_X1:.*]] = llvm.fadd %[[X0]], %[[X1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
523// CHECK:         %[[ADD_Y0_Y1:.*]] = llvm.fadd %[[Y0]], %[[Y1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
524// CHECK:         %{{.*}} = llvm.mlir.undef : !llvm.struct<(f128, f128)>
525// CHECK:         %{{.*}} = llvm.insertvalue %[[ADD_X0_X1]], %{{.*}}[0] : !llvm.struct<(f128, f128)>
526// CHECK:         %{{.*}} = llvm.insertvalue %[[ADD_Y0_Y1]], %{{.*}}[1] : !llvm.struct<(f128, f128)>
527// CHECK:         llvm.return %{{.*}} : !llvm.struct<(f128, f128)>
528
529// -----
530
531// Test FIR complex substraction conversion
532// given: (x + iy) - (x' + iy')
533// result: (x - x') + i(y - y')
534
535func.func @fir_complex_sub(%a: complex<f128>, %b: complex<f128>) -> complex<f128> {
536  %c = fir.subc %a, %b {fastmath = #arith.fastmath<fast>} : complex<f128>
537  return %c : complex<f128>
538}
539
540// CHECK-LABEL: llvm.func @fir_complex_sub(
541// CHECK-SAME:                             %[[ARG0:.*]]: !llvm.struct<(f128, f128)>,
542// CHECK-SAME:                             %[[ARG1:.*]]: !llvm.struct<(f128, f128)>) -> !llvm.struct<(f128, f128)> {
543// CHECK:         %[[X0:.*]] = llvm.extractvalue %[[ARG0]][0] : !llvm.struct<(f128, f128)>
544// CHECK:         %[[Y0:.*]] = llvm.extractvalue %[[ARG0]][1] : !llvm.struct<(f128, f128)>
545// CHECK:         %[[X1:.*]] = llvm.extractvalue %[[ARG1]][0] : !llvm.struct<(f128, f128)>
546// CHECK:         %[[Y1:.*]] = llvm.extractvalue %[[ARG1]][1] : !llvm.struct<(f128, f128)>
547// CHECK:         %[[SUB_X0_X1:.*]] = llvm.fsub %[[X0]], %[[X1]] {fastmathFlags = #llvm.fastmath<fast>}  : f128
548// CHECK:         %[[SUB_Y0_Y1:.*]] = llvm.fsub %[[Y0]], %[[Y1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
549// CHECK:         %{{.*}} = llvm.mlir.undef : !llvm.struct<(f128, f128)>
550// CHECK:         %{{.*}} = llvm.insertvalue %[[SUB_X0_X1]], %{{.*}}[0] : !llvm.struct<(f128, f128)>
551// CHECK:         %{{.*}} = llvm.insertvalue %[[SUB_Y0_Y1]], %{{.*}}[1] : !llvm.struct<(f128, f128)>
552// CHECK:         llvm.return %{{.*}} : !llvm.struct<(f128, f128)>
553
554// -----
555
556// Test FIR complex multiply conversion
557// given: (x + iy) * (x' + iy')
558// result: (xx'-yy')+i(xy'+yx')
559
560func.func @fir_complex_mul(%a: complex<f128>, %b: complex<f128>) -> complex<f128> {
561  %c = fir.mulc %a, %b {fastmath = #arith.fastmath<fast>} : complex<f128>
562  return %c : complex<f128>
563}
564
565// CHECK-LABEL: llvm.func @fir_complex_mul(
566// CHECK-SAME:                             %[[ARG0:.*]]: !llvm.struct<(f128, f128)>,
567// CHECK-SAME:                             %[[ARG1:.*]]: !llvm.struct<(f128, f128)>) -> !llvm.struct<(f128, f128)> {
568// CHECK:         %[[X0:.*]] = llvm.extractvalue %[[ARG0]][0] : !llvm.struct<(f128, f128)>
569// CHECK:         %[[Y0:.*]] = llvm.extractvalue %[[ARG0]][1] : !llvm.struct<(f128, f128)>
570// CHECK:         %[[X1:.*]] = llvm.extractvalue %[[ARG1]][0] : !llvm.struct<(f128, f128)>
571// CHECK:         %[[Y1:.*]] = llvm.extractvalue %[[ARG1]][1] : !llvm.struct<(f128, f128)>
572// CHECK:         %[[MUL_X0_X1:.*]] = llvm.fmul %[[X0]], %[[X1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
573// CHECK:         %[[MUL_Y0_X1:.*]] = llvm.fmul %[[Y0]], %[[X1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
574// CHECK:         %[[MUL_X0_Y1:.*]] = llvm.fmul %[[X0]], %[[Y1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
575// CHECK:         %[[ADD:.*]] = llvm.fadd %[[MUL_X0_Y1]], %[[MUL_Y0_X1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
576// CHECK:         %[[MUL_Y0_Y1:.*]] = llvm.fmul %[[Y0]], %[[Y1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
577// CHECK:         %[[SUB:.*]] = llvm.fsub %[[MUL_X0_X1]], %[[MUL_Y0_Y1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
578// CHECK:         %{{.*}} = llvm.mlir.undef : !llvm.struct<(f128, f128)>
579// CHECK:         %{{.*}} = llvm.insertvalue %[[SUB]], %{{.*}}[0] : !llvm.struct<(f128, f128)>
580// CHECK:         %{{.*}} = llvm.insertvalue %[[ADD]], %{{.*}}[1] : !llvm.struct<(f128, f128)>
581// CHECK:         llvm.return %{{.*}} : !llvm.struct<(f128, f128)>
582
583// -----
584
585// Test FIR complex division conversion
586// given: (x + iy) / (x' + iy')
587// result: ((xx'+yy')/d) + i((yx'-xy')/d) where d = x'x' + y'y'
588
589func.func @fir_complex_div(%a: complex<f128>, %b: complex<f128>) -> complex<f128> {
590  %c = fir.divc %a, %b {fastmath = #arith.fastmath<fast>} : complex<f128>
591  return %c : complex<f128>
592}
593
594// CHECK-LABEL: llvm.func @fir_complex_div(
595// CHECK-SAME:                             %[[ARG0:.*]]: !llvm.struct<(f128, f128)>,
596// CHECK-SAME:                             %[[ARG1:.*]]: !llvm.struct<(f128, f128)>) -> !llvm.struct<(f128, f128)> {
597// CHECK:         %[[X0:.*]] = llvm.extractvalue %[[ARG0]][0] : !llvm.struct<(f128, f128)>
598// CHECK:         %[[Y0:.*]] = llvm.extractvalue %[[ARG0]][1] : !llvm.struct<(f128, f128)>
599// CHECK:         %[[X1:.*]] = llvm.extractvalue %[[ARG1]][0] : !llvm.struct<(f128, f128)>
600// CHECK:         %[[Y1:.*]] = llvm.extractvalue %[[ARG1]][1] : !llvm.struct<(f128, f128)>
601// CHECK:         %[[MUL_X0_X1:.*]] = llvm.fmul %[[X0]], %[[X1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
602// CHECK:         %[[MUL_X1_X1:.*]] = llvm.fmul %[[X1]], %[[X1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
603// CHECK:         %[[MUL_Y0_X1:.*]] = llvm.fmul %[[Y0]], %[[X1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
604// CHECK:         %[[MUL_X0_Y1:.*]] = llvm.fmul %[[X0]], %[[Y1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
605// CHECK:         %[[MUL_Y0_Y1:.*]] = llvm.fmul %[[Y0]], %[[Y1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
606// CHECK:         %[[MUL_Y1_Y1:.*]] = llvm.fmul %[[Y1]], %[[Y1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
607// CHECK:         %[[ADD_X1X1_Y1Y1:.*]] = llvm.fadd %[[MUL_X1_X1]], %[[MUL_Y1_Y1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
608// CHECK:         %[[ADD_X0X1_Y0Y1:.*]] = llvm.fadd %[[MUL_X0_X1]], %[[MUL_Y0_Y1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
609// CHECK:         %[[SUB_Y0X1_X0Y1:.*]] = llvm.fsub %[[MUL_Y0_X1]], %[[MUL_X0_Y1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
610// CHECK:         %[[DIV0:.*]] = llvm.fdiv %[[ADD_X0X1_Y0Y1]], %[[ADD_X1X1_Y1Y1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
611// CHECK:         %[[DIV1:.*]] = llvm.fdiv %[[SUB_Y0X1_X0Y1]], %[[ADD_X1X1_Y1Y1]] {fastmathFlags = #llvm.fastmath<fast>} : f128
612// CHECK:         %{{.*}} = llvm.mlir.undef : !llvm.struct<(f128, f128)>
613// CHECK:         %{{.*}} = llvm.insertvalue %[[DIV0]], %{{.*}}[0] : !llvm.struct<(f128, f128)>
614// CHECK:         %{{.*}} = llvm.insertvalue %[[DIV1]], %{{.*}}[1] : !llvm.struct<(f128, f128)>
615// CHECK:         llvm.return %{{.*}} : !llvm.struct<(f128, f128)>
616
617// -----
618
619// Test FIR complex negation conversion
620// given: -(x + iy)
621// result: -x - iy
622
623func.func @fir_complex_neg(%a: complex<f128>) -> complex<f128> {
624  %c = fir.negc %a : complex<f128>
625  return %c : complex<f128>
626}
627
628// CHECK-LABEL: llvm.func @fir_complex_neg(
629// CHECK-SAME:                             %[[ARG0:.*]]: !llvm.struct<(f128, f128)>) -> !llvm.struct<(f128, f128)> {
630// CHECK:         %[[X:.*]] = llvm.extractvalue %[[ARG0]][0] : !llvm.struct<(f128, f128)>
631// CHECK:         %[[Y:.*]] = llvm.extractvalue %[[ARG0]][1] : !llvm.struct<(f128, f128)>
632// CHECK:         %[[NEGX:.*]] = llvm.fneg %[[X]]  : f128
633// CHECK:         %[[NEGY:.*]] = llvm.fneg %[[Y]]  : f128
634// CHECK:         %{{.*}} = llvm.insertvalue %[[NEGX]], %{{.*}}[0] : !llvm.struct<(f128, f128)>
635// CHECK:         %{{.*}} = llvm.insertvalue %[[NEGY]], %{{.*}}[1] : !llvm.struct<(f128, f128)>
636// CHECK:         llvm.return %{{.*}} : !llvm.struct<(f128, f128)>
637
638// -----
639
640// Test FIR complex compare conversion
641
642func.func @compare_complex_eq(%a : complex<f64>, %b : complex<f64>) -> i1 {
643  %r = fir.cmpc "oeq", %a, %b : complex<f64>
644  return %r : i1
645}
646
647// CHECK-LABEL: llvm.func @compare_complex_eq
648// CHECK-SAME: [[A:%.*]]: !llvm.struct<(f64, f64)>,
649// CHECK-SAME: [[B:%.*]]: !llvm.struct<(f64, f64)>
650// CHECK-DAG: [[RA:%.*]] = llvm.extractvalue [[A]][0] : !llvm.struct<(f64, f64)>
651// CHECK-DAG: [[IA:%.*]] = llvm.extractvalue [[A]][1] : !llvm.struct<(f64, f64)>
652// CHECK-DAG: [[RB:%.*]] = llvm.extractvalue [[B]][0] : !llvm.struct<(f64, f64)>
653// CHECK-DAG: [[IB:%.*]] = llvm.extractvalue [[B]][1] : !llvm.struct<(f64, f64)>
654// CHECK-DAG: [[RESR:%.*]] = llvm.fcmp "oeq" [[RA]], [[RB]] : f64
655// CHECK-DAG: [[RESI:%.*]] = llvm.fcmp "oeq" [[IA]], [[IB]] : f64
656// CHECK: [[RES:%.*]] = llvm.and [[RESR]], [[RESI]] : i1
657// CHECK: return [[RES]] : i1
658
659func.func @compare_complex_ne(%a : complex<f64>, %b : complex<f64>) -> i1 {
660  %r = fir.cmpc "une", %a, %b {fastmath = #arith.fastmath<fast>} : complex<f64>
661  return %r : i1
662}
663
664// CHECK-LABEL: llvm.func @compare_complex_ne
665// CHECK-SAME: [[A:%.*]]: !llvm.struct<(f64, f64)>,
666// CHECK-SAME: [[B:%.*]]: !llvm.struct<(f64, f64)>
667// CHECK-DAG: [[RA:%.*]] = llvm.extractvalue [[A]][0] : !llvm.struct<(f64, f64)>
668// CHECK-DAG: [[IA:%.*]] = llvm.extractvalue [[A]][1] : !llvm.struct<(f64, f64)>
669// CHECK-DAG: [[RB:%.*]] = llvm.extractvalue [[B]][0] : !llvm.struct<(f64, f64)>
670// CHECK-DAG: [[IB:%.*]] = llvm.extractvalue [[B]][1] : !llvm.struct<(f64, f64)>
671// CHECK-DAG: [[RESR:%.*]] = llvm.fcmp "une" [[RA]], [[RB]] {fastmathFlags = #llvm.fastmath<fast>} : f64
672// CHECK-DAG: [[RESI:%.*]] = llvm.fcmp "une" [[IA]], [[IB]] {fastmathFlags = #llvm.fastmath<fast>} : f64
673// CHECK: [[RES:%.*]] = llvm.or [[RESR]], [[RESI]] : i1
674// CHECK: return [[RES]] : i1
675
676func.func @compare_complex_other(%a : complex<f64>, %b : complex<f64>) -> i1 {
677  %r = fir.cmpc "ogt", %a, %b {fastmath = #arith.fastmath<fast>} : complex<f64>
678  return %r : i1
679}
680
681// CHECK-LABEL: llvm.func @compare_complex_other
682// CHECK-SAME: [[A:%.*]]: !llvm.struct<(f64, f64)>,
683// CHECK-SAME: [[B:%.*]]: !llvm.struct<(f64, f64)>
684// CHECK-DAG: [[RA:%.*]] = llvm.extractvalue [[A]][0] : !llvm.struct<(f64, f64)>
685// CHECK-DAG: [[RB:%.*]] = llvm.extractvalue [[B]][0] : !llvm.struct<(f64, f64)>
686// CHECK: [[RESR:%.*]] = llvm.fcmp "ogt" [[RA]], [[RB]] {fastmathFlags = #llvm.fastmath<fast>} : f64
687// CHECK: return [[RESR]] : i1
688
689// -----
690
691// Test `fir.convert` operation conversion from Float type.
692
693func.func @convert_from_float(%arg0 : f32) {
694  %0 = fir.convert %arg0 : (f32) -> f16
695  %1 = fir.convert %arg0 : (f32) -> f32
696  %2 = fir.convert %arg0 : (f32) -> f64
697  %3 = fir.convert %arg0 : (f32) -> f80
698  %4 = fir.convert %arg0 : (f32) -> f128
699  %5 = fir.convert %arg0 : (f32) -> i1
700  %6 = fir.convert %arg0 : (f32) -> i8
701  %7 = fir.convert %arg0 : (f32) -> i16
702  %8 = fir.convert %arg0 : (f32) -> i32
703  %9 = fir.convert %arg0 : (f32) -> i64
704  return
705}
706
707// CHECK-LABEL: convert_from_float(
708// CHECK-SAME:                     %[[ARG0:.*]]: f32
709// CHECK:         %{{.*}} = llvm.fptrunc %[[ARG0]] : f32 to f16
710// CHECK-NOT:     f32 to f32
711// CHECK:         %{{.*}} = llvm.fpext %[[ARG0]] : f32 to f64
712// CHECK:         %{{.*}} = llvm.fpext %[[ARG0]] : f32 to f80
713// CHECK:         %{{.*}} = llvm.fpext %[[ARG0]] : f32 to f128
714// CHECK:         %{{.*}} = llvm.fptosi %[[ARG0]] : f32 to i1
715// CHECK:         %{{.*}} = llvm.fptosi %[[ARG0]] : f32 to i8
716// CHECK:         %{{.*}} = llvm.fptosi %[[ARG0]] : f32 to i16
717// CHECK:         %{{.*}} = llvm.fptosi %[[ARG0]] : f32 to i32
718// CHECK:         %{{.*}} = llvm.fptosi %[[ARG0]] : f32 to i64
719
720// -----
721
722// Test `fir.convert` operation conversion from Integer type.
723
724func.func @convert_from_int(%arg0 : i32) {
725  %0 = fir.convert %arg0 : (i32) -> f16
726  %1 = fir.convert %arg0 : (i32) -> f32
727  %2 = fir.convert %arg0 : (i32) -> f64
728  %3 = fir.convert %arg0 : (i32) -> f80
729  %4 = fir.convert %arg0 : (i32) -> f128
730  %5 = fir.convert %arg0 : (i32) -> i1
731  %6 = fir.convert %arg0 : (i32) -> i8
732  %7 = fir.convert %arg0 : (i32) -> i16
733  %8 = fir.convert %arg0 : (i32) -> i32
734  %9 = fir.convert %arg0 : (i32) -> i64
735  %10 = fir.convert %arg0 : (i32) -> i64
736  %ptr = fir.convert %10 : (i64) -> !fir.ref<i64>
737  return
738}
739
740// CHECK-LABEL: convert_from_int(
741// CHECK-SAME:                   %[[ARG0:.*]]: i32
742// CHECK:         %{{.*}} = llvm.sitofp %[[ARG0]] : i32 to f16
743// CHECK:         %{{.*}} = llvm.sitofp %[[ARG0]] : i32 to f32
744// CHECK:         %{{.*}} = llvm.sitofp %[[ARG0]] : i32 to f64
745// CHECK:         %{{.*}} = llvm.sitofp %[[ARG0]] : i32 to f80
746// CHECK:         %{{.*}} = llvm.sitofp %[[ARG0]] : i32 to f128
747// CHECK:         %{{.*}} = llvm.trunc %[[ARG0]] : i32 to i1
748// CHECK:         %{{.*}} = llvm.trunc %[[ARG0]] : i32 to i8
749// CHECK:         %{{.*}} = llvm.trunc %[[ARG0]] : i32 to i16
750// CHECK-NOT:     %{{.*}} = llvm.trunc %[[ARG0]] : i32 to i32
751// CHECK:         %{{.*}} = llvm.sext %[[ARG0]] : i32 to i64
752// CHECK:         %{{.*}} = llvm.inttoptr %{{.*}} : i64 to !llvm.ptr
753
754
755func.func @convert_from_i1(%arg0 : i1) {
756  %0 = fir.convert %arg0 : (i1) -> i32
757  return
758}
759
760// CHECK-LABEL: convert_from_i1(
761// CHECK-SAME: %[[ARG0:.*]]: i1
762// CHECK:        %{{.*}} = llvm.zext %[[ARG0]] : i1 to i32
763
764// -----
765
766// Test `fir.convert` operation conversion from !fir.ref<> type.
767
768func.func @convert_from_ref(%arg0 : !fir.ref<i32>) {
769  %0 = fir.convert %arg0 : (!fir.ref<i32>) -> !fir.ref<i8>
770  %1 = fir.convert %arg0 : (!fir.ref<i32>) -> i32
771  return
772}
773
774// CHECK-LABEL: convert_from_ref(
775// CHECK-SAME:                   %[[ARG0:.*]]: !llvm.ptr
776// CHECK-NOT:         %{{.*}} = llvm.bitcast %[[ARG0]] : !llvm.ptr to !llvm.ptr
777// CHECK:         %{{.*}} = llvm.ptrtoint %[[ARG0]] : !llvm.ptr to i32
778
779// -----
780
781// Test `fir.convert` operation conversion between fir.complex types.
782
783func.func @convert_complex4(%arg0 : complex<f32>) -> complex<f64> {
784  %0 = fir.convert %arg0 : (complex<f32>) -> complex<f64>
785  return %0 : complex<f64>
786}
787
788// CHECK-LABEL: func @convert_complex4(
789// CHECK-SAME:                         %[[ARG0:.*]]: !llvm.struct<(f32, f32)>) -> !llvm.struct<(f64, f64)>
790// CHECK:         %[[X:.*]] = llvm.extractvalue %[[ARG0]][0] : !llvm.struct<(f32, f32)>
791// CHECK:         %[[Y:.*]] = llvm.extractvalue %[[ARG0]][1] : !llvm.struct<(f32, f32)>
792// CHECK:         %[[CONVERTX:.*]] = llvm.fpext %[[X]] : f32 to f64
793// CHECK:         %[[CONVERTY:.*]] = llvm.fpext %[[Y]] : f32 to f64
794// CHECK:         %[[STRUCT0:.*]] = llvm.mlir.undef : !llvm.struct<(f64, f64)>
795// CHECK:         %[[STRUCT1:.*]] = llvm.insertvalue %[[CONVERTX]], %[[STRUCT0]][0] : !llvm.struct<(f64, f64)>
796// CHECK:         %[[STRUCT2:.*]] = llvm.insertvalue %[[CONVERTY]], %[[STRUCT1]][1] : !llvm.struct<(f64, f64)>
797// CHECK:         llvm.return %[[STRUCT2]] : !llvm.struct<(f64, f64)>
798
799// Test `fir.convert` operation conversion between fir.complex types.
800
801func.func @convert_complex16(%arg0 : complex<f128>) -> complex<f16> {
802  %0 = fir.convert %arg0 : (complex<f128>) -> complex<f16>
803  return %0 : complex<f16>
804}
805
806// CHECK-LABEL: func @convert_complex16(
807// CHECK-SAME:                          %[[ARG0:.*]]: !llvm.struct<(f128, f128)>) -> !llvm.struct<(f16, f16)>
808// CHECK:         %[[X:.*]] = llvm.extractvalue %[[ARG0]][0] : !llvm.struct<(f128, f128)>
809// CHECK:         %[[Y:.*]] = llvm.extractvalue %[[ARG0]][1] : !llvm.struct<(f128, f128)>
810// CHECK:         %[[CONVERTX:.*]] = llvm.fptrunc %[[X]] : f128 to f16
811// CHECK:         %[[CONVERTY:.*]] = llvm.fptrunc %[[Y]] : f128 to f16
812// CHECK:         %[[STRUCT0:.*]] = llvm.mlir.undef : !llvm.struct<(f16, f16)>
813// CHECK:         %[[STRUCT1:.*]] = llvm.insertvalue %[[CONVERTX]], %[[STRUCT0]][0] : !llvm.struct<(f16, f16)>
814// CHECK:         %[[STRUCT2:.*]] = llvm.insertvalue %[[CONVERTY]], %[[STRUCT1]][1] : !llvm.struct<(f16, f16)>
815// CHECK:         llvm.return %[[STRUCT2]] : !llvm.struct<(f16, f16)>
816
817// -----
818
819// Test `fir.convert` operation conversion between compatible fir.record types.
820
821func.func @convert_record(%arg0 : !fir.type<_QMmod1Trec{i:i32,f:f64,c:!llvm.struct<(f32, f32)>,cstr:!fir.array<4x!fir.char<1>>}>) ->
822                                  !fir.type<_QMmod2Trec{i:i32,f:f64,c:!llvm.struct<(f32, f32)>,cstr:!fir.array<4x!fir.char<1>>}> {
823    %0 = fir.convert %arg0 : (!fir.type<_QMmod1Trec{i:i32,f:f64,c:!llvm.struct<(f32, f32)>,cstr:!fir.array<4x!fir.char<1>>}>) ->
824                              !fir.type<_QMmod2Trec{i:i32,f:f64,c:!llvm.struct<(f32, f32)>,cstr:!fir.array<4x!fir.char<1>>}>
825  return %0 : !fir.type<_QMmod2Trec{i:i32,f:f64,c:!llvm.struct<(f32, f32)>,cstr:!fir.array<4x!fir.char<1>>}>
826}
827
828// CHECK-LABEL: func @convert_record(
829// CHECK-SAME:    %[[ARG0:.*]]: [[MOD1_REC:!llvm.struct<"_QMmod1Trec", \(i32, f64, struct<\(f32, f32\)>, array<4 x array<1 x i8>>\)>]]) ->
830// CHECK-SAME:                  [[MOD2_REC:!llvm.struct<"_QMmod2Trec", \(i32, f64, struct<\(f32, f32\)>, array<4 x array<1 x i8>>\)>]]
831// CHECK:         %{{.*}} = llvm.mlir.undef : [[MOD2_REC]]
832// CHECK-DAG:     %[[I:.*]] = llvm.extractvalue %[[ARG0]][0] : [[MOD1_REC]]
833// CHECK-DAG:     %{{.*}} = llvm.insertvalue %[[I]], %{{.*}}[0] : [[MOD2_REC]]
834// CHECK-DAG:     %[[F:.*]] = llvm.extractvalue %[[ARG0]][1] : [[MOD1_REC]]
835// CHECK-DAG:     %{{.*}} = llvm.insertvalue %[[F]], %{{.*}}[1] : [[MOD2_REC]]
836// CHECK-DAG:     %[[C:.*]] = llvm.extractvalue %[[ARG0]][2] : [[MOD1_REC]]
837// CHECK-DAG:     %{{.*}} = llvm.insertvalue %[[C]], %{{.*}}[2] : [[MOD2_REC]]
838// CHECK-DAG:     %[[CSTR:.*]] = llvm.extractvalue %[[ARG0]][3] : [[MOD1_REC]]
839// CHECK-DAG:     %{{.*}} = llvm.insertvalue %[[CSTR]], %{{.*}}[3] : [[MOD2_REC]]
840// CHECK:         llvm.return %{{.*}} : [[MOD2_REC]]
841
842// -----
843
844// Test `fir.store` --> `llvm.store` conversion
845
846func.func @test_store_index(%val_to_store : index, %addr : !fir.ref<index>) {
847  fir.store %val_to_store to %addr : !fir.ref<index>
848  return
849}
850
851// CHECK-LABEL:   llvm.func @test_store_index
852// CHECK-SAME:    (%[[arg0:.*]]: i64, %[[arg1:.*]]: !llvm.ptr) {
853// CHECK-NEXT:    llvm.store %[[arg0]], %[[arg1]] : i64, !llvm.ptr
854// CHECK-NEXT:    llvm.return
855// CHECK-NEXT:  }
856
857func.func @test_store_box(%array : !fir.ref<!fir.box<!fir.array<?x?xf32>>>, %box : !fir.box<!fir.array<?x?xf32>>) {
858  fir.store %box to %array : !fir.ref<!fir.box<!fir.array<?x?xf32>>>
859  return
860}
861
862// CHECK-LABEL:  llvm.func @test_store_box
863// CHECK-SAME:  (%[[arg0:.*]]: !llvm.ptr,
864// CHECK-SAME:  %[[arg1:.*]]: !llvm.ptr) {
865// CHECK-NEXT:  %[[size:.*]] = llvm.mlir.constant(72 : i32) : i32
866// CHECK-NEXT:  "llvm.intr.memcpy"(%[[arg0]], %[[arg1]], %[[size]]) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> ()
867// CHECK-NEXT:  llvm.return
868// CHECK-NEXT:  }
869
870
871func.func @store_unlimited_polymorphic_box(%arg0 : !fir.class<none>, %arg1 : !fir.class<!fir.array<?xnone>>, %arg2 : !fir.box<none>, %arg3 : !fir.box<!fir.array<?xnone>>, %arg0r : !fir.ref<!fir.class<none>>, %arg1r : !fir.ref<!fir.class<!fir.array<?xnone>>>, %arg2r : !fir.ref<!fir.box<none>>, %arg3r : !fir.ref<!fir.box<!fir.array<?xnone>>>) {
872  fir.store %arg0 to %arg0r : !fir.ref<!fir.class<none>>
873  fir.store %arg1 to %arg1r : !fir.ref<!fir.class<!fir.array<?xnone>>>
874  fir.store %arg2 to %arg2r : !fir.ref<!fir.box<none>>
875  fir.store %arg3 to %arg3r : !fir.ref<!fir.box<!fir.array<?xnone>>>
876  return
877}
878// CHECK:   llvm.func @store_unlimited_polymorphic_box(%[[VAL_0:.*]]: !llvm.ptr, %[[VAL_1:.*]]: !llvm.ptr, %[[VAL_2:.*]]: !llvm.ptr, %[[VAL_3:.*]]: !llvm.ptr, %[[VAL_4:.*]]: !llvm.ptr, %[[VAL_5:.*]]: !llvm.ptr, %[[VAL_6:.*]]: !llvm.ptr, %[[VAL_7:.*]]: !llvm.ptr) {
879// CHECK:     %[[VAL_8:.*]] = llvm.mlir.constant(40 : i32) : i32
880// CHECK:     "llvm.intr.memcpy"(%[[VAL_4]], %[[VAL_0]], %[[VAL_8]]) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> ()
881// CHECK:     %[[VAL_9:.*]] = llvm.mlir.constant(64 : i32) : i32
882// CHECK:     "llvm.intr.memcpy"(%[[VAL_5]], %[[VAL_1]], %[[VAL_9]]) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> ()
883// CHECK:     %[[VAL_10:.*]] = llvm.mlir.constant(40 : i32) : i32
884// CHECK:     "llvm.intr.memcpy"(%[[VAL_6]], %[[VAL_2]], %[[VAL_10]]) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> ()
885// CHECK:     %[[VAL_11:.*]] = llvm.mlir.constant(64 : i32) : i32
886// CHECK:     "llvm.intr.memcpy"(%[[VAL_7]], %[[VAL_3]], %[[VAL_11]]) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> ()
887// CHECK:     llvm.return
888// CHECK:   }
889
890
891// -----
892
893func.func @store_assumed_rank_box(%box: !fir.box<!fir.array<*:f32>>, %ref: !fir.ref<!fir.box<!fir.array<*:f32>>>) {
894  fir.store %box to %ref : !fir.ref<!fir.box<!fir.array<*:f32>>>
895  return
896}
897
898// CHECK-LABEL:   llvm.func @store_assumed_rank_box(
899// CHECK-SAME:                                      %[[VAL_0:[^:]*]]: !llvm.ptr,
900// CHECK-SAME:                                      %[[VAL_1:.*]]: !llvm.ptr) {
901// CHECK:           %[[VAL_2:.*]] = llvm.mlir.constant(24 : i32) : i32
902// CHECK:           %[[VAL_3:.*]] = llvm.getelementptr %[[VAL_0]][0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<15 x array<3 x i64>>)>
903// CHECK:           %[[VAL_4:.*]] = llvm.load %[[VAL_3]] : !llvm.ptr -> i8
904// CHECK:           %[[VAL_5:.*]] = llvm.sext %[[VAL_4]] : i8 to i32
905// CHECK:           %[[VAL_6:.*]] = llvm.mlir.constant(24 : i32) : i32
906// CHECK:           %[[VAL_7:.*]] = llvm.mul %[[VAL_6]], %[[VAL_5]] : i32
907// CHECK:           %[[VAL_8:.*]] = llvm.add %[[VAL_2]], %[[VAL_7]] : i32
908// CHECK:           "llvm.intr.memcpy"(%[[VAL_1]], %[[VAL_0]], %[[VAL_8]]) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> ()
909
910// -----
911
912// Test `fir.load` --> `llvm.load` conversion
913
914func.func @test_load_index(%addr : !fir.ref<index>) {
915  %0 = fir.load %addr : !fir.ref<index>
916  return
917}
918
919// CHECK-LABEL: llvm.func @test_load_index(
920// CHECK-SAME:  %[[arg1:.*]]: !llvm.ptr) {
921// CHECK-NEXT:    %0 = llvm.load %[[arg1]] : !llvm.ptr -> i64
922// CHECK-NEXT:    llvm.return
923// CHECK-NEXT:  }
924
925func.func private @takes_box(!fir.box<!fir.array<10xf32>>) -> ()
926
927func.func @test_load_box(%addr : !fir.ref<!fir.box<!fir.array<10xf32>>>) {
928  %0 = fir.load %addr : !fir.ref<!fir.box<!fir.array<10xf32>>>
929  fir.call @takes_box(%0) : (!fir.box<!fir.array<10xf32>>) -> ()
930  return
931}
932
933// Loading a `fir.ref<!fir.box>> is creating a descriptor copy
934// CHECK-LABEL: llvm.func @test_load_box(
935// CHECK-SAME:      %[[arg0:.*]]: !llvm.ptr) {
936// CHECK-NEXT:    %[[c1:.*]] = llvm.mlir.constant(1 : i32) : i32
937// GENERIC-NEXT:  %[[box_copy:.*]] = llvm.alloca %[[c1]] x !llvm.struct<([[DESC_TYPE:.*]])>
938// AMDGPU-NEXT:   %[[alloca_box_copy:.*]] = llvm.alloca %[[c1]] x !llvm.struct<([[DESC_TYPE:.*]])>{{.*}} : (i32) -> !llvm.ptr<5>
939// AMDGPU-NEXT:   %[[box_copy:.*]] = llvm.addrspacecast %[[alloca_box_copy]] : !llvm.ptr<5> to !llvm.ptr
940// CHECK-NEXT:    %[[size:.*]] = llvm.mlir.constant(48 : i32) : i32
941// CHECK-NEXT:    "llvm.intr.memcpy"(%[[box_copy]], %[[arg0]], %[[size]]) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> ()
942// CHECK-NEXT:    llvm.call @takes_box(%[[box_copy]]) : (!llvm.ptr) -> ()
943// CHECK-NEXT:    llvm.return
944// CHECK-NEXT:  }
945
946// -----
947
948func.func @test_assumed_rank_load(%arg0: !fir.ref<!fir.box<!fir.array<*:f64>>>) -> () {
949  %0 = fir.load %arg0 : !fir.ref<!fir.box<!fir.array<*:f64>>>
950  fir.call @some_assumed_rank_func(%0) : (!fir.box<!fir.array<*:f64>>) -> ()
951  return
952}
953func.func private @some_assumed_rank_func(!fir.box<!fir.array<*:f64>>) -> ()
954
955// CHECK-LABEL:   llvm.func @test_assumed_rank_load(
956// CHECK-SAME:                                      %[[VAL_0:.*]]: !llvm.ptr) {
957// CHECK:           %[[VAL_1:.*]] = llvm.mlir.constant(1 : i32) : i32
958// GENERIC:         %[[VAL_2:.*]] = llvm.alloca %[[VAL_1]] x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<15 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr
959// AMDGPU:          %[[VAL_2A:.*]] = llvm.alloca %[[VAL_1]] x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<15 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr<5>
960// AMDGPU:          %[[VAL_2:.*]] = llvm.addrspacecast %[[VAL_2A]] : !llvm.ptr<5> to !llvm.ptr
961// CHECK:           %[[VAL_3:.*]] = llvm.mlir.constant(24 : i32) : i32
962// CHECK:           %[[VAL_4:.*]] = llvm.getelementptr %[[VAL_0]][0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<15 x array<3 x i64>>)>
963// CHECK:           %[[VAL_5:.*]] = llvm.load %[[VAL_4]] : !llvm.ptr -> i8
964// CHECK:           %[[VAL_6:.*]] = llvm.sext %[[VAL_5]] : i8 to i32
965// CHECK:           %[[VAL_7:.*]] = llvm.mlir.constant(24 : i32) : i32
966// CHECK:           %[[VAL_8:.*]] = llvm.mul %[[VAL_7]], %[[VAL_6]] : i32
967// CHECK:           %[[VAL_9:.*]] = llvm.add %[[VAL_3]], %[[VAL_8]] : i32
968// CHECK:           "llvm.intr.memcpy"(%[[VAL_2]], %[[VAL_0]], %[[VAL_9]]) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> ()
969// CHECK:           llvm.call @some_assumed_rank_func(%[[VAL_2]]) : (!llvm.ptr) -> ()
970
971// -----
972
973// Test `fir.box_rank` conversion.
974
975func.func @extract_rank(%arg0: !fir.box<!fir.array<*:f64>>) -> i32 {
976  %0 = fir.box_rank %arg0 : (!fir.box<!fir.array<*:f64>>) -> i32
977  return %0 : i32
978}
979
980// CHECK-LABEL: llvm.func @extract_rank(
981// CHECK-SAME:                          %[[ARG0:.*]]: !llvm.ptr) -> i32
982// CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
983// CHECK:         %[[RAW_RANK:.*]] = llvm.load %[[GEP]] : !llvm.ptr -> i8
984// CHECK:         %[[RANK:.*]] = llvm.sext %[[RAW_RANK]] : i8 to i32
985// CHECK:         llvm.return %[[RANK]] : i32
986
987func.func @extract_rank2(%arg0: !fir.ref<!fir.box<!fir.array<*:f64>>>) -> i32 {
988  %0 = fir.box_rank %arg0 : (!fir.ref<!fir.box<!fir.array<*:f64>>>) -> i32
989  return %0 : i32
990}
991
992// CHECK-LABEL: llvm.func @extract_rank2(
993// CHECK-SAME:                          %[[ARG0:.*]]: !llvm.ptr) -> i32
994// CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
995// CHECK:         %[[RAW_RANK:.*]] = llvm.load %[[GEP]] : !llvm.ptr -> i8
996// CHECK:         %[[RANK:.*]] = llvm.sext %[[RAW_RANK]] : i8 to i32
997// CHECK:         llvm.return %[[RANK]] : i32
998
999// -----
1000
1001// Test `fir.box_addr` conversion.
1002
1003func.func @extract_addr(%arg0: !fir.box<!fir.array<*:f64>>) -> !fir.ref<f64> {
1004  %0 = fir.box_addr %arg0 : (!fir.box<!fir.array<*:f64>>) -> !fir.ref<f64>
1005  return %0 : !fir.ref<f64>
1006}
1007
1008// CHECK-LABEL: llvm.func @extract_addr(
1009// CHECK-SAME:                          %[[ARG0:.*]]: !llvm.ptr) -> !llvm.ptr
1010// CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1011// CHECK:         %[[ADDR:.*]] = llvm.load %[[GEP]] : !llvm.ptr -> !llvm.ptr
1012// CHECK:         llvm.return %[[ADDR]] : !llvm.ptr
1013
1014// -----
1015
1016// Test `fir.box_dims` conversion.
1017
1018func.func @extract_dims(%arg0: !fir.box<!fir.array<*:f64>>) -> index {
1019  %c1 = arith.constant 0 : i32
1020  %cast = fir.convert %arg0 : (!fir.box<!fir.array<*:f64>>) -> !fir.box<!fir.array<?xf64>>
1021  %0:3 = fir.box_dims %cast, %c1 : (!fir.box<!fir.array<?xf64>>, i32) -> (index, index, index)
1022  return %0 : index
1023}
1024
1025// CHECK-LABEL: llvm.func @extract_dims(
1026// CHECK-SAME:                          %[[ARG0:.*]]: !llvm.ptr) -> i64
1027// CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i32) : i32
1028// CHECK:         %[[GEP0:.*]] = llvm.getelementptr %[[ARG0]][0, 7, %[[C0]], 0] :  (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1029// CHECK:         %[[LOAD0:.*]] = llvm.load %[[GEP0]] : !llvm.ptr -> i64
1030// CHECK:         %[[GEP1:.*]] = llvm.getelementptr %[[ARG0]][0, 7, %[[C0]], 1] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1031// CHECK:         %[[LOAD1:.*]] = llvm.load %[[GEP1]] : !llvm.ptr -> i64
1032// CHECK:         %[[GEP2:.*]] = llvm.getelementptr %[[ARG0]][0, 7, %[[C0]], 2] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1033// CHECK:         %[[LOAD2:.*]] = llvm.load %[[GEP2]] : !llvm.ptr -> i64
1034// CHECK:         llvm.return %[[LOAD0]] : i64
1035
1036// -----
1037
1038// Test `fir.box_elesize` conversion.
1039
1040func.func @extract_elesize(%arg0: !fir.box<f32>) -> i32 {
1041  %0 = fir.box_elesize %arg0 : (!fir.box<f32>) -> i32
1042  return %0 : i32
1043}
1044
1045// CHECK-LABEL: llvm.func @extract_elesize(
1046// CHECK-SAME:                             %[[ARG0:.*]]: !llvm.ptr) -> i32
1047// CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1048// CHECK:         %[[ELE_SIZE:.*]] = llvm.load %[[GEP]] : !llvm.ptr -> i64
1049// CHECK:         %[[ELE_SIZE_CONV:.*]] = llvm.trunc %[[ELE_SIZE]] : i64 to i32
1050// CHECK:         llvm.return %[[ELE_SIZE_CONV]] : i32
1051
1052// -----
1053
1054// Test `fir.box_isarray` conversion.
1055// `rank` is extracted from `fir.box` and compare to 0.
1056
1057func.func @box_isarray(%arg0: !fir.box<!fir.array<*:f64>>) -> i1 {
1058  %0 = fir.box_isarray %arg0 : (!fir.box<!fir.array<*:f64>>) -> i1
1059  return %0 : i1
1060}
1061
1062// CHECK-LABEL: llvm.func @box_isarray(
1063// CHECK-SAME:                         %[[ARG0:.*]]: !llvm.ptr) -> i1
1064// CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1065// CHECK:         %[[RANK:.*]] = llvm.load %[[GEP]] : !llvm.ptr -> i8
1066// CHECK:         %[[C0_ISARRAY:.*]] = llvm.mlir.constant(0 : i64) : i8
1067// CHECK:         %[[IS_ARRAY:.*]] = llvm.icmp "ne" %[[RANK]], %[[C0_ISARRAY]] : i8
1068// CHECK:         llvm.return %[[IS_ARRAY]] : i1
1069
1070// -----
1071
1072// Test `fir.box_isalloc` conversion.
1073// `attribute` is extracted from `fir.box` and checked against a mask equal to
1074// the value of `CFI_attribute_allocatable`.
1075
1076func.func @box_isalloc(%arg0: !fir.box<!fir.array<*:f64>>) -> i1 {
1077  %0 = fir.box_isalloc %arg0 : (!fir.box<!fir.array<*:f64>>) -> i1
1078  return %0 : i1
1079}
1080
1081// CHECK-LABEL: llvm.func @box_isalloc(
1082// CHECK-SAME:                         %[[ARG0:.*]]: !llvm.ptr) -> i1
1083// CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 5] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1084// CHECK:         %[[ATTR:.*]] = llvm.load %[[GEP]] : !llvm.ptr -> i8
1085// CHECK:         %[[ATTR_CONV:.*]] = llvm.sext %[[ATTR]] : i8 to i32
1086// CHECK:         %[[ATTR_ISALLOC:.*]] = llvm.mlir.constant(2 : i32) : i32
1087// CHECK:         %[[AND:.*]] = llvm.and %[[ATTR_CONV]], %[[ATTR_ISALLOC]]  : i32
1088// CHECK:         %[[CMP_C0:.*]] = llvm.mlir.constant(0 : i32) : i32
1089// CHECK:         %[[IS_ALLOC:.*]] = llvm.icmp "ne" %[[AND]], %[[CMP_C0]] : i32
1090// CHECK:         llvm.return %[[IS_ALLOC]] : i1
1091
1092// -----
1093
1094// Test `fir.box_isptr` conversion.
1095// `attribute` is extracted from `fir.box` and checked against a mask equal to
1096// the value of `CFI_attribute_pointer`.
1097
1098func.func @box_isptr(%arg0: !fir.box<!fir.array<*:f64>>) -> i1 {
1099  %0 = fir.box_isptr %arg0 : (!fir.box<!fir.array<*:f64>>) -> i1
1100  return %0 : i1
1101}
1102
1103// CHECK-LABEL: llvm.func @box_isptr(
1104// CHECK-SAME:                         %[[ARG0:.*]]: !llvm.ptr) -> i1
1105// CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 5] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1106// CHECK:         %[[ATTR:.*]] = llvm.load %[[GEP]] : !llvm.ptr -> i8
1107// CHECK:         %[[ATTR_CONV:.*]] = llvm.sext %[[ATTR]] : i8 to i32
1108// CHECK:         %[[ATTR_ISALLOC:.*]] = llvm.mlir.constant(1 : i32) : i32
1109// CHECK:         %[[AND:.*]] = llvm.and %[[ATTR_CONV]], %[[ATTR_ISALLOC]]  : i32
1110// CHECK:         %[[CMP_C0:.*]] = llvm.mlir.constant(0 : i32) : i32
1111// CHECK:         %[[IS_ALLOC:.*]] = llvm.icmp "ne" %[[AND]], %[[CMP_C0]] : i32
1112// CHECK:         llvm.return %[[IS_ALLOC]] : i1
1113
1114// -----
1115
1116// Test fir.alloca of one element
1117
1118func.func @alloca_one() -> !fir.ref<i32> {
1119  %1 = fir.alloca i32
1120  return %1 : !fir.ref<i32>
1121}
1122
1123// CHECK-LABEL: llvm.func @alloca_one() -> !llvm.ptr
1124// CHECK: [[N:%.*]] = llvm.mlir.constant(1 : i64) : i64
1125// GENERIC: [[A:%.*]] = llvm.alloca [[N]] x i32
1126// AMDGPU: [[AA:%.*]] = llvm.alloca [[N]] x i32 : (i64) -> !llvm.ptr<5>
1127// AMDGPU: [[A:%.*]] = llvm.addrspacecast [[AA]] : !llvm.ptr<5> to !llvm.ptr
1128// CHECK: llvm.return [[A]] : !llvm.ptr
1129
1130
1131// -----
1132
1133// Test fir.alloca of several elements
1134
1135func.func @alloca_several() -> !fir.ref<i32> {
1136  %0 = arith.constant 100 : index
1137  %1 = fir.alloca i32, %0
1138  return %1 : !fir.ref<i32>
1139}
1140
1141// CHECK-LABEL: llvm.func @alloca_several() -> !llvm.ptr
1142// CHECK: [[N:%.*]] = llvm.mlir.constant(100 : index) : i64
1143// CHECK: [[ONE:%.*]] = llvm.mlir.constant(1 : i64) : i64
1144// CHECK: [[TOTAL:%.*]] = llvm.mul [[ONE]], [[N]] : i64
1145// GENERIC: [[A:%.*]] = llvm.alloca [[TOTAL]] x i32
1146// AMDGPU: [[AA:%.*]] = llvm.alloca [[TOTAL]] x i32 : (i64) -> !llvm.ptr<5>
1147// AMDGPU: [[A:%.*]] = llvm.addrspacecast [[AA]] : !llvm.ptr<5> to !llvm.ptr
1148// CHECK: llvm.return [[A]] : !llvm.ptr
1149
1150// -----
1151
1152// Test fir.alloca of pointer to array
1153
1154func.func @alloca_ptr_to_array() -> !fir.ref<!fir.ptr<!fir.array<?xi32>>> {
1155  %1 = fir.alloca !fir.ptr<!fir.array<?xi32>>
1156  return %1 : !fir.ref<!fir.ptr<!fir.array<?xi32>>>
1157}
1158
1159// CHECK-LABEL: llvm.func @alloca_ptr_to_array() -> !llvm.ptr
1160// CHECK: [[ONE:%.*]] = llvm.mlir.constant(1 : i64) : i64
1161// GENERIC: [[A:%.*]] = llvm.alloca [[ONE]] x !llvm.ptr
1162// AMDGPU: [[AA:%.*]] = llvm.alloca [[ONE]] x !llvm.ptr : (i64) -> !llvm.ptr<5>
1163// AMDGPU: [[A:%.*]] = llvm.addrspacecast [[AA]] : !llvm.ptr<5> to !llvm.ptr
1164// CHECK: llvm.return [[A]] : !llvm.ptr
1165
1166// -----
1167
1168// Test fir.alloca of array of unknown-length chars
1169
1170func.func @alloca_char_array(%l: i32, %e : index) -> !fir.ref<!fir.array<?x?x!fir.char<1,?>>> {
1171  %a = fir.alloca !fir.array<?x?x!fir.char<1,?>>(%l : i32), %e, %e
1172  return %a :  !fir.ref<!fir.array<?x?x!fir.char<1,?>>>
1173}
1174
1175// CHECK-LABEL: llvm.func @alloca_char_array
1176// CHECK-SAME: ([[L:%.*]]: i32, [[E:%.*]]: i64) -> !llvm.ptr
1177// CHECK-DAG: [[UNUSEDONE:%.*]] = llvm.mlir.constant(1 : i64) : i64
1178// CHECK-DAG: [[LCAST:%.*]] = llvm.sext [[L]] : i32 to i64
1179// CHECK: [[PROD1:%.*]] = llvm.mul [[LCAST]], [[E]] : i64
1180// CHECK: [[PROD2:%.*]] = llvm.mul [[PROD1]], [[E]] : i64
1181// GENERIC: [[A:%.*]] = llvm.alloca [[PROD2]] x i8
1182// AMDGPU: [[AA:%.*]] = llvm.alloca [[PROD2]] x i8 : (i64) -> !llvm.ptr<5>
1183// AMDGPU: [[A:%.*]] = llvm.addrspacecast [[AA]] : !llvm.ptr<5> to !llvm.ptr
1184// CHECK: return [[A]] : !llvm.ptr
1185
1186// -----
1187
1188// Test fir.alloca of array of known-length chars
1189
1190func.func @alloca_fixed_char_array(%e : index) -> !fir.ref<!fir.array<?x?x!fir.char<1,8>>> {
1191  %a = fir.alloca !fir.array<?x?x!fir.char<1,8>>, %e, %e
1192  return %a :  !fir.ref<!fir.array<?x?x!fir.char<1,8>>>
1193}
1194
1195// CHECK-LABEL: llvm.func @alloca_fixed_char_array
1196// CHECK-SAME: ([[E:%.*]]: i64) -> !llvm.ptr
1197// CHECK-DAG: [[ONE:%.*]] = llvm.mlir.constant(1 : i64) : i64
1198// CHECK: [[PROD1:%.*]] = llvm.mul [[E]], [[ONE]] : i64
1199// CHECK: [[PROD2:%.*]] = llvm.mul [[PROD1]], [[E]] : i64
1200// GENERIC: [[A:%.*]] = llvm.alloca [[PROD2]] x !llvm.array<8 x i8>
1201// AMDGPU: [[AA:%.*]] = llvm.alloca [[PROD2]] x !llvm.array<8 x i8> : (i64) -> !llvm.ptr<5>
1202// AMDGPU: [[A:%.*]] = llvm.addrspacecast [[AA]] : !llvm.ptr<5> to !llvm.ptr
1203// CHECK: return [[A]] : !llvm.ptr
1204
1205// -----
1206
1207// Test fir.alloca of record type with LEN parameters
1208//   type t(p1,p2)
1209//      integer, len :: p1
1210//      integer(kind=2), len :: p2
1211//      integer f1
1212//      real f2
1213//   end type t
1214
1215func.func private @_QTtP.mem.size(%0 : i32, %1 : i16) -> index
1216
1217func.func @alloca_record(%arg0 : i32, %arg1 : i16) -> !fir.ref<!fir.type<_QTt(p1:i32,p2:i16){f1:i32,f2:f32}>> {
1218  %0 = fir.alloca !fir.type<_QTt(p1:i32,p2:i16){f1:i32,f2:f32}>(%arg0, %arg1 : i32, i16) {name = "_QEvar"}
1219  return %0 : !fir.ref<!fir.type<_QTt(p1:i32,p2:i16){f1:i32,f2:f32}>>
1220}
1221
1222// CHECK-LABEL: llvm.func @alloca_record
1223// CHECK-SAME: ([[ARG0:%.*]]: i32, [[ARG1:%.*]]: i16)
1224// CHECK-SAME: -> !llvm.ptr
1225// CHECK: [[SIZE:%.*]] = llvm.call @_QTtP.mem.size([[ARG0]], [[ARG1]]) : (i32, i16) -> i64
1226// GENERIC: [[ALLOC:%.*]] = llvm.alloca [[SIZE]] x i8
1227// AMDGPU: [[A:%.*]] = llvm.alloca [[SIZE]] x i8 : (i64) -> !llvm.ptr<5>
1228// AMDGPU: [[ALLOC:%.*]] = llvm.addrspacecast [[A]] : !llvm.ptr<5> to !llvm.ptr
1229// CHECK: llvm.return [[ALLOC]] : !llvm.ptr
1230
1231// -----
1232
1233// Test fir.alloca of a multidimensional array, with operands
1234
1235func.func @alloca_multidim_array(%0 : index) -> !fir.ref<!fir.array<8x16x32xf32>> {
1236  %1 = arith.constant 24 : index
1237  %2 = fir.alloca !fir.array<8x16x32xf32>, %0, %1
1238  return %2 : !fir.ref<!fir.array<8x16x32xf32>>
1239}
1240
1241// CHECK-LABEL: llvm.func @alloca_multidim_array
1242// CHECK-SAME: ([[OP1:%.*]]: i64) -> !llvm.ptr
1243// CHECK: [[OP2:%.*]] = llvm.mlir.constant(24 : index) : i64
1244// CHECK: [[ONE:%.*]] = llvm.mlir.constant(1 : i64) : i64
1245// CHECK: [[MUL1:%.*]] = llvm.mul [[OP1]], [[ONE]] : i64
1246// CHECK: [[TOTAL:%.*]] = llvm.mul [[MUL1]], [[OP2]] : i64
1247// GENERIC: [[A:%.*]] = llvm.alloca [[TOTAL]] x !llvm.array<32 x array<16 x array<8 x f32>>>
1248// AMDGPU: [[AA:%.*]] = llvm.alloca [[TOTAL]] x !llvm.array<32 x array<16 x array<8 x f32>>> : (i64) -> !llvm.ptr<5>
1249// AMDGPU: [[A:%.*]] = llvm.addrspacecast [[AA]] : !llvm.ptr<5> to !llvm.ptr
1250// CHECK: llvm.return [[A]] : !llvm.ptr
1251
1252// -----
1253
1254// Test fir.alloca of a multidimensional array with constant interior
1255
1256func.func @alloca_const_interior_array(%0 : index) -> !fir.ref<!fir.array<8x9x?x?xf32>> {
1257  %1 = arith.constant 64 : index
1258  %2 = fir.alloca !fir.array<8x9x?x?xf32>, %0, %1
1259  return %2 : !fir.ref<!fir.array<8x9x?x?xf32>>
1260}
1261
1262// CHECK-LABEL: llvm.func @alloca_const_interior_array
1263// CHECK-SAME: ([[OP1:%.*]]: i64) -> !llvm.ptr
1264// CHECK: [[OP2:%.*]] = llvm.mlir.constant(64 : index) : i64
1265// CHECK: [[ONE:%.*]] = llvm.mlir.constant(1 : i64) : i64
1266// CHECK: [[MUL1:%.*]] = llvm.mul [[OP1]], [[ONE]] : i64
1267// CHECK: [[TOTAL:%.*]] = llvm.mul [[MUL1]], [[OP2]] : i64
1268// GENERIC: [[A:%.*]] = llvm.alloca [[TOTAL]] x !llvm.array<9 x array<8 x f32>>
1269// AMDGPU: [[AA:%.*]] = llvm.alloca [[TOTAL]] x !llvm.array<9 x array<8 x f32>> : (i64) -> !llvm.ptr<5>
1270// AMDGPU: [[A:%.*]] = llvm.addrspacecast [[AA]] : !llvm.ptr<5> to !llvm.ptr
1271// CHECK: llvm.return [[A]] : !llvm.ptr
1272
1273// -----
1274
1275// Test alloca with an array with holes.
1276// Constant factor of 60 (4*3*5) must be included.
1277
1278func.func @alloca_array_with_holes(%0 : index, %1 : index) -> !fir.ref<!fir.array<4x?x3x?x5xi32>> {
1279  %a = fir.alloca !fir.array<4x?x3x?x5xi32>, %0, %1
1280  return %a : !fir.ref<!fir.array<4x?x3x?x5xi32>>
1281}
1282
1283// CHECK-LABEL: llvm.func @alloca_array_with_holes
1284// CHECK-SAME: ([[A:%.*]]: i64, [[B:%.*]]: i64) -> !llvm.ptr
1285// CHECK-DAG: [[ONE:%.*]] = llvm.mlir.constant(1 : i64) : i64
1286// CHECK-DAG: [[FIXED:%.*]] = llvm.mlir.constant(15 : i64) : i64
1287// CHECK: [[PROD1:%.*]] = llvm.mul [[ONE]], [[FIXED]] : i64
1288// CHECK: [[PROD2:%.*]] = llvm.mul [[PROD1]], [[A]] : i64
1289// CHECK: [[PROD3:%.*]] = llvm.mul [[PROD2]], [[B]] : i64
1290// GENERIC: [[RES:%.*]] = llvm.alloca [[PROD3]] x !llvm.array<4 x i32>
1291// AMDGPU: [[AA:%.*]] = llvm.alloca [[PROD3]] x !llvm.array<4 x i32> : (i64) -> !llvm.ptr<5>
1292// AMDGPU: [[RES:%.*]] = llvm.addrspacecast [[AA]] : !llvm.ptr<5> to !llvm.ptr
1293// CHECK: llvm.return [[RES]] : !llvm.ptr
1294
1295// -----
1296
1297// Test alloca of assumed-rank box
1298
1299func.func @alloca_assumed_rank_box() -> !fir.ref<!fir.box<!fir.array<*:f32>>> {
1300  %a = fir.alloca !fir.box<!fir.array<*:f32>>
1301  return %a : !fir.ref<!fir.box<!fir.array<*:f32>>>
1302}
1303// CHECK-LABEL: llvm.func @alloca_assumed_rank_box
1304// CHECK: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64
1305// GENERIC: llvm.alloca %[[ONE]] x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<15 x array<3 x i64>>)> : (i64) -> !llvm.ptr
1306// AMDGPU: %[[AA:.*]] = llvm.alloca %[[ONE]] x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<15 x array<3 x i64>>)> : (i64) -> !llvm.ptr<5>
1307// AMDGPU: llvm.addrspacecast %[[AA]] : !llvm.ptr<5> to !llvm.ptr
1308
1309// -----
1310
1311// Test `fir.select_case` operation conversion with INTEGER.
1312
1313func.func @select_case_integer(%arg0: !fir.ref<i32>) -> i32 {
1314  %2 = fir.load %arg0 : !fir.ref<i32>
1315  %c1_i32 = arith.constant 1 : i32
1316  %c2_i32 = arith.constant 2 : i32
1317  %c4_i32 = arith.constant 4 : i32
1318  %c5_i32 = arith.constant 5 : i32
1319  %c7_i32 = arith.constant 7 : i32
1320  %c8_i32 = arith.constant 8 : i32
1321  %c15_i32 = arith.constant 15 : i32
1322  %c21_i32 = arith.constant 21 : i32
1323  fir.select_case %2 : i32 [#fir.upper, %c1_i32, ^bb1,
1324                            #fir.point, %c2_i32, ^bb2,
1325                            #fir.interval, %c4_i32, %c5_i32, ^bb4,
1326                            #fir.point, %c7_i32, ^bb5,
1327                            #fir.interval, %c8_i32, %c15_i32, ^bb5,
1328                            #fir.lower, %c21_i32, ^bb5,
1329                            unit, ^bb3]
1330^bb1:  // pred: ^bb0
1331  %c1_i32_0 = arith.constant 1 : i32
1332  fir.store %c1_i32_0 to %arg0 : !fir.ref<i32>
1333  cf.br ^bb6
1334^bb2:  // pred: ^bb0
1335  %c2_i32_1 = arith.constant 2 : i32
1336  fir.store %c2_i32_1 to %arg0 : !fir.ref<i32>
1337  cf.br ^bb6
1338^bb3:  // pred: ^bb0
1339  %c0_i32 = arith.constant 0 : i32
1340  fir.store %c0_i32 to %arg0 : !fir.ref<i32>
1341  cf.br ^bb6
1342^bb4:  // pred: ^bb0
1343  %c4_i32_2 = arith.constant 4 : i32
1344  fir.store %c4_i32_2 to %arg0 : !fir.ref<i32>
1345  cf.br ^bb6
1346^bb5:  // 3 preds: ^bb0, ^bb0, ^bb0
1347  %c7_i32_3 = arith.constant 7 : i32
1348  fir.store %c7_i32_3 to %arg0 : !fir.ref<i32>
1349  cf.br ^bb6
1350^bb6:  // 5 preds: ^bb1, ^bb2, ^bb3, ^bb4, ^bb5
1351  %3 = fir.load %arg0 : !fir.ref<i32>
1352  return %3 : i32
1353}
1354
1355// CHECK-LABEL: llvm.func @select_case_integer(
1356// CHECK-SAME:                         %[[ARG0:.*]]: !llvm.ptr) -> i32 {
1357// CHECK:         %[[SELECT_VALUE:.*]] = llvm.load %[[ARG0]] : !llvm.ptr -> i32
1358// CHECK:         %[[CST1:.*]] = llvm.mlir.constant(1 : i32) : i32
1359// CHECK:         %[[CST2:.*]] = llvm.mlir.constant(2 : i32) : i32
1360// CHECK:         %[[CST4:.*]] = llvm.mlir.constant(4 : i32) : i32
1361// CHECK:         %[[CST5:.*]] = llvm.mlir.constant(5 : i32) : i32
1362// CHECK:         %[[CST7:.*]] = llvm.mlir.constant(7 : i32) : i32
1363// CHECK:         %[[CST8:.*]] = llvm.mlir.constant(8 : i32) : i32
1364// CHECK:         %[[CST15:.*]] = llvm.mlir.constant(15 : i32) : i32
1365// CHECK:         %[[CST21:.*]] = llvm.mlir.constant(21 : i32) : i32
1366// Check for upper bound `case (:1)`
1367// CHECK:         %[[CMP_SLE:.*]] = llvm.icmp "sle" %[[SELECT_VALUE]], %[[CST1]] : i32
1368// CHECK:         llvm.cond_br %[[CMP_SLE]], ^bb2, ^bb1
1369// CHECK-LABEL: ^bb1:
1370// Check for point value `case (2)`
1371// CHECK:         %[[CMP_EQ:.*]] = llvm.icmp "eq" %[[SELECT_VALUE]], %[[CST2]] : i32
1372// CHECK:         llvm.cond_br %[[CMP_EQ]], ^bb4, ^bb3
1373// Block ^bb1 in original FIR code.
1374// CHECK-LABEL: ^bb2:
1375// CHECK:         llvm.br ^bb{{.*}}
1376// CHECK-LABEL: ^bb3:
1377// Check for the lower bound for the interval `case (4:5)`
1378// CHECK:        %[[CMP_SLE:.*]] = llvm.icmp "sle" %[[CST4]], %[[SELECT_VALUE]] : i32
1379// CHECK:        llvm.cond_br %[[CMP_SLE]], ^bb[[UPPERBOUND5:.*]], ^bb7
1380// Block ^bb2 in original FIR code.
1381// CHECK-LABEL: ^bb4:
1382// CHECK:        llvm.br ^bb{{.*}}
1383// Block ^bb3 in original FIR code.
1384// CHECK-LABEL: ^bb5:
1385// CHECK:        llvm.br ^bb{{.*}}
1386// CHECK:       ^bb[[UPPERBOUND5]]:
1387// Check for the upper bound for the interval `case (4:5)`
1388// CHECK:        %[[CMP_SLE:.*]] = llvm.icmp "sle" %[[SELECT_VALUE]], %[[CST5]] : i32
1389// CHECK:        llvm.cond_br %[[CMP_SLE]], ^bb8, ^bb7
1390// CHECK-LABEL: ^bb7:
1391// Check for the point value 7 in `case (7,8:15,21:)`
1392// CHECK: %[[CMP_EQ:.*]] = llvm.icmp "eq" %[[SELECT_VALUE]], %[[CST7]] : i32
1393// CHECK: llvm.cond_br %[[CMP_EQ]], ^bb13, ^bb9
1394// Block ^bb4 in original FIR code.
1395// CHECK-LABEL: ^bb8:
1396// CHECK:        llvm.br ^bb{{.*}}
1397// CHECK-LABEL: ^bb9:
1398// Check for lower bound 8 in `case (7,8:15,21:)`
1399// CHECK:        %[[CMP_SLE:.*]] = llvm.icmp "sle" %[[CST8]], %[[SELECT_VALUE]] : i32
1400// CHECK:        llvm.cond_br %[[CMP_SLE]], ^bb[[INTERVAL8_15:.*]], ^bb11
1401// CHECK:       ^bb[[INTERVAL8_15]]:
1402// Check for upper bound 15 in `case (7,8:15,21:)`
1403// CHECK:        %[[CMP_SLE:.*]] = llvm.icmp "sle" %[[SELECT_VALUE]], %[[CST15]] : i32
1404// CHECK:        llvm.cond_br %[[CMP_SLE]], ^bb13, ^bb11
1405// CHECK-LABEL: ^bb11:
1406// Check for lower bound 21 in `case (7,8:15,21:)`
1407// CHECK:        %[[CMP_SLE:.*]]  = llvm.icmp "sle" %[[CST21]], %[[SELECT_VALUE]] : i32
1408// CHECK:        llvm.cond_br %[[CMP_SLE]], ^bb13, ^bb12
1409// CHECK-LABEL: ^bb12:
1410// CHECK:         llvm.br ^bb5
1411// Block ^bb5 in original FIR code.
1412// CHECK-LABEL: ^bb13:
1413// CHECK:        llvm.br ^bb14
1414// Block ^bb6 in original FIR code.
1415// CHECK-LABEL: ^bb14:
1416// CHECK:        %[[RET:.*]] = llvm.load %[[ARG0:.*]] : !llvm.ptr -> i32
1417// CHECK:        llvm.return %[[RET]] : i32
1418
1419// -----
1420
1421// Test `fir.select_case` operation conversion with LOGICAL.
1422
1423func.func @select_case_logical(%arg0: !fir.ref<!fir.logical<4>>) {
1424  %1 = fir.load %arg0 : !fir.ref<!fir.logical<4>>
1425  %2 = fir.convert %1 : (!fir.logical<4>) -> i1
1426  %false = arith.constant false
1427  %true = arith.constant true
1428  fir.select_case %2 : i1 [#fir.point, %false, ^bb1,
1429                           #fir.point, %true, ^bb2,
1430                            unit, ^bb3]
1431^bb1:
1432  %c1_i32 = arith.constant 1 : i32
1433  cf.br ^bb3
1434^bb2:
1435  %c2_i32 = arith.constant 2 : i32
1436  cf.br ^bb3
1437^bb3:
1438  return
1439}
1440
1441// CHECK-LABEL: llvm.func @select_case_logical(
1442// CHECK-SAME:                                 %[[ARG0:.*]]: !llvm.ptr
1443// CHECK:         %[[LOAD_ARG0:.*]] = llvm.load %[[ARG0]] : !llvm.ptr -> i32
1444// CHECK:         %[[CST_ZERO:.*]] = llvm.mlir.constant(0 : i64) : i32
1445// CHECK:         %[[SELECT_VALUE:.*]] = llvm.icmp "ne" %[[LOAD_ARG0]], %[[CST_ZERO]] : i32
1446// CHECK:         %[[CST_FALSE:.*]] = llvm.mlir.constant(false) : i1
1447// CHECK:         %[[CST_TRUE:.*]] = llvm.mlir.constant(true) : i1
1448// CHECK:         %[[CMPEQ:.*]] = llvm.icmp "eq" %[[SELECT_VALUE]], %[[CST_FALSE]] : i1
1449// CHECK:         llvm.cond_br %[[CMPEQ]], ^bb2, ^bb1
1450// CHECK-LABEL: ^bb1:
1451// CHECK:         %[[CMPEQ:.*]] = llvm.icmp "eq" %[[SELECT_VALUE]], %[[CST_TRUE]] : i1
1452// CHECK:         llvm.cond_br %[[CMPEQ]], ^bb4, ^bb3
1453// CHECK-LABEL: ^bb2:
1454// CHECK:         llvm.br ^bb5
1455// CHECK-LABEL: ^bb3:
1456// CHECK:         llvm.br ^bb5
1457// CHECK-LABEL: ^bb4:
1458// CHECK:         llvm.br ^bb5
1459// CHECK-LABEL: ^bb5:
1460// CHECK:        llvm.return
1461
1462// -----
1463
1464// Test `fir.is_present`
1465
1466func.func @test_is_present_i64(%arg0: !fir.ref<i64>) -> () {
1467  %0 = fir.is_present %arg0 : (!fir.ref<i64>) -> i1
1468  return
1469}
1470
1471// CHECK-LABEL: @test_is_present_i64
1472// CHECK-SAME: (%[[arg:.*]]: !llvm.ptr)
1473// CHECK-NEXT:  %[[constant:.*]] = llvm.mlir.constant(0 : i64) : i64
1474// CHECK-NEXT:  %[[ptr:.*]] = llvm.ptrtoint %[[arg]] : !llvm.ptr to i64
1475// CHECK-NEXT:  %{{.*}} = llvm.icmp "ne" %[[ptr]], %[[constant]] : i64
1476// CHECK-NEXT:  llvm.return
1477// CHECK-NEXT: }
1478
1479func.func @test_is_present_box(%arg0: !fir.box<!fir.ref<i64>>) -> () {
1480  %0 = fir.is_present %arg0 : (!fir.box<!fir.ref<i64>>) -> i1
1481  return
1482}
1483
1484// CHECK-LABEL: @test_is_present_box
1485// CHECK-SAME: (%[[arg:.*]]: !llvm.ptr)
1486// CHECK-NEXT: %[[constant:.*]] = llvm.mlir.constant(0 : i64) : i64
1487// CHECK-NEXT: %[[ptr:.*]] = llvm.ptrtoint %[[arg]] : !llvm.ptr to i64
1488// CHECK-NEXT: %{{.*}} = llvm.icmp "ne" %[[ptr]], %[[constant]] : i64
1489// CHECK-NEXT: llvm.return
1490// CHECK-NEXT: }
1491
1492
1493// -----
1494
1495// Test `fir.absent`
1496
1497func.func @test_absent_i64() -> () {
1498  %0 = fir.absent !fir.ref<i64>
1499  return
1500}
1501
1502// CHECK-LABEL: @test_absent_i64
1503// CHECK-NEXT:  %{{.*}} = llvm.mlir.zero : !llvm.ptr
1504// CHECK-NEXT:  llvm.return
1505// CHECK-NEXT:  }
1506
1507func.func @test_absent_box() -> () {
1508  %0 = fir.absent !fir.box<!fir.array<?xf32>>
1509  return
1510}
1511// CHECK-LABEL: @test_absent_box
1512// CHECK-NEXT:  %{{.*}} = llvm.mlir.zero : !llvm.ptr
1513// CHECK-NEXT:  llvm.return
1514// CHECK-NEXT:  }
1515
1516// -----
1517
1518// This is a bit more comprehensive test for `fir.is_present` and `fir.absent`
1519// when used together
1520
1521func.func @is_present(%arg0: !fir.ref<i64>) -> i1 {
1522  %0 = fir.is_present %arg0 : (!fir.ref<i64>) -> i1
1523  return %0 : i1
1524}
1525
1526// CHECK-LABEL: @is_present
1527// CHECK-SAME: (%[[arg:.*]]: !llvm.ptr) -> i1
1528// CHECK-NEXT:  %[[constant:.*]] = llvm.mlir.constant(0 : i64) : i64
1529// CHECK-NEXT:  %[[ptr:.*]] = llvm.ptrtoint %[[arg]] : !llvm.ptr to i64
1530// CHECK-NEXT:  %[[ret_val:.*]] = llvm.icmp "ne" %[[ptr]], %[[constant]] : i64
1531// CHECK-NEXT:  llvm.return %[[ret_val]] : i1
1532// CHECK-NEXT: }
1533
1534func.func @absent() -> i1 {
1535  %0 = fir.absent !fir.ref<i64>
1536  %1 = fir.call @is_present(%0) : (!fir.ref<i64>) -> i1
1537  return %1 : i1
1538}
1539
1540// CHECK-LABEL: @absent
1541// CHECK-SAME:  () -> i1
1542// CHECK-NEXT:  %[[ptr:.*]] = llvm.mlir.zero : !llvm.ptr
1543// CHECK-NEXT:  %[[ret_val:.*]] = llvm.call @is_present(%[[ptr]]) : (!llvm.ptr) -> i1
1544// CHECK-NEXT:  llvm.return %[[ret_val]] : i1
1545
1546// -----
1547
1548// Test `fir.string_lit` conversion.
1549
1550func.func @string_lit0() {
1551  %1 = fir.string_lit "Hello, World!"(13) : !fir.char<1>
1552  return
1553}
1554
1555// CHECK-LABEL: llvm.func @string_lit0
1556// CHECK: %{{.*}} = llvm.mlir.constant("Hello, World!") : !llvm.array<13 x i8>
1557
1558func.func @string_lit1() {
1559  %2 = fir.string_lit [158, 2345](2) : !fir.char<2>
1560  return
1561}
1562
1563// CHECK-LABEL: llvm.func @string_lit1
1564// %{{.*}} = llvm.mlir.constant(dense<[158, 2345]> : vector<2xi16>) : !llvm.array<2 x i16>
1565
1566// -----
1567
1568// Test must be dead conversion.
1569
1570func.func @dead_shift() {
1571  %c0 = arith.constant 0 : index
1572  %0 = fir.shift %c0 : (index) -> !fir.shift<1>
1573  return
1574}
1575
1576// CHECK-LABEL: llvm.func @dead_shift
1577// CHECK-NOT: fir.shift
1578// CHECK: %{{.*}} = llvm.mlir.constant(0 : index) : i{{.*}}
1579// CHECK-NEXT: llvm.return
1580
1581func.func @dead_shape() {
1582  %c0 = arith.constant 0 : index
1583  %0 = fir.shape %c0 : (index) -> !fir.shape<1>
1584  return
1585}
1586
1587// CHECK-LABEL: llvm.func @dead_shape
1588// CHECK-NOT: fir.shape
1589// CHECK: %{{.*}} = llvm.mlir.constant(0 : index) : i{{.*}}
1590// CHECK-NEXT: llvm.return
1591
1592func.func @dead_shapeshift() {
1593  %c0 = arith.constant 0 : index
1594  %0 = fir.shape_shift %c0, %c0 : (index, index) -> !fir.shapeshift<1>
1595  return
1596}
1597
1598// CHECK-LABEL: llvm.func @dead_shapeshift
1599// CHECK-NOT: fir.shape_shift
1600// CHECK: %{{.*}} = llvm.mlir.constant(0 : index) : i{{.*}}
1601// CHECK-NEXT: llvm.return
1602
1603func.func @dead_slice() {
1604  %c0 = arith.constant 0 : index
1605  %0 = fir.slice %c0, %c0, %c0 : (index, index, index) -> !fir.slice<1>
1606  return
1607}
1608
1609// CHECK-LABEL: llvm.func @dead_slice
1610// CHECK-NOT: fir.slice
1611// CHECK: %{{.*}} = llvm.mlir.constant(0 : index) : i{{.*}}
1612// CHECK-NEXT: llvm.return
1613
1614// -----
1615
1616// Test `fir.box_tdesc` conversion.
1617
1618func.func @box_tdesc(%arg0: !fir.box<!fir.type<dtdesc{a:i32}>>) {
1619  %0 = fir.box_tdesc %arg0 : (!fir.box<!fir.type<dtdesc{a:i32}>>) -> !fir.tdesc<!fir.type<dtdesc{a:i32}>>
1620  return
1621}
1622
1623// CHECK-LABEL: llvm.func @box_tdesc(
1624// CHECK-SAME:                       %[[ARG0:.*]]: !llvm.ptr) {
1625// CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 7] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr, array<1 x i{{.*}}>)>
1626// CHECK:         %[[LOAD:.*]] = llvm.load %[[GEP]] : !llvm.ptr -> !llvm.ptr
1627
1628// -----
1629
1630// Test `fir.embox` conversion.
1631
1632// Check basic creation of a descriptor and insertion of values.
1633// The indices used to insert values into the descriptor correspond the
1634// position of the fields in the descriptor as defined in `CFI_cdesc_t` in
1635// flang/ISO_Fortran_binding.h.
1636
1637func.func @embox0(%arg0: !fir.ref<!fir.array<100xi32>>) {
1638  %0 = fir.embox %arg0() : (!fir.ref<!fir.array<100xi32>>) -> !fir.box<!fir.array<100xi32>>
1639  return
1640}
1641
1642// CHECK-LABEL: func @embox0(
1643// CHECK-SAME:               %[[ARG0:.*]]: !llvm.ptr
1644// CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : i32) : i32
1645// GENERIC:       %[[ALLOCA:.*]] = llvm.alloca %[[C1]] x !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})> {alignment = 8 : i64} : (i32) -> !llvm.ptr
1646// AMDGPU:        %[[AA:.*]] = llvm.alloca %[[C1]] x !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})> {alignment = 8 : i64} : (i32) -> !llvm.ptr<5>
1647// AMDGPU:        %[[ALLOCA:.*]] = llvm.addrspacecast %[[AA]] : !llvm.ptr<5> to !llvm.ptr
1648// CHECK:         %[[TYPE_CODE:.*]] = llvm.mlir.constant(9 : i32) : i32
1649// CHECK:         %[[NULL:.*]] = llvm.mlir.zero : !llvm.ptr
1650// CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
1651// CHECK:         %[[I64_ELEM_SIZE:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64
1652// CHECK:         %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1653// CHECK:         %[[DESC0:.*]] = llvm.insertvalue %[[I64_ELEM_SIZE]], %[[DESC]][1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1654// CHECK:         %[[CFI_VERSION:.*]] = llvm.mlir.constant(20240719 : i32) : i32
1655// CHECK:         %[[DESC1:.*]] = llvm.insertvalue %[[CFI_VERSION]], %[[DESC0]][2] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1656// CHECK:         %[[RANK:.*]] = llvm.mlir.constant(0 : i32) : i32
1657// CHECK:         %[[RANK_I8:.*]] = llvm.trunc %[[RANK]] : i32 to i8
1658// CHECK:         %[[DESC2:.*]] = llvm.insertvalue %[[RANK_I8]], %[[DESC1]][3] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1659// CHECK:         %[[TYPE_CODE_I8:.*]] = llvm.trunc %[[TYPE_CODE]] : i32 to i8
1660// CHECK:         %[[DESC3:.*]] = llvm.insertvalue %[[TYPE_CODE_I8]], %[[DESC2]][4] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1661// CHECK:         %[[ATTR:.*]] = llvm.mlir.constant(0 : i32) : i32
1662// CHECK:         %[[ATTR_I8:.*]] = llvm.trunc %[[ATTR]] : i32 to i8
1663// CHECK:         %[[DESC4:.*]] = llvm.insertvalue %[[ATTR_I8]], %[[DESC3]][5] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1664// CHECK:         %[[F18ADDENDUM:.*]] = llvm.mlir.constant(0 : i32) : i32
1665// CHECK:         %[[F18ADDENDUM_I8:.*]] = llvm.trunc %[[F18ADDENDUM]] : i32 to i8
1666// CHECK:         %[[DESC5:.*]] = llvm.insertvalue %[[F18ADDENDUM_I8]], %[[DESC4]][6] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1667// CHECK:         %[[DESC6:.*]] = llvm.insertvalue %[[ARG0]], %[[DESC5]][0] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1668// CHECK:         llvm.store %[[DESC6]], %[[ALLOCA]] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>, !llvm.ptr
1669
1670// Check `fir.embox` in a `fir.global`. Descriptors created by `fir.embox`
1671// conversion are not generating `alloca` instructions. This test make sure of
1672// that.
1673
1674fir.global @box_global : !fir.ref<!fir.array<?xi32>> {
1675  %arr = fir.zero_bits !fir.ref<!fir.array<?xi32>>
1676  %0 = arith.constant 0 : index
1677  %3 = fir.embox %arr: (!fir.ref<!fir.array<?xi32>>) -> !fir.box<!fir.array<?xi32>>
1678  fir.has_value %arr : !fir.ref<!fir.array<?xi32>>
1679}
1680
1681// CHECK-LABEL: llvm.mlir.global external @box_global
1682// CHECK-NOT:     llvm.alloca
1683
1684// Check `fir.embox` conversion of a POINTER entity. Make sure that the
1685// attribute in the descriptor is set to 1 (value of CFI_attribute_pointer
1686// in flang/ISO_Fortran_binding.h).
1687
1688func.func @embox_pointer(%arg0: !fir.ref<i32>) {
1689  %0 = fir.embox %arg0 : (!fir.ref<i32>) -> !fir.box<!fir.ptr<i32>>
1690  return
1691}
1692
1693// CHECK-LABEL: llvm.func @embox_pointer
1694// Check 1st 1 constant to skip it.
1695// CHECK: %{{.*}} = llvm.mlir.constant(1 : i32) : i32
1696// CHECK: %[[CFI_ATTR_POINTER:.*]] = llvm.mlir.constant(1 : i32) : i32
1697// CHECK: %[[ATTR_I8:.*]] = llvm.trunc %[[CFI_ATTR_POINTER]] : i32 to i8
1698// CHECK: %{{.*}} = llvm.insertvalue %[[ATTR_I8]], %{{.*}}[5] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1699
1700// Check `fir.embox` conversion of an ALLOCATABLE entity. Make sure that the
1701// attribute in the descriptor is set to 2 (value of CFI_attribute_allocatable
1702// in flang/ISO_Fortran_binding.h).
1703
1704func.func @embox_allocatable(%arg0: !fir.heap<!fir.array<?x!fir.char<1,10>>>) {
1705  %0 = fir.embox %arg0 : (!fir.heap<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>
1706  return
1707}
1708
1709// CHECK-LABEL: llvm.func @embox_allocatable
1710// CHECK: %[[CFI_ATTR_ALLOCATABLE:.*]] = llvm.mlir.constant(2 : i32) : i32
1711// CHECK: %[[ATTR_I8:.*]] = llvm.trunc %[[CFI_ATTR_ALLOCATABLE]] : i32 to i8
1712// CHECK: %{{.*}} = llvm.insertvalue %[[ATTR_I8]], %{{.*}}[5] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1713
1714// Check `fir.embox` conversion of a type code.
1715
1716func.func @embox_typecode0(%arg0: !fir.ref<i64>) {
1717  %0 = fir.embox %arg0 : (!fir.ref<i64>) -> !fir.box<!fir.ptr<i64>>
1718  return
1719}
1720
1721// CHECK-LABEL: llvm.func @embox_typecode0
1722// CHECK: %[[TYPE_CODE_I64:.*]] = llvm.mlir.constant(10 : i32) : i32
1723// CHECK: %[[TYPE_CODE_I64_I8:.*]] = llvm.trunc %[[TYPE_CODE_I64]] : i32 to i8
1724// CHECK: %{{.*}} = llvm.insertvalue %[[TYPE_CODE_I64_I8]], %{{.*}}[4] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1725
1726func.func @embox_typecode1(%arg0: !fir.ref<f32>) {
1727  %0 = fir.embox %arg0 : (!fir.ref<f32>) -> !fir.box<!fir.ptr<f32>>
1728  return
1729}
1730
1731// CHECK-LABEL: llvm.func @embox_typecode1
1732// CHECK: %[[TYPE_CODE_F32:.*]] = llvm.mlir.constant(27 : i32) : i32
1733// CHECK: %[[TYPE_CODE_F32_I8:.*]] = llvm.trunc %[[TYPE_CODE_I64]] : i32 to i8
1734// CHECK: %{{.*}} = llvm.insertvalue %[[TYPE_CODE_F32_I8]], %{{.*}}[4] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1735
1736func.func @embox_typecode2(%arg0: !fir.ref<f128>) {
1737  %0 = fir.embox %arg0 : (!fir.ref<f128>) -> !fir.box<!fir.ptr<f128>>
1738  return
1739}
1740
1741// CHECK-LABEL: llvm.func @embox_typecode2
1742// CHECK: %[[TYPE_CODE_F128:.*]] = llvm.mlir.constant(31 : i32) : i32
1743// CHECK: %[[TYPE_CODE_F128_I8:.*]] = llvm.trunc %[[TYPE_CODE_F128]] : i32 to i8
1744// CHECK: %{{.*}} = llvm.insertvalue %[[TYPE_CODE_F128_I8]], %{{.*}}[4] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1745
1746func.func @embox_typecode3(%arg0: !fir.ref<complex<f32>>) {
1747  %0 = fir.embox %arg0 : (!fir.ref<complex<f32>>) -> !fir.box<!fir.ptr<complex<f32>>>
1748  return
1749}
1750
1751// CHECK-LABEL: llvm.func @embox_typecode3
1752// CHECK: %[[TYPE_CODE_CPLX4:.*]] = llvm.mlir.constant(34 : i32) : i32
1753// CHECK: %[[TYPE_CODE_CPLX4_I8:.*]] = llvm.trunc %[[TYPE_CODE_F128]] : i32 to i8
1754// CHECK: %{{.*}} = llvm.insertvalue %[[TYPE_CODE_CPLX4_I8]], %{{.*}}[4] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1755
1756func.func @embox_typecode4(%arg0: !fir.ref<!fir.logical<1>>) {
1757  %0 = fir.embox %arg0 : (!fir.ref<!fir.logical<1>>) -> !fir.box<!fir.ptr<!fir.logical<1>>>
1758  return
1759}
1760
1761// CHECK-LABEL: llvm.func @embox_typecode4
1762// CHECK: %[[TYPE_CODE_I64:.*]] = llvm.mlir.constant(39 : i32) : i32
1763// CHECK: %[[TYPE_CODE_I64_I8:.*]] = llvm.trunc %[[TYPE_CODE_I64]] : i32 to i8
1764// CHECK: %{{.*}} = llvm.insertvalue %[[TYPE_CODE_I64_I8]], %{{.*}}[4] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1765
1766// -----
1767
1768// Test `fir.embox` conversion. This test creates a global so it needs to be
1769// split from others.
1770
1771// Check descriptor for a derived type. Check that the f18Addendum flag is set
1772// to 1 meaning the addendum is present (true) and the addendum values are
1773// inserted.
1774
1775fir.global linkonce @_QMtest_dinitE.dt.tseq constant : i8
1776
1777func.func @embox1(%arg0: !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>) {
1778  %0 = fir.embox %arg0() : (!fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>) -> !fir.box<!fir.type<_QMtest_dinitTtseq{i:i32}>>
1779  return
1780}
1781
1782// CHECK-COMDAT: llvm.mlir.global linkonce constant @_QMtest_dinitE.dt.tseq() comdat(@__llvm_comdat::@_QMtest_dinitE.dt.tseq) {addr_space = 0 : i32} : i8
1783// CHECK-NO-COMDAT: llvm.mlir.global linkonce constant @_QMtest_dinitE.dt.tseq() {addr_space = 0 : i32} : i8
1784// CHECK-LABEL: llvm.func @embox1
1785// CHECK:         %[[TYPE_CODE:.*]] = llvm.mlir.constant(42 : i32) : i32
1786// CHECK:         %[[VERSION:.*]] = llvm.mlir.constant(20240719 : i32) : i32
1787// CHECK:         %{{.*}} = llvm.insertvalue %[[VERSION]], %{{.*}}[2] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, ptr, array<1 x i64>)>
1788// CHECK:         %[[TYPE_CODE_I8:.*]] = llvm.trunc %[[TYPE_CODE]] : i32 to i8
1789// CHECK:         %{{.*}} = llvm.insertvalue %[[TYPE_CODE_I8]], %{{.*}}[4] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr, array<1 x i{{.*}}>)>
1790// CHECK:         %[[TDESC:.*]] = llvm.mlir.addressof @_QMtest_dinitE.dt.tseq : !llvm.ptr
1791// CHECK:         %{{.*}} = llvm.insertvalue %[[TDESC]], %{{.*}}[7] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr, array<1 x i{{.*}}>)>
1792
1793// -----
1794
1795// Test `fir.field_index`
1796
1797func.func @field_index_static_size_1_elem() -> () {
1798  %1 = fir.field_index i, !fir.type<t1{i:i32}>
1799  return
1800}
1801
1802// CHECK-LABEL: @field_index_static_size_1_elem
1803// CHECK-NEXT:  %{{.*}} = llvm.mlir.constant(0 : i32) : i32
1804// CHECK-NEXT:  llvm.return
1805
1806func.func @field_index_static_size_3_elems() -> () {
1807  %1 = fir.field_index k, !fir.type<t2{i:i32, j:f32, k:i8}>
1808  return
1809}
1810
1811// CHECK-LABEL: @field_index_static_size_3_elems
1812// CHECK-NEXT:  %{{.*}} = llvm.mlir.constant(2 : i32) : i32
1813// CHECK-NEXT:  llvm.return
1814
1815//  When converting `fir.field_index` for a dynamically sized record, the
1816//  offset will be calculated at runtime by calling methods like the ones
1817//  below. Note that these methods would normally be generated by the compiler.
1818func.func private @custom_typeP.field_1.offset() -> i32
1819func.func private @custom_typeP.field_2.offset() -> i32
1820
1821func.func @field_index_dynamic_size() -> () {
1822  %1 = fir.field_index field_1, !fir.type<custom_type{field_1:i32, field_2:!fir.array<?xf32>}>
1823  %2 = fir.field_index field_2, !fir.type<custom_type{field_1:i32, field_2:!fir.array<?xf32>}>
1824  return
1825}
1826
1827// CHECK-LABEL: @field_index_dynamic_size
1828// CHECK-NEXT: %{{.*}} = llvm.call @custom_typeP.field_1.offset() {field = 0 : i64} : () -> i32
1829// CHECK-NEXT: %{{.*}} = llvm.call @custom_typeP.field_2.offset() {field = 1 : i64} : () -> i32
1830// CHECK-NEXT:  llvm.return
1831
1832// -----
1833
1834// Check `fir.no_reassoc` conversion to LLVM IR dialect
1835
1836func.func @no_reassoc(%arg0: !fir.ref<i32>) {
1837  %0 = fir.alloca i32
1838  %1 = fir.load %arg0 : !fir.ref<i32>
1839  %2 = fir.no_reassoc %1 : i32
1840  fir.store %2 to %0 : !fir.ref<i32>
1841  return
1842}
1843
1844// CHECK-LABEL: llvm.func @no_reassoc(
1845// CHECK-SAME:                        %[[ARG0:.*]]: !llvm.ptr) {
1846// CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
1847// GENERIC:       %[[ALLOC:.*]] = llvm.alloca %[[C1]] x i32 : (i64) -> !llvm.ptr
1848// AMDGPU:        %[[AA:.*]] = llvm.alloca %[[C1]] x i32 : (i64) -> !llvm.ptr<5>
1849// AMDGPU:        %[[ALLOC:.*]] = llvm.addrspacecast %[[AA]] : !llvm.ptr<5> to !llvm.ptr
1850// CHECK:         %[[LOAD:.*]] = llvm.load %[[ARG0]] : !llvm.ptr -> i32
1851// CHECK:         llvm.store %[[LOAD]], %[[ALLOC]] : i32, !llvm.ptr
1852// CHECK:         llvm.return
1853
1854// -----
1855
1856// Test `fircg.ext_embox` conversion.
1857
1858// Check complete `fircg.ext_embox`.
1859
1860func.func @xembox0(%arg0: !fir.ref<!fir.array<?xi32>>) {
1861  %c0 = arith.constant 0 : i64
1862  %0 = fircg.ext_embox %arg0(%c0) origin %c0[%c0, %c0, %c0] : (!fir.ref<!fir.array<?xi32>>, i64, i64, i64, i64, i64) -> !fir.box<!fir.array<?xi32>>
1863  return
1864}
1865
1866// CHECK-LABEL: llvm.func @xembox0(
1867// CHECK-SAME:                     %[[ARG0:.*]]: !llvm.ptr
1868// CHECK:         %[[ALLOCA_SIZE:.*]] = llvm.mlir.constant(1 : i32) : i32
1869// GENERIC:       %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_SIZE]] x !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr
1870// AMDGPU:        %[[AA:.*]] = llvm.alloca %[[ALLOCA_SIZE]] x !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr<5>
1871// AMDGPU:        %[[ALLOCA:.*]] = llvm.addrspacecast %[[AA]] : !llvm.ptr<5> to !llvm.ptr
1872// CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
1873// CHECK:         %[[TYPE:.*]] = llvm.mlir.constant(9 : i32) : i32
1874// CHECK:         %[[NULL:.*]] = llvm.mlir.zero : !llvm.ptr
1875// CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
1876// CHECK:         %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64
1877// CHECK:         %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1878// CHECK:         %[[BOX1:.*]] = llvm.insertvalue %[[ELEM_LEN_I64]], %[[BOX0]][1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1879// CHECK:         %[[VERSION:.*]] = llvm.mlir.constant(20240719 : i32) : i32
1880// CHECK:         %[[BOX2:.*]] = llvm.insertvalue %[[VERSION]], %[[BOX1]][2] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1881// CHECK:         %[[RANK:.*]] = llvm.mlir.constant(1 : i32) : i32
1882// CHECK:         %[[RANK_I8:.*]] = llvm.trunc %[[RANK]] : i32 to i8
1883// CHECK:         %[[BOX3:.*]] = llvm.insertvalue %[[RANK_I8]], %[[BOX2]][3] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1884// CHECK:         %[[TYPE_I8:.*]] = llvm.trunc %[[TYPE]] : i32 to i8
1885// CHECK:         %[[BOX4:.*]] = llvm.insertvalue %[[TYPE_I8]], %[[BOX3]][4] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1886// CHECK:         %[[ATTR:.*]] = llvm.mlir.constant(0 : i32) : i32
1887// CHECK:         %[[ATTR_I8:.*]] = llvm.trunc %[[ATTR]] : i32 to i8
1888// CHECK:         %[[BOX5:.*]] = llvm.insertvalue %[[ATTR_I8]], %[[BOX4]][5] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1889// CHECK:         %[[F18ADDENDUM:.*]] = llvm.mlir.constant(0 : i32) : i32
1890// CHECK:         %[[F18ADDENDUM_I8:.*]] = llvm.trunc %[[F18ADDENDUM]] : i32 to i8
1891// CHECK:         %[[BOX6:.*]] = llvm.insertvalue %[[F18ADDENDUM_I8]], %[[BOX5]][6] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1892// CHECK:         %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64
1893// CHECK:         %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64
1894// CHECK:         %[[ADJUSTED_OFFSET:.*]] = llvm.sub %[[C0]], %[[C0]]  : i64
1895// CHECK:         %[[DIM_OFFSET:.*]] = llvm.mul %[[ADJUSTED_OFFSET]], %[[ONE]]  : i64
1896// CHECK:         %[[PTR_OFFSET:.*]] = llvm.add %[[DIM_OFFSET]], %[[ZERO]]  : i64
1897// CHECK:         %[[EXTENT0:.*]] = llvm.sub %[[C0]], %[[C0]]  : i64
1898// CHECK:         %[[EXTENT1:.*]] = llvm.add %[[EXTENT0]], %[[C0]]  : i64
1899// CHECK:         %[[EXTENT2:.*]] = llvm.sdiv %[[EXTENT1]], %[[C0]]  : i64
1900// CHECK:         %[[EXTENT_CMP:.*]] = llvm.icmp "sgt" %[[EXTENT2]], %[[ZERO]] : i64
1901// CHECK:         %[[EXTENT:.*]] = llvm.select %[[EXTENT_CMP]], %[[EXTENT2]], %[[ZERO]] : i1, i64
1902// CHECK:         %[[BOX7:.*]] = llvm.insertvalue %[[ONE]], %[[BOX6]][7, 0, 0] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1903// CHECK:         %[[BOX8:.*]] = llvm.insertvalue %[[EXTENT]], %[[BOX7]][7, 0, 1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1904// CHECK:         %[[STRIDE:.*]] = llvm.mul %[[ELEM_LEN_I64]], %[[C0]]  : i64
1905// CHECK:         %[[BOX9:.*]] = llvm.insertvalue %[[STRIDE]], %[[BOX8]][7, 0, 2] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1906// CHECK:         %[[PREV_DIM:.*]] = llvm.mul %[[ELEM_LEN_I64]], %[[C0]]  : i64
1907// CHECK:         %[[PREV_PTROFF:.*]] = llvm.mul %[[ONE]], %[[C0]]  : i64
1908// CHECK:         %[[BASE_PTR:.*]] = llvm.getelementptr %[[ARG0]][%[[PTR_OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
1909// CHECK:         %[[BOX10:.*]] = llvm.insertvalue %[[BASE_PTR]], %[[BOX9]][0] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1910// CHECK:         llvm.store %[[BOX10]], %[[ALLOCA]] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>, !llvm.ptr
1911
1912// Test i32 shape/shift/slice:
1913func.func @xembox0_i32(%arg0: !fir.ref<!fir.array<?xi32>>) {
1914  %c0 = arith.constant 0 : i32
1915  %c0_i64 = arith.constant 0 : i64
1916  %0 = fircg.ext_embox %arg0(%c0) origin %c0[%c0, %c0, %c0] : (!fir.ref<!fir.array<?xi32>>, i32, i32, i32, i32, i32) -> !fir.box<!fir.array<?xi32>>
1917  return
1918}
1919// CHECK-LABEL: llvm.func @xembox0_i32(
1920// CHECK-SAME:                     %[[ARG0:.*]]: !llvm.ptr
1921// CHECK:         %[[ALLOCA_SIZE:.*]] = llvm.mlir.constant(1 : i32) : i32
1922// GENERIC:       %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_SIZE]] x !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr
1923// AMDGPU:        %[[AA:.*]] = llvm.alloca %[[ALLOCA_SIZE]] x !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr<5>
1924// AMDGPU:        %[[ALLOCA:.*]] = llvm.addrspacecast %[[AA]] : !llvm.ptr<5> to !llvm.ptr
1925// CHECK:         %[[C0_I32:.*]] = llvm.mlir.constant(0 : i32) : i32
1926// CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
1927// CHECK:         %[[TYPE:.*]] = llvm.mlir.constant(9 : i32) : i32
1928// CHECK:         %[[NULL:.*]] = llvm.mlir.zero : !llvm.ptr
1929// CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
1930// CHECK:         %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64
1931// CHECK:         %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1932// CHECK:         %[[BOX1:.*]] = llvm.insertvalue %[[ELEM_LEN_I64]], %[[BOX0]][1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1933// CHECK:         %[[VERSION:.*]] = llvm.mlir.constant(20240719 : i32) : i32
1934// CHECK:         %[[BOX2:.*]] = llvm.insertvalue %[[VERSION]], %[[BOX1]][2] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1935// CHECK:         %[[RANK:.*]] = llvm.mlir.constant(1 : i32) : i32
1936// CHECK:         %[[RANK_I8:.*]] = llvm.trunc %[[RANK]] : i32 to i8
1937// CHECK:         %[[BOX3:.*]] = llvm.insertvalue %[[RANK_I8]], %[[BOX2]][3] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1938// CHECK:         %[[TYPE_I8:.*]] = llvm.trunc %[[TYPE]] : i32 to i8
1939// CHECK:         %[[BOX4:.*]] = llvm.insertvalue %[[TYPE_I8]], %[[BOX3]][4] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1940// CHECK:         %[[ATTR:.*]] = llvm.mlir.constant(0 : i32) : i32
1941// CHECK:         %[[ATTR_I8:.*]] = llvm.trunc %[[ATTR]] : i32 to i8
1942// CHECK:         %[[BOX5:.*]] = llvm.insertvalue %[[ATTR_I8]], %[[BOX4]][5] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1943// CHECK:         %[[F18ADDENDUM:.*]] = llvm.mlir.constant(0 : i32) : i32
1944// CHECK:         %[[F18ADDENDUM_I8:.*]] = llvm.trunc %[[F18ADDENDUM]] : i32 to i8
1945// CHECK:         %[[BOX6:.*]] = llvm.insertvalue %[[F18ADDENDUM_I8]], %[[BOX5]][6] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1946// CHECK:         %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64
1947// CHECK:         %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64
1948// CHECK:         %[[C0_1:.*]] = llvm.sext %[[C0_I32]] : i32 to i64
1949// CHECK:         %[[C0_2:.*]] = llvm.sext %[[C0_I32]] : i32 to i64
1950// CHECK:         %[[C0_3:.*]] = llvm.sext %[[C0_I32]] : i32 to i64
1951// CHECK:         %[[ADJUSTED_OFFSET:.*]] = llvm.sub %[[C0_2]], %[[C0_3]]  : i64
1952// CHECK:         %[[DIM_OFFSET:.*]] = llvm.mul %[[ADJUSTED_OFFSET]], %[[ONE]]  : i64
1953// CHECK:         %[[PTR_OFFSET:.*]] = llvm.add %[[DIM_OFFSET]], %[[ZERO]]  : i64
1954// CHECK:         %[[C0_4:.*]] = llvm.sext %[[C0_I32]] : i32 to i64
1955// CHECK:         %[[C0_5:.*]] = llvm.sext %[[C0_I32]] : i32 to i64
1956// CHECK:         %[[C0_6:.*]] = llvm.sext %[[C0_I32]] : i32 to i64
1957// CHECK:         %[[EXTENT0:.*]] = llvm.sub %[[C0_5]], %[[C0_4]]  : i64
1958// CHECK:         %[[EXTENT1:.*]] = llvm.add %[[EXTENT0]], %[[C0_6]]  : i64
1959// CHECK:         %[[EXTENT2:.*]] = llvm.sdiv %[[EXTENT1]], %[[C0_6]]  : i64
1960// CHECK:         %[[EXTENT_CMP:.*]] = llvm.icmp "sgt" %[[EXTENT2]], %[[ZERO]] : i64
1961// CHECK:         %[[EXTENT:.*]] = llvm.select %[[EXTENT_CMP]], %[[EXTENT2]], %[[ZERO]] : i1, i64
1962// CHECK:         %[[BOX7:.*]] = llvm.insertvalue %[[ONE]], %[[BOX6]][7, 0, 0] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1963// CHECK:         %[[BOX8:.*]] = llvm.insertvalue %[[EXTENT]], %[[BOX7]][7, 0, 1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1964// CHECK:         %[[C0_7:.*]] = llvm.sext %[[C0_I32]] : i32 to i64
1965// CHECK:         %[[STRIDE:.*]] = llvm.mul %[[ELEM_LEN_I64]], %[[C0_7]]  : i64
1966// CHECK:         %[[BOX9:.*]] = llvm.insertvalue %[[STRIDE]], %[[BOX8]][7, 0, 2] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1967// CHECK:         %[[PREV_DIM:.*]] = llvm.mul %[[ELEM_LEN_I64]], %[[C0_1]]  : i64
1968// CHECK:         %[[PREV_PTROFF:.*]] = llvm.mul %[[ONE]], %[[C0_1]]  : i64
1969// CHECK:         %[[BASE_PTR:.*]] = llvm.getelementptr %[[ARG0]][%[[PTR_OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
1970// CHECK:         %[[BOX10:.*]] = llvm.insertvalue %[[BASE_PTR]], %[[BOX9]][0] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1971// CHECK:         llvm.store %[[BOX10]], %[[ALLOCA]] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>, !llvm.ptr
1972
1973// Check adjustment of element scaling factor.
1974
1975func.func @xembox1(%arg0: !fir.ref<!fir.array<?x!fir.char<1, 10>>>) {
1976  %c0 = arith.constant 0 : i64
1977  %0 = fircg.ext_embox %arg0(%c0) origin %c0[%c0, %c0, %c0] : (!fir.ref<!fir.array<?x!fir.char<1, 10>>>, i64, i64, i64, i64, i64) -> !fir.box<!fir.array<?x!fir.char<1, 10>>>
1978  return
1979}
1980
1981// CHECK-LABEL: llvm.func @xembox1(%{{.*}}: !llvm.ptr) {
1982// CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
1983// CHECK:         %[[NULL:.*]] = llvm.mlir.zero : !llvm.ptr
1984// CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
1985// CHECK:         %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64
1986// CHECK:         %{{.*}} = llvm.insertvalue %[[ELEM_LEN_I64]], %{{.*}}[1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1987// CHECK:         %[[PREV_PTROFF:.*]] = llvm.mul %[[ELEM_LEN_I64]], %[[C0]]  : i64
1988
1989// Fortran realistic use case extracted from the following snippet:
1990//
1991// ```
1992// subroutine sb(n,sh1,sh2)
1993//   integer::n,sh1,sh2
1994//   double precision::arr(sh1:n,sh2:n)
1995//   call xb(arr(2:n,4:n))
1996// end subroutine
1997// ```
1998
1999// N is the upperbound, sh1 and sh2 are the shifts or lowerbounds
2000func.func @_QPsb(%N: index, %sh1: index, %sh2: index) {
2001  %c4 = arith.constant 4 : index
2002  %c1 = arith.constant 1 : index
2003  %c2 = arith.constant 2 : index
2004  // Calculate nelems in dim1
2005  %n1_tmp = arith.subi %N, %sh1 : index
2006  %n1 = arith.addi %n1_tmp, %c1 : index
2007  // Calculate nelems in dim2
2008  %n2_tmp = arith.subi %N, %sh2 : index
2009  %n2 = arith.addi %n2_tmp, %c1 : index
2010  %arr = fir.alloca !fir.array<?x?xf64>, %n1, %n2 {bindc_name = "arr", uniq_name = "_QFsbEarr"}
2011  %box = fircg.ext_embox %arr(%n1, %n2) origin %sh1, %sh2[%c2, %N, %c1, %c4, %N, %c1] : (!fir.ref<!fir.array<?x?xf64>>, index, index, index, index, index, index, index, index, index, index) -> !fir.box<!fir.array<?x?xf64>>
2012  fir.call @_QPxb(%box) : (!fir.box<!fir.array<?x?xf64>>) -> ()
2013  return
2014}
2015func.func private @_QPxb(!fir.box<!fir.array<?x?xf64>>)
2016
2017// CHECK-LABEL: llvm.func @_QPsb(
2018// CHECK-SAME:                   %[[N:.*]]: i64, %[[SH1:.*]]: i64, %[[SH2:.*]]: i64) {
2019// CHECK:         %[[ALLOCA_SIZE:.*]] = llvm.mlir.constant(1 : i32) : i32
2020// GENERIC:       %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_SIZE]] x !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr
2021// AMDGPU:        %[[AA:.*]] = llvm.alloca %[[ALLOCA_SIZE]] x !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr<5>
2022// AMDGPU:        %[[ALLOCA:.*]] = llvm.addrspacecast %[[AA]] : !llvm.ptr<5> to !llvm.ptr
2023// CHECK:         %[[C4:.*]] = llvm.mlir.constant(4 : index) : i64
2024// CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : index) : i64
2025// CHECK:         %[[C2:.*]] = llvm.mlir.constant(2 : index) : i64
2026// CHECK:         %[[N1_TMP:.*]] = llvm.sub %[[N]], %[[SH1]]  : i64
2027// CHECK:         %[[N1:.*]] = llvm.add %[[N1_TMP]], %[[C1]]  : i64
2028// CHECK:         %[[N2_TMP:.*]] = llvm.sub %[[N]], %[[SH2]]  : i64
2029// CHECK:         %[[N2:.*]] = llvm.add %[[N2_TMP]], %[[C1]]  : i64
2030// CHECK:         %[[C1_0:.*]] = llvm.mlir.constant(1 : i64) : i64
2031// CHECK:         %[[ARR_SIZE_TMP1:.*]] = llvm.mul %[[N1]], %[[C1_0]]  : i64
2032// CHECK:         %[[ARR_SIZE:.*]] = llvm.mul %[[ARR_SIZE_TMP1]], %[[N2]]  : i64
2033// GENERIC:       %[[ARR:.*]] = llvm.alloca %[[ARR_SIZE]] x f64 {bindc_name = "arr"} : (i64) -> !llvm.ptr
2034// AMDGPU:        %[[AR:.*]] = llvm.alloca %[[ARR_SIZE]] x f64 {bindc_name = "arr"} : (i64) -> !llvm.ptr<5>
2035// AMDGPU:        %[[ARR:.*]] = llvm.addrspacecast %[[AR]] : !llvm.ptr<5> to !llvm.ptr
2036// CHECK:         %[[TYPE_CODE:.*]] = llvm.mlir.constant(28 : i32) : i32
2037// CHECK:         %[[NULL:.*]] = llvm.mlir.zero : !llvm.ptr
2038// CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
2039// CHECK:         %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64
2040// CHECK:         %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2041// CHECK:         %[[BOX1:.*]] = llvm.insertvalue %[[ELEM_LEN_I64]], %[[BOX0]][1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2042// CHECK:         %[[VERSION:.*]] = llvm.mlir.constant(20240719 : i32) : i32
2043// CHECK:         %[[BOX2:.*]] = llvm.insertvalue %[[VERSION]], %[[BOX1]][2] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2044// CHECK:         %[[RANK:.*]] = llvm.mlir.constant(2 : i32) : i32
2045// CHECK:         %[[RANK_I8:.*]] = llvm.trunc %[[RANK]] : i32 to i8
2046// CHECK:         %[[BOX3:.*]] = llvm.insertvalue %[[RANK_I8]], %[[BOX2]][3] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2047// CHECK:         %[[TYPE_I8:.*]] = llvm.trunc %[[TYPE_CODE]] : i32 to i8
2048// CHECK:         %[[BOX4:.*]] = llvm.insertvalue %[[TYPE_I8]], %[[BOX3]][4] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2049// CHECK:         %[[ATTR:.*]] = llvm.mlir.constant(0 : i32) : i32
2050// CHECK:         %[[ATTR_I8:.*]] = llvm.trunc %[[ATTR]] : i32 to i8
2051// CHECK:         %[[BOX5:.*]] = llvm.insertvalue %[[ATTR_I8]], %[[BOX4]][5] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2052// CHECK:         %[[F18ADDENDUM:.*]] = llvm.mlir.constant(0 : i32) : i32
2053// CHECK:         %[[F18ADDENDUM_I8:.*]] = llvm.trunc %[[F18ADDENDUM]] : i32 to i8
2054// CHECK:         %[[BOX6:.*]] = llvm.insertvalue %[[F18ADDENDUM_I8]], %[[BOX5]][6] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2055// CHECK:         %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64
2056// CHECK:         %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64
2057// CHECK:         %[[ADJUSTED_OFFSET:.*]] = llvm.sub %[[C2]], %[[SH1]] : i64
2058// CHECK:         %[[DIM_OFFSET:.*]] = llvm.mul %[[ADJUSTED_OFFSET]], %[[ONE]]  : i64
2059// CHECK:         %[[PTR_OFFSET:.*]] = llvm.add %[[DIM_OFFSET]], %[[ZERO]]  : i64
2060// CHECK:         %[[EXTENT0:.*]] = llvm.sub %[[ARG0]], %[[C2]]  : i64
2061// CHECK:         %[[EXTENT1:.*]] = llvm.add %[[EXTENT0]], %[[C1]]  : i64
2062// CHECK:         %[[EXTENT2:.*]] = llvm.sdiv %[[EXTENT1]], %[[C1]]  : i64
2063// CHECK:         %[[EXTENT_CMP:.*]] = llvm.icmp "sgt" %[[EXTENT2]], %[[ZERO]] : i64
2064// CHECK:         %[[EXTENT:.*]] = llvm.select %[[EXTENT_CMP]], %[[EXTENT2]], %[[ZERO]] : i1, i64
2065// CHECK:         %[[BOX7:.*]] = llvm.insertvalue %[[ONE]], %[[BOX6]][7, 0, 0] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2066// CHECK:         %[[BOX8:.*]] = llvm.insertvalue %[[EXTENT]], %[[BOX7]][7, 0, 1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2067// CHECK:         %[[STRIDE:.*]] = llvm.mul %[[ELEM_LEN_I64]], %[[C1]]  : i64
2068// CHECK:         %[[BOX9:.*]] = llvm.insertvalue %[[STRIDE]], %[[BOX8]][7, 0, 2] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2069// CHECK:         %[[PREV_DIM:.*]] = llvm.mul %[[ELEM_LEN_I64]], %[[N1]]  : i64
2070// CHECK:         %[[PREV_PTROFF:.*]] = llvm.mul %[[ONE]], %[[N1]]  : i64
2071// CHECK:         %[[ADJUSTED_OFFSET:.*]] = llvm.sub %[[C4]], %[[SH2]]  : i64
2072// CHECK:         %[[DIM_OFFSET:.*]] = llvm.mul %[[ADJUSTED_OFFSET]], %[[PREV_PTROFF]]  : i64
2073// CHECK:         %[[PTR_OFFSET0:.*]] = llvm.add %[[DIM_OFFSET]], %[[PTR_OFFSET]]  : i64
2074// CHECK:         %[[EXT_SUB:.*]] = llvm.sub %[[N]], %[[C4]]  : i64
2075// CHECK:         %[[EXT_ADD:.*]] = llvm.add %[[EXT_SUB]], %[[C1]]  : i64
2076// CHECK:         %[[EXT_SDIV:.*]] = llvm.sdiv %[[EXT_ADD]], %[[C1]]  : i64
2077// CHECK:         %[[EXT_ICMP:.*]] = llvm.icmp "sgt" %[[EXT_SDIV]], %[[ZERO]] : i64
2078// CHECK:         %[[EXT_SELECT:.*]] = llvm.select %[[EXT_ICMP]], %[[EXT_SDIV]], %[[ZERO]] : i1, i64
2079// CHECK:         %[[BOX10:.*]] = llvm.insertvalue %[[ONE]], %[[BOX9]][7, 1, 0] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2080// CHECK:         %[[BOX11:.*]] = llvm.insertvalue %[[EXT_SELECT]], %[[BOX10]][7, 1, 1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2081// CHECK:         %[[STRIDE_MUL:.*]] = llvm.mul %[[PREV_DIM]], %[[C1]]  : i64
2082// CHECK:         %[[BOX12:.*]] = llvm.insertvalue %[[STRIDE_MUL]], %[[BOX11]][7, 1, 2] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2083// CHECK:         %[[BASE_PTR:.*]] = llvm.getelementptr %[[ARR]][%[[PTR_OFFSET0]]] : (!llvm.ptr, i64) -> !llvm.ptr, f64
2084// CHECK:         %[[BOX13:.*]] = llvm.insertvalue %[[BASE_PTR]], %[[BOX12]][0] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2085// CHECK:         llvm.store %[[BOX13]], %[[ALLOCA]] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>, !llvm.ptr
2086
2087// Conversion with a subcomponent.
2088
2089func.func @_QPtest_dt_slice() {
2090  %c20 = arith.constant 20 : index
2091  %c1_i64 = arith.constant 1 : i64
2092  %c10_i64 = arith.constant 10 : i64
2093  %c2_i64 = arith.constant 2 : i64
2094  %0 = fir.alloca i32 {bindc_name = "v", uniq_name = "_QFtest_dt_sliceEv"}
2095  %1 = fir.alloca !fir.array<20x!fir.type<_QFtest_dt_sliceTt{i:i32,j:i32}>> {bindc_name = "x", uniq_name = "_QFtest_dt_sliceEx"}
2096  %2 = fir.field_index i, !fir.type<_QFtest_dt_sliceTt{i:i32,j:i32}>
2097  %5 = fircg.ext_embox %1(%c20)[%c1_i64, %c10_i64, %c2_i64] path %2 : (!fir.ref<!fir.array<20x!fir.type<_QFtest_dt_sliceTt{i:i32,j:i32}>>>, index, i64, i64, i64, !fir.field) -> !fir.box<!fir.array<?xi32>>
2098  fir.call @_QPtest_dt_callee(%5) : (!fir.box<!fir.array<?xi32>>) -> ()
2099  return
2100}
2101func.func private @_QPtest_dt_callee(%arg0: !fir.box<!fir.array<?xi32>>)
2102
2103// CHECK-LABEL: llvm.func @_QPtest_dt_slice
2104// CHECK:         %[[ALLOCA_SIZE:.*]] = llvm.mlir.constant(1 : i32) : i32
2105// GENERIC:       %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_SIZE]] x !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr
2106// AMDGPU:        %[[AA:.*]] = llvm.alloca %[[ALLOCA_SIZE]] x !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr<5>
2107// AMDGPU:        %[[ALLOCA:.*]] = llvm.addrspacecast %[[AA]] : !llvm.ptr<5> to !llvm.ptr
2108// CHECK:         %[[ALLOCA_SIZE_X:.*]] = llvm.mlir.constant(1 : i64) : i64
2109// GENERIC:       %[[X:.*]] = llvm.alloca %[[ALLOCA_SIZE_X]] x !llvm.array<20 x struct<"_QFtest_dt_sliceTt", (i32, i32)>> {bindc_name = "x"} : (i64) -> !llvm.ptr
2110// AMDGPU:        %[[AC:.*]] = llvm.alloca %[[ALLOCA_SIZE_X]] x !llvm.array<20 x struct<"_QFtest_dt_sliceTt", (i32, i32)>> {bindc_name = "x"} : (i64) -> !llvm.ptr<5>
2111// AMDGPU:        %[[X:.*]] = llvm.addrspacecast %[[AC]] : !llvm.ptr<5> to !llvm.ptr
2112// CHECK:         %[[ALLOCA_SIZE_V:.*]] = llvm.mlir.constant(1 : i64) : i64
2113// GENERIC:       %[[V:.*]] = llvm.alloca %[[ALLOCA_SIZE_V]] x i32 {bindc_name = "v"} : (i64) -> !llvm.ptr
2114// AMDGPU:        %[[AB:.*]] = llvm.alloca %[[ALLOCA_SIZE_V]] x i32 {bindc_name = "v"} : (i64) -> !llvm.ptr<5>
2115// AMDGPU:        %[[V:.*]] = llvm.addrspacecast %[[AB]] : !llvm.ptr<5> to !llvm.ptr
2116// CHECK:         %[[C20:.*]] = llvm.mlir.constant(20 : index) : i64
2117// CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
2118// CHECK:         %[[C10:.*]] = llvm.mlir.constant(10 : i64) : i64
2119// CHECK:         %[[C2:.*]] = llvm.mlir.constant(2 : i64) : i64
2120// CHECK:         %[[TYPE_CODE:.*]] = llvm.mlir.constant(9 : i32) : i32
2121// CHECK:         %[[NULL:.*]] = llvm.mlir.zero : !llvm.ptr
2122// CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
2123// CHECK:         %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64
2124// CHECK:         %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2125// CHECK:         %[[BOX1:.*]] = llvm.insertvalue %[[ELEM_LEN_I64]], %[[BOX0]][1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2126// CHECK:         %[[VERSION:.*]] = llvm.mlir.constant(20240719 : i32) : i32
2127// CHECK:         %[[BOX2:.*]] = llvm.insertvalue %[[VERSION]], %[[BOX1]][2] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2128// CHECK:         %[[RANK:.*]] = llvm.mlir.constant(1 : i32) : i32
2129// CHECK:         %[[RANK_I8:.*]] = llvm.trunc %[[RANK]] : i32 to i8
2130// CHECK:         %[[BOX3:.*]] = llvm.insertvalue %[[RANK_I8]], %[[BOX2]][3] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2131// CHECK:         %[[TYPE_CODE_I8:.*]] = llvm.trunc %[[TYPE_CODE]] : i32 to i8
2132// CHECK:         %[[BOX4:.*]] = llvm.insertvalue %[[TYPE_CODE_I8]], %[[BOX3]][4] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2133// CHECK:         %[[ATTR:.*]] = llvm.mlir.constant(0 : i32) : i32
2134// CHECK:         %[[ATTR_I8:.*]] = llvm.trunc %[[ATTR]] : i32 to i8
2135// CHECK:         %[[BOX5:.*]] = llvm.insertvalue %[[ATTR_I8]], %[[BOX4]][5] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2136// CHECK:         %[[F18ADDENDUM:.*]] = llvm.mlir.constant(0 : i32) : i32
2137// CHECK:         %[[F18ADDENDUM_I8:.*]] = llvm.trunc %[[F18ADDENDUM]] : i32 to i8
2138// CHECK:         %[[BOX6:.*]] = llvm.insertvalue %[[F18ADDENDUM_I8]], %[[BOX5]][6] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2139// CHECK:         %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64
2140// CHECK:         %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64
2141// CHECK:         %[[ELE_TYPE:.*]] = llvm.mlir.zero : !llvm.ptr
2142// CHECK:         %[[GEP_DTYPE_SIZE:.*]] = llvm.getelementptr %[[ELE_TYPE]][1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"_QFtest_dt_sliceTt", (i32, i32)>
2143// CHECK:         %[[PTRTOINT_DTYPE_SIZE:.*]] = llvm.ptrtoint %[[GEP_DTYPE_SIZE]] : !llvm.ptr to i64
2144// CHECK:         %[[ADJUSTED_OFFSET:.*]] = llvm.sub %[[C1]], %[[ONE]]  : i64
2145// CHECK:         %[[EXT_SUB:.*]] = llvm.sub %[[C10]], %[[C1]]  : i64
2146// CHECK:         %[[EXT_ADD:.*]] = llvm.add %[[EXT_SUB]], %[[C2]]  : i64
2147// CHECK:         %[[EXT_SDIV:.*]] = llvm.sdiv %[[EXT_ADD]], %[[C2]]  : i64
2148// CHECK:         %[[EXT_ICMP:.*]] = llvm.icmp "sgt" %[[EXT_SDIV]], %[[ZERO]] : i64
2149// CHECK:         %[[EXT_SELECT:.*]] = llvm.select %[[EXT_ICMP]], %[[EXT_SDIV]], %[[ZERO]] : i1, i64
2150// CHECK:         %[[BOX7:.*]] = llvm.insertvalue %[[ONE]], %[[BOX6]][7, 0, 0] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2151// CHECK:         %[[BOX8:.*]] = llvm.insertvalue %[[EXT_SELECT]], %[[BOX7]][7, 0, 1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2152// CHECK:         %[[STRIDE_MUL:.*]] = llvm.mul %[[PTRTOINT_DTYPE_SIZE]], %[[C2]]  : i64
2153// CHECK:         %[[BOX9:.*]] = llvm.insertvalue %[[STRIDE_MUL]], %[[BOX8]][7, 0, 2] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2154// CHECK:         %[[BASE_PTR:.*]] = llvm.getelementptr %[[X]][%[[ZERO]], %[[ADJUSTED_OFFSET]], 0] : (!llvm.ptr, i64, i64) -> !llvm.ptr, !llvm.array<20 x struct<"_QFtest_dt_sliceTt", (i32, i32)>>
2155// CHECK:         %[[BOX10:.*]] = llvm.insertvalue %[[BASE_PTR]], %[[BOX9]][0] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2156// CHECK:         llvm.store %[[BOX10]], %[[ALLOCA]] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>, !llvm.ptr
2157// CHECK:         llvm.call @_QPtest_dt_callee(%[[ALLOCA]]) : (!llvm.ptr) -> ()
2158
2159// Conversion with a subcomponent that indexes a 2d array field in a derived type.
2160
2161func.func @_QPtest_dt_slice2(%arg0: !fir.ref<!fir.array<2x!fir.type<_QPtest_dt_slice2Tt{a:!fir.array<2x3xi32>}>>>) {
2162  %c0 = arith.constant 0 : index
2163  %c1 = arith.constant 1 : index
2164  %c2 = arith.constant 2 : index
2165  %1 = fir.field_index a, !fir.type<_QPtest_dt_slice2Tt{a:!fir.array<2x3xi32>}>
2166  %2 = fircg.ext_embox %arg0(%c2)[%c1, %c2, %c1] path %1, %c0, %c1 : (!fir.ref<!fir.array<2x!fir.type<_QPtest_dt_slice2Tt{a:!fir.array<2x3xi32>}>>>, index, index, index, index, !fir.field, index, index) -> !fir.box<!fir.array<2xi32>>
2167  return
2168}
2169
2170// CHECK-LABEL: llvm.func @_QPtest_dt_slice2(
2171// CHECK-SAME:        %[[ARG0:.*]]: !llvm.ptr) {
2172// CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : index) : i64
2173// CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : index) : i64
2174// CHECK:         %[[C2:.*]] = llvm.mlir.constant(2 : index) : i64
2175// CHECK:         %[[C0_2:.*]] = llvm.mlir.constant(0 : i64) : i64
2176// CHECK:         %{{.*}} = llvm.getelementptr %[[ARG0]][%[[C0_2]], {{.*}}, 0, %[[C1]], %[[C0]]] : (!llvm.ptr, i64, i64, i64, i64) -> !llvm.ptr, !llvm.array<2 x struct<"_QPtest_dt_slice2Tt", (array<3 x array<2 x i32>>)>>
2177// CHECK:         return
2178// CHECK:       }
2179
2180// -----
2181
2182// Test `fircg.ext_array_coor` conversion.
2183
2184// Conversion with only shape and indice.
2185
2186func.func @ext_array_coor0(%arg0: !fir.ref<!fir.array<?xi32>>) {
2187  %c0 = arith.constant 0 : i64
2188  %1 = fircg.ext_array_coor %arg0(%c0) <%c0> : (!fir.ref<!fir.array<?xi32>>, i64, i64) -> !fir.ref<i32>
2189  return
2190}
2191
2192// CHECK-LABEL: llvm.func @ext_array_coor0(
2193// CHECK-SAME:                             %[[ARG0:.*]]: !llvm.ptr)
2194// CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
2195// CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
2196// CHECK:         %[[C0_1:.*]] = llvm.mlir.constant(0 : i64) : i64
2197// CHECK:         %[[IDX:.*]] = llvm.sub %[[C0]], %[[C1]] overflow<nsw> : i64
2198// CHECK:         %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] overflow<nsw> : i64
2199// CHECK:         %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[C1]]  overflow<nsw> : i64
2200// CHECK:         %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]]  overflow<nsw> : i64
2201// CHECK:         %{{.*}} = llvm.getelementptr %[[ARG0]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
2202
2203// Conversion with shift and slice.
2204
2205func.func @ext_array_coor1(%arg0: !fir.ref<!fir.array<?xi32>>) {
2206  %c0 = arith.constant 0 : i64
2207  %1 = fircg.ext_array_coor %arg0(%c0) origin %c0[%c0, %c0, %c0]<%c0> : (!fir.ref<!fir.array<?xi32>>, i64, i64, i64, i64, i64, i64) -> !fir.ref<i32>
2208  return
2209}
2210
2211// CHECK-LABEL: llvm.func @ext_array_coor1(
2212// CHECK-SAME:                             %[[ARG0:.*]]: !llvm.ptr)
2213// CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
2214// CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
2215// CHECK:         %[[C0_1:.*]] = llvm.mlir.constant(0 : i64) : i64
2216// CHECK:         %[[IDX:.*]] = llvm.sub %[[C0]], %[[C0]] overflow<nsw> : i64
2217// CHECK:         %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C0]] overflow<nsw> : i64
2218// CHECK:         %[[ADJ:.*]] = llvm.sub %[[C0]], %[[C0]]  overflow<nsw> : i64
2219// CHECK:         %[[DIFF1:.*]] = llvm.add %[[DIFF0]], %[[ADJ]] overflow<nsw> : i64
2220// CHECK:         %[[STRIDE:.*]] = llvm.mul %[[DIFF1]], %[[C1]] overflow<nsw> : i64
2221// CHECK:         %[[OFFSET:.*]] = llvm.add %[[STRIDE]], %[[C0_1]] overflow<nsw> : i64
2222// CHECK:         %{{.*}} = llvm.getelementptr %[[ARG0]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
2223
2224// Conversion for a dynamic length char.
2225
2226func.func @ext_array_coor2(%arg0: !fir.ref<!fir.array<?x!fir.char<1,?>>>) {
2227  %c0 = arith.constant 0 : i64
2228  %1 = fircg.ext_array_coor %arg0(%c0) <%c0> : (!fir.ref<!fir.array<?x!fir.char<1,?>>>, i64, i64) -> !fir.ref<i32>
2229  return
2230}
2231
2232// CHECK-LABEL: llvm.func @ext_array_coor2(
2233// CHECK-SAME:                             %[[ARG0:.*]]: !llvm.ptr)
2234// CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
2235// CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
2236// CHECK:         %[[C0_1:.*]] = llvm.mlir.constant(0 : i64) : i64
2237// CHECK:         %[[IDX:.*]] = llvm.sub %[[C0]], %[[C1]] overflow<nsw> : i64
2238// CHECK:         %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] overflow<nsw> : i64
2239// CHECK:         %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[C1]]  overflow<nsw> : i64
2240// CHECK:         %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]] overflow<nsw> : i64
2241// CHECK:         %{{.*}} = llvm.getelementptr %[[ARG0]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
2242
2243// Conversion for a `fir.box`.
2244
2245func.func @ext_array_coor3(%arg0: !fir.box<!fir.array<?xi32>>) {
2246  %c0 = arith.constant 0 : i64
2247  %1 = fircg.ext_array_coor %arg0(%c0) <%c0> : (!fir.box<!fir.array<?xi32>>, i64, i64) -> !fir.ref<i32>
2248  return
2249}
2250
2251// CHECK-LABEL: llvm.func @ext_array_coor3(
2252// CHECK-SAME:                             %[[ARG0:.*]]: !llvm.ptr) {
2253// CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
2254// CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
2255// CHECK:         %[[C0_1:.*]] = llvm.mlir.constant(0 : i64) : i64
2256// CHECK:         %[[IDX:.*]] = llvm.sub %[[C0]], %[[C1]] overflow<nsw> : i64
2257// CHECK:         %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] overflow<nsw> : i64
2258// CHECK:         %[[GEPSTRIDE:.*]] = llvm.getelementptr %[[ARG0]][0, 7, 0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2259// CHECK:         %[[LOADEDSTRIDE:.*]] = llvm.load %[[GEPSTRIDE]] : !llvm.ptr -> i64
2260// CHECK:         %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[LOADEDSTRIDE]] overflow<nsw> : i64
2261// CHECK:         %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]] overflow<nsw> : i64
2262// CHECK:         %[[GEPADDR:.*]] = llvm.getelementptr %[[ARG0]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2263// CHECK:         %[[LOADEDADDR:.*]] = llvm.load %[[GEPADDR]] : !llvm.ptr -> !llvm.ptr
2264// CHECK:         %[[GEPADDROFFSET:.*]] = llvm.getelementptr %[[LOADEDADDR]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
2265
2266// Conversion with non zero shift and slice.
2267
2268func.func @ext_array_coor4(%arg0: !fir.ref<!fir.array<100xi32>>) {
2269  %c0 = arith.constant 0 : i64
2270  %c10 = arith.constant 10 : i64
2271  %c20 = arith.constant 20 : i64
2272  %c1 = arith.constant 1 : i64
2273  %1 = fircg.ext_array_coor %arg0(%c0) origin %c0[%c10, %c20, %c1]<%c1> : (!fir.ref<!fir.array<100xi32>>, i64, i64, i64, i64, i64, i64) -> !fir.ref<i32>
2274  return
2275}
2276
2277// CHECK-LABEL: llvm.func @ext_array_coor4(
2278// CHECK:                                  %[[ARG0:.*]]: !llvm.ptr) {
2279// CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
2280// CHECK:         %[[C10:.*]] = llvm.mlir.constant(10 : i64) : i64
2281// CHECK:         %[[C20:.*]] = llvm.mlir.constant(20 : i64) : i64
2282// CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
2283// CHECK:         %[[C1_1:.*]] = llvm.mlir.constant(1 : i64) : i64
2284// CHECK:         %[[C0_1:.*]] = llvm.mlir.constant(0 : i64) : i64
2285// CHECK:         %[[IDX:.*]] = llvm.sub %[[C1]], %[[C0]] overflow<nsw> : i64
2286// CHECK:         %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] overflow<nsw> : i64
2287// CHECK:         %[[ADJ:.*]] = llvm.sub %[[C10]], %[[C0]] overflow<nsw> : i64
2288// CHECK:         %[[DIFF1:.*]] = llvm.add %[[DIFF0]], %[[ADJ]] overflow<nsw> : i64
2289// CHECK:         %[[STRIDE:.*]] = llvm.mul %[[DIFF1]], %[[C1_1]] overflow<nsw> : i64
2290// CHECK:         %[[OFFSET:.*]] = llvm.add %[[STRIDE]], %[[C0_1]] overflow<nsw> : i64
2291// CHECK:         %{{.*}} = llvm.getelementptr %[[ARG0]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
2292
2293// Conversion with index type shape and slice
2294
2295func.func @ext_array_coor5(%arg0: !fir.ref<!fir.array<?xi32>>, %idx1 : index, %idx2 : index, %idx3 : index, %idx4 : index, %idx5 : index) {
2296  %1 = fircg.ext_array_coor %arg0(%idx1)[%idx2, %idx3, %idx4]<%idx5> : (!fir.ref<!fir.array<?xi32>>, index, index, index, index, index) -> !fir.ref<i32>
2297  return
2298}
2299
2300// CHECK-LABEL:   llvm.func @ext_array_coor5(
2301// CHECK-SAME:        %[[VAL_0:.*]]: !llvm.ptr, %[[VAL_1:.*]]: i64, %[[VAL_2:.*]]: i64, %[[VAL_3:.*]]: i64, %[[VAL_4:.*]]: i64, %[[VAL_5:.*]]: i64) {
2302// CHECK:           %[[VAL_6:.*]] = llvm.mlir.constant(1 : i64) : i64
2303// CHECK:           %[[VAL_7:.*]] = llvm.mlir.constant(0 : i64) : i64
2304// CHECK:           %[[VAL_8:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] overflow<nsw> : i64
2305// CHECK:           %[[VAL_9:.*]] = llvm.mul %[[VAL_8]], %[[VAL_4]] overflow<nsw> : i64
2306// CHECK:           %[[VAL_10:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] overflow<nsw> : i64
2307// CHECK:           %[[VAL_11:.*]] = llvm.add %[[VAL_9]], %[[VAL_10]] overflow<nsw> : i64
2308// CHECK:           %[[VAL_12:.*]] = llvm.mul %[[VAL_11]], %[[VAL_6]] overflow<nsw> : i64
2309// CHECK:           %[[VAL_13:.*]] = llvm.add %[[VAL_12]], %[[VAL_7]] overflow<nsw> : i64
2310// CHECK:           %[[VAL_14:.*]] = llvm.mul %[[VAL_6]], %[[VAL_1]] overflow<nsw> : i64
2311// CHECK:           %[[VAL_16:.*]] = llvm.getelementptr %[[VAL_0]][%[[VAL_13]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
2312// CHECK:         }
2313
2314// Conversion for 3-d array
2315
2316func.func @ext_array_coor6(%arg0: !fir.ref<!fir.array<?x?x?xi32>>, %idx1 : index, %idx2 : index, %idx3 : index, %idx4 : index, %idx5 : index) {
2317  %1 = fircg.ext_array_coor %arg0(%idx1, %idx1, %idx1)[%idx2, %idx3, %idx4, %idx2, %idx3, %idx4, %idx2, %idx3, %idx4]<%idx5, %idx5, %idx5> : (!fir.ref<!fir.array<?x?x?xi32>>, index, index, index, index, index, index, index, index, index, index, index, index, index, index, index) -> !fir.ref<i32>
2318  return
2319}
2320
2321// CHECK-LABEL:   llvm.func @ext_array_coor6(
2322// CHECK-SAME:        %[[VAL_0:.*]]: !llvm.ptr, %[[VAL_1:.*]]: i64, %[[VAL_2:.*]]: i64, %[[VAL_3:.*]]: i64, %[[VAL_4:.*]]: i64, %[[VAL_5:.*]]: i64) {
2323// CHECK:           %[[VAL_6:.*]] = llvm.mlir.constant(1 : i64) : i64
2324// CHECK:           %[[VAL_7:.*]] = llvm.mlir.constant(0 : i64) : i64
2325// CHECK:           %[[VAL_8:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] overflow<nsw> : i64
2326// CHECK:           %[[VAL_9:.*]] = llvm.mul %[[VAL_8]], %[[VAL_4]] overflow<nsw> : i64
2327// CHECK:           %[[VAL_10:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] overflow<nsw> : i64
2328// CHECK:           %[[VAL_11:.*]] = llvm.add %[[VAL_9]], %[[VAL_10]] overflow<nsw> : i64
2329// CHECK:           %[[VAL_12:.*]] = llvm.mul %[[VAL_11]], %[[VAL_6]] overflow<nsw> : i64
2330// CHECK:           %[[VAL_13:.*]] = llvm.add %[[VAL_12]], %[[VAL_7]] overflow<nsw> : i64
2331// CHECK:           %[[VAL_14:.*]] = llvm.mul %[[VAL_6]], %[[VAL_1]] overflow<nsw> : i64
2332// CHECK:           %[[VAL_15:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] overflow<nsw> : i64
2333// CHECK:           %[[VAL_16:.*]] = llvm.mul %[[VAL_15]], %[[VAL_4]] overflow<nsw> : i64
2334// CHECK:           %[[VAL_17:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] overflow<nsw> : i64
2335// CHECK:           %[[VAL_18:.*]] = llvm.add %[[VAL_16]], %[[VAL_17]] overflow<nsw> : i64
2336// CHECK:           %[[VAL_19:.*]] = llvm.mul %[[VAL_18]], %[[VAL_14]] overflow<nsw> : i64
2337// CHECK:           %[[VAL_20:.*]] = llvm.add %[[VAL_19]], %[[VAL_13]] overflow<nsw> : i64
2338// CHECK:           %[[VAL_21:.*]] = llvm.mul %[[VAL_14]], %[[VAL_1]] overflow<nsw> : i64
2339// CHECK:           %[[VAL_22:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] overflow<nsw> : i64
2340// CHECK:           %[[VAL_23:.*]] = llvm.mul %[[VAL_22]], %[[VAL_4]] overflow<nsw> : i64
2341// CHECK:           %[[VAL_24:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] overflow<nsw> : i64
2342// CHECK:           %[[VAL_25:.*]] = llvm.add %[[VAL_23]], %[[VAL_24]] overflow<nsw> : i64
2343// CHECK:           %[[VAL_26:.*]] = llvm.mul %[[VAL_25]], %[[VAL_21]] overflow<nsw> : i64
2344// CHECK:           %[[VAL_27:.*]] = llvm.add %[[VAL_26]], %[[VAL_20]] overflow<nsw> : i64
2345// CHECK:           %[[VAL_28:.*]] = llvm.mul %[[VAL_21]], %[[VAL_1]] overflow<nsw> : i64
2346// CHECK:           %[[VAL_30:.*]] = llvm.getelementptr %[[VAL_0]][%[[VAL_27]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
2347// CHECK:           llvm.return
2348// CHECK:         }
2349
2350// Conversion for derived type with type param
2351
2352func.func @ext_array_coor_dt_slice(%arg0: !fir.ref<!fir.array<20x!fir.type<_QFtest_dt_sliceTt{i:i32,j:i32}>>>, %idx1 : index, %idx2 : index, %idx3 : index, %idx4 : index, %idx5 : index) {
2353  %1 = fir.field_index i, !fir.type<_QFtest_dt_sliceTt{i:i32,j:i32}>
2354  %2 = fircg.ext_array_coor %arg0(%idx1)[%idx2, %idx3, %idx4] path %1 <%idx5>: (!fir.ref<!fir.array<20x!fir.type<_QFtest_dt_sliceTt{i:i32,j:i32}>>>, index, index, index, index, !fir.field, index) -> !fir.ref<!fir.type<_QFtest_dt_sliceTt{i:i32,j:i32}>>
2355  return
2356}
2357
2358// CHECK-LABEL:   llvm.func @ext_array_coor_dt_slice(
2359// CHECK-SAME:        %[[VAL_0:.*]]: !llvm.ptr, %[[VAL_1:.*]]: i64, %[[VAL_2:.*]]: i64, %[[VAL_3:.*]]: i64, %[[VAL_4:.*]]: i64, %[[VAL_5:.*]]: i64) {
2360// CHECK:           %[[VAL_6:.*]] = llvm.mlir.constant(0 : i32) : i32
2361// CHECK:           %[[VAL_7:.*]] = llvm.mlir.constant(1 : i64) : i64
2362// CHECK:           %[[VAL_8:.*]] = llvm.mlir.constant(0 : i64) : i64
2363// CHECK:           %[[VAL_9:.*]] = llvm.sub %[[VAL_5]], %[[VAL_7]] overflow<nsw> : i64
2364// CHECK:           %[[VAL_10:.*]] = llvm.mul %[[VAL_9]], %[[VAL_4]] overflow<nsw> : i64
2365// CHECK:           %[[VAL_11:.*]] = llvm.sub %[[VAL_2]], %[[VAL_7]] overflow<nsw> : i64
2366// CHECK:           %[[VAL_12:.*]] = llvm.add %[[VAL_10]], %[[VAL_11]] overflow<nsw> : i64
2367// CHECK:           %[[VAL_13:.*]] = llvm.mul %[[VAL_12]], %[[VAL_7]] overflow<nsw> : i64
2368// CHECK:           %[[VAL_14:.*]] = llvm.add %[[VAL_13]], %[[VAL_8]] overflow<nsw> : i64
2369// CHECK:           %[[VAL_15:.*]] = llvm.mul %[[VAL_7]], %[[VAL_1]] overflow<nsw> : i64
2370// CHECK:           %[[VAL_17:.*]] = llvm.getelementptr %[[VAL_0]][%[[VAL_14]], 0] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<"_QFtest_dt_sliceTt", (i32, i32)>
2371// CHECK:           llvm.return
2372// CHECK:         }
2373
2374// Conversion for derived type with an array field
2375
2376func.func @ext_array_coor_dt_slice2(%arg0: !fir.ref<!fir.array<2x!fir.type<_QFtest_dt_slice2Tt{a:!fir.array<2x3xi32>}>>>, %idx1 : index, %idx2 : index, %idx3 : index, %idx4 : index, %idx5 : index, %idx6 : index, %idx7 : index) {
2377  %1 = fir.field_index a, !fir.type<_QFtest_dt_sliceT2t{a:!fir.array<2x3xi32>}>
2378  %2 = fircg.ext_array_coor %arg0(%idx1)[%idx2, %idx3, %idx4] path %1, %idx5, %idx6 <%idx7> : (!fir.ref<!fir.array<2x!fir.type<_QFtest_dt_slice2Tt{a:!fir.array<2x3xi32>}>>>, index, index, index, index, !fir.field, index, index, index) -> !fir.ref<i32>
2379  return
2380}
2381
2382// CHECK-LABEL:   llvm.func @ext_array_coor_dt_slice2(
2383// CHECK-SAME:        %[[ARG0:.*]]: !llvm.ptr, %[[IDX1:.*]]: i64, %[[IDX2:.*]]: i64, %[[IDX3:.*]]: i64, %[[IDX4:.*]]: i64, %[[IDX5:.*]]: i64, %[[IDX6:.*]]: i64, %[[IDX7:.*]]: i64) {
2384// CHECK:           %{{.*}} = llvm.getelementptr %[[ARG0]][%{{.*}}, 0, %[[IDX6]], %[[IDX5]]] : (!llvm.ptr, i64, i64, i64) -> !llvm.ptr, !llvm.struct<"_QFtest_dt_slice2Tt", (array<3 x array<2 x i32>>)>
2385// CHECK:           llvm.return
2386// CHECK:         }
2387
2388// -----
2389
2390// Check `fircg.ext_rebox` conversion to LLVM IR dialect
2391
2392// Test applying slice on fir.box. Note that the slice is 1D where as the array is 2D.
2393//   subroutine foo(x)
2394//     real :: x(3:, 4:)
2395//     call bar(x(5, 6:80:3))
2396//   end subroutine
2397
2398func.func private @bar1(!fir.box<!fir.array<?xf32>>)
2399func.func @test_rebox_1(%arg0: !fir.box<!fir.array<?x?xf32>>) {
2400  %c2 = arith.constant 2 : index
2401  %c3 = arith.constant 3 : index
2402  %c4 = arith.constant 4 : index
2403  %c5 = arith.constant 5 : index
2404  %c6 = arith.constant 6 : index
2405  %c80 = arith.constant 80 : index
2406  %0 = fir.undefined index
2407  %3 = fircg.ext_rebox %arg0 origin %c3, %c4[%c5, %0, %0, %c6, %c80, %c3] : (!fir.box<!fir.array<?x?xf32>>, index, index, index, index, index, index, index, index) -> !fir.box<!fir.array<?xf32>>
2408  fir.call @bar1(%3) : (!fir.box<!fir.array<?xf32>>) -> ()
2409  return
2410}
2411//CHECK-LABEL:  llvm.func @bar1
2412//CHECK-LABEL:  llvm.func @test_rebox_1
2413//CHECK-SAME:   %[[ARG0:.*]]: !llvm.ptr
2414//CHECK:    %[[ONE_1:.*]] = llvm.mlir.constant(1 : i32) : i32
2415//GENERIC:  %[[RESULT_BOX_REF:.*]] = llvm.alloca %[[ONE_1]] x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr
2416//AMDGPU:   %[[AA:.*]] = llvm.alloca %[[ONE_1]] x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr<5>
2417//AMDGPU:   %[[RESULT_BOX_REF:.*]] = llvm.addrspacecast %[[AA]] : !llvm.ptr<5> to !llvm.ptr
2418//CHECK:    %[[THREE:.*]] = llvm.mlir.constant(3 : index) : i64
2419//CHECK:    %[[FOUR:.*]] = llvm.mlir.constant(4 : index) : i64
2420//CHECK:    %[[FIVE:.*]] = llvm.mlir.constant(5 : index) : i64
2421//CHECK:    %[[SIX:.*]] = llvm.mlir.constant(6 : index) : i64
2422//CHECK:    %[[EIGHTY:.*]] = llvm.mlir.constant(80 : index) : i64
2423//CHECK:    %[[FLOAT_TYPE:.*]] = llvm.mlir.constant(27 : i32) : i32
2424//CHECK:    %[[NULL:.*]] = llvm.mlir.zero : !llvm.ptr
2425//CHECK:    %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
2426//CHECK:    %[[ELEM_SIZE_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64
2427//CHECK:    %[[EXTRA_GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 6] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<2 x array<3 x i64>>)>
2428//CHECK:    %[[EXTRA:.*]] = llvm.load %[[EXTRA_GEP]] : !llvm.ptr -> i8
2429//CHECK:    %[[RBOX:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2430//CHECK:    %[[RBOX_TMP1:.*]] = llvm.insertvalue %[[ELEM_SIZE_I64]], %[[RBOX]][1] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2431//CHECK:    %[[CFI_VERSION:.*]] = llvm.mlir.constant(20240719 : i32) : i32
2432//CHECK:    %[[RBOX_TMP2:.*]] = llvm.insertvalue %[[CFI_VERSION]], %[[RBOX_TMP1]][2] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2433//CHECK:    %[[RANK:.*]] = llvm.mlir.constant(1 : i32) : i32
2434//CHECK:    %[[RANK_I8:.*]] = llvm.trunc %[[RANK]] : i32 to i8
2435//CHECK:    %[[RBOX_TMP3:.*]] = llvm.insertvalue %[[RANK_I8]], %[[RBOX_TMP2]][3] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2436//CHECK:    %[[FLOAT_TYPE_I8:.*]] = llvm.trunc %[[FLOAT_TYPE]] : i32 to i8
2437//CHECK:    %[[RBOX_TMP4:.*]] = llvm.insertvalue %[[FLOAT_TYPE_I8]], %[[RBOX_TMP3]][4] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2438//CHECK:    %[[OTHER_ATTR:.*]] = llvm.mlir.constant(0 : i32) : i32
2439//CHECK:    %[[OTHER_ATTR_I8:.*]] = llvm.trunc %[[OTHER_ATTR]] : i32 to i8
2440//CHECK:    %[[RBOX_TMP5:.*]] = llvm.insertvalue %[[OTHER_ATTR_I8]], %[[RBOX_TMP4]][5] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2441//CHECK:    %[[MASK:.*]] = llvm.mlir.constant(254 : ui8) : i8
2442//CHECK:    %[[EXTRA_WITH_ADDENDUM_CORRECTION:.*]] = llvm.and %[[EXTRA]], %[[MASK]]  : i8
2443//CHECK:    %[[RBOX_TMP6:.*]] = llvm.insertvalue %[[EXTRA_WITH_ADDENDUM_CORRECTION]], %[[RBOX_TMP5]][6] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2444//CHECK:    %[[DIM1_STRIDE_REF:.*]] = llvm.getelementptr %[[ARG0]][0, 7, 0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<2 x array<3 x i64>>)>
2445//CHECK:    %[[DIM1_STRIDE:.*]] = llvm.load %[[DIM1_STRIDE_REF]] : !llvm.ptr -> i64
2446//CHECK:    %[[DIM2_STRIDE_REF:.*]] = llvm.getelementptr %[[ARG0]][0, 7, 1, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<2 x array<3 x i64>>)>
2447//CHECK:    %[[DIM2_STRIDE:.*]] = llvm.load %[[DIM2_STRIDE_REF]] : !llvm.ptr -> i64
2448//CHECK:    %[[SOURCE_ARRAY_PTR:.*]] = llvm.getelementptr %[[ARG0]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<2 x array<3 x i64>>)>
2449//CHECK:    %[[SOURCE_ARRAY:.*]] = llvm.load %[[SOURCE_ARRAY_PTR]] : !llvm.ptr -> !llvm.ptr
2450//CHECK:    %[[ZERO_ELEMS:.*]] = llvm.mlir.constant(0 : i64) : i64
2451//CHECK:    %[[DIM1_LB_DIFF:.*]] = llvm.sub %[[FIVE]], %[[THREE]]  : i64
2452//CHECK:    %[[DIM1_LB_OFFSET:.*]] = llvm.mul %[[DIM1_LB_DIFF]], %[[DIM1_STRIDE]]  : i64
2453//CHECK:    %[[RESULT_PTR_DIM1:.*]] = llvm.getelementptr %[[SOURCE_ARRAY]][%[[DIM1_LB_OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
2454//CHECK:    %[[DIM2_LB_DIFF:.*]] = llvm.sub %[[SIX]], %[[FOUR]]  : i64
2455//CHECK:    %[[DIM2_LB_OFFSET:.*]] = llvm.mul %[[DIM2_LB_DIFF]], %[[DIM2_STRIDE]]  : i64
2456//CHECK:    %[[RESULT_PTR:.*]] = llvm.getelementptr %[[RESULT_PTR_DIM1]][%[[DIM2_LB_OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
2457//CHECK:    %[[RESULT_UB_LB_DIFF:.*]] = llvm.sub %[[EIGHTY]], %[[SIX]]  : i64
2458//CHECK:    %[[RESULT_UB_LB_DIFF_PLUS_STRIDE:.*]] = llvm.add %[[RESULT_UB_LB_DIFF]], %[[THREE]]  : i64
2459//CHECK:    %[[RESULT_NELEMS_TMP:.*]] = llvm.sdiv %[[RESULT_UB_LB_DIFF_PLUS_STRIDE]], %[[THREE]]  : i64
2460//CHECK:    %[[RESULT_IF_NON_ZERO:.*]] = llvm.icmp "sgt" %[[RESULT_NELEMS_TMP]], %[[ZERO_ELEMS]] : i64
2461//CHECK:    %[[RESULT_NELEMS:.*]] = llvm.select %[[RESULT_IF_NON_ZERO]], %[[RESULT_NELEMS_TMP]], %[[ZERO_ELEMS]] : i1, i64
2462//CHECK:    %[[RESULT_STRIDE:.*]] = llvm.mul %[[THREE]], %[[DIM2_STRIDE]]  : i64
2463//CHECK:    %[[RESULT_LB:.*]] = llvm.mlir.constant(1 : i64) : i64
2464//CHECK:    %[[RBOX_TMP7_1:.*]] = llvm.insertvalue %[[RESULT_LB]], %[[RBOX_TMP6]][7, 0, 0] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2465//CHECK:    %[[RBOX_TMP7_2:.*]] = llvm.insertvalue %[[RESULT_NELEMS]], %[[RBOX_TMP7_1]][7, 0, 1] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2466//CHECK:    %[[RBOX_TMP7_3:.*]] = llvm.insertvalue %[[RESULT_STRIDE]], %[[RBOX_TMP7_2]][7, 0, 2] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2467//CHECK:    %[[RESULT_BOX:.*]] = llvm.insertvalue %[[RESULT_PTR]], %[[RBOX_TMP7_3]][0] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2468//CHECK:    llvm.store %[[RESULT_BOX]], %[[RESULT_BOX_REF]] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>, !llvm.ptr
2469//CHECK:    llvm.call @bar1(%[[RESULT_BOX_REF]]) : (!llvm.ptr) -> ()
2470
2471
2472// Test a rebox of an array section like x(3:60:9)%c(2:8) with both a triplet, a component and a substring where x is a fir.box.
2473func.func private @bar(!fir.box<!fir.array<?x!fir.char<1,?>>>)
2474func.func @foo(%arg0: !fir.box<!fir.array<?x!fir.type<t{i:i32,c:!fir.char<1,10>}>>>) {
2475  %c3_i64 = arith.constant 3 : i64
2476  %c60_i64 = arith.constant 60 : i64
2477  %c9_i64 = arith.constant 9 : i64
2478  %c1_i64 = arith.constant 1 : i64
2479  %c7_i64 = arith.constant 7 : i64
2480  %0 = fir.field_index c, !fir.type<t{i:i32,c:!fir.char<1,10>}>
2481  %1 = fircg.ext_rebox %arg0[%c3_i64, %c60_i64, %c9_i64] path %0 substr %c1_i64, %c7_i64 : (!fir.box<!fir.array<?x!fir.type<t{i:i32,c:!fir.char<1,10>}>>>, i64, i64, i64, !fir.field, i64, i64) -> !fir.box<!fir.array<?x!fir.char<1,?>>>
2482  fir.call @bar(%1) : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> ()
2483  return
2484}
2485
2486//CHECK: llvm.func @bar(!llvm.ptr) attributes {sym_visibility = "private"}
2487//CHECK-LABEL: llvm.func @foo
2488//CHECK-SAME: %[[ARG0:.*]]: !llvm.ptr
2489//CHECK:   %[[ONE:.*]] = llvm.mlir.constant(1 : i32) : i32
2490//GENERIC: %[[RESULT_BOX_REF:.*]] = llvm.alloca %[[ONE]] x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr
2491//AMDGPU:  %[[AA:.*]] = llvm.alloca %[[ONE]] x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr<5>
2492//AMDGPU:  %[[RESULT_BOX_REF:.*]] = llvm.addrspacecast %[[AA]] : !llvm.ptr<5> to !llvm.ptr
2493//CHECK:   %[[RESULT_LB:.*]] = llvm.mlir.constant(3 : i64) : i64
2494//CHECK:   %[[RESULT_UB:.*]] = llvm.mlir.constant(60 : i64) : i64
2495//CHECK:   %[[RESULT_STRIDE:.*]] = llvm.mlir.constant(9 : i64) : i64
2496//CHECK:   %[[COMPONENT_OFFSET_1:.*]] = llvm.mlir.constant(1 : i64) : i64
2497//CHECK:   %[[ELEM_COUNT:.*]] = llvm.mlir.constant(7 : i64) : i64
2498//CHECK:   %[[TYPE_CHAR:.*]] = llvm.mlir.constant(40 : i32) : i32
2499//CHECK:   %[[NULL:.*]] = llvm.mlir.zero : !llvm.ptr
2500//CHECK:   %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
2501//CHECK:   %[[CHAR_SIZE:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64
2502//CHECK:   %[[ELEM_SIZE:.*]] = llvm.mul %[[CHAR_SIZE]], %[[ELEM_COUNT]]
2503//CHECK:   %[[EXTRA_GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 6] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>
2504//CHECK:   %[[EXTRA:.*]] = llvm.load %[[EXTRA_GEP]] : !llvm.ptr -> i8
2505//CHECK:   %[[RBOX_TMP1:.*]] = llvm.insertvalue %[[ELEM_SIZE]], %{{.*}}[1] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2506//CHECK:   %[[RBOX_TMP2:.*]] = llvm.insertvalue %{{.*}}, %[[RBOX_TMP1]][2] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2507//CHECK:   %[[RANK:.*]] = llvm.mlir.constant(1 : i32) : i32
2508//CHECK:   %[[RANK_I8:.*]] = llvm.trunc %[[RANK]] : i32 to i8
2509//CHECK:   %[[RBOX_TMP3:.*]] = llvm.insertvalue %[[RANK_I8]], %[[RBOX_TMP2]][3] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2510//CHECK:   %[[TYPE_CHAR_I8:.*]] = llvm.trunc %[[TYPE_CHAR]] : i32 to i8
2511//CHECK:   %[[RBOX_TMP4:.*]] = llvm.insertvalue %[[TYPE_CHAR_I8]], %[[RBOX_TMP3]][4] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2512//CHECK:   %[[RBOX_TMP5:.*]] = llvm.insertvalue %{{.*}}, %[[RBOX_TMP4]][5] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2513//CHECK:   %[[MASK:.*]] = llvm.mlir.constant(254 : ui8) : i8
2514//CHECK:   %[[EXTRA_WITH_ADDENDUM_CORRECTION:.*]] = llvm.and %[[EXTRA]], %[[MASK]]  : i8
2515//CHECK:   %[[RBOX_TMP6:.*]] = llvm.insertvalue %[[EXTRA_WITH_ADDENDUM_CORRECTION]], %[[RBOX_TMP5]][6] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2516//CHECK:   %[[SRC_STRIDE_PTR:.*]] = llvm.getelementptr %[[ARG0]][0, 7, 0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>
2517//CHECK:   %[[SRC_STRIDE:.*]] = llvm.load %[[SRC_STRIDE_PTR]] : !llvm.ptr -> i64
2518//CHECK:   %[[SRC_ARRAY_PTR:.*]] = llvm.getelementptr %[[ARG0]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>
2519//CHECK:   %[[SRC_ARRAY:.*]] = llvm.load %[[SRC_ARRAY_PTR]] : !llvm.ptr -> !llvm.ptr
2520//CHECK:   %[[ZERO_6:.*]] = llvm.mlir.constant(0 : i64) : i64
2521//CHECK:   %[[COMPONENT:.*]] = llvm.getelementptr %[[SRC_ARRAY]][%[[ZERO_6]], 1, %[[COMPONENT_OFFSET_1]]] : (!llvm.ptr, i64, i64) -> !llvm.ptr, !llvm.struct<"t", (i32, array<10 x i8>)>
2522//CHECK:   %[[SRC_LB:.*]] = llvm.mlir.constant(1 : i64) : i64
2523//CHECK:   %[[RESULT_TMP0:.*]] = llvm.sub %[[RESULT_LB]], %[[SRC_LB]]  : i64
2524//CHECK:   %[[RESULT_OFFSET_START:.*]] = llvm.mul %[[RESULT_TMP0]], %[[SRC_STRIDE]]  : i64
2525//CHECK:   %[[RESULT_PTR:.*]] = llvm.getelementptr %[[COMPONENT]][%[[RESULT_OFFSET_START]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
2526//CHECK:   %[[RESULT_TMP1:.*]] = llvm.sub %[[RESULT_UB]], %[[RESULT_LB]]  : i64
2527//CHECK:   %[[RESULT_TMP2:.*]] = llvm.add %[[RESULT_TMP1]], %[[RESULT_STRIDE]]  : i64
2528//CHECK:   %[[RESULT_TMP3:.*]] = llvm.sdiv %[[RESULT_TMP2]], %[[RESULT_STRIDE]]  : i64
2529//CHECK:   %[[RESULT_TMP_PRED:.*]] = llvm.icmp "sgt" %[[RESULT_TMP3]], %[[ZERO_6]] : i64
2530//CHECK:   %[[RESULT_NELEMS:.*]] = llvm.select %[[RESULT_TMP_PRED]], %[[RESULT_TMP3]], %[[ZERO_6]] : i1, i64
2531//CHECK:   %[[RESULT_TOTAL_STRIDE:.*]] = llvm.mul %[[RESULT_STRIDE]], %[[SRC_STRIDE]]  : i64
2532//CHECK:   %[[RESULT_LB:.*]] = llvm.mlir.constant(1 : i64) : i64
2533//CHECK:   %[[RBOX_TMP7_1:.*]] = llvm.insertvalue %[[RESULT_LB]], %[[RBOX_TMP6]][7, 0, 0] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2534//CHECK:   %[[RBOX_TMP7_2:.*]] = llvm.insertvalue %[[RESULT_NELEMS]], %[[RBOX_TMP7_1]][7, 0, 1] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2535//CHECK:   %[[RBOX_TMP7_3:.*]] = llvm.insertvalue %[[RESULT_TOTAL_STRIDE]], %[[RBOX_TMP7_2]][7, 0, 2] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2536//CHECK:   %[[RESULT_BOX:.*]] = llvm.insertvalue %[[RESULT_PTR]], %[[RBOX_TMP7_3]][0] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2537//CHECK:   llvm.store %[[RESULT_BOX]], %[[RESULT_BOX_REF]] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>, !llvm.ptr
2538//CHECK:   llvm.call @bar(%[[RESULT_BOX_REF]]) : (!llvm.ptr) -> ()
2539//CHECK:   llvm.return
2540//CHECK: }
2541
2542// -----
2543
2544// Test `fir.coordinate_of` conversion (items inside `!fir.box`)
2545
2546// 1. COMPLEX TYPE (`fir.complex` is a special case)
2547// Complex type wrapped in `fir.ref`
2548func.func @coordinate_ref_complex(%arg0: !fir.ref<complex<f128>>) {
2549  %arg1 = llvm.mlir.constant(0 : i32) : i32
2550  %p = fir.coordinate_of %arg0, %arg1 : (!fir.ref<complex<f128>>, i32) -> !fir.ref<f32>
2551  return
2552}
2553// CHECK-LABEL: llvm.func @coordinate_ref_complex
2554// CHECK-SAME:  %[[ARG0:.*]]: !llvm.ptr
2555// CHECK:    %{{.*}} = llvm.getelementptr %[[ARG0]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f128, f128)>
2556// CHECK-NEXT:    llvm.return
2557
2558// -----
2559
2560// Complex type wrapped in `fir.box`
2561func.func @coordinate_box_complex(%arg0: !fir.box<complex<f128>>) {
2562  %arg1 = llvm.mlir.constant(0 : i32) : i32
2563  %p = fir.coordinate_of %arg0, %arg1 : (!fir.box<complex<f128>>, i32) -> !fir.ref<f32>
2564  return
2565}
2566// CHECK-LABEL: llvm.func @coordinate_box_complex
2567// CHECK-SAME:  %[[BOX:.*]]: !llvm.ptr
2568// CHECK:    %{{.*}} = llvm.getelementptr %[[BOX]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f128, f128)>
2569// CHECK-NEXT:    llvm.return
2570
2571// -----
2572
2573// Test `fir.coordinate_of` conversion (items inside `!fir.box`)
2574
2575// 2. BOX TYPE (objects wrapped in `fir.box`)
2576// Derived type - basic case (1 index)
2577func.func @coordinate_box_derived_1(%arg0: !fir.box<!fir.type<derived_1{field_1:i32, field_2:i32}>>) {
2578  %idx = fir.field_index field_2, !fir.type<derived_1{field_1:i32, field_2:i32}>
2579  %q = fir.coordinate_of %arg0, %idx : (!fir.box<!fir.type<derived_1{field_1:i32, field_2:i32}>>, !fir.field) -> !fir.ref<i32>
2580  return
2581}
2582// CHECK-LABEL: llvm.func @coordinate_box_derived_1
2583// CHECK-SAME: %[[BOX:.*]]: !llvm.ptr)
2584// CHECK:    %[[COORDINATE:.*]] = llvm.mlir.constant(1 : i32) : i32
2585// CHECK:    %[[DERIVED_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr, array<1 x i64>)>
2586// CHECK:    %[[DERIVED_VAL:.*]] = llvm.load %[[DERIVED_ADDR]] : !llvm.ptr -> !llvm.ptr
2587// CHECK:    %[[SUBOBJECT_ADDR:.*]] = llvm.getelementptr %[[DERIVED_VAL]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"derived_1", (i32, i32)>
2588// CHECK-NEXT:    llvm.return
2589
2590// Derived type - basic case (2 indices)
2591func.func @coordinate_box_derived_2(%arg0: !fir.box<!fir.type<derived_2{field_1:!fir.type<another_derived{inner1:i32, inner2:f32}>, field_2:i32}>>) {
2592  %idx0 = fir.field_index field_1, !fir.type<derived_2{field_1:!fir.type<another_derived{inner1:i32, inner2:f32}>, field_2:i32}>
2593  %idx1 = fir.field_index inner2, !fir.type<another_derived{inner1:i32, inner2:f32}>
2594  %q = fir.coordinate_of %arg0, %idx0, %idx1 : (!fir.box<!fir.type<derived_2{field_1:!fir.type<another_derived{inner1:i32, inner2:f32}>, field_2:i32}>>, !fir.field, !fir.field) -> !fir.ref<i32>
2595  return
2596}
2597
2598// CHECK-LABEL: llvm.func @coordinate_box_derived_2
2599// CHECK-SAME: (%[[BOX:.*]]: !llvm.ptr)
2600// CHECK-NEXT:    %[[C0_0:.*]] = llvm.mlir.constant(0 : i32) : i32
2601// CHECK-NEXT:    %[[C1:.*]] = llvm.mlir.constant(1 : i32) : i32
2602// CHECK:         %[[DERIVED_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}32, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr, array<1 x i64>)>
2603// CHECK-NEXT:    %[[DERIVED_VAL:.*]] = llvm.load %[[DERIVED_ADDR]] : !llvm.ptr -> !llvm.ptr
2604// CHECK-NEXT:    %[[ANOTHER_DERIVED_ADDR:.*]] = llvm.getelementptr %[[DERIVED_VAL]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"derived_2", (struct<"another_derived", (i32, f32)>, i32)>
2605// CHECK-NEXT:    %[[SUBOBJECT_ADDR:.*]] = llvm.getelementptr %[[ANOTHER_DERIVED_ADDR]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"another_derived", (i32, f32)>
2606// CHECK-NEXT:   llvm.return
2607
2608// TODO: Derived type - special case with `fir.len_param_index`
2609
2610// -----
2611
2612// Test `fir.coordinate_of` conversion (items inside `!fir.box`)
2613
2614// 3. BOX TYPE - `fir.array` wrapped in `fir.box`
2615// `fir.array` inside a `fir.box` (1d)
2616func.func @coordinate_box_array_1d(%arg0: !fir.box<!fir.array<10 x f32>>, %arg1: index) {
2617  %p = fir.coordinate_of %arg0, %arg1 : (!fir.box<!fir.array<10 x f32>>, index) -> !fir.ref<f32>
2618  return
2619}
2620// CHECK-LABEL: llvm.func @coordinate_box_array_1d
2621// CHECK-SAME:  %[[BOX:.*]]: !llvm.ptr
2622// CHECK-SAME:  %[[COORDINATE:.*]]: i64
2623// There's only one box here. Its index is `0`. Generate it.
2624// CHECK:       %[[ARRAY_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2625// CHECK-NEXT:  %[[ARRAY_OBJECT:.*]] = llvm.load %[[ARRAY_ADDR]] : !llvm.ptr -> !llvm.ptr
2626// CHECK-NEXT:  %[[OFFSET_INIT:.*]] = llvm.mlir.constant(0 : i64) : i64
2627// Index of the 1st CFI_dim_t object (corresonds the the 1st dimension)
2628// CHECK-NEXT:  %[[DIM_1_MEM_STRIDE_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 7, 0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2629// CHECK-NEXT:  %[[DIM_1_MEM_STRIDE_VAL:.*]] = llvm.load %[[DIM_1_MEM_STRIDE_ADDR]] : !llvm.ptr -> i64
2630// CHECK-NEXT:  %[[BYTE_OFFSET:.*]] = llvm.mul %[[COORDINATE]], %[[DIM_1_MEM_STRIDE_VAL]] overflow<nsw> : i64
2631// CHECK-NEXT:  %[[SUBOJECT_OFFSET:.*]] = llvm.add %[[BYTE_OFFSET]], %[[OFFSET_INIT]] overflow<nsw> : i64
2632// CHECK-NEXT:  %[[SUBOBJECT_ADDR:.*]] = llvm.getelementptr %[[ARRAY_OBJECT]][%[[SUBOJECT_OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
2633// CHECK-NEXT:  llvm.return
2634
2635// `fir.array` inside a `fir.box` (1d) - dynamic size
2636func.func @coordinate_of_box_dynamic_array_1d(%arg0: !fir.box<!fir.array<? x f32>>, %arg1: index) {
2637  %p = fir.coordinate_of %arg0, %arg1 : (!fir.box<!fir.array<? x f32>>, index) -> !fir.ref<f32>
2638  return
2639}
2640// CHECK-LABEL: llvm.func @coordinate_of_box_dynamic_array_1d
2641// CHECK-SAME:  %[[BOX:.*]]: !llvm.ptr
2642// CHECK-SAME:  %[[COORDINATE:.*]]: i64
2643// CHECK-NEXT:  %[[ARRAY_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2644// CHECK-NEXT:  %[[ARRAY_OBJECT:.*]] = llvm.load %[[ARRAY_ADDR]] : !llvm.ptr -> !llvm.ptr
2645// CHECK-NEXT:  %[[OFFSET_INIT:.*]] = llvm.mlir.constant(0 : i64) : i64
2646// Index of the 1st CFI_dim_t object (corresonds the the 1st dimension)
2647// CHECK-NEXT:  %[[DIM_1_MEM_STRIDE_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 7, 0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
2648// CHECK-NEXT:  %[[DIM_1_MEM_STRIDE_VAL:.*]] = llvm.load %[[DIM_1_MEM_STRIDE_ADDR]] : !llvm.ptr -> i64
2649// CHECK-NEXT:  %[[BYTE_OFFSET:.*]] = llvm.mul %[[COORDINATE]], %[[DIM_1_MEM_STRIDE_VAL]] overflow<nsw> : i64
2650// CHECK-NEXT:  %[[SUBOJECT_OFFSET:.*]] = llvm.add %[[BYTE_OFFSET]], %[[OFFSET_INIT]] overflow<nsw> : i64
2651// CHECK-NEXT:  %[[SUBOBJECT_ADDR:.*]] = llvm.getelementptr %[[ARRAY_OBJECT]][%[[SUBOJECT_OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
2652// CHECK-NEXT:  llvm.return
2653
2654// -----
2655
2656// `fir.array` inside a `fir.box` (2d)
2657func.func @coordinate_box_array_2d(%arg0: !fir.box<!fir.array<10 x 10 x f32>>, %arg1: index, %arg2: index) {
2658  %p = fir.coordinate_of %arg0, %arg1, %arg2 : (!fir.box<!fir.array<10 x 10 x f32>>, index, index) -> !fir.ref<f32>
2659  return
2660}
2661// CHECK-LABEL: llvm.func @coordinate_box_array_2d
2662// CHECK-SAME: %[[BOX:.*]]: !llvm.ptr
2663// CHECK-SAME: %[[COORDINATE_1:.*]]: i64, %[[COORDINATE_2:.*]]: i64)
2664// CHECK-NEXT:  %[[ARRAY_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2665// CHECK-NEXT:  %[[ARRAY_OBJECT:.*]] = llvm.load %[[ARRAY_ADDR]] : !llvm.ptr -> !llvm.ptr
2666// CHECK-NEXT:  %[[OFFSET_INIT:.*]] = llvm.mlir.constant(0 : i64) : i64
2667// Index of the 1st CFI_dim_t object (corresonds the the 1st dimension)
2668// CHECK-NEXT:  %[[DIM_1_MEM_STRIDE_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 7, 0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2669// CHECK-NEXT:  %[[DIM_1_MEM_STRIDE_VAL:.*]] = llvm.load %[[DIM_1_MEM_STRIDE_ADDR]] : !llvm.ptr -> i64
2670// CHECK-NEXT:  %[[BYTE_OFFSET_1:.*]] = llvm.mul %[[COORDINATE_1]], %[[DIM_1_MEM_STRIDE_VAL]] overflow<nsw> : i64
2671// CHECK-NEXT:  %[[SUBOBJECT_OFFSET_1:.*]] = llvm.add %[[BYTE_OFFSET]], %[[OFFSET_INIT]] overflow<nsw> : i64
2672// Index of the 1st CFI_dim_t object (corresonds the the 2nd dimension)
2673// CHECK-NEXT:  %[[DIM_2_MEM_STRIDE_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 7, 1, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
2674// CHECK-NEXT:  %[[DIM_2_MEM_STRIDE_VAL:.*]] = llvm.load %[[DIM_2_MEM_STRIDE_ADDR]] : !llvm.ptr -> i64
2675// CHECK-NEXT:  %[[BYTE_OFFSET_2:.*]] = llvm.mul %[[COORDINATE_2]], %[[DIM_2_MEM_STRIDE_VAL]] overflow<nsw> : i64
2676// CHECK-NEXT:  %[[SUBOBJECT_OFFSET_2:.*]] = llvm.add %[[BYTE_OFFSET_2]], %[[SUBOBJECT_OFFSET_1]] overflow<nsw> : i64
2677// CHECK-NEXT:  %[[SUBOBJECT_ADDR:.*]] = llvm.getelementptr %[[ARRAY_OBJECT]][%[[SUBOBJECT_OFFSET_2]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
2678// CHECK-NEXT:  llvm.return
2679
2680// -----
2681
2682// Test `fir.coordinate_of` conversion (items inside `!fir.box`)
2683
2684// 4. BOX TYPE - `fir.derived` inside `fir.array`
2685func.func @coordinate_box_derived_inside_array(%arg0: !fir.box<!fir.array<10 x !fir.type<derived_3{field_1:f32, field_2:f32}>>>, %arg1 : index) {
2686   %idx0 = fir.field_index field_2, !fir.type<derived_3{field_1:f32, field_2:f32}>
2687   %q = fir.coordinate_of %arg0, %arg1, %idx0 : (!fir.box<!fir.array<10 x !fir.type<derived_3{field_1:f32, field_2:f32}>>>, index, !fir.field) -> !fir.ref<f32>
2688   return
2689}
2690// CHECK-LABEL:   llvm.func @coordinate_box_derived_inside_array(
2691// CHECK-SAME:    %[[BOX:.*]]: !llvm.ptr,
2692// CHECK-SAME:    %[[COORDINATE_1:.*]]: i64) {
2693// CHECK:         %[[VAL_6:.*]] = llvm.getelementptr %[[BOX]]{{\[}}0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>
2694// CHECK:         %[[ARRAY:.*]] = llvm.load %[[VAL_6]] : !llvm.ptr -> !llvm.ptr
2695// CHECK:         %[[VAL_8:.*]] = llvm.mlir.constant(0 : i64) : i64
2696// CHECK:         %[[VAL_13:.*]] = llvm.getelementptr %[[BOX]][0, 7, 0, 2] : (!llvm.ptr) -> !llvm.ptr,  !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>
2697// CHECK:         %[[VAL_14:.*]] = llvm.load %[[VAL_13]] : !llvm.ptr -> i64
2698// CHECK:         %[[VAL_15:.*]] = llvm.mul %[[COORDINATE_1]], %[[VAL_14]] overflow<nsw> : i64
2699// CHECK:         %[[OFFSET:.*]] = llvm.add %[[VAL_15]], %[[VAL_8]] overflow<nsw> : i64
2700// CHECK:         %[[DERIVED:.*]] = llvm.getelementptr %[[ARRAY]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
2701// CHECK:         %[[VAL_20:.*]] = llvm.getelementptr %[[DERIVED]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"derived_3", (f32, f32)>
2702// CHECK:         llvm.return
2703
2704// -----
2705
2706// Test `fir.coordinate_of` conversion (items inside `!fir.ref`)
2707
2708// 5.1. `fir.array`
2709func.func @coordinate_array_unknown_size_1d(%arg0: !fir.ref<!fir.array<? x i32>>, %arg1 : index) {
2710   %q = fir.coordinate_of %arg0, %arg1 : (!fir.ref<!fir.array<? x i32>>, index) -> !fir.ref<i32>
2711   return
2712}
2713// CHECK-LABEL:   llvm.func @coordinate_array_unknown_size_1d(
2714// CHECK-SAME:    %[[VAL_0:.*]]: !llvm.ptr,
2715// CHECK-SAME:    %[[VAL_1:.*]]: i64) {
2716// CHECK:           %[[VAL_2:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}%[[VAL_1]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
2717// CHECK:           llvm.return
2718// CHECK:         }
2719
2720// -----
2721
2722func.func @coordinate_array_known_size_1d(%arg0: !fir.ref<!fir.array<10 x i32>>, %arg1 : index) {
2723   %q = fir.coordinate_of %arg0, %arg1 : (!fir.ref<!fir.array<10 x i32>>, index) -> !fir.ref<i32>
2724   return
2725}
2726// CHECK-LABEL:   llvm.func @coordinate_array_known_size_1d(
2727// CHECK-SAME:    %[[VAL_0:.*]]: !llvm.ptr,
2728// CHECK-SAME:    %[[VAL_1:.*]]: i64) {
2729// CHECK:           %[[VAL_3:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}0, %[[VAL_1]]] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.array<10 x i32>
2730// CHECK:           llvm.return
2731// CHECK:         }
2732
2733// -----
2734
2735func.func @coordinate_array_known_size_2d_get_i32(%arg0: !fir.ref<!fir.array<10 x 10 x i32>>, %arg1 : index, %arg2 : index) {
2736   %q = fir.coordinate_of %arg0, %arg1, %arg2 : (!fir.ref<!fir.array<10 x 10 x i32>>, index, index) -> !fir.ref<i32>
2737   return
2738}
2739// CHECK-LABEL:   llvm.func @coordinate_array_known_size_2d_get_i32(
2740// CHECK-SAME:    %[[VAL_0:.*]]: !llvm.ptr,
2741// CHECK-SAME:    %[[VAL_1:.*]]: i64,
2742// CHECK-SAME:    %[[VAL_2:.*]]: i64) {
2743// CHECK:           %[[VAL_4:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}0, %[[VAL_2]], %[[VAL_1]]] : (!llvm.ptr, i64, i64) -> !llvm.ptr, !llvm.array<10 x array<10 x i32>
2744// CHECK:           llvm.return
2745// CHECK:         }
2746
2747// -----
2748
2749func.func @coordinate_array_known_size_2d_get_array(%arg0: !fir.ref<!fir.array<10 x 10 x i32>>, %arg1 : index) {
2750   %q = fir.coordinate_of %arg0, %arg1 : (!fir.ref<!fir.array<10 x 10 x i32>>, index) -> !fir.ref<!fir.array<10 x i32>>
2751   return
2752}
2753// CHECK-LABEL:   llvm.func @coordinate_array_known_size_2d_get_array(
2754// CHECK-SAME:    %[[VAL_0:.*]]: !llvm.ptr,
2755// CHECK-SAME:    %[[VAL_1:.*]]: i64) {
2756// CHECK:           %[[VAL_3:.*]] = llvm.getelementptr %[[VAL_0]][0, %[[VAL_1]]] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.array<10 x array<10 x i32>>
2757// CHECK:           llvm.return
2758// CHECK:         }
2759
2760// -----
2761
2762// 5.2. `fir.derived`
2763func.func @coordinate_ref_derived(%arg0: !fir.ref<!fir.type<dervied_4{field_1:i32, field_2:i32}>>) {
2764  %idx = fir.field_index field_2, !fir.type<dervied_4{field_1:i32, field_2:i32}>
2765  %q = fir.coordinate_of %arg0, %idx : (!fir.ref<!fir.type<dervied_4{field_1:i32, field_2:i32}>>, !fir.field) -> !fir.ref<i32>
2766  return
2767}
2768// CHECK-LABEL:   llvm.func @coordinate_ref_derived(
2769// CHECK-SAME:    %[[VAL_0:.*]]: !llvm.ptr) {
2770// CHECK:           %[[VAL_3:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"dervied_4", (i32, i32)>
2771// CHECK:           llvm.return
2772// CHECK:         }
2773
2774// -----
2775
2776func.func @coordinate_ref_derived_nested(%arg0: !fir.ref<!fir.type<derived_5{field_1:!fir.type<nested_derived{inner1:i32, inner2:f32}>, field_2:i32}>>) {
2777  %idx0 = fir.field_index field_1, !fir.type<derived_5{field_1:!fir.type<nested_derived{inner1:i32, inner2:f32}>, field_2:i32}>
2778  %idx1 = fir.field_index inner2, !fir.type<nested_derived{inner1:i32, inner2:f32}>
2779  %q = fir.coordinate_of %arg0, %idx0, %idx1 : (!fir.ref<!fir.type<derived_5{field_1:!fir.type<nested_derived{inner1:i32, inner2:f32}>, field_2:i32}>>, !fir.field, !fir.field) -> !fir.ref<i32>
2780  return
2781}
2782// CHECK-LABEL:   llvm.func @coordinate_ref_derived_nested(
2783// CHECK-SAME:    %[[VAL_0:.*]]: !llvm.ptr) {
2784// CHECK:           %[[VAL_4:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}0, 0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"derived_5", (struct<"nested_derived", (i32, f32)>, i32)>
2785// CHECK:           llvm.return
2786// CHECK:         }
2787
2788// -----
2789
2790// 5.3 `fir.char`
2791func.func @test_coordinate_of_char(%arr : !fir.ref<!fir.char<10, 2>>) {
2792  %1 = arith.constant 10 : i32
2793  %2 = fir.coordinate_of %arr, %1 : (!fir.ref<!fir.char<10, 2>>, i32) -> !fir.ref<!fir.char<10>>
2794  return
2795}
2796// CHECK-LABEL:   llvm.func @test_coordinate_of_char(
2797// CHECK-SAME:    %[[VAL_0:.*]]: !llvm.ptr) {
2798// CHECK:           %[[VAL_1:.*]] = llvm.mlir.constant(10 : i32) : i32
2799// CHECK:           %[[VAL_2:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}%[[VAL_1]]] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.array<2 x i80>
2800// CHECK:           llvm.return
2801// CHECK:         }
2802
2803// -----
2804
2805// 5.4 `mlir.tuple`
2806func.func @test_coordinate_of_tuple(%tup : !fir.ref<tuple<!fir.ref<i32>>>) {
2807  %1 = arith.constant 0 : i32
2808  %2 = fir.coordinate_of %tup, %1 : (!fir.ref<tuple<!fir.ref<i32>>>, i32) -> !fir.ref<i32>
2809  return
2810}
2811// CHECK-LABEL:   llvm.func @test_coordinate_of_tuple(
2812// CHECK-SAME:                                     %[[VAL_0:.*]]: !llvm.ptr) {
2813// CHECK:           %[[VAL_3:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr)>
2814// CHECK:           llvm.return
2815// CHECK:         }
2816
2817// -----
2818
2819// Test `fir.coordinate_of` conversion - items inside `!fir.ptr`. This should
2820// be almost identical to `!fir.ref` (i.e. it's the same code path in the code
2821// gen). Instead of duplicating the tests, only one for sanity-checking is added.
2822
2823// 6.1. `fir.array`
2824func.func @coordinate_array_unknown_size_1d(%arg0: !fir.ptr<!fir.array<? x i32>>, %arg1 : index) {
2825   %q = fir.coordinate_of %arg0, %arg1 : (!fir.ptr<!fir.array<? x i32>>, index) -> !fir.ref<i32>
2826   return
2827}
2828// CHECK-LABEL:   llvm.func @coordinate_array_unknown_size_1d(
2829// CHECK-SAME:    %[[VAL_0:.*]]: !llvm.ptr,
2830// CHECK-SAME:    %[[VAL_1:.*]]: i64) {
2831// CHECK:           %[[VAL_2:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}%[[VAL_1]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
2832// CHECK:           llvm.return
2833// CHECK:         }
2834
2835// -----
2836
2837fir.global common @c_(dense<0> : vector<4294967296xi8>) : !fir.array<4294967296xi8>
2838
2839// CHECK: llvm.mlir.global common @c_(dense<0> : vector<4294967296xi8>) {addr_space = 0 : i32} : !llvm.array<4294967296 x i8>
2840
2841// -----
2842
2843gpu.module @cuda_device_mod {
2844  gpu.func @test_alloc_and_freemem_one() {
2845    %z0 = fir.allocmem i32
2846    fir.freemem %z0 : !fir.heap<i32>
2847    gpu.return
2848  }
2849}
2850
2851// CHECK: gpu.module @cuda_device_mod {
2852// CHECK: llvm.func @free(!llvm.ptr)
2853// CHECK: llvm.func @malloc(i64) -> !llvm.ptr
2854// CHECK: llvm.call @malloc
2855// CHECK: lvm.call @free
2856