aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp128
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();