diff mbox

patch to fix PR77761

Message ID 9475a197-c6c2-9d87-12ed-e7d4ce165225@redhat.com
State New
Headers show

Commit Message

Vladimir Makarov Dec. 6, 2016, 8:04 p.m. UTC
The following patch fixes

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77761

The patch was successfully bootstrapped and tested on x86-64

Committed as rev. 243316.
diff mbox

Patch

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 243315)
+++ ChangeLog	(working copy)
@@ -1,3 +1,9 @@ 
+2016-12-06  Vladimir Makarov  <vmakarov@redhat.com>
+
+	target/77761
+	* lra-lives.c (process_bb_lives): Update biggest mode for
+	implicitly used hard reg.
+
 2016-12-06  Uros Bizjak  <ubizjak@gmail.com>
 
 	* config/i386/predicates.md (general_gr_operand): New predicate.
Index: testsuite/ChangeLog
===================================================================
--- testsuite/ChangeLog	(revision 243315)
+++ testsuite/ChangeLog	(working copy)
@@ -1,3 +1,8 @@ 
+2016-12-06  Vladimir Makarov  <vmakarov@redhat.com>
+
+	target/77761
+	* testsuite/gcc.target/i386/pr77761.c: New.
+
 2016-12-06  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
 	PR fortran/78659
Index: lra-lives.c
===================================================================
--- lra-lives.c	(revision 243315)
+++ lra-lives.c	(working copy)
@@ -702,11 +702,24 @@  process_bb_lives (basic_block bb, int &c
       /* Update max ref width and hard reg usage.  */
       for (reg = curr_id->regs; reg != NULL; reg = reg->next)
 	{
+	  int i, regno = reg->regno;
+	  
 	  if (GET_MODE_SIZE (reg->biggest_mode)
-	      > GET_MODE_SIZE (lra_reg_info[reg->regno].biggest_mode))
-	    lra_reg_info[reg->regno].biggest_mode = reg->biggest_mode;
-	  if (reg->regno < FIRST_PSEUDO_REGISTER)
-	    lra_hard_reg_usage[reg->regno] += freq;
+	      > GET_MODE_SIZE (lra_reg_info[regno].biggest_mode))
+	    lra_reg_info[regno].biggest_mode = reg->biggest_mode;
+	  if (regno < FIRST_PSEUDO_REGISTER)
+	    {
+	      lra_hard_reg_usage[regno] += freq;
+	      /* A hard register explicitly can be used in small mode,
+		 but implicitly it can be used in natural mode as a
+		 part of multi-register group.  Process this case
+		 here.  */
+	      for (i = 1; i < hard_regno_nregs[regno][reg->biggest_mode]; i++)
+		if (GET_MODE_SIZE (GET_MODE (regno_reg_rtx[regno + i]))
+		    > GET_MODE_SIZE (lra_reg_info[regno + i].biggest_mode))
+		  lra_reg_info[regno + i].biggest_mode
+		    = GET_MODE (regno_reg_rtx[regno + i]);
+	    }
 	}
 
       call_p = CALL_P (curr_insn);
Index: testsuite/gcc.target/i386/pr77761.c
===================================================================
--- testsuite/gcc.target/i386/pr77761.c	(revision 0)
+++ testsuite/gcc.target/i386/pr77761.c	(working copy)
@@ -0,0 +1,55 @@ 
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-guess-branch-probability -fschedule-insns -fno-tree-ter -mavx512f --param=max-pending-list-length=512" } */
+/* { dg-require-effective-target avx512f } */
+
+#include "avx512f-check.h"
+
+typedef unsigned char u8;
+typedef unsigned char v64u8 __attribute__ ((vector_size (64)));
+typedef unsigned short u16;
+typedef unsigned short v64u16 __attribute__ ((vector_size (64)));
+typedef unsigned int u32;
+typedef unsigned int v64u32 __attribute__ ((vector_size (64)));
+typedef unsigned long long u64;
+typedef unsigned long long v64u64 __attribute__ ((vector_size (64)));
+typedef unsigned __int128 u128;
+typedef unsigned __int128 v64u128 __attribute__ ((vector_size (64)));
+
+v64u128 __attribute__ ((noinline, noclone))
+foo(u8 x1, u16 x2, u32 x3, u64 x4, v64u8 x5, v64u16 x6, v64u32 x7, v64u64 x8, v64u128 x9)
+{
+  u8 *p = &x1;
+  x9[0] -= *p;
+  x5 %= (v64u8){ 1, -x4, 0, x3, x5[9], x7[1], 4, x6[1], 13 << 4} | 1;
+  x5[1] = x5[0];
+  x8 %= (v64u64){1, x1} | 1;
+  x9 /= x9 | 1;
+  x5 -= (v64u8){0, 0, 3, 0, 0, 0, 0, x4, x9[0], 0, 1};
+  return x1 + x2 + x3 + x4 + (v64u128) x5 + (v64u128) x6 + (v64u128) x7 +
+    (v64u128) x8 + x9;
+}
+
+int
+do_main ()
+{
+  v64u128 x = foo(1, 0, 0, 0, (v64u8){}, (v64u16){}, (v64u32){}, (v64u64){}, (v64u128){});
+
+  if ((u64)(x[0] >> 64) != 0x0000000000ff00ff)
+    __builtin_abort();
+  if ((u64)(x[0] >>  0) != 0x0000000000fd0002)
+    __builtin_abort();
+
+  if (x[1] != 1)
+    __builtin_abort();
+  if (x[2] != 1)
+    __builtin_abort();
+  if (x[3] != 1)
+    __builtin_abort();
+  return 0;
+}
+
+static void
+avx512f_test (void)
+{
+  do_main ();
+}