Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
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
4 changes: 4 additions & 0 deletions src/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2411,6 +2411,7 @@ CodeGen::genCodeForTreeNode(GenTreePtr treeNode)
case GT_LSH:
case GT_RSH:
case GT_RSZ:
case GT_ROR:
genCodeForShift(treeNode->gtGetOp1(), treeNode->gtGetOp2(), treeNode);
// genCodeForShift() calls genProduceReg()
break;
Expand Down Expand Up @@ -4432,6 +4433,9 @@ instruction CodeGen::genGetInsForOper(genTreeOps oper, var_types type)
case GT_OR:
ins = INS_orr;
break;
case GT_ROR:
ins = INS_ror;
break;
case GT_RSH:
ins = INS_asr;
break;
Expand Down
28 changes: 23 additions & 5 deletions src/jit/codegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1516,6 +1516,8 @@ CodeGen::genCodeForTreeNode(GenTreePtr treeNode)
case GT_LSH:
case GT_RSH:
case GT_RSZ:
case GT_ROL:
case GT_ROR:
genCodeForShift(treeNode->gtGetOp1(), treeNode->gtGetOp2(), treeNode);
// genCodeForShift() calls genProduceReg()
break;
Expand Down Expand Up @@ -2584,7 +2586,9 @@ CodeGen::genCodeForTreeNode(GenTreePtr treeNode)
{
if (data->OperGet() == GT_LSH ||
data->OperGet() == GT_RSH ||
data->OperGet() == GT_RSZ)
data->OperGet() == GT_RSZ ||
data->OperGet() == GT_ROL ||
data->OperGet() == GT_ROR)
{
genCodeForShift(addr, data->gtOp.gtOp2, data);
}
Expand Down Expand Up @@ -4644,11 +4648,13 @@ instruction CodeGen::genGetInsForOper(genTreeOps oper, var_types type)
{
case GT_ADD: ins = INS_add; break;
case GT_AND: ins = INS_and; break;
case GT_MUL: ins = INS_imul; break;
case GT_LSH: ins = INS_shl; break;
case GT_MUL: ins = INS_imul; break;
case GT_NEG: ins = INS_neg; break;
case GT_NOT: ins = INS_not; break;
case GT_OR: ins = INS_or; break;
case GT_ROL: ins = INS_rol; break;
case GT_ROR: ins = INS_ror; break;
case GT_RSH: ins = INS_sar; break;
case GT_RSZ: ins = INS_shr; break;
case GT_SUB: ins = INS_sub; break;
Expand All @@ -4660,10 +4666,10 @@ instruction CodeGen::genGetInsForOper(genTreeOps oper, var_types type)
}

/** Generates the code sequence for a GenTree node that
* represents a bit shift operation (<<, >>, >>>).
* represents a bit shift or rotate operation (<<, >>, >>>, rol, ror).
*
* Arguments: operand: the value to be shifted by shiftBy bits.
* shiftBy: the number of bits to shift the operand.
* Arguments: operand: the value to be shifted or rotated by shiftBy bits.
* shiftBy: the number of bits to shift or rotate the operand.
* parent: the actual bitshift node (that specifies the
* type of bitshift to perform.
*
Expand Down Expand Up @@ -4758,6 +4764,12 @@ void CodeGen::genCodeForShift(GenTreePtr operand, GenTreePtr shiftBy,
case INS_shr:
ins = INS_shr_1;
break;
case INS_rol:
ins = INS_rol_1;
break;
case INS_ror:
ins = INS_ror_1;
break;
default:
// leave 'ins' unchanged
break;
Expand All @@ -4777,6 +4789,12 @@ void CodeGen::genCodeForShift(GenTreePtr operand, GenTreePtr shiftBy,
case INS_shr:
ins = INS_shr_N;
break;
case INS_rol:
ins = INS_rol_N;
break;
case INS_ror:
ins = INS_ror_N;
break;
default:
// leave 'ins' unchanged
break;
Expand Down
4 changes: 3 additions & 1 deletion src/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -4435,7 +4435,9 @@ protected :
void fgFixupIfCallArg(ArrayStack<GenTree *> *parentStack,
GenTree *oldChild,
GenTree *newChild);

// Recognize a rotation pattern and convert into a GT_ROL or a GT_ROR node.
GenTreePtr fgMorphRotation(GenTreePtr tree);

//-------- Determine the order in which the trees will be evaluated -------

unsigned fgTreeSeqNum;
Expand Down
22 changes: 22 additions & 0 deletions src/jit/emitxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3389,6 +3389,8 @@ void emitter::emitIns_R_I(instruction ins,

case INS_rcl_N:
case INS_rcr_N:
case INS_rol_N:
case INS_ror_N:
case INS_shl_N:
case INS_shr_N:
case INS_sar_N:
Expand Down Expand Up @@ -3968,6 +3970,8 @@ void emitter::emitIns_C_I (instruction ins,
{
case INS_rcl_N:
case INS_rcr_N:
case INS_rol_N:
case INS_ror_N:
case INS_shl_N:
case INS_shr_N:
case INS_sar_N:
Expand Down Expand Up @@ -4146,6 +4150,8 @@ void emitter::emitIns_I_AR (instruction ins,
{
case INS_rcl_N:
case INS_rcr_N:
case INS_rol_N:
case INS_ror_N:
case INS_shl_N:
case INS_shr_N:
case INS_sar_N:
Expand Down Expand Up @@ -4212,6 +4218,8 @@ void emitter::emitIns_I_AI (instruction ins,
{
case INS_rcl_N:
case INS_rcr_N:
case INS_rol_N:
case INS_ror_N:
case INS_shl_N:
case INS_shr_N:
case INS_sar_N:
Expand Down Expand Up @@ -4474,6 +4482,8 @@ void emitter::emitIns_I_ARR (instruction ins,
{
case INS_rcl_N:
case INS_rcr_N:
case INS_rol_N:
case INS_ror_N:
case INS_shl_N:
case INS_shr_N:
case INS_sar_N:
Expand Down Expand Up @@ -4620,6 +4630,8 @@ void emitter::emitIns_I_ARX (instruction ins,
{
case INS_rcl_N:
case INS_rcr_N:
case INS_rol_N:
case INS_ror_N:
case INS_shl_N:
case INS_shr_N:
case INS_sar_N:
Expand Down Expand Up @@ -4768,6 +4780,8 @@ void emitter::emitIns_I_AX (instruction ins,
{
case INS_rcl_N:
case INS_rcr_N:
case INS_rol_N:
case INS_ror_N:
case INS_shl_N:
case INS_shr_N:
case INS_sar_N:
Expand Down Expand Up @@ -5050,6 +5064,8 @@ void emitter::emitIns_S_I (instruction ins,
{
case INS_rcl_N:
case INS_rcr_N:
case INS_rol_N:
case INS_ror_N:
case INS_shl_N:
case INS_shr_N:
case INS_sar_N:
Expand Down Expand Up @@ -6363,6 +6379,8 @@ void emitter::emitDispShift(instruction ins, int cnt)
{
case INS_rcl_1:
case INS_rcr_1:
case INS_rol_1:
case INS_ror_1:
case INS_shl_1:
case INS_shr_1:
case INS_sar_1:
Expand All @@ -6371,6 +6389,8 @@ void emitter::emitDispShift(instruction ins, int cnt)

case INS_rcl:
case INS_rcr:
case INS_rol:
case INS_ror:
case INS_shl:
case INS_shr:
case INS_sar:
Expand All @@ -6379,6 +6399,8 @@ void emitter::emitDispShift(instruction ins, int cnt)

case INS_rcl_N:
case INS_rcr_N:
case INS_rol_N:
case INS_ror_N:
case INS_shl_N:
case INS_shr_N:
case INS_sar_N:
Expand Down
22 changes: 17 additions & 5 deletions src/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3694,6 +3694,8 @@ unsigned Compiler::gtSetEvalOrder(GenTree * tree)
case GT_LSH:
case GT_RSH:
case GT_RSZ:
case GT_ROL:
case GT_ROR:
case GT_ASG_LSH:
case GT_ASG_RSH:
case GT_ASG_RSZ:
Expand Down Expand Up @@ -9248,6 +9250,8 @@ GenTreePtr Compiler::gtFoldExprSpecial(GenTreePtr tree)
case GT_LSH:
case GT_RSH:
case GT_RSZ:
case GT_ROL:
case GT_ROR:
case GT_ASG_LSH:
case GT_ASG_RSH:
case GT_ASG_RSZ:
Expand Down Expand Up @@ -9943,9 +9947,13 @@ GenTreePtr Compiler::gtFoldExprConst(GenTreePtr tree)
case GT_LSH: i1 <<= (i2 & 0x1f); break;
case GT_RSH: i1 >>= (i2 & 0x1f); break;
case GT_RSZ:
/* logical shift -> make it unsigned to propagate the sign bit */
/* logical shift -> make it unsigned to not propagate the sign bit */
i1 = UINT32(i1) >> (i2 & 0x1f);
break;
case GT_ROL: i1 = (i1 << (i2 & 0x1f)) | (UINT32(i1) >> ((32 - i2) & 0x1f));
break;
case GT_ROR: i1 = (i1 << ((32 - i2) & 0x1f)) | (UINT32(i1) >> (i2 & 0x1f));
break;

/* DIV and MOD can generate an INT 0 - if division by 0
* or overflow - when dividing MIN by -1 */
Expand Down Expand Up @@ -10284,11 +10292,15 @@ GenTreePtr Compiler::gtFoldExprConst(GenTreePtr tree)
case GT_XOR: lval1 ^= lval2; break;
case GT_AND: lval1 &= lval2; break;

case GT_LSH: lval1 <<= (op2->gtIntConCommon.IconValue() & 0x3f); break;
case GT_RSH: lval1 >>= (op2->gtIntConCommon.IconValue() & 0x3f); break;
case GT_LSH: lval1 <<= (lval2 & 0x3f); break;
case GT_RSH: lval1 >>= (lval2 & 0x3f); break;
case GT_RSZ:
/* logical shift -> make it unsigned to propagate the sign bit */
lval1 = UINT64(lval1) >> (op2->gtIntConCommon.IconValue() & 0x3f);
/* logical shift -> make it unsigned to not propagate the sign bit */
lval1 = UINT64(lval1) >> (lval2 & 0x3f);
break;
case GT_ROL: lval1 = (lval1 << (lval2 & 0x3f)) | (UINT64(lval1) >> ((64 - lval2) & 0x3f));
break;
case GT_ROR: lval1 = (lval1 << ((64 - lval2) & 0x3f)) | (UINT64(lval1) >> (lval2 & 0x3f));
break;

//Both DIV and IDIV on x86 raise an exception for min_int (and min_long) / -1. So we preserve
Expand Down
18 changes: 11 additions & 7 deletions src/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -1086,23 +1086,25 @@ struct GenTree
int OperIsArithmetic() const
{
genTreeOps op = OperGet();
return op==GT_ADD
|| op==GT_SUB
|| op==GT_MUL
return op==GT_ADD
|| op==GT_SUB
|| op==GT_MUL
|| op==GT_DIV
|| op==GT_MOD

|| op==GT_UDIV
|| op==GT_UMOD

|| op==GT_OR
|| op==GT_OR
|| op==GT_XOR
|| op==GT_AND

|| op==GT_LSH
|| op==GT_RSH
|| op==GT_RSZ;

|| op==GT_RSZ

|| op==GT_ROL
|| op==GT_ROR;
}

static
Expand Down Expand Up @@ -3506,6 +3508,8 @@ inline bool GenTree::RequiresNonNullOp2(genTreeOps oper)
case GT_LSH:
case GT_RSH:
case GT_RSZ:
case GT_ROL:
case GT_ROR:
case GT_INDEX:
case GT_ASG:
case GT_ASG_ADD:
Expand Down
2 changes: 2 additions & 0 deletions src/jit/gtlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ GTNODE(GT_AND , "&" ,1,GTK_BINOP|GTK_LOGOP)
GTNODE(GT_LSH , "<<" ,0,GTK_BINOP)
GTNODE(GT_RSH , ">>" ,0,GTK_BINOP)
GTNODE(GT_RSZ , ">>>" ,0,GTK_BINOP)
GTNODE(GT_ROL , "rol" ,0,GTK_BINOP)
GTNODE(GT_ROR , "ror" ,0,GTK_BINOP)
GTNODE(GT_MULHI , "mulhi" ,1,GTK_BINOP) // returns high bits (top N bits of the 2N bit result of an NxN multiply)

GTNODE(GT_ASG , "=" ,0,GTK_BINOP|GTK_ASGOP)
Expand Down
6 changes: 6 additions & 0 deletions src/jit/instr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2627,6 +2627,8 @@ void CodeGen::inst_RV_SH(instruction ins,

assert(ins == INS_rcl ||
ins == INS_rcr ||
ins == INS_rol ||
ins == INS_ror ||
ins == INS_shl ||
ins == INS_shr ||
ins == INS_sar);
Expand All @@ -2639,6 +2641,8 @@ void CodeGen::inst_RV_SH(instruction ins,

assert(INS_rcl + 1 == INS_rcl_1);
assert(INS_rcr + 1 == INS_rcr_1);
assert(INS_rol + 1 == INS_rol_1);
assert(INS_ror + 1 == INS_ror_1);
assert(INS_shl + 1 == INS_shl_1);
assert(INS_shr + 1 == INS_shr_1);
assert(INS_sar + 1 == INS_sar_1);
Expand All @@ -2651,6 +2655,8 @@ void CodeGen::inst_RV_SH(instruction ins,

assert(INS_rcl + 2 == INS_rcl_N);
assert(INS_rcr + 2 == INS_rcr_N);
assert(INS_rol + 2 == INS_rol_N);
assert(INS_ror + 2 == INS_ror_N);
assert(INS_shl + 2 == INS_shl_N);
assert(INS_shr + 2 == INS_shr_N);
assert(INS_sar + 2 == INS_sar_N);
Expand Down
7 changes: 7 additions & 0 deletions src/jit/instrsxarch.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,13 @@ INST2(ret , "ret" , 0, IUM_RD, 0, 0, 0x0000C3, 0x0000C2)
INST2(loop , "loop" , 0, IUM_RD, 0, 0, BAD_CODE, 0x0000E2)
INST2(call , "call" , 0, IUM_RD, 0, 1, 0x0010FF, 0x0000E8)

INST2(rol , "rol" , 0, IUM_RW, 0, 1, 0x0000D2, BAD_CODE)
INST2(rol_1 , "rol" , 0, IUM_RW, 0, 1, 0x0000D0, 0x0000D0)
INST2(rol_N , "rol" , 0, IUM_RW, 0, 1, 0x0000C0, 0x0000C0)
INST2(ror , "ror" , 0, IUM_RW, 0, 1, 0x0008D2, BAD_CODE)
INST2(ror_1 , "ror" , 0, IUM_RW, 0, 1, 0x0008D0, 0x0008D0)
INST2(ror_N , "ror" , 0, IUM_RW, 0, 1, 0x0008C0, 0x0008C0)

INST2(rcl , "rcl" , 0, IUM_RW, 1, 1, 0x0010D2, BAD_CODE)
INST2(rcl_1 , "rcl" , 0, IUM_RW, 1, 1, 0x0010D0, 0x0010D0)
INST2(rcl_N , "rcl" , 0, IUM_RW, 1, 1, 0x0010C0, 0x0010C0)
Expand Down
4 changes: 3 additions & 1 deletion src/jit/lclvars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2899,7 +2899,9 @@ void Compiler::lvaMarkLclRefs(GenTreePtr tree)

if (tree->gtOper == GT_LSH ||
tree->gtOper == GT_RSH ||
tree->gtOper == GT_RSZ)
tree->gtOper == GT_RSZ ||
tree->gtOper == GT_ROL ||
tree->gtOper == GT_ROR)
{
if (tree->gtType == TYP_INT)
{
Expand Down
7 changes: 7 additions & 0 deletions src/jit/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,8 @@ void Lowering::DecomposeNode(GenTreePtr* pTree, Compiler::fgWalkData* data)
case GT_LSH:
case GT_RSH:
case GT_RSZ:
case GT_ROL:
case GT_ROR:
case GT_MULHI:
NYI("Arithmetic binary operators on TYP_LONG");
break;
Expand Down Expand Up @@ -525,6 +527,11 @@ void Lowering::LowerNode(GenTreePtr* ppTree, Compiler::fgWalkData* data)
}
break;

case GT_ROL:
case GT_ROR:
LowerRotate(*ppTree);
break;

#ifdef FEATURE_SIMD
case GT_SIMD:
if ((*ppTree)->TypeGet() == TYP_SIMD12)
Expand Down
1 change: 1 addition & 0 deletions src/jit/lower.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ class Lowering : public Phase
void HandleIndirAddressExpression(GenTree *indirTree, GenTree* tree);
void LowerGCWriteBarrier(GenTree *tree);
void LowerArrElem(GenTree **ppTree, Compiler::fgWalkData* data);
void LowerRotate(GenTree *tree);

// Utility functions
void MorphBlkIntoHelperCall (GenTreePtr pTree, GenTreePtr treeStmt);
Expand Down
5 changes: 5 additions & 0 deletions src/jit/lowerarm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ void Lowering::LowerCntBlockOp(GenTreePtr *ppTree)
NYI_ARM("ARM Lowering for BlockOp");
}

void Lowering::LowerRotate(GenTreePtr tree)
{
NYI_ARM("ARM Lowering for ROL and ROR");
}

void Lowering::TreeNodeInfoInitCall(GenTree *tree, TreeNodeInfo &info,
int &srcCount, // out
int &dstCount // out
Expand Down
Loading