diff options
author | Hongtao Yu <Hongtao.Yu@microsoft.com> | 2016-01-11 15:24:49 -0800 |
---|---|---|
committer | Hongtao Yu <hoy@microsoft.com> | 2016-01-12 16:56:54 -0800 |
commit | f5bee7d646dc2b2ee185c4862be6076ac0b7d773 (patch) | |
tree | 0e0ed20889ff9e5d16097339e134589af78f91d0 /src | |
parent | 880da9d64f23e2e7661eb0471f8d79394fc324d7 (diff) | |
download | coreclr-f5bee7d646dc2b2ee185c4862be6076ac0b7d773.tar.gz coreclr-f5bee7d646dc2b2ee185c4862be6076ac0b7d773.tar.bz2 coreclr-f5bee7d646dc2b2ee185c4862be6076ac0b7d773.zip |
Fix for bug 2610 Incorrect copy prop substitution.
The bug is due to missing lvAddrExposed flag for tmp vars serving as pass-by-ref arguments.
Diffstat (limited to 'src')
-rw-r--r-- | src/jit/morph.cpp | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp index db4a455722..4d3b086339 100644 --- a/src/jit/morph.cpp +++ b/src/jit/morph.cpp @@ -1997,6 +1997,7 @@ GenTreePtr Compiler::fgMakeTmpArgNode(unsigned tmpVarNum // Create a copy of the temp to go into the late argument list GenTreePtr arg = gtNewLclvNode(tmpVarNum, type); + GenTreePtr addrNode = nullptr; if (varTypeIsStruct(type)) { @@ -2017,6 +2018,7 @@ GenTreePtr Compiler::fgMakeTmpArgNode(unsigned tmpVarNum else { arg = gtNewOperNode(GT_ADDR, TYP_STRUCT, arg); + addrNode = arg; } #else // !FEATURE_UNIX_AMD64_STRUCT_PASSING @@ -2073,9 +2075,9 @@ GenTreePtr Compiler::fgMakeTmpArgNode(unsigned tmpVarNum // as that is how FEATURE_UNIX_AMD64_STRUCT_PASSING works. // Pass by value in two registers - arg->gtFlags |= GTF_DONT_CSE; arg = gtNewOperNode(GT_ADDR, TYP_BYREF, arg); - + addrNode = arg; + // Ldobj the temp to use it as a call argument arg = gtNewLdObjNode(lvaGetStruct(tmpVarNum), arg); } @@ -2083,8 +2085,8 @@ GenTreePtr Compiler::fgMakeTmpArgNode(unsigned tmpVarNum #endif // _TARGET_ARM64_ #endif // FEATURE_MULTIREG_STRUCTS { - arg->gtFlags |= GTF_DONT_CSE; arg = gtNewOperNode(GT_ADDR, TYP_I_IMPL, arg); + addrNode = arg; } } else // type was changed from a struct to a scalar type @@ -2099,9 +2101,9 @@ GenTreePtr Compiler::fgMakeTmpArgNode(unsigned tmpVarNum // other targets, we pass the struct by value assert(varTypeIsStruct(type)); - arg->gtFlags |= GTF_DONT_CSE; arg = gtNewOperNode(GT_ADDR, TYP_BYREF, arg); - + addrNode = arg; + // Ldobj the temp to use it as a call argument arg = gtNewLdObjNode(lvaGetStruct(tmpVarNum), arg); arg->gtFlags |= GTF_EXCEPT; @@ -2110,6 +2112,17 @@ GenTreePtr Compiler::fgMakeTmpArgNode(unsigned tmpVarNum } // (varTypeIsStruct(type)) + if (addrNode != nullptr) + { + assert(addrNode->gtOper == GT_ADDR); + + // This will prevent this LclVar from being optimized away + lvaSetVarAddrExposed(tmpVarNum); + + // the child of a GT_ADDR is required to have this flag set + addrNode->gtOp.gtOp1->gtFlags |= GTF_DONT_CSE; + } + return arg; } |