diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-07-18 11:13:37 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-07-18 11:13:37 +0000 |
commit | 204d2f94911cf16579bfa3dea1e8b2cc57cd6558 (patch) | |
tree | b37326901374d1542b48895f7a8d13061117176b /gcc/loop.c | |
parent | 78dca82b0f823a7ac64f8911f4ef1a02dc10a36b (diff) | |
download | gcc-204d2f94911cf16579bfa3dea1e8b2cc57cd6558.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@69552 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/loop.c')
-rw-r--r-- | gcc/loop.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/gcc/loop.c b/gcc/loop.c index 71c322c254b..683d83aef04 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; } |