combine: Fix PR83393

Message ID 93a9f1e991f9a5c398a6c44233d8966a4f15ef0e.1513167443.git.segher@kernel.crashing.org
State New
Headers show
Series
  • combine: Fix PR83393
Related show

Commit Message

Segher Boessenkool Dec. 13, 2017, 1:03 p.m.
In move_deaths we move a REG_DEAD note if the instruction combination
has extended the lifetime of a register so that the existing note is
no longer valid.  We find that note using reg_stat, but what that finds
can refer to a later insn.  If so, we cannot use the cached value.  This
patch implements that.

Tested on powerpc64-linux {-m32,-m64}; test is running on x64_64-linux
{-m32,-m64} (the new testcase tested fine already).  I'll commit it in
a bit if that test succeeds.


Segher


2017-12-13  Segher Boessenkool  <segher@kernel.crashing.org>

	PR rtl-optimization/83393
	* combine.c (move_deaths): If reg_stat points to a too new insn in
	last_death, do not use it: find the proper insn instead.

gcc/testsuite/
	PR rtl-optimization/83393
	* gcc.dg/pr83393.c: New testcase.

---
 gcc/combine.c                  |  2 +-
 gcc/testsuite/gcc.dg/pr83393.c | 38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr83393.c

-- 
1.8.3.1

Patch

diff --git a/gcc/combine.c b/gcc/combine.c
index b12484a..f96e08e 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -13912,7 +13912,7 @@  move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx_insn *to_insn,
 
       /* If we do not know where the register died, it may still die between
 	 FROM_LUID and TO_INSN.  If so, find it.  This is PR83304.  */
-      if (!where_dead)
+      if (!where_dead || DF_INSN_LUID (where_dead) >= DF_INSN_LUID (to_insn))
 	{
 	  rtx_insn *insn = prev_real_insn (to_insn);
 	  while (insn
diff --git a/gcc/testsuite/gcc.dg/pr83393.c b/gcc/testsuite/gcc.dg/pr83393.c
new file mode 100644
index 0000000..a9a6b33
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr83393.c
@@ -0,0 +1,38 @@ 
+/* PR rtl-optimization/83393 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-forward-propagate -fno-tree-bit-ccp" } */
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long long u64;
+
+u32 a, d;
+u64 b;
+u8 c;
+
+static u64 __attribute__ ((noinline, noclone))
+foo (u16 f, u64 g)
+{
+  f <<= 15;
+  f *= d;
+  f -= g %= 44;
+  f <<= f <= g;
+  c = 255;
+  c >>= (u8) f == 0;
+  f *= g;
+  c -= ~c;
+  return f + a + b + f;
+}
+
+int
+main (void)
+{
+#if (__SIZEOF_LONG_LONG__ == 8 && __SIZEOF_INT__ == 4 \
+     && __SIZEOF_SHORT__ == 2 && __CHAR_BIT__ == 8)
+  u64 x = foo (3, 0xE6C0011BBA6DBD7LL);
+  if (x != 0x1f66e)
+    __builtin_abort ();
+#endif
+  return 0;
+}