Merge pull request #8206 from pgavlin/DivModLowerAndNewTempAssignIssues
authorPat Gavlin <pgavlin@gmail.com>
Tue, 22 Nov 2016 00:48:04 +0000 (16:48 -0800)
committerGitHub <noreply@github.com>
Tue, 22 Nov 2016 00:48:04 +0000 (16:48 -0800)
Fix two bugs revealed during internal testing.

1  2 
src/jit/gentree.cpp
src/jit/lower.cpp

Simple merge
@@@ -3763,119 -3676,10 +3763,119 @@@ GenTree* Lowering::LowerSignedDivOrMod(
  
      if (!isPow2(absDivisorValue))
      {
 +#ifdef _TARGET_XARCH_
 +        ssize_t magic;
 +        int     shift;
 +
 +        if (type == TYP_INT)
 +        {
 +            magic = GetSignedMagicNumberForDivide<int32_t>(static_cast<int32_t>(divisorValue), &shift);
 +        }
 +        else
 +        {
 +#ifdef _TARGET_64BIT_
 +            magic = GetSignedMagicNumberForDivide<int64_t>(static_cast<int64_t>(divisorValue), &shift);
 +#else
 +            unreached();
 +#endif
 +        }
 +
 +        divisor->gtIntConCommon.SetIconValue(magic);
 +
 +        // Insert a new GT_MULHI node in front of the existing GT_DIV/GT_MOD node.
 +        // The existing node will later be transformed into a GT_ADD/GT_SUB that
 +        // computes the final result. This way don't need to find and change the
 +        // use of the existing node.
 +        GenTree* mulhi = comp->gtNewOperNode(GT_MULHI, type, divisor, dividend);
 +        BlockRange().InsertBefore(divMod, mulhi);
 +
 +        // mulhi was the easy part. Now we need to generate different code depending
 +        // on the divisor value:
 +        // For 3 we need:
 +        //     div = signbit(mulhi) + mulhi
 +        // For 5 we need:
 +        //     div = signbit(mulhi) + sar(mulhi, 1) ; requires shift adjust
 +        // For 7 we need:
 +        //     mulhi += dividend                    ; requires add adjust
 +        //     div = signbit(mulhi) + sar(mulhi, 2) ; requires shift adjust
 +        // For -3 we need:
 +        //     mulhi -= dividend                    ; requires sub adjust
 +        //     div = signbit(mulhi) + sar(mulhi, 1) ; requires shift adjust
 +        bool     requiresAddSubAdjust     = signum(divisorValue) != signum(magic);
 +        bool     requiresShiftAdjust      = shift != 0;
 +        bool     requiresDividendMultiuse = requiresAddSubAdjust || !isDiv;
 +        unsigned curBBWeight              = comp->compCurBB->getBBWeight(comp);
 +        unsigned dividendLclNum           = BAD_VAR_NUM;
 +
 +        if (requiresDividendMultiuse)
 +        {
 +            LIR::Use dividendUse(BlockRange(), &mulhi->gtOp.gtOp2, mulhi);
 +            dividendLclNum = dividendUse.ReplaceWithLclVar(comp, curBBWeight);
 +        }
 +
 +        GenTree* adjusted;
 +
 +        if (requiresAddSubAdjust)
 +        {
 +            dividend = comp->gtNewLclvNode(dividendLclNum, type);
 +            comp->lvaTable[dividendLclNum].incRefCnts(curBBWeight, comp);
 +
 +            adjusted = comp->gtNewOperNode(divisorValue > 0 ? GT_ADD : GT_SUB, type, mulhi, dividend);
 +            BlockRange().InsertBefore(divMod, dividend, adjusted);
 +        }
 +        else
 +        {
 +            adjusted = mulhi;
 +        }
 +
 +        GenTree* shiftBy = comp->gtNewIconNode(genTypeSize(type) * 8 - 1, type);
 +        GenTree* signBit = comp->gtNewOperNode(GT_RSZ, type, adjusted, shiftBy);
 +        BlockRange().InsertBefore(divMod, shiftBy, signBit);
 +
 +        LIR::Use adjustedUse(BlockRange(), &signBit->gtOp.gtOp1, signBit);
 +        unsigned adjustedLclNum = adjustedUse.ReplaceWithLclVar(comp, curBBWeight);
 +        adjusted                = comp->gtNewLclvNode(adjustedLclNum, type);
 +        comp->lvaTable[adjustedLclNum].incRefCnts(curBBWeight, comp);
 +        BlockRange().InsertBefore(divMod, adjusted);
 +
 +        if (requiresShiftAdjust)
 +        {
 +            shiftBy  = comp->gtNewIconNode(shift, TYP_INT);
 +            adjusted = comp->gtNewOperNode(GT_RSH, type, adjusted, shiftBy);
 +            BlockRange().InsertBefore(divMod, shiftBy, adjusted);
 +        }
 +
 +        if (isDiv)
 +        {
 +            divMod->SetOperRaw(GT_ADD);
 +            divMod->gtOp.gtOp1 = adjusted;
 +            divMod->gtOp.gtOp2 = signBit;
 +        }
 +        else
 +        {
 +            GenTree* div = comp->gtNewOperNode(GT_ADD, type, adjusted, signBit);
 +
 +            dividend = comp->gtNewLclvNode(dividendLclNum, type);
 +            comp->lvaTable[dividendLclNum].incRefCnts(curBBWeight, comp);
 +
 +            // divisor % dividend = dividend - divisor x div
 +            GenTree* divisor = comp->gtNewIconNode(divisorValue, type);
 +            GenTree* mul     = comp->gtNewOperNode(GT_MUL, type, div, divisor);
 +            BlockRange().InsertBefore(divMod, dividend, div, divisor, mul);
 +
 +            divMod->SetOperRaw(GT_SUB);
 +            divMod->gtOp.gtOp1 = dividend;
 +            divMod->gtOp.gtOp2 = mul;
 +        }
 +
 +        return mulhi;
 +#else
 +        // Currently there's no GT_MULHI for ARM32/64
          return next;
 +#endif
      }
  
-     // We're committed to the conversion now. Go find the use.
+     // We're committed to the conversion now. Go find the use if any.
      LIR::Use use;
      if (!BlockRange().TryGetUse(node, &use))
      {