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