add a SelectionDAG method to check if no common bits are set in two nodes; NFCI

This was suggested in:
http://reviews.llvm.org/D13956

and is a follow-on to:
http://reviews.llvm.org/rL252515
http://reviews.llvm.org/rL252519

This lets us remove logically equivalent/duplicated code from DAGCombiner and X86ISelDAGToDAG.

A corresponding function for IR instructions already exists in ValueTracking.

llvm-svn: 252539
This commit is contained in:
Sanjay Patel 2015-11-09 23:31:38 +00:00
parent e68649279e
commit 533c10c651
4 changed files with 22 additions and 33 deletions

View File

@ -1217,6 +1217,10 @@ public:
/// other positive zero.
bool isEqualTo(SDValue A, SDValue B) const;
/// Return true if A and B have no common bits set. As an example, this can
/// allow an 'add' to be transformed into an 'or'.
bool haveNoCommonBitsSet(SDValue A, SDValue B) const;
/// Utility function used by legalize and lowering to
/// "unroll" a vector operation by splitting out the scalars and operating
/// on each element individually. If the ResNE is 0, fully unroll the vector

View File

@ -1743,22 +1743,9 @@ SDValue DAGCombiner::visitADD(SDNode *N) {
return SDValue(N, 0);
// fold (a+b) -> (a|b) iff a and b share no bits.
if (VT.isInteger() && !VT.isVector()) {
APInt LHSZero, LHSOne;
APInt RHSZero, RHSOne;
DAG.computeKnownBits(N0, LHSZero, LHSOne);
if (LHSZero.getBoolValue()) {
DAG.computeKnownBits(N1, RHSZero, RHSOne);
// If all possibly-set bits on the LHS are clear on the RHS, return an OR.
// If all possibly-set bits on the RHS are clear on the LHS, return an OR.
if ((RHSZero & ~LHSZero) == ~LHSZero || (LHSZero & ~RHSZero) == ~RHSZero){
if (!LegalOperations || TLI.isOperationLegal(ISD::OR, VT))
return DAG.getNode(ISD::OR, SDLoc(N), VT, N0, N1);
}
}
}
if ((!LegalOperations || TLI.isOperationLegal(ISD::OR, VT)) &&
VT.isInteger() && !VT.isVector() && DAG.haveNoCommonBitsSet(N0, N1))
return DAG.getNode(ISD::OR, SDLoc(N), VT, N0, N1);
// fold (add x, shl(0 - y, n)) -> sub(x, shl(y, n))
if (N1.getOpcode() == ISD::SHL && N1.getOperand(0).getOpcode() == ISD::SUB &&

View File

@ -2833,6 +2833,16 @@ bool SelectionDAG::isEqualTo(SDValue A, SDValue B) const {
return false;
}
bool SelectionDAG::haveNoCommonBitsSet(SDValue A, SDValue B) const {
assert(A.getValueType() == B.getValueType() &&
"Values must have the same type");
APInt AZero, AOne;
APInt BZero, BOne;
computeKnownBits(A, AZero, AOne);
computeKnownBits(B, BZero, BOne);
return (AZero | BZero).isAllOnesValue();
}
/// getNode - Gets or creates the specified node.
///
SDValue SelectionDAG::getNode(unsigned Opcode, SDLoc DL, EVT VT) {

View File

@ -1338,29 +1338,17 @@ bool X86DAGToDAGISel::matchAddressRecursively(SDValue N, X86ISelAddressMode &AM,
return false;
break;
case ISD::OR: {
// TODO: The bit-checking logic should be put into a helper function and
// used by DAGCombiner.
case ISD::OR:
// We want to look through a transform in InstCombine and DAGCombiner that
// turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'.
APInt LHSZero, LHSOne;
APInt RHSZero, RHSOne;
CurDAG->computeKnownBits(N.getOperand(0), LHSZero, LHSOne);
CurDAG->computeKnownBits(N.getOperand(1), RHSZero, RHSOne);
// If we know that there are no common bits set by the operands of this
// 'or', it is equivalent to an 'add'. For example:
// (or (and x, 1), (shl y, 3)) --> (add (and x, 1), (shl y, 3))
// Example: (or (and x, 1), (shl y, 3)) --> (add (and x, 1), (shl y, 3))
// An 'lea' can then be used to match the shift (multiply) and add:
// and $1, %esi
// lea (%rsi, %rdi, 8), %rax
if ((LHSZero | RHSZero).isAllOnesValue())
if (!matchAdd(N, AM, Depth))
return false;
if (CurDAG->haveNoCommonBitsSet(N.getOperand(0), N.getOperand(1)) &&
!matchAdd(N, AM, Depth))
return false;
break;
}
case ISD::AND: {
// Perform some heroic transforms on an and of a constant-count shift