Closed sandreenko closed 4 years ago
The call side peeling is ok -- it only feeds an assert that the call is found in the right kind of tree.
If the return gets split from the call as you show above then the logic on the return side -- assuming you're hitting the final noway_assert
below:
// Delete GT_RETURN if any
if (nextMorphStmt != nullptr)
{
GenTreePtr retExpr = nextMorphStmt->gtStmtExpr;
noway_assert(retExpr->gtOper == GT_RETURN);
// If var=call, then the next stmt must be a GT_RETURN(TYP_VOID) or GT_RETURN(var).
// This can occur if impSpillStackEnsure() has introduced an assignment to a temp.
if (stmtExpr->gtOper == GT_ASG && info.compRetType != TYP_VOID)
{
noway_assert(stmtExpr->gtGetOp1()->OperIsLocal());
noway_assert(stmtExpr->gtGetOp1()->AsLclVarCommon()->gtLclNum ==
retExpr->gtGetOp1()->AsLclVarCommon()->gtLclNum);
}
-- will need a similar update: you will need to tunnel through casts on the retExpr op1 side to find a non-cast and then assert it is the expected local var.
Run ILC in Release mode with Debug RyuJit with such test:
Set ngenDump for GetAttributeConstructor, you will see:
and
Call 67 will be marked as tail call, but the morph condition for the return statement doesn't expect a cast and will blow up.
It works fine with the release mode of the jit. I am not yet sure about the right fix, but there is strange code in fgMorphCall:
It is inside the
#ifdef Debug
branch, that initially contained only assert checks, but some real code was added recently (#9405). @AndyAyersMS Is it right that we peel casts only in debug and only for the call node, but not for the return statement?cc @MichalStrehovsky @dotnet/jit-contrib.