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]

[3.3 PATCH] PR opt/13031: GCSE work-around for reload


The following patch is my proposed solution to PR optimization/13031
which is an ICE on valid compiling on the alpha.

The real problem, which isn't addressed by this patch, is that
local register allocation ends up replacing the use of an register
in a conditional branch instruction with a constant without
re-recognizing it.  This results in an unrecognizable instruction
that later ICEs the compiler.

Clearly, register allocation is significantly complicated by
instantiating registers with constants in conditional branches,
which may then become unconditional, perturbing the CFG and
potentially invalidating liveness information.  This is an area
of reload, I didn't even want to think about.

Instead, the following patch works around the problem.  The reason
this failure is not present on mainline, is that the problematic
code is never triggered.  If a register has a constant value for
its lifetime, GCSE should be able to perform this substitution
safely, which is indeed what happens on mainline.  Unfortunately,
a typo (of mine) on the 3.3 branch means that we weren't propagating
constants into some conditional jumps on platforms without condition
codes (i.e. the alpha).  I'd fixed this on mainline when adding some
additional functionality, and the patch below is a backport of the
"bug-fix" aspects of that later change.  We were calling
simplify_replace_rtx with the entire "set" when setcc was NULL,
which is a no-op.  We should have been passing just the set's src.


The following patch has been tested against the gcc-3_3-branch
on both i686-pc-linux-gnu and alphaev67-dec-osf5.1 with a full
"make bootstrap", all langauges except Ada and treelang, and
regression tested with a top-level "make -k check" with no new
failures.


Ok for 3.3.3?  I'm confident the changes themselves are correct,
but there's always the remote risk of exposing latent bugs down
stream.  Reload still needs to be fixed, but any change there
would be too risky for the release branch, and perhaps even 3.4.


Very many thanks in advance,


2003-12-13  Roger Sayle  <roger@eyesopen.com>

	PR optimization/13031
	* gcse.c (cprop_jump): Backport code clean-up and bug-fix
	from mainline [2003-05-20 Sayle, Hirata and Rennecke patch].
	(cprop_insn): Don't attemp further substitutions if the
	current instruction has been deleted.
	(local_cprop_pass): Likewise.

	* gcc.c-torture/compile/20031213-1.c: New test case.


Index: gcse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcse.c,v
retrieving revision 1.223.2.8
diff -c -3 -p -r1.223.2.8 gcse.c
*** gcse.c	8 Nov 2003 15:24:26 -0000	1.223.2.8
--- gcse.c	11 Dec 2003 02:41:27 -0000
*************** cprop_jump (bb, setcc, jump, from, src)
*** 4063,4090 ****
       rtx from;
       rtx src;
  {
!   rtx new, new_set;
    rtx set = pc_set (jump);

    /* First substitute in the INSN condition as the SET_SRC of the JUMP,
       then substitute that given values in this expanded JUMP.  */
!   if (setcc != NULL
        && !modified_between_p (from, setcc, jump)
        && !modified_between_p (src, setcc, jump))
      {
        rtx setcc_set = single_set (setcc);
!       new_set = simplify_replace_rtx (SET_SRC (set),
  				      SET_DEST (setcc_set),
  				      SET_SRC (setcc_set));
      }
    else
!     new_set = set;

!   new = simplify_replace_rtx (new_set, from, src);

    /* If no simplification can be made, then try the next
       register.  */
!   if (rtx_equal_p (new, new_set) || rtx_equal_p (new, SET_SRC (set)))
      return 0;

    /* If this is now a no-op delete it, otherwise this must be a valid insn.  */
--- 4063,4091 ----
       rtx from;
       rtx src;
  {
!   rtx new;
    rtx set = pc_set (jump);
+   rtx set_src = SET_SRC (set);

    /* First substitute in the INSN condition as the SET_SRC of the JUMP,
       then substitute that given values in this expanded JUMP.  */
!   if (setcc != NULL_RTX
        && !modified_between_p (from, setcc, jump)
        && !modified_between_p (src, setcc, jump))
      {
        rtx setcc_set = single_set (setcc);
!       set_src = simplify_replace_rtx (set_src,
  				      SET_DEST (setcc_set),
  				      SET_SRC (setcc_set));
      }
    else
!     setcc = NULL_RTX;

!   new = simplify_replace_rtx (set_src, from, src);

    /* If no simplification can be made, then try the next
       register.  */
!   if (rtx_equal_p (new, SET_SRC (set)))
      return 0;

    /* If this is now a no-op delete it, otherwise this must be a valid insn.  */
*************** cprop_insn (insn, alter_jumps)
*** 4235,4240 ****
--- 4236,4243 ----
  		  print_rtl (gcse_file, src);
  		  fprintf (gcse_file, "\n");
  		}
+ 	      if (INSN_DELETED_P (insn))
+ 		return 1;
  	    }
  	}
        else if (GET_CODE (src) == REG
*************** local_cprop_pass (alter_jumps)
*** 4477,4482 ****
--- 4480,4487 ----
  		    changed = true;
  		    break;
  		  }
+ 	      if (INSN_DELETED_P (insn))
+ 		break;
  	    }
  	  while (reg_use_count);
  	}


/* PR optimization/13031  */
/* The following code used to ICE on alphaev67-*-* at -O2 with an
   unrecognizable instruction, caused by local register allocation
   substituting a register for a constant in a conditional branch.  */

void emit(int, int);
int f(void);
static int signals[5];

static inline void select(int sel, void *klass)
{
  emit(klass ? 0 : f(), signals[sel ? 0 : 1]);
}

void all(void *gil, void *l, void *icon)
{
  while (l)
    if (icon)
      select(0, gil);
}


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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