From: Andy Ayers Date: Thu, 28 Feb 2019 20:15:19 +0000 (-0800) Subject: JIT: allow slightly more general promotion of structs with struct fields (#22867) X-Git-Tag: accepted/tizen/unified/20190813.215958~61^2~106 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8f5bf71321ca29dcd9c5847185e15c0b7fb9a8e7;p=platform%2Fupstream%2Fcoreclr.git JIT: allow slightly more general promotion of structs with struct fields (#22867) For a while now the jit has been able to promote an outer struct A with an inner struct field B that itself has a single non-struct field C, provided that C occupies all of B and that C and B are pointer-sized. For example, this comes up when supporting promotion of `Span`, as a span contains a `ByReference` field that itself contains a pointer-sized field. This change relaxes the constraints slightly, allowing B and C to be less than pointer sized, provided C still occupies all of B, and B is suitably aligned within A. Doing so allows promotion of the new `Range` type, which contains two `Index` fields that each wrap an `int`. This improves performance for uses of `Range` for simple examples like those in #22079. --- diff --git a/src/jit/lclvars.cpp b/src/jit/lclvars.cpp index 5e82ab7..7454bf7 100644 --- a/src/jit/lclvars.cpp +++ b/src/jit/lclvars.cpp @@ -2020,13 +2020,26 @@ bool Compiler::StructPromotionHelper::TryPromoteStructField(lvaStructFieldInfo& // // TODO-CQ: Right now we only promote an actual SIMD typed field, which would cause // a nested SIMD type to fail promotion. - if (fieldSize == 0 || fieldSize != TARGET_POINTER_SIZE || varTypeIsFloating(fieldVarType)) + if (fieldSize == 0 || fieldSize > TARGET_POINTER_SIZE || varTypeIsFloating(fieldVarType)) { JITDUMP("Promotion blocked: struct contains struct field with one field," " but that field has invalid size or type"); return false; } + if (fieldSize != TARGET_POINTER_SIZE) + { + unsigned outerFieldOffset = compHandle->getFieldOffset(fieldInfo.fldHnd); + + if ((outerFieldOffset % fieldSize) != 0) + { + JITDUMP("Promotion blocked: struct contains struct field with one field," + " but the outer struct offset %u is not a multiple of the inner field size %u", + outerFieldOffset, fieldSize); + return false; + } + } + // Insist this wrapped field occupy all of its parent storage. unsigned innerStructSize = compHandle->getClassSize(fieldInfo.fldTypeHnd);