From 87590ea09ebd900a226a96ddbf9025a2c6cccfb5 Mon Sep 17 00:00:00 2001 From: Egor Chesakov Date: Fri, 14 Aug 2020 18:19:08 -0700 Subject: [PATCH 1/4] Add regression test for https://github.com/dotnet/runtime/issues/40607 --- .../JitBlue/Runtime_40607/Runtime_40607.cs | 69 +++++++++++++++++++ .../Runtime_40607/Runtime_40607.csproj | 11 +++ 2 files changed, 80 insertions(+) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.csproj diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.cs b/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.cs new file mode 100644 index 00000000000000..5395a16b4a03bf --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.cs @@ -0,0 +1,69 @@ +using System; +using System.Runtime.CompilerServices; + +namespace Runtime_40607 +{ + class Program + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static bool WillBeInlined(out bool shouldBeFalse) + { + shouldBeFalse = false; + return true; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + [SkipLocalsInit] + static int DependsOnUnInitValue() + { + int retVal = 1; + bool shouldBeFalse; + + while (WillBeInlined(out shouldBeFalse)) + { + if (shouldBeFalse) + { + retVal = 0; + } + break; + } + + return retVal; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static unsafe int PoisonStackWith(uint fillValue) + { + int retVal = 1; + bool shouldBeFalse; + + *(uint*)&shouldBeFalse = fillValue; + + while (WillBeInlined(out shouldBeFalse)) + { + if (shouldBeFalse) + { + retVal = 0; + } + break; + } + + return retVal; + } + + static int Main(string[] args) + { + PoisonStackWith(0xdeadbeef); + + const int expected = 1; + int actual = DependsOnUnInitValue(); + + if (expected != actual) + { + return 0; + } + + return 100; + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.csproj new file mode 100644 index 00000000000000..2ab2ec62439f7f --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.csproj @@ -0,0 +1,11 @@ + + + Exe + + True + True + + + + + From b6e787b9eea68281b088879a23b7f295fb72da29 Mon Sep 17 00:00:00 2001 From: Egor Chesakov Date: Tue, 25 Aug 2020 21:37:06 -0700 Subject: [PATCH 2/4] Add Runtime_40607.tt --- .../Runtime_40607/Runtime_40607.csproj | 11 - .../JitBlue/Runtime_40607/Runtime_40607.il | 345 ++++++++++++++++++ .../Runtime_40607/Runtime_40607.ilproj | 10 + .../JitBlue/Runtime_40607/Runtime_40607.tt | 119 ++++++ 4 files changed, 474 insertions(+), 11 deletions(-) delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.csproj create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.il create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.ilproj create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.tt diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.csproj deleted file mode 100644 index 2ab2ec62439f7f..00000000000000 --- a/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - Exe - - True - True - - - - - diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.il b/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.il new file mode 100644 index 00000000000000..ed61d5fded2a68 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.il @@ -0,0 +1,345 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.assembly extern System.Console +{ +} +.assembly extern System.Runtime +{ +} +.assembly Runtime_40607 +{ +} +.module Runtime_40607.dll + +.class private auto ansi beforefieldinit Runtime_40607.Program extends [System.Runtime]System.Object +{ + .method private hidebysig static int32 DependsOnUnInitValue(bool valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (int32 V_0, bool V_1) + + IL_0000: ldc.i4.1 + IL_0001: stloc.0 + IL_0002: br.s IL_000b + + IL_0004: ldloc.1 + IL_0005: brfalse.s IL_0011 + + IL_0007: ldc.i4.0 + IL_0008: stloc.0 + IL_0009: br.s IL_0011 + + IL_000b: ldloca.s V_1 + IL_000d: ldarg.0 + IL_000e: stind.i1 + IL_000f: br.s IL_0004 + + IL_0011: ldloc.0 + IL_0012: ret + } + + .method private hidebysig static int32 DependsOnUnInitValue(int8 valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (int32 V_0, int8 V_1) + + IL_0000: ldc.i4.1 + IL_0001: stloc.0 + IL_0002: br.s IL_000b + + IL_0004: ldloc.1 + IL_0005: brfalse.s IL_0011 + + IL_0007: ldc.i4.0 + IL_0008: stloc.0 + IL_0009: br.s IL_0011 + + IL_000b: ldloca.s V_1 + IL_000d: ldarg.0 + IL_000e: stind.i1 + IL_000f: br.s IL_0004 + + IL_0011: ldloc.0 + IL_0012: ret + } + + .method private hidebysig static int32 DependsOnUnInitValue(uint8 valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (int32 V_0, uint8 V_1) + + IL_0000: ldc.i4.1 + IL_0001: stloc.0 + IL_0002: br.s IL_000b + + IL_0004: ldloc.1 + IL_0005: brfalse.s IL_0011 + + IL_0007: ldc.i4.0 + IL_0008: stloc.0 + IL_0009: br.s IL_0011 + + IL_000b: ldloca.s V_1 + IL_000d: ldarg.0 + IL_000e: stind.i1 + IL_000f: br.s IL_0004 + + IL_0011: ldloc.0 + IL_0012: ret + } + + .method private hidebysig static int32 DependsOnUnInitValue(int16 valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (int32 V_0, int16 V_1) + + IL_0000: ldc.i4.1 + IL_0001: stloc.0 + IL_0002: br.s IL_000b + + IL_0004: ldloc.1 + IL_0005: brfalse.s IL_0011 + + IL_0007: ldc.i4.0 + IL_0008: stloc.0 + IL_0009: br.s IL_0011 + + IL_000b: ldloca.s V_1 + IL_000d: ldarg.0 + IL_000e: stind.i2 + IL_000f: br.s IL_0004 + + IL_0011: ldloc.0 + IL_0012: ret + } + + .method private hidebysig static int32 DependsOnUnInitValue(uint16 valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (int32 V_0, uint16 V_1) + + IL_0000: ldc.i4.1 + IL_0001: stloc.0 + IL_0002: br.s IL_000b + + IL_0004: ldloc.1 + IL_0005: brfalse.s IL_0011 + + IL_0007: ldc.i4.0 + IL_0008: stloc.0 + IL_0009: br.s IL_0011 + + IL_000b: ldloca.s V_1 + IL_000d: ldarg.0 + IL_000e: stind.i2 + IL_000f: br.s IL_0004 + + IL_0011: ldloc.0 + IL_0012: ret + } + + .method private hidebysig static int32 DependsOnUnInitValue(int32 valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (int32 V_0, int32 V_1) + + IL_0000: ldc.i4.1 + IL_0001: stloc.0 + IL_0002: br.s IL_000b + + IL_0004: ldloc.1 + IL_0005: brfalse.s IL_0011 + + IL_0007: ldc.i4.0 + IL_0008: stloc.0 + IL_0009: br.s IL_0011 + + IL_000b: ldloca.s V_1 + IL_000d: ldarg.0 + IL_000e: stind.i4 + IL_000f: br.s IL_0004 + + IL_0011: ldloc.0 + IL_0012: ret + } + + .method private hidebysig static int32 DependsOnUnInitValue(uint32 valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (int32 V_0, uint32 V_1) + + IL_0000: ldc.i4.1 + IL_0001: stloc.0 + IL_0002: br.s IL_000b + + IL_0004: ldloc.1 + IL_0005: brfalse.s IL_0011 + + IL_0007: ldc.i4.0 + IL_0008: stloc.0 + IL_0009: br.s IL_0011 + + IL_000b: ldloca.s V_1 + IL_000d: ldarg.0 + IL_000e: stind.i4 + IL_000f: br.s IL_0004 + + IL_0011: ldloc.0 + IL_0012: ret + } + + + .method private hidebysig static int32 PoisonStackWith(int32 valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (int32 V_0, int32 V_1) + + IL_0000: ldc.i4.1 + IL_0001: stloc.0 + IL_0002: br.s IL_000b + + IL_0004: ldloc.1 + IL_0005: brfalse.s IL_0014 + + IL_0007: ldc.i4.0 + IL_0008: stloc.0 + IL_0009: br.s IL_0014 + + IL_000b: ldloca.s V_1 + IL_000d: conv.u + IL_000e: ldc.i4.0 + IL_000f: add + IL_0010: ldarg.0 + IL_0011: stind.i4 + IL_0012: br.s IL_0004 + + IL_0014: ldloc.0 + IL_0015: ret + } + + .method private hidebysig static int32 Main(string[] args) cil managed + { + .entrypoint + // Code size 75 (0x4b) + .maxstack 2 + .locals init (int32 V_0) + + ldc.i4.s 100 + stloc.0 + ldc.i4 0xdeadbeef + call int32 Runtime_40607.Program::PoisonStackWith(int32) + pop + + ldc.i4.0 + call int32 Runtime_40607.Program::DependsOnUnInitValue(bool) + ldc.i4.1 + beq.s IL_0000 + + ldstr "DependsOnUnInitValue(bool) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 + +IL_0000: + ldc.i4 0xdeadbeef + call int32 Runtime_40607.Program::PoisonStackWith(int32) + pop + + ldc.i4.0 + call int32 Runtime_40607.Program::DependsOnUnInitValue(int8) + ldc.i4.1 + beq.s IL_0001 + + ldstr "DependsOnUnInitValue(int8) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 + +IL_0001: + ldc.i4 0xdeadbeef + call int32 Runtime_40607.Program::PoisonStackWith(int32) + pop + + ldc.i4.0 + call int32 Runtime_40607.Program::DependsOnUnInitValue(uint8) + ldc.i4.1 + beq.s IL_0002 + + ldstr "DependsOnUnInitValue(uint8) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 + +IL_0002: + ldc.i4 0xdeadbeef + call int32 Runtime_40607.Program::PoisonStackWith(int32) + pop + + ldc.i4.0 + call int32 Runtime_40607.Program::DependsOnUnInitValue(int16) + ldc.i4.1 + beq.s IL_0003 + + ldstr "DependsOnUnInitValue(int16) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 + +IL_0003: + ldc.i4 0xdeadbeef + call int32 Runtime_40607.Program::PoisonStackWith(int32) + pop + + ldc.i4.0 + call int32 Runtime_40607.Program::DependsOnUnInitValue(uint16) + ldc.i4.1 + beq.s IL_0004 + + ldstr "DependsOnUnInitValue(uint16) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 + +IL_0004: + ldc.i4 0xdeadbeef + call int32 Runtime_40607.Program::PoisonStackWith(int32) + pop + + ldc.i4.0 + call int32 Runtime_40607.Program::DependsOnUnInitValue(int32) + ldc.i4.1 + beq.s IL_0005 + + ldstr "DependsOnUnInitValue(int32) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 + +IL_0005: + ldc.i4 0xdeadbeef + call int32 Runtime_40607.Program::PoisonStackWith(int32) + pop + + ldc.i4.0 + call int32 Runtime_40607.Program::DependsOnUnInitValue(uint32) + ldc.i4.1 + beq.s IL_0006 + + ldstr "DependsOnUnInitValue(uint32) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 + +IL_0006: + ldloc.0 + ret + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.ilproj b/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.ilproj new file mode 100644 index 00000000000000..7dab57fe6d2256 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.ilproj @@ -0,0 +1,10 @@ + + + Exe + None + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.tt b/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.tt new file mode 100644 index 00000000000000..5c521cc9f6ddbf --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.tt @@ -0,0 +1,119 @@ +<#@ template debug="false" hostspecific="true" language="C#" #> +<#@ output extension=".il" #> +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.assembly extern System.Console +{ +} +.assembly extern System.Runtime +{ +} +.assembly Runtime_40607 +{ +} +.module Runtime_40607.dll + +.class private auto ansi beforefieldinit Runtime_40607.Program extends [System.Runtime]System.Object +{ +<# + foreach ((string varType, int sizeInBytes) in new [] { ("bool", 1), ("int8", 1), ("uint8", 1), ("int16", 2), ("uint16", 2), ("int32", 4), ("uint32", 4) }) + { +#> + .method private hidebysig static int32 DependsOnUnInitValue(<#= varType #> valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (int32 V_0, <#= varType #> V_1) + + IL_0000: ldc.i4.1 + IL_0001: stloc.0 + IL_0002: br.s IL_000b + + IL_0004: ldloc.1 + IL_0005: brfalse.s IL_0011 + + IL_0007: ldc.i4.0 + IL_0008: stloc.0 + IL_0009: br.s IL_0011 + + IL_000b: ldloca.s V_1 + IL_000d: ldarg.0 + IL_000e: stind.i<#= sizeInBytes #> + IL_000f: br.s IL_0004 + + IL_0011: ldloc.0 + IL_0012: ret + } + +<# + } +#> + + .method private hidebysig static int32 PoisonStackWith(int32 valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (int32 V_0, int32 V_1) + + IL_0000: ldc.i4.1 + IL_0001: stloc.0 + IL_0002: br.s IL_000b + + IL_0004: ldloc.1 + IL_0005: brfalse.s IL_0014 + + IL_0007: ldc.i4.0 + IL_0008: stloc.0 + IL_0009: br.s IL_0014 + + IL_000b: ldloca.s V_1 + IL_000d: conv.u + IL_000e: ldc.i4.0 + IL_000f: add + IL_0010: ldarg.0 + IL_0011: stind.i4 + IL_0012: br.s IL_0004 + + IL_0014: ldloc.0 + IL_0015: ret + } + + .method private hidebysig static int32 Main(string[] args) cil managed + { + .entrypoint + // Code size 75 (0x4b) + .maxstack 2 + .locals init (int32 V_0) + + ldc.i4.s 100 + stloc.0 +<# + string[] varTypes = new string[] { "bool", "int8", "uint8", "int16", "uint16", "int32", "uint32" }; + + for (int i = 0; i < varTypes.Length; i++) + { + string varType = varTypes[i]; + string lblName = string.Format("IL_{0:x4}", i); +#> + ldc.i4 0xdeadbeef + call int32 Runtime_40607.Program::PoisonStackWith(int32) + pop + + ldc.i4.0 + call int32 Runtime_40607.Program::DependsOnUnInitValue(<#= varType #>) + ldc.i4.1 + beq.s <#= lblName #> + + ldstr "DependsOnUnInitValue(<#= varType #>) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 + +<#= lblName #>: +<# + } +#> + ldloc.0 + ret + } +} From 5eb63fa6bcb3a3a4da96a546bff3a73fa76e3a94 Mon Sep 17 00:00:00 2001 From: Egor Chesakov Date: Fri, 28 Aug 2020 15:49:42 -0700 Subject: [PATCH 3/4] Add more extensive tests for loads in Runtime_40607.tt Runtime_40607.il --- .../JitBlue/Runtime_40607/Runtime_40607.il | 404 +++++++++++++++++- .../JitBlue/Runtime_40607/Runtime_40607.tt | 105 ++++- 2 files changed, 477 insertions(+), 32 deletions(-) diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.il b/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.il index ed61d5fded2a68..ca0106255f1f4b 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.il +++ b/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.il @@ -189,6 +189,158 @@ IL_0012: ret } + .method private hidebysig static int32 SignExtendsWrittenValue(int8 valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (int8 V_0) + + IL_0000: br.s IL_0007 + + IL_0002: ldloca.s V_0 + IL_0004: ldind.i1 + IL_0005: br.s IL_000d + + IL_0007: ldloca.s V_0 + IL_0009: ldarg.0 + IL_000a: stind.i1 + IL_000b: br.s IL_0002 + + IL_000d: ret + } + + .method private hidebysig static int32 ZeroExtendsWrittenValue(int8 valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (int8 V_0) + + IL_0000: br.s IL_0007 + + IL_0002: ldloca.s V_0 + IL_0004: ldind.u1 + IL_0005: br.s IL_000d + + IL_0007: ldloca.s V_0 + IL_0009: ldarg.0 + IL_000a: stind.i1 + IL_000b: br.s IL_0002 + + IL_000d: ret + } + + .method private hidebysig static int32 SignExtendsWrittenValue(uint8 valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (uint8 V_0) + + IL_0000: br.s IL_0007 + + IL_0002: ldloca.s V_0 + IL_0004: ldind.i1 + IL_0005: br.s IL_000d + + IL_0007: ldloca.s V_0 + IL_0009: ldarg.0 + IL_000a: stind.i1 + IL_000b: br.s IL_0002 + + IL_000d: ret + } + + .method private hidebysig static int32 ZeroExtendsWrittenValue(uint8 valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (uint8 V_0) + + IL_0000: br.s IL_0007 + + IL_0002: ldloca.s V_0 + IL_0004: ldind.u1 + IL_0005: br.s IL_000d + + IL_0007: ldloca.s V_0 + IL_0009: ldarg.0 + IL_000a: stind.i1 + IL_000b: br.s IL_0002 + + IL_000d: ret + } + + .method private hidebysig static int32 SignExtendsWrittenValue(int16 valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (int16 V_0) + + IL_0000: br.s IL_0007 + + IL_0002: ldloca.s V_0 + IL_0004: ldind.i2 + IL_0005: br.s IL_000d + + IL_0007: ldloca.s V_0 + IL_0009: ldarg.0 + IL_000a: stind.i2 + IL_000b: br.s IL_0002 + + IL_000d: ret + } + + .method private hidebysig static int32 ZeroExtendsWrittenValue(int16 valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (int16 V_0) + + IL_0000: br.s IL_0007 + + IL_0002: ldloca.s V_0 + IL_0004: ldind.u2 + IL_0005: br.s IL_000d + + IL_0007: ldloca.s V_0 + IL_0009: ldarg.0 + IL_000a: stind.i2 + IL_000b: br.s IL_0002 + + IL_000d: ret + } + + .method private hidebysig static int32 SignExtendsWrittenValue(uint16 valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (uint16 V_0) + + IL_0000: br.s IL_0007 + + IL_0002: ldloca.s V_0 + IL_0004: ldind.i2 + IL_0005: br.s IL_000d + + IL_0007: ldloca.s V_0 + IL_0009: ldarg.0 + IL_000a: stind.i2 + IL_000b: br.s IL_0002 + + IL_000d: ret + } + + .method private hidebysig static int32 ZeroExtendsWrittenValue(uint16 valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (uint16 V_0) + + IL_0000: br.s IL_0007 + + IL_0002: ldloca.s V_0 + IL_0004: ldind.u2 + IL_0005: br.s IL_000d + + IL_0007: ldloca.s V_0 + IL_0009: ldarg.0 + IL_000a: stind.i2 + IL_000b: br.s IL_0002 + + IL_000d: ret + } + .method private hidebysig static int32 PoisonStackWith(int32 valueToWrite) cil managed noinlining { @@ -221,125 +373,333 @@ .method private hidebysig static int32 Main(string[] args) cil managed { .entrypoint - // Code size 75 (0x4b) .maxstack 2 .locals init (int32 V_0) ldc.i4.s 100 stloc.0 +// BEGIN_DependsOnUnInitValue_bool ldc.i4 0xdeadbeef call int32 Runtime_40607.Program::PoisonStackWith(int32) pop ldc.i4.0 call int32 Runtime_40607.Program::DependsOnUnInitValue(bool) - ldc.i4.1 - beq.s IL_0000 + brtrue.s END_DependsOnUnInitValue_bool ldstr "DependsOnUnInitValue(bool) has failed" call void [System.Console]System.Console::WriteLine(string) ldc.i4.0 stloc.0 +END_DependsOnUnInitValue_bool: -IL_0000: +// BEGIN_DependsOnUnInitValue_int8 ldc.i4 0xdeadbeef call int32 Runtime_40607.Program::PoisonStackWith(int32) pop ldc.i4.0 call int32 Runtime_40607.Program::DependsOnUnInitValue(int8) - ldc.i4.1 - beq.s IL_0001 + brtrue.s END_DependsOnUnInitValue_int8 ldstr "DependsOnUnInitValue(int8) has failed" call void [System.Console]System.Console::WriteLine(string) ldc.i4.0 stloc.0 +END_DependsOnUnInitValue_int8: -IL_0001: +// BEGIN_DependsOnUnInitValue_uint8 ldc.i4 0xdeadbeef call int32 Runtime_40607.Program::PoisonStackWith(int32) pop ldc.i4.0 call int32 Runtime_40607.Program::DependsOnUnInitValue(uint8) - ldc.i4.1 - beq.s IL_0002 + brtrue.s END_DependsOnUnInitValue_uint8 ldstr "DependsOnUnInitValue(uint8) has failed" call void [System.Console]System.Console::WriteLine(string) ldc.i4.0 stloc.0 +END_DependsOnUnInitValue_uint8: -IL_0002: +// BEGIN_DependsOnUnInitValue_int16 ldc.i4 0xdeadbeef call int32 Runtime_40607.Program::PoisonStackWith(int32) pop ldc.i4.0 call int32 Runtime_40607.Program::DependsOnUnInitValue(int16) - ldc.i4.1 - beq.s IL_0003 + brtrue.s END_DependsOnUnInitValue_int16 ldstr "DependsOnUnInitValue(int16) has failed" call void [System.Console]System.Console::WriteLine(string) ldc.i4.0 stloc.0 +END_DependsOnUnInitValue_int16: -IL_0003: +// BEGIN_DependsOnUnInitValue_uint16 ldc.i4 0xdeadbeef call int32 Runtime_40607.Program::PoisonStackWith(int32) pop ldc.i4.0 call int32 Runtime_40607.Program::DependsOnUnInitValue(uint16) - ldc.i4.1 - beq.s IL_0004 + brtrue.s END_DependsOnUnInitValue_uint16 ldstr "DependsOnUnInitValue(uint16) has failed" call void [System.Console]System.Console::WriteLine(string) ldc.i4.0 stloc.0 +END_DependsOnUnInitValue_uint16: -IL_0004: +// BEGIN_DependsOnUnInitValue_int32 ldc.i4 0xdeadbeef call int32 Runtime_40607.Program::PoisonStackWith(int32) pop ldc.i4.0 call int32 Runtime_40607.Program::DependsOnUnInitValue(int32) - ldc.i4.1 - beq.s IL_0005 + brtrue.s END_DependsOnUnInitValue_int32 ldstr "DependsOnUnInitValue(int32) has failed" call void [System.Console]System.Console::WriteLine(string) ldc.i4.0 stloc.0 +END_DependsOnUnInitValue_int32: -IL_0005: +// BEGIN_DependsOnUnInitValue_uint32 ldc.i4 0xdeadbeef call int32 Runtime_40607.Program::PoisonStackWith(int32) pop ldc.i4.0 call int32 Runtime_40607.Program::DependsOnUnInitValue(uint32) - ldc.i4.1 - beq.s IL_0006 + brtrue.s END_DependsOnUnInitValue_uint32 ldstr "DependsOnUnInitValue(uint32) has failed" call void [System.Console]System.Console::WriteLine(string) ldc.i4.0 stloc.0 +END_DependsOnUnInitValue_uint32: + +// BEGIN_SignExtendsWrittenValue_int8_0x7f: + ldc.i4 0x7f + call int32 Runtime_40607.Program::SignExtendsWrittenValue(int8) + ldc.i4 0x7f + beq.s END_SignExtendsWrittenValue_int8_0x7f + + ldstr "SignExtendsWrittenValue(int8) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_SignExtendsWrittenValue_int8_0x7f: + +// BEGIN_ZeroExtendsWrittenValue_int8_0x7f: + ldc.i4 0x7f + call int32 Runtime_40607.Program::ZeroExtendsWrittenValue(int8) + ldc.i4 0x7f + beq.s END_ZeroExtendsWrittenValue_int8_0x7f + + ldstr "ZeroExtendsWrittenValue(int8) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_ZeroExtendsWrittenValue_int8_0x7f: + +// BEGIN_SignExtendsWrittenValue_int8_0x80: + ldc.i4 0x80 + call int32 Runtime_40607.Program::SignExtendsWrittenValue(int8) + ldc.i4 0xffffff80 + beq.s END_SignExtendsWrittenValue_int8_0x80 + + ldstr "SignExtendsWrittenValue(int8) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_SignExtendsWrittenValue_int8_0x80: + +// BEGIN_ZeroExtendsWrittenValue_int8_0x80: + ldc.i4 0x80 + call int32 Runtime_40607.Program::ZeroExtendsWrittenValue(int8) + ldc.i4 0x80 + beq.s END_ZeroExtendsWrittenValue_int8_0x80 + + ldstr "ZeroExtendsWrittenValue(int8) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_ZeroExtendsWrittenValue_int8_0x80: + +// BEGIN_SignExtendsWrittenValue_uint8_0x7f: + ldc.i4 0x7f + call int32 Runtime_40607.Program::SignExtendsWrittenValue(uint8) + ldc.i4 0x7f + beq.s END_SignExtendsWrittenValue_uint8_0x7f + + ldstr "SignExtendsWrittenValue(uint8) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_SignExtendsWrittenValue_uint8_0x7f: + +// BEGIN_ZeroExtendsWrittenValue_uint8_0x7f: + ldc.i4 0x7f + call int32 Runtime_40607.Program::ZeroExtendsWrittenValue(uint8) + ldc.i4 0x7f + beq.s END_ZeroExtendsWrittenValue_uint8_0x7f + + ldstr "ZeroExtendsWrittenValue(uint8) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_ZeroExtendsWrittenValue_uint8_0x7f: + +// BEGIN_SignExtendsWrittenValue_uint8_0x80: + ldc.i4 0x80 + call int32 Runtime_40607.Program::SignExtendsWrittenValue(uint8) + ldc.i4 0xffffff80 + beq.s END_SignExtendsWrittenValue_uint8_0x80 + + ldstr "SignExtendsWrittenValue(uint8) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_SignExtendsWrittenValue_uint8_0x80: + +// BEGIN_ZeroExtendsWrittenValue_uint8_0x80: + ldc.i4 0x80 + call int32 Runtime_40607.Program::ZeroExtendsWrittenValue(uint8) + ldc.i4 0x80 + beq.s END_ZeroExtendsWrittenValue_uint8_0x80 + + ldstr "ZeroExtendsWrittenValue(uint8) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_ZeroExtendsWrittenValue_uint8_0x80: + +// BEGIN_SignExtendsWrittenValue_int16_0x7fff: + ldc.i4 0x7fff + call int32 Runtime_40607.Program::SignExtendsWrittenValue(int16) + ldc.i4 0x7fff + beq.s END_SignExtendsWrittenValue_int16_0x7fff + + ldstr "SignExtendsWrittenValue(int16) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_SignExtendsWrittenValue_int16_0x7fff: + +// BEGIN_ZeroExtendsWrittenValue_int16_0x7fff: + ldc.i4 0x7fff + call int32 Runtime_40607.Program::ZeroExtendsWrittenValue(int16) + ldc.i4 0x7fff + beq.s END_ZeroExtendsWrittenValue_int16_0x7fff + + ldstr "ZeroExtendsWrittenValue(int16) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_ZeroExtendsWrittenValue_int16_0x7fff: + +// BEGIN_SignExtendsWrittenValue_int16_0x8000: + ldc.i4 0x8000 + call int32 Runtime_40607.Program::SignExtendsWrittenValue(int16) + ldc.i4 0xffff8000 + beq.s END_SignExtendsWrittenValue_int16_0x8000 + + ldstr "SignExtendsWrittenValue(int16) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_SignExtendsWrittenValue_int16_0x8000: + +// BEGIN_ZeroExtendsWrittenValue_int16_0x8000: + ldc.i4 0x8000 + call int32 Runtime_40607.Program::ZeroExtendsWrittenValue(int16) + ldc.i4 0x8000 + beq.s END_ZeroExtendsWrittenValue_int16_0x8000 + + ldstr "ZeroExtendsWrittenValue(int16) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_ZeroExtendsWrittenValue_int16_0x8000: + +// BEGIN_SignExtendsWrittenValue_uint16_0x7fff: + ldc.i4 0x7fff + call int32 Runtime_40607.Program::SignExtendsWrittenValue(uint16) + ldc.i4 0x7fff + beq.s END_SignExtendsWrittenValue_uint16_0x7fff + + ldstr "SignExtendsWrittenValue(uint16) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_SignExtendsWrittenValue_uint16_0x7fff: + +// BEGIN_ZeroExtendsWrittenValue_uint16_0x7fff: + ldc.i4 0x7fff + call int32 Runtime_40607.Program::ZeroExtendsWrittenValue(uint16) + ldc.i4 0x7fff + beq.s END_ZeroExtendsWrittenValue_uint16_0x7fff + + ldstr "ZeroExtendsWrittenValue(uint16) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_ZeroExtendsWrittenValue_uint16_0x7fff: + +// BEGIN_SignExtendsWrittenValue_uint16_0x8000: + ldc.i4 0x8000 + call int32 Runtime_40607.Program::SignExtendsWrittenValue(uint16) + ldc.i4 0xffff8000 + beq.s END_SignExtendsWrittenValue_uint16_0x8000 + + ldstr "SignExtendsWrittenValue(uint16) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_SignExtendsWrittenValue_uint16_0x8000: + +// BEGIN_ZeroExtendsWrittenValue_uint16_0x8000: + ldc.i4 0x8000 + call int32 Runtime_40607.Program::ZeroExtendsWrittenValue(uint16) + ldc.i4 0x8000 + beq.s END_ZeroExtendsWrittenValue_uint16_0x8000 + + ldstr "ZeroExtendsWrittenValue(uint16) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_ZeroExtendsWrittenValue_uint16_0x8000: -IL_0006: ldloc.0 ret } } + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.tt b/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.tt index 5c521cc9f6ddbf..9d3223581fbb9c 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.tt +++ b/src/tests/JIT/Regression/JitBlue/Runtime_40607/Runtime_40607.tt @@ -17,7 +17,7 @@ .class private auto ansi beforefieldinit Runtime_40607.Program extends [System.Runtime]System.Object { <# - foreach ((string varType, int sizeInBytes) in new [] { ("bool", 1), ("int8", 1), ("uint8", 1), ("int16", 2), ("uint16", 2), ("int32", 4), ("uint32", 4) }) + foreach ((string varType, int sizeInBytes) in new [] { ("bool", sizeof(bool)), ("int8", sizeof(sbyte)), ("uint8", sizeof(byte)), ("int16", sizeof(short)), ("uint16", sizeof(ushort)), ("int32", sizeof(int)), ("uint32", sizeof(uint)) }) { #> .method private hidebysig static int32 DependsOnUnInitValue(<#= varType #> valueToWrite) cil managed noinlining @@ -45,6 +45,50 @@ IL_0012: ret } +<# + } + + foreach ((string varType, int sizeInBytes) in new [] { ("int8", sizeof(sbyte)), ("uint8", sizeof(byte)), ("int16", sizeof(short)), ("uint16", sizeof(ushort)) }) + { +#> + .method private hidebysig static int32 SignExtendsWrittenValue(<#= varType #> valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (<#= varType #> V_0) + + IL_0000: br.s IL_0007 + + IL_0002: ldloca.s V_0 + IL_0004: ldind.i<#= sizeInBytes #> + IL_0005: br.s IL_000d + + IL_0007: ldloca.s V_0 + IL_0009: ldarg.0 + IL_000a: stind.i<#= sizeInBytes #> + IL_000b: br.s IL_0002 + + IL_000d: ret + } + + .method private hidebysig static int32 ZeroExtendsWrittenValue(<#= varType #> valueToWrite) cil managed noinlining + { + .maxstack 8 + .locals (<#= varType #> V_0) + + IL_0000: br.s IL_0007 + + IL_0002: ldloca.s V_0 + IL_0004: ldind.u<#= sizeInBytes #> + IL_0005: br.s IL_000d + + IL_0007: ldloca.s V_0 + IL_0009: ldarg.0 + IL_000a: stind.i<#= sizeInBytes #> + IL_000b: br.s IL_0002 + + IL_000d: ret + } + <# } #> @@ -80,36 +124,63 @@ .method private hidebysig static int32 Main(string[] args) cil managed { .entrypoint - // Code size 75 (0x4b) .maxstack 2 .locals init (int32 V_0) ldc.i4.s 100 stloc.0 <# - string[] varTypes = new string[] { "bool", "int8", "uint8", "int16", "uint16", "int32", "uint32" }; - - for (int i = 0; i < varTypes.Length; i++) + foreach (string varType in new [] { "bool", "int8", "uint8", "int16", "uint16", "int32", "uint32" }) { - string varType = varTypes[i]; - string lblName = string.Format("IL_{0:x4}", i); + string testName = $"DependsOnUnInitValue_{varType}"; #> +// BEGIN_<#= testName #> ldc.i4 0xdeadbeef call int32 Runtime_40607.Program::PoisonStackWith(int32) pop ldc.i4.0 call int32 Runtime_40607.Program::DependsOnUnInitValue(<#= varType #>) - ldc.i4.1 - beq.s <#= lblName #> + brtrue.s END_<#= testName #> ldstr "DependsOnUnInitValue(<#= varType #>) has failed" call void [System.Console]System.Console::WriteLine(string) ldc.i4.0 stloc.0 +END_<#= testName #>: + +<# + } + + foreach ((string varType, int sizeInBytes, int valueToWrite) in new [] { + ("int8", sizeof(sbyte), 0x7f), + ("int8", sizeof(sbyte), 0x80), + ("uint8", sizeof(byte), 0x7f), + ("uint8", sizeof(byte), 0x80), + ("int16", sizeof(short), 0x7fff), + ("int16", sizeof(short), 0x8000), + ("uint16", sizeof(ushort), 0x7fff), + ("uint16", sizeof(ushort), 0x8000) }) + foreach ((string testName, int expectedResult) in new[] { + ("SignExtendsWrittenValue", SignExtend(valueToWrite, sizeInBytes)), + ("ZeroExtendsWrittenValue", valueToWrite) }) + { + string lblName = $"{testName}_{varType}_0x{valueToWrite:x}"; +#> +// BEGIN_<#= lblName #>: + ldc.i4 0x<#= valueToWrite.ToString("x") #> + call int32 Runtime_40607.Program::<#= testName #>(<#= varType #>) + ldc.i4 0x<#= expectedResult.ToString("x") #> + beq.s END_<#= lblName #> + + ldstr "<#= testName #>(<#= varType #>) has failed" + call void [System.Console]System.Console::WriteLine(string) + + ldc.i4.0 + stloc.0 +END_<#= lblName #>: -<#= lblName #>: <# } #> @@ -117,3 +188,17 @@ ret } } + +<#+ + int SignExtend(int value, int sizeInBytes) + { + if ((value & (1 << (8 * sizeInBytes - 1))) != 0) + { + for (int i = 8 * sizeInBytes; i < 8 * sizeof(int); i++) + { + value |= (1 << i); + } + } + return value; + } +#> From e1a7e38894f89c332cce0318e7c8c831bf9469aa Mon Sep 17 00:00:00 2001 From: Egor Chesakov Date: Wed, 26 Aug 2020 12:20:58 -0700 Subject: [PATCH 4/4] Fold *(typ*)&lclVar tree when: 1) it is *definitely load* and types of both indirection and local variable have the same signedness (e.g. bool and byte) 2) otherwise, fold the tree and mark the local node with GTF_VAR_FOLDED_IND and call fgDoNormalizeOnStore() on such nodes' parents in post-order morph. --- src/coreclr/src/jit/compiler.h | 6 ++-- src/coreclr/src/jit/flowgraph.cpp | 4 +++ src/coreclr/src/jit/gentree.h | 3 ++ src/coreclr/src/jit/morph.cpp | 54 ++++++++++++++++--------------- 4 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/coreclr/src/jit/compiler.h b/src/coreclr/src/jit/compiler.h index e94dc8ad4c9a2f..c3a01feb9d7cec 100644 --- a/src/coreclr/src/jit/compiler.h +++ b/src/coreclr/src/jit/compiler.h @@ -476,8 +476,6 @@ class LclVarDsc unsigned char lvContainsHoles : 1; // True when we have a promoted struct that contains holes unsigned char lvCustomLayout : 1; // True when this struct has "CustomLayout" - unsigned char lvForceLoadNormalize : 1; // True when this local had a cast on the LHS of an assignment - unsigned char lvIsMultiRegArg : 1; // true if this is a multireg LclVar struct used in an argument context unsigned char lvIsMultiRegRet : 1; // true if this is a multireg LclVar struct assigned from a multireg call @@ -886,14 +884,14 @@ class LclVarDsc { return varTypeIsSmall(TypeGet()) && // lvIsStructField is treated the same as the aliased local, see fgDoNormalizeOnStore. - (lvIsParam || lvAddrExposed || lvIsStructField || lvForceLoadNormalize); + (lvIsParam || lvAddrExposed || lvIsStructField); } bool lvNormalizeOnStore() const { return varTypeIsSmall(TypeGet()) && // lvIsStructField is treated the same as the aliased local, see fgDoNormalizeOnStore. - !(lvIsParam || lvAddrExposed || lvIsStructField || lvForceLoadNormalize); + !(lvIsParam || lvAddrExposed || lvIsStructField); } void incRefCnts(BasicBlock::weight_t weight, diff --git a/src/coreclr/src/jit/flowgraph.cpp b/src/coreclr/src/jit/flowgraph.cpp index 48f3273e38eaaa..03e1936224e8b3 100644 --- a/src/coreclr/src/jit/flowgraph.cpp +++ b/src/coreclr/src/jit/flowgraph.cpp @@ -21608,6 +21608,10 @@ void Compiler::fgDebugCheckFlags(GenTree* tree) chkFlags |= GTF_GLOB_REF | GTF_ASG; break; + case GT_LCL_VAR: + assert((tree->gtFlags & GTF_VAR_FOLDED_IND) == 0); + break; + default: break; } diff --git a/src/coreclr/src/jit/gentree.h b/src/coreclr/src/jit/gentree.h index 5c3a94395db6fc..c7d5f2cf3a3a08 100644 --- a/src/coreclr/src/jit/gentree.h +++ b/src/coreclr/src/jit/gentree.h @@ -815,6 +815,9 @@ struct GenTree #define GTF_VAR_ITERATOR 0x00800000 // GT_LCL_VAR -- this is a iterator reference in the loop condition #define GTF_VAR_CLONED 0x00400000 // GT_LCL_VAR -- this node has been cloned or is a clone #define GTF_VAR_CONTEXT 0x00200000 // GT_LCL_VAR -- this node is part of a runtime lookup +#define GTF_VAR_FOLDED_IND 0x00100000 // GT_LCL_VAR -- this node was folded from *(typ*)&lclVar expression tree in fgMorphSmpOp() +// where 'typ' is a small type and 'lclVar' corresponds to a normalized-on-store local variable. +// This flag identifies such nodes in order to make sure that fgDoNormalizeOnStore() is called on their parents in post-order morph. // Relevant for inlining optimizations (see fgInlinePrependStatements) diff --git a/src/coreclr/src/jit/morph.cpp b/src/coreclr/src/jit/morph.cpp index dc5bef62f9c44e..b3547979766860 100644 --- a/src/coreclr/src/jit/morph.cpp +++ b/src/coreclr/src/jit/morph.cpp @@ -12643,6 +12643,13 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) { case GT_ASG: + if (op1->OperIs(GT_LCL_VAR) && ((op1->gtFlags & GTF_VAR_FOLDED_IND) != 0)) + { + op1->gtFlags &= ~GTF_VAR_FOLDED_IND; + tree = fgDoNormalizeOnStore(tree); + op2 = tree->gtGetOp2(); + } + lclVarTree = fgIsIndirOfAddrOfLocal(op1); if (lclVarTree != nullptr) { @@ -13601,17 +13608,16 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) break; case GT_IND: - + { // Can not remove a GT_IND if it is currently a CSE candidate. if (gtIsActiveCSE_Candidate(tree)) { break; } - bool foldAndReturnTemp; - foldAndReturnTemp = false; - temp = nullptr; - ival1 = 0; + bool foldAndReturnTemp = false; + temp = nullptr; + ival1 = 0; // Don't remove a volatile GT_IND, even if the address points to a local variable. if ((tree->gtFlags & GTF_IND_VOLATILE) == 0) @@ -13641,11 +13647,6 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) unsigned lclNum = temp->AsLclVarCommon()->GetLclNum(); LclVarDsc* varDsc = &lvaTable[lclNum]; - // Note that fgMorph uses GTF_DONT_CSE to mark the left side of an assignment - // Thus stores have this flag and load do not have this flag - // - bool isLoad = (tree->gtFlags & GTF_DONT_CSE) == 0; - // We will try to optimize when we have a promoted struct promoted with a zero lvFldOffset if (varDsc->lvPromoted && (varDsc->lvFldOffset == 0)) { @@ -13675,25 +13676,25 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) // correctly normalized. // // The below transformation cannot be applied if the local var needs to be normalized on load. - else if (varTypeIsSmall(typ) && (genTypeSize(lvaTable[lclNum].lvType) == genTypeSize(typ)) && + else if (varTypeIsSmall(typ) && (genTypeSize(varDsc) == genTypeSize(typ)) && !lvaTable[lclNum].lvNormalizeOnLoad()) { - // For any stores of small types, we will force loads to be normalized - // this is necessary as we need to zero/sign extend any load - // after this kind of store. - // - if (!isLoad) - { - varDsc->lvForceLoadNormalize = true; - } - // otherwise we have a load operation - // - // And for loads signed/unsigned differences do matter. - // - else if (varTypeIsUnsigned(lvaTable[lclNum].lvType) == varTypeIsUnsigned(typ)) + const bool definitelyLoad = (tree->gtFlags & GTF_DONT_CSE) == 0; + const bool possiblyStore = !definitelyLoad; + + if (possiblyStore || (varTypeIsUnsigned(varDsc) == varTypeIsUnsigned(typ))) { - tree->gtType = typ = temp->TypeGet(); - foldAndReturnTemp = true; + typ = temp->TypeGet(); + tree->gtType = typ; + foldAndReturnTemp = true; + + if (possiblyStore) + { + // This node can be on the left-hand-side of an assignment node. + // Mark this node with GTF_VAR_FOLDED_IND to make sure that fgDoNormalizeOnStore() + // is called on its parent in post-order morph. + temp->gtFlags |= GTF_VAR_FOLDED_IND; + } } } // For matching types we can fold @@ -13970,6 +13971,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) } break; + } case GT_ADDR: