Skip to content

fir.embox lowering produces invalid IR during fir-to-llvm-ir #118066

@matthias-springer

Description

@matthias-springer

I noticed that fir-opt produces invalid IR during fir-to-llvm-ir for this test case:

fir.global @elesize_of_embox constant : i32 {
  %0 = fir.zero_bits !fir.ptr<i32>
  %1 = fir.embox %0 : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>>
  %2 = fir.box_elesize %1 : (!fir.box<!fir.ptr<i32>>) -> i32
  fir.has_value %2 : i32
}

Error:

within split at llvm-project/flang/test/Fir/convert-to-llvm.fir:1 offset :4:8: error: ops with side effects not allowed in global initializers
  %2 = fir.box_elesize %1 : (!fir.box<!fir.ptr<i32>>) -> i32
       ^
within split at llvm-project/flang/test/Fir/convert-to-llvm.fir:1 offset :4:8: note: see current operation: %23 = "llvm.load"(%22) <{ordering = 0 : i64}> : (!llvm.ptr) -> i64

This is only one of the problems. The dialect conversion also inserts an unrealized_conversion_cast from the boxed ptr to a bare pointer:

  "llvm.mlir.global"() <{addr_space = 0 : i32, constant, global_type = i32, linkage = #llvm.linkage<external>, sym_name = "elesize_of_embox", visibility_ = 0 : i64}> ({
    %0 = "llvm.mlir.zero"() : () -> !llvm.ptr
    %1 = "llvm.mlir.constant"() <{value = 9 : i32}> : () -> i32
    %2 = "llvm.mlir.zero"() : () -> !llvm.ptr
    %3 = "llvm.getelementptr"(%2) <{elem_type = i32, rawConstantIndices = array<i32: 1>}> : (!llvm.ptr) -> !llvm.ptr
    %4 = "llvm.ptrtoint"(%3) : (!llvm.ptr) -> i64

    ...

    %20 = "llvm.insertvalue"(%19, %0) <{position = array<i64: 0>}> : (!llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>, !llvm.ptr) -> !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>
    %21 = "builtin.unrealized_conversion_cast"(%20) : (!llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) -> !llvm.ptr
    %22 = "llvm.getelementptr"(%21) <{elem_type = !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>, rawConstantIndices = array<i32: 0, 1>}> : (!llvm.ptr) -> !llvm.ptr
    %23 = "llvm.load"(%22) <{ordering = 0 : i64}> : (!llvm.ptr) -> i64
    %24 = "llvm.trunc"(%23) <{overflowFlags = #llvm.overflow<none>}> : (i64) -> i32
    "llvm.return"(%24) : (i32) -> ()
  }) : () -> ()

Within fir.global, fir.embox does not lower to an alloca but directly to an LLVM struct. This does not compose with the remaining ops. I think the only thing you can do is returning the boxed values via fir.has_value, everything else produces invalid IR.

Why does Flang store the LLVM struct that is generated during "boxing" in a stack allocation? Why not use the LLVM struct directly? In the type converter, there is convertBoxType and convertBoxTypeAsStruct. Why isn't convertBoxTypeAsStruct used everywhere?

Context: I am looking at this as part of refactorings of the dialect conversion framework and ran into issues with HasValueOpConversion and InsertValueOpConversion (in CodeGen.cpp). Ideally, these should run with a type converter. I'm trying to understand what's the right solution here.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions