diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2166ec5c54b39853b8ddbba372d64cc7f46fb053..1162471468f13aee0e092297fc2c850d141a0fde 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2003-07-17  Jakub Jelinek  <jakub@redhat.com>
+
+	PR target/11087
+	* loop.c (basic_induction_var): Check if convert_modes emitted any
+	instructions. Remove them and return 0 if so.
+
 2003-07-18  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
 	PR optimization/11083
diff --git a/gcc/loop.c b/gcc/loop.c
index 71c322c254bcbb1e51db288b32dfec785d5b9b9e..683d83aef043794b0268f21cb9a7175f84b87c60 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;
 	}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c69031a5be2264c54fd9d5fd6a1eda68c7ab9741..70c6936fb98b4d11c0152885dca555df284bec44 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2003-07-17  Jakub Jelinek  <jakub@redhat.com>
+
+	PR target/11087
+	* gcc.c-torture/execute/20030717-1.c: New test.
+
 2003-07-18  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
 	* g++.dg/opt/cfg1.C: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20030717-1.c b/gcc/testsuite/gcc.c-torture/execute/20030717-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..7e43e44be041b315d1de020b6abb970290101bcd
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20030717-1.c
@@ -0,0 +1,69 @@
+/* PR target/11087
+   This testcase was miscompiled on ppc64, because basic_induction_var called
+   convert_modes, yet did not expect it to emit any new instructions.
+   Those were emitted at the end of the function and destroyed during life
+   analysis, while the program used uninitialized pseudos created by
+   convert_modes.  */
+
+struct A
+{
+  unsigned short a1;
+  unsigned long a2;
+};
+
+struct B
+{
+  int b1, b2, b3, b4, b5;
+};
+
+struct C
+{
+  struct B c1[1];
+  int c2, c3;
+};
+
+static
+int foo (int x)
+{
+  return  x < 0 ? -x : x;
+}
+
+int bar (struct C *x, struct A *y)
+{
+  int a = x->c3;
+  const int b = y->a1 >> 9;
+  const unsigned long c = y->a2;
+  int d = a;
+  unsigned long e, f;
+
+  f = foo (c - x->c1[d].b4);
+  do
+    {
+      if (d <= 0)
+	d = x->c2;
+      d--;
+
+      e = foo (c-x->c1[d].b4);
+      if (e < f)
+	a = d;
+    }
+  while (d != x->c3);
+  x->c1[a].b4 = c + b;
+  return a;
+}
+
+int
+main ()
+{
+  struct A a;
+  struct C b;
+  int c;
+
+  a.a1 = 512;
+  a.a2 = 4242;
+  __builtin_memset (&b, 0, sizeof (b));
+  b.c1[0].b3 = 424242;
+  b.c2 = 1;
+  c = bar (&b, &a);
+  return 0;
+}