Merge pull request #2822 from BrzVlad/feature-lshift-decomposition
authorVlad Brezae <brezaevlad@gmail.com>
Tue, 12 Apr 2016 21:32:39 +0000 (05:32 +0800)
committerVlad Brezae <brezaevlad@gmail.com>
Tue, 12 Apr 2016 21:32:39 +0000 (05:32 +0800)
[jit] Decompose long immediate shifts

1  2 
mono/mini/decompose.c
mono/mini/local-propagation.c

diff --combined mono/mini/decompose.c
index 10a5bdfd5b40a943f3a0b627cd4cb91265ff7121,187bf138f1e0422e8de39d90e77e1a27d001b6d3..9546009e724697247abc5e7e3e11ff1f67c8e685
@@@ -6,7 -6,6 +6,7 @@@
   *
   * (C) 2002 Ximian, Inc.
   * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
 + * Licensed under the MIT license. See LICENSE file in the project root for full license information.
   */
  
  #include "mini.h"
@@@ -933,6 -932,8 +933,8 @@@ mono_decompose_long_opts (MonoCompile *
                                MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), tree->inst_ls_word);
                                MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), tree->inst_ms_word);
                                break;
+ #ifdef TARGET_POWERPC
+ /* FIXME This is normally handled in cprop. Proper fix or remove if no longer needed. */
                        case OP_LSHR_UN_IMM:
                                if (tree->inst_c1 == 32) {
  
                                         * later apply the speedup to the left shift as well
                                         * See BUG# 57957.
                                         */
-                                       /* FIXME: Move this to the strength reduction pass */
                                        /* just move the upper half to the lower and zero the high word */
                                        MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), MONO_LVREG_MS (tree->sreg1));
                                        MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), 0);
                                }
                                break;
-                       case OP_LSHL_IMM:
-                               if (tree->inst_c1 == 32) {
-                                       /* just move the lower half to the upper and zero the lower word */
-                                       MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (tree->dreg), MONO_LVREG_LS (tree->sreg1));
-                                       MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_LS (tree->dreg), 0);
-                               }
-                               break;
+ #endif
                        case OP_LCOMPARE: {
                                MonoInst *next = mono_inst_next (tree, FILTER_IL_SEQ_POINT);
  
index f23c5ff3bb9e5c1278220b19656c554e6f85d527,dc159106eb01a32ef9fa71c427674ce5a2c3f651..32cd496f30f19b43817bfef49cfe95f27a2d5a08
@@@ -10,7 -10,6 +10,7 @@@
   *
   * (C) 2006 Novell, Inc.  http://www.novell.com
   * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
 + * Licensed under the MIT license. See LICENSE file in the project root for full license information.
   */
  
  #include <config.h>
@@@ -181,6 -180,69 +181,69 @@@ mono_strength_reduction_ins (MonoCompil
  #endif
                break;
        }
+ #if SIZEOF_REGISTER == 4
+       case OP_LSHR_IMM: {
+               if (ins->inst_c1 == 32) {
+                       MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (ins->dreg), MONO_LVREG_MS (ins->sreg1));
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_IMM, MONO_LVREG_MS (ins->dreg), MONO_LVREG_MS (ins->sreg1), 31);
+               } else if (ins->inst_c1 == 0) {
+                       MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (ins->dreg), MONO_LVREG_LS (ins->sreg1));
+                       MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (ins->dreg), MONO_LVREG_MS (ins->sreg1));
+               } else if (ins->inst_c1 > 32) {
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_IMM, MONO_LVREG_LS (ins->dreg), MONO_LVREG_MS (ins->sreg1), ins->inst_c1 - 32);
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_IMM, MONO_LVREG_MS (ins->dreg), MONO_LVREG_MS (ins->sreg1), 31);
+               } else {
+                       guint32 tmpreg = alloc_ireg (cfg);
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHL_IMM, tmpreg, MONO_LVREG_MS (ins->sreg1), 32 - ins->inst_c1);
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_IMM, MONO_LVREG_MS (ins->dreg), MONO_LVREG_MS (ins->sreg1), ins->inst_c1);
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, MONO_LVREG_LS (ins->dreg), MONO_LVREG_LS (ins->sreg1), ins->inst_c1);
+                       MONO_EMIT_NEW_BIALU (cfg, OP_IOR, MONO_LVREG_LS (ins->dreg), MONO_LVREG_LS (ins->dreg), tmpreg);
+                       allocated_vregs = TRUE;
+               }
+               break;
+       }
+       case OP_LSHR_UN_IMM: {
+               if (ins->inst_c1 == 32) {
+                       MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (ins->dreg), MONO_LVREG_MS (ins->sreg1));
+                       MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (ins->dreg), 0);
+               } else if (ins->inst_c1 == 0) {
+                       MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (ins->dreg), MONO_LVREG_LS (ins->sreg1));
+                       MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (ins->dreg), MONO_LVREG_MS (ins->sreg1));
+               } else if (ins->inst_c1 > 32) {
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, MONO_LVREG_LS (ins->dreg), MONO_LVREG_MS (ins->sreg1), ins->inst_c1 - 32);
+                       MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (ins->dreg), 0);
+               } else {
+                       guint32 tmpreg = alloc_ireg (cfg);
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHL_IMM, tmpreg, MONO_LVREG_MS (ins->sreg1), 32 - ins->inst_c1);
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, MONO_LVREG_MS (ins->dreg), MONO_LVREG_MS (ins->sreg1), ins->inst_c1);
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, MONO_LVREG_LS (ins->dreg), MONO_LVREG_LS (ins->sreg1), ins->inst_c1);
+                       MONO_EMIT_NEW_BIALU (cfg, OP_IOR, MONO_LVREG_LS (ins->dreg), MONO_LVREG_LS (ins->dreg), tmpreg);
+                       allocated_vregs = TRUE;
+               }
+               break;
+       }
+       case OP_LSHL_IMM: {
+               if (ins->inst_c1 == 32) {
+                       /* just move the lower half to the upper and zero the lower word */
+                       MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (ins->dreg), MONO_LVREG_LS (ins->sreg1));
+                       MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_LS (ins->dreg), 0);
+               } else if (ins->inst_c1 == 0) {
+                       MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (ins->dreg), MONO_LVREG_LS (ins->sreg1));
+                       MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (ins->dreg), MONO_LVREG_MS (ins->sreg1));
+               } else if (ins->inst_c1 > 32) {
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHL_IMM, MONO_LVREG_MS (ins->dreg), MONO_LVREG_LS (ins->sreg1), ins->inst_c1 - 32);
+                       MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_LS (ins->dreg), 0);
+               } else {
+                       guint32 tmpreg = alloc_ireg (cfg);
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, tmpreg, MONO_LVREG_LS (ins->sreg1), 32 - ins->inst_c1);
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHL_IMM, MONO_LVREG_MS (ins->dreg), MONO_LVREG_MS (ins->sreg1), ins->inst_c1);
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHL_IMM, MONO_LVREG_LS (ins->dreg), MONO_LVREG_LS (ins->sreg1), ins->inst_c1);
+                       MONO_EMIT_NEW_BIALU (cfg, OP_IOR, MONO_LVREG_MS (ins->dreg), MONO_LVREG_MS (ins->dreg), tmpreg);
+                       allocated_vregs = TRUE;
+               }
+               break;
+       }
+ #endif
  
        default:
                break;