From 4b11dc566a5bbfa1378d6266525c281b028abcc8 Mon Sep 17 00:00:00 2001 From: Jiyoung Yun Date: Fri, 10 Feb 2017 20:35:12 +0900 Subject: Imported Upstream version 1.0.0.9910 --- src/jit/lowerarm.cpp | 148 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 123 insertions(+), 25 deletions(-) (limited to 'src/jit/lowerarm.cpp') diff --git a/src/jit/lowerarm.cpp b/src/jit/lowerarm.cpp index 5bf23c4199..9792b8a9c6 100644 --- a/src/jit/lowerarm.cpp +++ b/src/jit/lowerarm.cpp @@ -23,8 +23,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #ifndef LEGACY_BACKEND // This file is ONLY used for the RyuJIT backend that uses the linear scan register allocator -// The ARM backend is not yet implemented, so the methods here are all NYI. -// TODO-ARM-NYI: Lowering for ARM. #ifdef _TARGET_ARM_ #include "jit.h" @@ -32,6 +30,68 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #include "lower.h" #include "lsra.h" +//------------------------------------------------------------------------ +// LowerStoreLoc: Lower a store of a lclVar +// +// Arguments: +// storeLoc - the local store (GT_STORE_LCL_FLD or GT_STORE_LCL_VAR) +// +// Notes: +// This involves: +// - Widening operations of unsigneds. +// +void Lowering::LowerStoreLoc(GenTreeLclVarCommon* storeLoc) +{ + // Try to widen the ops if they are going into a local var. + GenTree* op1 = storeLoc->gtGetOp1(); + if ((storeLoc->gtOper == GT_STORE_LCL_VAR) && (op1->gtOper == GT_CNS_INT)) + { + GenTreeIntCon* con = op1->AsIntCon(); + ssize_t ival = con->gtIconVal; + unsigned varNum = storeLoc->gtLclNum; + LclVarDsc* varDsc = comp->lvaTable + varNum; + + if (varDsc->lvIsSIMDType()) + { + noway_assert(storeLoc->gtType != TYP_STRUCT); + } + unsigned size = genTypeSize(storeLoc); + // If we are storing a constant into a local variable + // we extend the size of the store here + if ((size < 4) && !varTypeIsStruct(varDsc)) + { + if (!varTypeIsUnsigned(varDsc)) + { + if (genTypeSize(storeLoc) == 1) + { + if ((ival & 0x7f) != ival) + { + ival = ival | 0xffffff00; + } + } + else + { + assert(genTypeSize(storeLoc) == 2); + if ((ival & 0x7fff) != ival) + { + ival = ival | 0xffff0000; + } + } + } + + // A local stack slot is at least 4 bytes in size, regardless of + // what the local var is typed as, so auto-promote it here + // unless it is a field of a promoted struct + // TODO-ARM-CQ: if the field is promoted shouldn't we also be able to do this? + if (!varDsc->lvIsStructField) + { + storeLoc->gtType = TYP_INT; + con->SetIconValue(ival); + } + } + } +} + //------------------------------------------------------------------------ // LowerCast: Lower GT_CAST(srcType, DstType) nodes. // @@ -57,7 +117,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // Note that for the overflow conversions we still depend on helper calls and // don't expect to see them here. // i) GT_CAST(float/double, int type with overflow detection) - +// void Lowering::LowerCast(GenTree* tree) { assert(tree->OperGet() == GT_CAST); @@ -71,10 +131,8 @@ void Lowering::LowerCast(GenTree* tree) var_types srcType = op1->TypeGet(); var_types tmpType = TYP_UNDEF; - // TODO-ARM-Cleanup: Remove following NYI assertions. if (varTypeIsFloating(srcType)) { - NYI_ARM("Lowering for cast from float"); // Not tested yet. noway_assert(!tree->gtOverflow()); } @@ -104,36 +162,78 @@ void Lowering::LowerCast(GenTree* tree) } } +//------------------------------------------------------------------------ +// LowerRotate: Lower GT_ROL and GT_ROL nodes. +// +// Arguments: +// tree - the node to lower +// +// Return Value: +// None. +// void Lowering::LowerRotate(GenTreePtr tree) { - NYI_ARM("ARM Lowering for ROL and ROR"); -} + if (tree->OperGet() == GT_ROL) + { + // There is no ROL instruction on ARM. Convert ROL into ROR. + GenTreePtr rotatedValue = tree->gtOp.gtOp1; + unsigned rotatedValueBitSize = genTypeSize(rotatedValue->gtType) * 8; + GenTreePtr rotateLeftIndexNode = tree->gtOp.gtOp2; -void Lowering::TreeNodeInfoInit(GenTree* stmt) -{ - NYI("ARM TreeNodInfoInit"); + if (rotateLeftIndexNode->IsCnsIntOrI()) + { + ssize_t rotateLeftIndex = rotateLeftIndexNode->gtIntCon.gtIconVal; + ssize_t rotateRightIndex = rotatedValueBitSize - rotateLeftIndex; + rotateLeftIndexNode->gtIntCon.gtIconVal = rotateRightIndex; + } + else + { + GenTreePtr tmp = + comp->gtNewOperNode(GT_NEG, genActualType(rotateLeftIndexNode->gtType), rotateLeftIndexNode); + BlockRange().InsertAfter(rotateLeftIndexNode, tmp); + tree->gtOp.gtOp2 = tmp; + } + tree->ChangeOper(GT_ROR); + } } -// returns true if the tree can use the read-modify-write memory instruction form -bool Lowering::isRMWRegOper(GenTreePtr tree) +//------------------------------------------------------------------------ +// LowerPutArgStk: Lower a GT_PUTARG_STK node +// +// Arguments: +// argNode - a GT_PUTARG_STK node +// +// Return Value: +// None. +// +// Notes: +// There is currently no Lowering required for this on ARM. +// +void Lowering::LowerPutArgStk(GenTreePutArgStk* argNode, fgArgTabEntryPtr info) { - return false; } +//------------------------------------------------------------------------ +// IsCallTargetInRange: Can a call target address be encoded in-place? +// +// Return Value: +// True if the addr fits into the range. +// bool Lowering::IsCallTargetInRange(void* addr) { return comp->codeGen->validImmForBL((ssize_t)addr); } -// return true if the immediate can be folded into an instruction, for example small enough and non-relocatable +//------------------------------------------------------------------------ +// IsContainableImmed: Is an immediate encodable in-place? +// +// Return Value: +// True if the immediate can be folded into an instruction, +// for example small enough and non-relocatable. bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode) { if (varTypeIsFloating(parentNode->TypeGet())) { - // TODO-ARM-Cleanup: not tested yet. - NYI_ARM("ARM IsContainableImmed for floating point type"); - - // We can contain a floating point 0.0 constant in a compare instruction switch (parentNode->OperGet()) { default: @@ -146,7 +246,12 @@ bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode) case GT_GE: case GT_GT: if (childNode->IsIntegralConst(0)) + { + // TODO-ARM-Cleanup: not tested yet. + NYI_ARM("ARM IsContainableImmed for floating point type"); + // We can contain a floating point 0.0 constant in a compare instruction return true; + } break; } } @@ -185,13 +290,6 @@ bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode) if (emitter::emitIns_valid_imm_for_alu(immVal)) return true; break; - - case GT_STORE_LCL_VAR: - // TODO-ARM-Cleanup: not tested yet - NYI_ARM("ARM IsContainableImmed for GT_STORE_LCL_VAR"); - if (immVal == 0) - return true; - break; } } -- cgit v1.2.3