summaryrefslogtreecommitdiff
path: root/src/jit/codegenarm64.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/codegenarm64.cpp')
-rw-r--r--src/jit/codegenarm64.cpp210
1 files changed, 19 insertions, 191 deletions
diff --git a/src/jit/codegenarm64.cpp b/src/jit/codegenarm64.cpp
index 7f98221df8..7de19f9043 100644
--- a/src/jit/codegenarm64.cpp
+++ b/src/jit/codegenarm64.cpp
@@ -906,7 +906,7 @@ void CodeGen::genFuncletProlog(BasicBlock* block)
#endif
assert(block != NULL);
- assert(block->bbFlags && BBF_FUNCLET_BEG);
+ assert(block->bbFlags & BBF_FUNCLET_BEG);
ScopedSetVariable<bool> _setGeneratingProlog(&compiler->compGeneratingProlog, true);
@@ -1441,9 +1441,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre
else
{
// Get a temp integer register to compute long address.
- regMaskTP addrRegMask = tree->gtRsvdRegs;
- regNumber addrReg = genRegNumFromMask(addrRegMask);
- noway_assert(addrReg != REG_NA);
+ regNumber addrReg = tree->GetSingleTempReg();
// We must load the FP constant from the constant pool
// Emit a data section constant for the float or double constant.
@@ -2441,30 +2439,8 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode)
break;
case GT_JTRUE:
- {
- GenTree* cmp = treeNode->gtOp.gtOp1->gtEffectiveVal();
- assert(cmp->OperIsCompare());
- assert(compiler->compCurBB->bbJumpKind == BBJ_COND);
-
- // Get the "kind" and type of the comparison. Note that whether it is an unsigned cmp
- // is governed by a flag NOT by the inherent type of the node
- emitJumpKind jumpKind[2];
- bool branchToTrueLabel[2];
- genJumpKindsForTree(cmp, jumpKind, branchToTrueLabel);
- assert(jumpKind[0] != EJ_NONE);
-
- // On Arm64 the branches will always branch to the true label
- assert(branchToTrueLabel[0]);
- inst_JMP(jumpKind[0], compiler->compCurBB->bbJumpDest);
-
- if (jumpKind[1] != EJ_NONE)
- {
- // the second conditional branch always has to be to the true label
- assert(branchToTrueLabel[1]);
- inst_JMP(jumpKind[1], compiler->compCurBB->bbJumpDest);
- }
- }
- break;
+ genCodeForJumpTrue(treeNode);
+ break;
case GT_RETURNTRAP:
{
@@ -2854,7 +2830,6 @@ void CodeGen::genLclHeap(GenTreePtr tree)
noway_assert((genActualType(size->gtType) == TYP_INT) || (genActualType(size->gtType) == TYP_I_IMPL));
regNumber targetReg = tree->gtRegNum;
- regMaskTP tmpRegsMask = tree->gtRsvdRegs;
regNumber regCnt = REG_NA;
regNumber pspSymReg = REG_NA;
var_types type = genActualType(size->gtType);
@@ -2923,17 +2898,16 @@ void CodeGen::genLclHeap(GenTreePtr tree)
// since we don't need any internal registers.
if (!hasPspSym && compiler->info.compInitMem)
{
- assert(genCountBits(tmpRegsMask) == 0);
+ assert(tree->AvailableTempRegCount() == 0);
regCnt = targetReg;
}
else
{
- assert(genCountBits(tmpRegsMask) >= 1);
- regMaskTP regCntMask = genFindLowestBit(tmpRegsMask);
- tmpRegsMask &= ~regCntMask;
- regCnt = genRegNumFromMask(regCntMask);
+ regCnt = tree->ExtractTempReg();
if (regCnt != targetReg)
+ {
inst_RV_RV(INS_mov, regCnt, targetReg, size->TypeGet());
+ }
}
// Align to STACK_ALIGN
@@ -2950,10 +2924,7 @@ void CodeGen::genLclHeap(GenTreePtr tree)
stackAdjustment += STACK_ALIGN;
// Save a copy of PSPSym
- assert(genCountBits(tmpRegsMask) >= 1);
- regMaskTP pspSymRegMask = genFindLowestBit(tmpRegsMask);
- tmpRegsMask &= ~pspSymRegMask;
- pspSymReg = genRegNumFromMask(pspSymRegMask);
+ pspSymReg = tree->ExtractTempReg();
getEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, pspSymReg, compiler->lvaPSPSym, 0);
}
#endif
@@ -3021,15 +2992,12 @@ void CodeGen::genLclHeap(GenTreePtr tree)
assert(regCnt == REG_NA);
if (!hasPspSym && compiler->info.compInitMem)
{
- assert(genCountBits(tmpRegsMask) == 0);
+ assert(tree->AvailableTempRegCount() == 0);
regCnt = targetReg;
}
else
{
- assert(genCountBits(tmpRegsMask) >= 1);
- regMaskTP regCntMask = genFindLowestBit(tmpRegsMask);
- tmpRegsMask &= ~regCntMask;
- regCnt = genRegNumFromMask(regCntMask);
+ regCnt = tree->ExtractTempReg();
}
genSetRegToIcon(regCnt, amount, ((int)amount == amount) ? TYP_INT : TYP_LONG);
}
@@ -3094,9 +3062,7 @@ void CodeGen::genLclHeap(GenTreePtr tree)
//
// Setup the regTmp
- assert(tmpRegsMask != RBM_NONE);
- assert(genCountBits(tmpRegsMask) == 1);
- regNumber regTmp = genRegNumFromMask(tmpRegsMask);
+ regNumber regTmp = tree->GetSingleTempReg();
BasicBlock* loop = genCreateTempLabel();
BasicBlock* done = genCreateTempLabel();
@@ -3391,13 +3357,11 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode)
unsigned offset = 0;
// Grab the integer temp register to emit the loads and stores.
- regMaskTP tmpMask = genFindLowestBit(cpBlkNode->gtRsvdRegs & RBM_ALLINT);
- regNumber tmpReg = genRegNumFromMask(tmpMask);
+ regNumber tmpReg = cpBlkNode->ExtractTempReg(RBM_ALLINT);
if (size >= 2 * REGSIZE_BYTES)
{
- regMaskTP tmp2Mask = cpBlkNode->gtRsvdRegs & RBM_ALLINT & ~tmpMask;
- regNumber tmp2Reg = genRegNumFromMask(tmp2Mask);
+ regNumber tmp2Reg = cpBlkNode->ExtractTempReg(RBM_ALLINT);
size_t slots = size / (2 * REGSIZE_BYTES);
@@ -3498,13 +3462,8 @@ void CodeGen::genCodeForCpObj(GenTreeObj* cpObjNode)
gcInfo.gcMarkRegPtrVal(REG_WRITE_BARRIER_DST_BYREF, dstAddr->TypeGet());
// Temp register used to perform the sequence of loads and stores.
- regNumber tmpReg = genRegNumFromMask(cpObjNode->gtRsvdRegs);
-
-#ifdef DEBUG
- assert(cpObjNode->gtRsvdRegs != RBM_NONE);
- assert(genCountBits(cpObjNode->gtRsvdRegs) == 1);
+ regNumber tmpReg = cpObjNode->GetSingleTempReg();
assert(genIsValidIntReg(tmpReg));
-#endif // DEBUG
unsigned slots = cpObjNode->gtSlots;
emitter* emit = getEmitter();
@@ -3571,7 +3530,7 @@ void CodeGen::genTableBasedSwitch(GenTree* treeNode)
regNumber idxReg = treeNode->gtOp.gtOp1->gtRegNum;
regNumber baseReg = treeNode->gtOp.gtOp2->gtRegNum;
- regNumber tmpReg = genRegNumFromMask(treeNode->gtRsvdRegs);
+ regNumber tmpReg = treeNode->GetSingleTempReg();
// load the ip-relative offset (which is relative to start of fgFirstBB)
getEmitter()->emitIns_R_R_R(INS_ldr, EA_4BYTE, baseReg, baseReg, idxReg, INS_OPTS_LSL);
@@ -4022,9 +3981,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea)
if (offset != 0)
{
- regMaskTP tmpRegMask = lea->gtRsvdRegs;
- regNumber tmpReg = genRegNumFromMask(tmpRegMask);
- noway_assert(tmpReg != REG_NA);
+ regNumber tmpReg = lea->GetSingleTempReg();
if (emitter::emitIns_valid_imm_for_add(offset, EA_8BYTE))
{
@@ -4041,7 +3998,6 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea)
// Then compute target reg from [tmpReg + offset]
emit->emitIns_R_R_I(INS_add, size, lea->gtRegNum, tmpReg, offset);
- ;
}
else // large offset
{
@@ -4091,9 +4047,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea)
else
{
// We require a tmpReg to hold the offset
- regMaskTP tmpRegMask = lea->gtRsvdRegs;
- regNumber tmpReg = genRegNumFromMask(tmpRegMask);
- noway_assert(tmpReg != REG_NA);
+ regNumber tmpReg = lea->GetSingleTempReg();
// First load tmpReg with the large offset constant
instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
@@ -4116,131 +4070,6 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea)
}
//-------------------------------------------------------------------------------------------
-// genJumpKindsForTree: Determine the number and kinds of conditional branches
-// necessary to implement the given GT_CMP node
-//
-// Arguments:
-// cmpTree - (input) The GenTree node that is used to set the Condition codes
-// - The GenTree Relop node that was used to set the Condition codes
-// jmpKind[2] - (output) One or two conditional branch instructions
-// jmpToTrueLabel[2] - (output) On Arm64 both branches will always branch to the true label
-//
-// Return Value:
-// Sets the proper values into the array elements of jmpKind[] and jmpToTrueLabel[]
-//
-// Assumptions:
-// At least one conditional branch instruction will be returned.
-// Typically only one conditional branch is needed
-// and the second jmpKind[] value is set to EJ_NONE
-//-------------------------------------------------------------------------------------------
-
-// static
-void CodeGen::genJumpKindsForTree(GenTreePtr cmpTree, emitJumpKind jmpKind[2], bool jmpToTrueLabel[2])
-{
- // On Arm64 both branches will always branch to the true label
- jmpToTrueLabel[0] = true;
- jmpToTrueLabel[1] = true;
-
- // For integer comparisons just use genJumpKindForOper
- if (!varTypeIsFloating(cmpTree->gtOp.gtOp1->gtEffectiveVal()))
- {
- CompareKind compareKind = ((cmpTree->gtFlags & GTF_UNSIGNED) != 0) ? CK_UNSIGNED : CK_SIGNED;
- jmpKind[0] = genJumpKindForOper(cmpTree->gtOper, compareKind);
- jmpKind[1] = EJ_NONE;
- }
- else // We have a Floating Point Compare operation
- {
- assert(cmpTree->OperIsCompare());
-
- // For details on this mapping, see the ARM64 Condition Code
- // table at section C1.2.3 in the ARMV8 architecture manual
- //
-
- // We must check the GTF_RELOP_NAN_UN to find out
- // if we need to branch when we have a NaN operand.
- //
- if ((cmpTree->gtFlags & GTF_RELOP_NAN_UN) != 0)
- {
- // Must branch if we have an NaN, unordered
- switch (cmpTree->gtOper)
- {
- case GT_EQ:
- jmpKind[0] = EJ_eq; // branch or set when equal (and no NaN's)
- jmpKind[1] = EJ_vs; // branch or set when we have a NaN
- break;
-
- case GT_NE:
- jmpKind[0] = EJ_ne; // branch or set when not equal (or have NaN's)
- jmpKind[1] = EJ_NONE;
- break;
-
- case GT_LT:
- jmpKind[0] = EJ_lt; // branch or set when less than (or have NaN's)
- jmpKind[1] = EJ_NONE;
- break;
-
- case GT_LE:
- jmpKind[0] = EJ_le; // branch or set when less than or equal (or have NaN's)
- jmpKind[1] = EJ_NONE;
- break;
-
- case GT_GT:
- jmpKind[0] = EJ_hi; // branch or set when greater than (or have NaN's)
- jmpKind[1] = EJ_NONE;
- break;
-
- case GT_GE:
- jmpKind[0] = EJ_hs; // branch or set when greater than or equal (or have NaN's)
- jmpKind[1] = EJ_NONE;
- break;
-
- default:
- unreached();
- }
- }
- else // ((cmpTree->gtFlags & GTF_RELOP_NAN_UN) == 0)
- {
- // Do not branch if we have an NaN, unordered
- switch (cmpTree->gtOper)
- {
- case GT_EQ:
- jmpKind[0] = EJ_eq; // branch or set when equal (and no NaN's)
- jmpKind[1] = EJ_NONE;
- break;
-
- case GT_NE:
- jmpKind[0] = EJ_gt; // branch or set when greater than (and no NaN's)
- jmpKind[1] = EJ_lo; // branch or set when less than (and no NaN's)
- break;
-
- case GT_LT:
- jmpKind[0] = EJ_lo; // branch or set when less than (and no NaN's)
- jmpKind[1] = EJ_NONE;
- break;
-
- case GT_LE:
- jmpKind[0] = EJ_ls; // branch or set when less than or equal (and no NaN's)
- jmpKind[1] = EJ_NONE;
- break;
-
- case GT_GT:
- jmpKind[0] = EJ_gt; // branch or set when greater than (and no NaN's)
- jmpKind[1] = EJ_NONE;
- break;
-
- case GT_GE:
- jmpKind[0] = EJ_ge; // branch or set when greater than or equal (and no NaN's)
- jmpKind[1] = EJ_NONE;
- break;
-
- default:
- unreached();
- }
- }
- }
-}
-
-//-------------------------------------------------------------------------------------------
// genSetRegToCond: Set a register 'dstReg' to the appropriate one or zero value
// corresponding to a binary Relational operator result.
//
@@ -4484,9 +4313,8 @@ void CodeGen::genCkfinite(GenTreePtr treeNode)
emitter* emit = getEmitter();
// Extract exponent into a register.
- regNumber intReg = genRegNumFromMask(treeNode->gtRsvdRegs);
+ regNumber intReg = treeNode->GetSingleTempReg();
regNumber fpReg = genConsumeReg(op1);
- assert(intReg != REG_NA);
emit->emitIns_R_R(ins_Copy(targetType), emitTypeSize(treeNode), intReg, fpReg);
emit->emitIns_R_R_I(INS_lsr, emitTypeSize(targetType), intReg, intReg, shiftAmount);