浮点数相除
// Replace "val / dcon" with "val * (1.0 / dcon)" if dcon is a power of two.
// Powers of two within range are always exactly represented,
// so multiplication by the reciprocal is safe in this scenario
if (fgGlobalMorph && op2->IsCnsFltOrDbl())
{
double divisor = op2->AsDblCon()->DconValue();
if (((typ == TYP_DOUBLE) && FloatingPointUtils::hasPreciseReciprocal(divisor)) ||
((typ == TYP_FLOAT) && FloatingPointUtils::hasPreciseReciprocal(forceCastToFloat(divisor))))
{
oper = GT_MUL;
tree->ChangeOper(oper);
op2->AsDblCon()->SetDconValue(1.0 / divisor);
}
}
GenTree* Compiler::fgMorphSmpOp
当除数是一个浮点型立即数时GT_DIV改为GT_MUL (1/divisor),[https://github.com/dotnet/runtime/blob/main/src/coreclr/jit/morph.cpp]
当除数是2的幂时可以优化
将除法改为右移 a%b可以替换为 a & (b-1) 在低级化lowerconstdivormod
if (isDiv)
{
// perform the division by right shifting the adjusted dividend
divisor->AsIntCon()->SetIconValue(genLog2(absDivisorValue));
newDivMod = comp->gtNewOperNode(GT_RSH, type, adjustedDividend, divisor);
ContainCheckShiftRotate(newDivMod->AsOp());
if (divisorValue < 0)
{
// negate the result if the divisor is negative
newDivMod = comp->gtNewOperNode(GT_NEG, type, newDivMod);
ContainCheckNode(newDivMod);
}
}
else
{
// divisor % dividend = dividend - divisor x (dividend / divisor)
// divisor x (dividend / divisor) translates to (dividend >> log2(divisor)) << log2(divisor)
// which simply discards the low log2(divisor) bits, that's just dividend & ~(divisor - 1)
divisor->AsIntCon()->SetIconValue(~(absDivisorValue - 1));
newDivMod = comp->gtNewOperNode(GT_SUB, type,
comp->gtNewLclvNode(dividend->AsLclVar()->GetLclNum(), dividend->TypeGet()),
comp->gtNewOperNode(GT_AND, type, adjustedDividend, divisor));
}
// Remove the divisor and dividend nodes from the linear order,
// since we have reused them and will resequence the tree
BlockRange().Remove(divisor);
BlockRange().Remove(dividend);
// linearize and insert the new tree before the original divMod node
InsertTreeBeforeAndContainCheck(divMod, newDivMod);
BlockRange().Remove(divMod);
// replace the original divmod node with the new divmod tree
use.ReplaceWith(newDivMod);
*nextNode = newDivMod->gtNext;
return true;
}