From: Steve MacLean, Qualcomm Datacenter Technologies Inc Date: Tue, 5 Sep 2017 23:04:22 +0000 (-0400) Subject: [Arm64] Allow a%b to a&(b-1) transform X-Git-Tag: accepted/tizen/base/20180629.140029~670^2~61^2~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=53c3f6dad573ee6e589c84974df57a148b18b1e0;p=platform%2Fupstream%2Fcoreclr.git [Arm64] Allow a%b to a&(b-1) transform For a % b, if b is an integer const power of two Mod a % b can be tranformed to a & (b - 1). Allow transform if (isPow2(b >> 1)) --- diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp index e7f173c..d910250 100644 --- a/src/jit/morph.cpp +++ b/src/jit/morph.cpp @@ -11876,12 +11876,31 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) // // a % b = a - (a / b) * b; // - // NOTE: we should never need to perform this transformation when remorphing, since global morphing - // should already have done so and we do not introduce new modulus nodes in later phases. - assert(!optValnumCSE_phase); - tree = fgMorphModToSubMulDiv(tree->AsOp()); - op1 = tree->gtOp.gtOp1; - op2 = tree->gtOp.gtOp2; + // Use the suggested transform unless the special case tranform works: + // + // a % b = a & (b - 1); + // + { + bool doMorph = !op2->IsIntegralConst() || op1->IsCnsIntOrI() || (tree->OperGet() == GT_MOD); + + if (!doMorph) + { + size_t divisorValue = (tree->OperGet() == GT_MOD) && (tree->TypeGet() == TYP_INT) + ? op2->AsIntCon()->IconValue() & UINT32_MAX + : op2->AsIntCon()->IconValue(); + + doMorph |= !isPow2(divisorValue); + } + + if (doMorph) + { + assert(!optValnumCSE_phase); + + tree = fgMorphModToSubMulDiv(tree->AsOp()); + op1 = tree->gtOp.gtOp1; + op2 = tree->gtOp.gtOp2; + } + } #else //_TARGET_ARM64_ // If b is not a power of 2 constant then lowering replaces a % b // with a - (a / b) * b and applies magic division optimization to