summaryrefslogtreecommitdiff
path: root/tests/src/JIT/Regression/JitBlue/DevDiv_278523/DevDiv_278523.il
diff options
context:
space:
mode:
Diffstat (limited to 'tests/src/JIT/Regression/JitBlue/DevDiv_278523/DevDiv_278523.il')
-rw-r--r--tests/src/JIT/Regression/JitBlue/DevDiv_278523/DevDiv_278523.il113
1 files changed, 113 insertions, 0 deletions
diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278523/DevDiv_278523.il b/tests/src/JIT/Regression/JitBlue/DevDiv_278523/DevDiv_278523.il
new file mode 100644
index 0000000000..9c9ba4946c
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278523/DevDiv_278523.il
@@ -0,0 +1,113 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern mscorlib {}
+.assembly a {}
+.module a.exe
+
+// This test originally triggered an assert when computing the value number for a block assignment. In particular, the
+// VN framework expected any block assignments to a tracked lclVar to have a destination address of the form
+// `(addr (lclVar))` or `(addr (lclFld))`. The check that it was using to determine whether or not a block assignment
+// targets a lclVar also admitted addresses formed by some combination of adds of constants to these patterns (e.g.
+// `(add (const 4) (add (addr lclVar) (const 4)))`. The bits of IL that trigger the assert are called out in the method
+// bodies below. They differ for 32- and 64-bit targets because on 64-bit targets, the importer will insert an
+// int->long conversion when adding a constant int to any long. Due to the cast, the resulting IR is not considered to
+// be an add of a constant and a lclVar address. In order to repro the bug on a 64-bit target, the input IL must
+// directly produce a long constant.
+
+.class private sequential ansi sealed beforefieldinit S extends [mscorlib]System.ValueType
+{
+ .field public uint8 m_fld
+ .field public uint8 m_fld1
+ .field public uint8 m_fld2
+ .field public uint8 m_fld3
+ .field public uint8 m_fld4
+ .field public uint8 m_fld5
+ .field public uint8 m_fld6
+}
+
+.class private sequential ansi sealed beforefieldinit T extends [mscorlib]System.ValueType
+{
+ .field public int32 m_int
+ .field public valuetype S m_fld
+}
+
+.class private abstract auto ansi sealed beforefieldinit C extends [mscorlib]System.Object
+{
+ .method private static int32 Test32Bit(int32 i) noinlining
+ {
+ .locals init (valuetype S V_0, valuetype T V_1)
+
+ ldloca.s V_0
+ ldarg.0
+ conv.u1
+ stfld uint8 S::m_fld6
+
+ // This sequence of IL repros the issue.
+ ldloca.s V_1
+ ldc.i4.4
+ add
+ ldloc.0
+ stobj S
+
+ ldloca.s V_1
+ ldfld valuetype S T::m_fld
+ ldfld uint8 S::m_fld6
+ conv.i4
+ ret
+ }
+
+ .method private static int32 Test64Bit(int32 i) noinlining
+ {
+ .locals init (valuetype S V_0, valuetype T V_1)
+
+ ldloca.s V_0
+ ldarg.0
+ conv.u1
+ stfld uint8 S::m_fld6
+
+ // This sequence of IL repros the issue. Note that the `ldc.i8` is necessary (rather than an `ldc.i4` that is
+ // implicitly converted to a long byt the `add`).
+ ldloca.s V_1
+ ldc.i8 4
+ add
+ ldloc.0
+ stobj S
+
+ ldloca.s V_1
+ ldfld valuetype S T::m_fld
+ ldfld uint8 S::m_fld6
+ conv.i4
+ ret
+ }
+
+ .method private static int32 Main()
+ {
+ .entrypoint
+ .locals init (int32 V_0)
+
+ ldc.i4 100
+ dup
+
+ sizeof [mscorlib]System.IntPtr
+ ldc.i4 8
+ beq.s _64bit
+
+ call int32 C::Test32Bit(int32)
+ bne.un.s fail
+ br.s success
+
+_64bit:
+ call int32 C::Test64Bit(int32)
+ bne.un.s fail
+
+success:
+ ldc.i4 100
+ ret
+
+fail:
+ ldc.i4 101
+ ret
+ }
+}