diff options
author | Sanjay Patel <spatel@rotateright.com> | 2016-12-14 22:59:14 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2016-12-14 22:59:14 +0000 |
commit | afee21a5b273ca1f150f85ecc8deb560e0ff3096 (patch) | |
tree | 864a528d362c4132995c01cced264f915ac7e046 /llvm/lib/CodeGen/SelectionDAG | |
parent | 1ebbd176b356a0c7d870fcef68f99e792759e9ed (diff) | |
download | bcm5719-llvm-afee21a5b273ca1f150f85ecc8deb560e0ff3096.tar.gz bcm5719-llvm-afee21a5b273ca1f150f85ecc8deb560e0ff3096.zip |
[DAG] allow more select folding for targets that have 'and not' (PR31175)
The original motivation for this patch comes from wanting to canonicalize
more IR to selects and also canonicalizing min/max.
If we're going to do that, we need more backend fixups to undo select codegen
when simpler ops will do. I chose AArch64 for the tests because that shows the
difference in the simplest way. This should fix:
https://llvm.org/bugs/show_bug.cgi?id=31175
Differential Revision: https://reviews.llvm.org/D27489
llvm-svn: 289738
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 829e8a6fb16..c38a420b7bf 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -14879,17 +14879,31 @@ bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect, SDValue LHS, SDValue DAGCombiner::foldSelectCCToShiftAnd(const SDLoc &DL, SDValue N0, SDValue N1, SDValue N2, SDValue N3, ISD::CondCode CC) { - // Check to see if we can perform the "gzip trick", transforming - // (select_cc setlt X, 0, A, 0) -> (and (sra X, size(X)-1), A) + // If this is a select where the false operand is zero and the compare is a + // check of the sign bit, see if we can perform the "gzip trick": + // select_cc setlt X, 0, A, 0 -> and (sra X, size(X)-1), A + // select_cc setgt X, 0, A, 0 -> and (not (sra X, size(X)-1)), A EVT XType = N0.getValueType(); EVT AType = N2.getValueType(); - if (!isNullConstant(N3) || CC != ISD::SETLT || !XType.bitsGE(AType)) + if (!isNullConstant(N3) || !XType.bitsGE(AType)) return SDValue(); - // (a < 0) ? b : 0 - // (a < 1) ? a : 0 - if (!(isNullConstant(N1) || (isOneConstant(N1) && N0 == N2))) + // If the comparison is testing for a positive value, we have to invert + // the sign bit mask, so only do that transform if the target has a bitwise + // 'and not' instruction (the invert is free). + if (CC == ISD::SETGT && TLI.hasAndNot(N2)) { + // (X > -1) ? A : 0 + // (X > 0) ? X : 0 <-- This is canonical signed max. + if (!(isAllOnesConstant(N1) || (isNullConstant(N1) && N0 == N2))) + return SDValue(); + } else if (CC == ISD::SETLT) { + // (X < 0) ? A : 0 + // (X < 1) ? X : 0 <-- This is un-canonicalized signed min. + if (!(isNullConstant(N1) || (isOneConstant(N1) && N0 == N2))) + return SDValue(); + } else { return SDValue(); + } // and (sra X, size(X)-1), A -> "and (srl X, C2), A" iff A is a single-bit // constant. @@ -14906,6 +14920,9 @@ SDValue DAGCombiner::foldSelectCCToShiftAnd(const SDLoc &DL, SDValue N0, AddToWorklist(Shift.getNode()); } + if (CC == ISD::SETGT) + Shift = DAG.getNOT(DL, Shift, AType); + return DAG.getNode(ISD::AND, DL, AType, Shift, N2); } @@ -14918,6 +14935,9 @@ SDValue DAGCombiner::foldSelectCCToShiftAnd(const SDLoc &DL, SDValue N0, AddToWorklist(Shift.getNode()); } + if (CC == ISD::SETGT) + Shift = DAG.getNOT(DL, Shift, AType); + return DAG.getNode(ISD::AND, DL, AType, Shift, N2); } |