This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix cse related fail of pure-1.c on powerpc64-linux


gcc.c-torture/execute/pure-1.c is failing at -O1 on powerpc64-linux,
in a rather curious way.  I see link_error{1,3,5,7}, which has
nothing to do with gcc not seeing const or pure attributes for
the functions.  Instead, it looks like cse is losing track of
register values.

The first few lines of pure-1.c's main are:

int main ()
{
  int i[10], r;

  i[0] = 0;
  r = func0(0);
  if (i[0])
    link_error0();

  i[1] = 0;
  r = func1(0);
  if (i[1])
    link_error1();

RTL corresponding to "i[1] = 0" is:

(insn 27 168 28 2 0x40081740 (set (reg:SI 126)
        (const_int 0 [0x0])) -1 (nil)
    (expr_list:REG_EQUAL (const_int 0 [0x0])
        (nil)))

(insn 28 27 30 2 0x40081740 (set (mem/s/j:SI (plus:DI (reg/f:DI 31 r31)
                (const_int 116 [0x74])) [0 i+4 S4 A32])
        (reg:SI 126)) 300 {*movsi_internal1} (nil)
    (nil))


What I'm seeing is that cse_insn finds an equivalent register holding
a zero instead of using (reg:SI 126) in insn 28.  It's choice is
(subreg:SI (reg:DI 124) 4), which is quite valid.  This register
happens to be loaded as part of "if (i[0])" with

(insn 19 16 20 0 0x40081740 (set:DI (reg:DI 124)
        (zero_extend:DI (mem/j:SI (plus:DI (reg/f:DI 31 r31)
                    (const_int 112 [0x70])) [0 i+0 S4 A128]))) 12 {*rs6000.md:1151} (nil)
    (nil))

Because func0 is pure, (reg:DI 124) is correctly recognized as holding
a zero when insn 19 is processed, and I see an entry in cse's main hash
table grouped with other DImode zero values.  The trouble is that
(subreg:SI (reg:DI 124) 4) isn't put into the table with SImode zero
values.  Instead it gets a class all of its own..


The following hack rectifies this.  I'm calling it a hack because it's
quite possible that src_eqv_elt should have been set earlier.  I'm not
familiar enough with this code to really say.

	* cse.c (cse_insn): Set classp using src_const_elt if
	src_eqv_elt is NULL.

--- gcc-ppc64-33.orig/gcc/cse.c	2003-01-12 08:18:06.000000000 +1030
+++ gcc-ppc64-33/gcc/cse.c	2003-03-28 21:35:06.000000000 +1030
@@ -5960,18 +5960,21 @@ cse_insn (insn, libcall_insn)
 	  {
 	    /* Insert source and constant equivalent into hash table, if not
 	       already present.  */
 	    struct table_elt *classp = src_eqv_elt;
 	    rtx src = sets[i].src;
 	    rtx dest = SET_DEST (sets[i].rtl);
 	    enum machine_mode mode
 	      = GET_MODE (src) == VOIDmode ? GET_MODE (dest) : GET_MODE (src);
 
+	    if (!classp)
+	      classp = sets[i].src_const_elt;
+
 	    if (sets[i].src_elt == 0)
 	      {
 		/* Don't put a hard register source into the table if this is
 		   the last insn of a libcall.  In this case, we only need
 		   to put src_eqv_elt in src_elt.  */
 		if (! find_reg_note (insn, REG_RETVAL, NULL_RTX))
 		  {
 		    struct table_elt *elt;
 
-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]