diff options
Diffstat (limited to 'src/jit/lsraarm64.cpp')
-rw-r--r-- | src/jit/lsraarm64.cpp | 167 |
1 files changed, 85 insertions, 82 deletions
diff --git a/src/jit/lsraarm64.cpp b/src/jit/lsraarm64.cpp index 37391675b0..cea80e2093 100644 --- a/src/jit/lsraarm64.cpp +++ b/src/jit/lsraarm64.cpp @@ -44,18 +44,21 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // requirements needed by LSRA to build the Interval Table (source, // destination and internal [temp] register counts). // -void Lowering::TreeNodeInfoInit(GenTree* tree) +void LinearScan::TreeNodeInfoInit(GenTree* tree) { - LinearScan* l = m_lsra; - Compiler* compiler = comp; - unsigned kind = tree->OperKind(); TreeNodeInfo* info = &(tree->gtLsraInfo); RegisterType registerType = TypeGet(tree); - JITDUMP("TreeNodeInfoInit for: "); - DISPNODE(tree); - JITDUMP("\n"); + if (tree->isContained()) + { + info->dstCount = 0; + assert(info->srcCount == 0); + return; + } + + // Set the default dstCount. This may be modified below. + info->dstCount = tree->IsValue() ? 1 : 0; switch (tree->OperGet()) { @@ -63,7 +66,6 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) GenTree* op2; default: - info->dstCount = tree->IsValue() ? 1 : 0; if (kind & (GTK_CONST | GTK_LEAF)) { info->srcCount = 0; @@ -88,7 +90,7 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) case GT_STORE_LCL_FLD: case GT_STORE_LCL_VAR: info->srcCount = 1; - info->dstCount = 0; + assert(info->dstCount == 0); TreeNodeInfoInitStoreLoc(tree->AsLclVarCommon()); break; @@ -99,12 +101,12 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) case GT_START_NONGC: case GT_PROF_HOOK: info->srcCount = 0; - info->dstCount = 0; + assert(info->dstCount == 0); break; case GT_CNS_DBL: info->srcCount = 0; - info->dstCount = 1; + assert(info->dstCount == 1); { GenTreeDblCon* dblConst = tree->AsDblCon(); double constValue = dblConst->gtDblCon.gtDconVal; @@ -126,7 +128,7 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) case GT_QMARK: case GT_COLON: info->srcCount = 0; - info->dstCount = 0; + assert(info->dstCount == 0); unreached(); break; @@ -138,17 +140,17 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) if (tree->TypeGet() == TYP_VOID) { info->srcCount = 0; - info->dstCount = 0; + assert(info->dstCount == 0); } else { assert(tree->TypeGet() == TYP_INT); info->srcCount = 1; - info->dstCount = 0; + assert(info->dstCount == 0); - info->setSrcCandidates(l, RBM_INTRET); - tree->gtOp.gtOp1->gtLsraInfo.setSrcCandidates(l, RBM_INTRET); + info->setSrcCandidates(this, RBM_INTRET); + tree->gtOp.gtOp1->gtLsraInfo.setSrcCandidates(this, RBM_INTRET); } break; @@ -159,42 +161,40 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) info->srcCount = 0; if (tree->TypeGet() != TYP_VOID && tree->gtOp.gtOp1 == nullptr) { - info->dstCount = 1; + assert(info->dstCount == 1); } else { - info->dstCount = 0; + assert(info->dstCount == 0); } break; case GT_JTRUE: info->srcCount = 0; - info->dstCount = 0; - l->clearDstCount(tree->gtOp.gtOp1); + assert(info->dstCount == 0); break; case GT_JMP: info->srcCount = 0; - info->dstCount = 0; + assert(info->dstCount == 0); break; case GT_SWITCH: // This should never occur since switch nodes must not be visible at this // point in the JIT. info->srcCount = 0; - info->dstCount = 0; // To avoid getting uninit errors. noway_assert(!"Switch must be lowered at this point"); break; case GT_JMPTABLE: info->srcCount = 0; - info->dstCount = 1; + assert(info->dstCount == 1); break; case GT_SWITCH_TABLE: info->srcCount = 2; info->internalIntCount = 1; - info->dstCount = 0; + assert(info->dstCount == 0); break; case GT_ASG: @@ -202,7 +202,6 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) case GT_ASG_SUB: noway_assert(!"We should never hit any assignment operator in lowering"); info->srcCount = 0; - info->dstCount = 0; break; case GT_ADD: @@ -217,9 +216,6 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) assert(tree->gtOp.gtOp1->TypeGet() == tree->gtOp.gtOp2->TypeGet()); info->srcCount = 2; - info->dstCount = 1; - - break; } __fallthrough; @@ -227,16 +223,15 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) case GT_AND: case GT_OR: case GT_XOR: - ContainCheckBinary(tree->AsOp()); info->srcCount = tree->gtOp.gtOp2->isContained() ? 1 : 2; - info->dstCount = 1; + assert(info->dstCount == 1); break; case GT_RETURNTRAP: // this just turns into a compare of its child with an int // + a conditional call info->srcCount = 1; - info->dstCount = 0; + assert(info->dstCount == 0); break; case GT_MOD: @@ -259,7 +254,7 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) case GT_UDIV: { info->srcCount = 2; - info->dstCount = 1; + assert(info->dstCount == 1); } break; @@ -277,7 +272,7 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) assert(op1->TypeGet() == tree->TypeGet()); info->srcCount = 1; - info->dstCount = 1; + assert(info->dstCount == 1); } break; @@ -294,7 +289,7 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) // see CodeGen::genIntToIntCast() info->srcCount = 1; - info->dstCount = 1; + assert(info->dstCount == 1); // Non-overflow casts to/from float/double are done using SSE2 instructions // and that allow the source operand to be either a reg or memop. Given the @@ -320,10 +315,9 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) #endif // DEBUG // Some overflow checks need a temp reg - CastInfo castInfo; - + Lowering::CastInfo castInfo; // Get information about the cast. - getCastDescription(tree, &castInfo); + Lowering::getCastDescription(tree, &castInfo); if (castInfo.requiresOverflowCheck) { @@ -347,12 +341,12 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) case GT_NEG: info->srcCount = 1; - info->dstCount = 1; + assert(info->dstCount == 1); break; case GT_NOT: info->srcCount = 1; - info->dstCount = 1; + assert(info->dstCount == 1); break; case GT_LSH: @@ -368,27 +362,36 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) case GT_LE: case GT_GE: case GT_GT: + case GT_TEST_EQ: + case GT_TEST_NE: TreeNodeInfoInitCmp(tree); break; case GT_CKFINITE: - info->srcCount = 1; - info->dstCount = 1; + info->srcCount = 1; + assert(info->dstCount == 1); info->internalIntCount = 1; break; case GT_CMPXCHG: info->srcCount = 3; - info->dstCount = 1; + assert(info->dstCount == 1); // TODO-ARM64-NYI NYI("CMPXCHG"); break; case GT_LOCKADD: - ContainCheckBinary(tree->AsOp()); info->srcCount = tree->gtOp.gtOp2->isContained() ? 1 : 2; - info->dstCount = 1; + assert(info->dstCount == 1); + break; + + case GT_PUTARG_STK: + TreeNodeInfoInitPutArgStk(tree->AsPutArgStk()); + break; + + case GT_PUTARG_REG: + TreeNodeInfoInitPutArgReg(tree->AsUnOp()); break; case GT_CALL: @@ -399,10 +402,10 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) { // For a GT_ADDR, the child node should not be evaluated into a register GenTreePtr child = tree->gtOp.gtOp1; - assert(!l->isCandidateLocalRef(child)); - MakeSrcContained(tree, child); + assert(!isCandidateLocalRef(child)); + assert(child->isContained()); + assert(info->dstCount == 1); info->srcCount = 0; - info->dstCount = 1; } break; @@ -411,26 +414,22 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) // These should all be eliminated prior to Lowering. assert(!"Non-store block node in Lowering"); info->srcCount = 0; - info->dstCount = 0; break; case GT_STORE_BLK: case GT_STORE_OBJ: case GT_STORE_DYN_BLK: - LowerBlockStore(tree->AsBlk()); TreeNodeInfoInitBlockStore(tree->AsBlk()); break; case GT_INIT_VAL: // Always a passthrough of its child's value. - info->srcCount = 0; - info->dstCount = 0; + assert(!"INIT_VAL should always be contained"); break; case GT_LCLHEAP: { - ContainCheckLclHeap(tree->AsOp()); - info->dstCount = 1; + assert(info->dstCount == 1); // Need a variable number of temp regs (see genLclHeap() in codegenamd64.cpp): // Here '-' means don't care. @@ -536,7 +535,7 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) GenTreeBoundsChk* node = tree->AsBoundsChk(); // Consumes arrLen & index - has no result info->srcCount = 2; - info->dstCount = 0; + assert(info->dstCount == 0); GenTree* intCns = nullptr; GenTree* other = nullptr; @@ -555,12 +554,12 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) // These must have been lowered to GT_ARR_INDEX noway_assert(!"We should never see a GT_ARR_ELEM in lowering"); info->srcCount = 0; - info->dstCount = 0; + assert(info->dstCount == 0); break; case GT_ARR_INDEX: - info->srcCount = 2; - info->dstCount = 1; + info->srcCount = 2; + assert(info->dstCount == 1); info->internalIntCount = 1; info->isInternalRegDelayFree = true; @@ -571,11 +570,10 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) break; case GT_ARR_OFFSET: - ContainCheckArrOffset(tree->AsArrOffs()); // This consumes the offset, if any, the arrObj and the effective index, // and produces the flattened offset for this dimension. - info->srcCount = tree->gtArrOffs.gtOffset->isContained() ? 2 : 3; - info->dstCount = 1; + info->srcCount = tree->gtArrOffs.gtOffset->isContained() ? 2 : 3; + assert(info->dstCount == 1); info->internalIntCount = 1; break; @@ -585,10 +583,9 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) GenTree* base = lea->Base(); GenTree* index = lea->Index(); - unsigned cns = lea->gtOffset; + int cns = lea->Offset(); - // This LEA is instantiating an address, - // so we set up the srcCount and dstCount here. + // This LEA is instantiating an address, so we set up the srcCount here. info->srcCount = 0; if (base != nullptr) { @@ -598,7 +595,7 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) { info->srcCount++; } - info->dstCount = 1; + assert(info->dstCount == 1); // On ARM64 we may need a single internal register // (when both conditions are true then we still only need a single internal register) @@ -617,7 +614,7 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) case GT_STOREIND: { - info->dstCount = 0; + assert(info->dstCount == 0); if (compiler->codeGen->gcInfo.gcIsWriteBarrierAsgNode(tree)) { @@ -635,23 +632,23 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) break; case GT_NULLCHECK: - info->dstCount = 0; - info->srcCount = 1; - info->isLocalDefUse = true; - // null check is an indirection on an addr - TreeNodeInfoInitIndir(tree->AsIndir()); + // Unlike ARM, ARM64 implements NULLCHECK as a load to REG_ZR, so no internal register + // is required, and it is not a localDefUse. + assert(info->dstCount == 0); + assert(!tree->gtGetOp1()->isContained()); + info->srcCount = 1; break; case GT_IND: - info->dstCount = 1; + assert(info->dstCount == 1); info->srcCount = 1; TreeNodeInfoInitIndir(tree->AsIndir()); break; case GT_CATCH_ARG: info->srcCount = 0; - info->dstCount = 1; - info->setDstCandidates(l, RBM_EXCEPTION_OBJECT); + assert(info->dstCount == 1); + info->setDstCandidates(this, RBM_EXCEPTION_OBJECT); break; case GT_CLS_VAR: @@ -661,12 +658,22 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) // It will produce a result of the type of the // node, and use an internal register for the address. - info->dstCount = 1; + assert(info->dstCount == 1); assert((tree->gtFlags & (GTF_VAR_DEF | GTF_VAR_USEASG)) == 0); info->internalIntCount = 1; break; + + case GT_INDEX_ADDR: + info->srcCount = 2; + info->dstCount = 1; + info->internalIntCount = 1; + break; } // end switch (tree->OperGet()) + if (tree->IsUnusedValue() && (info->dstCount != 0)) + { + info->isLocalDefUse = true; + } // We need to be sure that we've set info->srcCount and info->dstCount appropriately assert((info->dstCount < 2) || tree->IsMultiRegCall()); } @@ -680,19 +687,15 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) // Return Value: // None. // -void Lowering::TreeNodeInfoInitReturn(GenTree* tree) +void LinearScan::TreeNodeInfoInitReturn(GenTree* tree) { - ContainCheckRet(tree->AsOp()); - - TreeNodeInfo* info = &(tree->gtLsraInfo); - LinearScan* l = m_lsra; - Compiler* compiler = comp; + TreeNodeInfo* info = &(tree->gtLsraInfo); GenTree* op1 = tree->gtGetOp1(); regMaskTP useCandidates = RBM_NONE; info->srcCount = ((tree->TypeGet() == TYP_VOID) || op1->isContained()) ? 0 : 1; - info->dstCount = 0; + assert(info->dstCount == 0); if (varTypeIsStruct(tree)) { @@ -731,7 +734,7 @@ void Lowering::TreeNodeInfoInitReturn(GenTree* tree) if (useCandidates != RBM_NONE) { - tree->gtOp.gtOp1->gtLsraInfo.setSrcCandidates(l, useCandidates); + tree->gtOp.gtOp1->gtLsraInfo.setSrcCandidates(this, useCandidates); } } |