From 35b28bf537a563d72198a5456e827da727f62d7e Mon Sep 17 00:00:00 2001 From: mad1081 Date: Sun, 3 May 2026 23:47:47 +0500 Subject: [PATCH] fix: expand GT_UMOD with constant divisor in morph to enable CSE On XARCH, the transformation of `a % b` into `a - (a / b) * b` was only applied for signed GT_MOD, not unsigned GT_UMOD. This prevented CSE from recognizing the shared division in patterns like `x / 3` and `x % 3`, causing two separate div instructions to be emitted. Extends the existing else-if condition to include GT_UMOD so unsigned modulo with a non-power-of-2 constant divisor is also expanded during morph, matching the behavior already present for GT_MOD. --- src/coreclr/jit/morph.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index e713a94e0e095f..f1edf7006999b2 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -7330,12 +7330,13 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA // for the mod operator. else #else - // XARCH only applies this transformation if we know - // that magic division will be used - which is determined - // when 'b' is not a power of 2 constant and mod operator is signed. - // Lowering for XARCH does this optimization already, - // but is also done here to take advantage of CSE. - else if (tree->OperIs(GT_MOD) && op2->IsIntegralConst() && !op2->IsIntegralConstAbsPow2()) + // XARCH only applies this transformation if we know that magic division will be used, + // which is when 'b' is a non-power-of-2 constant. For signed mod, power-of-2 divisors + // are handled by lowering via a special path. For unsigned mod, power-of-2 divisors are + // already handled above via fgMorphUModToAndSub. + // This is done here in morph (rather than waiting for lowering) to expose CSE opportunities + // when both `a / b` and `a % b` appear with the same constant divisor. + else if (tree->OperIs(GT_MOD, GT_UMOD) && op2->IsIntegralConst() && !op2->IsIntegralConstAbsPow2()) #endif { // Transformation: a % b = a - (a / b) * b;