[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Nate Begeman
natebegeman at mac.com
Mon Oct 10 14:27:00 PDT 2005
Changes in directory llvm/lib/CodeGen/SelectionDAG:
DAGCombiner.cpp updated: 1.26 -> 1.27
---
Log message:
Teach the DAGCombiner several new tricks, teaching it how to turn
sext_inreg into zext_inreg based on the signbit (fires a lot), srem into
urem, etc.
---
Diffs of the changes: (+46 -32)
DAGCombiner.cpp | 78 +++++++++++++++++++++++++++++++++-----------------------
1 files changed, 46 insertions(+), 32 deletions(-)
Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.26 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.27
--- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.26 Mon Oct 10 11:52:03 2005
+++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Oct 10 16:26:48 2005
@@ -20,7 +20,6 @@
// ZERO_EXTEND/SIGN_EXTEND by converting them to an ANY_EXTEND node which
// we don't have yet.
//
-// FIXME: select C, 16, 0 -> shr C, 4
// FIXME: select C, pow2, pow2 -> something smart
// FIXME: trunc(select X, Y, Z) -> select X, trunc(Y), trunc(Z)
// FIXME: (select C, load A, load B) -> load (select C, A, B)
@@ -30,20 +29,13 @@
// FIXME: TRUNC (LOAD) -> EXT_LOAD/LOAD(smaller)
// FIXME: mul (x, const) -> shifts + adds
// FIXME: undef values
-// FIXME: zero extend when top bits are 0 -> drop it ?
// FIXME: make truncate see through SIGN_EXTEND and AND
-// FIXME: sext_in_reg(setcc) on targets that return zero or one, and where
-// EVT != MVT::i1 can drop the sext.
// FIXME: (sra (sra x, c1), c2) -> (sra x, c1+c2)
// FIXME: verify that getNode can't return extends with an operand whose type
// is >= to that of the extend.
// FIXME: divide by zero is currently left unfolded. do we want to turn this
// into an undef?
// FIXME: select ne (select cc, 1, 0), 0, true, false -> select cc, true, false
-// FIXME: sext_inreg(SRL) -> SRA:
-// int %simple(uint %X) { %tmp.4 = shr uint %X, ubyte 16
-// %tmp.5 = cast uint %tmp.4 to short %tmp.6 = cast short %tmp.5 to int
-// ret int %tmp.6 }
//
//===----------------------------------------------------------------------===//
@@ -154,8 +146,8 @@
};
}
-/// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use
-/// this predicate to simplify operations downstream. V and Mask are known to
+/// MaskedValueIsZero - Return true if 'Op & Mask' is known to be zero. We use
+/// this predicate to simplify operations downstream. Op and Mask are known to
/// be the same type.
static bool MaskedValueIsZero(const SDOperand &Op, uint64_t Mask,
const TargetLowering &TLI) {
@@ -167,7 +159,6 @@
case ISD::Constant:
return (cast<ConstantSDNode>(Op)->getValue() & Mask) == 0;
case ISD::SETCC:
- // FIXME: teach this about non ZeroOrOne values, such as 0 or -1
return ((Mask & 1) == 0) &&
TLI.getSetCCResultContents() == TargetLowering::ZeroOrOneSetCCResult;
case ISD::ZEXTLOAD:
@@ -184,7 +175,6 @@
if (MaskedValueIsZero(Op.getOperand(1), Mask, TLI) ||
MaskedValueIsZero(Op.getOperand(0), Mask, TLI))
return true;
-
// (X & C1) & C2 == 0 iff C1 & C2 == 0.
if (ConstantSDNode *AndRHS = dyn_cast<ConstantSDNode>(Op.getOperand(1)))
return MaskedValueIsZero(Op.getOperand(0),AndRHS->getValue() & Mask, TLI);
@@ -545,15 +535,12 @@
if (N0C && N1C && !N1C->isNullValue())
return DAG.getConstant(N0C->getSignExtended() / N1C->getSignExtended(),
N->getValueType(0));
-
// If we know the sign bits of both operands are zero, strength reduce to a
// udiv instead. Handles (X&15) /s 4 -> X&15 >> 2
uint64_t SignBit = 1ULL << (MVT::getSizeInBits(VT)-1);
if (MaskedValueIsZero(N1, SignBit, TLI) &&
MaskedValueIsZero(N0, SignBit, TLI))
return DAG.getNode(ISD::UDIV, N1.getValueType(), N0, N1);
-
-
return SDOperand();
}
@@ -578,6 +565,7 @@
SDOperand DAGCombiner::visitSREM(SDNode *N) {
SDOperand N0 = N->getOperand(0);
SDOperand N1 = N->getOperand(1);
+ MVT::ValueType VT = N->getValueType(0);
ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
@@ -585,6 +573,12 @@
if (N0C && N1C && !N1C->isNullValue())
return DAG.getConstant(N0C->getSignExtended() % N1C->getSignExtended(),
N->getValueType(0));
+ // If we know the sign bits of both operands are zero, strength reduce to a
+ // urem instead. Handles (X & 0x0FFFFFFF) %s 16 -> X&15
+ uint64_t SignBit = 1ULL << (MVT::getSizeInBits(VT)-1);
+ if (MaskedValueIsZero(N1, SignBit, TLI) &&
+ MaskedValueIsZero(N0, SignBit, TLI))
+ return DAG.getNode(ISD::UREM, N1.getValueType(), N0, N1);
return SDOperand();
}
@@ -598,7 +592,10 @@
if (N0C && N1C && !N1C->isNullValue())
return DAG.getConstant(N0C->getValue() % N1C->getValue(),
N->getValueType(0));
- // FIXME: c2 power of 2 -> mask?
+ // fold (urem x, pow2) -> (and x, pow2-1)
+ if (N1C && !N1C->isNullValue() && isPowerOf2_64(N1C->getValue()))
+ return DAG.getNode(ISD::AND, N0.getValueType(), N0,
+ DAG.getConstant(N1C->getValue()-1, N1.getValueType()));
return SDOperand();
}
@@ -1173,6 +1170,7 @@
ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
MVT::ValueType VT = N->getValueType(0);
MVT::ValueType EVT = cast<VTSDNode>(N1)->getVT();
+ unsigned EVTBits = MVT::getSizeInBits(EVT);
// fold (sext_in_reg c1) -> c1
if (N0C) {
@@ -1200,23 +1198,20 @@
return N0;
}
// fold (sext_in_reg (setcc x)) -> setcc x iff (setcc x) == 0 or -1
- // FIXME: teach isSetCCEquivalent about 0, -1 and then use it here
if (N0.getOpcode() == ISD::SETCC &&
TLI.getSetCCResultContents() ==
TargetLowering::ZeroOrNegativeOneSetCCResult)
return N0;
- // FIXME: this code is currently just ported over from SelectionDAG.cpp
- // we probably actually want to handle this in two pieces. Rather than
- // checking all the top bits for zero, just check the sign bit here and turn
- // it into a zero extend inreg (AND with constant).
- // then, let the code for AND figure out if the mask is superfluous rather
- // than doing so here.
- if (N0.getOpcode() == ISD::AND &&
- N0.getOperand(1).getOpcode() == ISD::Constant) {
- uint64_t Mask = cast<ConstantSDNode>(N0.getOperand(1))->getValue();
- unsigned NumBits = MVT::getSizeInBits(EVT);
- if ((Mask & (~0ULL << (NumBits-1))) == 0)
- return N0;
+ // fold (sext_in_reg x) -> (zext_in_reg x) if the sign bit is zero
+ if (MaskedValueIsZero(N0, 1ULL << (EVTBits-1), TLI))
+ return DAG.getNode(ISD::AND, N0.getValueType(), N0,
+ DAG.getConstant(~0ULL >> (64-EVTBits), VT));
+ // fold (sext_in_reg (srl x)) -> sra x
+ if (N0.getOpcode() == ISD::SRL &&
+ N0.getOperand(1).getOpcode() == ISD::Constant &&
+ cast<ConstantSDNode>(N0.getOperand(1))->getValue() == EVTBits) {
+ return DAG.getNode(ISD::SRA, N0.getValueType(), N0.getOperand(0),
+ N0.getOperand(1));
}
return SDOperand();
}
@@ -1590,8 +1585,7 @@
MVT::ValueType AType = N2.getValueType();
if (XType >= AType) {
// and (sra X, size(X)-1, A) -> "and (srl X, C2), A" iff A is a
- // single-bit constant. FIXME: remove once the dag combiner
- // exists.
+ // single-bit constant.
if (N2C && ((N2C->getValue() & (N2C->getValue()-1)) == 0)) {
unsigned ShCtV = Log2_64(N2C->getValue());
ShCtV = MVT::getSizeInBits(XType)-ShCtV-1;
@@ -1615,7 +1609,27 @@
return DAG.getNode(ISD::AND, AType, Shift, N2);
}
}
-
+
+ // fold select C, 16, 0 -> shl C, 4
+ if (N2C && N3C && N3C->isNullValue() && isPowerOf2_64(N2C->getValue()) &&
+ TLI.getSetCCResultContents() == TargetLowering::ZeroOrOneSetCCResult) {
+ // Get a SetCC of the condition
+ // FIXME: Should probably make sure that setcc is legal if we ever have a
+ // target where it isn't.
+ SDOperand Temp, SCC = DAG.getSetCC(TLI.getSetCCResultTy(), N0, N1, CC);
+ WorkList.push_back(SCC.Val);
+ // cast from setcc result type to select result type
+ if (AfterLegalize)
+ Temp = DAG.getZeroExtendInReg(SCC, N2.getValueType());
+ else
+ Temp = DAG.getNode(ISD::ZERO_EXTEND, N2.getValueType(), SCC);
+ WorkList.push_back(Temp.Val);
+ // shl setcc result by log2 n2c
+ return DAG.getNode(ISD::SHL, N2.getValueType(), Temp,
+ DAG.getConstant(Log2_64(N2C->getValue()),
+ TLI.getShiftAmountTy()));
+ }
+
// Check to see if this is the equivalent of setcc
// FIXME: Turn all of these into setcc if setcc if setcc is legal
// otherwise, go ahead with the folds.
More information about the llvm-commits
mailing list