Skip to content

Commit 5f848c6

Browse files
kill rdx register for mulx instead of specifying as fixed register for use
1 parent 7854142 commit 5f848c6

File tree

2 files changed

+20
-7
lines changed

2 files changed

+20
-7
lines changed

src/coreclr/jit/lsrabuild.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -787,8 +787,18 @@ regMaskTP LinearScan::getKillSetForMul(GenTreeOp* mulNode)
787787
// If we can use the mulx instruction, we don't need to kill RAX
788788
if (mulNode->IsUnsigned() && compiler->compOpportunisticallyDependsOn(InstructionSet_AVX2))
789789
{
790-
// For mulx we force one arg to RDX, but we do not modify it
791-
// keep killMask set to RBM_NONE
790+
// While we do not need to kill RDX, the register allocator
791+
// seems to produce less spills if we kill it than if we specify it as fixed register
792+
// for one of the operands.
793+
// If second operand is used from memory, we define op1 as fixed rd register, so we don't need to kill it.
794+
if (mulNode->gtGetOp2()->isUsedFromMemory())
795+
{
796+
killMask = RBM_NONE;
797+
}
798+
else
799+
{
800+
killMask = RBM_RDX;
801+
}
792802
}
793803
else
794804
{

src/coreclr/jit/lsraxarch.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3233,7 +3233,7 @@ int LinearScan::BuildMul(GenTree* tree)
32333233

32343234
bool isUnsignedMultiply = tree->IsUnsigned();
32353235
bool requiresOverflowCheck = tree->gtOverflowEx();
3236-
bool useMulx = tree->OperGet() != GT_MUL && isUnsignedMultiply &&
3236+
bool useMulx = !tree->OperIs(GT_MUL) && isUnsignedMultiply &&
32373237
compiler->compOpportunisticallyDependsOn(InstructionSet_AVX2);
32383238

32393239
// ToDo-APX : imul currently doesn't have rex2 support. So, cannot use R16-R31.
@@ -3250,15 +3250,18 @@ int LinearScan::BuildMul(GenTree* tree)
32503250
// Lowering has ensured that op1 is never the memory operand
32513251
assert(!op1->isUsedFromMemory());
32523252

3253-
// prefer to have the constant in RDX (op1) this is especially useful for MUL_HI usage
3254-
if (op2->IsCnsIntOrI())
3253+
SingleTypeRegSet srcCandidates1 = RBM_NONE;
3254+
3255+
// If one of the operands is a memory address, specify RDX for the other operand
3256+
if (op2->isUsedFromMemory())
32553257
{
3256-
std::swap(op1, op2);
3258+
// If op2 is a memory operand, we place it in RDX
3259+
srcCandidates1 = SRBM_RDX;
32573260
}
32583261

32593262
// In lowering, we place any memory operand in op2 so we default to placing op1 in RDX
32603263
// By selecting RDX here we don't have to kill it
3261-
srcCount = BuildOperandUses(op1, SRBM_RDX);
3264+
srcCount = BuildOperandUses(op1, srcCandidates1);
32623265
srcCount += BuildOperandUses(op2, RBM_NONE);
32633266
}
32643267
else

0 commit comments

Comments
 (0)