Skip to content

Commit

Permalink
Don't mark LCL_VAR that is used in RETURN(IND(ADDR(LCL_VAR)) as addre…
Browse files Browse the repository at this point in the history
…ss taken when possible

11 methods improved, 3 regression fixed, -100 bytes diff.
  • Loading branch information
Sergey Andreenko committed Jun 11, 2020
1 parent b2ce59f commit 22c3a1b
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 35 deletions.
1 change: 1 addition & 0 deletions src/coreclr/src/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5595,6 +5595,7 @@ class Compiler
GenTree* fgMorphCopyBlock(GenTree* tree);
GenTree* fgMorphForRegisterFP(GenTree* tree);
GenTree* fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac = nullptr);
GenTree* fgMorphRetInd(GenTreeUnOp* tree);
GenTree* fgMorphModToSubMulDiv(GenTreeOp* tree);
GenTree* fgMorphSmpOpOptional(GenTreeOp* tree);

Expand Down
27 changes: 15 additions & 12 deletions src/coreclr/src/jit/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2935,7 +2935,6 @@ void Lowering::LowerRet(GenTreeUnOp* ret)
if ((ret->TypeGet() != TYP_VOID) && !varTypeIsStruct(ret) &&
(varTypeUsesFloatReg(ret) != varTypeUsesFloatReg(ret->gtGetOp1())))
{
assert(comp->compDoOldStructRetyping());
GenTreeUnOp* bitcast = new (comp, GT_BITCAST) GenTreeOp(GT_BITCAST, ret->TypeGet(), ret->gtGetOp1(), nullptr);
ret->gtOp1 = bitcast;
BlockRange().InsertBefore(ret, bitcast);
Expand All @@ -2952,15 +2951,26 @@ void Lowering::LowerRet(GenTreeUnOp* ret)
if (varTypeIsStruct(ret->TypeGet()))
{
assert(!comp->compDoOldStructRetyping());
bool actualTypesMatch = false;
if (genActualType(comp->info.compRetNativeType) == genActualType(retVal->TypeGet()))
bool constStructInit = retVal->IsConstInitVal();

bool actualTypesMatch = false;
var_types retActualType = genActualType(comp->info.compRetNativeType);
var_types retValActualType = genActualType(retVal->TypeGet());
if (retActualType == retValActualType)
{
// This could happen if we have retyped op1 as a primitive type during struct promotion,
// check `retypedFieldsMap` for details.
actualTypesMatch = true;
}
bool constStructInit = retVal->IsConstInitVal();
assert(actualTypesMatch || constStructInit);
assert(comp->info.compRetNativeType != TYP_STRUCT);

bool implicitCastFromSameOrBiggerSize = false;
if (genTypeSize(retActualType) <= genTypeSize(retValActualType))
{
implicitCastFromSameOrBiggerSize = true;
}

assert(actualTypesMatch || constStructInit || implicitCastFromSameOrBiggerSize);
}
else
{
Expand Down Expand Up @@ -3248,13 +3258,6 @@ void Lowering::LowerRetStructLclVar(GenTreeUnOp* ret)
unsigned lclNum = lclVar->GetLclNum();
LclVarDsc* varDsc = comp->lvaGetDesc(lclNum);

#ifdef DEBUG
if (comp->gtGetStructHandleIfPresent(lclVar) == NO_CLASS_HANDLE)
{
// a promoted struct field was retyped as its only field.
assert(varDsc->lvIsStructField);
}
#endif
if (varDsc->lvPromoted && (comp->lvaGetPromotionType(lclNum) == Compiler::PROMOTION_TYPE_INDEPENDENT))
{
if (varDsc->lvFieldCnt == 1)
Expand Down
90 changes: 67 additions & 23 deletions src/coreclr/src/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11965,30 +11965,9 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)

return tree;
}
if (varTypeIsStruct(tree) && op1->OperIs(GT_OBJ, GT_BLK))
if (!compDoOldStructRetyping() && !tree->TypeIs(TYP_VOID) && op1->OperIs(GT_OBJ, GT_BLK, GT_IND))
{
assert(!compDoOldStructRetyping());
GenTree* addr = op1->AsBlk()->Addr();
// if we return `OBJ` or `BLK` from a local var, lcl var has to have a stack address.
if (addr->OperIs(GT_ADDR) && addr->gtGetOp1()->OperIs(GT_LCL_VAR))
{
GenTreeLclVar* lclVar = addr->gtGetOp1()->AsLclVar();
assert(!gtIsActiveCSE_Candidate(addr) && !gtIsActiveCSE_Candidate(op1));
if (gtGetStructHandle(tree) == gtGetStructHandleIfPresent(lclVar))
{
// Fold *(&x).
tree->AsUnOp()->gtOp1 = op1;
DEBUG_DESTROY_NODE(op1);
DEBUG_DESTROY_NODE(addr);
op1 = lclVar;
}
else
{
// TODO-1stClassStructs: It is not address-taken or block operation,
// but the current IR doesn't allow to express that cast without stack, see #11413.
lvaSetVarDoNotEnregister(lclVar->GetLclNum() DEBUGARG(DNER_BlockOp));
}
}
op1 = fgMorphRetInd(tree->AsUnOp());
}
break;

Expand Down Expand Up @@ -14209,6 +14188,71 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)

return tree;
}

//----------------------------------------------------------------------------------------------
// fgMorphRetInd: Try to get rid of extra IND(ADDR()) pairs in a return tree.
//
// Arguments:
// node - The return node that uses an indirection.
//
// Return Value:
// the original op1 of the ret if there was no optimization or an optimized new op1.
//
GenTree* Compiler::fgMorphRetInd(GenTreeUnOp* ret)
{
assert(!compDoOldStructRetyping());
assert(ret->OperIs(GT_RETURN));
assert(ret->gtGetOp1()->OperIs(GT_IND, GT_BLK, GT_OBJ));
GenTreeIndir* ind = ret->gtGetOp1()->AsIndir();
GenTree* addr = ind->Addr();

if (addr->OperIs(GT_ADDR) && addr->gtGetOp1()->OperIs(GT_LCL_VAR))
{
// If `return` retypes LCL_VAR as a smaller struct it should not set `doNotEnregister` on that
// LclVar.
// Example: in `Vector128:AsVector2` we have RETURN SIMD8(OBJ SIMD8(ADDR byref(LCL_VAR SIMD16))).
GenTreeLclVar* lclVar = addr->gtGetOp1()->AsLclVar();
if (!lvaIsImplicitByRefLocal(lclVar->GetLclNum()))
{
assert(!gtIsActiveCSE_Candidate(addr) && !gtIsActiveCSE_Candidate(ind));
unsigned indSize;
if (ind->OperIs(GT_IND))
{
indSize = genTypeSize(ind);
}
else
{
indSize = ind->AsBlk()->GetLayout()->GetSize();
}

LclVarDsc* varDsc = lvaGetDesc(lclVar);

unsigned lclVarSize;
if (!lclVar->TypeIs(TYP_STRUCT))

{
lclVarSize = genTypeSize(lclVar->TypeGet());
}
else
{
lclVarSize = varDsc->lvExactSize;
}
assert((indSize <= lclVarSize) || varDsc->lvDoNotEnregister);
if (indSize <= lclVarSize)
{
// Fold (TYPE1)*(&(TYPE2)x) even if types do not match, lowering will handle it.
// Getting rid of this IND(ADDR()) pair allows to keep lclVar as not address taken
// and enregister it.
DEBUG_DESTROY_NODE(ind);
DEBUG_DESTROY_NODE(addr);
ret->gtOp1 = lclVar;
return ret->gtOp1;
}
}
}
return ind;
}

#ifdef _PREFAST_
#pragma warning(pop)
#endif
Expand Down

0 comments on commit 22c3a1b

Please sign in to comment.