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