aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/SelectionDAG/DAGCombiner.cpp')
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp52
1 files changed, 52 insertions, 0 deletions
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index dc0276d57667..03698ac862af 100644
--- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -242,6 +242,7 @@ namespace {
SDValue visitUSUBO(SDNode *N);
SDValue visitADDE(SDNode *N);
SDValue visitADDCARRY(SDNode *N);
+ SDValue visitADDCARRYLike(SDValue N0, SDValue N1, SDValue CarryIn, SDNode *N);
SDValue visitSUBE(SDNode *N);
SDValue visitSUBCARRY(SDNode *N);
SDValue visitMUL(SDNode *N);
@@ -2142,6 +2143,24 @@ SDValue DAGCombiner::visitADDCARRY(SDNode *N) {
if (isNullConstant(CarryIn))
return DAG.getNode(ISD::UADDO, SDLoc(N), N->getVTList(), N0, N1);
+ if (SDValue Combined = visitADDCARRYLike(N0, N1, CarryIn, N))
+ return Combined;
+
+ if (SDValue Combined = visitADDCARRYLike(N1, N0, CarryIn, N))
+ return Combined;
+
+ return SDValue();
+}
+
+SDValue DAGCombiner::visitADDCARRYLike(SDValue N0, SDValue N1, SDValue CarryIn,
+ SDNode *N) {
+ // Iff the flag result is dead:
+ // (addcarry (add|uaddo X, Y), 0, Carry) -> (addcarry X, Y, Carry)
+ if ((N0.getOpcode() == ISD::ADD || N0.getOpcode() == ISD::UADDO) &&
+ isNullConstant(N1) && !N->hasAnyUseOfValue(1))
+ return DAG.getNode(ISD::ADDCARRY, SDLoc(N), N->getVTList(),
+ N0.getOperand(0), N0.getOperand(1), CarryIn);
+
return SDValue();
}
@@ -5294,6 +5313,17 @@ SDValue DAGCombiner::visitSHL(SDNode *N) {
}
}
+ // If the target supports masking y in (shl, y),
+ // fold (shl x, (and y, ((1 << numbits(x)) - 1))) -> (shl x, y)
+ if (TLI.isOperationLegal(ISD::SHL, VT) &&
+ TLI.supportsModuloShift(ISD::SHL, VT) && N1->getOpcode() == ISD::AND) {
+ if (ConstantSDNode *Mask = isConstOrConstSplat(N1->getOperand(1))) {
+ if (Mask->getZExtValue() == OpSizeInBits - 1) {
+ return DAG.getNode(ISD::SHL, SDLoc(N), VT, N0, N1->getOperand(0));
+ }
+ }
+ }
+
ConstantSDNode *N1C = isConstOrConstSplat(N1);
// fold (shl c1, c2) -> c1<<c2
@@ -5492,6 +5522,17 @@ SDValue DAGCombiner::visitSRA(SDNode *N) {
EVT VT = N0.getValueType();
unsigned OpSizeInBits = VT.getScalarSizeInBits();
+ // If the target supports masking y in (sra, y),
+ // fold (sra x, (and y, ((1 << numbits(x)) - 1))) -> (sra x, y)
+ if (TLI.isOperationLegal(ISD::SRA, VT) &&
+ TLI.supportsModuloShift(ISD::SRA, VT) && N1->getOpcode() == ISD::AND) {
+ if (ConstantSDNode *Mask = isConstOrConstSplat(N1->getOperand(1))) {
+ if (Mask->getZExtValue() == OpSizeInBits - 1) {
+ return DAG.getNode(ISD::SRA, SDLoc(N), VT, N0, N1->getOperand(0));
+ }
+ }
+ }
+
// Arithmetic shifting an all-sign-bit value is a no-op.
if (DAG.ComputeNumSignBits(N0) == OpSizeInBits)
return N0;
@@ -5650,6 +5691,17 @@ SDValue DAGCombiner::visitSRL(SDNode *N) {
EVT VT = N0.getValueType();
unsigned OpSizeInBits = VT.getScalarSizeInBits();
+ // If the target supports masking y in (srl, y),
+ // fold (srl x, (and y, ((1 << numbits(x)) - 1))) -> (srl x, y)
+ if (TLI.isOperationLegal(ISD::SRL, VT) &&
+ TLI.supportsModuloShift(ISD::SRL, VT) && N1->getOpcode() == ISD::AND) {
+ if (ConstantSDNode *Mask = isConstOrConstSplat(N1->getOperand(1))) {
+ if (Mask->getZExtValue() == OpSizeInBits - 1) {
+ return DAG.getNode(ISD::SRL, SDLoc(N), VT, N0, N1->getOperand(0));
+ }
+ }
+ }
+
// fold vector ops
if (VT.isVector())
if (SDValue FoldedVOp = SimplifyVBinOp(N))