summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHongtao Yu <Hongtao.Yu@microsoft.com>2016-01-11 15:24:49 -0800
committerHongtao Yu <hoy@microsoft.com>2016-01-12 16:56:54 -0800
commitf5bee7d646dc2b2ee185c4862be6076ac0b7d773 (patch)
tree0e0ed20889ff9e5d16097339e134589af78f91d0 /src
parent880da9d64f23e2e7661eb0471f8d79394fc324d7 (diff)
downloadcoreclr-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.cpp23
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;
}