From 3a93ebd6fee0a42c4dece98f0baca9b7008cbfc6 Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Fri, 31 Jan 2020 16:40:47 -0500 Subject: [PATCH] Abort cmov optimization, when one of the out blocks is try block (#18626) --- mono/mini/branch-opts.c | 16 +++++++----- mono/mini/iltests.il | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/mono/mini/branch-opts.c b/mono/mini/branch-opts.c index 15c2a76d674..67eabd7c082 100644 --- a/mono/mini/branch-opts.c +++ b/mono/mini/branch-opts.c @@ -304,6 +304,16 @@ mono_if_conversion (MonoCompile *cfg) MonoBasicBlock *bb1, *bb2; restart: + if (!(bb->out_count == 2 && !bb->extended)) + continue; + + bb1 = bb->out_bb [0]; + bb2 = bb->out_bb [1]; + + /* If either bb1 or bb2 is a try block, abort the optimization attempt. */ + if (bb1->try_start || bb2->try_start) + continue; + /* Look for the IR code generated from cond ? a : b * which is: * BB: @@ -315,12 +325,6 @@ mono_if_conversion (MonoCompile *cfg) * <- * br BB3 */ - if (!(bb->out_count == 2 && !bb->extended)) - continue; - - bb1 = bb->out_bb [0]; - bb2 = bb->out_bb [1]; - if (bb1->in_count == 1 && bb2->in_count == 1 && bb1->out_count == 1 && bb2->out_count == 1 && bb1->out_bb [0] == bb2->out_bb [0]) { MonoInst *compare, *branch, *ins1, *ins2, *cmov, *move, *tmp; MonoBasicBlock *true_bb, *false_bb; diff --git a/mono/mini/iltests.il b/mono/mini/iltests.il index 40c55e63e9b..ba6aba836d4 100644 --- a/mono/mini/iltests.il +++ b/mono/mini/iltests.il @@ -3491,4 +3491,70 @@ L3: ret } */ + + .method public hidebysig static string cmov_try_block_helper (string s) cil managed noinlining + { + // Code size 43 (0x2b) + .maxstack 2 + .locals init (bool V_0, string V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: callvirt instance int32 [mscorlib]System.String::get_Length() + IL_0007: ldc.i4.0 + IL_0008: ceq + IL_000a: stloc.0 + IL_000b: ldloc.0 + IL_000c: brfalse.s IL_0016 + + IL_000e: ldstr "Empty" + IL_0013: stloc.1 + IL_0014: br.s IL_0029 + + IL_0016: nop + .try + { + IL_0017: nop + IL_0018: ldarg.0 + IL_0019: stloc.1 + IL_001a: leave.s IL_0029 + } // end .try + catch [mscorlib]System.Exception + { + IL_001c: pop + IL_001d: nop + IL_001e: nop + IL_001f: leave.s IL_0021 + } // end handler + IL_0021: ldstr "Should not happen" + IL_0026: stloc.1 + IL_0027: br.s IL_0029 + + IL_0029: ldloc.1 + IL_002a: ret + } + + .method public hidebysig static int32 test_1_cmov_try_block() cil managed + { + // Code size 37 (0x25) + .maxstack 2 + .locals init (string V_0, bool V_1, int32 V_2) + IL_0000: nop + IL_0001: ldstr "abc" + IL_0006: call string Tests::cmov_try_block_helper(string) + IL_000d: ldstr "abc" + IL_0012: call bool [mscorlib]System.String::op_Equality(string,string) + IL_0019: brfalse.s IL_001f + + IL_001b: ldc.i4.1 + IL_001c: stloc.2 + IL_001d: br.s IL_0023 + + IL_001f: ldc.i4.0 + IL_0020: stloc.2 + IL_0021: br.s IL_0023 + + IL_0023: ldloc.2 + IL_0024: ret + } + } -- 2.11.4.GIT