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] loop-{iv,unswitch}.c fixes (PR rtl-optimization/58997)


Hi!

Apparently, for iv->extend == IV_UNKNOWN_EXTEND if iv->mode !=
iv->extend_mode get_iv_value returns a value in iv->mode mode, while
otherwise in iv->extend_mode.  This makes some sense, because with
IV_UNKNOWN_EXTEND the upper bits are unknown, so there is nothing reasonable
to return in the extended mode.  But e.g. iv_subreg when it calls assumed
unconditionally the value would be in iv->extend_mode (the reason for the
ICE on the attached testcase).  Furthermore, for iv_extend, IMHO if
iv->extend isn't IV_UNKNOWN_EXTEND, but is different from the new extend,
the middle bits might be incorrect.  And, lastly, I think may_unswitch_on
assumes the returned values will be in the expected mode (iv->mode), but
they can be wider and that can result in invalid RTL (say comparing of
SImode with DImode rtl), or wrong code.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk and for 4.8 later?

2013-11-05  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/58997
	* loop-iv.c (iv_subreg): For IV_UNKNOWN_EXTEND, expect
	get_iv_value to be in iv->mode rather than iv->extend_mode.
	(iv_extend): Likewise.  Otherwise, if iv->extend != extend,
	use lowpart_subreg on get_iv_value before calling simplify_gen_unary.
	* loop-unswitch.c (may_unswitch_on): Make sure op[i] is in the right
	mode.

	* gcc.c-torture/compile/pr58997.c: New test.

--- gcc/loop-iv.c.jj	2013-10-17 22:30:56.000000000 +0200
+++ gcc/loop-iv.c	2013-11-05 10:10:31.685719102 +0100
@@ -436,7 +436,9 @@ iv_subreg (struct rtx_iv *iv, enum machi
       && !iv->first_special)
     {
       rtx val = get_iv_value (iv, const0_rtx);
-      val = lowpart_subreg (mode, val, iv->extend_mode);
+      val = lowpart_subreg (mode, val,
+			    iv->extend == IV_UNKNOWN_EXTEND
+			    ? iv->mode : iv->extend_mode);
 
       iv->base = val;
       iv->extend = IV_UNKNOWN_EXTEND;
@@ -476,8 +478,14 @@ iv_extend (struct rtx_iv *iv, enum iv_ex
       && !iv->first_special)
     {
       rtx val = get_iv_value (iv, const0_rtx);
+      if (iv->extend_mode != iv->mode
+	  && iv->extend != IV_UNKNOWN_EXTEND
+	  && iv->extend != extend)
+	val = lowpart_subreg (iv->mode, val, iv->extend_mode);
       val = simplify_gen_unary (iv_extend_to_rtx_code (extend), mode,
-				val, iv->extend_mode);
+				val,
+				iv->extend == extend
+				? iv->extend_mode : iv->mode);
       iv->base = val;
       iv->extend = IV_UNKNOWN_EXTEND;
       iv->mode = iv->extend_mode = mode;
--- gcc/loop-unswitch.c.jj	2013-10-17 22:30:41.780251692 +0200
+++ gcc/loop-unswitch.c	2013-11-05 10:28:57.172719881 +0100
@@ -191,6 +191,7 @@ may_unswitch_on (basic_block bb, struct
   if (!test)
     return NULL_RTX;
 
+  mode = VOIDmode;
   for (i = 0; i < 2; i++)
     {
       op[i] = XEXP (test, i);
@@ -205,11 +206,15 @@ may_unswitch_on (basic_block bb, struct
 	return NULL_RTX;
 
       op[i] = get_iv_value (&iv, const0_rtx);
+      if (iv.extend != IV_UNKNOWN_EXTEND
+	  && iv.mode != iv.extend_mode)
+	op[i] = lowpart_subreg (iv.mode, op[i], iv.extend_mode);
+      if (mode == VOIDmode)
+	mode = iv.mode;
+      else
+	gcc_assert (mode == iv.mode);
     }
 
-  mode = GET_MODE (op[0]);
-  if (mode == VOIDmode)
-    mode = GET_MODE (op[1]);
   if (GET_MODE_CLASS (mode) == MODE_CC)
     {
       if (at != BB_END (bb))
--- gcc/testsuite/gcc.c-torture/compile/pr58997.c.jj	2013-11-05 10:26:30.802517924 +0100
+++ gcc/testsuite/gcc.c-torture/compile/pr58997.c	2013-11-05 10:26:15.000000000 +0100
@@ -0,0 +1,19 @@
+/* PR rtl-optimization/58997 */
+
+int a, b, c, e;
+short d;
+char h;
+
+void
+foo ()
+{
+  while (b)
+    {
+      d = a ? c : 1 % a;
+      c = d;
+      h = d;
+      if (!h)
+	while (e)
+	  ;
+    }
+}

	Jakub


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