summaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp60
1 files changed, 45 insertions, 15 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 57f8fc409de4..962f0d98e3be 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -3786,7 +3786,15 @@ bool TargetLowering::isGuaranteedNotToBeUndefOrPoisonForTargetNode(
Op.getOpcode() == ISD::INTRINSIC_VOID) &&
"Should use isGuaranteedNotToBeUndefOrPoison if you don't know whether Op"
" is a target node!");
- return false;
+
+ // If Op can't create undef/poison and none of its operands are undef/poison
+ // then Op is never undef/poison.
+ return !canCreateUndefOrPoisonForTargetNode(Op, DemandedElts, DAG, PoisonOnly,
+ /*ConsiderFlags*/ true, Depth) &&
+ all_of(Op->ops(), [&](SDValue V) {
+ return DAG.isGuaranteedNotToBeUndefOrPoison(V, PoisonOnly,
+ Depth + 1);
+ });
}
bool TargetLowering::canCreateUndefOrPoisonForTargetNode(
@@ -6908,6 +6916,11 @@ TargetLowering::prepareSREMEqFold(EVT SETCCVT, SDValue REMNode,
// Q = floor((2 * A) / (2^K))
APInt Q = (2 * A).udiv(APInt::getOneBitSet(W, K));
+ assert(APInt::getAllOnes(SVT.getSizeInBits()).ugt(A) &&
+ "We are expecting that A is always less than all-ones for SVT");
+ assert(APInt::getAllOnes(ShSVT.getSizeInBits()).ugt(K) &&
+ "We are expecting that K is always less than all-ones for ShSVT");
+
// If D was a power of two, apply the alternate constant derivation.
if (D0.isOne()) {
// A = 2^(W-1)
@@ -6916,11 +6929,6 @@ TargetLowering::prepareSREMEqFold(EVT SETCCVT, SDValue REMNode,
Q = APInt::getAllOnes(W - K).zext(W);
}
- assert(APInt::getAllOnes(SVT.getSizeInBits()).ugt(A) &&
- "We are expecting that A is always less than all-ones for SVT");
- assert(APInt::getAllOnes(ShSVT.getSizeInBits()).ugt(K) &&
- "We are expecting that K is always less than all-ones for ShSVT");
-
// If the divisor is 1 the result can be constant-folded. Likewise, we
// don't care about INT_MIN lanes, those can be set to undef if appropriate.
if (D.isOne()) {
@@ -8702,11 +8710,21 @@ SDValue TargetLowering::expandCTPOP(SDNode *Node, SelectionDAG &DAG) const {
}
// v = (v * 0x01010101...) >> (Len - 8)
- SDValue Mask01 =
- DAG.getConstant(APInt::getSplat(Len, APInt(8, 0x01)), dl, VT);
- return DAG.getNode(ISD::SRL, dl, VT,
- DAG.getNode(ISD::MUL, dl, VT, Op, Mask01),
- DAG.getConstant(Len - 8, dl, ShVT));
+ SDValue V;
+ if (isOperationLegalOrCustomOrPromote(
+ ISD::MUL, getTypeToTransformTo(*DAG.getContext(), VT))) {
+ SDValue Mask01 =
+ DAG.getConstant(APInt::getSplat(Len, APInt(8, 0x01)), dl, VT);
+ V = DAG.getNode(ISD::MUL, dl, VT, Op, Mask01);
+ } else {
+ V = Op;
+ for (unsigned Shift = 8; Shift < Len; Shift *= 2) {
+ SDValue ShiftC = DAG.getShiftAmountConstant(Shift, VT, dl);
+ V = DAG.getNode(ISD::ADD, dl, VT, V,
+ DAG.getNode(ISD::SHL, dl, VT, V, ShiftC));
+ }
+ }
+ return DAG.getNode(ISD::SRL, dl, VT, V, DAG.getConstant(Len - 8, dl, ShVT));
}
SDValue TargetLowering::expandVPCTPOP(SDNode *Node, SelectionDAG &DAG) const {
@@ -8759,10 +8777,22 @@ SDValue TargetLowering::expandVPCTPOP(SDNode *Node, SelectionDAG &DAG) const {
return Op;
// v = (v * 0x01010101...) >> (Len - 8)
- SDValue Mask01 =
- DAG.getConstant(APInt::getSplat(Len, APInt(8, 0x01)), dl, VT);
- return DAG.getNode(ISD::VP_LSHR, dl, VT,
- DAG.getNode(ISD::VP_MUL, dl, VT, Op, Mask01, Mask, VL),
+ SDValue V;
+ if (isOperationLegalOrCustomOrPromote(
+ ISD::VP_MUL, getTypeToTransformTo(*DAG.getContext(), VT))) {
+ SDValue Mask01 =
+ DAG.getConstant(APInt::getSplat(Len, APInt(8, 0x01)), dl, VT);
+ V = DAG.getNode(ISD::VP_MUL, dl, VT, Op, Mask01, Mask, VL);
+ } else {
+ V = Op;
+ for (unsigned Shift = 8; Shift < Len; Shift *= 2) {
+ SDValue ShiftC = DAG.getShiftAmountConstant(Shift, VT, dl);
+ V = DAG.getNode(ISD::VP_ADD, dl, VT, V,
+ DAG.getNode(ISD::VP_SHL, dl, VT, V, ShiftC, Mask, VL),
+ Mask, VL);
+ }
+ }
+ return DAG.getNode(ISD::VP_LSHR, dl, VT, V,
DAG.getConstant(Len - 8, dl, ShVT), Mask, VL);
}