summaryrefslogtreecommitdiff
path: root/gcc/loop.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2003-07-18 11:13:37 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2003-07-18 11:13:37 +0000
commit204d2f94911cf16579bfa3dea1e8b2cc57cd6558 (patch)
treeb37326901374d1542b48895f7a8d13061117176b /gcc/loop.c
parent78dca82b0f823a7ac64f8911f4ef1a02dc10a36b (diff)
downloadgcc-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.c33
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;
}