2015-10-20 Vladimir Makarov <vmakarov@redhat.com>
authorvmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 20 Oct 2015 16:26:05 +0000 (16:26 +0000)
committervmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 20 Oct 2015 16:26:05 +0000 (16:26 +0000)
PR rtl-optimization/67609
* lra-splill.c (lra_final_code_change): Don't remove all
sub-registers.

2015-10-20  Vladimir Makarov  <vmakarov@redhat.com>

PR rtl-optimization/67609
* gcc.target/i386/pr67609.c: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@229087 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/lra-spills.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr67609.c [new file with mode: 0644]

index e339817..9ad52a8 100644 (file)
@@ -1,3 +1,9 @@
+2015-10-20  Vladimir Makarov  <vmakarov@redhat.com>
+
+       PR rtl-optimization/67609
+       * lra-splill.c (lra_final_code_change): Don't remove all
+       sub-registers.
+
 2015-10-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * simplify-rtx.c (simplify_binary_operation): If either operand was
index a210c41..9c1207f 100644 (file)
@@ -727,14 +727,44 @@ lra_final_code_change (void)
          lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
          struct lra_static_insn_data *static_id = id->insn_static_data;
          bool insn_change_p = false;
-
-         for (i = id->insn_static_data->n_operands - 1; i >= 0; i--)
-           if ((DEBUG_INSN_P (insn) || ! static_id->operand[i].is_operator)
-               && alter_subregs (id->operand_loc[i], ! DEBUG_INSN_P (insn)))
-             {
-               lra_update_dup (id, i);
-               insn_change_p = true;
-             }
+         
+          for (i = id->insn_static_data->n_operands - 1; i >= 0; i--)
+           {
+             if (! DEBUG_INSN_P (insn) && static_id->operand[i].is_operator)
+               continue;
+             
+             rtx op = *id->operand_loc[i];
+             
+             if (static_id->operand[i].type == OP_OUT
+                 && GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op))
+                 && ! LRA_SUBREG_P (op))
+               {
+                 hard_regno = REGNO (SUBREG_REG (op));
+                 /* We can not always remove sub-registers of
+                    hard-registers as we may lose information that
+                    only a part of registers is changed and
+                    subsequent optimizations may do wrong
+                    transformations (e.g. dead code eliminations).
+                    We can not also keep all sub-registers as the
+                    subsequent optimizations can not handle all such
+                    cases.  Here is a compromise which works.  */
+                 if ((GET_MODE_SIZE (GET_MODE (op))
+                      < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))))
+                     && (hard_regno_nregs[hard_regno][GET_MODE (SUBREG_REG (op))]
+                         == hard_regno_nregs[hard_regno][GET_MODE (op)])
+#ifdef STACK_REGS
+                     && (hard_regno < FIRST_STACK_REG
+                         || hard_regno > LAST_STACK_REG)
+#endif
+                     )
+                   continue;
+               }
+             if (alter_subregs (id->operand_loc[i], ! DEBUG_INSN_P (insn)))
+               {
+                 lra_update_dup (id, i);
+                 insn_change_p = true;
+               }
+           }
          if (insn_change_p)
            lra_update_operator_dups (id);
        }
index 2b6118f..8620128 100644 (file)
@@ -1,3 +1,8 @@
+2015-10-20  Vladimir Makarov  <vmakarov@redhat.com>
+
+       PR rtl-optimization/67609
+       * gcc.target/i386/pr67609.c: New.
+
 2015-10-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * gcc.target/aarch64/fmul_fcvt_1.c: Add multiply-by-32 cases.
diff --git a/gcc/testsuite/gcc.target/i386/pr67609.c b/gcc/testsuite/gcc.target/i386/pr67609.c
new file mode 100644 (file)
index 0000000..518071b
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-final { scan-assembler "movdqa" } } */
+
+#include <emmintrin.h>
+__m128d reg;
+void set_lower(double b)
+{
+  double v[2];
+  _mm_store_pd(v, reg);
+  v[0] = b;
+  reg = _mm_load_pd(v);
+}