Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/coreclr/jit/lsra.h
Original file line number Diff line number Diff line change
Expand Up @@ -1955,6 +1955,7 @@ class LinearScan : public RegAllocInterface
#ifdef TARGET_XARCH
int BuildRMWUses(
GenTree* node, GenTree* op1, GenTree* op2, SingleTypeRegSet op1Candidates, SingleTypeRegSet op2Candidates);
int BuildUnaryRMWUses(GenTree* op1, SingleTypeRegSet candidates = RBM_NONE);
inline SingleTypeRegSet BuildEvexIncompatibleMask(GenTree* tree);
inline SingleTypeRegSet ForceLowGprForApx(GenTree* tree,
SingleTypeRegSet candidates = RBM_NONE,
Expand Down
40 changes: 38 additions & 2 deletions src/coreclr/jit/lsraxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,13 +424,21 @@ int LinearScan::BuildNode(GenTree* tree)
}
else
{
srcCount = BuildOperandUses(tree->gtGetOp1());
srcCount = BuildUnaryRMWUses(tree->gtGetOp1());
}
BuildDef(tree);
break;

case GT_NOT:
srcCount = BuildOperandUses(tree->gtGetOp1());
srcCount = BuildUnaryRMWUses(tree->gtGetOp1());
Comment thread
tannergooding marked this conversation as resolved.
BuildDef(tree);
break;

case GT_BSWAP:
case GT_BSWAP16:
// These are "bswap reg" / "ror reg.16, 8", which are RMW, unless the
// operand is contained, in which case we generate a "movbe reg, [mem]".
srcCount = BuildUnaryRMWUses(tree->gtGetOp1());
BuildDef(tree);
break;

Expand Down Expand Up @@ -820,6 +828,34 @@ bool LinearScan::isRMWRegOper(GenTree* tree)
}
}

//------------------------------------------------------------------------
// BuildUnaryRMWUses: Build the use RefPosition for a unary node whose instruction
// form is read-modify-write, e.g. "neg reg", "not reg", "bswap reg".
//
// Arguments:
// op1 - the operand of the unary node
// candidates - the register candidates for the use
//
// Return Value:
// The number of sources consumed by the node.
//
// Notes:
// Unlike the binary case handled by BuildRMWUses, there is no second operand that
// could be assigned the target register, so no `delayRegFree` is needed here; we
// only preference the operand to the target so that codegen can elide the "mov"
// that emitIns_BASE_R_R() would otherwise emit ahead of the instruction.
Comment on lines +843 to +846
//
int LinearScan::BuildUnaryRMWUses(GenTree* op1, SingleTypeRegSet candidates)
{
if (op1->isContained())
{
return BuildOperandUses(op1, candidates);
}

tgtPrefUse = BuildUse(op1, candidates);
return 1;
}

// Support for building RefPositions for RMW nodes.
int LinearScan::BuildRMWUses(
GenTree* node, GenTree* op1, GenTree* op2, SingleTypeRegSet op1Candidates, SingleTypeRegSet op2Candidates)
Expand Down
Loading