re PR rtl-optimization/67609 (Generates wrong code for SSE2 _mm_load_pd)
authorVladimir Makarov <vmakarov@redhat.com>
Tue, 20 Oct 2015 16:26:05 +0000 (16:26 +0000)
committerVladimir Makarov <vmakarov@gcc.gnu.org>
Tue, 20 Oct 2015 16:26:05 +0000 (16:26 +0000)
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  Vladimir Makarov  <vmakarov@redhat.com>

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

From-SVN: r229087

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

index e3398170ed4b910c02a6d38260c439f44a7a0b6a..9ad52a8262e8b5365a13f654aec4add22a8da278 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 a210c41da3151ad175e07874e8c1f123804e2e7d..9c1207f5057956015f475978d19f82cdd3b8d4c0 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 2b6118fd8a35349b32f9f6b628fb597bc4ebe061..8620128cdff8acb2afaa8779f24106a2f76b81d1 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);
+}