diff options
Diffstat (limited to 'src/jit/lowerarmarch.cpp')
-rw-r--r-- | src/jit/lowerarmarch.cpp | 100 |
1 files changed, 86 insertions, 14 deletions
diff --git a/src/jit/lowerarmarch.cpp b/src/jit/lowerarmarch.cpp index 7104577839..64c7886a64 100644 --- a/src/jit/lowerarmarch.cpp +++ b/src/jit/lowerarmarch.cpp @@ -126,6 +126,8 @@ bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode) case GT_AND: case GT_OR: case GT_XOR: + case GT_TEST_EQ: + case GT_TEST_NE: return emitter::emitIns_valid_imm_for_alu(immVal, size); break; #elif defined(_TARGET_ARM_) @@ -215,6 +217,21 @@ void Lowering::LowerStoreLoc(GenTreeLclVarCommon* storeLoc) } } } + ContainCheckStoreLoc(storeLoc); +} + +//------------------------------------------------------------------------ +// LowerStoreIndir: Determine addressing mode for an indirection, and whether operands are contained. +// +// Arguments: +// node - The indirect store node (GT_STORE_IND) of interest +// +// Return Value: +// None. +// +void Lowering::LowerStoreIndir(GenTreeIndir* node) +{ + ContainCheckStoreIndir(node); } //------------------------------------------------------------------------ @@ -255,6 +272,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) GenTreePtr initVal = source; if (initVal->OperIsInitVal()) { + initVal->SetContained(); initVal = initVal->gtGetOp1(); } srcAddrOrFill = initVal; @@ -276,7 +294,11 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) // the largest width store of the desired inline expansion. ssize_t fill = initVal->gtIntCon.gtIconVal & 0xFF; - if (size < REGSIZE_BYTES) + if (fill == 0) + { + MakeSrcContained(blkNode, source); + } + else if (size < REGSIZE_BYTES) { initVal->gtIntCon.gtIconVal = 0x01010101 * fill; } @@ -348,6 +370,16 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindHelper; } } + // CopyObj or CopyBlk + if (source->gtOper == GT_IND) + { + MakeSrcContained(blkNode, source); + } + else if (!source->IsMultiRegCall() && !source->OperIsSIMD()) + { + assert(source->IsLocal()); + MakeSrcContained(blkNode, source); + } } } @@ -418,6 +450,9 @@ void Lowering::LowerCast(GenTree* tree) tree->gtOp.gtOp1 = tmp; BlockRange().InsertAfter(op1, tmp); } + + // Now determine if we have operands that should be contained. + ContainCheckCast(tree->AsCast()); } //------------------------------------------------------------------------ @@ -453,6 +488,7 @@ void Lowering::LowerRotate(GenTreePtr tree) } tree->ChangeOper(GT_ROR); } + ContainCheckShiftRotate(tree->AsOp()); } //------------------------------------------------------------------------ @@ -460,31 +496,67 @@ void Lowering::LowerRotate(GenTreePtr tree) //------------------------------------------------------------------------ //------------------------------------------------------------------------ -// ContainCheckIndir: Determine whether operands of an indir should be contained. +// ContainCheckCallOperands: Determine whether operands of a call should be contained. // // Arguments: -// node - The indirection node of interest -// -// Notes: -// This is called for both store and load indirections. +// call - The call node of interest // // Return Value: // None. // -void Lowering::ContainCheckIndir(GenTreeIndir* indirNode) +void Lowering::ContainCheckCallOperands(GenTreeCall* call) { -#ifdef _TARGET_ARM64_ - if (indirNode->OperIs(GT_STOREIND)) + GenTree* ctrlExpr = call->gtControlExpr; + // If there is an explicit this pointer, we don't want that node to produce anything + // as it is redundant + if (call->gtCallObjp != nullptr) { - GenTree* src = indirNode->gtOp.gtOp2; - if (!varTypeIsFloating(src->TypeGet()) && src->IsIntegralConst(0)) + GenTreePtr thisPtrNode = call->gtCallObjp; + + if (thisPtrNode->canBeContained()) { - // an integer zero for 'src' can be contained. - MakeSrcContained(indirNode, src); + MakeSrcContained(call, thisPtrNode); + if (thisPtrNode->gtOper == GT_PUTARG_REG) + { + MakeSrcContained(call, thisPtrNode->gtOp.gtOp1); + } } } +} + +//------------------------------------------------------------------------ +// ContainCheckStoreIndir: determine whether the sources of a STOREIND node should be contained. +// +// Arguments: +// node - pointer to the node +// +void Lowering::ContainCheckStoreIndir(GenTreeIndir* node) +{ +#ifdef _TARGET_ARM64_ + GenTree* src = node->gtOp.gtOp2; + if (!varTypeIsFloating(src->TypeGet()) && src->IsIntegralConst(0)) + { + // an integer zero for 'src' can be contained. + MakeSrcContained(node, src); + } #endif // _TARGET_ARM64_ + ContainCheckIndir(node); +} +//------------------------------------------------------------------------ +// ContainCheckIndir: Determine whether operands of an indir should be contained. +// +// Arguments: +// indirNode - The indirection node of interest +// +// Notes: +// This is called for both store and load indirections. +// +// Return Value: +// None. +// +void Lowering::ContainCheckIndir(GenTreeIndir* indirNode) +{ // If this is the rhs of a block copy it will be handled when we handle the store. if (indirNode->TypeGet() == TYP_STRUCT) { @@ -498,7 +570,7 @@ void Lowering::ContainCheckIndir(GenTreeIndir* indirNode) GenTreeAddrMode* lea = addr->AsAddrMode(); GenTree* base = lea->Base(); GenTree* index = lea->Index(); - unsigned cns = lea->gtOffset; + int cns = lea->Offset(); #ifdef _TARGET_ARM_ // ARM floating-point load/store doesn't support a form similar to integer |