Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
Add GT_BT, GT_BTC, GT_BTR and GT_BTS
Browse files Browse the repository at this point in the history
  • Loading branch information
mikedn committed Aug 28, 2017
1 parent bbeb1bc commit fa7a4a3
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/jit/codegenlinear.h
Expand Up @@ -163,6 +163,7 @@ void genCodeForShiftLong(GenTreePtr tree);

#ifdef _TARGET_XARCH_
void genCodeForShiftRMW(GenTreeStoreInd* storeInd);
void genCodeForBTx(GenTreeOp* btx, instruction ins);
#endif // _TARGET_XARCH_

void genCodeForCast(GenTreeOp* tree);
Expand Down
51 changes: 51 additions & 0 deletions src/jit/codegenxarch.cpp
Expand Up @@ -1439,6 +1439,41 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree)
}
}

//------------------------------------------------------------------------
// genCodeForBTx: Generates code for a GT_BT/GT_BTS/GT_BTR/GT_BTC node.
//
// Arguments:
// tree - The node.
//
// Return Value:
// None
//
void CodeGen::genCodeForBTx(GenTreeOp* btx, instruction ins)
{
GenTree* op1 = btx->gtGetOp1();
GenTree* op2 = btx->gtGetOp2();
var_types type = (ins != INS_bt) ? btx->TypeGet() : op1->TypeGet();

assert(op1->isUsedFromReg() || op1->isUsedFromMemory());
assert(op2->isUsedFromReg() || op2->isContainedIntOrIImmed());
assert((genTypeSize(type) > 1) && (genTypeSize(type) <= genTypeSize(TYP_I_IMPL)));

genConsumeOperands(btx);

if ((ins != INS_bt) && op1->isUsedFromReg() && (btx->gtRegNum != op1->gtRegNum))
{
inst_RV_RV(INS_mov, btx->gtRegNum, op1->gtRegNum, type);
op1 = btx;
}

getEmitter()->emitInsBinary(ins, emitTypeSize(type), op1, op2);

if (ins != INS_bt)
{
genProduceReg(btx);
}
}

//------------------------------------------------------------------------
// genCodeForJumpTrue: Generates code for jmpTrue statement.
//
Expand Down Expand Up @@ -1840,6 +1875,22 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode)
genCodeForSetcc(treeNode->AsCC());
break;

case GT_BT:
genCodeForBTx(treeNode->AsOp(), INS_bt);
break;

case GT_BTC:
genCodeForBTx(treeNode->AsOp(), INS_btc);
break;

case GT_BTR:
genCodeForBTx(treeNode->AsOp(), INS_btr);
break;

case GT_BTS:
genCodeForBTx(treeNode->AsOp(), INS_bts);
break;

case GT_RETURNTRAP:
genCodeForReturnTrap(treeNode->AsOp());
break;
Expand Down
6 changes: 6 additions & 0 deletions src/jit/gtlist.h
Expand Up @@ -226,6 +226,12 @@ GTNODE(JCC , GenTreeCC ,0,GTK_LEAF|GTK_NOVALUE) // Check
GTNODE(SETCC , GenTreeCC ,0,GTK_LEAF) // Checks the condition flags and produces 1 if the condition specified
// by GenTreeCC::gtCondition is true and 0 otherwise.

#ifdef _TARGET_XARCH_
GTNODE(BT , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE)
GTNODE(BTC , GenTreeOp ,0,GTK_BINOP)
GTNODE(BTR , GenTreeOp ,0,GTK_BINOP)
GTNODE(BTS , GenTreeOp ,0,GTK_BINOP)
#endif
//-----------------------------------------------------------------------------
// Other nodes that look like unary/binary operators:
//-----------------------------------------------------------------------------
Expand Down
9 changes: 9 additions & 0 deletions src/jit/lower.cpp
Expand Up @@ -178,6 +178,15 @@ GenTree* Lowering::LowerNode(GenTree* node)
LowerCall(node);
break;

#ifdef _TARGET_XARCH_
case GT_BT:
case GT_BTC:
case GT_BTR:
case GT_BTS:
ContainCheckBTx(node->AsOp());
break;
#endif

case GT_LT:
case GT_LE:
case GT_GT:
Expand Down
1 change: 1 addition & 0 deletions src/jit/lower.h
Expand Up @@ -116,6 +116,7 @@ class Lowering : public Phase
#ifdef _TARGET_XARCH_
void ContainCheckFloatBinary(GenTreeOp* node);
void ContainCheckIntrinsic(GenTreeOp* node);
void ContainCheckBTx(GenTreeOp* btx);
#endif // _TARGET_XARCH_
#ifdef FEATURE_SIMD
void ContainCheckSIMD(GenTreeSIMD* simdNode);
Expand Down
35 changes: 35 additions & 0 deletions src/jit/lowerxarch.cpp
Expand Up @@ -1782,6 +1782,41 @@ void Lowering::ContainCheckCast(GenTreeCast* node)
#endif // !defined(_TARGET_64BIT_)
}

//------------------------------------------------------------------------
// ContainCheckBTx: determine whether the sources of a BT/BTC/BTR/BTS node should be contained.
//
// Arguments:
// btx - pointer to the BT/BTC/BTS/BTR node
//
void Lowering::ContainCheckBTx(GenTreeOp* btx)
{
//
// The BT instruction family supports "reg/mem,reg" and "reg/mem,imm" forms.
// However, the "mem,reg" form has a slightly different semantic than the other forms,
// it treats the memory as an array indexed by bit_index / 32/64. This is rarely useful
// as these instructions are tipically produced by transforming shift instructions and
// those simply use the shift count % 32/64. Also, the "mem,reg" form has poor performance
// characteristics.
//

if (btx->gtGetOp2()->IsIntegralConst())
{
MakeSrcContained(btx, btx->gtGetOp2());

if (btx->OperIs(GT_BT))
{
if (IsContainableMemoryOp(btx->gtGetOp1()))
{
MakeSrcContained(btx, btx->gtGetOp1());
}
else if (!btx->gtGetOp1()->IsIntegralConst())
{
SetRegOptional(btx->gtGetOp1());
}
}
}
}

//------------------------------------------------------------------------
// ContainCheckCompare: determine whether the sources of a compare node should be contained.
//
Expand Down
4 changes: 4 additions & 0 deletions src/jit/lsraxarch.cpp
Expand Up @@ -343,6 +343,10 @@ void LinearScan::TreeNodeInfoInit(GenTree* tree)
case GT_AND:
case GT_OR:
case GT_XOR:
case GT_BT:
case GT_BTC:
case GT_BTR:
case GT_BTS:
info->srcCount = GetOperandSourceCount(tree->gtOp.gtOp1);
info->srcCount += GetOperandSourceCount(tree->gtOp.gtOp2);
break;
Expand Down

0 comments on commit fa7a4a3

Please sign in to comment.