diff options
Diffstat (limited to 'src/jit/codegenarm64.cpp')
-rw-r--r-- | src/jit/codegenarm64.cpp | 210 |
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); |