diff options
| author | Sanjay Patel <spatel@rotateright.com> | 2019-06-25 12:49:35 +0000 |
|---|---|---|
| committer | Sanjay Patel <spatel@rotateright.com> | 2019-06-25 12:49:35 +0000 |
| commit | e4ef62291b46c261e6205e76f869902dcef8e0c0 (patch) | |
| tree | 4dc8d3cc3891d71ffc5bd70d2d2a51cc84116118 /llvm/lib/CodeGen | |
| parent | 42f44b387e4d741a2fc909cacc98b6f3d08c8718 (diff) | |
| download | bcm5719-llvm-e4ef62291b46c261e6205e76f869902dcef8e0c0.tar.gz bcm5719-llvm-e4ef62291b46c261e6205e76f869902dcef8e0c0.zip | |
[SDAG] improve expansion of ctpop+setcc
This should not cause any visible change in output, but it's
more efficient because we were producing non-canonical 'sub x, 1'
and 'setcc ugt x, 0'. As mentioned in the TODO, we should also
be handling the inverse predicate.
llvm-svn: 364302
Diffstat (limited to 'llvm/lib/CodeGen')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index b20c3a937fe..5fd9b469dfa 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -2700,17 +2700,20 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, return DAG.getSetCC(dl, VT, And, DAG.getConstant(0, dl, CTVT), CC); } - // (ctpop x) == 1 -> x && (x & x-1) == 0 iff ctpop is illegal. - if (Cond == ISD::SETEQ && C1 == 1 && - !isOperationLegalOrCustom(ISD::CTPOP, CTVT)) { - SDValue Sub = - DAG.getNode(ISD::SUB, dl, CTVT, CTOp, DAG.getConstant(1, dl, CTVT)); - SDValue And = DAG.getNode(ISD::AND, dl, CTVT, CTOp, Sub); - SDValue LHS = DAG.getSetCC(dl, VT, CTOp, DAG.getConstant(0, dl, CTVT), - ISD::SETUGT); - SDValue RHS = - DAG.getSetCC(dl, VT, And, DAG.getConstant(0, dl, CTVT), ISD::SETEQ); - return DAG.getNode(ISD::AND, dl, VT, LHS, RHS); + // If ctpop is not supported, expand a power-of-2 comparison based on it. + if (C1 == 1 && !isOperationLegalOrCustom(ISD::CTPOP, CTVT)) { + // (ctpop x) == 1 --> (x != 0) && ((x & x-1) == 0) + if (Cond == ISD::SETEQ) { + SDValue Zero = DAG.getConstant(0, dl, CTVT); + SDValue NegOne = DAG.getAllOnesConstant(dl, CTVT); + SDValue Add = DAG.getNode(ISD::ADD, dl, CTVT, CTOp, NegOne); + SDValue And = DAG.getNode(ISD::AND, dl, CTVT, CTOp, Add); + SDValue LHS = DAG.getSetCC(dl, VT, CTOp, Zero, ISD::SETNE); + SDValue RHS = DAG.getSetCC(dl, VT, And, Zero, ISD::SETEQ); + return DAG.getNode(ISD::AND, dl, VT, LHS, RHS); + } + // TODO: + // (ctpop x) != 1 --> (x == 0) || ((x & x-1) != 0) } } |

