[Mlir-commits] [mlir] [mlir][llvm] Implement ConstantLike for ZeroOp, UndefOp, PoisonOp (PR #93617)
Guy David
llvmlistbot at llvm.org
Tue May 28 15:15:04 PDT 2024
https://github.com/guy-david created https://github.com/llvm/llvm-project/pull/93617
These act as constants and should be propagated whenever possible. It is safe to do so for mlir.undef and mlir.poison because they remain "dirty" through out their lifetime and can be duplicated, merged, etc. per the LangRef.
If the direction is alright, I'll tend to the broken tests.
>From f0d835e24e1c28be2d636586550cef89565f1ade Mon Sep 17 00:00:00 2001
From: Guy David <guy.david at nextsilicon.com>
Date: Wed, 29 May 2024 01:12:10 +0300
Subject: [PATCH] [mlir][llvm] Implement ConstantLike for ZeroOp, UndefOp,
PoisonOp
These act as constants and should be propagated whenever possible.
It is safe to do so for mlir.undef and mlir.poison because they remain
"dirty" through out their lifetime and can be duplicated, merged, etc.
per the LangRef.
Signed-off-by: Guy David <guy.david at nextsilicon.com>
---
.../mlir/Dialect/LLVMIR/LLVMAttrDefs.td | 14 +++++
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td | 9 ++-
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 32 ++++++++++
.../test/Dialect/LLVMIR/constant-folding.mlir | 60 +++++++++++++++++++
4 files changed, 112 insertions(+), 3 deletions(-)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index 535cf8dfd2ced..0fab9cbab9226 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -1037,4 +1037,18 @@ def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features">
let genVerifyDecl = 1;
}
+//===----------------------------------------------------------------------===//
+// UndefAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_UndefAttr : LLVM_Attr<"Undef", "undef"> {
+}
+
+//===----------------------------------------------------------------------===//
+// PoisonAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_PoisonAttr : LLVM_Attr<"Poison", "poison"> {
+}
+
#endif // LLVMIR_ATTRDEFS
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 84e67d2c11dbd..f6f907f39a4b4 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -1522,7 +1522,7 @@ def LLVM_NoneTokenOp
let assemblyFormat = "attr-dict `:` type($res)";
}
-def LLVM_UndefOp : LLVM_Op<"mlir.undef", [Pure]>,
+def LLVM_UndefOp : LLVM_Op<"mlir.undef", [Pure, ConstantLike]>,
LLVM_Builder<"$res = llvm::UndefValue::get($_resultType);"> {
let summary = "Creates an undefined value of LLVM dialect type.";
let description = [{
@@ -1541,9 +1541,10 @@ def LLVM_UndefOp : LLVM_Op<"mlir.undef", [Pure]>,
let results = (outs LLVM_Type:$res);
let builders = [LLVM_OneResultOpBuilder];
let assemblyFormat = "attr-dict `:` type($res)";
+ let hasFolder = 1;
}
-def LLVM_PoisonOp : LLVM_Op<"mlir.poison", [Pure]>,
+def LLVM_PoisonOp : LLVM_Op<"mlir.poison", [Pure, ConstantLike]>,
LLVM_Builder<"$res = llvm::PoisonValue::get($_resultType);"> {
let summary = "Creates a poison value of LLVM dialect type.";
let description = [{
@@ -1563,10 +1564,11 @@ def LLVM_PoisonOp : LLVM_Op<"mlir.poison", [Pure]>,
let results = (outs LLVM_Type:$res);
let builders = [LLVM_OneResultOpBuilder];
let assemblyFormat = "attr-dict `:` type($res)";
+ let hasFolder = 1;
}
def LLVM_ZeroOp
- : LLVM_Op<"mlir.zero", [Pure]>,
+ : LLVM_Op<"mlir.zero", [Pure, ConstantLike]>,
LLVM_Builder<"$res = llvm::Constant::getNullValue($_resultType);">
{
let summary = "Creates a zero-initialized value of LLVM dialect type.";
@@ -1588,6 +1590,7 @@ def LLVM_ZeroOp
let builders = [LLVM_OneResultOpBuilder];
let assemblyFormat = "attr-dict `:` type($res)";
let hasVerifier = 1;
+ let hasFolder = 1;
}
def LLVM_ConstantOp
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index dcf3f3b52a606..22db7f21db299 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -2555,6 +2555,26 @@ Region *LLVMFuncOp::getCallableRegion() {
return &getBody();
}
+//===----------------------------------------------------------------------===//
+// UndefOp.
+//===----------------------------------------------------------------------===//
+
+/// Fold a undef operation to a dedicated undef attribute.
+OpFoldResult LLVM::UndefOp::fold(FoldAdaptor) {
+ // TODO: Should fold into ub::*?
+ return mlir::LLVM::UndefAttr::get(getContext());
+}
+
+//===----------------------------------------------------------------------===//
+// PoisonOp.
+//===----------------------------------------------------------------------===//
+
+/// Fold a poison operation to a dedicated poison attribute.
+OpFoldResult LLVM::PoisonOp::fold(FoldAdaptor) {
+ // TODO: Should fold to ub::PoisonAttr?
+ return mlir::LLVM::PoisonAttr::get(getContext());
+}
+
//===----------------------------------------------------------------------===//
// ZeroOp.
//===----------------------------------------------------------------------===//
@@ -2568,6 +2588,13 @@ LogicalResult LLVM::ZeroOp::verify() {
return success();
}
+OpFoldResult LLVM::ZeroOp::fold(FoldAdaptor) {
+ OpFoldResult result = Builder(getContext()).getZeroAttr(getType());
+ if (result)
+ return result;
+ return TypeAttr::get(getType());
+}
+
//===----------------------------------------------------------------------===//
// ConstantOp.
//===----------------------------------------------------------------------===//
@@ -3276,6 +3303,11 @@ Operation *LLVMDialect::materializeConstant(OpBuilder &builder, Attribute value,
if (auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
if (isa<LLVM::LLVMPointerType>(type))
return builder.create<LLVM::AddressOfOp>(loc, type, symbol);
+ // If this was folded from an llvm.mlir.zero operation, it should be
+ // materialized as such. However, prefer to use llvm.mlir.constant for
+ // compatible types.
+ if (isZeroAttribute(value) && !LLVM::ConstantOp::isBuildableWith(value, type))
+ return builder.create<LLVM::ZeroOp>(loc, type);
// Otherwise try materializing it as a regular llvm.mlir.constant op.
return LLVM::ConstantOp::materialize(builder, value, type, loc);
}
diff --git a/mlir/test/Dialect/LLVMIR/constant-folding.mlir b/mlir/test/Dialect/LLVMIR/constant-folding.mlir
index 454126321eb97..3b2125b859cb1 100644
--- a/mlir/test/Dialect/LLVMIR/constant-folding.mlir
+++ b/mlir/test/Dialect/LLVMIR/constant-folding.mlir
@@ -101,3 +101,63 @@ llvm.func @addressof_blocks(%arg: i1) -> !llvm.ptr {
}
llvm.mlir.global constant @foo() : i32
+
+// -----
+
+// CHECK-LABEL: llvm.func @zero
+llvm.func @zero() {
+ // CHECK-NEXT: %[[ZERO:.+]] = llvm.mlir.zero : i32
+ %zero1 = llvm.mlir.zero : i32
+ %zero2 = llvm.mlir.zero : i32
+ // CHECK-NEXT: llvm.call @foo(%[[ZERO]], %[[ZERO]])
+ llvm.call @foo(%zero1, %zero2) : (i32, i32) -> ()
+ // CHECK-NEXT: llvm.return
+ llvm.return
+}
+
+llvm.func @foo(i32, i32)
+
+// -----
+
+// CHECK-LABEL: llvm.func @null_pointer
+llvm.func @null_pointer() {
+ // CHECK-NEXT: %[[NULLPTR:.+]] = llvm.mlir.zero : !llvm.ptr
+ %nullptr1 = llvm.mlir.zero : !llvm.ptr
+ %nullptr2 = llvm.mlir.zero : !llvm.ptr
+ // CHECK-NEXT: llvm.call @foo(%[[NULLPTR]], %[[NULLPTR]])
+ llvm.call @foo(%nullptr1, %nullptr2) : (!llvm.ptr, !llvm.ptr) -> ()
+ // CHECK-NEXT: llvm.return
+ llvm.return
+}
+
+llvm.func @foo(!llvm.ptr, !llvm.ptr)
+
+// -----
+
+// CHECK-LABEL: llvm.func @undef
+llvm.func @undef() {
+ // CHECK-NEXT: %[[UNDEF:.+]] = llvm.mlir.undef : i32
+ %undef1 = llvm.mlir.undef : i32
+ %undef2 = llvm.mlir.undef : i32
+ // CHECK-NEXT: llvm.call @foo(%[[UNDEF]], %[[UNDEF]])
+ llvm.call @foo(%undef1, %undef2) : (i32, i32) -> ()
+ // CHECK-NEXT: llvm.return
+ llvm.return
+}
+
+llvm.func @foo(i32, i32)
+
+// -----
+
+// CHECK-LABEL: llvm.func @poison
+llvm.func @poison() {
+ // CHECK-NEXT: %[[POISON:.+]] = llvm.mlir.poison : i32
+ %poison1 = llvm.mlir.poison : i32
+ %poison2 = llvm.mlir.poison : i32
+ // CHECK-NEXT: llvm.call @foo(%[[POISON]], %[[POISON]])
+ llvm.call @foo(%poison1, %poison2) : (i32, i32) -> ()
+ // CHECK-NEXT: llvm.return
+ llvm.return
+}
+
+llvm.func @foo(i32, i32)
More information about the Mlir-commits
mailing list