Hi!

The following testcase is miscompiled, because due to STV we end up
with a load from V2DFmode MEM for which get_pool_entry returns
a V1TImode vector.  maybe_get_pool_constant doesn't have code
to handle mode differences between what get_pool_constant returns
and the requested mode.  While it wouldn't be that hard to add,
this all is done properly in avoid_constant_pool_reference already,
which does everything maybe_get_pool_constant needs to do.

So, this patch just removes the maybe_get_pool_constant function and
uses avoid_constant_pool_reference instead.  I've looked into history
and the latter has been introduced in 2001, the former in 2002, but at
that point the latter didn't do any delegitimization (but has the
mode conversions at that point), while the former had hand-written
delegitimization.  But since then delegitimization has been added to
a_c_p_r and custom delegitimization changed into the full blown one in
m_g_p_c.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/7.x?

2017-10-26  Jakub Jelinek  <ja...@redhat.com>

        PR target/82703
        * config/i386/i386-protos.h (maybe_get_pool_constant): Removed.
        * config/i386/i386.c (maybe_get_pool_constant): Removed.
        (ix86_split_to_parts): Use avoid_constant_pool_reference instead of
        maybe_get_pool_constant.
        * config/i386/predicates.md (zero_extended_scalar_load_operand):
        Likewise.

        * gcc.dg/pr82703.c: New test.

--- gcc/config/i386/i386-protos.h.jj    2017-04-20 12:19:54.000000000 +0200
+++ gcc/config/i386/i386-protos.h       2017-10-26 13:14:05.172571175 +0200
@@ -282,8 +282,6 @@ extern bool i386_pe_type_dllexport_p (tr
 
 extern int i386_pe_reloc_rw_mask (void);
 
-extern rtx maybe_get_pool_constant (rtx);
-
 extern char internal_label_prefix[16];
 extern int internal_label_prefix_len;
 
--- gcc/config/i386/i386.c.jj   2017-09-30 10:26:43.000000000 +0200
+++ gcc/config/i386/i386.c      2017-10-26 13:15:03.917891804 +0200
@@ -19830,20 +19830,6 @@ ix86_expand_clear (rtx dest)
   emit_insn (tmp);
 }
 
-/* X is an unchanging MEM.  If it is a constant pool reference, return
-   the constant pool rtx, else NULL.  */
-
-rtx
-maybe_get_pool_constant (rtx x)
-{
-  x = ix86_delegitimize_address (XEXP (x, 0));
-
-  if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
-    return get_pool_constant (x);
-
-  return NULL_RTX;
-}
-
 void
 ix86_expand_move (machine_mode mode, rtx operands[])
 {
@@ -25371,11 +25357,7 @@ ix86_split_to_parts (rtx operand, rtx *p
   /* Optimize constant pool reference to immediates.  This is used by fp
      moves, that force all constants to memory to allow combining.  */
   if (MEM_P (operand) && MEM_READONLY_P (operand))
-    {
-      rtx tmp = maybe_get_pool_constant (operand);
-      if (tmp)
-       operand = tmp;
-    }
+    operand = avoid_constant_pool_reference (operand);
 
   if (MEM_P (operand) && !offsettable_memref_p (operand))
     {
--- gcc/config/i386/predicates.md.jj    2017-04-20 12:19:54.000000000 +0200
+++ gcc/config/i386/predicates.md       2017-10-26 13:16:27.399926361 +0200
@@ -975,9 +975,9 @@ (define_predicate "zero_extended_scalar_
   (match_code "mem")
 {
   unsigned n_elts;
-  op = maybe_get_pool_constant (op);
+  op = avoid_constant_pool_reference (op);
 
-  if (!(op && GET_CODE (op) == CONST_VECTOR))
+  if (GET_CODE (op) != CONST_VECTOR)
     return false;
 
   n_elts = CONST_VECTOR_NUNITS (op);
--- gcc/testsuite/gcc.dg/pr82703.c.jj   2017-10-26 13:19:23.879885830 +0200
+++ gcc/testsuite/gcc.dg/pr82703.c      2017-10-26 13:18:42.000000000 +0200
@@ -0,0 +1,28 @@
+/* PR target/82703 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-tree-sra -ftree-vectorize" } */
+
+__attribute__((noinline, noclone)) void
+compare (const double *p, const double *q)
+{
+  for (int i = 0; i < 3; ++i)
+    if (p[i] != q[i])
+      __builtin_abort ();
+}
+
+double vr[3] = { 4, 4, 4 };
+
+int
+main ()
+{
+  double v1[3] = { 1, 2, 3 };
+  double v2[3] = { 3, 2, 1 };
+  double v3[3];
+  __builtin_memcpy (v3, v1, sizeof (v1));
+  for (int i = 0; i < 3; ++i)
+    v3[i] += v2[i];
+  for (int i = 0; i < 3; ++i)
+    v1[i] += v2[i];
+  compare (v3, vr);
+  return 0;
+}

        Jakub

Reply via email to