aboutsummaryrefslogtreecommitdiff
path: root/gcc/loop.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2003-07-18 13:13:37 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2003-07-18 13:13:37 +0200
commit16f6812f86b9095a7b38d1a6cbe665bc801ca50a (patch)
treeb37326901374d1542b48895f7a8d13061117176b /gcc/loop.c
parent2d5f9af2bf821d062b6e089e15ccbae915aa1efe (diff)
downloadgcc-16f6812f86b9095a7b38d1a6cbe665bc801ca50a.zip
gcc-16f6812f86b9095a7b38d1a6cbe665bc801ca50a.tar.gz
gcc-16f6812f86b9095a7b38d1a6cbe665bc801ca50a.tar.bz2
re PR target/11087 (gcc miscompiles raid1.c from linux kernel)
PR target/11087 * loop.c (basic_induction_var): Check if convert_modes emitted any instructions. Remove them and return 0 if so. * gcc.c-torture/execute/20030717-1.c: New test. From-SVN: r69552
Diffstat (limited to 'gcc/loop.c')
-rw-r--r--gcc/loop.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/gcc/loop.c b/gcc/loop.c
index 71c322c..683d83a 100644
--- a/gcc/loop.c
+++ b/gcc/loop.c
@@ -6197,7 +6197,7 @@ basic_induction_var (const struct loop *loop, rtx x, enum machine_mode mode,
{
enum rtx_code code;
rtx *argp, arg;
- rtx insn, set = 0;
+ rtx insn, set = 0, last, inc;
code = GET_CODE (x);
*location = NULL;
@@ -6225,7 +6225,26 @@ basic_induction_var (const struct loop *loop, rtx x, enum machine_mode mode,
if (loop_invariant_p (loop, arg) != 1)
return 0;
- *inc_val = convert_modes (GET_MODE (dest_reg), GET_MODE (x), arg, 0);
+ /* convert_modes can emit new instructions, e.g. when arg is a loop
+ invariant MEM and dest_reg has a different mode.
+ These instructions would be emitted after the end of the function
+ and then *inc_val would be an unitialized pseudo.
+ Detect this and bail in this case.
+ Other alternatives to solve this can be introducing a convert_modes
+ variant which is allowed to fail but not allowed to emit new
+ instructions, emit these instructions before loop start and let
+ it be garbage collected if *inc_val is never used or saving the
+ *inc_val initialization sequence generated here and when *inc_val
+ is going to be actually used, emit it at some suitable place. */
+ last = get_last_insn ();
+ inc = convert_modes (GET_MODE (dest_reg), GET_MODE (x), arg, 0);
+ if (get_last_insn () != last)
+ {
+ delete_insns_since (last);
+ return 0;
+ }
+
+ *inc_val = inc;
*mult_val = const1_rtx;
*location = argp;
return 1;
@@ -6306,7 +6325,15 @@ basic_induction_var (const struct loop *loop, rtx x, enum machine_mode mode,
&& GET_MODE_CLASS (mode) != MODE_CC)
{
/* Possible bug here? Perhaps we don't know the mode of X. */
- *inc_val = convert_modes (GET_MODE (dest_reg), mode, x, 0);
+ last = get_last_insn ();
+ inc = convert_modes (GET_MODE (dest_reg), mode, x, 0);
+ if (get_last_insn () != last)
+ {
+ delete_insns_since (last);
+ return 0;
+ }
+
+ *inc_val = inc;
*mult_val = const0_rtx;
return 1;
}