diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 128 |
1 files changed, 80 insertions, 48 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index aa688d9dda3c..2654c00929d8 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2392,12 +2392,14 @@ static SDValue foldAddSubOfSignBit(SDNode *N, SelectionDAG &DAG) { // add (srl (not X), 31), C --> add (sra X, 31), (C + 1) // sub C, (srl (not X), 31) --> add (srl X, 31), (C - 1) SDLoc DL(N); - auto ShOpcode = IsAdd ? ISD::SRA : ISD::SRL; - SDValue NewShift = DAG.getNode(ShOpcode, DL, VT, Not.getOperand(0), ShAmt); - if (SDValue NewC = - DAG.FoldConstantArithmetic(IsAdd ? ISD::ADD : ISD::SUB, DL, VT, - {ConstantOp, DAG.getConstant(1, DL, VT)})) + if (SDValue NewC = DAG.FoldConstantArithmetic( + IsAdd ? ISD::ADD : ISD::SUB, DL, VT, + {ConstantOp, DAG.getConstant(1, DL, VT)})) { + SDValue NewShift = DAG.getNode(IsAdd ? ISD::SRA : ISD::SRL, DL, VT, + Not.getOperand(0), ShAmt); return DAG.getNode(ISD::ADD, DL, VT, NewShift, NewC); + } + return SDValue(); } @@ -3760,6 +3762,17 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { } } + // If there's no chance of borrowing from adjacent bits, then sub is xor: + // sub C0, X --> xor X, C0 + if (ConstantSDNode *C0 = isConstOrConstSplat(N0)) { + if (!C0->isOpaque()) { + const APInt &C0Val = C0->getAPIntValue(); + const APInt &MaybeOnes = ~DAG.computeKnownBits(N1).Zero; + if ((C0Val - MaybeOnes) == (C0Val ^ MaybeOnes)) + return DAG.getNode(ISD::XOR, DL, VT, N1, N0); + } + } + return SDValue(); } @@ -4550,13 +4563,12 @@ SDValue DAGCombiner::visitREM(SDNode *N) { SDLoc DL(N); // fold (rem c1, c2) -> c1%c2 - ConstantSDNode *N1C = isConstOrConstSplat(N1); if (SDValue C = DAG.FoldConstantArithmetic(Opcode, DL, VT, {N0, N1})) return C; // fold (urem X, -1) -> select(FX == -1, 0, FX) // Freeze the numerator to avoid a miscompile with an undefined value. - if (!isSigned && N1C && N1C->isAllOnes()) { + if (!isSigned && llvm::isAllOnesOrAllOnesSplat(N1, /*AllowUndefs*/ false)) { SDValue F0 = DAG.getFreeze(N0); SDValue EqualsNeg1 = DAG.getSetCC(DL, CCVT, F0, N1, ISD::SETEQ); return DAG.getSelect(DL, VT, EqualsNeg1, DAG.getConstant(0, DL, VT), F0); @@ -4581,9 +4593,12 @@ SDValue DAGCombiner::visitREM(SDNode *N) { AddToWorklist(Add.getNode()); return DAG.getNode(ISD::AND, DL, VT, N0, Add); } - if (N1.getOpcode() == ISD::SHL && + // fold (urem x, (shl pow2, y)) -> (and x, (add (shl pow2, y), -1)) + // fold (urem x, (lshr pow2, y)) -> (and x, (add (lshr pow2, y), -1)) + // TODO: We should sink the following into isKnownToBePowerOfTwo + // using a OrZero parameter analogous to our handling in ValueTracking. + if ((N1.getOpcode() == ISD::SHL || N1.getOpcode() == ISD::SRL) && DAG.isKnownToBeAPowerOfTwo(N1.getOperand(0))) { - // fold (urem x, (shl pow2, y)) -> (and x, (add (shl pow2, y), -1)) SDValue NegOne = DAG.getAllOnesConstant(DL, VT); SDValue Add = DAG.getNode(ISD::ADD, DL, VT, N1, NegOne); AddToWorklist(Add.getNode()); @@ -9288,31 +9303,44 @@ SDValue DAGCombiner::visitSRA(SDNode *N) { // We convert trunc/ext to opposing shifts in IR, but casts may be cheaper. // sra (add (shl X, N1C), AddC), N1C --> // sext (add (trunc X to (width - N1C)), AddC') - if (N0.getOpcode() == ISD::ADD && N0.hasOneUse() && N1C && - N0.getOperand(0).getOpcode() == ISD::SHL && - N0.getOperand(0).getOperand(1) == N1 && N0.getOperand(0).hasOneUse()) { - if (ConstantSDNode *AddC = isConstOrConstSplat(N0.getOperand(1))) { - SDValue Shl = N0.getOperand(0); - // Determine what the truncate's type would be and ask the target if that - // is a free operation. - LLVMContext &Ctx = *DAG.getContext(); - unsigned ShiftAmt = N1C->getZExtValue(); - EVT TruncVT = EVT::getIntegerVT(Ctx, OpSizeInBits - ShiftAmt); - if (VT.isVector()) - TruncVT = EVT::getVectorVT(Ctx, TruncVT, VT.getVectorElementCount()); - - // TODO: The simple type check probably belongs in the default hook - // implementation and/or target-specific overrides (because - // non-simple types likely require masking when legalized), but that - // restriction may conflict with other transforms. - if (TruncVT.isSimple() && isTypeLegal(TruncVT) && - TLI.isTruncateFree(VT, TruncVT)) { - SDLoc DL(N); - SDValue Trunc = DAG.getZExtOrTrunc(Shl.getOperand(0), DL, TruncVT); - SDValue ShiftC = DAG.getConstant(AddC->getAPIntValue().lshr(ShiftAmt). - trunc(TruncVT.getScalarSizeInBits()), DL, TruncVT); - SDValue Add = DAG.getNode(ISD::ADD, DL, TruncVT, Trunc, ShiftC); - return DAG.getSExtOrTrunc(Add, DL, VT); + // sra (sub AddC, (shl X, N1C)), N1C --> + // sext (sub AddC1',(trunc X to (width - N1C))) + if ((N0.getOpcode() == ISD::ADD || N0.getOpcode() == ISD::SUB) && N1C && + N0.hasOneUse()) { + bool IsAdd = N0.getOpcode() == ISD::ADD; + SDValue Shl = N0.getOperand(IsAdd ? 0 : 1); + if (Shl.getOpcode() == ISD::SHL && Shl.getOperand(1) == N1 && + Shl.hasOneUse()) { + // TODO: AddC does not need to be a splat. + if (ConstantSDNode *AddC = + isConstOrConstSplat(N0.getOperand(IsAdd ? 1 : 0))) { + // Determine what the truncate's type would be and ask the target if + // that is a free operation. + LLVMContext &Ctx = *DAG.getContext(); + unsigned ShiftAmt = N1C->getZExtValue(); + EVT TruncVT = EVT::getIntegerVT(Ctx, OpSizeInBits - ShiftAmt); + if (VT.isVector()) + TruncVT = EVT::getVectorVT(Ctx, TruncVT, VT.getVectorElementCount()); + + // TODO: The simple type check probably belongs in the default hook + // implementation and/or target-specific overrides (because + // non-simple types likely require masking when legalized), but + // that restriction may conflict with other transforms. + if (TruncVT.isSimple() && isTypeLegal(TruncVT) && + TLI.isTruncateFree(VT, TruncVT)) { + SDLoc DL(N); + SDValue Trunc = DAG.getZExtOrTrunc(Shl.getOperand(0), DL, TruncVT); + SDValue ShiftC = + DAG.getConstant(AddC->getAPIntValue().lshr(ShiftAmt).trunc( + TruncVT.getScalarSizeInBits()), + DL, TruncVT); + SDValue Add; + if (IsAdd) + Add = DAG.getNode(ISD::ADD, DL, TruncVT, Trunc, ShiftC); + else + Add = DAG.getNode(ISD::SUB, DL, TruncVT, ShiftC, Trunc); + return DAG.getSExtOrTrunc(Add, DL, VT); + } } } } @@ -11025,6 +11053,9 @@ SDValue DAGCombiner::visitVSELECT(SDNode *N) { if (SDValue V = foldVSelectToSignBitSplatMask(N, DAG)) return V; + if (SimplifyDemandedVectorElts(SDValue(N, 0))) + return SDValue(N, 0); + return SDValue(); } @@ -13243,18 +13274,6 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { } } - // See if we can simplify the input to this truncate through knowledge that - // only the low bits are being used. - // For example "trunc (or (shl x, 8), y)" // -> trunc y - // Currently we only perform this optimization on scalars because vectors - // may have different active low bits. - if (!VT.isVector()) { - APInt Mask = - APInt::getLowBitsSet(N0.getValueSizeInBits(), VT.getSizeInBits()); - if (SDValue Shorter = DAG.GetDemandedBits(N0, Mask)) - return DAG.getNode(ISD::TRUNCATE, SDLoc(N), VT, Shorter); - } - // fold (truncate (load x)) -> (smaller load x) // fold (truncate (srl (load x), c)) -> (smaller load (x+c/evtbits)) if (!LegalTypes || TLI.isTypeDesirableForOp(N0.getOpcode(), VT)) { @@ -13341,6 +13360,18 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { if (SimplifyDemandedBits(SDValue(N, 0))) return SDValue(N, 0); + // See if we can simplify the input to this truncate through knowledge that + // only the low bits are being used. + // For example "trunc (or (shl x, 8), y)" // -> trunc y + // Currently we only perform this optimization on scalars because vectors + // may have different active low bits. + if (!VT.isVector()) { + APInt Mask = + APInt::getLowBitsSet(N0.getValueSizeInBits(), VT.getSizeInBits()); + if (SDValue Shorter = DAG.GetDemandedBits(N0, Mask)) + return DAG.getNode(ISD::TRUNCATE, SDLoc(N), VT, Shorter); + } + // fold (truncate (extract_subvector(ext x))) -> // (extract_subvector x) // TODO: This can be generalized to cover cases where the truncate and extract @@ -24514,8 +24545,9 @@ bool DAGCombiner::mayAlias(SDNode *Op0, SDNode *Op1) const { auto &Size0 = MUC0.NumBytes; auto &Size1 = MUC1.NumBytes; if (OrigAlignment0 == OrigAlignment1 && SrcValOffset0 != SrcValOffset1 && - Size0 && Size1 && *Size0 == *Size1 && OrigAlignment0 > *Size0 && - SrcValOffset0 % *Size0 == 0 && SrcValOffset1 % *Size1 == 0) { + Size0.has_value() && Size1.has_value() && *Size0 == *Size1 && + OrigAlignment0 > *Size0 && SrcValOffset0 % *Size0 == 0 && + SrcValOffset1 % *Size1 == 0) { int64_t OffAlign0 = SrcValOffset0 % OrigAlignment0.value(); int64_t OffAlign1 = SrcValOffset1 % OrigAlignment1.value(); |