1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 02:33:06 +01:00

[DAG] Add initial SelectionDAG::isGuaranteedNotToBeUndefOrPoison framework (PR51129)

I've setup the basic framework for the isGuaranteedNotToBeUndefOrPoison call and updated DAGCombiner::visitFREEZE to use it, further Opcodes can be handled when we have test coverage.

I'm not aware of any vector test freeze coverage so the DemandedElts (and the Depth) args are not being used yet - but they are in place.

SelectionDAG::isGuaranteedNotToBePoison wrappers have also been added.

Differential Revision: https://reviews.llvm.org/D106668
This commit is contained in:
Simon Pilgrim 2021-07-24 11:36:20 +01:00
parent 70ba442475
commit cb0d04c29e
5 changed files with 101 additions and 6 deletions

View File

@ -1769,6 +1769,31 @@ public:
unsigned ComputeNumSignBits(SDValue Op, const APInt &DemandedElts,
unsigned Depth = 0) const;
/// Return true if this function can prove that \p Op is never poison
/// and, if \p PoisonOnly is false, does not have undef bits.
bool isGuaranteedNotToBeUndefOrPoison(SDValue Op, bool PoisonOnly = false,
unsigned Depth = 0) const;
/// Return true if this function can prove that \p Op is never poison
/// and, if \p PoisonOnly is false, does not have undef bits. The DemandedElts
/// argument limits the check to the requested vector elements.
bool isGuaranteedNotToBeUndefOrPoison(SDValue Op, const APInt &DemandedElts,
bool PoisonOnly = false,
unsigned Depth = 0) const;
/// Return true if this function can prove that \p Op is never poison.
bool isGuaranteedNotToBePoison(SDValue Op, unsigned Depth = 0) const {
return isGuaranteedNotToBeUndefOrPoison(Op, /*PoisonOnly*/ true, Depth);
}
/// Return true if this function can prove that \p Op is never poison. The
/// DemandedElts argument limits the check to the requested vector elements.
bool isGuaranteedNotToBePoison(SDValue Op, const APInt &DemandedElts,
unsigned Depth = 0) const {
return isGuaranteedNotToBeUndefOrPoison(Op, DemandedElts,
/*PoisonOnly*/ true, Depth);
}
/// Return true if the specified operand is an ISD::ADD with a ConstantSDNode
/// on the right-hand side, or if it is an ISD::OR with a ConstantSDNode that
/// is guaranteed to have the same semantics as an ADD. This handles the

View File

@ -3491,6 +3491,13 @@ public:
SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts,
SelectionDAG &DAG, unsigned Depth) const;
/// Return true if this function can prove that \p Op is never poison
/// and, if \p PoisonOnly is false, does not have undef bits. The DemandedElts
/// argument limits the check to the requested vector elements.
virtual bool isGuaranteedNotToBeUndefOrPoisonForTargetNode(
SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG,
bool PoisonOnly, unsigned Depth) const;
/// Tries to build a legal vector shuffle using the provided parameters
/// or equivalent variations. The Mask argument maybe be modified as the
/// function tries different variations.

View File

@ -12820,12 +12820,7 @@ SDValue DAGCombiner::visitBUILD_PAIR(SDNode *N) {
SDValue DAGCombiner::visitFREEZE(SDNode *N) {
SDValue N0 = N->getOperand(0);
// (freeze (freeze x)) -> (freeze x)
if (N0.getOpcode() == ISD::FREEZE)
return N0;
// If the input is a constant, return it.
if (isIntOrFPConstant(N0))
if (DAG.isGuaranteedNotToBeUndefOrPoison(N0, /*PoisonOnly*/ false))
return N0;
return SDValue();

View File

@ -4247,6 +4247,61 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, const APInt &DemandedElts,
return std::max(FirstAnswer, Mask.countLeadingOnes());
}
bool SelectionDAG::isGuaranteedNotToBeUndefOrPoison(SDValue Op, bool PoisonOnly,
unsigned Depth) const {
// Early out for FREEZE.
if (Op.getOpcode() == ISD::FREEZE)
return true;
// TODO: Assume we don't know anything for now.
EVT VT = Op.getValueType();
if (VT.isScalableVector())
return false;
APInt DemandedElts = VT.isVector()
? APInt::getAllOnesValue(VT.getVectorNumElements())
: APInt(1, 1);
return isGuaranteedNotToBeUndefOrPoison(Op, DemandedElts, PoisonOnly, Depth);
}
bool SelectionDAG::isGuaranteedNotToBeUndefOrPoison(SDValue Op,
const APInt &DemandedElts,
bool PoisonOnly,
unsigned Depth) const {
unsigned Opcode = Op.getOpcode();
// Early out for FREEZE.
if (Opcode == ISD::FREEZE)
return true;
if (Depth >= MaxRecursionDepth)
return false; // Limit search depth.
if (isIntOrFPConstant(Op))
return true;
switch (Opcode) {
case ISD::UNDEF:
return PoisonOnly;
// TODO: ISD::BUILD_VECTOR handling
// TODO: Search for noundef attributes from library functions.
// TODO: Pointers dereferenced by ISD::LOAD/STORE ops are noundef.
default:
// Allow the target to implement this method for its nodes.
if (Opcode >= ISD::BUILTIN_OP_END || Opcode == ISD::INTRINSIC_WO_CHAIN ||
Opcode == ISD::INTRINSIC_W_CHAIN || Opcode == ISD::INTRINSIC_VOID)
return TLI->isGuaranteedNotToBeUndefOrPoisonForTargetNode(
Op, DemandedElts, *this, PoisonOnly, Depth);
break;
}
return false;
}
bool SelectionDAG::isBaseWithConstantOffset(SDValue Op) const {
if ((Op.getOpcode() != ISD::ADD && Op.getOpcode() != ISD::OR) ||
!isa<ConstantSDNode>(Op.getOperand(1)))

View File

@ -3056,6 +3056,19 @@ const Constant *TargetLowering::getTargetConstantFromLoad(LoadSDNode*) const {
return nullptr;
}
bool TargetLowering::isGuaranteedNotToBeUndefOrPoisonForTargetNode(
SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG,
bool PoisonOnly, unsigned Depth) const {
assert(
(Op.getOpcode() >= ISD::BUILTIN_OP_END ||
Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN ||
Op.getOpcode() == ISD::INTRINSIC_W_CHAIN ||
Op.getOpcode() == ISD::INTRINSIC_VOID) &&
"Should use isGuaranteedNotToBeUndefOrPoison if you don't know whether Op"
" is a target node!");
return false;
}
bool TargetLowering::isKnownNeverNaNForTargetNode(SDValue Op,
const SelectionDAG &DAG,
bool SNaN,