summaryrefslogtreecommitdiff
path: root/src/jit/lsraarm64.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/lsraarm64.cpp')
-rw-r--r--src/jit/lsraarm64.cpp167
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);
}
}