Skip to content

Commit

Permalink
[arm64] JIT: Recognize sbfiz/ubfiz idioms (#61045)
Browse files Browse the repository at this point in the history
  • Loading branch information
EgorBo committed Nov 4, 2021
1 parent 22f0683 commit bfc5ebc
Show file tree
Hide file tree
Showing 8 changed files with 807 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/coreclr/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
void genCodeForJumpTrue(GenTreeOp* jtrue);
#ifdef TARGET_ARM64
void genCodeForJumpCompare(GenTreeOp* tree);
void genCodeForBfiz(GenTreeOp* tree);
#endif // TARGET_ARM64

#if defined(FEATURE_EH_FUNCLETS)
Expand Down
26 changes: 26 additions & 0 deletions src/coreclr/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9564,4 +9564,30 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind)
}
}

//------------------------------------------------------------------------
// genCodeForBfiz: Generates the code sequence for a GenTree node that
// represents a bitfield insert in zero with sign/zero extension.
//
// Arguments:
// tree - the bitfield insert in zero node.
//
void CodeGen::genCodeForBfiz(GenTreeOp* tree)
{
assert(tree->OperIs(GT_BFIZ));

emitAttr size = emitActualTypeSize(tree);
unsigned shiftBy = (unsigned)tree->gtGetOp2()->AsIntCon()->IconValue();
unsigned shiftByImm = shiftBy & (emitter::getBitWidth(size) - 1);
GenTreeCast* cast = tree->gtGetOp1()->AsCast();
GenTree* castOp = cast->CastOp();

genConsumeRegs(castOp);
unsigned srcBits = varTypeIsSmall(cast->CastToType()) ? genTypeSize(cast->CastToType()) * BITS_PER_BYTE
: genTypeSize(castOp) * BITS_PER_BYTE;
const bool isUnsigned = cast->IsUnsigned() || varTypeIsUnsigned(cast->CastToType());
GetEmitter()->emitIns_R_R_I_I(isUnsigned ? INS_ubfiz : INS_sbfiz, size, tree->GetRegNum(), castOp->GetRegNum(),
(int)shiftByImm, (int)srcBits);
genProduceReg(tree);
}

#endif // TARGET_ARM64
12 changes: 8 additions & 4 deletions src/coreclr/jit/codegenarmarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
case GT_SWAP:
genCodeForSwap(treeNode->AsOp());
break;

case GT_BFIZ:
genCodeForBfiz(treeNode->AsOp());
break;
#endif // TARGET_ARM64

case GT_JMP:
Expand Down Expand Up @@ -1614,23 +1618,23 @@ void CodeGen::genCodeForShift(GenTree* tree)
genTreeOps oper = tree->OperGet();
instruction ins = genGetInsForOper(oper, targetType);
emitAttr size = emitActualTypeSize(tree);
regNumber dstReg = tree->GetRegNum();

assert(tree->GetRegNum() != REG_NA);
assert(dstReg != REG_NA);

genConsumeOperands(tree->AsOp());

GenTree* operand = tree->gtGetOp1();
GenTree* shiftBy = tree->gtGetOp2();
if (!shiftBy->IsCnsIntOrI())
{
GetEmitter()->emitIns_R_R_R(ins, size, tree->GetRegNum(), operand->GetRegNum(), shiftBy->GetRegNum());
GetEmitter()->emitIns_R_R_R(ins, size, dstReg, operand->GetRegNum(), shiftBy->GetRegNum());
}
else
{
unsigned immWidth = emitter::getBitWidth(size); // For ARM64, immWidth will be set to 32 or 64
unsigned shiftByImm = (unsigned)shiftBy->AsIntCon()->gtIconVal & (immWidth - 1);

GetEmitter()->emitIns_R_R_I(ins, size, tree->GetRegNum(), operand->GetRegNum(), shiftByImm);
GetEmitter()->emitIns_R_R_I(ins, size, dstReg, operand->GetRegNum(), shiftByImm);
}

genProduceReg(tree);
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/jit/gtlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ GTNODE(PHI_ARG , GenTreePhiArg ,0,(GTK_LEAF|GTK_LOCAL)) // phi

GTNODE(JMPTABLE , GenTree ,0, (GTK_LEAF|GTK_NOCONTAIN)) // Generates the jump table for switches
GTNODE(SWITCH_TABLE , GenTreeOp ,0, (GTK_BINOP|GTK_NOVALUE)) // Jump Table based switch construct
#ifdef TARGET_ARM64
GTNODE(BFIZ, GenTreeBfiz ,0, GTK_BINOP) // Bitfield Insert in Zero
#endif

//-----------------------------------------------------------------------------
// Nodes used only within the code generator:
Expand Down
29 changes: 29 additions & 0 deletions src/coreclr/jit/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5753,6 +5753,35 @@ void Lowering::LowerShift(GenTreeOp* shift)
shift->gtOp2->ClearContained();
}
ContainCheckShiftRotate(shift);

#ifdef TARGET_ARM64
// Try to recognize ubfiz/sbfiz idiom in LSH(CAST(X), CNS) tree
if (comp->opts.OptimizationEnabled() && shift->OperIs(GT_LSH) && shift->gtGetOp1()->OperIs(GT_CAST) &&
shift->gtGetOp2()->IsCnsIntOrI() && !shift->isContained())
{
GenTreeIntCon* cns = shift->gtGetOp2()->AsIntCon();
GenTreeCast* cast = shift->gtGetOp1()->AsCast();

if (!cast->isContained() && !cast->IsRegOptional() && !cast->gtOverflow() &&
// Smaller CastOp is most likely an IND(X) node which is lowered to a zero-extend load
cast->CastOp()->TypeIs(TYP_LONG, TYP_INT))
{
// Cast is either "TYP_LONG <- TYP_INT" or "TYP_INT <- %SMALL_INT% <- TYP_INT" (signed or unsigned)
unsigned dstBits = genTypeSize(cast) * BITS_PER_BYTE;
unsigned srcBits = varTypeIsSmall(cast->CastToType()) ? genTypeSize(cast->CastToType()) * BITS_PER_BYTE
: genTypeSize(cast->CastOp()) * BITS_PER_BYTE;
assert(!cast->CastOp()->isContained());

// It has to be an upcast and CNS must be in [1..srcBits) range
if ((srcBits < dstBits) && ((UINT32)cns->IconValue() < srcBits))
{
JITDUMP("Recognized ubfix/sbfix pattern in LSH(CAST, CNS). Changing op to GT_BFIZ");
shift->ChangeOper(GT_BFIZ);
MakeSrcContained(shift, cast);
}
}
}
#endif
}

void Lowering::WidenSIMD12IfNecessary(GenTreeLclVarCommon* node)
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/jit/lsraarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,12 @@ int LinearScan::BuildNode(GenTree* tree)
BuildDef(tree);
break;

case GT_BFIZ:
assert(tree->gtGetOp1()->OperIs(GT_CAST));
srcCount = BuildOperandUses(tree->gtGetOp1()->gtGetOp1());
BuildDef(tree);
break;

case GT_RETURNTRAP:
// this just turns into a compare of its child with an int
// + a conditional call
Expand Down
Loading

0 comments on commit bfc5ebc

Please sign in to comment.