Break circular dependency between FIR dialect and utilities
[llvm-project.git] / flang / test / Fir / convert-to-llvm.fir
blob85b8f666a18f8911f0d37cf803601cb0c56f13bf
1 // RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s | FileCheck %s
2 // RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s
3 // RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=i386-unknown-linux-gnu" %s | FileCheck %s
4 // RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=powerpc64le-unknown-linux-gn" %s | FileCheck %s
6 //=============================================================================
7 // SUMMARY: Tests for FIR --> LLVM MLIR conversion independent of the target
8 //=============================================================================
10 // Test simple global LLVM conversion
12 fir.global @g_i0 : i32 {
13   %1 = arith.constant 0 : i32
14   fir.has_value %1 : i32
17 // CHECK: llvm.mlir.global external @g_i0() {addr_space = 0 : i32} : i32 {
18 // CHECK:   %[[C0:.*]] = llvm.mlir.constant(0 : i32) : i32
19 // CHECK:   llvm.return %[[C0]] : i32
20 // CHECK: }
22 // -----
24 fir.global @g_ci5 constant : i32 {
25   %c = arith.constant 5 : i32
26   fir.has_value %c : i32
29 // CHECK: llvm.mlir.global external constant @g_ci5() {addr_space = 0 : i32} : i32 {
30 // CHECK:   %[[C5:.*]] = llvm.mlir.constant(5 : i32) : i32
31 // CHECK:   llvm.return %[[C5]] : i32
32 // CHECK: }
34 // -----
36 fir.global internal @i_i515 (515:i32) : i32
37 // CHECK: llvm.mlir.global internal @i_i515(515 : i32) {addr_space = 0 : i32} : i32
39 // -----
41 fir.global common @C_i511 (0:i32) : i32
42 // CHECK: llvm.mlir.global common @C_i511(0 : i32) {addr_space = 0 : i32} : i32
44 // -----
46 fir.global weak @w_i86 (86:i32) : i32
47 // CHECK: llvm.mlir.global weak @w_i86(86 : i32) {addr_space = 0 : i32} : i32
49 // -----
51 fir.global linkonce @w_i86 (86:i32) : i32
52 // CHECK: llvm.mlir.global linkonce @w_i86(86 : i32) {addr_space = 0 : i32} : i32
54 // -----
56 // Test conversion of fir.address_of with fir.global
58 func.func @f1() {
59   %0 = fir.address_of(@symbol) : !fir.ref<i64>
60   return
63 fir.global @symbol : i64 {
64   %0 = arith.constant 1 : i64
65   fir.has_value %0 : i64
68 // CHECK: %{{.*}} = llvm.mlir.addressof @[[SYMBOL:.*]] : !llvm.ptr<i64>
70 // CHECK: llvm.mlir.global external @[[SYMBOL]]() {addr_space = 0 : i32} : i64 {
71 // CHECK:   %{{.*}} = llvm.mlir.constant(1 : i64) : i64
72 // CHECK:   llvm.return %{{.*}} : i64
73 // CHECK: }
75 // -----
77 // Test global with insert_on_range operation covering the full array
78 // in initializer region.
80 fir.global internal @_QEmultiarray : !fir.array<32x32xi32> {
81   %c0_i32 = arith.constant 1 : i32
82   %0 = fir.undefined !fir.array<32x32xi32>
83   %2 = fir.insert_on_range %0, %c0_i32 from (0, 0) to (31, 31) : (!fir.array<32x32xi32>, i32) -> !fir.array<32x32xi32>
84   fir.has_value %2 : !fir.array<32x32xi32>
87 // CHECK: llvm.mlir.global internal @_QEmultiarray() {addr_space = 0 : i32} : !llvm.array<32 x array<32 x i32>> {
88 // CHECK:   %[[CST:.*]] = llvm.mlir.constant(dense<1> : vector<32x32xi32>) : !llvm.array<32 x array<32 x i32>>
89 // CHECK:   llvm.return %[[CST]] : !llvm.array<32 x array<32 x i32>>
90 // CHECK: }
92 // -----
94 // Test global with insert_on_range operation not covering the full array
95 // in initializer region.
97 fir.global internal @_QEmultiarray : !fir.array<32xi32> {
98   %c0_i32 = arith.constant 1 : i32
99   %0 = fir.undefined !fir.array<32xi32>
100   %2 = fir.insert_on_range %0, %c0_i32 from (5) to (31) : (!fir.array<32xi32>, i32) -> !fir.array<32xi32>
101   fir.has_value %2 : !fir.array<32xi32>
104 // CHECK:          llvm.mlir.global internal @_QEmultiarray() {addr_space = 0 : i32} : !llvm.array<32 x i32> {
105 // CHECK:            %[[CST:.*]] = llvm.mlir.constant(1 : i32) : i32
106 // CHECK:            %{{.*}} = llvm.mlir.undef : !llvm.array<32 x i32>
107 // CHECK:            %{{.*}} = llvm.insertvalue %[[CST]], %{{.*}}[5] : !llvm.array<32 x i32>
108 // CHECK-COUNT-24:   %{{.*}} = llvm.insertvalue %[[CST]], %{{.*}}[{{.*}}] : !llvm.array<32 x i32>
109 // CHECK:            %{{.*}} = llvm.insertvalue %[[CST]], %{{.*}}[31] : !llvm.array<32 x i32>
110 // CHECK-NOT:        llvm.insertvalue
111 // CHECK:            llvm.return %{{.*}} : !llvm.array<32 x i32>
112 // CHECK:          }
114 // -----
116 // Test global with box
118 fir.global internal @_QFEx : !fir.box<!fir.ptr<i32>> {
119   %0 = fir.zero_bits !fir.ptr<i32>
120   %1 = fir.embox %0 : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>>
121   fir.has_value %1 : !fir.box<!fir.ptr<i32>>
124 // CHECK-LABEL: llvm.mlir.global internal @_QFEx()
125 // CHECK-SAME:  !llvm.struct<([[DES_FIELDS:.*]])>
126 // CHECK:         %[[T0:.*]] = llvm.mlir.undef : !llvm.struct<([[DES_FIELDS]])>
127 // CHECK:         %[[T1:.*]] = llvm.insertvalue %{{.*}}, %[[T0]][1] : !llvm.struct<([[DES_FIELDS]])>
128 // CHECK:         %[[T2:.*]] = llvm.insertvalue %{{.*}}, %[[T1]][2] : !llvm.struct<([[DES_FIELDS]])>
129 // CHECK:         %[[T3:.*]] = llvm.insertvalue %{{.*}}, %[[T2]][3] : !llvm.struct<([[DES_FIELDS]])>
130 // CHECK:         %[[T4:.*]] = llvm.insertvalue %{{.*}}, %[[T3]][4] : !llvm.struct<([[DES_FIELDS]])>
131 // CHECK:         %[[T5:.*]] = llvm.insertvalue %{{.*}}, %[[T4]][5] : !llvm.struct<([[DES_FIELDS]])>
132 // CHECK:         %[[T6:.*]] = llvm.insertvalue %{{.*}}, %[[T5]][6] : !llvm.struct<([[DES_FIELDS]])>
133 // CHECK:         %[[GDES:.*]] = llvm.insertvalue %{{.*}}, %[[T6]][0] : !llvm.struct<([[DES_FIELDS]])>
134 // CHECK:         llvm.return %[[GDES]] : !llvm.struct<([[DES_FIELDS]])>
136 // -----
138 // Test fir.zero_bits operation with LLVM ptr type
140 func.func @zero_test_ptr() {
141   %z = fir.zero_bits !llvm.ptr<f32>
142   return
145 // CHECK: %{{.*}} = llvm.mlir.null : !llvm.ptr<f32>
146 // CHECK-NOT: fir.zero_bits
148 // -----
150 // Test fir.zero_bits operation with integer type.
152 func.func @zero_test_integer() {
153   %z0 = fir.zero_bits i8
154   %z1 = fir.zero_bits i16
155   %z2 = fir.zero_bits i32
156   %z3 = fir.zero_bits i64
157   return
160 // CHECK: %{{.*}} = llvm.mlir.constant(0 : i8) : i8
161 // CHECK: %{{.*}} = llvm.mlir.constant(0 : i16) : i16
162 // CHECK: %{{.*}} = llvm.mlir.constant(0 : i32) : i32
163 // CHECK: %{{.*}} = llvm.mlir.constant(0 : i64) : i64
164 // CHECK-NOT: fir.zero_bits
166 // -----
168 // Test fir.zero_bits operation with floating points types.
170 func.func @zero_test_float() {
171   %z0 = fir.zero_bits f16
172   %z1 = fir.zero_bits bf16
173   %z2 = fir.zero_bits f32
174   %z3 = fir.zero_bits f64
175   %z4 = fir.zero_bits f80
176   %z5 = fir.zero_bits f128
177   return
180 // CHECK: %{{.*}} = llvm.mlir.constant(0.000000e+00 : f16) : f16
181 // CHECK: %{{.*}} = llvm.mlir.constant(0.000000e+00 : bf16) : bf16
182 // CHECK: %{{.*}} = llvm.mlir.constant(0.000000e+00 : f32) : f32
183 // CHECK: %{{.*}} = llvm.mlir.constant(0.000000e+00 : f64) : f64
184 // CHECK: %{{.*}} = llvm.mlir.constant(0.000000e+00 : f80) : f80
185 // CHECK: %{{.*}} = llvm.mlir.constant(0.000000e+00 : f128) : f128
186 // CHECK-NOT: fir.zero_bits
188 // -----
190 // Verify that fir.allocmem is transformed to a call to malloc
191 // and that fir.freemem is transformed to a call to free
192 // Single item case
194 func.func @test_alloc_and_freemem_one() {
195   %z0 = fir.allocmem i32
196   fir.freemem %z0 : !fir.heap<i32>
197   return
200 // CHECK-LABEL:  llvm.func @test_alloc_and_freemem_one() {
201 // CHECK-NEXT:    %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr<i32>
202 // CHECK-NEXT:    %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
203 // CHECK-NEXT:    %[[N:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr<i32> to i64
204 // CHECK-NEXT:    llvm.call @malloc(%[[N]])
205 // CHECK:         llvm.call @free(%{{.*}})
206 // CHECK-NEXT:    llvm.return
208 // -----
209 // Verify that fir.allocmem is transformed to a call to malloc
210 // and that fir.freemem is transformed to a call to free
211 // Several item case
213 func.func @test_alloc_and_freemem_several() {
214   %z0 = fir.allocmem !fir.array<100xf32>
215   fir.freemem %z0 : !fir.heap<!fir.array<100xf32>>
216   return
219 // CHECK-LABEL:  llvm.func @test_alloc_and_freemem_several() {
220 // CHECK: [[NULL:%.*]]  = llvm.mlir.null : !llvm.ptr<array<100 x f32>>
221 // CHECK: [[PTR:%.*]]  = llvm.getelementptr [[NULL]][{{.*}}] : (!llvm.ptr<array<100 x f32>>) -> !llvm.ptr<array<100 x f32>>
222 // CHECK: [[N:%.*]]  = llvm.ptrtoint [[PTR]] : !llvm.ptr<array<100 x f32>> to i64
223 // CHECK: [[MALLOC:%.*]] = llvm.call @malloc([[N]])
224 // CHECK: [[B1:%.*]] = llvm.bitcast [[MALLOC]] : !llvm.ptr<i8> to !llvm.ptr<array<100 x f32>>
225 // CHECK: [[B2:%.*]] = llvm.bitcast [[B1]] : !llvm.ptr<array<100 x f32>> to !llvm.ptr<i8>
226 // CHECK:              llvm.call @free([[B2]])
227 // CHECK:              llvm.return
230 func.func @test_with_shape(%ncols: index, %nrows: index) {
231   %1 = fir.allocmem !fir.array<?x?xf32>, %ncols, %nrows
232   fir.freemem %1 : !fir.heap<!fir.array<?x?xf32>>
233   return
236 // CHECK-LABEL: llvm.func @test_with_shape
237 // CHECK-SAME: %[[NCOLS:.*]]: i64, %[[NROWS:.*]]: i64
238 // CHECK:   %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr<f32>
239 // CHECK:   %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
240 // CHECK:   %[[FOUR:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr<f32> to i64
241 // CHECK:   %[[DIM1_SIZE:.*]] = llvm.mul %[[FOUR]], %[[NCOLS]]  : i64
242 // CHECK:   %[[TOTAL_SIZE:.*]] = llvm.mul %[[DIM1_SIZE]], %[[NROWS]]  : i64
243 // CHECK:   %[[MEM:.*]] = llvm.call @malloc(%[[TOTAL_SIZE]])
244 // CHECK:   %[[B1:.*]] = llvm.bitcast %[[MEM]] : !llvm.ptr<i8> to !llvm.ptr<f32>
245 // CHECK:   %[[B2:.*]] = llvm.bitcast %[[B1]] : !llvm.ptr<f32> to !llvm.ptr<i8>
246 // CHECK:   llvm.call @free(%[[B2]]) : (!llvm.ptr<i8>) -> ()
247 // CHECK:   llvm.return
248 // CHECK: }
250 func.func @test_string_with_shape(%len: index, %nelems: index) {
251   %1 = fir.allocmem !fir.array<?x!fir.char<1,?>>(%len : index), %nelems
252   fir.freemem %1 : !fir.heap<!fir.array<?x!fir.char<1,?>>>
253   return
256 // CHECK-LABEL: llvm.func @test_string_with_shape
257 // CHECK-SAME: %[[LEN:.*]]: i64, %[[NELEMS:.*]]: i64)
258 // CHECK:   %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr<i8>
259 // CHECK:   %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
260 // CHECK:   %[[ONE:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr<i8> to i64
261 // CHECK:   %[[LEN_SIZE:.*]] = llvm.mul %[[ONE]], %[[LEN]]  : i64
262 // CHECK:   %[[TOTAL_SIZE:.*]] = llvm.mul %[[LEN_SIZE]], %[[NELEMS]]  : i64
263 // CHECK:   %[[MEM:.*]] = llvm.call @malloc(%[[TOTAL_SIZE]])
264 // CHECK:   %[[B1:.*]] = llvm.bitcast %[[MEM]] : !llvm.ptr<i8> to !llvm.ptr<i8>
265 // CHECK:   %[[B2:.*]] = llvm.bitcast %[[B1]] : !llvm.ptr<i8> to !llvm.ptr<i8>
266 // CHECK:   llvm.call @free(%[[B2]]) : (!llvm.ptr<i8>) -> ()
267 // CHECK:   llvm.return
268 // CHECK: }
270 // -----
272 // Verify that fir.unreachable is transformed to llvm.unreachable
274 func.func @test_unreachable() {
275   fir.unreachable
278 // CHECK:  llvm.func @test_unreachable() {
279 // CHECK-NEXT:    llvm.unreachable
280 // CHECK-NEXT:  }
282 // -----
284 // Test `fir.select` operation conversion pattern.
285 // Check that the if-then-else ladder is correctly constructed and that we
286 // branch to the correct block.
288 func.func @select(%arg : index, %arg2 : i32) -> i32 {
289   %0 = arith.constant 1 : i32
290   %1 = arith.constant 2 : i32
291   %2 = arith.constant 3 : i32
292   %3 = arith.constant 4 : i32
293   fir.select %arg:index [ 1, ^bb1(%0:i32),
294                           2, ^bb2(%2,%arg,%arg2:i32,index,i32),
295                           3, ^bb3(%arg2,%2:i32,i32),
296                           4, ^bb4(%1:i32),
297                           unit, ^bb5 ]
298   ^bb1(%a : i32) :
299     return %a : i32
300   ^bb2(%b : i32, %b2 : index, %b3:i32) :
301     %castidx = arith.index_cast %b2 : index to i32
302     %4 = arith.addi %b, %castidx : i32
303     %5 = arith.addi %4, %b3 : i32
304     return %5 : i32
305   ^bb3(%c:i32, %c2:i32) :
306     %6 = arith.addi %c, %c2 : i32
307     return %6 : i32
308   ^bb4(%d : i32) :
309     return %d : i32
310   ^bb5 :
311     %zero = arith.constant 0 : i32
312     return %zero : i32
315 // CHECK-LABEL: func @select(
316 // CHECK-SAME:               %[[SELECTVALUE:.*]]: [[IDX:.*]],
317 // CHECK-SAME:               %[[ARG1:.*]]: i32)
318 // CHECK:         %[[C0:.*]] = llvm.mlir.constant(1 : i32) : i32
319 // CHECK:         %[[C1:.*]] = llvm.mlir.constant(2 : i32) : i32
320 // CHECK:         %[[C2:.*]] = llvm.mlir.constant(3 : i32) : i32
321 // CHECK:         %[[SELECTOR:.*]] = llvm.trunc %[[SELECTVALUE]] : i{{.*}} to i32
322 // CHECK:         llvm.switch %[[SELECTOR]] : i32, ^bb5 [
323 // CHECK:           1: ^bb1(%[[C0]] : i32),
324 // CHECK:           2: ^bb2(%[[C2]], %[[SELECTVALUE]], %[[ARG1]] : i32, [[IDX]], i32),
325 // CHECK:           3: ^bb3(%[[ARG1]], %[[C2]] : i32, i32),
326 // CHECK:           4: ^bb4(%[[C1]] : i32)
327 // CHECK:         ]
329 // -----
331 // Test `fir.select_rank` operation conversion pattern.
332 // Check that the if-then-else ladder is correctly constructed and that we
333 // branch to the correct block.
335 func.func @select_rank(%arg : i32, %arg2 : i32) -> i32 {
336   %0 = arith.constant 1 : i32
337   %1 = arith.constant 2 : i32
338   %2 = arith.constant 3 : i32
339   %3 = arith.constant 4 : i32
340   fir.select_rank %arg:i32 [ 1, ^bb1(%0:i32),
341                              2, ^bb2(%2,%arg,%arg2:i32,i32,i32),
342                              3, ^bb3(%arg2,%2:i32,i32),
343                              4, ^bb4(%1:i32),
344                              unit, ^bb5 ]
345   ^bb1(%a : i32) :
346     return %a : i32
347   ^bb2(%b : i32, %b2 : i32, %b3:i32) :
348     %4 = arith.addi %b, %b2 : i32
349     %5 = arith.addi %4, %b3 : i32
350     return %5 : i32
351   ^bb3(%c:i32, %c2:i32) :
352     %6 = arith.addi %c, %c2 : i32
353     return %6 : i32
354   ^bb4(%d : i32) :
355     return %d : i32
356   ^bb5 :
357     %zero = arith.constant 0 : i32
358     return %zero : i32
361 // CHECK-LABEL: func @select_rank(
362 // CHECK-SAME:                    %[[SELECTVALUE:.*]]: i32,
363 // CHECK-SAME:                    %[[ARG1:.*]]: i32)
364 // CHECK:         %[[C0:.*]] = llvm.mlir.constant(1 : i32) : i32
365 // CHECK:         %[[C1:.*]] = llvm.mlir.constant(2 : i32) : i32
366 // CHECK:         %[[C2:.*]] = llvm.mlir.constant(3 : i32) : i32
367 // CHECK:         llvm.switch %[[SELECTVALUE]] : i32, ^bb5 [
368 // CHECK:           1: ^bb1(%[[C0]] : i32),
369 // CHECK:           2: ^bb2(%[[C2]], %[[SELECTVALUE]], %[[ARG1]] : i32, i32, i32),
370 // CHECK:           3: ^bb3(%[[ARG1]], %[[C2]] : i32, i32),
371 // CHECK:           4: ^bb4(%[[C1]] : i32)
372 // CHECK:         ]
374 // -----
376 // Test fir.extract_value operation conversion with derived type.
378 func.func @extract_derived_type() -> f32 {
379   %0 = fir.undefined !fir.type<derived{f:f32}>
380   %1 = fir.extract_value %0, ["f", !fir.type<derived{f:f32}>] : (!fir.type<derived{f:f32}>) -> f32
381   return %1 : f32
384 // CHECK-LABEL: llvm.func @extract_derived_type
385 // CHECK:         %[[STRUCT:.*]] = llvm.mlir.undef : !llvm.struct<"derived", (f32)>
386 // CHECK:         %[[VALUE:.*]] = llvm.extractvalue %[[STRUCT]][0] : !llvm.struct<"derived", (f32)>
387 // CHECK:         llvm.return %[[VALUE]] : f32
389 // -----
391 // Test fir.extract_value operation conversion with a multi-dimensional array
392 // of tuple.
394 func.func @extract_array(%a : !fir.array<10x10xtuple<i32, f32>>) -> f32 {
395   %0 = fir.extract_value %a, [5 : index, 4 : index, 1 : index] : (!fir.array<10x10xtuple<i32, f32>>) -> f32
396   return %0 : f32
399 // CHECK-LABEL: llvm.func @extract_array(
400 // CHECK-SAME:                           %[[ARR:.*]]: !llvm.array<10 x array<10 x struct<(i32, f32)>>>
401 // CHECK:         %[[VALUE:.*]] = llvm.extractvalue %[[ARR]][4, 5, 1] : !llvm.array<10 x array<10 x struct<(i32, f32)>>>
402 // CHECK:         llvm.return %[[VALUE]] : f32
404 // -----
406 // Test fir.insert_value operation conversion with a multi-dimensional array
407 // of tuple.
409 func.func @extract_array(%a : !fir.array<10x10xtuple<i32, f32>>) {
410   %f = arith.constant 2.0 : f32
411   %i = arith.constant 1 : i32
412   %0 = fir.insert_value %a, %i, [5 : index, 4 : index, 0 : index] : (!fir.array<10x10xtuple<i32, f32>>, i32) -> !fir.array<10x10xtuple<i32, f32>>
413   %1 = fir.insert_value %a, %f, [5 : index, 4 : index, 1 : index] : (!fir.array<10x10xtuple<i32, f32>>, f32) -> !fir.array<10x10xtuple<i32, f32>>
414   return
417 // CHECK-LABEL: llvm.func @extract_array(
418 // CHECK-SAME:                           %[[ARR:.*]]: !llvm.array<10 x array<10 x struct<(i32, f32)>>>
419 // CHECK:         %{{.*}} = llvm.insertvalue %{{.*}}, %[[ARR]][4, 5, 0] : !llvm.array<10 x array<10 x struct<(i32, f32)>>>
420 // CHECK:         %{{.*}} = llvm.insertvalue %{{.*}}, %[[ARR]][4, 5, 1] : !llvm.array<10 x array<10 x struct<(i32, f32)>>>
421 // CHECK:         llvm.return
423 // -----
425 // Test fir.insert_value operation conversion with derived type.
427 func.func @insert_tuple(%a : tuple<i32, f32>) {
428   %f = arith.constant 2.0 : f32
429   %1 = fir.insert_value %a, %f, [1 : index] : (tuple<i32, f32>, f32) -> tuple<i32, f32>
430   return
433 // CHECK-LABEL: func @insert_tuple(
434 // CHECK-SAME:                     %[[TUPLE:.*]]: !llvm.struct<(i32, f32)>
435 // CHECK:         %{{.*}} = llvm.insertvalue %{{.*}}, %[[TUPLE]][1] : !llvm.struct<(i32, f32)>
436 // CHECK:         llvm.return
438 // -----
440 // Test `fir.call` -> `llvm.call` conversion for functions that take no arguments
441 // and return nothing
443 func.func @dummy_basic() {
444   return
447 func.func @test_call_basic() {
448   fir.call @dummy_basic() : () -> ()
449   return
452 // CHECK-LABEL: func @test_call_basic() {
453 // CHECK-NEXT:  llvm.call @dummy_basic() : () -> ()
454 // CHECK-NEXT:  return
455 // CHECK-NEXT: }
457 // Test `fir.call` -> `llvm.call` conversion for functions that take one
458 // argument and return nothing
460 func.func @dummy_with_arg(%arg0 : i32) {
461   return
464 func.func @test_call_with_arg(%arg0 : i32) {
465   fir.call @dummy_with_arg(%arg0) : (i32) -> ()
466   return
469 // CHECK-LABEL:  llvm.func @test_call_with_arg(%arg0: i32) {
470 // CHECK-NEXT:    llvm.call @dummy_with_arg(%arg0) : (i32) -> ()
471 // CHECK-NEXT:    llvm.return
472 // CHECK-NEXT:  }
474 // Test `fir.call` -> `llvm.call` conversion for functions that take no
475 // arguments, but return a value
477 func.func @dummy_return_val() -> i32 {
478   %1 = arith.constant 123 : i32
479   return %1 : i32
482 func.func @test_call_return_val() -> i32 {
483   %1 = fir.call @dummy_return_val() : () -> (i32)
484   return %1 : i32
487 // CHECK-LABEL:  llvm.func @test_call_return_val() -> i32 {
488 // CHECK-NEXT:    %0 = llvm.call @dummy_return_val() : () -> i32
489 // CHECK-NEXT:    llvm.return %0 : i32
490 // CHECK-NEXT:  }
492 // -----
494 // Test FIR complex addition conversion
495 // given: (x + iy) + (x' + iy')
496 // result: (x + x') + i(y + y')
498 func.func @fir_complex_add(%a: !fir.complex<16>, %b: !fir.complex<16>) -> !fir.complex<16> {
499   %c = fir.addc %a, %b : !fir.complex<16>
500   return %c : !fir.complex<16>
503 // CHECK-LABEL: llvm.func @fir_complex_add(
504 // CHECK-SAME:                             %[[ARG0:.*]]: !llvm.struct<(f128, f128)>,
505 // CHECK-SAME:                             %[[ARG1:.*]]: !llvm.struct<(f128, f128)>) -> !llvm.struct<(f128, f128)> {
506 // CHECK:         %[[X0:.*]] = llvm.extractvalue %[[ARG0]][0] : !llvm.struct<(f128, f128)>
507 // CHECK:         %[[Y0:.*]] = llvm.extractvalue %[[ARG0]][1] : !llvm.struct<(f128, f128)>
508 // CHECK:         %[[X1:.*]] = llvm.extractvalue %[[ARG1]][0] : !llvm.struct<(f128, f128)>
509 // CHECK:         %[[Y1:.*]] = llvm.extractvalue %[[ARG1]][1] : !llvm.struct<(f128, f128)>
510 // CHECK:         %[[ADD_X0_X1:.*]] = llvm.fadd %[[X0]], %[[X1]]  : f128
511 // CHECK:         %[[ADD_Y0_Y1:.*]] = llvm.fadd %[[Y0]], %[[Y1]]  : f128
512 // CHECK:         %{{.*}} = llvm.mlir.undef : !llvm.struct<(f128, f128)>
513 // CHECK:         %{{.*}} = llvm.insertvalue %[[ADD_X0_X1]], %{{.*}}[0] : !llvm.struct<(f128, f128)>
514 // CHECK:         %{{.*}} = llvm.insertvalue %[[ADD_Y0_Y1]], %{{.*}}[1] : !llvm.struct<(f128, f128)>
515 // CHECK:         llvm.return %{{.*}} : !llvm.struct<(f128, f128)>
517 // -----
519 // Test FIR complex substraction conversion
520 // given: (x + iy) - (x' + iy')
521 // result: (x - x') + i(y - y')
523 func.func @fir_complex_sub(%a: !fir.complex<16>, %b: !fir.complex<16>) -> !fir.complex<16> {
524   %c = fir.subc %a, %b : !fir.complex<16>
525   return %c : !fir.complex<16>
528 // CHECK-LABEL: llvm.func @fir_complex_sub(
529 // CHECK-SAME:                             %[[ARG0:.*]]: !llvm.struct<(f128, f128)>,
530 // CHECK-SAME:                             %[[ARG1:.*]]: !llvm.struct<(f128, f128)>) -> !llvm.struct<(f128, f128)> {
531 // CHECK:         %[[X0:.*]] = llvm.extractvalue %[[ARG0]][0] : !llvm.struct<(f128, f128)>
532 // CHECK:         %[[Y0:.*]] = llvm.extractvalue %[[ARG0]][1] : !llvm.struct<(f128, f128)>
533 // CHECK:         %[[X1:.*]] = llvm.extractvalue %[[ARG1]][0] : !llvm.struct<(f128, f128)>
534 // CHECK:         %[[Y1:.*]] = llvm.extractvalue %[[ARG1]][1] : !llvm.struct<(f128, f128)>
535 // CHECK:         %[[SUB_X0_X1:.*]] = llvm.fsub %[[X0]], %[[X1]]  : f128
536 // CHECK:         %[[SUB_Y0_Y1:.*]] = llvm.fsub %[[Y0]], %[[Y1]]  : f128
537 // CHECK:         %{{.*}} = llvm.mlir.undef : !llvm.struct<(f128, f128)>
538 // CHECK:         %{{.*}} = llvm.insertvalue %[[SUB_X0_X1]], %{{.*}}[0] : !llvm.struct<(f128, f128)>
539 // CHECK:         %{{.*}} = llvm.insertvalue %[[SUB_Y0_Y1]], %{{.*}}[1] : !llvm.struct<(f128, f128)>
540 // CHECK:         llvm.return %{{.*}} : !llvm.struct<(f128, f128)>
542 // -----
544 // Test FIR complex multiply conversion
545 // given: (x + iy) * (x' + iy')
546 // result: (xx'-yy')+i(xy'+yx')
548 func.func @fir_complex_mul(%a: !fir.complex<16>, %b: !fir.complex<16>) -> !fir.complex<16> {
549   %c = fir.mulc %a, %b : !fir.complex<16>
550   return %c : !fir.complex<16>
553 // CHECK-LABEL: llvm.func @fir_complex_mul(
554 // CHECK-SAME:                             %[[ARG0:.*]]: !llvm.struct<(f128, f128)>,
555 // CHECK-SAME:                             %[[ARG1:.*]]: !llvm.struct<(f128, f128)>) -> !llvm.struct<(f128, f128)> {
556 // CHECK:         %[[X0:.*]] = llvm.extractvalue %[[ARG0]][0] : !llvm.struct<(f128, f128)>
557 // CHECK:         %[[Y0:.*]] = llvm.extractvalue %[[ARG0]][1] : !llvm.struct<(f128, f128)>
558 // CHECK:         %[[X1:.*]] = llvm.extractvalue %[[ARG1]][0] : !llvm.struct<(f128, f128)>
559 // CHECK:         %[[Y1:.*]] = llvm.extractvalue %[[ARG1]][1] : !llvm.struct<(f128, f128)>
560 // CHECK:         %[[MUL_X0_X1:.*]] = llvm.fmul %[[X0]], %[[X1]]  : f128
561 // CHECK:         %[[MUL_Y0_X1:.*]] = llvm.fmul %[[Y0]], %[[X1]]  : f128
562 // CHECK:         %[[MUL_X0_Y1:.*]] = llvm.fmul %[[X0]], %[[Y1]]  : f128
563 // CHECK:         %[[ADD:.*]] = llvm.fadd %[[MUL_X0_Y1]], %[[MUL_Y0_X1]]  : f128
564 // CHECK:         %[[MUL_Y0_Y1:.*]] = llvm.fmul %[[Y0]], %[[Y1]]  : f128
565 // CHECK:         %[[SUB:.*]] = llvm.fsub %[[MUL_X0_X1]], %[[MUL_Y0_Y1]]  : f128
566 // CHECK:         %{{.*}} = llvm.mlir.undef : !llvm.struct<(f128, f128)>
567 // CHECK:         %{{.*}} = llvm.insertvalue %[[SUB]], %{{.*}}[0] : !llvm.struct<(f128, f128)>
568 // CHECK:         %{{.*}} = llvm.insertvalue %[[ADD]], %{{.*}}[1] : !llvm.struct<(f128, f128)>
569 // CHECK:         llvm.return %{{.*}} : !llvm.struct<(f128, f128)>
571 // -----
573 // Test FIR complex division conversion
574 // given: (x + iy) / (x' + iy')
575 // result: ((xx'+yy')/d) + i((yx'-xy')/d) where d = x'x' + y'y'
577 func.func @fir_complex_div(%a: !fir.complex<16>, %b: !fir.complex<16>) -> !fir.complex<16> {
578   %c = fir.divc %a, %b : !fir.complex<16>
579   return %c : !fir.complex<16>
582 // CHECK-LABEL: llvm.func @fir_complex_div(
583 // CHECK-SAME:                             %[[ARG0:.*]]: !llvm.struct<(f128, f128)>,
584 // CHECK-SAME:                             %[[ARG1:.*]]: !llvm.struct<(f128, f128)>) -> !llvm.struct<(f128, f128)> {
585 // CHECK:         %[[X0:.*]] = llvm.extractvalue %[[ARG0]][0] : !llvm.struct<(f128, f128)>
586 // CHECK:         %[[Y0:.*]] = llvm.extractvalue %[[ARG0]][1] : !llvm.struct<(f128, f128)>
587 // CHECK:         %[[X1:.*]] = llvm.extractvalue %[[ARG1]][0] : !llvm.struct<(f128, f128)>
588 // CHECK:         %[[Y1:.*]] = llvm.extractvalue %[[ARG1]][1] : !llvm.struct<(f128, f128)>
589 // CHECK:         %[[MUL_X0_X1:.*]] = llvm.fmul %[[X0]], %[[X1]]  : f128
590 // CHECK:         %[[MUL_X1_X1:.*]] = llvm.fmul %[[X1]], %[[X1]]  : f128
591 // CHECK:         %[[MUL_Y0_X1:.*]] = llvm.fmul %[[Y0]], %[[X1]]  : f128
592 // CHECK:         %[[MUL_X0_Y1:.*]] = llvm.fmul %[[X0]], %[[Y1]]  : f128
593 // CHECK:         %[[MUL_Y0_Y1:.*]] = llvm.fmul %[[Y0]], %[[Y1]]  : f128
594 // CHECK:         %[[MUL_Y1_Y1:.*]] = llvm.fmul %[[Y1]], %[[Y1]]  : f128
595 // CHECK:         %[[ADD_X1X1_Y1Y1:.*]] = llvm.fadd %[[MUL_X1_X1]], %[[MUL_Y1_Y1]]  : f128
596 // CHECK:         %[[ADD_X0X1_Y0Y1:.*]] = llvm.fadd %[[MUL_X0_X1]], %[[MUL_Y0_Y1]]  : f128
597 // CHECK:         %[[SUB_Y0X1_X0Y1:.*]] = llvm.fsub %[[MUL_Y0_X1]], %[[MUL_X0_Y1]]  : f128
598 // CHECK:         %[[DIV0:.*]] = llvm.fdiv %[[ADD_X0X1_Y0Y1]], %[[ADD_X1X1_Y1Y1]]  : f128
599 // CHECK:         %[[DIV1:.*]] = llvm.fdiv %[[SUB_Y0X1_X0Y1]], %[[ADD_X1X1_Y1Y1]]  : f128
600 // CHECK:         %{{.*}} = llvm.mlir.undef : !llvm.struct<(f128, f128)>
601 // CHECK:         %{{.*}} = llvm.insertvalue %[[DIV0]], %{{.*}}[0] : !llvm.struct<(f128, f128)>
602 // CHECK:         %{{.*}} = llvm.insertvalue %[[DIV1]], %{{.*}}[1] : !llvm.struct<(f128, f128)>
603 // CHECK:         llvm.return %{{.*}} : !llvm.struct<(f128, f128)>
605 // -----
607 // Test FIR complex negation conversion
608 // given: -(x + iy)
609 // result: -x - iy
611 func.func @fir_complex_neg(%a: !fir.complex<16>) -> !fir.complex<16> {
612   %c = fir.negc %a : !fir.complex<16>
613   return %c : !fir.complex<16>
616 // CHECK-LABEL: llvm.func @fir_complex_neg(
617 // CHECK-SAME:                             %[[ARG0:.*]]: !llvm.struct<(f128, f128)>) -> !llvm.struct<(f128, f128)> {
618 // CHECK:         %[[X:.*]] = llvm.extractvalue %[[ARG0]][0] : !llvm.struct<(f128, f128)>
619 // CHECK:         %[[Y:.*]] = llvm.extractvalue %[[ARG0]][1] : !llvm.struct<(f128, f128)>
620 // CHECK:         %[[NEGX:.*]] = llvm.fneg %[[X]]  : f128
621 // CHECK:         %[[NEGY:.*]] = llvm.fneg %[[Y]]  : f128
622 // CHECK:         %{{.*}} = llvm.insertvalue %[[NEGX]], %{{.*}}[0] : !llvm.struct<(f128, f128)>
623 // CHECK:         %{{.*}} = llvm.insertvalue %[[NEGY]], %{{.*}}[1] : !llvm.struct<(f128, f128)>
624 // CHECK:         llvm.return %{{.*}} : !llvm.struct<(f128, f128)>
626 // -----
628 // Test FIR complex compare conversion
630 func.func @compare_complex_eq(%a : !fir.complex<8>, %b : !fir.complex<8>) -> i1 {
631   %r = fir.cmpc "oeq", %a, %b : !fir.complex<8>
632   return %r : i1
635 // CHECK-LABEL: llvm.func @compare_complex_eq
636 // CHECK-SAME: [[A:%.*]]: !llvm.struct<(f64, f64)>,
637 // CHECK-SAME: [[B:%.*]]: !llvm.struct<(f64, f64)>
638 // CHECK-DAG: [[RA:%.*]] = llvm.extractvalue [[A]][0] : !llvm.struct<(f64, f64)>
639 // CHECK-DAG: [[IA:%.*]] = llvm.extractvalue [[A]][1] : !llvm.struct<(f64, f64)>
640 // CHECK-DAG: [[RB:%.*]] = llvm.extractvalue [[B]][0] : !llvm.struct<(f64, f64)>
641 // CHECK-DAG: [[IB:%.*]] = llvm.extractvalue [[B]][1] : !llvm.struct<(f64, f64)>
642 // CHECK-DAG: [[RESR:%.*]] = llvm.fcmp "oeq" [[RA]], [[RB]] : f64
643 // CHECK-DAG: [[RESI:%.*]] = llvm.fcmp "oeq" [[IA]], [[IB]] : f64
644 // CHECK: [[RES:%.*]] = llvm.and [[RESR]], [[RESI]] : i1
645 // CHECK: return [[RES]] : i1
647 func.func @compare_complex_ne(%a : !fir.complex<8>, %b : !fir.complex<8>) -> i1 {
648   %r = fir.cmpc "une", %a, %b : !fir.complex<8>
649   return %r : i1
652 // CHECK-LABEL: llvm.func @compare_complex_ne
653 // CHECK-SAME: [[A:%.*]]: !llvm.struct<(f64, f64)>,
654 // CHECK-SAME: [[B:%.*]]: !llvm.struct<(f64, f64)>
655 // CHECK-DAG: [[RA:%.*]] = llvm.extractvalue [[A]][0] : !llvm.struct<(f64, f64)>
656 // CHECK-DAG: [[IA:%.*]] = llvm.extractvalue [[A]][1] : !llvm.struct<(f64, f64)>
657 // CHECK-DAG: [[RB:%.*]] = llvm.extractvalue [[B]][0] : !llvm.struct<(f64, f64)>
658 // CHECK-DAG: [[IB:%.*]] = llvm.extractvalue [[B]][1] : !llvm.struct<(f64, f64)>
659 // CHECK-DAG: [[RESR:%.*]] = llvm.fcmp "une" [[RA]], [[RB]] : f64
660 // CHECK-DAG: [[RESI:%.*]] = llvm.fcmp "une" [[IA]], [[IB]] : f64
661 // CHECK: [[RES:%.*]] = llvm.or [[RESR]], [[RESI]] : i1
662 // CHECK: return [[RES]] : i1
664 func.func @compare_complex_other(%a : !fir.complex<8>, %b : !fir.complex<8>) -> i1 {
665   %r = fir.cmpc "ogt", %a, %b : !fir.complex<8>
666   return %r : i1
669 // CHECK-LABEL: llvm.func @compare_complex_other
670 // CHECK-SAME: [[A:%.*]]: !llvm.struct<(f64, f64)>,
671 // CHECK-SAME: [[B:%.*]]: !llvm.struct<(f64, f64)>
672 // CHECK-DAG: [[RA:%.*]] = llvm.extractvalue [[A]][0] : !llvm.struct<(f64, f64)>
673 // CHECK-DAG: [[RB:%.*]] = llvm.extractvalue [[B]][0] : !llvm.struct<(f64, f64)>
674 // CHECK: [[RESR:%.*]] = llvm.fcmp "ogt" [[RA]], [[RB]] : f64
675 // CHECK: return [[RESR]] : i1
677 // -----
679 // Test `fir.convert` operation conversion from Float type.
681 func.func @convert_from_float(%arg0 : f32) {
682   %0 = fir.convert %arg0 : (f32) -> f16
683   %1 = fir.convert %arg0 : (f32) -> f32
684   %2 = fir.convert %arg0 : (f32) -> f64
685   %3 = fir.convert %arg0 : (f32) -> f80
686   %4 = fir.convert %arg0 : (f32) -> f128
687   %5 = fir.convert %arg0 : (f32) -> i1
688   %6 = fir.convert %arg0 : (f32) -> i8
689   %7 = fir.convert %arg0 : (f32) -> i16
690   %8 = fir.convert %arg0 : (f32) -> i32
691   %9 = fir.convert %arg0 : (f32) -> i64
692   return
695 // CHECK-LABEL: convert_from_float(
696 // CHECK-SAME:                     %[[ARG0:.*]]: f32
697 // CHECK:         %{{.*}} = llvm.fptrunc %[[ARG0]] : f32 to f16
698 // CHECK-NOT:     f32 to f32
699 // CHECK:         %{{.*}} = llvm.fpext %[[ARG0]] : f32 to f64
700 // CHECK:         %{{.*}} = llvm.fpext %[[ARG0]] : f32 to f80
701 // CHECK:         %{{.*}} = llvm.fpext %[[ARG0]] : f32 to f128
702 // CHECK:         %{{.*}} = llvm.fptosi %[[ARG0]] : f32 to i1
703 // CHECK:         %{{.*}} = llvm.fptosi %[[ARG0]] : f32 to i8
704 // CHECK:         %{{.*}} = llvm.fptosi %[[ARG0]] : f32 to i16
705 // CHECK:         %{{.*}} = llvm.fptosi %[[ARG0]] : f32 to i32
706 // CHECK:         %{{.*}} = llvm.fptosi %[[ARG0]] : f32 to i64
708 // -----
710 // Test `fir.convert` operation conversion from Integer type.
712 func.func @convert_from_int(%arg0 : i32) {
713   %0 = fir.convert %arg0 : (i32) -> f16
714   %1 = fir.convert %arg0 : (i32) -> f32
715   %2 = fir.convert %arg0 : (i32) -> f64
716   %3 = fir.convert %arg0 : (i32) -> f80
717   %4 = fir.convert %arg0 : (i32) -> f128
718   %5 = fir.convert %arg0 : (i32) -> i1
719   %6 = fir.convert %arg0 : (i32) -> i8
720   %7 = fir.convert %arg0 : (i32) -> i16
721   %8 = fir.convert %arg0 : (i32) -> i32
722   %9 = fir.convert %arg0 : (i32) -> i64
723   %10 = fir.convert %arg0 : (i32) -> i64
724   %ptr = fir.convert %10 : (i64) -> !fir.ref<i64>
725   return
728 // CHECK-LABEL: convert_from_int(
729 // CHECK-SAME:                   %[[ARG0:.*]]: i32
730 // CHECK:         %{{.*}} = llvm.sitofp %[[ARG0]] : i32 to f16
731 // CHECK:         %{{.*}} = llvm.sitofp %[[ARG0]] : i32 to f32
732 // CHECK:         %{{.*}} = llvm.sitofp %[[ARG0]] : i32 to f64
733 // CHECK:         %{{.*}} = llvm.sitofp %[[ARG0]] : i32 to f80
734 // CHECK:         %{{.*}} = llvm.sitofp %[[ARG0]] : i32 to f128
735 // CHECK:         %{{.*}} = llvm.trunc %[[ARG0]] : i32 to i1
736 // CHECK:         %{{.*}} = llvm.trunc %[[ARG0]] : i32 to i8
737 // CHECK:         %{{.*}} = llvm.trunc %[[ARG0]] : i32 to i16
738 // CHECK-NOT:     %{{.*}} = llvm.trunc %[[ARG0]] : i32 to i32
739 // CHECK:         %{{.*}} = llvm.sext %[[ARG0]] : i32 to i64
740 // CHECK:         %{{.*}} = llvm.inttoptr %{{.*}} : i64 to !llvm.ptr<i64>
742 // -----
744 // Test `fir.convert` operation conversion from !fir.ref<> type.
746 func.func @convert_from_ref(%arg0 : !fir.ref<i32>) {
747   %0 = fir.convert %arg0 : (!fir.ref<i32>) -> !fir.ref<i8>
748   %1 = fir.convert %arg0 : (!fir.ref<i32>) -> i32
749   return
752 // CHECK-LABEL: convert_from_ref(
753 // CHECK-SAME:                   %[[ARG0:.*]]: !llvm.ptr<i32>
754 // CHECK:         %{{.*}} = llvm.bitcast %[[ARG0]] : !llvm.ptr<i32> to !llvm.ptr<i8>
755 // CHECK:         %{{.*}} = llvm.ptrtoint %[[ARG0]] : !llvm.ptr<i32> to i32
757 // -----
759 // Test `fir.convert` operation conversion between fir.complex types.
761 func.func @convert_complex4(%arg0 : !fir.complex<4>) -> !fir.complex<8> {
762   %0 = fir.convert %arg0 : (!fir.complex<4>) -> !fir.complex<8>
763   return %0 : !fir.complex<8>
766 // CHECK-LABEL: func @convert_complex4(
767 // CHECK-SAME:                         %[[ARG0:.*]]: !llvm.struct<(f32, f32)>) -> !llvm.struct<(f64, f64)>
768 // CHECK:         %[[X:.*]] = llvm.extractvalue %[[ARG0]][0] : !llvm.struct<(f32, f32)>
769 // CHECK:         %[[Y:.*]] = llvm.extractvalue %[[ARG0]][1] : !llvm.struct<(f32, f32)>
770 // CHECK:         %[[CONVERTX:.*]] = llvm.fpext %[[X]] : f32 to f64
771 // CHECK:         %[[CONVERTY:.*]] = llvm.fpext %[[Y]] : f32 to f64
772 // CHECK:         %[[STRUCT0:.*]] = llvm.mlir.undef : !llvm.struct<(f64, f64)>
773 // CHECK:         %[[STRUCT1:.*]] = llvm.insertvalue %[[CONVERTX]], %[[STRUCT0]][0] : !llvm.struct<(f64, f64)>
774 // CHECK:         %[[STRUCT2:.*]] = llvm.insertvalue %[[CONVERTY]], %[[STRUCT1]][1] : !llvm.struct<(f64, f64)>
775 // CHECK:         llvm.return %[[STRUCT2]] : !llvm.struct<(f64, f64)>
777 // Test `fir.convert` operation conversion between fir.complex types.
779 func.func @convert_complex16(%arg0 : !fir.complex<16>) -> !fir.complex<2> {
780   %0 = fir.convert %arg0 : (!fir.complex<16>) -> !fir.complex<2>
781   return %0 : !fir.complex<2>
784 // CHECK-LABEL: func @convert_complex16(
785 // CHECK-SAME:                          %[[ARG0:.*]]: !llvm.struct<(f128, f128)>) -> !llvm.struct<(f16, f16)>
786 // CHECK:         %[[X:.*]] = llvm.extractvalue %[[ARG0]][0] : !llvm.struct<(f128, f128)>
787 // CHECK:         %[[Y:.*]] = llvm.extractvalue %[[ARG0]][1] : !llvm.struct<(f128, f128)>
788 // CHECK:         %[[CONVERTX:.*]] = llvm.fptrunc %[[X]] : f128 to f16
789 // CHECK:         %[[CONVERTY:.*]] = llvm.fptrunc %[[Y]] : f128 to f16
790 // CHECK:         %[[STRUCT0:.*]] = llvm.mlir.undef : !llvm.struct<(f16, f16)>
791 // CHECK:         %[[STRUCT1:.*]] = llvm.insertvalue %[[CONVERTX]], %[[STRUCT0]][0] : !llvm.struct<(f16, f16)>
792 // CHECK:         %[[STRUCT2:.*]] = llvm.insertvalue %[[CONVERTY]], %[[STRUCT1]][1] : !llvm.struct<(f16, f16)>
793 // CHECK:         llvm.return %[[STRUCT2]] : !llvm.struct<(f16, f16)>
795 // -----
797 // Test constc.
799 func.func @test_constc4() -> !fir.complex<4> {
800   %0 = fir.constc (#fir.real<4, 1.4>, #fir.real<4, 2.3>) : !fir.complex<4>
801   return %0 : !fir.complex<4>
804 // CHECK-LABEL: @test_constc4
805 // CHECK-SAME: () -> !llvm.struct<(f32, f32)>
806 // CHECK-DAG: [[rp:%.*]] = llvm.mlir.constant(1.400000e+00 : f32) : f32
807 // CHECK-DAG: [[ip:%.*]] = llvm.mlir.constant(2.300000e+00 : f32) : f32
808 // CHECK: [[undef:%.*]] = llvm.mlir.undef : !llvm.struct<(f32, f32)>
809 // CHECK: [[withr:%.*]] = llvm.insertvalue [[rp]], [[undef]][0] : !llvm.struct<(f32, f32)>
810 // CHECK: [[full:%.*]] = llvm.insertvalue [[ip]], [[withr]][1] : !llvm.struct<(f32, f32)>
811 // CHECK: return [[full]] : !llvm.struct<(f32, f32)>
813 func.func @test_constc8() -> !fir.complex<8> {
814   %0 = fir.constc (#fir.real<8, 1.8>, #fir.real<8, 2.3>) : !fir.complex<8>
815   return %0 : !fir.complex<8>
818 // CHECK-LABEL: @test_constc8
819 // CHECK-SAME: () -> !llvm.struct<(f64, f64)>
820 // CHECK-DAG: [[rp:%.*]] = llvm.mlir.constant(1.800000e+00 : f64) : f64
821 // CHECK-DAG: [[ip:%.*]] = llvm.mlir.constant(2.300000e+00 : f64) : f64
822 // CHECK: [[undef:%.*]] = llvm.mlir.undef : !llvm.struct<(f64, f64)>
823 // CHECK: [[withr:%.*]] = llvm.insertvalue [[rp]], [[undef]][0] : !llvm.struct<(f64, f64)>
824 // CHECK: [[full:%.*]] = llvm.insertvalue [[ip]], [[withr]][1] : !llvm.struct<(f64, f64)>
825 // CHECK: return [[full]] : !llvm.struct<(f64, f64)>
827 // -----
829 // Test `fir.store` --> `llvm.store` conversion
831 func.func @test_store_index(%val_to_store : index, %addr : !fir.ref<index>) {
832   fir.store %val_to_store to %addr : !fir.ref<index>
833   return
836 // CHECK-LABEL:   llvm.func @test_store_index
837 // CHECK-SAME:    (%[[arg0:.*]]: i64, %[[arg1:.*]]: !llvm.ptr<i64>) {
838 // CHECK-NEXT:    llvm.store %[[arg0]], %[[arg1]] : !llvm.ptr<i64>
839 // CHECK-NEXT:    llvm.return
840 // CHECK-NEXT:  }
842 func.func @test_store_box(%array : !fir.ref<!fir.box<!fir.array<?x?xf32>>>, %box : !fir.box<!fir.array<?x?xf32>>) {
843   fir.store %box to %array : !fir.ref<!fir.box<!fir.array<?x?xf32>>>
844   return
847 // CHECK-LABEL:  llvm.func @test_store_box
848 // CHECK-SAME:  (%[[arg0:.*]]: !llvm.ptr<struct<(ptr<f{{.*}}>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i{{.*}}>>)>>,
849 // CHECK-SAME:  %[[arg1:.*]]: !llvm.ptr<struct<(ptr<f{{.*}}>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i{{.*}}>>)>>) {
850 // CHECK-NEXT:  %[[box_to_store:.*]] = llvm.load %arg1 : !llvm.ptr<struct<(ptr<f{{.*}}>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i{{.*}}>>)>>
851 // CHECK-NEXT:  llvm.store %[[box_to_store]], %[[arg0]] : !llvm.ptr<struct<(ptr<f{{.*}}>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i{{.*}}>>)>>
852 // CHECK-NEXT:  llvm.return
853 // CHECK-NEXT:  }
855 // -----
857 // Test `fir.load` --> `llvm.load` conversion
859 func.func @test_load_index(%addr : !fir.ref<index>) {
860   %0 = fir.load %addr : !fir.ref<index>
861   return
864 // CHECK-LABEL: llvm.func @test_load_index(
865 // CHECK-SAME:  %[[arg1:.*]]: !llvm.ptr<i64>) {
866 // CHECK-NEXT:    %0 = llvm.load %[[arg1]] : !llvm.ptr<i64>
867 // CHECK-NEXT:    llvm.return
868 // CHECK-NEXT:  }
870 func.func private @takes_box(!fir.box<!fir.array<10xf32>>) -> ()
872 func.func @test_load_box(%addr : !fir.ref<!fir.box<!fir.array<10xf32>>>) {
873   %0 = fir.load %addr : !fir.ref<!fir.box<!fir.array<10xf32>>>
874   fir.call @takes_box(%0) : (!fir.box<!fir.array<10xf32>>) -> ()
875   return
878 // Loading a `fir.ref<!fir.box>> is creating a descriptor copy
879 // CHECK-LABEL: llvm.func @test_load_box(
880 // CHECK-SAME:      %[[arg0:.*]]: !llvm.ptr<struct<([[DESC_TYPE:.*]])>>) {
881 // CHECK-NEXT:    %[[c1:.*]] = llvm.mlir.constant(1 : i32) : i32
882 // CHECK-NEXT:    %[[box_copy:.*]] = llvm.alloca %[[c1]] x !llvm.struct<([[DESC_TYPE]])>
883 // CHECK-NEXT:    %[[box_val:.*]] = llvm.load %[[arg0]] : !llvm.ptr<struct<([[DESC_TYPE]])>>
884 // CHECK-NEXT:    llvm.store %[[box_val]], %[[box_copy]] : !llvm.ptr<struct<([[DESC_TYPE]])>>
885 // CHECK-NEXT:    llvm.call @takes_box(%[[box_copy]]) : (!llvm.ptr<struct<([[DESC_TYPE]])>>) -> ()
886 // CHECK-NEXT:    llvm.return
887 // CHECK-NEXT:  }
889 // -----
891 // Test `fir.box_rank` conversion.
893 func.func @extract_rank(%arg0: !fir.box<!fir.array<*:f64>>) -> i32 {
894   %0 = fir.box_rank %arg0 : (!fir.box<!fir.array<*:f64>>) -> i32
895   return %0 : i32
898 // CHECK-LABEL: llvm.func @extract_rank(
899 // CHECK-SAME:                          %[[ARG0:.*]]: !llvm.ptr<struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>) -> i32
900 // CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 3] : (!llvm.ptr<struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>) -> !llvm.ptr<i32>
901 // CHECK:         %[[RANK:.*]] = llvm.load %[[GEP]] : !llvm.ptr<i32>
902 // CHECK:         llvm.return %[[RANK]] : i32
904 // -----
906 // Test `fir.box_addr` conversion.
908 func.func @extract_addr(%arg0: !fir.box<!fir.array<*:f64>>) -> !fir.ref<f64> {
909   %0 = fir.box_addr %arg0 : (!fir.box<!fir.array<*:f64>>) -> !fir.ref<f64>
910   return %0 : !fir.ref<f64>
913 // CHECK-LABEL: llvm.func @extract_addr(
914 // CHECK-SAME:                          %[[ARG0:.*]]: !llvm.ptr<struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>) -> !llvm.ptr<f64>
915 // CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 0] : (!llvm.ptr<struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>) -> !llvm.ptr<ptr<f64>>
916 // CHECK:         %[[ADDR:.*]] = llvm.load %[[GEP]] : !llvm.ptr<ptr<f64>>
917 // CHECK:         llvm.return %[[ADDR]] : !llvm.ptr<f64>
919 // -----
921 // Test `fir.box_dims` conversion.
923 func.func @extract_dims(%arg0: !fir.box<!fir.array<*:f64>>) -> index {
924   %c1 = arith.constant 0 : i32
925   %cast = fir.convert %arg0 : (!fir.box<!fir.array<*:f64>>) -> !fir.box<!fir.array<?xf64>>
926   %0:3 = fir.box_dims %cast, %c1 : (!fir.box<!fir.array<?xf64>>, i32) -> (index, index, index)
927   return %0 : index
930 // CHECK-LABEL: llvm.func @extract_dims(
931 // CHECK-SAME:                          %[[ARG0:.*]]: !llvm.ptr<struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>) -> i64
932 // CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i32) : i32
933 // CHECK:    %[[CAST:.*]] = llvm.bitcast %[[ARG0]] : !llvm.ptr<struct<(ptr<f64>, i64, i32, i8, i8, i8, i8)>> to !llvm.ptr<struct<(ptr<f64>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>>
934 // CHECK:         %[[GEP0:.*]] = llvm.getelementptr %[[CAST]][0, 7, %[[C0]], 0] :  (!llvm.ptr<struct<(ptr<f64>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>>, i32) -> !llvm.ptr<i64>
935 // CHECK:         %[[LOAD0:.*]] = llvm.load %[[GEP0]] : !llvm.ptr<i64>
936 // CHECK:         %[[GEP1:.*]] = llvm.getelementptr %[[CAST]][0, 7, %[[C0]], 1] : (!llvm.ptr<struct<(ptr<f64>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>>, i32) -> !llvm.ptr<i64>
937 // CHECK:         %[[LOAD1:.*]] = llvm.load %[[GEP1]] : !llvm.ptr<i64>
938 // CHECK:         %[[GEP2:.*]] = llvm.getelementptr %[[CAST]][0, 7, %[[C0]], 2] : (!llvm.ptr<struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>, i32) -> !llvm.ptr<i64>
939 // CHECK:         %[[LOAD2:.*]] = llvm.load %[[GEP2]] : !llvm.ptr<i64>
940 // CHECK:         llvm.return %[[LOAD0]] : i64
942 // -----
944 // Test `fir.box_elesize` conversion.
946 func.func @extract_elesize(%arg0: !fir.box<f32>) -> i32 {
947   %0 = fir.box_elesize %arg0 : (!fir.box<f32>) -> i32
948   return %0 : i32
951 // CHECK-LABEL: llvm.func @extract_elesize(
952 // CHECK-SAME:                             %[[ARG0:.*]]: !llvm.ptr<struct<(ptr<f32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>) -> i32
953 // CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 1] : (!llvm.ptr<struct<(ptr<f32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>) -> !llvm.ptr<i32>
954 // CHECK:         %[[ELE_SIZE:.*]] = llvm.load %[[GEP]] : !llvm.ptr<i32>
955 // CHECK:         llvm.return %[[ELE_SIZE]] : i32
957 // -----
959 // Test `fir.box_isarray` conversion.
960 // `rank` is extracted from `fir.box` and compare to 0.
962 func.func @box_isarray(%arg0: !fir.box<!fir.array<*:f64>>) -> i1 {
963   %0 = fir.box_isarray %arg0 : (!fir.box<!fir.array<*:f64>>) -> i1
964   return %0 : i1
967 // CHECK-LABEL: llvm.func @box_isarray(
968 // CHECK-SAME:                         %[[ARG0:.*]]: !llvm.ptr<struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>) -> i1
969 // CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 3] : (!llvm.ptr<struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>) -> !llvm.ptr<i32>
970 // CHECK:         %[[RANK:.*]] = llvm.load %[[GEP]] : !llvm.ptr<i32>
971 // CHECK:         %[[C0_ISARRAY:.*]] = llvm.mlir.constant(0 : i32) : i32
972 // CHECK:         %[[IS_ARRAY:.*]] = llvm.icmp "ne" %[[RANK]], %[[C0_ISARRAY]] : i32
973 // CHECK:         llvm.return %[[IS_ARRAY]] : i1
975 // -----
977 // Test `fir.box_isalloc` conversion.
978 // `attribute` is extracted from `fir.box` and checked against a mask equal to
979 // the value of `CFI_attribute_allocatable`.
981 func.func @box_isalloc(%arg0: !fir.box<!fir.array<*:f64>>) -> i1 {
982   %0 = fir.box_isalloc %arg0 : (!fir.box<!fir.array<*:f64>>) -> i1
983   return %0 : i1
986 // CHECK-LABEL: llvm.func @box_isalloc(
987 // CHECK-SAME:                         %[[ARG0:.*]]: !llvm.ptr<struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>) -> i1
988 // CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 5] : (!llvm.ptr<struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>) -> !llvm.ptr<i32>
989 // CHECK:         %[[ATTR:.*]] = llvm.load %[[GEP]] : !llvm.ptr<i32>
990 // CHECK:         %[[ATTR_ISALLOC:.*]] = llvm.mlir.constant(2 : i32) : i32
991 // CHECK:         %[[AND:.*]] = llvm.and %[[ATTR]], %[[ATTR_ISALLOC]]  : i32
992 // CHECK:         %[[CMP_C0:.*]] = llvm.mlir.constant(0 : i32) : i32
993 // CHECK:         %[[IS_ALLOC:.*]] = llvm.icmp "ne" %[[AND]], %[[CMP_C0]] : i32
994 // CHECK:         llvm.return %[[IS_ALLOC]] : i1
996 // -----
998 // Test `fir.box_isptr` conversion.
999 // `attribute` is extracted from `fir.box` and checked against a mask equal to
1000 // the value of `CFI_attribute_pointer`.
1002 func.func @box_isptr(%arg0: !fir.box<!fir.array<*:f64>>) -> i1 {
1003   %0 = fir.box_isptr %arg0 : (!fir.box<!fir.array<*:f64>>) -> i1
1004   return %0 : i1
1007 // CHECK-LABEL: llvm.func @box_isptr(
1008 // CHECK-SAME:                         %[[ARG0:.*]]: !llvm.ptr<struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>) -> i1
1009 // CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 5] : (!llvm.ptr<struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>) -> !llvm.ptr<i32>
1010 // CHECK:         %[[ATTR:.*]] = llvm.load %[[GEP]] : !llvm.ptr<i32>
1011 // CHECK:         %[[ATTR_ISALLOC:.*]] = llvm.mlir.constant(1 : i32) : i32
1012 // CHECK:         %[[AND:.*]] = llvm.and %[[ATTR]], %[[ATTR_ISALLOC]]  : i32
1013 // CHECK:         %[[CMP_C0:.*]] = llvm.mlir.constant(0 : i32) : i32
1014 // CHECK:         %[[IS_ALLOC:.*]] = llvm.icmp "ne" %[[AND]], %[[CMP_C0]] : i32
1015 // CHECK:         llvm.return %[[IS_ALLOC]] : i1
1017 // -----
1019 // Test fir.alloca of one element
1021 func.func @alloca_one() -> !fir.ref<i32> {
1022   %1 = fir.alloca i32
1023   return %1 : !fir.ref<i32>
1026 // CHECK-LABEL: llvm.func @alloca_one() -> !llvm.ptr<i32>
1027 // CHECK: [[N:%.*]] = llvm.mlir.constant(1 : i64) : i64
1028 // CHECK: [[A:%.*]] = llvm.alloca [[N]] x i32
1029 // CHECK: llvm.return [[A]] : !llvm.ptr<i32>
1031 // -----
1033 // Test fir.alloca of several elements
1035 func.func @alloca_several() -> !fir.ref<i32> {
1036   %0 = arith.constant 100 : index
1037   %1 = fir.alloca i32, %0
1038   return %1 : !fir.ref<i32>
1041 // CHECK-LABEL: llvm.func @alloca_several() -> !llvm.ptr<i32>
1042 // CHECK: [[N:%.*]] = llvm.mlir.constant(100 : index) : i64
1043 // CHECK: [[ONE:%.*]] = llvm.mlir.constant(1 : i64) : i64
1044 // CHECK: [[TOTAL:%.*]] = llvm.mul [[ONE]], [[N]] : i64
1045 // CHECK: [[A:%.*]] = llvm.alloca [[TOTAL]] x i32
1046 // CHECK: llvm.return [[A]] : !llvm.ptr<i32>
1048 // -----
1050 // Test fir.alloca of pointer to array
1052 func.func @alloca_ptr_to_array() -> !fir.ref<!fir.ptr<!fir.array<?xi32>>> {
1053   %1 = fir.alloca !fir.ptr<!fir.array<?xi32>>
1054   return %1 : !fir.ref<!fir.ptr<!fir.array<?xi32>>>
1057 // CHECK-LABEL: llvm.func @alloca_ptr_to_array() -> !llvm.ptr<ptr<i32>>
1058 // CHECK: [[ONE:%.*]] = llvm.mlir.constant(1 : i64) : i64
1059 // CHECK: [[A:%.*]] = llvm.alloca [[ONE]] x !llvm.ptr<i32>
1060 // CHECK: llvm.return [[A]] : !llvm.ptr<ptr<i32>>
1062 // -----
1064 // Test fir.alloca of array of unknown-length chars
1066 func.func @alloca_char_array(%l: i32, %e : index) -> !fir.ref<!fir.array<?x?x!fir.char<1,?>>> {
1067   %a = fir.alloca !fir.array<?x?x!fir.char<1,?>>(%l : i32), %e, %e
1068   return %a :  !fir.ref<!fir.array<?x?x!fir.char<1,?>>>
1071 // CHECK-LABEL: llvm.func @alloca_char_array
1072 // CHECK-SAME: ([[L:%.*]]: i32, [[E:%.*]]: i64) -> !llvm.ptr<i8>
1073 // CHECK-DAG: [[UNUSEDONE:%.*]] = llvm.mlir.constant(1 : i64) : i64
1074 // CHECK-DAG: [[LCAST:%.*]] = llvm.sext [[L]] : i32 to i64
1075 // CHECK: [[PROD1:%.*]] = llvm.mul [[LCAST]], [[E]] : i64
1076 // CHECK: [[PROD2:%.*]] = llvm.mul [[PROD1]], [[E]] : i64
1077 // CHECK: [[A:%.*]] = llvm.alloca [[PROD2]] x i8 {in_type = !fir.array<?x?x!fir.char<1,?>>
1078 // CHECK: return [[A]] : !llvm.ptr<i8>
1080 // -----
1082 // Test fir.alloca of array of known-length chars
1084 func.func @alloca_fixed_char_array(%e : index) -> !fir.ref<!fir.array<?x?x!fir.char<1,8>>> {
1085   %a = fir.alloca !fir.array<?x?x!fir.char<1,8>>, %e, %e
1086   return %a :  !fir.ref<!fir.array<?x?x!fir.char<1,8>>>
1089 // CHECK-LABEL: llvm.func @alloca_fixed_char_array
1090 // CHECK-SAME: ([[E:%.*]]: i64) -> !llvm.ptr<array<8 x i8>>
1091 // CHECK-DAG: [[ONE:%.*]] = llvm.mlir.constant(1 : i64) : i64
1092 // CHECK: [[PROD1:%.*]] = llvm.mul [[ONE]], [[E]] : i64
1093 // CHECK: [[PROD2:%.*]] = llvm.mul [[PROD1]], [[E]] : i64
1094 // CHECK: [[A:%.*]] = llvm.alloca [[PROD2]] x !llvm.array<8 x i8> {in_type = !fir.array<?x?x!fir.char<1,8>>
1095 // CHECK: return [[A]] : !llvm.ptr<array<8 x i8>>
1097 // -----
1099 // Test fir.alloca of record type with LEN parameters
1100 //   type t(p1,p2)
1101 //      integer, len :: p1
1102 //      integer(kind=2), len :: p2
1103 //      integer f1
1104 //      real f2
1105 //   end type t
1107 func.func private @_QTtP.mem.size(%0 : i32, %1 : i16) -> index
1109 func.func @alloca_record(%arg0 : i32, %arg1 : i16) -> !fir.ref<!fir.type<_QTt(p1:i32,p2:i16){f1:i32,f2:f32}>> {
1110   %0 = fir.alloca !fir.type<_QTt(p1:i32,p2:i16){f1:i32,f2:f32}>(%arg0, %arg1 : i32, i16) {name = "_QEvar"}
1111   return %0 : !fir.ref<!fir.type<_QTt(p1:i32,p2:i16){f1:i32,f2:f32}>>
1114 // CHECK-LABEL: llvm.func @alloca_record
1115 // CHECK-SAME: ([[ARG0:%.*]]: i32, [[ARG1:%.*]]: i16)
1116 // CHECK-SAME: -> !llvm.ptr<struct<"_QTt", (i32, f32)>>
1117 // CHECK: [[SIZE:%.*]] = llvm.call @_QTtP.mem.size([[ARG0]], [[ARG1]]) : (i32, i16) -> i64
1118 // CHECK: [[ALLOC:%.*]] = llvm.alloca [[SIZE]] x i8
1119 // CHECK: [[A:%.*]] = llvm.bitcast [[ALLOC]] : !llvm.ptr<i8> to !llvm.ptr<struct<"_QTt", (i32, f32)>>
1120 // CHECK: llvm.return [[A]] : !llvm.ptr<struct<"_QTt", (i32, f32)>>
1122 // -----
1124 // Test fir.alloca of a multidimensional array, with operands
1126 func.func @alloca_multidim_array(%0 : index) -> !fir.ref<!fir.array<8x16x32xf32>> {
1127   %1 = arith.constant 24 : index
1128   %2 = fir.alloca !fir.array<8x16x32xf32>, %0, %1
1129   return %2 : !fir.ref<!fir.array<8x16x32xf32>>
1132 // CHECK-LABEL: llvm.func @alloca_multidim_array
1133 // CHECK-SAME: ([[OP1:%.*]]: i64) -> !llvm.ptr<array<32 x array<16 x array<8 x f32>
1134 // CHECK: [[OP2:%.*]] = llvm.mlir.constant(24 : index) : i64
1135 // CHECK: [[ONE:%.*]] = llvm.mlir.constant(1 : i64) : i64
1136 // CHECK: [[MUL1:%.*]] = llvm.mul [[ONE]], [[OP1]] : i64
1137 // CHECK: [[TOTAL:%.*]] = llvm.mul [[MUL1]], [[OP2]] : i64
1138 // CHECK: [[A:%.*]] = llvm.alloca [[TOTAL]] x !llvm.array<32 x array<16 x array<8 x f32>
1139 // CHECK: llvm.return [[A]] : !llvm.ptr<array<32 x array<16 x array<8 x f32>
1141 // -----
1143 // Test fir.alloca of a multidimensional array with constant interior
1145 func.func @alloca_const_interior_array(%0 : index) -> !fir.ref<!fir.array<8x9x?x?xf32>> {
1146   %1 = arith.constant 64 : index
1147   %2 = fir.alloca !fir.array<8x9x?x?xf32>, %0, %1
1148   return %2 : !fir.ref<!fir.array<8x9x?x?xf32>>
1151 // CHECK-LABEL: llvm.func @alloca_const_interior_array
1152 // CHECK-SAME: ([[OP1:%.*]]: i64) -> !llvm.ptr<array<9 x array<8 x f32>
1153 // CHECK: [[OP2:%.*]] = llvm.mlir.constant(64 : index) : i64
1154 // CHECK: [[ONE:%.*]] = llvm.mlir.constant(1 : i64) : i64
1155 // CHECK: [[MUL1:%.*]] = llvm.mul [[ONE]], [[OP1]] : i64
1156 // CHECK: [[TOTAL:%.*]] = llvm.mul [[MUL1]], [[OP2]] : i64
1157 // CHECK: [[A:%.*]] = llvm.alloca [[TOTAL]] x !llvm.array<9 x array<8 x f32>
1158 // CHECK: llvm.return [[A]] : !llvm.ptr<array<9 x array<8 x f32>
1160 // -----
1162 // Test alloca with an array with holes.
1163 // Constant factor of 60 (4*3*5) must be included.
1165 func.func @alloca_array_with_holes(%0 : index, %1 : index) -> !fir.ref<!fir.array<4x?x3x?x5xi32>> {
1166   %a = fir.alloca !fir.array<4x?x3x?x5xi32>, %0, %1
1167   return %a : !fir.ref<!fir.array<4x?x3x?x5xi32>>
1170 // CHECK-LABEL: llvm.func @alloca_array_with_holes
1171 // CHECK-SAME: ([[A:%.*]]: i64, [[B:%.*]]: i64) -> !llvm.ptr<array<4 x i32>>
1172 // CHECK-DAG: [[ONE:%.*]] = llvm.mlir.constant(1 : i64) : i64
1173 // CHECK-DAG: [[FIXED:%.*]] = llvm.mlir.constant(15 : i64) : i64
1174 // CHECK: [[PROD1:%.*]] = llvm.mul [[ONE]], [[FIXED]] : i64
1175 // CHECK: [[PROD2:%.*]] = llvm.mul [[PROD1]], [[A]] : i64
1176 // CHECK: [[PROD3:%.*]] = llvm.mul [[PROD2]], [[B]] : i64
1177 // CHECK: [[RES:%.*]] = llvm.alloca [[PROD3]] x !llvm.array<4 x i32> {in_type = !fir.array<4x?x3x?x5xi32>
1178 // CHECK: llvm.return [[RES]] : !llvm.ptr<array<4 x i32>>
1180 // -----
1182 // Test `fir.select_case` operation conversion with INTEGER.
1184 func.func @select_case_integer(%arg0: !fir.ref<i32>) -> i32 {
1185   %2 = fir.load %arg0 : !fir.ref<i32>
1186   %c1_i32 = arith.constant 1 : i32
1187   %c2_i32 = arith.constant 2 : i32
1188   %c4_i32 = arith.constant 4 : i32
1189   %c5_i32 = arith.constant 5 : i32
1190   %c7_i32 = arith.constant 7 : i32
1191   %c8_i32 = arith.constant 8 : i32
1192   %c15_i32 = arith.constant 15 : i32
1193   %c21_i32 = arith.constant 21 : i32
1194   fir.select_case %2 : i32 [#fir.upper, %c1_i32, ^bb1,
1195                             #fir.point, %c2_i32, ^bb2,
1196                             #fir.interval, %c4_i32, %c5_i32, ^bb4,
1197                             #fir.point, %c7_i32, ^bb5,
1198                             #fir.interval, %c8_i32, %c15_i32, ^bb5,
1199                             #fir.lower, %c21_i32, ^bb5,
1200                             unit, ^bb3]
1201 ^bb1:  // pred: ^bb0
1202   %c1_i32_0 = arith.constant 1 : i32
1203   fir.store %c1_i32_0 to %arg0 : !fir.ref<i32>
1204   cf.br ^bb6
1205 ^bb2:  // pred: ^bb0
1206   %c2_i32_1 = arith.constant 2 : i32
1207   fir.store %c2_i32_1 to %arg0 : !fir.ref<i32>
1208   cf.br ^bb6
1209 ^bb3:  // pred: ^bb0
1210   %c0_i32 = arith.constant 0 : i32
1211   fir.store %c0_i32 to %arg0 : !fir.ref<i32>
1212   cf.br ^bb6
1213 ^bb4:  // pred: ^bb0
1214   %c4_i32_2 = arith.constant 4 : i32
1215   fir.store %c4_i32_2 to %arg0 : !fir.ref<i32>
1216   cf.br ^bb6
1217 ^bb5:  // 3 preds: ^bb0, ^bb0, ^bb0
1218   %c7_i32_3 = arith.constant 7 : i32
1219   fir.store %c7_i32_3 to %arg0 : !fir.ref<i32>
1220   cf.br ^bb6
1221 ^bb6:  // 5 preds: ^bb1, ^bb2, ^bb3, ^bb4, ^bb5
1222   %3 = fir.load %arg0 : !fir.ref<i32>
1223   return %3 : i32
1226 // CHECK-LABEL: llvm.func @select_case_integer(
1227 // CHECK-SAME:                         %[[ARG0:.*]]: !llvm.ptr<i32>) -> i32 {
1228 // CHECK:         %[[SELECT_VALUE:.*]] = llvm.load %[[ARG0]] : !llvm.ptr<i32>
1229 // CHECK:         %[[CST1:.*]] = llvm.mlir.constant(1 : i32) : i32
1230 // CHECK:         %[[CST2:.*]] = llvm.mlir.constant(2 : i32) : i32
1231 // CHECK:         %[[CST4:.*]] = llvm.mlir.constant(4 : i32) : i32
1232 // CHECK:         %[[CST5:.*]] = llvm.mlir.constant(5 : i32) : i32
1233 // CHECK:         %[[CST7:.*]] = llvm.mlir.constant(7 : i32) : i32
1234 // CHECK:         %[[CST8:.*]] = llvm.mlir.constant(8 : i32) : i32
1235 // CHECK:         %[[CST15:.*]] = llvm.mlir.constant(15 : i32) : i32
1236 // CHECK:         %[[CST21:.*]] = llvm.mlir.constant(21 : i32) : i32
1237 // Check for upper bound `case (:1)`
1238 // CHECK:         %[[CMP_SLE:.*]] = llvm.icmp "sle" %[[SELECT_VALUE]], %[[CST1]] : i32
1239 // CHECK:         llvm.cond_br %[[CMP_SLE]], ^bb2, ^bb1
1240 // CHECK-LABEL: ^bb1:
1241 // Check for point value `case (2)`
1242 // CHECK:         %[[CMP_EQ:.*]] = llvm.icmp "eq" %[[SELECT_VALUE]], %[[CST2]] : i32
1243 // CHECK:         llvm.cond_br %[[CMP_EQ]], ^bb4, ^bb3
1244 // Block ^bb1 in original FIR code.
1245 // CHECK-LABEL: ^bb2:
1246 // CHECK:         llvm.br ^bb{{.*}}
1247 // CHECK-LABEL: ^bb3:
1248 // Check for the lower bound for the interval `case (4:5)`
1249 // CHECK:        %[[CMP_SLE:.*]] = llvm.icmp "sle" %[[CST4]], %[[SELECT_VALUE]] : i32
1250 // CHECK:        llvm.cond_br %[[CMP_SLE]], ^bb[[UPPERBOUND5:.*]], ^bb7
1251 // Block ^bb2 in original FIR code.
1252 // CHECK-LABEL: ^bb4:
1253 // CHECK:        llvm.br ^bb{{.*}}
1254 // Block ^bb3 in original FIR code.
1255 // CHECK-LABEL: ^bb5:
1256 // CHECK:        llvm.br ^bb{{.*}}
1257 // CHECK:       ^bb[[UPPERBOUND5]]:
1258 // Check for the upper bound for the interval `case (4:5)`
1259 // CHECK:        %[[CMP_SLE:.*]] = llvm.icmp "sle" %[[SELECT_VALUE]], %[[CST5]] : i32
1260 // CHECK:        llvm.cond_br %[[CMP_SLE]], ^bb8, ^bb7
1261 // CHECK-LABEL: ^bb7:
1262 // Check for the point value 7 in `case (7,8:15,21:)`
1263 // CHECK: %[[CMP_EQ:.*]] = llvm.icmp "eq" %[[SELECT_VALUE]], %[[CST7]] : i32
1264 // CHECK: llvm.cond_br %[[CMP_EQ]], ^bb13, ^bb9
1265 // Block ^bb4 in original FIR code.
1266 // CHECK-LABEL: ^bb8:
1267 // CHECK:        llvm.br ^bb{{.*}}
1268 // CHECK-LABEL: ^bb9:
1269 // Check for lower bound 8 in `case (7,8:15,21:)`
1270 // CHECK:        %[[CMP_SLE:.*]] = llvm.icmp "sle" %[[CST8]], %[[SELECT_VALUE]] : i32
1271 // CHECK:        llvm.cond_br %[[CMP_SLE]], ^bb[[INTERVAL8_15:.*]], ^bb11
1272 // CHECK:       ^bb[[INTERVAL8_15]]:
1273 // Check for upper bound 15 in `case (7,8:15,21:)`
1274 // CHECK:        %[[CMP_SLE:.*]] = llvm.icmp "sle" %[[SELECT_VALUE]], %[[CST15]] : i32
1275 // CHECK:        llvm.cond_br %[[CMP_SLE]], ^bb13, ^bb11
1276 // CHECK-LABEL: ^bb11:
1277 // Check for lower bound 21 in `case (7,8:15,21:)`
1278 // CHECK:        %[[CMP_SLE:.*]]  = llvm.icmp "sle" %[[CST21]], %[[SELECT_VALUE]] : i32
1279 // CHECK:        llvm.cond_br %[[CMP_SLE]], ^bb13, ^bb12
1280 // CHECK-LABEL: ^bb12:
1281 // CHECK:         llvm.br ^bb5
1282 // Block ^bb5 in original FIR code.
1283 // CHECK-LABEL: ^bb13:
1284 // CHECK:        llvm.br ^bb14
1285 // Block ^bb6 in original FIR code.
1286 // CHECK-LABEL: ^bb14:
1287 // CHECK:        %[[RET:.*]] = llvm.load %[[ARG0:.*]] : !llvm.ptr<i32>
1288 // CHECK:        llvm.return %[[RET]] : i32
1290 // -----
1292 // Test `fir.select_case` operation conversion with LOGICAL.
1294 func.func @select_case_logical(%arg0: !fir.ref<!fir.logical<4>>) {
1295   %1 = fir.load %arg0 : !fir.ref<!fir.logical<4>>
1296   %2 = fir.convert %1 : (!fir.logical<4>) -> i1
1297   %false = arith.constant false
1298   %true = arith.constant true
1299   fir.select_case %2 : i1 [#fir.point, %false, ^bb1,
1300                            #fir.point, %true, ^bb2,
1301                             unit, ^bb3]
1302 ^bb1:
1303   %c1_i32 = arith.constant 1 : i32
1304   cf.br ^bb3
1305 ^bb2:
1306   %c2_i32 = arith.constant 2 : i32
1307   cf.br ^bb3
1308 ^bb3:
1309   return
1312 // CHECK-LABEL: llvm.func @select_case_logical(
1313 // CHECK-SAME:                                 %[[ARG0:.*]]: !llvm.ptr<i32>
1314 // CHECK:         %[[LOAD_ARG0:.*]] = llvm.load %[[ARG0]] : !llvm.ptr<i32>
1315 // CHECK:         %[[CST_ZERO:.*]] = llvm.mlir.constant(0 : i64) : i32
1316 // CHECK:         %[[SELECT_VALUE:.*]] = llvm.icmp "ne" %[[LOAD_ARG0]], %[[CST_ZERO]] : i32
1317 // CHECK:         %[[CST_FALSE:.*]] = llvm.mlir.constant(false) : i1
1318 // CHECK:         %[[CST_TRUE:.*]] = llvm.mlir.constant(true) : i1
1319 // CHECK:         %[[CMPEQ:.*]] = llvm.icmp "eq" %[[SELECT_VALUE]], %[[CST_FALSE]] : i1
1320 // CHECK:         llvm.cond_br %[[CMPEQ]], ^bb2, ^bb1
1321 // CHECK-LABEL: ^bb1:
1322 // CHECK:         %[[CMPEQ:.*]] = llvm.icmp "eq" %[[SELECT_VALUE]], %[[CST_TRUE]] : i1
1323 // CHECK:         llvm.cond_br %[[CMPEQ]], ^bb4, ^bb3
1324 // CHECK-LABEL: ^bb2:
1325 // CHECK:         llvm.br ^bb5
1326 // CHECK-LABEL: ^bb3:
1327 // CHECK:         llvm.br ^bb5
1328 // CHECK-LABEL: ^bb4:
1329 // CHECK:         llvm.br ^bb5
1330 // CHECK-LABEL: ^bb5:
1331 // CHECK:        llvm.return
1333 // -----
1335 // Test `fir.is_present`
1337 func.func @test_is_present_i64(%arg0: !fir.ref<i64>) -> () {
1338   %0 = fir.is_present %arg0 : (!fir.ref<i64>) -> i1
1339   return
1342 // CHECK-LABEL: @test_is_present_i64
1343 // CHECK-SAME: (%[[arg:.*]]: !llvm.ptr<i64>)
1344 // CHECK-NEXT:  %[[constant:.*]] = llvm.mlir.constant(0 : i64) : i64
1345 // CHECK-NEXT:  %[[ptr:.*]] = llvm.ptrtoint %[[arg]] : !llvm.ptr<i64> to i64
1346 // CHECK-NEXT:  %{{.*}} = llvm.icmp "ne" %[[ptr]], %[[constant]] : i64
1347 // CHECK-NEXT:  llvm.return
1348 // CHECK-NEXT: }
1350 func.func @test_is_present_box(%arg0: !fir.box<!fir.ref<i64>>) -> () {
1351   %0 = fir.is_present %arg0 : (!fir.box<!fir.ref<i64>>) -> i1
1352   return
1355 // CHECK-LABEL: @test_is_present_box
1356 // CHECK-SAME: (%[[arg:.*]]: !llvm.ptr<struct<(ptr<i64>, i64, i32, i8, i8, i8, i8)>>)
1357 // CHECK-NEXT: %[[constant:.*]] = llvm.mlir.constant(0 : i64) : i64
1358 // CHECK-NEXT: %[[ptr:.*]] = llvm.ptrtoint %[[arg]] : !llvm.ptr<struct<(ptr<i64>, i64, i32, i8, i8, i8, i8)>> to i64
1359 // CHECK-NEXT: %{{.*}} = llvm.icmp "ne" %[[ptr]], %[[constant]] : i64
1360 // CHECK-NEXT: llvm.return
1361 // CHECK-NEXT: }
1364 // -----
1366 // Test `fir.absent`
1368 func.func @test_absent_i64() -> () {
1369   %0 = fir.absent !fir.ref<i64>
1370   return
1373 // CHECK-LABEL: @test_absent_i64
1374 // CHECK-NEXT:  %{{.*}} = llvm.mlir.null : !llvm.ptr<i64>
1375 // CHECK-NEXT:  llvm.return
1376 // CHECK-NEXT:  }
1378 func.func @test_absent_box() -> () {
1379   %0 = fir.absent !fir.box<!fir.array<?xf32>>
1380   return
1382 // CHECK-LABEL: @test_absent_box
1383 // CHECK-NEXT:  %{{.*}} = llvm.mlir.null : !llvm.ptr<struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>>
1384 // CHECK-NEXT:  llvm.return
1385 // CHECK-NEXT:  }
1387 // -----
1389 // This is a bit more comprehensive test for `fir.is_present` and `fir.absent`
1390 // when used together
1392 func.func @is_present(%arg0: !fir.ref<i64>) -> i1 {
1393   %0 = fir.is_present %arg0 : (!fir.ref<i64>) -> i1
1394   return %0 : i1
1397 // CHECK-LABEL: @is_present
1398 // CHECK-SAME: (%[[arg:.*]]: !llvm.ptr<i64>) -> i1
1399 // CHECK-NEXT:  %[[constant:.*]] = llvm.mlir.constant(0 : i64) : i64
1400 // CHECK-NEXT:  %[[ptr:.*]] = llvm.ptrtoint %[[arg]] : !llvm.ptr<i64> to i64
1401 // CHECK-NEXT:  %[[ret_val:.*]] = llvm.icmp "ne" %[[ptr]], %[[constant]] : i64
1402 // CHECK-NEXT:  llvm.return %[[ret_val]] : i1
1403 // CHECK-NEXT: }
1405 func.func @absent() -> i1 {
1406   %0 = fir.absent !fir.ref<i64>
1407   %1 = fir.call @is_present(%0) : (!fir.ref<i64>) -> i1
1408   return %1 : i1
1411 // CHECK-LABEL: @absent
1412 // CHECK-SAME:  () -> i1
1413 // CHECK-NEXT:  %[[ptr:.*]] = llvm.mlir.null : !llvm.ptr<i64>
1414 // CHECK-NEXT:  %[[ret_val:.*]] = llvm.call @is_present(%[[ptr]]) : (!llvm.ptr<i64>) -> i1
1415 // CHECK-NEXT:  llvm.return %[[ret_val]] : i1
1417 // -----
1419 // Test `fir.string_lit` conversion.
1421 func.func @string_lit0() {
1422   %1 = fir.string_lit "Hello, World!"(13) : !fir.char<1>
1423   return
1426 // CHECK-LABEL: llvm.func @string_lit0
1427 // CHECK: %{{.*}} = llvm.mlir.constant("Hello, World!") : !llvm.array<13 x i8>
1429 func.func @string_lit1() {
1430   %2 = fir.string_lit [158, 2345](2) : !fir.char<2>
1431   return
1434 // CHECK-LABEL: llvm.func @string_lit1
1435 // %{{.*}} = llvm.mlir.constant(dense<[158, 2345]> : vector<2xi16>) : !llvm.array<2 x i16>
1437 // -----
1439 // Test must be dead conversion.
1441 func.func @dead_shift() {
1442   %c0 = arith.constant 0 : index
1443   %0 = fir.shift %c0 : (index) -> !fir.shift<1>
1444   return
1447 // CHECK-LABEL: llvm.func @dead_shift
1448 // CHECK-NOT: fir.shift
1449 // CHECK: %{{.*}} = llvm.mlir.constant(0 : index) : i{{.*}}
1450 // CHECK-NEXT: llvm.return
1452 func.func @dead_shape() {
1453   %c0 = arith.constant 0 : index
1454   %0 = fir.shape %c0 : (index) -> !fir.shape<1>
1455   return
1458 // CHECK-LABEL: llvm.func @dead_shape
1459 // CHECK-NOT: fir.shape
1460 // CHECK: %{{.*}} = llvm.mlir.constant(0 : index) : i{{.*}}
1461 // CHECK-NEXT: llvm.return
1463 func.func @dead_shapeshift() {
1464   %c0 = arith.constant 0 : index
1465   %0 = fir.shape_shift %c0, %c0 : (index, index) -> !fir.shapeshift<1>
1466   return
1469 // CHECK-LABEL: llvm.func @dead_shapeshift
1470 // CHECK-NOT: fir.shape_shift
1471 // CHECK: %{{.*}} = llvm.mlir.constant(0 : index) : i{{.*}}
1472 // CHECK-NEXT: llvm.return
1474 func.func @dead_slice() {
1475   %c0 = arith.constant 0 : index
1476   %0 = fir.slice %c0, %c0, %c0 : (index, index, index) -> !fir.slice<1>
1477   return
1480 // CHECK-LABEL: llvm.func @dead_slice
1481 // CHECK-NOT: fir.slice
1482 // CHECK: %{{.*}} = llvm.mlir.constant(0 : index) : i{{.*}}
1483 // CHECK-NEXT: llvm.return
1485 // -----
1487 // Test `fir.box_tdesc` conversion.
1489 func.func @box_tdesc(%arg0: !fir.box<!fir.type<dtdesc{a:i32}>>) {
1490   %0 = fir.box_tdesc %arg0 : (!fir.box<!fir.type<dtdesc{a:i32}>>) -> !fir.tdesc<!fir.type<dtdesc{a:i32}>>
1491   return
1494 // CHECK-LABEL: llvm.func @box_tdesc(
1495 // CHECK-SAME:                       %[[ARG0:.*]]: !llvm.ptr<struct<(ptr<struct<"dtdesc", (i{{.*}})>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr<i{{.*}}>, array<1 x i{{.*}}>)>>) {
1496 // CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 7] : (!llvm.ptr<struct<(ptr<struct<"dtdesc", (i{{.*}})>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr<i{{.*}}>, array<1 x i{{.*}}>)>>) -> !llvm.ptr<ptr<i8>> 
1497 // CHECK:         %[[LOAD:.*]] = llvm.load %[[GEP]] : !llvm.ptr<ptr<i{{.*}}>>
1499 // -----
1501 // Test `fir.embox` conversion.
1503 // Check basic creation of a descriptor and insertion of values.
1504 // The indices used to insert values into the descriptor correspond the
1505 // position of the fields in the descriptor as defined in `CFI_cdesc_t` in
1506 // flang/ISO_Fortran_binding.h.
1508 func.func @embox0(%arg0: !fir.ref<!fir.array<100xi32>>) {
1509   %0 = fir.embox %arg0() : (!fir.ref<!fir.array<100xi32>>) -> !fir.box<!fir.array<100xi32>>
1510   return
1513 // CHECK-LABEL: func @embox0(
1514 // CHECK-SAME:               %[[ARG0:.*]]: !llvm.ptr<array<100 x i32>>
1515 // CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : i32) : i32
1516 // CHECK:         %[[ALLOCA:.*]] = llvm.alloca %[[C1]] x !llvm.struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})> {alignment = 8 : i64} : (i32) -> !llvm.ptr<struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>
1517 // CHECK:         %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr<i32>
1518 // CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
1519 // CHECK:         %[[I64_ELEM_SIZE:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr<i32> to i64
1520 // CHECK:         %[[TYPE_CODE:.*]] = llvm.mlir.constant(9 : i32) : i32
1521 // CHECK:         %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1522 // CHECK:         %[[DESC0:.*]] = llvm.insertvalue %[[I64_ELEM_SIZE]], %[[DESC]][1] : !llvm.struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1523 // CHECK:         %[[CFI_VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32
1524 // CHECK:         %[[DESC1:.*]] = llvm.insertvalue %[[CFI_VERSION]], %[[DESC0]][2] : !llvm.struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1525 // CHECK:         %[[RANK:.*]] = llvm.mlir.constant(0 : i32) : i32
1526 // CHECK:         %[[RANK_I8:.*]] = llvm.trunc %[[RANK]] : i32 to i8
1527 // CHECK:         %[[DESC2:.*]] = llvm.insertvalue %[[RANK_I8]], %[[DESC1]][3] : !llvm.struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1528 // CHECK:         %[[TYPE_CODE_I8:.*]] = llvm.trunc %[[TYPE_CODE]] : i32 to i8
1529 // CHECK:         %[[DESC3:.*]] = llvm.insertvalue %[[TYPE_CODE_I8]], %[[DESC2]][4] : !llvm.struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1530 // CHECK:         %[[ATTR:.*]] = llvm.mlir.constant(0 : i32) : i32
1531 // CHECK:         %[[ATTR_I8:.*]] = llvm.trunc %[[ATTR]] : i32 to i8
1532 // CHECK:         %[[DESC4:.*]] = llvm.insertvalue %[[ATTR_I8]], %[[DESC3]][5] : !llvm.struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1533 // CHECK:         %[[F18ADDENDUM:.*]] = llvm.mlir.constant(0 : i32) : i32
1534 // CHECK:         %[[F18ADDENDUM_I8:.*]] = llvm.trunc %[[F18ADDENDUM]] : i32 to i8
1535 // CHECK:         %[[DESC5:.*]] = llvm.insertvalue %[[F18ADDENDUM_I8]], %[[DESC4]][6] : !llvm.struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1536 // CHECK:         %[[ADDR:.*]] = llvm.bitcast %[[ARG0]] : !llvm.ptr<array<100 x i32>> to !llvm.ptr<array<100 x i32>>
1537 // CHECK:         %[[DESC6:.*]] = llvm.insertvalue %[[ADDR]], %[[DESC5]][0] : !llvm.struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1538 // CHECK:         llvm.store %[[DESC6]], %[[ALLOCA]] : !llvm.ptr<struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>
1540 // Check `fir.embox` in a `fir.global`. Descriptors created by `fir.embox`
1541 // conversion are not generating `alloca` instructions. This test make sure of
1542 // that.
1544 fir.global @box_global : !fir.ref<!fir.array<?xi32>> {
1545   %arr = fir.zero_bits !fir.ref<!fir.array<?xi32>>
1546   %0 = arith.constant 0 : index
1547   %3 = fir.embox %arr: (!fir.ref<!fir.array<?xi32>>) -> !fir.box<!fir.array<?xi32>>
1548   fir.has_value %arr : !fir.ref<!fir.array<?xi32>>
1551 // CHECK-LABEL: llvm.mlir.global external @box_global
1552 // CHECK-NOT:     llvm.alloca
1554 // Check `fir.embox` conversion of a POINTER entity. Make sure that the
1555 // attribute in the descriptor is set to 1 (value of CFI_attribute_pointer
1556 // in flang/ISO_Fortran_binding.h).
1558 func.func @embox_pointer(%arg0: !fir.ref<i32>) {
1559   %0 = fir.embox %arg0 : (!fir.ref<i32>) -> !fir.box<!fir.ptr<i32>>
1560   return
1563 // CHECK-LABEL: llvm.func @embox_pointer
1564 // Check 1st 1 constant to skip it.
1565 // CHECK: %{{.*}} = llvm.mlir.constant(1 : i32) : i32
1566 // CHECK: %[[CFI_ATTR_POINTER:.*]] = llvm.mlir.constant(1 : i32) : i32
1567 // CHECK: %[[ATTR_I8:.*]] = llvm.trunc %[[CFI_ATTR_POINTER]] : i32 to i8
1568 // CHECK: %{{.*}} = llvm.insertvalue %[[ATTR_I8]], %{{.*}}[5] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1570 // Check `fir.embox` conversion of an ALLOCATABLE entity. Make sure that the
1571 // attribute in the descriptor is set to 2 (value of CFI_attribute_allocatable
1572 // in flang/ISO_Fortran_binding.h).
1574 func.func @embox_allocatable(%arg0: !fir.heap<!fir.array<?x!fir.char<1,10>>>) {
1575   %0 = fir.embox %arg0 : (!fir.heap<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>
1576   return
1579 // CHECK-LABEL: llvm.func @embox_allocatable
1580 // CHECK: %[[CFI_ATTR_ALLOCATABLE:.*]] = llvm.mlir.constant(2 : i32) : i32
1581 // CHECK: %[[ATTR_I8:.*]] = llvm.trunc %[[CFI_ATTR_ALLOCATABLE]] : i32 to i8
1582 // CHECK: %{{.*}} = llvm.insertvalue %[[ATTR_I8]], %{{.*}}[5] : !llvm.struct<(ptr<array<10 x i8>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1584 // Check `fir.embox` conversion of a type code.
1586 func.func @embox_typecode0(%arg0: !fir.ref<i64>) {
1587   %0 = fir.embox %arg0 : (!fir.ref<i64>) -> !fir.box<!fir.ptr<i64>>
1588   return
1591 // CHECK-LABEL: llvm.func @embox_typecode0
1592 // CHECK: %[[TYPE_CODE_I64:.*]] = llvm.mlir.constant(10 : i32) : i32
1593 // CHECK: %[[TYPE_CODE_I64_I8:.*]] = llvm.trunc %[[TYPE_CODE_I64]] : i32 to i8
1594 // CHECK: %{{.*}} = llvm.insertvalue %[[TYPE_CODE_I64_I8]], %{{.*}}[4] : !llvm.struct<(ptr<i64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1596 func.func @embox_typecode1(%arg0: !fir.ref<f32>) {
1597   %0 = fir.embox %arg0 : (!fir.ref<f32>) -> !fir.box<!fir.ptr<f32>>
1598   return
1601 // CHECK-LABEL: llvm.func @embox_typecode1
1602 // CHECK: %[[TYPE_CODE_F32:.*]] = llvm.mlir.constant(27 : i32) : i32
1603 // CHECK: %[[TYPE_CODE_F32_I8:.*]] = llvm.trunc %[[TYPE_CODE_I64]] : i32 to i8
1604 // CHECK: %{{.*}} = llvm.insertvalue %[[TYPE_CODE_F32_I8]], %{{.*}}[4] : !llvm.struct<(ptr<f32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1606 func.func @embox_typecode2(%arg0: !fir.ref<f128>) {
1607   %0 = fir.embox %arg0 : (!fir.ref<f128>) -> !fir.box<!fir.ptr<f128>>
1608   return
1611 // CHECK-LABEL: llvm.func @embox_typecode2
1612 // CHECK: %[[TYPE_CODE_F128:.*]] = llvm.mlir.constant(31 : i32) : i32
1613 // CHECK: %[[TYPE_CODE_F128_I8:.*]] = llvm.trunc %[[TYPE_CODE_F128]] : i32 to i8
1614 // CHECK: %{{.*}} = llvm.insertvalue %[[TYPE_CODE_F128_I8]], %{{.*}}[4] : !llvm.struct<(ptr<f128>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1616 func.func @embox_typecode3(%arg0: !fir.ref<!fir.complex<4>>) {
1617   %0 = fir.embox %arg0 : (!fir.ref<!fir.complex<4>>) -> !fir.box<!fir.ptr<!fir.complex<4>>>
1618   return
1621 // CHECK-LABEL: llvm.func @embox_typecode3
1622 // CHECK: %[[TYPE_CODE_CPLX4:.*]] = llvm.mlir.constant(34 : i32) : i32
1623 // CHECK: %[[TYPE_CODE_CPLX4_I8:.*]] = llvm.trunc %[[TYPE_CODE_F128]] : i32 to i8
1624 // CHECK: %{{.*}} = llvm.insertvalue %[[TYPE_CODE_CPLX4_I8]], %{{.*}}[4] : !llvm.struct<(ptr<struct<(f32, f32)>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1626 func.func @embox_typecode4(%arg0: !fir.ref<!fir.logical<1>>) {
1627   %0 = fir.embox %arg0 : (!fir.ref<!fir.logical<1>>) -> !fir.box<!fir.ptr<!fir.logical<1>>>
1628   return
1631 // CHECK-LABEL: llvm.func @embox_typecode4
1632 // CHECK: %[[TYPE_CODE_I64:.*]] = llvm.mlir.constant(39 : i32) : i32
1633 // CHECK: %[[TYPE_CODE_I64_I8:.*]] = llvm.trunc %[[TYPE_CODE_I64]] : i32 to i8
1634 // CHECK: %{{.*}} = llvm.insertvalue %[[TYPE_CODE_I64_I8]], %{{.*}}[4] : !llvm.struct<(ptr<i8>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
1636 // -----
1638 // Test `fir.embox` conversion. This test creates a global so it needs to be
1639 // split from others.
1641 // Check descriptor for a derived type. Check that the f18Addendum flag is set
1642 // to 1 meaning the addendum is present (true) and the addendum values are
1643 // inserted.
1645 fir.global linkonce @_QMtest_dinitE.dt.tseq constant : i8
1647 func.func @embox1(%arg0: !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>) {
1648   %0 = fir.embox %arg0() : (!fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>) -> !fir.box<!fir.type<_QMtest_dinitTtseq{i:i32}>>
1649   return
1652 // CHECK: llvm.mlir.global linkonce constant @_QMtest_dinitE.dt.tseq() {addr_space = 0 : i32} : i8
1653 // CHECK-LABEL: llvm.func @embox1
1654 // CHECK:         %[[TYPE_CODE:.*]] = llvm.mlir.constant(42 : i32) : i32
1655 // CHECK:         %[[TYPE_CODE_I8:.*]] = llvm.trunc %[[TYPE_CODE]] : i32 to i8
1656 // CHECK:         %{{.*}} = llvm.insertvalue %[[TYPE_CODE_I8]], %{{.*}}[4] : !llvm.struct<(ptr<struct<"_QMtest_dinitTtseq", (i32)>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr<i{{.*}}>, array<1 x i{{.*}}>)>
1657 // CHECK:         %[[F18ADDENDUM:.*]] = llvm.mlir.constant(1 : i32) : i32
1658 // CHECK:         %[[F18ADDENDUM_I8:.*]] = llvm.trunc %[[F18ADDENDUM]] : i32 to i8
1659 // CHECK:         %{{.*}} = llvm.insertvalue %[[F18ADDENDUM_I8]], %17[6] : !llvm.struct<(ptr<struct<"_QMtest_dinitTtseq", (i32)>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr<i{{.*}}>, array<1 x i{{.*}}>)>
1660 // CHECK:         %[[TDESC:.*]] = llvm.mlir.addressof @_QMtest_dinitE.dt.tseq : !llvm.ptr<i8>
1661 // CHECK:         %[[TDESC_CAST:.*]] = llvm.bitcast %21 : !llvm.ptr<i8> to !llvm.ptr<i8>
1662 // CHECK:         %{{.*}} = llvm.insertvalue %[[TDESC_CAST]], %{{.*}}[7] : !llvm.struct<(ptr<struct<"_QMtest_dinitTtseq", (i32)>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr<i{{.*}}>, array<1 x i{{.*}}>)>
1664 // -----
1666 // Test `fir.field_index`
1668 func.func @field_index_static_size_1_elem() -> () {
1669   %1 = fir.field_index i, !fir.type<t1{i:i32}>
1670   return
1673 // CHECK-LABEL: @field_index_static_size_1_elem
1674 // CHECK-NEXT:  %{{.*}} = llvm.mlir.constant(0 : i32) : i32
1675 // CHECK-NEXT:  llvm.return
1677 func.func @field_index_static_size_3_elems() -> () {
1678   %1 = fir.field_index k, !fir.type<t2{i:i32, j:f32, k:i8}>
1679   return
1682 // CHECK-LABEL: @field_index_static_size_3_elems
1683 // CHECK-NEXT:  %{{.*}} = llvm.mlir.constant(2 : i32) : i32
1684 // CHECK-NEXT:  llvm.return
1686 //  When converting `fir.field_index` for a dynamically sized record, the
1687 //  offset will be calculated at runtime by calling methods like the ones
1688 //  below. Note that these methods would normally be generated by the compiler.
1689 func.func private @custom_typeP.field_1.offset() -> i32
1690 func.func private @custom_typeP.field_2.offset() -> i32
1692 func.func @field_index_dynamic_size() -> () {
1693   %1 = fir.field_index field_1, !fir.type<custom_type{field_1:i32, field_2:!fir.array<?xf32>}>
1694   %2 = fir.field_index field_2, !fir.type<custom_type{field_1:i32, field_2:!fir.array<?xf32>}>
1695   return
1698 // CHECK-LABEL: @field_index_dynamic_size
1699 // CHECK-NEXT: %{{.*}} = llvm.call @custom_typeP.field_1.offset() {field = 0 : i64} : () -> i32
1700 // CHECK-NEXT: %{{.*}} = llvm.call @custom_typeP.field_2.offset() {field = 1 : i64} : () -> i32
1701 // CHECK-NEXT:  llvm.return
1703 // -----
1705 // Check `fir.no_reassoc` conversion to LLVM IR dialect
1707 func.func @no_reassoc(%arg0: !fir.ref<i32>) {
1708   %0 = fir.alloca i32
1709   %1 = fir.load %arg0 : !fir.ref<i32>
1710   %2 = fir.no_reassoc %1 : i32
1711   fir.store %2 to %0 : !fir.ref<i32>
1712   return
1715 // CHECK-LABEL: llvm.func @no_reassoc(
1716 // CHECK-SAME:                        %[[ARG0:.*]]: !llvm.ptr<i32>) {
1717 // CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
1718 // CHECK:         %[[ALLOC:.*]] = llvm.alloca %[[C1]] x i32 {in_type = i32, operand_segment_sizes = array<i32: 0, 0>} : (i64) -> !llvm.ptr<i32>
1719 // CHECK:         %[[LOAD:.*]] = llvm.load %[[ARG0]] : !llvm.ptr<i32>
1720 // CHECK:         llvm.store %[[LOAD]], %[[ALLOC]] : !llvm.ptr<i32>
1721 // CHECK:         llvm.return
1723 // -----
1725 // Test `fircg.ext_embox` conversion.
1727 // Check complete `fircg.ext_embox`.
1729 func.func @xembox0(%arg0: !fir.ref<!fir.array<?xi32>>) {
1730   %c0 = arith.constant 0 : i64
1731   %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>>
1732   return
1735 // CHECK-LABEL: llvm.func @xembox0(
1736 // CHECK-SAME:                     %[[ARG0:.*]]: !llvm.ptr<i32>
1737 // CHECK:         %[[ALLOCA_SIZE:.*]] = llvm.mlir.constant(1 : i32) : i32
1738 // CHECK:         %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_SIZE]] x !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr<struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>>
1739 // CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
1740 // CHECK:         %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr<i32>
1741 // CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
1742 // CHECK:         %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr<i32> to i64
1743 // CHECK:         %[[TYPE:.*]] = llvm.mlir.constant(9 : i32) : i32
1744 // CHECK:         %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1745 // CHECK:         %[[BOX1:.*]] = llvm.insertvalue %[[ELEM_LEN_I64]], %[[BOX0]][1] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1746 // CHECK:         %[[VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32
1747 // CHECK:         %[[BOX2:.*]] = llvm.insertvalue %[[VERSION]], %[[BOX1]][2] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1748 // CHECK:         %[[RANK:.*]] = llvm.mlir.constant(1 : i32) : i32
1749 // CHECK:         %[[RANK_I8:.*]] = llvm.trunc %[[RANK]] : i32 to i8
1750 // CHECK:         %[[BOX3:.*]] = llvm.insertvalue %[[RANK_I8]], %[[BOX2]][3] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1751 // CHECK:         %[[TYPE_I8:.*]] = llvm.trunc %[[TYPE]] : i32 to i8
1752 // CHECK:         %[[BOX4:.*]] = llvm.insertvalue %[[TYPE_I8]], %[[BOX3]][4] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1753 // CHECK:         %[[ATTR:.*]] = llvm.mlir.constant(0 : i32) : i32
1754 // CHECK:         %[[ATTR_I8:.*]] = llvm.trunc %[[ATTR]] : i32 to i8
1755 // CHECK:         %[[BOX5:.*]] = llvm.insertvalue %[[ATTR_I8]], %[[BOX4]][5] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1756 // CHECK:         %[[F18ADDENDUM:.*]] = llvm.mlir.constant(0 : i32) : i32
1757 // CHECK:         %[[F18ADDENDUM_I8:.*]] = llvm.trunc %[[F18ADDENDUM]] : i32 to i8
1758 // CHECK:         %[[BOX6:.*]] = llvm.insertvalue %[[F18ADDENDUM_I8]], %[[BOX5]][6] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1759 // CHECK:         %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64
1760 // CHECK:         %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64
1761 // CHECK:         %[[ADJUSTED_OFFSET:.*]] = llvm.sub %[[C0]], %[[C0]]  : i64
1762 // CHECK:         %[[DIM_OFFSET:.*]] = llvm.mul %[[ADJUSTED_OFFSET]], %[[ONE]]  : i64
1763 // CHECK:         %[[PTR_OFFSET:.*]] = llvm.add %[[DIM_OFFSET]], %[[ZERO]]  : i64
1764 // CHECK:         %[[EXTENT0:.*]] = llvm.sub %[[C0]], %[[C0]]  : i64
1765 // CHECK:         %[[EXTENT1:.*]] = llvm.add %[[EXTENT0]], %[[C0]]  : i64
1766 // CHECK:         %[[EXTENT2:.*]] = llvm.sdiv %[[EXTENT1]], %[[C0]]  : i64
1767 // CHECK:         %[[EXTENT_CMP:.*]] = llvm.icmp "sgt" %[[EXTENT2]], %[[ZERO]] : i64
1768 // CHECK:         %[[EXTENT:.*]] = llvm.select %[[EXTENT_CMP]], %[[EXTENT2]], %[[ZERO]] : i1, i64
1769 // CHECK:         %[[BOX7:.*]] = llvm.insertvalue %[[ONE]], %[[BOX6]][7, 0, 0] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1770 // CHECK:         %[[BOX8:.*]] = llvm.insertvalue %[[EXTENT]], %[[BOX7]][7, 0, 1] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1771 // CHECK:         %[[STRIDE:.*]] = llvm.mul %[[ELEM_LEN_I64]], %[[C0]]  : i64
1772 // CHECK:         %[[BOX9:.*]] = llvm.insertvalue %[[STRIDE]], %[[BOX8]][7, 0, 2] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1773 // CHECK:         %[[PREV_DIM:.*]] = llvm.mul %[[ELEM_LEN_I64]], %[[C0]]  : i64
1774 // CHECK:         %[[PREV_PTROFF:.*]] = llvm.mul %[[ONE]], %[[C0]]  : i64
1775 // CHECK:         %[[BASE_PTR:.*]] = llvm.getelementptr %[[ARG0]][%[[PTR_OFFSET]]] : (!llvm.ptr<i32>, i64) -> !llvm.ptr<i32>
1776 // CHECK:         %[[ADDR_BITCAST:.*]] = llvm.bitcast %[[BASE_PTR]] : !llvm.ptr<i32> to !llvm.ptr<i32>
1777 // CHECK:         %[[BOX10:.*]] = llvm.insertvalue %[[ADDR_BITCAST]], %[[BOX9]][0] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1778 // CHECK:         llvm.store %[[BOX10]], %[[ALLOCA]] : !llvm.ptr<struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>>
1780 // Check adjustment of element scaling factor.
1782 func.func @xembox1(%arg0: !fir.ref<!fir.array<?x!fir.char<1, 10>>>) {
1783   %c0 = arith.constant 0 : i64
1784   %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>>>
1785   return
1788 // CHECK-LABEL: llvm.func @xembox1(%{{.*}}: !llvm.ptr<array<10 x i8>>) {
1789 // CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
1790 // CHECK:         %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr<array<10 x i8>>
1791 // CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
1792 // CHECK:         %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr<array<10 x i8>> to i64
1793 // CHECK:         %{{.*}} = llvm.insertvalue %[[ELEM_LEN_I64]], %{{.*}}[1] : !llvm.struct<(ptr<array<10 x i8>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1794 // CHECK:         %[[PREV_PTROFF:.*]] = llvm.mul %[[ELEM_LEN_I64]], %[[C0]]  : i64
1796 // Fortran realistic use case extracted from the following snippet:
1798 // ```
1799 // subroutine sb(n,sh1,sh2)
1800 //   integer::n,sh1,sh2
1801 //   double precision::arr(sh1:n,sh2:n)
1802 //   call xb(arr(2:n,4:n))
1803 // end subroutine
1804 // ```
1806 // N is the upperbound, sh1 and sh2 are the shifts or lowerbounds
1807 func.func @_QPsb(%N: index, %sh1: index, %sh2: index) {
1808   %c4 = arith.constant 4 : index
1809   %c1 = arith.constant 1 : index
1810   %c2 = arith.constant 2 : index
1811   // Calculate nelems in dim1
1812   %n1_tmp = arith.subi %N, %sh1 : index
1813   %n1 = arith.addi %n1_tmp, %c1 : index
1814   // Calculate nelems in dim2
1815   %n2_tmp = arith.subi %N, %sh2 : index
1816   %n2 = arith.addi %n2_tmp, %c1 : index
1817   %arr = fir.alloca !fir.array<?x?xf64>, %n1, %n2 {bindc_name = "arr", uniq_name = "_QFsbEarr"}
1818   %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>>
1819   fir.call @_QPxb(%box) : (!fir.box<!fir.array<?x?xf64>>) -> ()
1820   return
1822 func.func private @_QPxb(!fir.box<!fir.array<?x?xf64>>)
1824 // CHECK-LABEL: llvm.func @_QPsb(
1825 // CHECK-SAME:                   %[[N:.*]]: i64, %[[SH1:.*]]: i64, %[[SH2:.*]]: i64) {
1826 // CHECK:         %[[ALLOCA_SIZE:.*]] = llvm.mlir.constant(1 : i32) : i32
1827 // CHECK:         %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_SIZE]] x !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr<struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>>
1828 // CHECK:         %[[C4:.*]] = llvm.mlir.constant(4 : index) : i64
1829 // CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : index) : i64
1830 // CHECK:         %[[C2:.*]] = llvm.mlir.constant(2 : index) : i64
1831 // CHECK:         %[[N1_TMP:.*]] = llvm.sub %[[N]], %[[SH1]]  : i64
1832 // CHECK:         %[[N1:.*]] = llvm.add %[[N1_TMP]], %[[C1]]  : i64
1833 // CHECK:         %[[N2_TMP:.*]] = llvm.sub %[[N]], %[[SH2]]  : i64
1834 // CHECK:         %[[N2:.*]] = llvm.add %[[N2_TMP]], %[[C1]]  : i64
1835 // CHECK:         %[[C1_0:.*]] = llvm.mlir.constant(1 : i64) : i64
1836 // CHECK:         %[[ARR_SIZE_TMP1:.*]] = llvm.mul %[[C1_0]], %[[N1]]  : i64
1837 // CHECK:         %[[ARR_SIZE:.*]] = llvm.mul %[[ARR_SIZE_TMP1]], %[[N2]]  : i64
1838 // CHECK:         %[[ARR:.*]] = llvm.alloca %[[ARR_SIZE]] x f64 {bindc_name = "arr", in_type = !fir.array<?x?xf64>, operand_segment_sizes = array<i32: 0, 2>, uniq_name = "_QFsbEarr"} : (i64) -> !llvm.ptr<f64>
1839 // CHECK:         %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr<f64>
1840 // CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
1841 // CHECK:         %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr<f64> to i64
1842 // CHECK:         %[[TYPE_CODE:.*]] = llvm.mlir.constant(28 : i32) : i32
1843 // CHECK:         %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
1844 // CHECK:         %[[BOX1:.*]] = llvm.insertvalue %[[ELEM_LEN_I64]], %[[BOX0]][1] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
1845 // CHECK:         %[[VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32
1846 // CHECK:         %[[BOX2:.*]] = llvm.insertvalue %[[VERSION]], %[[BOX1]][2] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
1847 // CHECK:         %[[RANK:.*]] = llvm.mlir.constant(2 : i32) : i32
1848 // CHECK:         %[[RANK_I8:.*]] = llvm.trunc %[[RANK]] : i32 to i8
1849 // CHECK:         %[[BOX3:.*]] = llvm.insertvalue %[[RANK_I8]], %[[BOX2]][3] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
1850 // CHECK:         %[[TYPE_I8:.*]] = llvm.trunc %[[TYPE_CODE]] : i32 to i8
1851 // CHECK:         %[[BOX4:.*]] = llvm.insertvalue %[[TYPE_I8]], %[[BOX3]][4] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
1852 // CHECK:         %[[ATTR:.*]] = llvm.mlir.constant(0 : i32) : i32
1853 // CHECK:         %[[ATTR_I8:.*]] = llvm.trunc %[[ATTR]] : i32 to i8
1854 // CHECK:         %[[BOX5:.*]] = llvm.insertvalue %[[ATTR_I8]], %[[BOX4]][5] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
1855 // CHECK:         %[[F18ADDENDUM:.*]] = llvm.mlir.constant(0 : i32) : i32
1856 // CHECK:         %[[F18ADDENDUM_I8:.*]] = llvm.trunc %[[F18ADDENDUM]] : i32 to i8
1857 // CHECK:         %[[BOX6:.*]] = llvm.insertvalue %[[F18ADDENDUM_I8]], %[[BOX5]][6] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
1858 // CHECK:         %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64
1859 // CHECK:         %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64
1860 // CHECK:         %[[ADJUSTED_OFFSET:.*]] = llvm.sub %[[C2]], %[[SH1]] : i64
1861 // CHECK:         %[[DIM_OFFSET:.*]] = llvm.mul %[[ADJUSTED_OFFSET]], %[[ONE]]  : i64
1862 // CHECK:         %[[PTR_OFFSET:.*]] = llvm.add %[[DIM_OFFSET]], %[[ZERO]]  : i64
1863 // CHECK:         %[[EXTENT0:.*]] = llvm.sub %[[ARG0]], %[[C2]]  : i64
1864 // CHECK:         %[[EXTENT1:.*]] = llvm.add %[[EXTENT0]], %[[C1]]  : i64
1865 // CHECK:         %[[EXTENT2:.*]] = llvm.sdiv %[[EXTENT1]], %[[C1]]  : i64
1866 // CHECK:         %[[EXTENT_CMP:.*]] = llvm.icmp "sgt" %[[EXTENT2]], %[[ZERO]] : i64
1867 // CHECK:         %[[EXTENT:.*]] = llvm.select %[[EXTENT_CMP]], %[[EXTENT2]], %[[ZERO]] : i1, i64
1868 // CHECK:         %[[BOX7:.*]] = llvm.insertvalue %[[ONE]], %[[BOX6]][7, 0, 0] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
1869 // CHECK:         %[[BOX8:.*]] = llvm.insertvalue %[[EXTENT]], %[[BOX7]][7, 0, 1] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
1870 // CHECK:         %[[STRIDE:.*]] = llvm.mul %[[ELEM_LEN_I64]], %[[C1]]  : i64
1871 // CHECK:         %[[BOX9:.*]] = llvm.insertvalue %[[STRIDE]], %[[BOX8]][7, 0, 2] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
1872 // CHECK:         %[[PREV_DIM:.*]] = llvm.mul %[[ELEM_LEN_I64]], %[[N1]]  : i64
1873 // CHECK:         %[[PREV_PTROFF:.*]] = llvm.mul %[[ONE]], %[[N1]]  : i64
1874 // CHECK:         %[[ADJUSTED_OFFSET:.*]] = llvm.sub %[[C4]], %[[SH2]]  : i64
1875 // CHECK:         %[[DIM_OFFSET:.*]] = llvm.mul %[[ADJUSTED_OFFSET]], %[[PREV_PTROFF]]  : i64
1876 // CHECK:         %[[PTR_OFFSET0:.*]] = llvm.add %[[DIM_OFFSET]], %[[PTR_OFFSET]]  : i64
1877 // CHECK:         %[[EXT_SUB:.*]] = llvm.sub %[[N]], %[[C4]]  : i64
1878 // CHECK:         %[[EXT_ADD:.*]] = llvm.add %[[EXT_SUB]], %[[C1]]  : i64
1879 // CHECK:         %[[EXT_SDIV:.*]] = llvm.sdiv %[[EXT_ADD]], %[[C1]]  : i64
1880 // CHECK:         %[[EXT_ICMP:.*]] = llvm.icmp "sgt" %[[EXT_SDIV]], %[[ZERO]] : i64
1881 // CHECK:         %[[EXT_SELECT:.*]] = llvm.select %[[EXT_ICMP]], %[[EXT_SDIV]], %[[ZERO]] : i1, i64
1882 // CHECK:         %[[BOX10:.*]] = llvm.insertvalue %[[ONE]], %[[BOX9]][7, 1, 0] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
1883 // CHECK:         %[[BOX11:.*]] = llvm.insertvalue %[[EXT_SELECT]], %[[BOX10]][7, 1, 1] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
1884 // CHECK:         %[[STRIDE_MUL:.*]] = llvm.mul %[[PREV_DIM]], %[[C1]]  : i64
1885 // CHECK:         %[[BOX12:.*]] = llvm.insertvalue %[[STRIDE_MUL]], %[[BOX11]][7, 1, 2] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
1886 // CHECK:         %[[BASE_PTR:.*]] = llvm.getelementptr %[[ARR]][%[[PTR_OFFSET0]]] : (!llvm.ptr<f64>, i64) -> !llvm.ptr<f64>
1887 // CHECK:         %[[ADDR_BITCAST:.*]] = llvm.bitcast %[[BASE_PTR]] : !llvm.ptr<f64> to !llvm.ptr<f64>
1888 // CHECK:         %[[BOX13:.*]] = llvm.insertvalue %[[ADDR_BITCAST]], %[[BOX12]][0] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
1889 // CHECK:         llvm.store %[[BOX13]], %[[ALLOCA]] : !llvm.ptr<struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>>
1891 // Conversion with a subcomponent.
1893 func.func @_QPtest_dt_slice() {
1894   %c20 = arith.constant 20 : index
1895   %c1_i64 = arith.constant 1 : i64
1896   %c10_i64 = arith.constant 10 : i64
1897   %c2_i64 = arith.constant 2 : i64
1898   %0 = fir.alloca i32 {bindc_name = "v", uniq_name = "_QFtest_dt_sliceEv"}
1899   %1 = fir.alloca !fir.array<20x!fir.type<_QFtest_dt_sliceTt{i:i32,j:i32}>> {bindc_name = "x", uniq_name = "_QFtest_dt_sliceEx"}
1900   %2 = fir.field_index i, !fir.type<_QFtest_dt_sliceTt{i:i32,j:i32}>
1901   %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>>
1902   fir.call @_QPtest_dt_callee(%5) : (!fir.box<!fir.array<?xi32>>) -> ()
1903   return
1905 func.func private @_QPtest_dt_callee(%arg0: !fir.box<!fir.array<?xi32>>)
1907 // CHECK-LABEL: llvm.func @_QPtest_dt_slice
1908 // CHECK:         %[[ALLOCA_SIZE:.*]] = llvm.mlir.constant(1 : i32) : i32
1909 // CHECK:         %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_SIZE]] x !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr<struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>>
1910 // CHECK:         %[[C20:.*]] = llvm.mlir.constant(20 : index) : i64
1911 // CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
1912 // CHECK:         %[[C10:.*]] = llvm.mlir.constant(10 : i64) : i64
1913 // CHECK:         %[[C2:.*]] = llvm.mlir.constant(2 : i64) : i64
1914 // CHECK:         %[[ALLOCA_SIZE_V:.*]] = llvm.mlir.constant(1 : i64) : i64
1915 // CHECK:         %[[V:.*]] = llvm.alloca %[[ALLOCA_SIZE_V]] x i32 {bindc_name = "v", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFtest_dt_sliceEv"} : (i64) -> !llvm.ptr<i32>
1916 // CHECK:         %[[ALLOCA_SIZE_X:.*]] = llvm.mlir.constant(1 : i64) : i64
1917 // CHECK:         %[[X:.*]] = llvm.alloca %[[ALLOCA_SIZE_X]] x !llvm.array<20 x struct<"_QFtest_dt_sliceTt", (i32, i32)>> {bindc_name = "x", in_type = !fir.array<20x!fir.type<_QFtest_dt_sliceTt{i:i32,j:i32}>>, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFtest_dt_sliceEx"} : (i64) -> !llvm.ptr<array<20 x struct<"_QFtest_dt_sliceTt", (i32, i32)>>>
1918 // CHECK:         %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr<i32>
1919 // CHECK:         %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
1920 // CHECK:         %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr<i32> to i64
1921 // CHECK:         %[[TYPE_CODE:.*]] = llvm.mlir.constant(9 : i32) : i32
1922 // CHECK:         %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1923 // CHECK:         %[[BOX1:.*]] = llvm.insertvalue %[[ELEM_LEN_I64]], %[[BOX0]][1] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1924 // CHECK:         %[[VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32
1925 // CHECK:         %[[BOX2:.*]] = llvm.insertvalue %[[VERSION]], %[[BOX1]][2] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1926 // CHECK:         %[[RANK:.*]] = llvm.mlir.constant(1 : i32) : i32
1927 // CHECK:         %[[RANK_I8:.*]] = llvm.trunc %[[RANK]] : i32 to i8
1928 // CHECK:         %[[BOX3:.*]] = llvm.insertvalue %[[RANK_I8]], %[[BOX2]][3] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1929 // CHECK:         %[[TYPE_CODE_I8:.*]] = llvm.trunc %[[TYPE_CODE]] : i32 to i8
1930 // CHECK:         %[[BOX4:.*]] = llvm.insertvalue %[[TYPE_CODE_I8]], %[[BOX3]][4] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1931 // CHECK:         %[[ATTR:.*]] = llvm.mlir.constant(0 : i32) : i32
1932 // CHECK:         %[[ATTR_I8:.*]] = llvm.trunc %[[ATTR]] : i32 to i8
1933 // CHECK:         %[[BOX5:.*]] = llvm.insertvalue %[[ATTR_I8]], %[[BOX4]][5] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1934 // CHECK:         %[[F18ADDENDUM:.*]] = llvm.mlir.constant(0 : i32) : i32
1935 // CHECK:         %[[F18ADDENDUM_I8:.*]] = llvm.trunc %[[F18ADDENDUM]] : i32 to i8
1936 // CHECK:         %[[BOX6:.*]] = llvm.insertvalue %[[F18ADDENDUM_I8]], %[[BOX5]][6] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1937 // CHECK:         %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64
1938 // CHECK:         %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64
1939 // CHECK:         %[[ELE_TYPE:.*]] = llvm.mlir.null : !llvm.ptr<struct<"_QFtest_dt_sliceTt", (i32, i32)>>
1940 // CHECK:         %[[GEP_DTYPE_SIZE:.*]] = llvm.getelementptr %[[ELE_TYPE]][1] : (!llvm.ptr<struct<"_QFtest_dt_sliceTt", (i32, i32)>>) -> !llvm.ptr<struct<"_QFtest_dt_sliceTt", (i32, i32)>>
1941 // CHECK:         %[[PTRTOINT_DTYPE_SIZE:.*]] = llvm.ptrtoint %[[GEP_DTYPE_SIZE]] : !llvm.ptr<struct<"_QFtest_dt_sliceTt", (i32, i32)>> to i64
1942 // CHECK:         %[[ADJUSTED_OFFSET:.*]] = llvm.sub %[[C1]], %[[ONE]]  : i64
1943 // CHECK:         %[[EXT_SUB:.*]] = llvm.sub %[[C10]], %[[C1]]  : i64
1944 // CHECK:         %[[EXT_ADD:.*]] = llvm.add %[[EXT_SUB]], %[[C2]]  : i64
1945 // CHECK:         %[[EXT_SDIV:.*]] = llvm.sdiv %[[EXT_ADD]], %[[C2]]  : i64
1946 // CHECK:         %[[EXT_ICMP:.*]] = llvm.icmp "sgt" %[[EXT_SDIV]], %[[ZERO]] : i64
1947 // CHECK:         %[[EXT_SELECT:.*]] = llvm.select %[[EXT_ICMP]], %[[EXT_SDIV]], %[[ZERO]] : i1, i64
1948 // CHECK:         %[[BOX7:.*]] = llvm.insertvalue %[[ONE]], %[[BOX6]][7, 0, 0] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1949 // CHECK:         %[[BOX8:.*]] = llvm.insertvalue %[[EXT_SELECT]], %[[BOX7]][7, 0, 1] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1950 // CHECK:         %[[STRIDE_MUL:.*]] = llvm.mul %[[PTRTOINT_DTYPE_SIZE]], %[[C2]]  : i64
1951 // CHECK:         %[[BOX9:.*]] = llvm.insertvalue %[[STRIDE_MUL]], %[[BOX8]][7, 0, 2] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1952 // CHECK:         %[[BASE_PTR:.*]] = llvm.getelementptr %[[X]][%[[ZERO]], %[[ADJUSTED_OFFSET]], 0] : (!llvm.ptr<array<20 x struct<"_QFtest_dt_sliceTt", (i32, i32)>>>, i64, i64) -> !llvm.ptr<i32>
1953 // CHECK:         %[[ADDR_BITCAST:.*]] = llvm.bitcast %[[BASE_PTR]] : !llvm.ptr<i32> to !llvm.ptr<i32>
1954 // CHECK:         %[[BOX10:.*]] = llvm.insertvalue %[[ADDR_BITCAST]], %[[BOX9]][0] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
1955 // CHECK:         llvm.store %[[BOX10]], %[[ALLOCA]] : !llvm.ptr<struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>>
1956 // CHECK:         llvm.call @_QPtest_dt_callee(%1) : (!llvm.ptr<struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>>) -> ()
1958 // -----
1960 // Test `fircg.ext_array_coor` conversion.
1962 // Conversion with only shape and indice.
1964 func.func @ext_array_coor0(%arg0: !fir.ref<!fir.array<?xi32>>) {
1965   %c0 = arith.constant 0 : i64
1966   %1 = fircg.ext_array_coor %arg0(%c0) <%c0> : (!fir.ref<!fir.array<?xi32>>, i64, i64) -> !fir.ref<i32>
1967   return
1970 // CHECK-LABEL: llvm.func @ext_array_coor0(
1971 // CHECK-SAME:                             %[[ARG0:.*]]: !llvm.ptr<i32>)
1972 // CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
1973 // CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
1974 // CHECK:         %[[C0_1:.*]] = llvm.mlir.constant(0 : i64) : i64
1975 // CHECK:         %[[IDX:.*]] = llvm.sub %[[C0]], %[[C1]] : i64
1976 // CHECK:         %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] : i64
1977 // CHECK:         %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[C1]]  : i64
1978 // CHECK:         %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]]  : i64
1979 // CHECK:         %[[BITCAST:.*]] = llvm.bitcast %[[ARG0]] : !llvm.ptr<i32> to !llvm.ptr<i32>
1980 // CHECK:         %{{.*}} = llvm.getelementptr %[[BITCAST]][%[[OFFSET]]] : (!llvm.ptr<i32>, i64) -> !llvm.ptr<i32>
1982 // Conversion with shift and slice.
1984 func.func @ext_array_coor1(%arg0: !fir.ref<!fir.array<?xi32>>) {
1985   %c0 = arith.constant 0 : i64
1986   %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>
1987   return
1990 // CHECK-LABEL: llvm.func @ext_array_coor1(
1991 // CHECK-SAME:                             %[[ARG0:.*]]: !llvm.ptr<i32>)
1992 // CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
1993 // CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
1994 // CHECK:         %[[C0_1:.*]] = llvm.mlir.constant(0 : i64) : i64
1995 // CHECK:         %[[IDX:.*]] = llvm.sub %[[C0]], %[[C0]] : i64
1996 // CHECK:         %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C0]] : i64
1997 // CHECK:         %[[ADJ:.*]] = llvm.sub %[[C0]], %[[C0]]  : i64
1998 // CHECK:         %[[DIFF1:.*]] = llvm.add %[[DIFF0]], %[[ADJ]]  : i64
1999 // CHECK:         %[[STRIDE:.*]] = llvm.mul %[[DIFF1]], %[[C1]]  : i64
2000 // CHECK:         %[[OFFSET:.*]] = llvm.add %[[STRIDE]], %[[C0_1]]  : i64
2001 // CHECK:         %[[BITCAST:.*]] = llvm.bitcast %[[ARG0]] : !llvm.ptr<i32> to !llvm.ptr<i32>
2002 // CHECK:         %{{.*}} = llvm.getelementptr %[[BITCAST]][%[[OFFSET]]] : (!llvm.ptr<i32>, i64) -> !llvm.ptr<i32>
2004 // Conversion for a dynamic length char.
2006 func.func @ext_array_coor2(%arg0: !fir.ref<!fir.array<?x!fir.char<1,?>>>) {
2007   %c0 = arith.constant 0 : i64
2008   %1 = fircg.ext_array_coor %arg0(%c0) <%c0> : (!fir.ref<!fir.array<?x!fir.char<1,?>>>, i64, i64) -> !fir.ref<i32>
2009   return
2012 // CHECK-LABEL: llvm.func @ext_array_coor2(
2013 // CHECK-SAME:                             %[[ARG0:.*]]: !llvm.ptr<i8>)
2014 // CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
2015 // CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
2016 // CHECK:         %[[C0_1:.*]] = llvm.mlir.constant(0 : i64) : i64
2017 // CHECK:         %[[IDX:.*]] = llvm.sub %[[C0]], %[[C1]] : i64
2018 // CHECK:         %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] : i64
2019 // CHECK:         %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[C1]]  : i64
2020 // CHECK:         %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]]  : i64
2021 // CHECK:         %[[BITCAST:.*]] = llvm.bitcast %[[ARG0]] : !llvm.ptr<i8> to !llvm.ptr<i32>
2022 // CHECK:         %{{.*}} = llvm.getelementptr %[[BITCAST]][%[[OFFSET]]] : (!llvm.ptr<i32>, i64) -> !llvm.ptr<i32>
2024 // Conversion for a `fir.box`.
2026 func.func @ext_array_coor3(%arg0: !fir.box<!fir.array<?xi32>>) {
2027   %c0 = arith.constant 0 : i64
2028   %1 = fircg.ext_array_coor %arg0(%c0) <%c0> : (!fir.box<!fir.array<?xi32>>, i64, i64) -> !fir.ref<i32>
2029   return
2032 // CHECK-LABEL: llvm.func @ext_array_coor3(
2033 // CHECK-SAME:                             %[[ARG0:.*]]: !llvm.ptr<struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>>) {
2034 // CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
2035 // CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
2036 // CHECK:         %[[C0_1:.*]] = llvm.mlir.constant(0 : i64) : i64
2037 // CHECK:         %[[IDX:.*]] = llvm.sub %[[C0]], %[[C1]] : i64
2038 // CHECK:         %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] : i64
2039 // CHECK:         %[[GEPSTRIDE:.*]] = llvm.getelementptr %[[ARG0]][0, 7, 0, 2] : (!llvm.ptr<struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>>) -> !llvm.ptr<i64>
2040 // CHECK:         %[[LOADEDSTRIDE:.*]] = llvm.load %[[GEPSTRIDE]] : !llvm.ptr<i64>
2041 // CHECK:         %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[LOADEDSTRIDE]]  : i64
2042 // CHECK:         %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]]  : i64
2043 // CHECK:         %[[GEPADDR:.*]] = llvm.getelementptr %[[ARG0]][0, 0] : (!llvm.ptr<struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>>) -> !llvm.ptr<ptr<i32>>
2044 // CHECK:         %[[LOADEDADDR:.*]] = llvm.load %[[GEPADDR]] : !llvm.ptr<ptr<i32>>
2045 // CHECK:         %[[LOADEDADDRBITCAST:.*]] = llvm.bitcast %[[LOADEDADDR]] : !llvm.ptr<i32> to !llvm.ptr<i8>
2046 // CHECK:         %[[GEPADDROFFSET:.*]] = llvm.getelementptr %[[LOADEDADDRBITCAST]][%[[OFFSET]]] : (!llvm.ptr<i8>, i64) -> !llvm.ptr<i8>
2047 // CHECK:         %{{.*}} = llvm.bitcast %[[GEPADDROFFSET]] : !llvm.ptr<i8> to !llvm.ptr<i32>
2049 // Conversion with non zero shift and slice.
2051 func.func @ext_array_coor4(%arg0: !fir.ref<!fir.array<100xi32>>) {
2052   %c0 = arith.constant 0 : i64
2053   %c10 = arith.constant 10 : i64
2054   %c20 = arith.constant 20 : i64
2055   %c1 = arith.constant 1 : i64
2056   %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>
2057   return
2060 // CHECK-LABEL: llvm.func @ext_array_coor4(
2061 // CHECK:                                  %[[ARG0:.*]]: !llvm.ptr<array<100 x i32>>) {
2062 // CHECK:         %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
2063 // CHECK:         %[[C10:.*]] = llvm.mlir.constant(10 : i64) : i64
2064 // CHECK:         %[[C20:.*]] = llvm.mlir.constant(20 : i64) : i64
2065 // CHECK:         %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
2066 // CHECK:         %[[C1_1:.*]] = llvm.mlir.constant(1 : i64) : i64
2067 // CHECK:         %[[C0_1:.*]] = llvm.mlir.constant(0 : i64) : i64
2068 // CHECK:         %[[IDX:.*]] = llvm.sub %[[C1]], %[[C0]]  : i64
2069 // CHECK:         %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]]  : i64
2070 // CHECK:         %[[ADJ:.*]] = llvm.sub %[[C10]], %[[C0]]  : i64
2071 // CHECK:         %[[DIFF1:.*]] = llvm.add %[[DIFF0]], %[[ADJ]]  : i64
2072 // CHECK:         %[[STRIDE:.*]] = llvm.mul %[[DIFF1]], %[[C1_1]] : i64
2073 // CHECK:         %[[OFFSET:.*]] = llvm.add %[[STRIDE]], %[[C0_1]]  : i64
2074 // CHECK:         %[[BITCAST:.*]] = llvm.bitcast %[[ARG0]] : !llvm.ptr<array<100 x i32>> to !llvm.ptr<i32>
2075 // CHECK:         %{{.*}} = llvm.getelementptr %[[BITCAST]][%[[OFFSET]]] : (!llvm.ptr<i32>, i64) -> !llvm.ptr<i32>
2077 // Conversion with index type shape and slice
2079 func.func @ext_array_coor5(%arg0: !fir.ref<!fir.array<?xi32>>, %idx1 : index, %idx2 : index, %idx3 : index, %idx4 : index, %idx5 : index) {
2080   %1 = fircg.ext_array_coor %arg0(%idx1)[%idx2, %idx3, %idx4]<%idx5> : (!fir.ref<!fir.array<?xi32>>, index, index, index, index, index) -> !fir.ref<i32>
2081   return
2084 // CHECK-LABEL:   llvm.func @ext_array_coor5(
2085 // CHECK-SAME:        %[[VAL_0:.*]]: !llvm.ptr<i32>, %[[VAL_1:.*]]: i64, %[[VAL_2:.*]]: i64, %[[VAL_3:.*]]: i64, %[[VAL_4:.*]]: i64, %[[VAL_5:.*]]: i64) {
2086 // CHECK:           %[[VAL_6:.*]] = llvm.mlir.constant(1 : i64) : i64
2087 // CHECK:           %[[VAL_7:.*]] = llvm.mlir.constant(0 : i64) : i64
2088 // CHECK:           %[[VAL_8:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]]  : i64
2089 // CHECK:           %[[VAL_9:.*]] = llvm.mul %[[VAL_8]], %[[VAL_4]]  : i64
2090 // CHECK:           %[[VAL_10:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]]  : i64
2091 // CHECK:           %[[VAL_11:.*]] = llvm.add %[[VAL_9]], %[[VAL_10]]  : i64
2092 // CHECK:           %[[VAL_12:.*]] = llvm.mul %[[VAL_11]], %[[VAL_6]]  : i64
2093 // CHECK:           %[[VAL_13:.*]] = llvm.add %[[VAL_12]], %[[VAL_7]]  : i64
2094 // CHECK:           %[[VAL_14:.*]] = llvm.mul %[[VAL_6]], %[[VAL_1]]  : i64
2095 // CHECK:           %[[VAL_15:.*]] = llvm.bitcast %[[VAL_0]] : !llvm.ptr<i32> to !llvm.ptr<i32>
2096 // CHECK:           %[[VAL_16:.*]] = llvm.getelementptr %[[VAL_15]][%[[VAL_13]]] : (!llvm.ptr<i32>, i64) -> !llvm.ptr<i32>
2097 // CHECK:         }
2099 // Conversion for 3-d array
2101 func.func @ext_array_coor6(%arg0: !fir.ref<!fir.array<?x?x?xi32>>, %idx1 : index, %idx2 : index, %idx3 : index, %idx4 : index, %idx5 : index) {
2102   %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>
2103   return
2106 // CHECK-LABEL:   llvm.func @ext_array_coor6(
2107 // CHECK-SAME:        %[[VAL_0:.*]]: !llvm.ptr<i32>, %[[VAL_1:.*]]: i64, %[[VAL_2:.*]]: i64, %[[VAL_3:.*]]: i64, %[[VAL_4:.*]]: i64, %[[VAL_5:.*]]: i64) {
2108 // CHECK:           %[[VAL_6:.*]] = llvm.mlir.constant(1 : i64) : i64
2109 // CHECK:           %[[VAL_7:.*]] = llvm.mlir.constant(0 : i64) : i64
2110 // CHECK:           %[[VAL_8:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]]  : i64
2111 // CHECK:           %[[VAL_9:.*]] = llvm.mul %[[VAL_8]], %[[VAL_4]]  : i64
2112 // CHECK:           %[[VAL_10:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]]  : i64
2113 // CHECK:           %[[VAL_11:.*]] = llvm.add %[[VAL_9]], %[[VAL_10]]  : i64
2114 // CHECK:           %[[VAL_12:.*]] = llvm.mul %[[VAL_11]], %[[VAL_6]]  : i64
2115 // CHECK:           %[[VAL_13:.*]] = llvm.add %[[VAL_12]], %[[VAL_7]]  : i64
2116 // CHECK:           %[[VAL_14:.*]] = llvm.mul %[[VAL_6]], %[[VAL_1]]  : i64
2117 // CHECK:           %[[VAL_15:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]]  : i64
2118 // CHECK:           %[[VAL_16:.*]] = llvm.mul %[[VAL_15]], %[[VAL_4]]  : i64
2119 // CHECK:           %[[VAL_17:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]]  : i64
2120 // CHECK:           %[[VAL_18:.*]] = llvm.add %[[VAL_16]], %[[VAL_17]]  : i64
2121 // CHECK:           %[[VAL_19:.*]] = llvm.mul %[[VAL_18]], %[[VAL_14]]  : i64
2122 // CHECK:           %[[VAL_20:.*]] = llvm.add %[[VAL_19]], %[[VAL_13]]  : i64
2123 // CHECK:           %[[VAL_21:.*]] = llvm.mul %[[VAL_14]], %[[VAL_1]]  : i64
2124 // CHECK:           %[[VAL_22:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]]  : i64
2125 // CHECK:           %[[VAL_23:.*]] = llvm.mul %[[VAL_22]], %[[VAL_4]]  : i64
2126 // CHECK:           %[[VAL_24:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]]  : i64
2127 // CHECK:           %[[VAL_25:.*]] = llvm.add %[[VAL_23]], %[[VAL_24]]  : i64
2128 // CHECK:           %[[VAL_26:.*]] = llvm.mul %[[VAL_25]], %[[VAL_21]]  : i64
2129 // CHECK:           %[[VAL_27:.*]] = llvm.add %[[VAL_26]], %[[VAL_20]]  : i64
2130 // CHECK:           %[[VAL_28:.*]] = llvm.mul %[[VAL_21]], %[[VAL_1]]  : i64
2131 // CHECK:           %[[VAL_29:.*]] = llvm.bitcast %[[VAL_0]] : !llvm.ptr<i32> to !llvm.ptr<i32>
2132 // CHECK:           %[[VAL_30:.*]] = llvm.getelementptr %[[VAL_29]][%[[VAL_27]]] : (!llvm.ptr<i32>, i64) -> !llvm.ptr<i32>
2133 // CHECK:           llvm.return
2134 // CHECK:         }
2136 // Conversion for derived type with type param
2138 func.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) {
2139   %1 = fir.field_index i, !fir.type<_QFtest_dt_sliceTt{i:i32,j:i32}>
2140   %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}>>
2141   return
2144 // CHECK-LABEL:   llvm.func @ext_array_coor_dt_slice(
2145 // CHECK-SAME:        %[[VAL_0:.*]]: !llvm.ptr<array<20 x struct<"_QFtest_dt_sliceTt", (i32, i32)>>>, %[[VAL_1:.*]]: i64, %[[VAL_2:.*]]: i64, %[[VAL_3:.*]]: i64, %[[VAL_4:.*]]: i64, %[[VAL_5:.*]]: i64) {
2146 // CHECK:           %[[VAL_6:.*]] = llvm.mlir.constant(0 : i32) : i32
2147 // CHECK:           %[[VAL_7:.*]] = llvm.mlir.constant(1 : i64) : i64
2148 // CHECK:           %[[VAL_8:.*]] = llvm.mlir.constant(0 : i64) : i64
2149 // CHECK:           %[[VAL_9:.*]] = llvm.sub %[[VAL_5]], %[[VAL_7]]  : i64
2150 // CHECK:           %[[VAL_10:.*]] = llvm.mul %[[VAL_9]], %[[VAL_4]]  : i64
2151 // CHECK:           %[[VAL_11:.*]] = llvm.sub %[[VAL_2]], %[[VAL_7]]  : i64
2152 // CHECK:           %[[VAL_12:.*]] = llvm.add %[[VAL_10]], %[[VAL_11]]  : i64
2153 // CHECK:           %[[VAL_13:.*]] = llvm.mul %[[VAL_12]], %[[VAL_7]]  : i64
2154 // CHECK:           %[[VAL_14:.*]] = llvm.add %[[VAL_13]], %[[VAL_8]]  : i64
2155 // CHECK:           %[[VAL_15:.*]] = llvm.mul %[[VAL_7]], %[[VAL_1]]  : i64
2156 // CHECK:           %[[VAL_16:.*]] = llvm.bitcast %[[VAL_0]] : !llvm.ptr<array<20 x struct<"_QFtest_dt_sliceTt", (i32, i32)>>> to !llvm.ptr<struct<"_QFtest_dt_sliceTt", (i32, i32)>>
2157 // CHECK:           %[[VAL_17:.*]] = llvm.getelementptr %[[VAL_16]][%[[VAL_14]], 0] : (!llvm.ptr<struct<"_QFtest_dt_sliceTt", (i32, i32)>>, i64) -> !llvm.ptr<struct<"_QFtest_dt_sliceTt", (i32, i32)>>
2158 // CHECK:           llvm.return
2159 // CHECK:         }
2161 // -----
2163 // Check `fircg.ext_rebox` conversion to LLVM IR dialect
2165 // Test applying slice on fir.box. Note that the slice is 1D where as the array is 2D.
2166 //   subroutine foo(x)
2167 //     real :: x(3:, 4:)
2168 //     call bar(x(5, 6:80:3))
2169 //   end subroutine
2171 func.func private @bar1(!fir.box<!fir.array<?xf32>>)
2172 func.func @test_rebox_1(%arg0: !fir.box<!fir.array<?x?xf32>>) {
2173   %c2 = arith.constant 2 : index
2174   %c3 = arith.constant 3 : index
2175   %c4 = arith.constant 4 : index
2176   %c5 = arith.constant 5 : index
2177   %c6 = arith.constant 6 : index
2178   %c80 = arith.constant 80 : index
2179   %0 = fir.undefined index
2180   %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>>
2181   fir.call @bar1(%3) : (!fir.box<!fir.array<?xf32>>) -> ()
2182   return
2184 //CHECK-LABEL:  llvm.func @bar1
2185 //CHECK-LABEL:  llvm.func @test_rebox_1
2186 //CHECK-SAME:   %[[ARG0:.*]]: !llvm.ptr<struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<2 x array<3 x i64>>)>>
2187 //CHECK:    %[[ONE_1:.*]] = llvm.mlir.constant(1 : i32) : i32
2188 //CHECK:    %[[RESULT_BOX_REF:.*]] = llvm.alloca %[[ONE_1]] x !llvm.struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr<struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>>
2189 //CHECK:    %[[THREE:.*]] = llvm.mlir.constant(3 : index) : i64
2190 //CHECK:    %[[FOUR:.*]] = llvm.mlir.constant(4 : index) : i64
2191 //CHECK:    %[[FIVE:.*]] = llvm.mlir.constant(5 : index) : i64
2192 //CHECK:    %[[SIX:.*]] = llvm.mlir.constant(6 : index) : i64
2193 //CHECK:    %[[EIGHTY:.*]] = llvm.mlir.constant(80 : index) : i64
2194 //CHECK:    %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr<f32>
2195 //CHECK:    %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
2196 //CHECK:    %[[ELEM_SIZE_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr<f32> to i64
2197 //CHECK:    %[[FLOAT_TYPE:.*]] = llvm.mlir.constant(27 : i32) : i32
2198 //CHECK:    %[[RBOX:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2199 //CHECK:    %[[RBOX_TMP1:.*]] = llvm.insertvalue %[[ELEM_SIZE_I64]], %[[RBOX]][1] : !llvm.struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2200 //CHECK:    %[[CFI_VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32
2201 //CHECK:    %[[RBOX_TMP2:.*]] = llvm.insertvalue %[[CFI_VERSION]], %[[RBOX_TMP1]][2] : !llvm.struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2202 //CHECK:    %[[RANK:.*]] = llvm.mlir.constant(1 : i32) : i32
2203 //CHECK:    %[[RANK_I8:.*]] = llvm.trunc %[[RANK]] : i32 to i8
2204 //CHECK:    %[[RBOX_TMP3:.*]] = llvm.insertvalue %[[RANK_I8]], %[[RBOX_TMP2]][3] : !llvm.struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2205 //CHECK:    %[[FLOAT_TYPE_I8:.*]] = llvm.trunc %[[FLOAT_TYPE]] : i32 to i8
2206 //CHECK:    %[[RBOX_TMP4:.*]] = llvm.insertvalue %[[FLOAT_TYPE_I8]], %[[RBOX_TMP3]][4] : !llvm.struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2207 //CHECK:    %[[OTHER_ATTR:.*]] = llvm.mlir.constant(0 : i32) : i32
2208 //CHECK:    %[[OTHER_ATTR_I8:.*]] = llvm.trunc %[[OTHER_ATTR]] : i32 to i8
2209 //CHECK:    %[[RBOX_TMP5:.*]] = llvm.insertvalue %[[OTHER_ATTR_I8]], %[[RBOX_TMP4]][5] : !llvm.struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2210 //CHECK:    %[[ADDENDUM:.*]] = llvm.mlir.constant(0 : i32) : i32
2211 //CHECK:    %[[ADDENDUM_I8:.*]] = llvm.trunc %[[ADDENDUM]] : i32 to i8
2212 //CHECK:    %[[RBOX_TMP6:.*]] = llvm.insertvalue %[[ADDENDUM_I8]], %[[RBOX_TMP5]][6] : !llvm.struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2213 //CHECK:    %[[DIM1_STRIDE_REF:.*]] = llvm.getelementptr %[[ARG0]][0, 7, 0, 2] : (!llvm.ptr<struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<2 x array<3 x i64>>)>>) -> !llvm.ptr<i64>
2214 //CHECK:    %[[DIM1_STRIDE:.*]] = llvm.load %[[DIM1_STRIDE_REF]] : !llvm.ptr<i64>
2215 //CHECK:    %[[DIM2_STRIDE_REF:.*]] = llvm.getelementptr %[[ARG0]][0, 7, 1, 2] : (!llvm.ptr<struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<2 x array<3 x i64>>)>>) -> !llvm.ptr<i64>
2216 //CHECK:    %[[DIM2_STRIDE:.*]] = llvm.load %[[DIM2_STRIDE_REF]] : !llvm.ptr<i64>
2217 //CHECK:    %[[SOURCE_ARRAY_PTR:.*]] = llvm.getelementptr %[[ARG0]][0, 0] : (!llvm.ptr<struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<2 x array<3 x i64>>)>>) -> !llvm.ptr<ptr<f32>>
2218 //CHECK:    %[[SOURCE_ARRAY:.*]] = llvm.load %[[SOURCE_ARRAY_PTR]] : !llvm.ptr<ptr<f32>>
2219 //CHECK:    %[[ZERO_ELEMS:.*]] = llvm.mlir.constant(0 : i64) : i64
2220 //CHECK:    %[[SOURCE_ARRAY_I8PTR:.*]] = llvm.bitcast %[[SOURCE_ARRAY]] : !llvm.ptr<f32> to !llvm.ptr<i8>
2221 //CHECK:    %[[DIM1_LB_DIFF:.*]] = llvm.sub %[[FIVE]], %[[THREE]]  : i64
2222 //CHECK:    %[[DIM1_LB_OFFSET:.*]] = llvm.mul %[[DIM1_LB_DIFF]], %[[DIM1_STRIDE]]  : i64
2223 //CHECK:    %[[RESULT_PTR_DIM1:.*]] = llvm.getelementptr %[[SOURCE_ARRAY_I8PTR]][%[[DIM1_LB_OFFSET]]] : (!llvm.ptr<i8>, i64) -> !llvm.ptr<i8>
2224 //CHECK:    %[[DIM2_LB_DIFF:.*]] = llvm.sub %[[SIX]], %[[FOUR]]  : i64
2225 //CHECK:    %[[DIM2_LB_OFFSET:.*]] = llvm.mul %[[DIM2_LB_DIFF]], %[[DIM2_STRIDE]]  : i64
2226 //CHECK:    %[[RESULT_PTR_I8:.*]] = llvm.getelementptr %[[RESULT_PTR_DIM1]][%[[DIM2_LB_OFFSET]]] : (!llvm.ptr<i8>, i64) -> !llvm.ptr<i8>
2227 //CHECK:    %[[RESULT_UB_LB_DIFF:.*]] = llvm.sub %[[EIGHTY]], %[[SIX]]  : i64
2228 //CHECK:    %[[RESULT_UB_LB_DIFF_PLUS_STRIDE:.*]] = llvm.add %[[RESULT_UB_LB_DIFF]], %[[THREE]]  : i64
2229 //CHECK:    %[[RESULT_NELEMS_TMP:.*]] = llvm.sdiv %[[RESULT_UB_LB_DIFF_PLUS_STRIDE]], %[[THREE]]  : i64
2230 //CHECK:    %[[RESULT_IF_NON_ZERO:.*]] = llvm.icmp "sgt" %[[RESULT_NELEMS_TMP]], %[[ZERO_ELEMS]] : i64
2231 //CHECK:    %[[RESULT_NELEMS:.*]] = llvm.select %[[RESULT_IF_NON_ZERO]], %[[RESULT_NELEMS_TMP]], %[[ZERO_ELEMS]] : i1, i64
2232 //CHECK:    %[[RESULT_STRIDE:.*]] = llvm.mul %[[THREE]], %[[DIM2_STRIDE]]  : i64
2233 //CHECK:    %[[RESULT_LB:.*]] = llvm.mlir.constant(1 : i64) : i64
2234 //CHECK:    %[[RBOX_TMP7_1:.*]] = llvm.insertvalue %[[RESULT_LB]], %[[RBOX_TMP6]][7, 0, 0] : !llvm.struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2235 //CHECK:    %[[RBOX_TMP7_2:.*]] = llvm.insertvalue %[[RESULT_NELEMS]], %[[RBOX_TMP7_1]][7, 0, 1] : !llvm.struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2236 //CHECK:    %[[RBOX_TMP7_3:.*]] = llvm.insertvalue %[[RESULT_STRIDE]], %[[RBOX_TMP7_2]][7, 0, 2] : !llvm.struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2237 //CHECK:    %[[RESULT_PTR_F32:.*]] = llvm.bitcast %[[RESULT_PTR_I8]] : !llvm.ptr<i8> to !llvm.ptr<f32>
2238 //CHECK:    %[[RESULT_BOX:.*]] = llvm.insertvalue %[[RESULT_PTR_F32]], %[[RBOX_TMP7_3]][0] : !llvm.struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2239 //CHECK:    llvm.store %[[RESULT_BOX]], %[[RESULT_BOX_REF]] : !llvm.ptr<struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>>
2240 //CHECK:    llvm.call @bar1(%[[RESULT_BOX_REF]]) : (!llvm.ptr<struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>>) -> ()
2243 // 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.
2244 func.func private @bar(!fir.box<!fir.array<?x!fir.char<1,?>>>)
2245 func.func @foo(%arg0: !fir.box<!fir.array<?x!fir.type<t{i:i32,c:!fir.char<1,10>}>>>) {
2246   %c3_i64 = arith.constant 3 : i64
2247   %c60_i64 = arith.constant 60 : i64
2248   %c9_i64 = arith.constant 9 : i64
2249   %c1_i64 = arith.constant 1 : i64
2250   %c7_i64 = arith.constant 7 : i64
2251   %0 = fir.field_index c, !fir.type<t{i:i32,c:!fir.char<1,10>}>
2252   %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,?>>>
2253   fir.call @bar(%1) : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> ()
2254   return
2257 //CHECK: llvm.func @bar(!llvm.ptr<struct<(ptr<i8>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>>) attributes {sym_visibility = "private"}
2258 //CHECK-LABEL: llvm.func @foo
2259 //CHECK-SAME: %[[ARG0:.*]]: !llvm.ptr<struct<(ptr<struct<"t", (i32, array<10 x i8>)>>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr<i8>, array<1 x i64>)>>
2260 //CHECK:   %[[ONE:.*]] = llvm.mlir.constant(1 : i32) : i32
2261 //CHECK:   %[[RESULT_BOX_REF:.*]] = llvm.alloca %[[ONE]] x !llvm.struct<(ptr<i8>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr<struct<(ptr<i8>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>>
2262 //CHECK:   %[[RESULT_LB:.*]] = llvm.mlir.constant(3 : i64) : i64
2263 //CHECK:   %[[RESULT_UB:.*]] = llvm.mlir.constant(60 : i64) : i64
2264 //CHECK:   %[[RESULT_STRIDE:.*]] = llvm.mlir.constant(9 : i64) : i64
2265 //CHECK:   %[[COMPONENT_OFFSET_1:.*]] = llvm.mlir.constant(1 : i64) : i64
2266 //CHECK:   %[[ELEM_COUNT:.*]] = llvm.mlir.constant(7 : i64) : i64
2267 //CHECK:   %[[TYPE_CHAR:.*]] = llvm.mlir.constant(40 : i32) : i32
2268 //CHECK:   %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr<i8>
2269 //CHECK:   %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
2270 //CHECK:   %[[CHAR_SIZE:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr<i8> to i64
2271 //CHECK:   %[[ELEM_SIZE:.*]] = llvm.mul %[[CHAR_SIZE]], %[[ELEM_COUNT]]
2272 //CHECK:   %[[RBOX_TMP1:.*]] = llvm.insertvalue %[[ELEM_SIZE]], %{{.*}}[1] : !llvm.struct<(ptr<i8>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2273 //CHECK:   %[[RBOX_TMP2:.*]] = llvm.insertvalue %{{.*}}, %[[RBOX_TMP1]][2] : !llvm.struct<(ptr<i8>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2274 //CHECK:   %[[RANK:.*]] = llvm.mlir.constant(1 : i32) : i32
2275 //CHECK:   %[[RANK_I8:.*]] = llvm.trunc %[[RANK]] : i32 to i8
2276 //CHECK:   %[[RBOX_TMP3:.*]] = llvm.insertvalue %[[RANK_I8]], %[[RBOX_TMP2]][3] : !llvm.struct<(ptr<i8>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2277 //CHECK:   %[[TYPE_CHAR_I8:.*]] = llvm.trunc %[[TYPE_CHAR]] : i32 to i8
2278 //CHECK:   %[[RBOX_TMP4:.*]] = llvm.insertvalue %[[TYPE_CHAR_I8]], %[[RBOX_TMP3]][4] : !llvm.struct<(ptr<i8>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2279 //CHECK:   %[[RBOX_TMP5:.*]] = llvm.insertvalue %{{.*}}, %[[RBOX_TMP4]][5] : !llvm.struct<(ptr<i8>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2280 //CHECK:   %[[ADDENDUM:.*]] = llvm.mlir.constant(0 : i32) : i32
2281 //CHECK:   %[[ADDENDUM_I8:.*]] = llvm.trunc %[[ADDENDUM]] : i32 to i8
2282 //CHECK:   %[[RBOX_TMP6:.*]] = llvm.insertvalue %[[ADDENDUM_I8]], %[[RBOX_TMP5]][6] : !llvm.struct<(ptr<i8>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2283 //CHECK:   %[[SRC_STRIDE_PTR:.*]] = llvm.getelementptr %[[ARG0]][0, 7, 0, 2] : (!llvm.ptr<struct<(ptr<struct<"t", (i32, array<10 x i8>)>>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr<i8>, array<1 x i64>)>>) -> !llvm.ptr<i64>
2284 //CHECK:   %[[SRC_STRIDE:.*]] = llvm.load %[[SRC_STRIDE_PTR]] : !llvm.ptr<i64>
2285 //CHECK:   %[[SRC_ARRAY_PTR:.*]] = llvm.getelementptr %[[ARG0]][0, 0] : (!llvm.ptr<struct<(ptr<struct<"t", (i32, array<10 x i8>)>>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr<i8>, array<1 x i64>)>>) -> !llvm.ptr<ptr<struct<"t", (i32, array<10 x i8>)>>>
2286 //CHECK:   %[[SRC_ARRAY:.*]] = llvm.load %[[SRC_ARRAY_PTR]] : !llvm.ptr<ptr<struct<"t", (i32, array<10 x i8>)>>>
2287 //CHECK:   %[[ZERO_6:.*]] = llvm.mlir.constant(0 : i64) : i64
2288 //CHECK:   %[[SRC_CAST:.*]] = llvm.bitcast %[[SRC_ARRAY]] : !llvm.ptr<struct<"t", (i32, array<10 x i8>)>> to !llvm.ptr<struct<"t", (i32, array<10 x i8>)>>
2289 //CHECK:   %[[COMPONENT:.*]] = llvm.getelementptr %[[SRC_CAST]][%[[ZERO_6]], 1, %[[COMPONENT_OFFSET_1]]] : (!llvm.ptr<struct<"t", (i32, array<10 x i8>)>>, i64, i64) -> !llvm.ptr<i8>
2290 //CHECK:   %[[COMPONENT_CAST:.*]] = llvm.bitcast %[[COMPONENT]] : !llvm.ptr<i8> to !llvm.ptr<i8>
2291 //CHECK:   %[[SRC_LB:.*]] = llvm.mlir.constant(1 : i64) : i64
2292 //CHECK:   %[[RESULT_TMP0:.*]] = llvm.sub %[[RESULT_LB]], %[[SRC_LB]]  : i64
2293 //CHECK:   %[[RESULT_OFFSET_START:.*]] = llvm.mul %[[RESULT_TMP0]], %[[SRC_STRIDE]]  : i64
2294 //CHECK:   %[[RESULT_PTR_I8:.*]] = llvm.getelementptr %[[COMPONENT_CAST]][%[[RESULT_OFFSET_START]]] : (!llvm.ptr<i8>, i64) -> !llvm.ptr<i8>
2295 //CHECK:   %[[RESULT_TMP1:.*]] = llvm.sub %[[RESULT_UB]], %[[RESULT_LB]]  : i64
2296 //CHECK:   %[[RESULT_TMP2:.*]] = llvm.add %[[RESULT_TMP1]], %[[RESULT_STRIDE]]  : i64
2297 //CHECK:   %[[RESULT_TMP3:.*]] = llvm.sdiv %[[RESULT_TMP2]], %[[RESULT_STRIDE]]  : i64
2298 //CHECK:   %[[RESULT_TMP_PRED:.*]] = llvm.icmp "sgt" %[[RESULT_TMP3]], %[[ZERO_6]] : i64
2299 //CHECK:   %[[RESULT_NELEMS:.*]] = llvm.select %[[RESULT_TMP_PRED]], %[[RESULT_TMP3]], %[[ZERO_6]] : i1, i64
2300 //CHECK:   %[[RESULT_TOTAL_STRIDE:.*]] = llvm.mul %[[RESULT_STRIDE]], %[[SRC_STRIDE]]  : i64
2301 //CHECK:   %[[RESULT_LB:.*]] = llvm.mlir.constant(1 : i64) : i64
2302 //CHECK:   %[[RBOX_TMP7_1:.*]] = llvm.insertvalue %[[RESULT_LB]], %[[RBOX_TMP6]][7, 0, 0] : !llvm.struct<(ptr<i8>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2303 //CHECK:   %[[RBOX_TMP7_2:.*]] = llvm.insertvalue %[[RESULT_NELEMS]], %[[RBOX_TMP7_1]][7, 0, 1] : !llvm.struct<(ptr<i8>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2304 //CHECK:   %[[RBOX_TMP7_3:.*]] = llvm.insertvalue %[[RESULT_TOTAL_STRIDE]], %[[RBOX_TMP7_2]][7, 0, 2] : !llvm.struct<(ptr<i8>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2305 //CHECK:   %[[RESULT_PTR_CAST:.*]] = llvm.bitcast %[[RESULT_PTR_I8]] : !llvm.ptr<i8> to !llvm.ptr<i8>
2306 //CHECK:   %[[RESULT_BOX:.*]] = llvm.insertvalue %[[RESULT_PTR_CAST]], %[[RBOX_TMP7_3]][0] : !llvm.struct<(ptr<i8>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
2307 //CHECK:   llvm.store %[[RESULT_BOX]], %[[RESULT_BOX_REF]] : !llvm.ptr<struct<(ptr<i8>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>>
2308 //CHECK:   llvm.call @bar(%[[RESULT_BOX_REF]]) : (!llvm.ptr<struct<(ptr<i8>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>>) -> ()
2309 //CHECK:   llvm.return
2310 //CHECK: }
2312 // -----
2314 // Test `fir.coordinate_of` conversion (items inside `!fir.box`)
2316 // 1. COMPLEX TYPE (`fir.complex` is a special case)
2317 // Complex type wrapped in `fir.ref`
2318 func.func @coordinate_ref_complex(%arg0: !fir.ref<!fir.complex<16>>) {
2319   %arg1 = llvm.mlir.constant(0 : i32) : i32
2320   %p = fir.coordinate_of %arg0, %arg1 : (!fir.ref<!fir.complex<16>>, i32) -> !fir.ref<f32>
2321   return
2323 // CHECK-LABEL: llvm.func @coordinate_ref_complex
2324 // CHECK-SAME:  %[[ARG0:.*]]: !llvm.ptr<struct<(f128, f128)>>
2325 // CHECK:    %{{.*}} = llvm.getelementptr %[[ARG0]][0, 0] : (!llvm.ptr<struct<(f128, f128)>>) -> !llvm.ptr<f32>
2326 // CHECK-NEXT:    llvm.return
2328 // -----
2330 // Complex type wrapped in `fir.box`
2331 func.func @coordinate_box_complex(%arg0: !fir.box<!fir.complex<16>>) {
2332   %arg1 = llvm.mlir.constant(0 : i32) : i32
2333   %p = fir.coordinate_of %arg0, %arg1 : (!fir.box<!fir.complex<16>>, i32) -> !fir.ref<f32>
2334   return
2336 // CHECK-LABEL: llvm.func @coordinate_box_complex
2337 // CHECK-SAME:  %[[BOX:.*]]: !llvm.ptr<struct<(ptr<struct<(f128, f128)>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>
2338 // CHECK:    %{{.*}} = llvm.getelementptr %[[BOX]][0, 0] : (!llvm.ptr<struct<(ptr<struct<(f128, f128)>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>) -> !llvm.ptr<f32>
2339 // CHECK-NEXT:    llvm.return
2341 // -----
2343 // Test `fir.coordinate_of` conversion (items inside `!fir.box`)
2345 // 2. BOX TYPE (objects wrapped in `fir.box`)
2346 // Derived type - basic case (1 index)
2347 func.func @coordinate_box_derived_1(%arg0: !fir.box<!fir.type<derived_1{field_1:i32, field_2:i32}>>) {
2348   %idx = fir.field_index field_2, !fir.type<derived_1{field_1:i32, field_2:i32}>
2349   %q = fir.coordinate_of %arg0, %idx : (!fir.box<!fir.type<derived_1{field_1:i32, field_2:i32}>>, !fir.field) -> !fir.ref<i32>
2350   return
2352 // CHECK-LABEL: llvm.func @coordinate_box_derived_1
2353 // CHECK-SAME: %[[BOX:.*]]: !llvm.ptr<struct<(ptr<struct<"derived_1", (i32, i32)>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr<i8>, array<1 x i64>)>>)
2354 // CHECK:    %[[COORDINATE:.*]] = llvm.mlir.constant(1 : i32) : i32
2355 // CHECK:    %[[DERIVED_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 0] : (!llvm.ptr<struct<(ptr<struct<"derived_1", (i32, i32)>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr<i8>, array<1 x i64>)>>) -> !llvm.ptr<ptr<struct<"derived_1", (i32, i32)>>>
2356 // CHECK:    %[[DERIVED_VAL:.*]] = llvm.load %[[DERIVED_ADDR]] : !llvm.ptr<ptr<struct<"derived_1", (i32, i32)>>>
2357 // CHECK:    %[[DERIVED_CAST:.*]] = llvm.bitcast %[[DERIVED_VAL]] : !llvm.ptr<struct<"derived_1", (i32, i32)>> to !llvm.ptr<struct<"derived_1", (i32, i32)>>
2358 // CHECK:    %[[SUBOBJECT_ADDR:.*]] = llvm.getelementptr %[[DERIVED_CAST]][0, 1] : (!llvm.ptr<struct<"derived_1", (i32, i32)>>) -> !llvm.ptr<i32>
2359 // CHECK:    %[[CAST_TO_I8_PTR:.*]] = llvm.bitcast %[[SUBOBJECT_ADDR]] : !llvm.ptr<i32> to !llvm.ptr<i8>
2360 // CHECK:    %{{.*}} = llvm.bitcast %[[CAST_TO_I8_PTR]] : !llvm.ptr<i8> to !llvm.ptr<i32>
2361 // CHECK-NEXT:    llvm.return
2363 // Derived type - basic case (2 indices)
2364 func.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}>>) {
2365   %idx0 = fir.field_index field_1, !fir.type<derived_2{field_1:!fir.type<another_derived{inner1:i32, inner2:f32}>, field_2:i32}>
2366   %idx1 = fir.field_index inner2, !fir.type<another_derived{inner1:i32, inner2:f32}>
2367   %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>
2368   return
2371 // CHECK-LABEL: llvm.func @coordinate_box_derived_2
2372 // CHECK-SAME: (%[[BOX:.*]]: !llvm.ptr<struct<(ptr<struct<"derived_2", (struct<"another_derived", (i32, f32)>, i32)>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr<i8>, array<1 x i64>)>>)
2373 // CHECK-NEXT:    %[[C0_0:.*]] = llvm.mlir.constant(0 : i32) : i32
2374 // CHECK-NEXT:    %[[C1:.*]] = llvm.mlir.constant(1 : i32) : i32
2375 // CHECK:         %[[DERIVED_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 0] : (!llvm.ptr<struct<(ptr<struct<"derived_2", (struct<"another_derived", (i32, f32)>, i32)>>, i{{.*}}, i{{.*}}32, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr<i8>, array<1 x i64>)>>) -> !llvm.ptr<ptr<struct<"derived_2", (struct<"another_derived", (i32, f32)>, i32)>>>
2376 // CHECK-NEXT:    %[[DERIVED_VAL:.*]] = llvm.load %[[DERIVED_ADDR]] : !llvm.ptr<ptr<struct<"derived_2", (struct<"another_derived", (i32, f32)>, i32)>>>
2377 // CHECK-NEXT:    %[[DERIVED_CAST_I8_PTR:.*]] = llvm.bitcast %[[DERIVED_VAL]] : !llvm.ptr<struct<"derived_2", (struct<"another_derived", (i32, f32)>, i32)>> to !llvm.ptr<struct<"derived_2", (struct<"another_derived", (i32, f32)>, i32)>>
2378 // CHECK-NEXT:    %[[ANOTHER_DERIVED_ADDR:.*]] = llvm.getelementptr %[[DERIVED_CAST_I8_PTR]][0, 0] : (!llvm.ptr<struct<"derived_2", (struct<"another_derived", (i32, f32)>, i32)>>) -> !llvm.ptr<struct<"another_derived", (i32, f32)>>
2379 // CHECK-NEXT:    %[[ANOTHER_DERIVED_ADDR_AS_VOID_PTR:.*]] = llvm.bitcast %[[ANOTHER_DERIVED_ADDR]] : !llvm.ptr<struct<"another_derived", (i32, f32)>> to !llvm.ptr<i8>
2380 // CHECK-NEXT:    %[[ANOTHER_DERIVED_RECAST:.*]] = llvm.bitcast %[[ANOTHER_DERIVED_ADDR_AS_VOID_PTR]] : !llvm.ptr<i8> to !llvm.ptr<struct<"another_derived", (i32, f32)>>
2381 // CHECK-NEXT:    %[[SUBOBJECT_ADDR:.*]] = llvm.getelementptr %[[ANOTHER_DERIVED_RECAST]][0, 1] : (!llvm.ptr<struct<"another_derived", (i32, f32)>>) -> !llvm.ptr<f32>
2382 // CHECK-NEXT:    %[[SUBOBJECT_AS_VOID_PTR:.*]] = llvm.bitcast %[[SUBOBJECT_ADDR]] : !llvm.ptr<f32> to !llvm.ptr<i8>
2383 // CHECK-NEXT:    %{{.*}} = llvm.bitcast %[[SUBOBJECT_AS_VOID_PTR]] : !llvm.ptr<i8> to !llvm.ptr<i32>
2384 // CHECK-NEXT:   llvm.return
2386 // TODO: Derived type - special case with `fir.len_param_index`
2388 // -----
2390 // Test `fir.coordinate_of` conversion (items inside `!fir.box`)
2392 // 3. BOX TYPE - `fir.array` wrapped in `fir.box`
2393 // `fir.array` inside a `fir.box` (1d)
2394 func.func @coordinate_box_array_1d(%arg0: !fir.box<!fir.array<10 x f32>>, %arg1: index) {
2395   %p = fir.coordinate_of %arg0, %arg1 : (!fir.box<!fir.array<10 x f32>>, index) -> !fir.ref<f32>
2396   return
2398 // CHECK-LABEL: llvm.func @coordinate_box_array_1d
2399 // CHECK-SAME:  %[[BOX:.*]]: !llvm.ptr<struct<(ptr<array<10 x f32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>>
2400 // CHECK-SAME:  %[[COORDINATE:.*]]: i64
2401 // There's only one box here. Its index is `0`. Generate it.
2402 // CHECK:       %[[ARRAY_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 0] : (!llvm.ptr<struct<(ptr<array<10 x f32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>>) -> !llvm.ptr<ptr<array<10 x f32>>>
2403 // CHECK-NEXT:  %[[ARRAY_OBJECT:.*]] = llvm.load %[[ARRAY_ADDR]] : !llvm.ptr<ptr<array<10 x f32>>>
2404 // CHECK-NEXT:  %[[OFFSET_INIT:.*]] = llvm.mlir.constant(0 : i64) : i64
2405 // Index of the 1st CFI_dim_t object (corresonds the the 1st dimension)
2406 // CHECK-NEXT:  %[[DIM_1_MEM_STRIDE_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 7, 0, 2] : (!llvm.ptr<struct<(ptr<array<10 x f32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>>) -> !llvm.ptr<i64>
2407 // CHECK-NEXT:  %[[DIM_1_MEM_STRIDE_VAL:.*]] = llvm.load %[[DIM_1_MEM_STRIDE_ADDR]] : !llvm.ptr<i64>
2408 // CHECK-NEXT:  %[[BYTE_OFFSET:.*]] = llvm.mul %[[COORDINATE]], %[[DIM_1_MEM_STRIDE_VAL]]  : i64
2409 // CHECK-NEXT:  %[[SUBOJECT_OFFSET:.*]] = llvm.add %[[BYTE_OFFSET]], %[[OFFSET_INIT]]  : i64
2410 // CHECK-NEXT:  %[[ARRAY_OBJECT_AS_VOID_PTR:.*]] = llvm.bitcast %[[ARRAY_OBJECT]] : !llvm.ptr<array<10 x f32>> to !llvm.ptr<i8>
2411 // CHECK-NEXT:  %[[SUBOBJECT_ADDR:.*]] = llvm.getelementptr %[[ARRAY_OBJECT_AS_VOID_PTR]][%[[SUBOJECT_OFFSET]]] : (!llvm.ptr<i8>, i64) -> !llvm.ptr<i8>
2412 // CHECK-NEXT:  %[[RETURN_VAL:.*]] = llvm.bitcast %[[SUBOBJECT_ADDR]] : !llvm.ptr<i8> to !llvm.ptr<f32>
2413 // CHECK-NEXT:  llvm.return
2415 // `fir.array` inside a `fir.box` (1d) - dynamic size
2416 func.func @coordinate_of_box_dynamic_array_1d(%arg0: !fir.box<!fir.array<? x f32>>, %arg1: index) {
2417   %p = fir.coordinate_of %arg0, %arg1 : (!fir.box<!fir.array<? x f32>>, index) -> !fir.ref<f32>
2418   return
2420 // CHECK-LABEL: llvm.func @coordinate_of_box_dynamic_array_1d
2421 // CHECK-SAME:  %[[BOX:.*]]: !llvm.ptr<struct<(ptr<f32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>>
2422 // CHECK-SAME:  %[[COORDINATE:.*]]: i64
2423 // CHECK-NEXT:  %[[ARRAY_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 0] : (!llvm.ptr<struct<(ptr<f32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>>) -> !llvm.ptr<ptr<f32>>
2424 // CHECK-NEXT:  %[[ARRAY_OBJECT:.*]] = llvm.load %[[ARRAY_ADDR]] : !llvm.ptr<ptr<f32>>
2425 // CHECK-NEXT:  %[[OFFSET_INIT:.*]] = llvm.mlir.constant(0 : i64) : i64
2426 // Index of the 1st CFI_dim_t object (corresonds the the 1st dimension)
2427 // CHECK-NEXT:  %[[DIM_1_MEM_STRIDE_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 7, 0, 2] : (!llvm.ptr<struct<(ptr<f32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>>) -> !llvm.ptr<i64>
2428 // CHECK-NEXT:  %[[DIM_1_MEM_STRIDE_VAL:.*]] = llvm.load %[[DIM_1_MEM_STRIDE_ADDR]] : !llvm.ptr<i64>
2429 // CHECK-NEXT:  %[[BYTE_OFFSET:.*]] = llvm.mul %[[COORDINATE]], %[[DIM_1_MEM_STRIDE_VAL]]  : i64
2430 // CHECK-NEXT:  %[[SUBOJECT_OFFSET:.*]] = llvm.add %[[BYTE_OFFSET]], %[[OFFSET_INIT]]  : i64
2431 // CHECK-NEXT:  %[[ARRAY_OBJECT_AS_VOID_PTR:.*]] = llvm.bitcast %[[ARRAY_OBJECT]] : !llvm.ptr<f32> to !llvm.ptr<i8>
2432 // CHECK-NEXT:  %[[SUBOBJECT_ADDR:.*]] = llvm.getelementptr %[[ARRAY_OBJECT_AS_VOID_PTR]][%[[SUBOJECT_OFFSET]]] : (!llvm.ptr<i8>, i64) -> !llvm.ptr<i8>
2433 // CHECK-NEXT:  %[[RETURN_VAL:.*]] = llvm.bitcast %[[SUBOBJECT_ADDR]] : !llvm.ptr<i8> to !llvm.ptr<f32>
2434 // CHECK-NEXT:  llvm.return
2436 // -----
2438 // `fir.array` inside a `fir.box` (2d)
2439 func.func @coordinate_box_array_2d(%arg0: !fir.box<!fir.array<10 x 10 x f32>>, %arg1: index, %arg2: index) {
2440   %p = fir.coordinate_of %arg0, %arg1, %arg2 : (!fir.box<!fir.array<10 x 10 x f32>>, index, index) -> !fir.ref<f32>
2441   return
2443 // CHECK-LABEL: llvm.func @coordinate_box_array_2d
2444 // CHECK-SAME: %[[BOX:.*]]: !llvm.ptr<struct<(ptr<array<10 x array<10 x f32>>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>>
2445 // CHECK-SAME: %[[COORDINATE_1:.*]]: i64, %[[COORDINATE_2:.*]]: i64)
2446 // CHECK-NEXT:  %[[ARRAY_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 0] : (!llvm.ptr<struct<(ptr<array<10 x array<10 x f32>>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>>) -> !llvm.ptr<ptr<array<10 x array<10 x f32>>>>
2447 // CHECK-NEXT:  %[[ARRAY_OBJECT:.*]] = llvm.load %[[ARRAY_ADDR]] : !llvm.ptr<ptr<array<10 x array<10 x f32>>>>
2448 // CHECK-NEXT:  %[[OFFSET_INIT:.*]] = llvm.mlir.constant(0 : i64) : i64
2449 // Index of the 1st CFI_dim_t object (corresonds the the 1st dimension)
2450 // CHECK-NEXT:  %[[DIM_1_MEM_STRIDE_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 7, 0, 2] : (!llvm.ptr<struct<(ptr<array<10 x array<10 x f32>>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>>) -> !llvm.ptr<i64>
2451 // CHECK-NEXT:  %[[DIM_1_MEM_STRIDE_VAL:.*]] = llvm.load %[[DIM_1_MEM_STRIDE_ADDR]] : !llvm.ptr<i64>
2452 // CHECK-NEXT:  %[[BYTE_OFFSET_1:.*]] = llvm.mul %[[COORDINATE_1]], %[[DIM_1_MEM_STRIDE_VAL]]  : i64
2453 // CHECK-NEXT:  %[[SUBOBJECT_OFFSET_1:.*]] = llvm.add %[[BYTE_OFFSET]], %[[OFFSET_INIT]]  : i64
2454 // Index of the 1st CFI_dim_t object (corresonds the the 2nd dimension)
2455 // CHECK-NEXT:  %[[DIM_2_MEM_STRIDE_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 7, 1, 2] : (!llvm.ptr<struct<(ptr<array<10 x array<10 x f32>>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>>) -> !llvm.ptr<i64>
2456 // CHECK-NEXT:  %[[DIM_2_MEM_STRIDE_VAL:.*]] = llvm.load %[[DIM_2_MEM_STRIDE_ADDR]] : !llvm.ptr<i64>
2457 // CHECK-NEXT:  %[[BYTE_OFFSET_2:.*]] = llvm.mul %[[COORDINATE_2]], %[[DIM_2_MEM_STRIDE_VAL]]  : i64
2458 // CHECK-NEXT:  %[[SUBOBJECT_OFFSET_2:.*]] = llvm.add %[[BYTE_OFFSET_2]], %[[SUBOBJECT_OFFSET_1]]  : i64
2459 // CHECK-NEXT:  %[[ARRAY_OBJECT_AS_VOID_PTR:.*]] = llvm.bitcast %[[ARRAY_OBJECT]] : !llvm.ptr<array<10 x array<10 x f32>>> to !llvm.ptr<i8>
2460 // CHECK-NEXT:  %[[SUBOBJECT_ADDR:.*]] = llvm.getelementptr %[[ARRAY_OBJECT_AS_VOID_PTR]][%[[SUBOBJECT_OFFSET_2]]] : (!llvm.ptr<i8>, i64) -> !llvm.ptr<i8>
2461 // CHECK-NEXT:  %[[RETURN_VAL:.*]] = llvm.bitcast %[[SUBOBJECT_ADDR]] : !llvm.ptr<i8> to !llvm.ptr<f32>
2462 // CHECK-NEXT:  llvm.return
2464 // -----
2466 // Test `fir.coordinate_of` conversion (items inside `!fir.box`)
2468 // 4. BOX TYPE - `fir.derived` inside `fir.array`
2469 func.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) {
2470    %idx0 = fir.field_index field_2, !fir.type<derived_3{field_1:f32, field_2:f32}>
2471    %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>
2472    return
2474 // CHECK-LABEL:   llvm.func @coordinate_box_derived_inside_array(
2475 // CHECK-SAME:    %[[BOX:.*]]: !llvm.ptr<struct<(ptr<array<10 x struct<"derived_3", (f32, f32)>>>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr<i8>, array<1 x i64>)>>,
2476 // CHECK-SAME:    %[[COORDINATE_1:.*]]: i64) {
2477 // CHECK:         %[[VAL_6:.*]] = llvm.getelementptr %[[BOX]]{{\[}}0, 0] : (!llvm.ptr<struct<(ptr<array<10 x struct<"derived_3", (f32, f32)>>>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr<i8>, array<1 x i64>)>>) -> !llvm.ptr<ptr<array<10 x struct<"derived_3", (f32, f32)>>>>
2478 // CHECK:         %[[ARRAY:.*]] = llvm.load %[[VAL_6]] : !llvm.ptr<ptr<array<10 x struct<"derived_3", (f32, f32)>>>>
2479 // CHECK:         %[[VAL_8:.*]] = llvm.mlir.constant(0 : i64) : i64
2480 // CHECK:         %[[VAL_13:.*]] = llvm.getelementptr %[[BOX]][0, 7, 0, 2] : (!llvm.ptr<struct<(ptr<array<10 x struct<"derived_3", (f32, f32)>>>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr<i8>, array<1 x i64>)>>) -> !llvm.ptr<i64>
2481 // CHECK:         %[[VAL_14:.*]] = llvm.load %[[VAL_13]] : !llvm.ptr<i64>
2482 // CHECK:         %[[VAL_15:.*]] = llvm.mul %[[COORDINATE_1]], %[[VAL_14]]  : i64
2483 // CHECK:         %[[OFFSET:.*]] = llvm.add %[[VAL_15]], %[[VAL_8]]  : i64
2484 // CHECK:         %[[VAL_17:.*]] = llvm.bitcast %[[ARRAY]] : !llvm.ptr<array<10 x struct<"derived_3", (f32, f32)>>> to !llvm.ptr<i8>
2485 // CHECK:         %[[VAL_18:.*]] = llvm.getelementptr %[[VAL_17]][%[[OFFSET]]] : (!llvm.ptr<i8>, i64) -> !llvm.ptr<i8>
2486 // CHECK:         %[[DERIVED:.*]] = llvm.bitcast %[[VAL_18]] : !llvm.ptr<i8> to !llvm.ptr<struct<"derived_3", (f32, f32)>>
2487 // CHECK:         %[[VAL_20:.*]] = llvm.getelementptr %[[DERIVED]][0, 1] : (!llvm.ptr<struct<"derived_3", (f32, f32)>>) -> !llvm.ptr<f32>
2488 // CHECK:         %[[VAL_21:.*]] = llvm.bitcast %[[VAL_20]] : !llvm.ptr<f32> to !llvm.ptr<i8>
2489 // CHECK:         %[[VAL_22:.*]] = llvm.bitcast %[[VAL_21]] : !llvm.ptr<i8> to !llvm.ptr<f32>
2490 // CHECK:         llvm.return
2492 // -----
2494 // Test `fir.coordinate_of` conversion (items inside `!fir.ref`)
2496 // 5.1. `fir.array`
2497 func.func @coordinate_array_unknown_size_1d(%arg0: !fir.ref<!fir.array<? x i32>>, %arg1 : index) {
2498    %q = fir.coordinate_of %arg0, %arg1 : (!fir.ref<!fir.array<? x i32>>, index) -> !fir.ref<i32>
2499    return
2501 // CHECK-LABEL:   llvm.func @coordinate_array_unknown_size_1d(
2502 // CHECK-SAME:    %[[VAL_0:.*]]: !llvm.ptr<i32>,
2503 // CHECK-SAME:    %[[VAL_1:.*]]: i64) {
2504 // CHECK:           %[[VAL_2:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}%[[VAL_1]]] : (!llvm.ptr<i32>, i64) -> !llvm.ptr<i32>
2505 // CHECK:           llvm.return
2506 // CHECK:         }
2508 // -----
2510 func.func @coordinate_array_known_size_1d(%arg0: !fir.ref<!fir.array<10 x i32>>, %arg1 : index) {
2511    %q = fir.coordinate_of %arg0, %arg1 : (!fir.ref<!fir.array<10 x i32>>, index) -> !fir.ref<i32>
2512    return
2514 // CHECK-LABEL:   llvm.func @coordinate_array_known_size_1d(
2515 // CHECK-SAME:    %[[VAL_0:.*]]: !llvm.ptr<array<10 x i32>>,
2516 // CHECK-SAME:    %[[VAL_1:.*]]: i64) {
2517 // CHECK:           %[[VAL_3:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}0, %[[VAL_1]]] : (!llvm.ptr<array<10 x i32>>, i64) -> !llvm.ptr<i32>
2518 // CHECK:           llvm.return
2519 // CHECK:         }
2521 // -----
2523 func.func @coordinate_array_known_size_2d_get_i32(%arg0: !fir.ref<!fir.array<10 x 10 x i32>>, %arg1 : index, %arg2 : index) {
2524    %q = fir.coordinate_of %arg0, %arg1, %arg2 : (!fir.ref<!fir.array<10 x 10 x i32>>, index, index) -> !fir.ref<i32>
2525    return
2527 // CHECK-LABEL:   llvm.func @coordinate_array_known_size_2d_get_i32(
2528 // CHECK-SAME:    %[[VAL_0:.*]]: !llvm.ptr<array<10 x array<10 x i32>>>,
2529 // CHECK-SAME:    %[[VAL_1:.*]]: i64,
2530 // CHECK-SAME:    %[[VAL_2:.*]]: i64) {
2531 // CHECK:           %[[VAL_4:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}0, %[[VAL_2]], %[[VAL_1]]] : (!llvm.ptr<array<10 x array<10 x i32>>>, i64, i64) -> !llvm.ptr<i32>
2532 // CHECK:           llvm.return
2533 // CHECK:         }
2535 // -----
2537 func.func @coordinate_array_known_size_2d_get_array(%arg0: !fir.ref<!fir.array<10 x 10 x i32>>, %arg1 : index) {
2538    %q = fir.coordinate_of %arg0, %arg1 : (!fir.ref<!fir.array<10 x 10 x i32>>, index) -> !fir.ref<!fir.array<10 x i32>>
2539    return
2541 // CHECK-LABEL:   llvm.func @coordinate_array_known_size_2d_get_array(
2542 // CHECK-SAME:    %[[VAL_0:.*]]: !llvm.ptr<array<10 x array<10 x i32>>>,
2543 // CHECK-SAME:    %[[VAL_1:.*]]: i64) {
2544 // CHECK:           %[[VAL_3:.*]] = llvm.getelementptr %[[VAL_0]][0, %[[VAL_1]]] : (!llvm.ptr<array<10 x array<10 x i32>>>, i64) -> !llvm.ptr<array<10 x i32>>
2545 // CHECK:           llvm.return
2546 // CHECK:         }
2548 // -----
2550 // 5.2. `fir.derived`
2551 func.func @coordinate_ref_derived(%arg0: !fir.ref<!fir.type<dervied_4{field_1:i32, field_2:i32}>>) {
2552   %idx = fir.field_index field_2, !fir.type<dervied_4{field_1:i32, field_2:i32}>
2553   %q = fir.coordinate_of %arg0, %idx : (!fir.ref<!fir.type<dervied_4{field_1:i32, field_2:i32}>>, !fir.field) -> !fir.ref<i32>
2554   return
2556 // CHECK-LABEL:   llvm.func @coordinate_ref_derived(
2557 // CHECK-SAME:    %[[VAL_0:.*]]: !llvm.ptr<struct<"dervied_4", (i32, i32)>>) {
2558 // CHECK:           %[[VAL_3:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}0, 1] : (!llvm.ptr<struct<"dervied_4", (i32, i32)>>) -> !llvm.ptr<i32>
2559 // CHECK:           llvm.return
2560 // CHECK:         }
2562 // -----
2564 func.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}>>) {
2565   %idx0 = fir.field_index field_1, !fir.type<derived_5{field_1:!fir.type<nested_derived{inner1:i32, inner2:f32}>, field_2:i32}>
2566   %idx1 = fir.field_index inner2, !fir.type<nested_derived{inner1:i32, inner2:f32}>
2567   %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>
2568   return
2570 // CHECK-LABEL:   llvm.func @coordinate_ref_derived_nested(
2571 // CHECK-SAME:    %[[VAL_0:.*]]: !llvm.ptr<struct<"derived_5", (struct<"nested_derived", (i32, f32)>, i32)>>) {
2572 // CHECK:           %[[VAL_4:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}0, 0, 1] : (!llvm.ptr<struct<"derived_5", (struct<"nested_derived", (i32, f32)>, i32)>>) -> !llvm.ptr<i32>
2573 // CHECK:           llvm.return
2574 // CHECK:         }
2576 // -----
2578 // 5.3 `fir.char`
2579 func.func @test_coordinate_of_char(%arr : !fir.ref<!fir.char<10, 2>>) {
2580   %1 = arith.constant 10 : i32
2581   %2 = fir.coordinate_of %arr, %1 : (!fir.ref<!fir.char<10, 2>>, i32) -> !fir.ref<!fir.char<10>>
2582   return
2584 // CHECK-LABEL:   llvm.func @test_coordinate_of_char(
2585 // CHECK-SAME:    %[[VAL_0:.*]]: !llvm.ptr<array<2 x i80>>) {
2586 // CHECK:           %[[VAL_1:.*]] = llvm.mlir.constant(10 : i32) : i32
2587 // CHECK:           %[[VAL_2:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}%[[VAL_1]]] : (!llvm.ptr<array<2 x i80>>, i32) -> !llvm.ptr<array<1 x i80>>
2588 // CHECK:           llvm.return
2589 // CHECK:         }
2591 // -----
2593 // 5.4 `mlir.tuple`
2594 func.func @test_coordinate_of_tuple(%tup : !fir.ref<tuple<!fir.ref<i32>>>) {
2595   %1 = arith.constant 0 : i32
2596   %2 = fir.coordinate_of %tup, %1 : (!fir.ref<tuple<!fir.ref<i32>>>, i32) -> !fir.ref<i32>
2597   return
2599 // CHECK-LABEL:   llvm.func @test_coordinate_of_tuple(
2600 // CHECK-SAME:                                     %[[VAL_0:.*]]: !llvm.ptr<struct<(ptr<i32>)>>) {
2601 // CHECK:           %[[VAL_3:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}0, 0] : (!llvm.ptr<struct<(ptr<i32>)>>) -> !llvm.ptr<i32>
2602 // CHECK:           llvm.return
2603 // CHECK:         }
2605 // -----
2607 // Test `fir.coordinate_of` conversion - items inside `!fir.ptr`. This should
2608 // be almost identical to `!fir.ref` (i.e. it's the same code path in the code
2609 // gen). Instead of duplicating the tests, only one for sanity-checking is added.
2611 // 6.1. `fir.array`
2612 func.func @coordinate_array_unknown_size_1d(%arg0: !fir.ptr<!fir.array<? x i32>>, %arg1 : index) {
2613    %q = fir.coordinate_of %arg0, %arg1 : (!fir.ptr<!fir.array<? x i32>>, index) -> !fir.ref<i32>
2614    return
2616 // CHECK-LABEL:   llvm.func @coordinate_array_unknown_size_1d(
2617 // CHECK-SAME:    %[[VAL_0:.*]]: !llvm.ptr<i32>,
2618 // CHECK-SAME:    %[[VAL_1:.*]]: i64) {
2619 // CHECK:           %[[VAL_2:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}%[[VAL_1]]] : (!llvm.ptr<i32>, i64) -> !llvm.ptr<i32>
2620 // CHECK:           llvm.return
2621 // CHECK:         }