Skip to content

Commit

Permalink
[DAGCombiner] Handle correctly non-splat power of 2 -1 divisor (PR37119)
Browse files Browse the repository at this point in the history
The combine added in commit 329525 overlooked the case where one, but not all, of the divisor elements is -1, -1 is the only power of two value for which the sdiv expansion recipe breaks.

Thanks to @zvi for the original patch.

Differential Revision: https://reviews.llvm.org/D45806

llvm-svn: 336048
  • Loading branch information
RKSimon committed Jun 30, 2018
1 parent 14cd199 commit fae3377
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 275 deletions.
16 changes: 9 additions & 7 deletions llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Expand Up @@ -3051,11 +3051,8 @@ SDValue DAGCombiner::visitSDIV(SDNode *N) {
auto IsPowerOfTwo = [](ConstantSDNode *C) {
if (C->isNullValue() || C->isOpaque())
return false;
if (C->getAPIntValue().isAllOnesValue())
return false;
if (C->getAPIntValue().isMinSignedValue())
return false;

if (C->getAPIntValue().isPowerOf2())
return true;
if ((-C->getAPIntValue()).isPowerOf2())
Expand Down Expand Up @@ -3095,6 +3092,15 @@ SDValue DAGCombiner::visitSDIV(SDNode *N) {
SDValue Sra = DAG.getNode(ISD::SRA, DL, VT, Add, C1);
AddToWorklist(Sra.getNode());

// Special case: (sdiv X, 1) -> X
// Special Case: (sdiv X, -1) -> 0-X
SDValue One = DAG.getConstant(1, DL, VT);
SDValue AllOnes = DAG.getAllOnesConstant(DL, VT);
SDValue IsOne = DAG.getSetCC(DL, CCVT, N1, One, ISD::SETEQ);
SDValue IsAllOnes = DAG.getSetCC(DL, CCVT, N1, AllOnes, ISD::SETEQ);
SDValue IsOneOrAllOnes = DAG.getNode(ISD::OR, DL, CCVT, IsOne, IsAllOnes);
Sra = DAG.getSelect(DL, VT, IsOneOrAllOnes, N0, Sra);

// If dividing by a positive value, we're done. Otherwise, the result must
// be negated.
SDValue Zero = DAG.getConstant(0, DL, VT);
Expand All @@ -3103,10 +3109,6 @@ SDValue DAGCombiner::visitSDIV(SDNode *N) {
// FIXME: Use SELECT_CC once we improve SELECT_CC constant-folding.
SDValue IsNeg = DAG.getSetCC(DL, CCVT, N1, Zero, ISD::SETLT);
SDValue Res = DAG.getSelect(DL, VT, IsNeg, Sub, Sra);
// Special case: (sdiv X, 1) -> X
SDValue One = DAG.getConstant(1, DL, VT);
SDValue IsOne = DAG.getSetCC(DL, CCVT, N1, One, ISD::SETEQ);
Res = DAG.getSelect(DL, VT, IsOne, N0, Res);
return Res;
}

Expand Down

0 comments on commit fae3377

Please sign in to comment.