aboutsummaryrefslogtreecommitdiff
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.cpp114
1 files changed, 100 insertions, 14 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 66389a57f780..cd4f0ae42bcd 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -1056,13 +1056,13 @@ bool TargetLowering::SimplifyDemandedBits(
// TODO: We can probably do more work on calculating the known bits and
// simplifying the operations for scalable vectors, but for now we just
// bail out.
- if (Op.getValueType().isScalableVector())
+ EVT VT = Op.getValueType();
+ if (VT.isScalableVector())
return false;
bool IsLE = TLO.DAG.getDataLayout().isLittleEndian();
unsigned NumElts = OriginalDemandedElts.getBitWidth();
- assert((!Op.getValueType().isVector() ||
- NumElts == Op.getValueType().getVectorNumElements()) &&
+ assert((!VT.isVector() || NumElts == VT.getVectorNumElements()) &&
"Unexpected vector size");
APInt DemandedBits = OriginalDemandedBits;
@@ -1088,7 +1088,6 @@ bool TargetLowering::SimplifyDemandedBits(
}
// Other users may use these bits.
- EVT VT = Op.getValueType();
if (!Op.getNode()->hasOneUse() && !AssumeSingleUse) {
if (Depth != 0) {
// If not at the root, Just compute the Known bits to
@@ -1468,6 +1467,33 @@ bool TargetLowering::SimplifyDemandedBits(
}
}
+ // (or (and X, C1), (and (or X, Y), C2)) -> (or (and X, C1|C2), (and Y, C2))
+ // TODO: Use SimplifyMultipleUseDemandedBits to peek through masks.
+ if (Op0.getOpcode() == ISD::AND && Op1.getOpcode() == ISD::AND &&
+ Op0->hasOneUse() && Op1->hasOneUse()) {
+ // Attempt to match all commutations - m_c_Or would've been useful!
+ for (int I = 0; I != 2; ++I) {
+ SDValue X = Op.getOperand(I).getOperand(0);
+ SDValue C1 = Op.getOperand(I).getOperand(1);
+ SDValue Alt = Op.getOperand(1 - I).getOperand(0);
+ SDValue C2 = Op.getOperand(1 - I).getOperand(1);
+ if (Alt.getOpcode() == ISD::OR) {
+ for (int J = 0; J != 2; ++J) {
+ if (X == Alt.getOperand(J)) {
+ SDValue Y = Alt.getOperand(1 - J);
+ if (SDValue C12 = TLO.DAG.FoldConstantArithmetic(ISD::OR, dl, VT,
+ {C1, C2})) {
+ SDValue MaskX = TLO.DAG.getNode(ISD::AND, dl, VT, X, C12);
+ SDValue MaskY = TLO.DAG.getNode(ISD::AND, dl, VT, Y, C2);
+ return TLO.CombineTo(
+ Op, TLO.DAG.getNode(ISD::OR, dl, VT, MaskX, MaskY));
+ }
+ }
+ }
+ }
+ }
+ }
+
Known |= Known2;
break;
}
@@ -1500,7 +1526,7 @@ bool TargetLowering::SimplifyDemandedBits(
if (DemandedBits.isSubsetOf(Known.Zero | Known2.Zero))
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::OR, dl, VT, Op0, Op1));
- ConstantSDNode* C = isConstOrConstSplat(Op1, DemandedElts);
+ ConstantSDNode *C = isConstOrConstSplat(Op1, DemandedElts);
if (C) {
// If one side is a constant, and all of the set bits in the constant are
// also known set on the other side, turn this into an AND, as we know
@@ -1521,6 +1547,32 @@ bool TargetLowering::SimplifyDemandedBits(
SDValue New = TLO.DAG.getNOT(dl, Op0, VT);
return TLO.CombineTo(Op, New);
}
+
+ unsigned Op0Opcode = Op0.getOpcode();
+ if ((Op0Opcode == ISD::SRL || Op0Opcode == ISD::SHL) && Op0.hasOneUse()) {
+ if (ConstantSDNode *ShiftC =
+ isConstOrConstSplat(Op0.getOperand(1), DemandedElts)) {
+ // Don't crash on an oversized shift. We can not guarantee that a
+ // bogus shift has been simplified to undef.
+ if (ShiftC->getAPIntValue().ult(BitWidth)) {
+ uint64_t ShiftAmt = ShiftC->getZExtValue();
+ APInt Ones = APInt::getAllOnes(BitWidth);
+ Ones = Op0Opcode == ISD::SHL ? Ones.shl(ShiftAmt)
+ : Ones.lshr(ShiftAmt);
+ const TargetLowering &TLI = TLO.DAG.getTargetLoweringInfo();
+ if ((DemandedBits & C->getAPIntValue()) == (DemandedBits & Ones) &&
+ TLI.isDesirableToCommuteXorWithShift(Op.getNode())) {
+ // If the xor constant is a demanded mask, do a 'not' before the
+ // shift:
+ // xor (X << ShiftC), XorC --> (not X) << ShiftC
+ // xor (X >> ShiftC), XorC --> (not X) >> ShiftC
+ SDValue Not = TLO.DAG.getNOT(dl, Op0.getOperand(0), VT);
+ return TLO.CombineTo(Op, TLO.DAG.getNode(Op0Opcode, dl, VT, Not,
+ Op0.getOperand(1)));
+ }
+ }
+ }
+ }
}
// If we can't turn this into a 'not', try to shrink the constant.
@@ -1723,6 +1775,26 @@ bool TargetLowering::SimplifyDemandedBits(
if ((ShAmt < DemandedBits.getActiveBits()) &&
ShrinkDemandedOp(Op, BitWidth, DemandedBits, TLO))
return true;
+ } else {
+ // This is a variable shift, so we can't shift the demand mask by a known
+ // amount. But if we are not demanding high bits, then we are not
+ // demanding those bits from the pre-shifted operand either.
+ if (unsigned CTLZ = DemandedBits.countLeadingZeros()) {
+ APInt DemandedFromOp(APInt::getLowBitsSet(BitWidth, BitWidth - CTLZ));
+ if (SimplifyDemandedBits(Op0, DemandedFromOp, DemandedElts, Known, TLO,
+ Depth + 1)) {
+ SDNodeFlags Flags = Op.getNode()->getFlags();
+ if (Flags.hasNoSignedWrap() || Flags.hasNoUnsignedWrap()) {
+ // Disable the nsw and nuw flags. We can no longer guarantee that we
+ // won't wrap after simplification.
+ Flags.setNoSignedWrap(false);
+ Flags.setNoUnsignedWrap(false);
+ Op->setFlags(Flags);
+ }
+ return true;
+ }
+ Known.resetAll();
+ }
}
// If we are only demanding sign bits then we can use the shift source
@@ -3292,6 +3364,12 @@ bool TargetLowering::SimplifyDemandedVectorElts(
TLO, Depth + 1))
return true;
+ // If every element pair has a zero/undef then just fold to zero.
+ // fold (and x, undef) -> 0 / (and x, 0) -> 0
+ // fold (mul x, undef) -> 0 / (mul x, 0) -> 0
+ if (DemandedElts.isSubsetOf(SrcZero | KnownZero | SrcUndef | KnownUndef))
+ return TLO.CombineTo(Op, TLO.DAG.getConstant(0, SDLoc(Op), VT));
+
// If either side has a zero element, then the result element is zero, even
// if the other is an UNDEF.
// TODO: Extend getKnownUndefForVectorBinop to also deal with known zeros
@@ -3301,7 +3379,6 @@ bool TargetLowering::SimplifyDemandedVectorElts(
KnownUndef &= ~KnownZero;
// Attempt to avoid multi-use ops if we don't need anything from them.
- // TODO - use KnownUndef to relax the demandedelts?
if (!DemandedElts.isAllOnes())
if (SimplifyDemandedVectorEltsBinOp(Op0, Op1))
return true;
@@ -5204,6 +5281,7 @@ TargetLowering::ParseConstraints(const DataLayout &DL,
// ConstraintOperands list.
unsigned ArgNo = 0; // ArgNo - The argument of the CallInst.
unsigned ResNo = 0; // ResNo - The result number of the next output.
+ unsigned LabelNo = 0; // LabelNo - CallBr indirect dest number.
for (InlineAsm::ConstraintInfo &CI : IA->ParseConstraints()) {
ConstraintOperands.emplace_back(std::move(CI));
@@ -5240,6 +5318,14 @@ TargetLowering::ParseConstraints(const DataLayout &DL,
case InlineAsm::isInput:
OpInfo.CallOperandVal = Call.getArgOperand(ArgNo);
break;
+ case InlineAsm::isLabel:
+ OpInfo.CallOperandVal =
+ cast<CallBrInst>(&Call)->getBlockAddressForIndirectDest(LabelNo);
+ OpInfo.ConstraintVT =
+ getAsmOperandValueType(DL, OpInfo.CallOperandVal->getType())
+ .getSimpleVT();
+ ++LabelNo;
+ continue;
case InlineAsm::isClobber:
// Nothing to do.
break;
@@ -5852,22 +5938,22 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG,
// FIXME: We should use a narrower constant when the upper
// bits are known to be zero.
const APInt& Divisor = C->getAPIntValue();
- UnsignedDivisonByConstantInfo magics = UnsignedDivisonByConstantInfo::get(Divisor);
+ UnsignedDivisionByConstantInfo magics =
+ UnsignedDivisionByConstantInfo::get(Divisor);
unsigned PreShift = 0, PostShift = 0;
// If the divisor is even, we can avoid using the expensive fixup by
// shifting the divided value upfront.
- if (magics.IsAdd != 0 && !Divisor[0]) {
+ if (magics.IsAdd && !Divisor[0]) {
PreShift = Divisor.countTrailingZeros();
// Get magic number for the shifted divisor.
- magics = UnsignedDivisonByConstantInfo::get(Divisor.lshr(PreShift), PreShift);
- assert(magics.IsAdd == 0 && "Should use cheap fixup now");
+ magics =
+ UnsignedDivisionByConstantInfo::get(Divisor.lshr(PreShift), PreShift);
+ assert(!magics.IsAdd && "Should use cheap fixup now");
}
- APInt Magic = magics.Magic;
-
unsigned SelNPQ;
- if (magics.IsAdd == 0 || Divisor.isOne()) {
+ if (!magics.IsAdd || Divisor.isOne()) {
assert(magics.ShiftAmount < Divisor.getBitWidth() &&
"We shouldn't generate an undefined shift!");
PostShift = magics.ShiftAmount;
@@ -5878,7 +5964,7 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG,
}
PreShifts.push_back(DAG.getConstant(PreShift, dl, ShSVT));
- MagicFactors.push_back(DAG.getConstant(Magic, dl, SVT));
+ MagicFactors.push_back(DAG.getConstant(magics.Magic, dl, SVT));
NPQFactors.push_back(
DAG.getConstant(SelNPQ ? APInt::getOneBitSet(EltBits, EltBits - 1)
: APInt::getZero(EltBits),