gcc 2.95.3 [not pre-3.x]: gmp powm incorrect i686 code

Bernd Schmidt bernds@redhat.com
Fri Mar 30 05:18:00 GMT 2001


On 23 Mar 2001, Kevin Ryde wrote:

> This bug, as far as I can tell, doesn't occur in the current gcc cvs.
> I say i686 in the subject because removing -march=pentiumpro from the
> flags makes the bug disappear and because the problem is near a p-pro
> cmov, but actually I've got no idea whether this is relevant or merely
> a coincidence.
>
> Using a Debian i386 packaged gcc 2.95.3,
>
>     Reading specs from /usr/lib/gcc-lib/i386-linux/2.95.3/specs
>     gcc version 2.95.3 20010111 (prerelease)
>
> (or 2.95.2 on Debian or FreeBSD), I believe the program below results
> in incorrect assembler code when compiled with
>
>     gcc -g -O -fomit-frame-pointer -march=pentiumpro -mcpu=pentiumpro \
>        powm311.c
>
> The statement
>
>     j = (c->_mp_size >= 0 ? c->_mp_size : - c->_mp_size);
>
> comes out as follows (from objdump), and I believe 0x20(%esp) is being
> used uninitialized.

The problem here is that reload decides to delete an output reload for a
stack slot that is still used afterwards.  This is because
delete_output_reload is looking for the wrong piece of rtl: it's using
reg_equiv_memory_loc without calling eliminate_regs on it.  Fixed with
the following patch in the 2.95 branch; I will add it to the mainline and
the 3.0 branch as well after all the necessary bootstraps.

I have a feeling that the code may now be too conservative; I'm not sure
it won't count some occurrences twice (once in the insn pattern, and
another time in the USEs before it).  However, there didn't seem to be
any code generation differences for the Linux kernel on x86-linux and
for stress-1.16 on sh-elf.


Bernd

Index: ChangeLog
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ChangeLog,v
retrieving revision 1.3667.4.343
diff -u -p -r1.3667.4.343 ChangeLog
--- ChangeLog	2001/03/30 09:50:41	1.3667.4.343
+++ ChangeLog	2001/03/30 13:06:40
@@ -2,6 +2,9 @@

 	* jump.c (delete_barrier_successors): Fix error in last change.

+	* reload1.c (delete_output_reload): Call eliminate_regs on substed.
+	(reload_as_needed): Call update_eliminable_offsets a bit later.
+
 2001-03-28  Bernd Schmidt  <bernds@redhat.com>

 	* flow.c (propagate_block): When trying to delete a case vector, cope
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload1.c,v
retrieving revision 1.145.4.12
diff -u -p -r1.145.4.12 reload1.c
--- reload1.c	2001/01/25 14:03:21	1.145.4.12
+++ reload1.c	2001/03/30 13:06:46
@@ -4278,9 +4278,6 @@ reload_as_needed (live_known)
 			    spill_reg_order);
 	    }

-	  if (num_eliminable && chain->need_elim)
-	    update_eliminable_offsets ();
-
 	  if (n_reloads > 0)
 	    {
 	      rtx next = NEXT_INSN (insn);
@@ -4327,6 +4324,10 @@ reload_as_needed (live_known)
 		      NOTE_LINE_NUMBER (p) = NOTE_INSN_DELETED;
 		    }
 	    }
+
+	  if (num_eliminable && chain->need_elim)
+	    update_eliminable_offsets ();
+
 	  /* Any previously reloaded spilled pseudo reg, stored in this insn,
 	     is no longer validly lying around to save a future reload.
 	     Note that this does not detect pseudos that were reloaded
@@ -8071,7 +8072,9 @@ delete_output_reload (insn, j, last_relo
     }
   n_occurrences = count_occurrences (PATTERN (insn), reg);
   if (substed)
-    n_occurrences += count_occurrences (PATTERN (insn), substed);
+    n_occurrences += count_occurrences (PATTERN (insn),
+					eliminate_regs (substed, 0,
+							NULL_RTX));
   if (n_occurrences > n_inherited)
     return;




More information about the Gcc-patches mailing list