diff options
author | Simon Pilgrim <llvm-dev@redking.me.uk> | 2019-02-26 11:27:53 +0000 |
---|---|---|
committer | Simon Pilgrim <llvm-dev@redking.me.uk> | 2019-02-26 11:27:53 +0000 |
commit | 810fa04ac7e367ed1aa736f2c54d980bc6fc09f1 (patch) | |
tree | 768fbe18dd07cfa04df8f55bd0358663294cb933 /llvm/lib/CodeGen | |
parent | 8335fd1923c1b7d9772dcc0e70a7d51f3773ecc0 (diff) | |
download | bcm5719-llvm-810fa04ac7e367ed1aa736f2c54d980bc6fc09f1.tar.gz bcm5719-llvm-810fa04ac7e367ed1aa736f2c54d980bc6fc09f1.zip |
[LegalizeDAG] Expand SADDO/SSUBO using SADDSAT/SSUBSAT (PR37763)
If SADDSAT/SSUBSAT are legal, then we can expand SADDO/SSUBO by performing a ADD/SUB and a SADDO/SSUBO and then compare the results.
I looked at doing this for UADDO/USUBO as well but as we don't have to do as many range comparisons I didn't see any/much benefit.
Differential Revision: https://reviews.llvm.org/D58637
llvm-svn: 354866
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 4ee0b933b9e..0e5ba3453c1 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -3261,13 +3261,25 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) { case ISD::SSUBO: { SDValue LHS = Node->getOperand(0); SDValue RHS = Node->getOperand(1); - SDValue Sum = DAG.getNode(Node->getOpcode() == ISD::SADDO ? - ISD::ADD : ISD::SUB, dl, LHS.getValueType(), - LHS, RHS); + bool IsAdd = Node->getOpcode() == ISD::SADDO; + + SDValue Sum = DAG.getNode(IsAdd ? ISD::ADD : ISD::SUB, dl, + LHS.getValueType(), LHS, RHS); Results.push_back(Sum); + EVT ResultType = Node->getValueType(1); EVT OType = getSetCCResultType(Node->getValueType(0)); + // If SADDSAT/SSUBSAT is legal, compare results to detect overflow. + unsigned OpcSat = IsAdd ? ISD::SADDSAT : ISD::SSUBSAT; + if (TLI.isOperationLegalOrCustom(OpcSat, LHS.getValueType())) { + SDValue Sat = DAG.getNode(OpcSat, dl, LHS.getValueType(), LHS, RHS); + SDValue SetCC = DAG.getSetCC(dl, OType, Sum, Sat, ISD::SETNE); + Results.push_back( + DAG.getBoolExtOrTrunc(SetCC, dl, ResultType, ResultType)); + break; + } + SDValue Zero = DAG.getConstant(0, dl, LHS.getValueType()); // LHSSign -> LHS >= 0 @@ -3281,8 +3293,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) { SDValue LHSSign = DAG.getSetCC(dl, OType, LHS, Zero, ISD::SETGE); SDValue RHSSign = DAG.getSetCC(dl, OType, RHS, Zero, ISD::SETGE); SDValue SignsMatch = DAG.getSetCC(dl, OType, LHSSign, RHSSign, - Node->getOpcode() == ISD::SADDO ? - ISD::SETEQ : ISD::SETNE); + IsAdd ? ISD::SETEQ : ISD::SETNE); SDValue SumSign = DAG.getSetCC(dl, OType, Sum, Zero, ISD::SETGE); SDValue SumSignNE = DAG.getSetCC(dl, OType, LHSSign, SumSign, ISD::SETNE); @@ -3296,6 +3307,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) { SDValue LHS = Node->getOperand(0); SDValue RHS = Node->getOperand(1); bool IsAdd = Node->getOpcode() == ISD::UADDO; + // If ADD/SUBCARRY is legal, use that instead. unsigned OpcCarry = IsAdd ? ISD::ADDCARRY : ISD::SUBCARRY; if (TLI.isOperationLegalOrCustom(OpcCarry, Node->getValueType(0))) { |