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/SelectionDAG | |
| 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/SelectionDAG')
| -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)        }      }  | 

