Problem definitions
Right now, the LLVM IR importer cannot translate some of the complex constants, llvm::ConstantStruct
and llvm::ConstantAggregateZero
for instance, into LLVMIR dialect directives. For example, give the following type definitions and global constants:
%sub_struct = type {i8, i32}
%my_struct = type {i8, i32, %sub_struct, i16*, i8*}
@.str.8 = private unnamed_addr constant [5 x i8] c"unix\00"
@my_global = global %my_struct {i8 8, i32 7,
%sub_struct zeroinitializer, i16* null,
i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.8, i32 0, i32 0)}
The importer will bail out with an error message: “error: unhandled constant {i8 8, i32 7, …}”.
The problem in this motivating example was three-fold:
- The importer doesn’t recognize
zeroinitializer
, which is represented byllvm::ConstantAggregateZero
. - The importer cannot translate
llvm::ConstantAggregate
with heterogeneous element types. Namely,llvm::ConstantStruct
. Ideally, we should able to translate such concept intoArrayAttr
(which actually doesn’t require elements to have same types). - Although the importer is able to handle
null
(i.e.llvm::ConstantPointerNull
) and inlinedi8* getelementptr
(i.e.llvm::ConstantExpr
), both of them will be lowered into an operation. Assuming we want to translate the enclosing struct into anArrayAttr
as mentioned in the first bullet point. The existing translation scheme cannot be fitted in (becauseArrayAttr
only takesAttribute
rather thanValue
). Let’s say we want to go the other way around and reuse existing translation schemes (translate into operations), we will lower the initialization for the aggregate constant into a region. I couldn’t find a proper way to express “per-element” initialization on the aggregate constant in the current codebase (are we going to usellvm.getelementptr
to access individual elements and assign operation values to them, which are part of a constant?).
Proposed solutions
I would like to propose several fixes in the LLVM dialect to address these problems. For the first issue, I’m planning to add a new attribute, #llvm.zeroinitializer<ty>
, where ty
is an aggregate type. In the motivating example above, ty
will be %sub_struct
.
The second and third issue are more tricky. There are 2 kinds of solutions for them:
- Adding a new operation
llvm.mlir.constant.aggregate
that takesLLVMType
values as operands and generate a constant with aggregate type. For instance, the motivating example can be rewritten into (some syntax and type annotations has been omitted):
llvm.mlir.global constant @my_global() : !llvm.struct<my_struct> {
%0 = llvm.mlir.constant(8) : i8
%1 = llvm.mlir.constant(7) : i8
%2 = llvm.mlir.constant(#llvm.zeroinitializer<"llvm.struct<sub_struct>">) : !llvm.struct<sub_struct>
%3 = llvm.mlir.null : !llvm.ptr<i16>
%4 = llvm.getelementptr ...
%final = llvm.mlir.constant.aggregate(%0, %1, %2, %3, %4)
llvm.return %final
}
Pros: Reuse the existing translation code for llvm::ConstantExpr
and llvm::CosntantPointerNull
.
Cons: The ConstantLike
trait – which requires zero (value) operand – cannot be applied on llvm.mlir.constant.aggregate
, this might hinder some optimization opportunities. The initialization region also look cumbersome.
- Create attributes for
llvm::ConstantPointerNull
(e.g.#llvm.null<ty>
) and every kinds ofllvm::ConstantExpr
(e.g.#llvm.constexpr.getelementptr<...>
), such that they can be composed (with other attributes) into a singleArrayAttr
. For instane, the motivating example can be rewritten into (some syntax and type annotations has been omitted):
llvm.mlir.global constant @my_global([8, 7, #llvm.zeroinitializer<"llvm.struct<sub_struct>">, #llvm.null<"llvm.ptr<i16>">, #llvm.constexpr.getelementptr<...>]) : !llvm.struct<my_struct>
Pros: Both llvm::ConstantPointerNull
and llvm::ConstantExpr
are constants in the LLVM land, so it modeling them as constants – namely, attributes – in MLIR flows much naturally.
Cons: There are many kinds of llvm::ConstantExpr
.
Personally, I’m lean toward solution 2 since its downside (I can think of now) is not really an issue once we have a consensus here.
Your comments on this topic are much appreciated!