From 512052a88e8f1b0bb874f741fe72fb398d12ffbc Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Mon, 9 Nov 2015 23:31:38 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252539 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/SelectionDAG.h | 4 ++++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 19 +++---------------- lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 10 ++++++++++ lib/Target/X86/X86ISelDAGToDAG.cpp | 22 +++++----------------- 4 files changed, 22 insertions(+), 33 deletions(-) diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index f9a760fb2e4..8dfdd902994 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -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 diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index a1ea6d829f6..2dd71bd4e7f 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -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 && diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 3e7f466d89d..90ab785b2a4 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -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) { diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index 0cbeda91ccc..868ae4e19e5 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -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 -- 2.34.1