[llvm] Introducing a new ISD::POISON SDNode to represent the poison value in the IR. (PR #125883)
zhijian lin via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 19 07:04:20 PST 2025
https://github.com/diggerlin updated https://github.com/llvm/llvm-project/pull/125883
>From fa4eafd19c1f5daf44d7f17dd27dbbcbf6d10868 Mon Sep 17 00:00:00 2001
From: zhijian <zhijian at ca.ibm.com>
Date: Wed, 5 Feb 2025 17:04:32 +0000
Subject: [PATCH 1/2] introduce a new ISDNODE POISON
---
llvm/include/llvm/CodeGen/ISDOpcodes.h | 3 +++
llvm/include/llvm/CodeGen/SelectionDAG.h | 3 +++
llvm/include/llvm/CodeGen/SelectionDAGNodes.h | 16 ++++++++++++++--
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 3 ++-
llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 17 +++++++++++++++++
.../SelectionDAG/LegalizeIntegerTypes.cpp | 2 ++
.../SelectionDAG/LegalizeVectorTypes.cpp | 3 +++
llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 9 +++++++++
.../SelectionDAG/SelectionDAGBuilder.cpp | 2 +-
.../CodeGen/SelectionDAG/SelectionDAGDumper.cpp | 1 +
.../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 1 +
11 files changed, 56 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index 665c4d6baad80..ff3c96eaa08bd 100644
--- a/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -217,6 +217,9 @@ enum NodeType {
/// UNDEF - An undefined node.
UNDEF,
+ /// POISON - A poison node.
+ POISON,
+
/// FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or
/// is evaluated to UNDEF), or returns VAL otherwise. Note that each
/// read of UNDEF can yield different value, but FREEZE(UNDEF) cannot.
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index aa0dfbe666cde..8984d33559c58 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -1130,6 +1130,9 @@ class SelectionDAG {
return getNode(ISD::UNDEF, SDLoc(), VT);
}
+ /// Return an POISON node. POISON does not have a useful SDLoc.
+ SDValue getPoison(EVT VT) { return getNode(ISD::POISON, SDLoc(), VT); }
+
/// Return a node that represents the runtime scaling 'MulImm * RuntimeVL'.
SDValue getVScale(const SDLoc &DL, EVT VT, APInt MulImm,
bool ConstantFold = true);
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index 6eff6bfe8d5b1..7f229fb70f8b3 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -690,8 +690,20 @@ END_TWO_BYTE_PACK()
/// \<target\>ISD namespace).
bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; }
- /// Return true if the type of the node type undefined.
- bool isUndef() const { return NodeType == ISD::UNDEF; }
+ /// Returns true if the node type is UNDEF or, when DoNotIncludeExplicitPoison
+ /// is false, POISON.
+ /// - When DoNotIncludeExplicitPoison is true, returns true only for UNDEF.
+ /// - When DoNotIncludeExplicitPoison is false, returns true for both UNDEF
+ /// and POISON.
+ /// @param DoNotIncludeExplicitPoison Determines whether to check only for
+ /// UNDEF.
+ bool isUndef(bool DoNotIncludeExplicitPoison = false) const {
+ return NodeType == ISD::UNDEF ||
+ (!DoNotIncludeExplicitPoison && NodeType == ISD::POISON);
+ }
+
+ /// Return true if the type of the node type poison.
+ bool isPoison() const { return NodeType == ISD::POISON; }
/// Test if this node is a memory intrinsic (with valid pointer information).
bool isMemIntrinsic() const { return SDNodeBits.IsMemIntrinsic; }
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index f52447b86a7e4..da7a68b3c5875 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -16171,7 +16171,8 @@ SDValue DAGCombiner::visitFREEZE(SDNode *N) {
// Finally, recreate the node, it's operands were updated to use
// frozen operands, so we just need to use it's "original" operands.
SmallVector<SDValue> Ops(N0->ops());
- // Special-handle ISD::UNDEF, each single one of them can be it's own thing.
+ // Special-handle ISD::UNDEF, ISD::POISON, each single one of them can be it's
+ // own thing.
for (SDValue &Op : Ops) {
if (Op.isUndef())
Op = DAG.getFreeze(Op);
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index f56097fdbb51a..eb65e524761b8 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -977,6 +977,22 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
TargetLowering::LegalizeAction Action = TargetLowering::Legal;
bool SimpleFinishLegalizing = true;
switch (Node->getOpcode()) {
+ // FIXME: If the node represents a poison value, replace it with an undef
+ // value.
+ // A poison value results from an erroneous operation but does not cause
+ // immediate undefined behavior, allowing speculative execution.
+ // Since most operations propagate poison, it is valid to replace poison
+ // with an undef value, which can take any legal value of the same type.
+ // This ensures that downstream computations do not rely on poison semantics.
+ // Poison is more restrictive than undef. Since we replace poison with undef
+ // here, the poison information will be lost after the code is executed. In
+ // the futher, If we need to retain the poison information after the code is
+ // executed, we will need to modify the code accordingly.
+ case ISD::POISON: {
+ SDValue UndefNode = DAG.getUNDEF(Node->getValueType(0));
+ ReplaceNode(Node, UndefNode.getNode());
+ break;
+ }
case ISD::INTRINSIC_W_CHAIN:
case ISD::INTRINSIC_WO_CHAIN:
case ISD::INTRINSIC_VOID:
@@ -3136,6 +3152,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
for (unsigned i = 0; i < Node->getNumValues(); i++)
Results.push_back(Node->getOperand(i));
break;
+ case ISD::POISON:
case ISD::UNDEF: {
EVT VT = Node->getValueType(0);
if (VT.isInteger())
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index 204b323d7084a..f944104a0e9d6 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -118,6 +118,7 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
case ISD::VP_SRL: Res = PromoteIntRes_SRL(N); break;
case ISD::VP_TRUNCATE:
case ISD::TRUNCATE: Res = PromoteIntRes_TRUNCATE(N); break;
+ case ISD::POISON:
case ISD::UNDEF: Res = PromoteIntRes_UNDEF(N); break;
case ISD::VAARG: Res = PromoteIntRes_VAARG(N); break;
case ISD::VSCALE: Res = PromoteIntRes_VSCALE(N); break;
@@ -2932,6 +2933,7 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) {
case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, ResNo, Lo, Hi); break;
case ISD::SELECT: SplitRes_Select(N, Lo, Hi); break;
case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break;
+ case ISD::POISON:
case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
case ISD::FREEZE: SplitRes_FREEZE(N, Lo, Hi); break;
case ISD::SETCC: ExpandIntRes_SETCC(N, Lo, Hi); break;
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index 9d42ec2fdf859..f934d8b37561e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -71,6 +71,7 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
case ISD::SELECT: R = ScalarizeVecRes_SELECT(N); break;
case ISD::SELECT_CC: R = ScalarizeVecRes_SELECT_CC(N); break;
case ISD::SETCC: R = ScalarizeVecRes_SETCC(N); break;
+ case ISD::POISON:
case ISD::UNDEF: R = ScalarizeVecRes_UNDEF(N); break;
case ISD::VECTOR_SHUFFLE: R = ScalarizeVecRes_VECTOR_SHUFFLE(N); break;
case ISD::IS_FPCLASS: R = ScalarizeVecRes_IS_FPCLASS(N); break;
@@ -1137,6 +1138,7 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
case ISD::VP_MERGE:
case ISD::VP_SELECT: SplitRes_Select(N, Lo, Hi); break;
case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break;
+ case ISD::POISON:
case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
case ISD::BITCAST: SplitVecRes_BITCAST(N, Lo, Hi); break;
case ISD::BUILD_VECTOR: SplitVecRes_BUILD_VECTOR(N, Lo, Hi); break;
@@ -4592,6 +4594,7 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break;
case ISD::VP_SETCC:
case ISD::SETCC: Res = WidenVecRes_SETCC(N); break;
+ case ISD::POISON:
case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break;
case ISD::VECTOR_SHUFFLE:
Res = WidenVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N));
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index de092cba333c2..c0bee7fa34cd2 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -5436,6 +5436,9 @@ bool SelectionDAG::isGuaranteedNotToBeUndefOrPoison(SDValue Op,
case ISD::CopyFromReg:
return true;
+ case ISD::POISON:
+ return false;
+
case ISD::UNDEF:
return PoisonOnly;
@@ -6288,6 +6291,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
if (N1.isUndef())
// sext(undef) = 0, because the top bits will all be the same.
return getConstant(0, DL, VT);
+
break;
case ISD::ZERO_EXTEND:
assert(VT.isInteger() && N1.getValueType().isInteger() &&
@@ -9228,6 +9232,11 @@ SDValue SelectionDAG::getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType,
SDVTList VTs = Indexed ?
getVTList(VT, Ptr.getValueType(), MVT::Other) : getVTList(VT, MVT::Other);
+
+ // Lower poison to undef.
+ if (Ptr.getNode()->isPoison())
+ Ptr = getUNDEF(Ptr.getValueType());
+
SDValue Ops[] = { Chain, Ptr, Offset };
FoldingSetNodeID ID;
AddNodeIDNode(ID, ISD::LOAD, VTs, Ops);
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 1c58a7f05446c..9f9fee19da228 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -1818,7 +1818,7 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) {
return DAG.getConstantFP(*CFP, getCurSDLoc(), VT);
if (isa<UndefValue>(C) && !V->getType()->isAggregateType())
- return DAG.getUNDEF(VT);
+ return isa<PoisonValue>(C) ? DAG.getPoison(VT) : DAG.getUNDEF(VT);
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
visit(CE->getOpcode(), *CE);
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index 8457bee3f665b..29edb5c646035 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -185,6 +185,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::CopyToReg: return "CopyToReg";
case ISD::CopyFromReg: return "CopyFromReg";
case ISD::UNDEF: return "undef";
+ case ISD::POISON: return "poison";
case ISD::VSCALE: return "vscale";
case ISD::MERGE_VALUES: return "merge_values";
case ISD::INLINEASM: return "inlineasm";
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 61e5aa270bc11..8d0938fef4f9f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -3275,6 +3275,7 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
case ISD::WRITE_REGISTER:
Select_WRITE_REGISTER(NodeToMatch);
return;
+ case ISD::POISON:
case ISD::UNDEF:
Select_UNDEF(NodeToMatch);
return;
>From 94fad7f1c873a3525a095ef197f9512388c551dc Mon Sep 17 00:00:00 2001
From: zhijian <zhijian at ca.ibm.com>
Date: Wed, 19 Feb 2025 15:17:02 +0000
Subject: [PATCH 2/2] address comment
---
llvm/include/llvm/CodeGen/SelectionDAGNodes.h | 3 ---
llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 11 -----------
2 files changed, 14 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index 7f229fb70f8b3..c5d4fbe6fd479 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -692,9 +692,6 @@ END_TWO_BYTE_PACK()
/// Returns true if the node type is UNDEF or, when DoNotIncludeExplicitPoison
/// is false, POISON.
- /// - When DoNotIncludeExplicitPoison is true, returns true only for UNDEF.
- /// - When DoNotIncludeExplicitPoison is false, returns true for both UNDEF
- /// and POISON.
/// @param DoNotIncludeExplicitPoison Determines whether to check only for
/// UNDEF.
bool isUndef(bool DoNotIncludeExplicitPoison = false) const {
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index eb65e524761b8..c6f118f32afcc 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -977,17 +977,6 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
TargetLowering::LegalizeAction Action = TargetLowering::Legal;
bool SimpleFinishLegalizing = true;
switch (Node->getOpcode()) {
- // FIXME: If the node represents a poison value, replace it with an undef
- // value.
- // A poison value results from an erroneous operation but does not cause
- // immediate undefined behavior, allowing speculative execution.
- // Since most operations propagate poison, it is valid to replace poison
- // with an undef value, which can take any legal value of the same type.
- // This ensures that downstream computations do not rely on poison semantics.
- // Poison is more restrictive than undef. Since we replace poison with undef
- // here, the poison information will be lost after the code is executed. In
- // the futher, If we need to retain the poison information after the code is
- // executed, we will need to modify the code accordingly.
case ISD::POISON: {
SDValue UndefNode = DAG.getUNDEF(Node->getValueType(0));
ReplaceNode(Node, UndefNode.getNode());
More information about the llvm-commits
mailing list