summaryrefslogtreecommitdiff
path: root/src/jit/codegenlinear.cpp
diff options
context:
space:
mode:
authorPat Gavlin <pagavlin@microsoft.com>2016-10-05 13:43:10 -0700
committerPat Gavlin <pagavlin@microsoft.com>2016-10-06 10:12:05 -0700
commit4319b49cdc3ef514dad2e93ec28ec8003f749aab (patch)
tree915a24ad649a5221ee66ecc279346f3f4bb6cef2 /src/jit/codegenlinear.cpp
parent349542aebf82f2f4d02384598c3a6994aa0b8611 (diff)
downloadcoreclr-4319b49cdc3ef514dad2e93ec28ec8003f749aab.tar.gz
coreclr-4319b49cdc3ef514dad2e93ec28ec8003f749aab.tar.bz2
coreclr-4319b49cdc3ef514dad2e93ec28ec8003f749aab.zip
Always normalize stores when spilling lclVars.
In order to support the semantics of the MSIL evaluation stack, RyuJIT normalizes all "small" lclVars (i.e. lclVars with a non-struct type that is smaller than an int32) from the actual type of the lclVar to int32. This normalization may be performed in one of two ways: - the lclVar's may be normalized when the lclVar is used (load normalization) - at any point at which the value is defined, the value being stored to the lclVar is normalized (store normalization) Store normalization must not be used if the lclVar is aliasable, since the contents of the upper bytes for that lclVar's slot may be modified by some other alias. Load normalization must be used if the lclVar is a method parameter, as there is no guarantee that the caller has properly nomralized the arguments it has passed. As such, any lclVar that is either aliasable or is a method parameter is load-normalized, and any other lclVar is store-normalized. lclVars that are store-normalized are assumed to be represented as properly zero- or sign-extended 4-byte values at all times, and so can simply be loaded as int32s. This picture becomes somewhat more subtle after register allocation, however: once a lclVar has been enregistered, the contents of its register are guaranteed to be properly zero- or sign-extended for the purposes of store normalization, and in order for the lclVar to have been enregistered in the first place, it must not have been aliasable. As such, all enregistered variables may be store-normalized (as well as load-normalized, if they represent method parameters). This has a particularly significant impact on spills, as it implies that even if the lclVar being spilled is not normally considered store-normalized, it may be considered so for the purposes of the spill. This is advantageous for architectures such as x86, as it allows a small lclVar to be successfully spilled from a register that is not addressable at the size of the lclVar's type. This change switches both LSRA and the code generator to always use the actual type of a spilled lclVar for the corresponding store rather than making this behavior conditional on whether or not the lclVar is store-normalized. Fixes #7236.
Diffstat (limited to 'src/jit/codegenlinear.cpp')
-rw-r--r--src/jit/codegenlinear.cpp12
1 files changed, 6 insertions, 6 deletions
diff --git a/src/jit/codegenlinear.cpp b/src/jit/codegenlinear.cpp
index 0d99ee0f88..121b4ffb65 100644
--- a/src/jit/codegenlinear.cpp
+++ b/src/jit/codegenlinear.cpp
@@ -710,12 +710,12 @@ void CodeGen::genSpillVar(GenTreePtr tree)
bool needsSpill = ((tree->gtFlags & GTF_VAR_DEF) == 0 && varDsc->lvIsInReg());
if (needsSpill)
{
- var_types lclTyp = varDsc->TypeGet();
- if (varDsc->lvNormalizeOnStore())
- {
- lclTyp = genActualType(lclTyp);
- }
- emitAttr size = emitTypeSize(lclTyp);
+ // In order for a lclVar to have been allocated to a register, it must not have been aliasable, and can
+ // therefore be store-normalized (rather than load-normalized). In fact, not performing store normalization
+ // can lead to problems on architectures where a lclVar may be allocated to a register that is not
+ // addressable at the granularity of the lclVar's defined type (e.g. x86).
+ var_types lclTyp = genActualType(varDsc->TypeGet());
+ emitAttr size = emitTypeSize(lclTyp);
bool restoreRegVar = false;
if (tree->gtOper == GT_REG_VAR)