diff options
| author | Simon Pilgrim <llvm-dev@redking.me.uk> | 2019-01-22 13:44:49 +0000 |
|---|---|---|
| committer | Simon Pilgrim <llvm-dev@redking.me.uk> | 2019-01-22 13:44:49 +0000 |
| commit | 933673d8786a905f77b3366f1a6630ab45f6db20 (patch) | |
| tree | 926b0513cc8bbdea7f210cd9ce4462491788ac69 /llvm/lib/Target/X86 | |
| parent | 6202a3ad67d776179cb2952cd1b3dafcc2d04998 (diff) | |
| download | bcm5719-llvm-933673d8786a905f77b3366f1a6630ab45f6db20.tar.gz bcm5719-llvm-933673d8786a905f77b3366f1a6630ab45f6db20.zip | |
[X86][SSE] Canonicalize OR(AND(X,C),AND(Y,~C)) -> OR(AND(X,C),ANDNP(C,Y))
For constant bit select patterns, replace one AND with a ANDNP, allowing us to reuse the constant mask. Only do this if the mask has multiple uses (to avoid losing load folding) or if we have XOP as its VPCMOV can handle most folding commutations.
This also requires computeKnownBitsForTargetNode support for X86ISD::ANDNP and X86ISD::FOR to prevent regressions in fabs/fcopysign patterns.
Differential Revision: https://reviews.llvm.org/D55935
llvm-svn: 351819
Diffstat (limited to 'llvm/lib/Target/X86')
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index a800a42818b..9a1341b81c7 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -30233,6 +30233,27 @@ void X86TargetLowering::computeKnownBitsForTargetNode(const SDValue Op, Known = Known.trunc(BitWidth); break; } + case X86ISD::ANDNP: { + KnownBits Known2; + Known = DAG.computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); + Known2 = DAG.computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); + + // ANDNP = (~X & Y); + Known.One &= Known2.Zero; + Known.Zero |= Known2.One; + break; + } + case X86ISD::FOR: { + KnownBits Known2; + Known = DAG.computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); + Known2 = DAG.computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); + + // Output known-0 bits are only known if clear in both the LHS & RHS. + Known.Zero &= Known2.Zero; + // Output known-1 are known to be set if set in either the LHS | RHS. + Known.One |= Known2.One; + break; + } case X86ISD::CMOV: { Known = DAG.computeKnownBits(Op.getOperand(1), Depth+1); // If we don't know any bits, early out. @@ -36519,6 +36540,52 @@ static SDValue combineAnd(SDNode *N, SelectionDAG &DAG, return SDValue(); } +// Canonicalize OR(AND(X,C),AND(Y,~C)) -> OR(AND(X,C),ANDNP(C,Y)) +static SDValue canonicalizeBitSelect(SDNode *N, SelectionDAG &DAG, + const X86Subtarget &Subtarget) { + assert(N->getOpcode() == ISD::OR && "Unexpected Opcode"); + + EVT VT = N->getValueType(0); + if (!VT.isVector()) + return SDValue(); + + SDValue N0 = peekThroughBitcasts(N->getOperand(0)); + SDValue N1 = peekThroughBitcasts(N->getOperand(1)); + if (N0.getOpcode() != ISD::AND || N1.getOpcode() != ISD::AND) + return SDValue(); + + // On XOP we'll lower to PCMOV so accept one use, otherwise only + // do this if either mask has multiple uses already. + if (!(Subtarget.hasXOP() || !N0.getOperand(1).hasOneUse() || + !N1.getOperand(1).hasOneUse())) + return SDValue(); + + // Attempt to extract constant byte masks. + APInt UndefElts0, UndefElts1; + SmallVector<APInt, 32> EltBits0, EltBits1; + if (!getTargetConstantBitsFromNode(N0.getOperand(1), 8, UndefElts0, EltBits0, + false, false)) + return SDValue(); + if (!getTargetConstantBitsFromNode(N1.getOperand(1), 8, UndefElts1, EltBits1, + false, false)) + return SDValue(); + + for (unsigned i = 0, e = EltBits0.size(); i != e; ++i) { + // TODO - add UNDEF elts support. + if (UndefElts0[i] || UndefElts1[i]) + return SDValue(); + if (EltBits0[i] != ~EltBits1[i]) + return SDValue(); + } + + SDLoc DL(N); + SDValue X = N->getOperand(0); + SDValue Y = + DAG.getNode(X86ISD::ANDNP, DL, VT, DAG.getBitcast(VT, N0.getOperand(1)), + DAG.getBitcast(VT, N1.getOperand(0))); + return DAG.getNode(ISD::OR, DL, VT, X, Y); +} + // Try to match OR(AND(~MASK,X),AND(MASK,Y)) logic pattern. static bool matchLogicBlend(SDNode *N, SDValue &X, SDValue &Y, SDValue &Mask) { if (N->getOpcode() != ISD::OR) @@ -36781,6 +36848,9 @@ static SDValue combineOr(SDNode *N, SelectionDAG &DAG, if (SDValue FPLogic = convertIntLogicToFPLogic(N, DAG, Subtarget)) return FPLogic; + if (SDValue R = canonicalizeBitSelect(N, DAG, Subtarget)) + return R; + if (SDValue R = combineLogicBlendIntoPBLENDV(N, DAG, Subtarget)) return R; |

