summaryrefslogtreecommitdiffstats
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.cpp56
1 files changed, 46 insertions, 10 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 46c2f8ebfb8..8b6b4520ad6 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -1179,29 +1179,64 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
Known.Zero |= ~InMask;
break;
}
- case ISD::BITCAST:
+ case ISD::BITCAST: {
+ SDValue Src = Op.getOperand(0);
+ EVT SrcVT = Src.getValueType();
+ unsigned NumSrcEltBits = SrcVT.getScalarSizeInBits();
+
// If this is an FP->Int bitcast and if the sign bit is the only
// thing demanded, turn this into a FGETSIGN.
- if (!TLO.LegalOperations() && !VT.isVector() &&
- !Op.getOperand(0).getValueType().isVector() &&
+ if (!TLO.LegalOperations() && !VT.isVector() && !SrcVT.isVector() &&
NewMask == APInt::getSignMask(Op.getValueSizeInBits()) &&
- Op.getOperand(0).getValueType().isFloatingPoint()) {
+ SrcVT.isFloatingPoint()) {
bool OpVTLegal = isOperationLegalOrCustom(ISD::FGETSIGN, VT);
- bool i32Legal = isOperationLegalOrCustom(ISD::FGETSIGN, MVT::i32);
- if ((OpVTLegal || i32Legal) && VT.isSimple() &&
- Op.getOperand(0).getValueType() != MVT::f16 &&
- Op.getOperand(0).getValueType() != MVT::f128) {
+ bool i32Legal = isOperationLegalOrCustom(ISD::FGETSIGN, MVT::i32);
+ if ((OpVTLegal || i32Legal) && VT.isSimple() && SrcVT != MVT::f16 &&
+ SrcVT != MVT::f128) {
// Cannot eliminate/lower SHL for f128 yet.
EVT Ty = OpVTLegal ? VT : MVT::i32;
// Make a FGETSIGN + SHL to move the sign bit into the appropriate
// place. We expect the SHL to be eliminated by other optimizations.
- SDValue Sign = TLO.DAG.getNode(ISD::FGETSIGN, dl, Ty, Op.getOperand(0));
+ SDValue Sign = TLO.DAG.getNode(ISD::FGETSIGN, dl, Ty, Src);
unsigned OpVTSizeInBits = Op.getValueSizeInBits();
if (!OpVTLegal && OpVTSizeInBits > 32)
Sign = TLO.DAG.getNode(ISD::ZERO_EXTEND, dl, VT, Sign);
unsigned ShVal = Op.getValueSizeInBits() - 1;
SDValue ShAmt = TLO.DAG.getConstant(ShVal, dl, VT);
- return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SHL, dl, VT, Sign, ShAmt));
+ return TLO.CombineTo(Op,
+ TLO.DAG.getNode(ISD::SHL, dl, VT, Sign, ShAmt));
+ }
+ }
+ // If bitcast from a vector and the mask covers entire elements, see if we
+ // can use SimplifyDemandedVectorElts.
+ // TODO - bigendian once we have test coverage.
+ // TODO - bool vectors once SimplifyDemandedVectorElts has SETCC support.
+ if (SrcVT.isVector() && NumSrcEltBits > 1 &&
+ (BitWidth % NumSrcEltBits) == 0 &&
+ TLO.DAG.getDataLayout().isLittleEndian()) {
+ unsigned Scale = BitWidth / NumSrcEltBits;
+ auto GetDemandedSubMask = [&](APInt &DemandedSubElts) -> bool {
+ DemandedSubElts = APInt::getNullValue(Scale);
+ for (unsigned i = 0; i != Scale; ++i) {
+ unsigned Offset = i * NumSrcEltBits;
+ APInt Sub = DemandedMask.extractBits(NumSrcEltBits, Offset);
+ if (Sub.isAllOnesValue())
+ DemandedSubElts.setBit(i);
+ else if (!Sub.isNullValue())
+ return false;
+ }
+ return true;
+ };
+
+ APInt DemandedSubElts;
+ if (GetDemandedSubMask(DemandedSubElts)) {
+ unsigned NumSrcElts = SrcVT.getVectorNumElements();
+ APInt DemandedElts = APInt::getSplat(NumSrcElts, DemandedSubElts);
+
+ APInt KnownUndef, KnownZero;
+ if (SimplifyDemandedVectorElts(Src, DemandedElts, KnownUndef, KnownZero,
+ TLO, Depth + 1))
+ return true;
}
}
// If this is a bitcast, let computeKnownBits handle it. Only do this on a
@@ -1211,6 +1246,7 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
return false;
}
break;
+ }
case ISD::ADD:
case ISD::MUL:
case ISD::SUB: {
OpenPOWER on IntegriCloud