From 61d6a817e39d3bae0f47dbc09838d51db22a5d30 Mon Sep 17 00:00:00 2001 From: Jiyoung Yun Date: Tue, 13 Jun 2017 18:47:36 +0900 Subject: Imported Upstream version 2.0.0.11992 --- src/jit/morph.cpp | 77 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 24 deletions(-) (limited to 'src/jit/morph.cpp') diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp index f63496b686..6928c3c393 100644 --- a/src/jit/morph.cpp +++ b/src/jit/morph.cpp @@ -6099,7 +6099,7 @@ GenTreePtr Compiler::fgMorphStackArgForVarArgs(unsigned lclNum, var_types varTyp * Transform the given GT_LCL_VAR tree for code generation. */ -GenTreePtr Compiler::fgMorphLocalVar(GenTreePtr tree) +GenTreePtr Compiler::fgMorphLocalVar(GenTreePtr tree, bool forceRemorph) { noway_assert(tree->gtOper == GT_LCL_VAR); @@ -6129,7 +6129,7 @@ GenTreePtr Compiler::fgMorphLocalVar(GenTreePtr tree) /* If not during the global morphing phase bail */ - if (!fgGlobalMorph) + if (!fgGlobalMorph && !forceRemorph) { return tree; } @@ -6560,6 +6560,13 @@ GenTreePtr Compiler::fgMorphField(GenTreePtr tree, MorphAddrContext* mac) GenTreePtr tlsRef = gtNewIconHandleNode(WIN32_TLS_SLOTS, GTF_ICON_TLS_HDL); + // Translate GTF_FLD_INITCLASS to GTF_ICON_INITCLASS + if ((tree->gtFlags & GTF_FLD_INITCLASS) != 0) + { + tree->gtFlags &= ~GTF_FLD_INITCLASS; + tlsRef->gtFlags |= GTF_ICON_INITCLASS; + } + tlsRef = gtNewOperNode(GT_IND, TYP_I_IMPL, tlsRef); if (dllRef != nullptr) @@ -6614,6 +6621,12 @@ GenTreePtr Compiler::fgMorphField(GenTreePtr tree, MorphAddrContext* mac) FieldSeqNode* fieldSeq = fieldMayOverlap ? FieldSeqStore::NotAField() : GetFieldSeqStore()->CreateSingleton(symHnd); addr->gtIntCon.gtFieldSeq = fieldSeq; + // Translate GTF_FLD_INITCLASS to GTF_ICON_INITCLASS + if ((tree->gtFlags & GTF_FLD_INITCLASS) != 0) + { + tree->gtFlags &= ~GTF_FLD_INITCLASS; + addr->gtFlags |= GTF_ICON_INITCLASS; + } tree->SetOper(GT_IND); // The GTF_FLD_NULLCHECK is the same bit as GTF_IND_ARR_LEN. @@ -6628,9 +6641,10 @@ GenTreePtr Compiler::fgMorphField(GenTreePtr tree, MorphAddrContext* mac) else #endif // _TARGET_64BIT_ { - // Only volatile could be set, and it maps over - noway_assert((tree->gtFlags & ~(GTF_FLD_VOLATILE | GTF_COMMON_MASK)) == 0); - noway_assert(GTF_FLD_VOLATILE == GTF_IND_VOLATILE); + // Only volatile or classinit could be set, and they map over + noway_assert((tree->gtFlags & ~(GTF_FLD_VOLATILE | GTF_FLD_INITCLASS | GTF_COMMON_MASK)) == 0); + static_assert_no_msg(GTF_FLD_VOLATILE == GTF_CLS_VAR_VOLATILE); + static_assert_no_msg(GTF_FLD_INITCLASS == GTF_CLS_VAR_INITCLASS); tree->SetOper(GT_CLS_VAR); tree->gtClsVar.gtClsVarHnd = symHnd; FieldSeqNode* fieldSeq = @@ -6644,6 +6658,13 @@ GenTreePtr Compiler::fgMorphField(GenTreePtr tree, MorphAddrContext* mac) { GenTreePtr addr = gtNewIconHandleNode((size_t)pFldAddr, GTF_ICON_STATIC_HDL); + // Translate GTF_FLD_INITCLASS to GTF_ICON_INITCLASS + if ((tree->gtFlags & GTF_FLD_INITCLASS) != 0) + { + tree->gtFlags &= ~GTF_FLD_INITCLASS; + addr->gtFlags |= GTF_ICON_INITCLASS; + } + // There are two cases here, either the static is RVA based, // in which case the type of the FIELD node is not a GC type // and the handle to the RVA is a TYP_I_IMPL. Or the FIELD node is @@ -8522,7 +8543,8 @@ GenTreePtr Compiler::fgMorphLeaf(GenTreePtr tree) if (tree->gtOper == GT_LCL_VAR) { - return fgMorphLocalVar(tree); + const bool forceRemorph = false; + return fgMorphLocalVar(tree, forceRemorph); } #ifdef _TARGET_X86_ else if (tree->gtOper == GT_LCL_FLD) @@ -13132,26 +13154,14 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) varTypeIsStruct(tempTyp) || (tempTyp == TYP_BLK) || (tempTyp == TYP_LCLBLK); const unsigned varSize = useExactSize ? varDsc->lvExactSize : genTypeSize(temp); + // Make sure we do not enregister this lclVar. + lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_LocalField)); + // If the size of the load is greater than the size of the lclVar, we cannot fold this access into // a lclFld: the access represented by an lclFld node must begin at or after the start of the // lclVar and must not extend beyond the end of the lclVar. - if ((ival1 < 0) || ((ival1 + genTypeSize(typ)) > varSize)) - { - lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_LocalField)); - } - else + if ((ival1 >= 0) && ((ival1 + genTypeSize(typ)) <= varSize)) { - // Make sure we don't separately promote the fields of this struct. - if (varDsc->lvRegStruct) - { - // We can enregister, but can't promote. - varDsc->lvPromoted = false; - } - else - { - lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_LocalField)); - } - // We will turn a GT_LCL_VAR into a GT_LCL_FLD with an gtLclOffs of 'ival' // or if we already have a GT_LCL_FLD we will adjust the gtLclOffs by adding 'ival' // Then we change the type of the GT_LCL_FLD to match the orginal GT_IND type. @@ -13195,6 +13205,25 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) DEBUG_DESTROY_NODE(op1); // GT_ADD or GT_ADDR DEBUG_DESTROY_NODE(tree); // GT_IND + // If the result of the fold is a local var, we may need to perform further adjustments e.g. for + // normalization. + if (temp->OperIs(GT_LCL_VAR)) + { +#ifdef DEBUG + // We clear this flag on `temp` because `fgMorphLocalVar` may assert that this bit is clear + // and the node in question must have this bit set (as it has already been morphed). + temp->gtDebugFlags &= ~GTF_DEBUG_NODE_MORPHED; +#endif // DEBUG + const bool forceRemorph = true; + temp = fgMorphLocalVar(temp, forceRemorph); +#ifdef DEBUG + // We then set this flag on `temp` because `fgMorhpLocalVar` may not set it itself, and the + // caller of `fgMorphSmpOp` may assert that this flag is set on `temp` once this function + // returns. + temp->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED; +#endif // DEBUG + } + return temp; } @@ -13644,7 +13673,7 @@ GenTree* Compiler::fgMorphSmpOpOptional(GenTreeOp* tree) GenTree* op2 = tree->gtOp2; var_types typ = tree->TypeGet(); - if (GenTree::OperIsCommutative(oper)) + if (fgGlobalMorph && GenTree::OperIsCommutative(oper)) { /* Swap the operands so that the more expensive one is 'op1' */ @@ -13682,7 +13711,7 @@ GenTree* Compiler::fgMorphSmpOpOptional(GenTreeOp* tree) /* Change "((x+icon)+y)" to "((x+y)+icon)" Don't reorder floating-point operations */ - if ((oper == GT_ADD) && !tree->gtOverflow() && (op1->gtOper == GT_ADD) && !op1->gtOverflow() && + if (fgGlobalMorph && (oper == GT_ADD) && !tree->gtOverflow() && (op1->gtOper == GT_ADD) && !op1->gtOverflow() && varTypeIsIntegralOrI(typ)) { GenTreePtr ad2 = op1->gtOp.gtOp2; -- cgit v1.2.3