This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] loop-{iv,unswitch}.c fixes (PR rtl-optimization/58997)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Biener <rguenther at suse dot de>, Zdenek Dvorak <ook at ucw dot cz>, Jan Hubicka <jh at suse dot cz>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Tue, 5 Nov 2013 14:09:55 +0100
- Subject: [PATCH] loop-{iv,unswitch}.c fixes (PR rtl-optimization/58997)
- Authentication-results: sourceware.org; auth=none
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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