This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] combine: Do not call simplify from inside change_zero_ext (PR78232)


When combine splits a three-insn combination into two instructions it
can reuse i2dest for the temporary result of the first new instruction.
However all information it has in reg_stat about that register will be
stale.  This results in the simplify_gen_binary calls in change_zero_ext
using out-of-date information, which makes it think one of the ANDs
generated there always results in 0, and it doesn't get better from there.

This can also happen if a splitter in the MD uses nonzero_bits (for
example).  I tried to make the splitting code in combine save and restore
the i2dest reg_stat info, but that causes one of the acats tests to fail.

This whole reg_stat thing needs an overhaul.

This patch changes change_zero_ext to do the expected simplifications
itself and not call simplify_gen_*.

Does anyone have a brighter idea?


Segher


2016-11-08  Segher Boessenkool  <segher@kernel.crashing.org>

	PR rtl-optimization/78232
	* combine.c (change_zero_ext): Do not call simplify_gen_binary, do
	the simplifications manually.

---
 gcc/combine.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/gcc/combine.c b/gcc/combine.c
index 7ed0a62..40fe9b4 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -11163,8 +11163,10 @@ change_zero_ext (rtx pat)
 	  if (BITS_BIG_ENDIAN)
 	    start = GET_MODE_PRECISION (mode) - size - start;
 
-	  x = simplify_gen_binary (LSHIFTRT, mode,
-				   XEXP (x, 0), GEN_INT (start));
+	  if (start)
+	    x = gen_rtx_LSHIFTRT (mode, XEXP (x, 0), GEN_INT (start));
+	  else
+	    x = XEXP (x, 0);
 	}
       else if (GET_CODE (x) == ZERO_EXTEND
 	       && SCALAR_INT_MODE_P (mode)
@@ -11220,16 +11222,18 @@ change_zero_ext (rtx pat)
       if (BITS_BIG_ENDIAN)
 	offset = reg_width - width - offset;
 
+      rtx x, y, z, w;
       wide_int mask = wi::shifted_mask (offset, width, true, reg_width);
-      rtx x = gen_rtx_AND (mode, reg, immed_wide_int_const (mask, mode));
-      rtx y = simplify_gen_binary (ASHIFT, mode, SET_SRC (pat),
-				   GEN_INT (offset));
       wide_int mask2 = wi::shifted_mask (offset, width, false, reg_width);
-      y = simplify_gen_binary (AND, mode, y,
-			       immed_wide_int_const (mask2, mode));
-      rtx z = simplify_gen_binary (IOR, mode, x, y);
+      x = gen_rtx_AND (mode, reg, immed_wide_int_const (mask, mode));
+      if (offset)
+	y = gen_rtx_ASHIFT (mode, SET_SRC (pat), GEN_INT (offset));
+      else
+	y = SET_SRC (pat);
+      z = gen_rtx_AND (mode, y, immed_wide_int_const (mask2, mode));
+      w = gen_rtx_IOR (mode, x, z);
       SUBST (SET_DEST (pat), reg);
-      SUBST (SET_SRC (pat), z);
+      SUBST (SET_SRC (pat), w);
 
       changed = true;
     }
-- 
1.9.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]