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]

gcse crash fix (Was: Re: gcc-3_0 march=athlon && (-Os || -ggdb))


> BOOT_CFLAGS="-g -O -Os -march=athlon"
> 
> it all goes horribly wrong:
> 
> 
> stage1/xgcc -Bstage1/ -B/u0/alasdair/experimental/i386-netbsd/bin/ -c  -DIN_GCC
>    -g -O -Os -march=athlon -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wtraditional -pedantic -Wno-long-long  -DHAVE_CONFIG_H -DGENERATOR_FILE    -I. -I. -I../../egcs/gcc -I../../egcs/gcc/. -I../../egcs/gcc/config -I../../egcs/gcc/../include ../../egcs/gcc/genattrtab.c
> ../../egcs/gcc/genattrtab.c: In function `evaluate_eq_attr':
> ../../egcs/gcc/genattrtab.c:2960: RTL check: expected code `set', have `parallel' in handle_avail_expr, at gcse.c:3493
> Please submit a full bug report,
> with preprocessed source if appropriate.
> See <URL:http://www.gnu.org/software/gcc/bugs.html> for instructions.

This is unrelated bug related to Richard Kenner's gcse changes. GCSE pass
now do CSE over expressions that are valid as (insn (set (reg) (expr))).
On i386 we do use clobber of flags for addsi pattern, but trick is that
we also do have lea pattern able to do that without clobber. GCSE notices
that and does CSE, but fails to finish the transformation, as handle_avail_expr
is not ready for that.

I've updated it to use signle_set call. In longer term we should GCSE all
insns and only customize PRE for insns needing clobbers of hard registers
and finally we should do limited life analysis over hard registers to be
able to do motion of these insns together with their clobbers.

This is first step to fix the bug. It don't seems to be present in 3.0

Thanks for bugreport!

Sun Jun  3 00:52:04 CEST 2001  Jan Hubicka  <jh@suse.cz>
	* gcse.c (handle_avail_expr): Be prepared to handle single_set
	parallels.
Index: gcse.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/gcse.c,v
retrieving revision 1.131
diff -c -3 -p -r1.131 gcse.c
*** gcse.c	2001/05/18 13:43:27	1.131
--- gcse.c	2001/06/02 22:48:50
*************** handle_avail_expr (insn, expr)
*** 3472,3478 ****
       rtx insn;
       struct expr *expr;
  {
!   rtx pat, insn_computes_expr;
    rtx to;
    struct reg_set *this_reg;
    int found_setting, use_src;
--- 3472,3478 ----
       rtx insn;
       struct expr *expr;
  {
!   rtx pat, insn_computes_expr, expr_set;
    rtx to;
    struct reg_set *this_reg;
    int found_setting, use_src;
*************** handle_avail_expr (insn, expr)
*** 3483,3488 ****
--- 3483,3491 ----
    insn_computes_expr = computing_insn (expr, insn);
    if (insn_computes_expr == NULL)
      return 0;
+   expr_set = single_set (insn_computes_expr);
+   if (!expr_set)
+     abort ();
  
    found_setting = 0;
    use_src = 0;
*************** handle_avail_expr (insn, expr)
*** 3490,3501 ****
    /* At this point we know only one computation of EXPR outside of this
       block reaches this insn.  Now try to find a register that the
       expression is computed into.  */
!   if (GET_CODE (SET_SRC (PATTERN (insn_computes_expr))) == REG)
      {
        /* This is the case when the available expression that reaches
  	 here has already been handled as an available expression.  */
        unsigned int regnum_for_replacing
! 	= REGNO (SET_SRC (PATTERN (insn_computes_expr)));
  
        /* If the register was created by GCSE we can't use `reg_set_table',
  	 however we know it's set only once.  */
--- 3493,3504 ----
    /* At this point we know only one computation of EXPR outside of this
       block reaches this insn.  Now try to find a register that the
       expression is computed into.  */
!   if (GET_CODE (SET_SRC (expr_set)) == REG)
      {
        /* This is the case when the available expression that reaches
  	 here has already been handled as an available expression.  */
        unsigned int regnum_for_replacing
! 	= REGNO (SET_SRC (expr_set));
  
        /* If the register was created by GCSE we can't use `reg_set_table',
  	 however we know it's set only once.  */
*************** handle_avail_expr (insn, expr)
*** 3514,3520 ****
    if (!found_setting)
      {
        unsigned int regnum_for_replacing
! 	= REGNO (SET_DEST (PATTERN (insn_computes_expr)));
  
        /* This shouldn't happen.  */
        if (regnum_for_replacing >= max_gcse_regno)
--- 3517,3523 ----
    if (!found_setting)
      {
        unsigned int regnum_for_replacing
! 	= REGNO (SET_DEST (expr_set));
  
        /* This shouldn't happen.  */
        if (regnum_for_replacing >= max_gcse_regno)
*************** handle_avail_expr (insn, expr)
*** 3533,3541 ****
      {
        pat = PATTERN (insn);
        if (use_src)
! 	to = SET_SRC (PATTERN (insn_computes_expr));
        else
! 	to = SET_DEST (PATTERN (insn_computes_expr));
        changed = validate_change (insn, &SET_SRC (pat), to, 0);
  
        /* We should be able to ignore the return code from validate_change but
--- 3536,3544 ----
      {
        pat = PATTERN (insn);
        if (use_src)
! 	to = SET_SRC (expr_set);
        else
! 	to = SET_DEST (expr_set);
        changed = validate_change (insn, &SET_SRC (pat), to, 0);
  
        /* We should be able to ignore the return code from validate_change but
*************** handle_avail_expr (insn, expr)
*** 3563,3577 ****
  	 replace all uses of REGB with REGN.  */
        rtx new_insn;
  
!       to = gen_reg_rtx (GET_MODE (SET_DEST (PATTERN (insn_computes_expr))));
  
        /* Generate the new insn.  */
        /* ??? If the change fails, we return 0, even though we created
  	 an insn.  I think this is ok.  */
        new_insn
  	= emit_insn_after (gen_rtx_SET (VOIDmode, to,
! 					SET_DEST (PATTERN
! 						  (insn_computes_expr))),
  			   insn_computes_expr);
  
        /* Keep block number table up to date.  */
--- 3566,3579 ----
  	 replace all uses of REGB with REGN.  */
        rtx new_insn;
  
!       to = gen_reg_rtx (GET_MODE (SET_DEST (expr_set)));
  
        /* Generate the new insn.  */
        /* ??? If the change fails, we return 0, even though we created
  	 an insn.  I think this is ok.  */
        new_insn
  	= emit_insn_after (gen_rtx_SET (VOIDmode, to,
! 					SET_DEST (expr_set)),
  			   insn_computes_expr);
  
        /* Keep block number table up to date.  */


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