From 98959b5434c4e1e4bd6b0e89f12cc7042566868e Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Mon, 9 May 2016 16:42:50 +0000 Subject: [PATCH] [TargetLowering] make helper function for SetCC + and optimizations (NFC) After looking at D19087 again, it occurred to me that we can do better. If we consolidate the valueHasExactlyOneBitSet() transforms, we won't incur extra overhead from calling it a 2nd time, and we can shrink SimplifySetCC() a bit. No functional change intended. Differential Revision: http://reviews.llvm.org/D20050 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@268932 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetLowering.h | 5 ++ lib/CodeGen/SelectionDAG/TargetLowering.cpp | 92 +++++++++++++---------------- 2 files changed, 45 insertions(+), 52 deletions(-) diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index ea7ef5d4db6..c47e3c0d963 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -3018,6 +3018,11 @@ public: /// Lower TLS global address SDNode for target independent emulated TLS model. virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const; + +private: + SDValue simplifySetCCWithAnd(EVT VT, SDValue N0, SDValue N1, + ISD::CondCode Cond, DAGCombinerInfo &DCI, + SDLoc DL) const; }; /// Given an LLVM IR type and return type attributes, compute the return value diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 6faad8b8151..7010347f12a 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1304,18 +1304,20 @@ bool TargetLowering::isExtendedTrueVal(const ConstantSDNode *N, EVT VT, llvm_unreachable("Unexpected enumeration."); } -/// If the target supports an 'and-not' or 'and-complement' logic operation, -/// try to use that to make a comparison operation more efficient. -static SDValue createAndNotSetCC(EVT VT, SDValue N0, SDValue N1, - ISD::CondCode Cond, SelectionDAG &DAG, - SDLoc dl) { +/// This helper function of SimplifySetCC tries to optimize the comparison when +/// either operand of the SetCC node is a bitwise-and instruction. +SDValue TargetLowering::simplifySetCCWithAnd(EVT VT, SDValue N0, SDValue N1, + ISD::CondCode Cond, + DAGCombinerInfo &DCI, + SDLoc DL) const { // Match these patterns in any of their permutations: // (X & Y) == Y // (X & Y) != Y if (N1.getOpcode() == ISD::AND && N0.getOpcode() != ISD::AND) std::swap(N0, N1); - if (N0.getOpcode() != ISD::AND || !N0.hasOneUse() || + EVT OpVT = N0.getValueType(); + if (N0.getOpcode() != ISD::AND || !OpVT.isInteger() || (Cond != ISD::SETEQ && Cond != ISD::SETNE)) return SDValue(); @@ -1330,24 +1332,37 @@ static SDValue createAndNotSetCC(EVT VT, SDValue N0, SDValue N1, return SDValue(); } - // Bail out if the compare operand that we want to turn into a zero is already - // a zero (otherwise, infinite loop). - auto *YConst = dyn_cast(Y); - if (YConst && YConst->isNullValue()) - return SDValue(); - - // We don't want to do this transform if the mask is a single bit because - // there are more efficient ways to deal with that case (for example, 'bt' on - // x86 or 'rlwinm' on PPC). - if (!DAG.getTargetLoweringInfo().hasAndNotCompare(Y) || - valueHasExactlyOneBitSet(Y, DAG)) - return SDValue(); + SelectionDAG &DAG = DCI.DAG; + SDValue Zero = DAG.getConstant(0, DL, OpVT); + if (valueHasExactlyOneBitSet(Y, DAG)) { + // Simplify X & Y == Y to X & Y != 0 if Y has exactly one bit set. + // Note that where Y is variable and is known to have at most one bit set + // (for example, if it is Z & 1) we cannot do this; the expressions are not + // equivalent when Y == 0. + Cond = ISD::getSetCCInverse(Cond, /*isInteger=*/true); + if (DCI.isBeforeLegalizeOps() || + isCondCodeLegal(Cond, N0.getSimpleValueType())) + return DAG.getSetCC(DL, VT, N0, Zero, Cond); + } else if (N0.hasOneUse() && hasAndNotCompare(Y)) { + // If the target supports an 'and-not' or 'and-complement' logic operation, + // try to use that to make a comparison operation more efficient. + // But don't do this transform if the mask is a single bit because there are + // more efficient ways to deal with that case (for example, 'bt' on x86 or + // 'rlwinm' on PPC). + + // Bail out if the compare operand that we want to turn into a zero is + // already a zero (otherwise, infinite loop). + auto *YConst = dyn_cast(Y); + if (YConst && YConst->isNullValue()) + return SDValue(); + + // Transform this into: ~X & Y == 0. + SDValue NotX = DAG.getNOT(SDLoc(X), X, OpVT); + SDValue NewAnd = DAG.getNode(ISD::AND, SDLoc(N0), OpVT, NotX, Y); + return DAG.getSetCC(DL, VT, NewAnd, Zero, Cond); + } - // Transform this into: ~X & Y == 0. - EVT OpVT = X.getValueType(); - SDValue NotX = DAG.getNOT(SDLoc(X), X, OpVT); - SDValue NewAnd = DAG.getNode(ISD::AND, SDLoc(N0), OpVT, NotX, Y); - return DAG.getSetCC(dl, VT, NewAnd, DAG.getConstant(0, dl, OpVT), Cond); + return SDValue(); } /// Try to simplify a setcc built with the specified operands and cc. If it is @@ -2134,32 +2149,8 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, } } - // Simplify x&y == y to x&y != 0 if y has exactly one bit set. - // Note that where y is variable and is known to have at most - // one bit set (for example, if it is z&1) we cannot do this; - // the expressions are not equivalent when y==0. - if (N0.getOpcode() == ISD::AND) - if (N0.getOperand(0) == N1 || N0.getOperand(1) == N1) { - if (valueHasExactlyOneBitSet(N1, DAG)) { - Cond = ISD::getSetCCInverse(Cond, /*isInteger=*/true); - if (DCI.isBeforeLegalizeOps() || - isCondCodeLegal(Cond, N0.getSimpleValueType())) { - SDValue Zero = DAG.getConstant(0, dl, N1.getValueType()); - return DAG.getSetCC(dl, VT, N0, Zero, Cond); - } - } - } - if (N1.getOpcode() == ISD::AND) - if (N1.getOperand(0) == N0 || N1.getOperand(1) == N0) { - if (valueHasExactlyOneBitSet(N0, DAG)) { - Cond = ISD::getSetCCInverse(Cond, /*isInteger=*/true); - if (DCI.isBeforeLegalizeOps() || - isCondCodeLegal(Cond, N1.getSimpleValueType())) { - SDValue Zero = DAG.getConstant(0, dl, N0.getValueType()); - return DAG.getSetCC(dl, VT, N1, Zero, Cond); - } - } - } + if (SDValue V = simplifySetCCWithAnd(VT, N0, N1, Cond, DCI, dl)) + return V; } // Fold away ALL boolean setcc's. @@ -2212,9 +2203,6 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, return N0; } - if (SDValue AndNotCC = createAndNotSetCC(VT, N0, N1, Cond, DAG, dl)) - return AndNotCC; - // Could not fold it. return SDValue(); } -- 2.11.0