diff --git a/mlir/docs/Dialects/LLVM.md b/mlir/docs/Dialects/LLVM.md --- a/mlir/docs/Dialects/LLVM.md +++ b/mlir/docs/Dialects/LLVM.md @@ -105,6 +105,7 @@ are produced by dedicated operations that have the corresponding semantics: [`llvm.mlir.constant`](#llvmmlirconstant-mlirllvmconstantop), [`llvm.mlir.undef`](#llvmmlirundef-mlirllvmundefop), +[`llvm.mlir.poison`](#llvmmlirpoison-mlirllvmpoisonop), [`llvm.mlir.null`](#llvmmlirnull-mlirllvmnullop). Note how these operations are prefixed with `mlir.` to indicate that they don't belong to LLVM IR but are only necessary to model it in MLIR. The values produced by these operations are diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -1652,7 +1652,7 @@ Unlike LLVM IR, MLIR does not have first-class undefined values. Such values must be created as SSA values using `llvm.mlir.undef`. This operation has no operands or attributes. It creates an undefined value of the specified LLVM - IR dialect type wrapping an LLVM IR structure type. + IR dialect type. Example: @@ -1666,6 +1666,28 @@ let assemblyFormat = "attr-dict `:` type($res)"; } +def LLVM_PoisonOp : LLVM_Op<"mlir.poison", [Pure]>, + LLVM_Builder<"$res = llvm::PoisonValue::get($_resultType);"> { + let summary = "Creates a poison value of LLVM dialect type."; + let description = [{ + Unlike LLVM IR, MLIR does not have first-class poison values. Such values + must be created as SSA values using `llvm.mlir.poison`. This operation has + no operands or attributes. It creates a poison value of the specified LLVM + IR dialect type. + + Example: + + ```mlir + // Create a poison value for a structure with a 32-bit integer followed + // by a float. + %0 = llvm.mlir.poison : !llvm.struct<(i32, f32)> + ``` + }]; + let results = (outs LLVM_Type:$res); + let builders = [LLVM_OneResultOpBuilder]; + let assemblyFormat = "attr-dict `:` type($res)"; +} + def LLVM_ConstantOp : LLVM_Op<"mlir.constant", [Pure, ConstantLike]>, LLVM_Builder<[{$res = getLLVMConstant($_resultType, $value, $_location, diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -1036,6 +1036,12 @@ return builder.create(loc, type).getResult(); } + // Convert poison. + if (auto *poisonVal = dyn_cast(constant)) { + Type type = convertType(poisonVal->getType()); + return builder.create(loc, type).getResult(); + } + // Convert undef. if (auto *undefVal = dyn_cast(constant)) { Type type = convertType(undefVal->getType()); diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir --- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir +++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir @@ -438,10 +438,14 @@ func.func @useFreezeOp(%arg0: i32) { // CHECK: = llvm.freeze %[[ARG0:.*]] : i32 %0 = llvm.freeze %arg0 : i32 - // CHECK: %[[x:.*]] = llvm.mlir.undef : i8 + // CHECK: %[[UNDEF:.*]] = llvm.mlir.undef : i8 %1 = llvm.mlir.undef : i8 - // CHECK: = llvm.freeze %[[x]] : i8 + // CHECK: = llvm.freeze %[[UNDEF]] : i8 %2 = llvm.freeze %1 : i8 + // CHECK: %[[POISON:.*]] = llvm.mlir.poison : i8 + %3 = llvm.mlir.poison : i8 + // CHECK: = llvm.freeze %[[POISON]] : i8 + %4 = llvm.freeze %3 : i8 return } diff --git a/mlir/test/Target/LLVMIR/Import/instructions.ll b/mlir/test/Target/LLVMIR/Import/instructions.ll --- a/mlir/test/Target/LLVMIR/Import/instructions.ll +++ b/mlir/test/Target/LLVMIR/Import/instructions.ll @@ -523,10 +523,13 @@ ; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]] define void @freeze(i32 %arg1) { ; CHECK: %[[UNDEF:[0-9]+]] = llvm.mlir.undef : i64 + ; CHECK: %[[POISON:[0-9]+]] = llvm.mlir.poison : i16 ; CHECK: llvm.freeze %[[ARG1]] : i32 ; CHECK: llvm.freeze %[[UNDEF]] : i64 + ; CHECK: llvm.freeze %[[POISON]] : i16 %1 = freeze i32 %arg1 %2 = freeze i64 undef + %3 = freeze i16 poison ret void } diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir --- a/mlir/test/Target/LLVMIR/llvmir.mlir +++ b/mlir/test/Target/LLVMIR/llvmir.mlir @@ -1618,6 +1618,9 @@ %1 = llvm.mlir.undef : i32 // CHECK: freeze i32 undef %2 = llvm.freeze %1 : i32 + %3 = llvm.mlir.poison : i32 + // CHECK: freeze i32 poison + %4 = llvm.freeze %3 : i32 llvm.return }