Skip to content
Open
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
2 changes: 2 additions & 0 deletions src/coreclr/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -1256,7 +1256,9 @@ class CodeGen final : public CodeGenInterface
void genCodeForJumpCompare(GenTreeOpCC* tree);
void genCompareImmAndJump(
GenCondition::Code cond, regNumber reg, ssize_t compareImm, emitAttr size, BasicBlock* target);
void genCodeForBfi(GenTreeOp* tree);
void genCodeForBfiz(GenTreeOp* tree);
void genCodeForBfx(GenTreeOp* tree);
#endif // TARGET_ARM64

void genEHCatchRet(BasicBlock* block);
Expand Down
64 changes: 64 additions & 0 deletions src/coreclr/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5831,6 +5831,38 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind)
}
}

//------------------------------------------------------------------------
// genCodeForBfi: Generates the code sequence for a GenTree node that
// represents a bitfield insert.
//
// Arguments:
// tree - the bitfield insert.
//
void CodeGen::genCodeForBfi(GenTreeOp* tree)
{
assert(tree->OperIs(GT_BFI));

GenTreeBfm* bfm = tree->AsBfm();

emitAttr size = emitActualTypeSize(tree);
unsigned regBits = emitter::getBitWidth(size);

GenTree* base = tree->gtGetOp1();
GenTree* src = tree->gtGetOp2();

genConsumeOperands(bfm);

unsigned offset = bfm->GetOffset();
unsigned width = bfm->GetWidth();

assert(width >= 1 && width <= regBits);
assert(offset < regBits && (offset + width) <= regBits);

GetEmitter()->emitIns_R_R_I_I(INS_bfi, size, base->GetRegNum(), src->GetRegNum(), (int)offset, (int)width);

genProduceReg(tree);
}

//------------------------------------------------------------------------
// genCodeForBfiz: Generates the code sequence for a GenTree node that
// represents a bitfield insert in zero with sign/zero extension.
Expand Down Expand Up @@ -5858,6 +5890,38 @@ void CodeGen::genCodeForBfiz(GenTreeOp* tree)
genProduceReg(tree);
}

//------------------------------------------------------------------------
// genCodeForBfx: Generates the code sequence for a GenTree node that
// represents a bitfield extract.
//
// Arguments:
// tree - the bitfield extract.
//
void CodeGen::genCodeForBfx(GenTreeOp* tree)
{
assert(tree->OperIs(GT_BFX));

GenTreeBfm* bfm = tree->AsBfm();
emitAttr size = emitActualTypeSize(tree);

GenTree* src = tree->gtGetOp1();

const unsigned bitWidth = emitter::getBitWidth(size);
const unsigned lsb = bfm->GetOffset();
const unsigned width = bfm->GetWidth();

assert((bitWidth == 32) || (bitWidth == 64));
assert(lsb < bitWidth);
assert(width > 0);
assert((lsb + width) <= bitWidth);

genConsumeRegs(src);

GetEmitter()->emitIns_R_R_I_I(INS_ubfx, size, tree->GetRegNum(), src->GetRegNum(), (int)lsb, (int)width);

genProduceReg(tree);
}

//------------------------------------------------------------------------
// JumpKindToInsCond: Convert a Jump Kind to a condition.
//
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/jit/codegenarmarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,17 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
genCodeForSwap(treeNode->AsOp());
break;

case GT_BFI:
genCodeForBfi(treeNode->AsOp());
break;

case GT_BFIZ:
genCodeForBfiz(treeNode->AsOp());
break;

case GT_BFX:
genCodeForBfx(treeNode->AsOp());
break;
#endif // TARGET_ARM64

case GT_JMP:
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -2983,6 +2983,11 @@ class Compiler
GenTreeColon* gtNewColonNode(var_types type, GenTree* thenNode, GenTree* elseNode);
GenTreeQmark* gtNewQmarkNode(var_types type, GenTree* cond, GenTreeColon* colon);

#if defined(TARGET_ARM64)
GenTreeBfm* gtNewBfiNode(var_types type, GenTree* base, GenTree* src, unsigned offset, unsigned width);
GenTreeBfm* gtNewBfxNode(var_types type, GenTree* base, unsigned offset, unsigned width);
#endif

GenTree* gtNewLargeOperNode(genTreeOps oper,
var_types type = TYP_I_IMPL,
GenTree* op1 = nullptr,
Expand Down
12 changes: 12 additions & 0 deletions src/coreclr/jit/compiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4629,6 +4629,18 @@ GenTree::VisitResult GenTree::VisitOperands(TVisitor visitor)
return visitor(cond->gtOp2);
}

#ifdef TARGET_ARM64
case GT_BFX:
{
GenTree* op1 = gtGetOp1();
if (op1 != nullptr)
{
return visitor(op1);
}
return VisitResult::Continue;
}
#endif

// Binary nodes
default:
assert(this->OperIsBinary());
Expand Down
27 changes: 27 additions & 0 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7770,6 +7770,24 @@ GenTreeQmark* Compiler::gtNewQmarkNode(var_types type, GenTree* cond, GenTreeCol
return result;
}

#if defined(TARGET_ARM64)
GenTreeBfm* Compiler::gtNewBfiNode(var_types type, GenTree* base, GenTree* src, unsigned offset, unsigned width)
{
GenTreeBfm* result = new (this, GT_BFI) GenTreeBfm(GT_BFI, type, base, src, offset, width);
result->gtFlags |= (base->gtFlags | src->gtFlags) & (GTF_ALL_EFFECT);
result->gtFlags &= ~GTF_SET_FLAGS;
return result;
}

GenTreeBfm* Compiler::gtNewBfxNode(var_types type, GenTree* base, unsigned offset, unsigned width)
{
GenTreeBfm* result = new (this, GT_BFX) GenTreeBfm(GT_BFX, type, base, nullptr, offset, width);
result->gtFlags |= (base->gtFlags & GTF_ALL_EFFECT);
result->gtFlags &= ~GTF_SET_FLAGS;
return result;
}
#endif

GenTreeIntCon* Compiler::gtNewIconNode(ssize_t value, var_types type)
{
assert(genActualType(type) == type);
Expand Down Expand Up @@ -10472,6 +10490,15 @@ GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node)
m_advance = &GenTreeUseEdgeIterator::Terminate;
return;

#ifdef TARGET_ARM64
case GT_BFX:
assert(m_node->AsOp()->gtOp2 == nullptr);
m_edge = &m_node->AsOp()->gtOp1;
assert(*m_edge != nullptr);
m_advance = &GenTreeUseEdgeIterator::Terminate;
return;
#endif

// Unary operators with an optional operand
case GT_FIELD_ADDR:
case GT_RETURN:
Expand Down
38 changes: 38 additions & 0 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -5957,6 +5957,44 @@ struct GenTreeQmark : public GenTreeOp
#endif
};

#ifdef TARGET_ARM64
struct GenTreeBfm : public GenTreeOp
{
unsigned gtOffset;
unsigned gtWidth;

GenTreeBfm(genTreeOps oper, var_types type, GenTree* base, GenTree* src, unsigned offset, unsigned width)
: GenTreeOp(oper, type, base, src)
, gtOffset(offset)
, gtWidth(width)
{
assert((oper == GT_BFI) || (oper == GT_BFX));
assert((oper != GT_BFX) || (src == nullptr));
assert((oper != GT_BFI) || (src != nullptr));
}

unsigned GetOffset() const
{
return gtOffset;
}
unsigned GetWidth() const
{
return gtWidth;
}
unsigned GetMask() const
{
return ((~0ULL >> (64 - gtWidth)) << gtOffset);
}

#if DEBUGGABLE_GENTREE
GenTreeBfm()
: GenTreeOp()
{
}
#endif
};
#endif

/* gtIntrinsic -- intrinsic (possibly-binary op [NULL op2 is allowed] with an additional field) */

struct GenTreeIntrinsic : public GenTreeOp
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/jit/gtlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,9 @@ GTNODE(OR_NOT , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR)
GTNODE(XOR_NOT , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR)

#ifdef TARGET_ARM64
GTNODE(BFI , GenTreeBfm ,0,0,GTK_BINOP|GTK_EXOP|DBK_NOTHIR) // Bitfield Insert.
GTNODE(BFIZ , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) // Bitfield Insert in Zero.
GTNODE(BFX , GenTreeBfm ,0,0,GTK_UNOP|GTK_EXOP|DBK_NOTHIR) // Bitfield Extract.
#endif

//-----------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/gtstructs.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ GTSTRUCT_1(StoreInd , GT_STOREIND)
GTSTRUCT_1(CmpXchg , GT_CMPXCHG)
#ifdef TARGET_ARM64
GTSTRUCT_N(Conditional , GT_SELECT, GT_SELECT_INC, GT_SELECT_INV, GT_SELECT_NEG)
GTSTRUCT_2(Bfm , GT_BFI, GT_BFX)
#else
GTSTRUCT_N(Conditional , GT_SELECT)
#endif //TARGET_ARM64
Expand Down
Loading
Loading