Skip to content

Commit 4bce270

Browse files
authored
[mlir][llvm] Implement ConstantLike for ZeroOp, UndefOp, PoisonOp (#93690)
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 <[email protected]>
1 parent 6a3982f commit 4bce270

File tree

9 files changed

+210
-82
lines changed

9 files changed

+210
-82
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,4 +1037,25 @@ def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features">
10371037
let genVerifyDecl = 1;
10381038
}
10391039

1040+
//===----------------------------------------------------------------------===//
1041+
// UndefAttr
1042+
//===----------------------------------------------------------------------===//
1043+
1044+
/// Folded into from LLVM::UndefOp.
1045+
def LLVM_UndefAttr : LLVM_Attr<"Undef", "undef">;
1046+
1047+
//===----------------------------------------------------------------------===//
1048+
// PoisonAttr
1049+
//===----------------------------------------------------------------------===//
1050+
1051+
/// Folded into from LLVM::PoisonOp.
1052+
def LLVM_PoisonAttr : LLVM_Attr<"Poison", "poison">;
1053+
1054+
//===----------------------------------------------------------------------===//
1055+
// ZeroAttr
1056+
//===----------------------------------------------------------------------===//
1057+
1058+
/// Folded into from LLVM::ZeroOp.
1059+
def LLVM_ZeroAttr : LLVM_Attr<"Zero", "zero">;
1060+
10401061
#endif // LLVMIR_ATTRDEFS

mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,7 +1522,7 @@ def LLVM_NoneTokenOp
15221522
let assemblyFormat = "attr-dict `:` type($res)";
15231523
}
15241524

1525-
def LLVM_UndefOp : LLVM_Op<"mlir.undef", [Pure]>,
1525+
def LLVM_UndefOp : LLVM_Op<"mlir.undef", [Pure, ConstantLike]>,
15261526
LLVM_Builder<"$res = llvm::UndefValue::get($_resultType);"> {
15271527
let summary = "Creates an undefined value of LLVM dialect type.";
15281528
let description = [{
@@ -1541,9 +1541,10 @@ def LLVM_UndefOp : LLVM_Op<"mlir.undef", [Pure]>,
15411541
let results = (outs LLVM_Type:$res);
15421542
let builders = [LLVM_OneResultOpBuilder];
15431543
let assemblyFormat = "attr-dict `:` type($res)";
1544+
let hasFolder = 1;
15441545
}
15451546

1546-
def LLVM_PoisonOp : LLVM_Op<"mlir.poison", [Pure]>,
1547+
def LLVM_PoisonOp : LLVM_Op<"mlir.poison", [Pure, ConstantLike]>,
15471548
LLVM_Builder<"$res = llvm::PoisonValue::get($_resultType);"> {
15481549
let summary = "Creates a poison value of LLVM dialect type.";
15491550
let description = [{
@@ -1563,10 +1564,11 @@ def LLVM_PoisonOp : LLVM_Op<"mlir.poison", [Pure]>,
15631564
let results = (outs LLVM_Type:$res);
15641565
let builders = [LLVM_OneResultOpBuilder];
15651566
let assemblyFormat = "attr-dict `:` type($res)";
1567+
let hasFolder = 1;
15661568
}
15671569

15681570
def LLVM_ZeroOp
1569-
: LLVM_Op<"mlir.zero", [Pure]>,
1571+
: LLVM_Op<"mlir.zero", [Pure, ConstantLike]>,
15701572
LLVM_Builder<"$res = llvm::Constant::getNullValue($_resultType);">
15711573
{
15721574
let summary = "Creates a zero-initialized value of LLVM dialect type.";
@@ -1588,6 +1590,7 @@ def LLVM_ZeroOp
15881590
let builders = [LLVM_OneResultOpBuilder];
15891591
let assemblyFormat = "attr-dict `:` type($res)";
15901592
let hasVerifier = 1;
1593+
let hasFolder = 1;
15911594
}
15921595

15931596
def LLVM_ConstantOp

mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2555,6 +2555,24 @@ Region *LLVMFuncOp::getCallableRegion() {
25552555
return &getBody();
25562556
}
25572557

2558+
//===----------------------------------------------------------------------===//
2559+
// UndefOp.
2560+
//===----------------------------------------------------------------------===//
2561+
2562+
/// Fold an undef operation to a dedicated undef attribute.
2563+
OpFoldResult LLVM::UndefOp::fold(FoldAdaptor) {
2564+
return LLVM::UndefAttr::get(getContext());
2565+
}
2566+
2567+
//===----------------------------------------------------------------------===//
2568+
// PoisonOp.
2569+
//===----------------------------------------------------------------------===//
2570+
2571+
/// Fold a poison operation to a dedicated poison attribute.
2572+
OpFoldResult LLVM::PoisonOp::fold(FoldAdaptor) {
2573+
return LLVM::PoisonAttr::get(getContext());
2574+
}
2575+
25582576
//===----------------------------------------------------------------------===//
25592577
// ZeroOp.
25602578
//===----------------------------------------------------------------------===//
@@ -2568,6 +2586,15 @@ LogicalResult LLVM::ZeroOp::verify() {
25682586
return success();
25692587
}
25702588

2589+
/// Fold a zero operation to a builtin zero attribute when possible and fall
2590+
/// back to a dedicated zero attribute.
2591+
OpFoldResult LLVM::ZeroOp::fold(FoldAdaptor) {
2592+
OpFoldResult result = Builder(getContext()).getZeroAttr(getType());
2593+
if (result)
2594+
return result;
2595+
return LLVM::ZeroAttr::get(getContext());
2596+
}
2597+
25712598
//===----------------------------------------------------------------------===//
25722599
// ConstantOp.
25732600
//===----------------------------------------------------------------------===//
@@ -3271,11 +3298,18 @@ LogicalResult LLVMDialect::verifyRegionResultAttribute(Operation *op,
32713298

32723299
Operation *LLVMDialect::materializeConstant(OpBuilder &builder, Attribute value,
32733300
Type type, Location loc) {
3274-
// If this was folded from an llvm.mlir.addressof operation, it should be
3275-
// materialized as such.
3301+
// If this was folded from an operation other than llvm.mlir.constant, it
3302+
// should be materialized as such. Note that an llvm.mlir.zero may fold into
3303+
// a builtin zero attribute and thus will materialize as a llvm.mlir.constant.
32763304
if (auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
32773305
if (isa<LLVM::LLVMPointerType>(type))
32783306
return builder.create<LLVM::AddressOfOp>(loc, type, symbol);
3307+
if (isa<LLVM::UndefAttr>(value))
3308+
return builder.create<LLVM::UndefOp>(loc, type);
3309+
if (isa<LLVM::PoisonAttr>(value))
3310+
return builder.create<LLVM::PoisonOp>(loc, type);
3311+
if (isa<LLVM::ZeroAttr>(value))
3312+
return builder.create<LLVM::ZeroOp>(loc, type);
32793313
// Otherwise try materializing it as a regular llvm.mlir.constant op.
32803314
return LLVM::ConstantOp::materialize(builder, value, type, loc);
32813315
}

0 commit comments

Comments
 (0)