diff options
author | Sergey Andreenko <seandree@microsoft.com> | 2017-12-14 18:17:53 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-12-14 18:17:53 -0800 |
commit | 9576b24e491b8a28442dec2696b862dcb29ddc25 (patch) | |
tree | cfa65eb065decd55ec3bed6e45f40076ba29fb75 /src | |
parent | 8a09729219e81a4951a6911b1b1eb4a199d0e178 (diff) | |
download | coreclr-9576b24e491b8a28442dec2696b862dcb29ddc25.tar.gz coreclr-9576b24e491b8a28442dec2696b862dcb29ddc25.tar.bz2 coreclr-9576b24e491b8a28442dec2696b862dcb29ddc25.zip |
[RyuJit][Armel] Do not lose type information (#15449)
* Do not lose type information
fgMorphMultiregStructArg could lose type information when replaced smth like this:
GT_OBJ - TYP_STRUCT <== arg
+ GT_ADDR - TYP_I_IMPL
+ + GT_LCL_VAR - TYP_BLK <== argValue
* Move the test to pri0 to test in ci.
* add an assert
* add the test to the arm list
* make the optimization only if struct handlers match.
* format job
* fix for the unoptimized case.
* check that we have addr node.
* change the reason to lvaSetVarDoNotEnregister
Diffstat (limited to 'src')
-rw-r--r-- | src/jit/morph.cpp | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp index 73883e57b4..b5d2e8a96f 100644 --- a/src/jit/morph.cpp +++ b/src/jit/morph.cpp @@ -4963,11 +4963,18 @@ GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr f objClass = argObj->gtClass; structSize = info.compCompHnd->getClassSize(objClass); - // If we have a GT_OBJ of a GT_ADDR then we set argValue to the child node of the GT_ADDR - // - if (argObj->gtOp1->OperGet() == GT_ADDR) + // If we have a GT_OBJ of a GT_ADDR then we set argValue to the child node of the GT_ADDR. + GenTree* op1 = argObj->gtOp1; + if (op1->OperGet() == GT_ADDR) { - argValue = argObj->gtOp1->gtOp.gtOp1; + GenTree* underlyingTree = op1->gtOp.gtOp1; + + // Only update to the same type. + if ((underlyingTree->TypeGet() == argValue->TypeGet()) && + (objClass == gtGetStructHandleIfPresent(underlyingTree))) + { + argValue = underlyingTree; + } } } else if (arg->OperGet() == GT_LCL_VAR) @@ -5342,6 +5349,19 @@ GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr f GenTreePtr baseAddr = argObj->gtOp1; var_types addrType = baseAddr->TypeGet(); + if (baseAddr->OperGet() == GT_ADDR) + { + GenTree* addrTaken = baseAddr->gtOp.gtOp1; + if (addrTaken->IsLocal()) + { + GenTreeLclVarCommon* varNode = addrTaken->AsLclVarCommon(); + unsigned varNum = varNode->gtLclNum; + // We access non-struct type (for example, long) as a struct type. + // Make sure lclVar lives on stack to make sure its fields are accessible by address. + lvaSetVarDoNotEnregister(varNum DEBUGARG(DNER_LocalField)); + } + } + // Create a new tree for 'arg' // replace the existing LDOBJ(EXPR) // with a FIELD_LIST(IND(EXPR), FIELD_LIST(IND(EXPR+8), nullptr) ...) |