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]

ifcvt RTL sharing patch updated


Hi,
I tought I sent this one already, but apparently I didn't, so here is
updated patch for RTL sharing problems, so it apply to current tree and
pass testing on i686-pc-gnu-linux and x86_64-linux.
It contains also the checking bits but they are disabled so we are not
immediately bit by the latent problems elsewhere in the compiler.
OK?

Honza

2003-11-09  Jan Hubicka  <jh@suse.cz>
	* emit-rtl.c (set_used_flags): New.
	(verify_rtx_sharing, verify_rtl_sharing): New.
	(unshare_all_rtl_1): Rename to....
	(unshare_all_rtl_in_chain): ... this one; make static.
	(copy_rtx_if_shared): LABEL_REF chan be shared.
	* ifcvt.c (unshare_ifcvt_sequence): New.
	(noce_try_move, noce_try_store_flag, noce_try_store_flag_constants,
	noce_try_addcc, noce_try_addcc, noce_try_store_flag_mask,
	noce_try_cmove, noce_try_store_flag_mask, noce_try_minmax,
	noce_try_abs, noce_process_if_block, find_cond_trap
	* rtl.h (verify_rtl_sharing, set_used_flags, unshare_all_rtl_in_chain):
	Declare.
	* toplev.c (rest_of_compilation): Check for RTL sharing.
Index: emit-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v
retrieving revision 1.352
diff -c -3 -p -r1.352 emit-rtl.c
*** emit-rtl.c	4 Nov 2003 09:14:18 -0000	1.352
--- emit-rtl.c	9 Nov 2003 15:19:37 -0000
*************** static rtx make_jump_insn_raw (rtx);
*** 180,186 ****
  static rtx make_call_insn_raw (rtx);
  static rtx find_line_note (rtx);
  static rtx change_address_1 (rtx, enum machine_mode, rtx, int);
- static void unshare_all_rtl_1 (rtx);
  static void unshare_all_decls (tree);
  static void reset_used_decls (tree);
  static void mark_label_nuses (rtx);
--- 180,185 ----
*************** unshare_all_rtl (tree fndecl, rtx insn)
*** 2448,2454 ****
    unshare_all_decls (DECL_INITIAL (fndecl));
  
    /* Unshare just about everything else.  */
!   unshare_all_rtl_1 (insn);
  
    /* Make sure the addresses of stack slots found outside the insn chain
       (such as, in DECL_RTL of a variable) are not shared
--- 2447,2453 ----
    unshare_all_decls (DECL_INITIAL (fndecl));
  
    /* Unshare just about everything else.  */
!   unshare_all_rtl_in_chain (insn);
  
    /* Make sure the addresses of stack slots found outside the insn chain
       (such as, in DECL_RTL of a variable) are not shared
*************** unshare_all_rtl_again (rtx insn)
*** 2490,2500 ****
    unshare_all_rtl (cfun->decl, insn);
  }
  
  /* Go through all the RTL insn bodies and copy any invalid shared structure.
     Assumes the mark bits are cleared at entry.  */
  
! static void
! unshare_all_rtl_1 (rtx insn)
  {
    for (; insn; insn = NEXT_INSN (insn))
      if (INSN_P (insn))
--- 2489,2626 ----
    unshare_all_rtl (cfun->decl, insn);
  }
  
+ /* Check that ORIG is not marked when it should not be and mark ORIG as in use,
+    Recursively does the same for subexpressions.  */
+ 
+ static void
+ verify_rtx_sharing (rtx orig, rtx insn)
+ {
+   rtx x = orig;
+   int i;
+   enum rtx_code code;
+   const char *format_ptr;
+ 
+   if (x == 0)
+     return;
+ 
+   code = GET_CODE (x);
+ 
+   /* These types may be freely shared.  */
+ 
+   switch (code)
+     {
+     case REG:
+     case QUEUED:
+     case CONST_INT:
+     case CONST_DOUBLE:
+     case CONST_VECTOR:
+     case SYMBOL_REF:
+     case LABEL_REF:
+     case CODE_LABEL:
+     case PC:
+     case CC0:
+     case SCRATCH:
+       /* SCRATCH must be shared because they represent distinct values.  */
+       return;
+ 
+     case CONST:
+       /* CONST can be shared if it contains a SYMBOL_REF.  If it contains
+ 	 a LABEL_REF, it isn't sharable.  */
+       if (GET_CODE (XEXP (x, 0)) == PLUS
+ 	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+ 	  && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
+ 	return;
+       break;
+ 
+     case MEM:
+       /* A MEM is allowed to be shared if its address is constant.  */
+       if (CONSTANT_ADDRESS_P (XEXP (x, 0))
+ 	  || reload_completed || reload_in_progress)
+ 	return;
+ 
+       break;
+ 
+     default:
+       break;
+     }
+ 
+   /* This rtx may not be shared.  If it has already been seen,
+      replace it with a copy of itself.  */
+ 
+   if (RTX_FLAG (x, used))
+     {
+       error ("Invalid rtl sharing found in the insn");
+       debug_rtx (insn);
+       error ("Shared rtx");
+       debug_rtx (x);
+       abort ();
+     }
+   RTX_FLAG (x, used) = 1;
+ 
+   /* Now scan the subexpressions recursively. */
+ 
+   format_ptr = GET_RTX_FORMAT (code);
+ 
+   for (i = 0; i < GET_RTX_LENGTH (code); i++)
+     {
+       switch (*format_ptr++)
+ 	{
+ 	case 'e':
+ 	  verify_rtx_sharing (XEXP (x, i), insn);
+ 	  break;
+ 
+ 	case 'E':
+ 	  if (XVEC (x, i) != NULL)
+ 	    {
+ 	      int j;
+ 	      int len = XVECLEN (x, i);
+ 
+ 	      for (j = 0; j < len; j++)
+ 		{
+ 		  /* We allow sharing of ASM_OPERANDS inside single instruction.  */
+ 		  if (j && GET_CODE (XVECEXP (x, i, j)) == SET
+ 		      && GET_CODE (SET_SRC (XVECEXP (x, i, j))) == ASM_OPERANDS)
+ 		    verify_rtx_sharing (SET_DEST (XVECEXP (x, i, j)), insn);
+ 		  else
+ 		    verify_rtx_sharing (XVECEXP (x, i, j), insn);
+ 		}
+ 	    }
+ 	  break;
+ 	}
+     }
+   return;
+ }
+ 
+ /* Go through all the RTL insn bodies and chec that there is no inexpected
+    sharing in between the subexpressions.  */
+ 
+ void
+ verify_rtl_sharing (void)
+ {
+   rtx p;
+ 
+   for (p = get_insns (); p; p = NEXT_INSN (p))
+     if (INSN_P (p))
+       {
+ 	reset_used_flags (PATTERN (p));
+ 	reset_used_flags (REG_NOTES (p));
+ 	reset_used_flags (LOG_LINKS (p));
+       }
+ 
+   for (p = get_insns (); p; p = NEXT_INSN (p))
+     if (INSN_P (p))
+       {
+ 	verify_rtx_sharing (PATTERN (p), p);
+ 	verify_rtx_sharing (REG_NOTES (p), p);
+ 	verify_rtx_sharing (LOG_LINKS (p), p);
+       }
+ }
+ 
  /* Go through all the RTL insn bodies and copy any invalid shared structure.
     Assumes the mark bits are cleared at entry.  */
  
! void
! unshare_all_rtl_in_chain (rtx insn)
  {
    for (; insn; insn = NEXT_INSN (insn))
      if (INSN_P (insn))
*************** copy_rtx_if_shared (rtx orig)
*** 2666,2671 ****
--- 2792,2798 ----
      case CONST_DOUBLE:
      case CONST_VECTOR:
      case SYMBOL_REF:
+     case LABEL_REF:
      case CODE_LABEL:
      case PC:
      case CC0:
*************** reset_used_flags (rtx x)
*** 2798,2803 ****
--- 2925,2993 ----
  	case 'E':
  	  for (j = 0; j < XVECLEN (x, i); j++)
  	    reset_used_flags (XVECEXP (x, i, j));
+ 	  break;
+ 	}
+     }
+ }
+ 
+ /* Set all the USED bits in X to allow copy_rtx_if_shared to be used
+    to look for shared sub-parts.  */
+ 
+ void
+ set_used_flags (rtx x)
+ {
+   int i, j;
+   enum rtx_code code;
+   const char *format_ptr;
+ 
+   if (x == 0)
+     return;
+ 
+   code = GET_CODE (x);
+ 
+   /* These types may be freely shared so we needn't do any resetting
+      for them.  */
+ 
+   switch (code)
+     {
+     case REG:
+     case QUEUED:
+     case CONST_INT:
+     case CONST_DOUBLE:
+     case CONST_VECTOR:
+     case SYMBOL_REF:
+     case CODE_LABEL:
+     case PC:
+     case CC0:
+       return;
+ 
+     case INSN:
+     case JUMP_INSN:
+     case CALL_INSN:
+     case NOTE:
+     case LABEL_REF:
+     case BARRIER:
+       /* The chain of insns is not being copied.  */
+       return;
+ 
+     default:
+       break;
+     }
+ 
+   RTX_FLAG (x, used) = 1;
+ 
+   format_ptr = GET_RTX_FORMAT (code);
+   for (i = 0; i < GET_RTX_LENGTH (code); i++)
+     {
+       switch (*format_ptr++)
+ 	{
+ 	case 'e':
+ 	  set_used_flags (XEXP (x, i));
+ 	  break;
+ 
+ 	case 'E':
+ 	  for (j = 0; j < XVECLEN (x, i); j++)
+ 	    set_used_flags (XVECEXP (x, i, j));
  	  break;
  	}
      }
Index: ifcvt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ifcvt.c,v
retrieving revision 1.129
diff -c -3 -p -r1.129 ifcvt.c
*** ifcvt.c	2 Nov 2003 13:56:40 -0000	1.129
--- ifcvt.c	9 Nov 2003 15:19:38 -0000
*************** noce_emit_move_insn (rtx x, rtx y)
*** 700,705 ****
--- 700,715 ----
  		   GET_MODE_BITSIZE (inmode));
  }
  
+ /* Unshare sequence SEQ produced by if conversion.  We care to mark
+    all arguments that may be shared with outer instruction stream.  */
+ static void
+ unshare_ifcvt_sequence (struct noce_if_info *if_info, rtx seq)
+ {
+   set_used_flags (if_info->x);
+   set_used_flags (if_info->cond);
+   unshare_all_rtl_in_chain (seq);
+ }
+ 
  /* Convert "if (a != b) x = a; else x = b" into "x = a" and
     "if (a == b) x = a; else x = b" into "x = b".  */
  
*************** noce_try_move (struct noce_if_info *if_i
*** 734,739 ****
--- 744,750 ----
  	  start_sequence ();
  	  noce_emit_move_insn (if_info->x, y);
  	  seq = get_insns ();
+ 	  unshare_ifcvt_sequence (if_info, seq);
  	  end_sequence ();
  	  emit_insn_before_setloc (seq, if_info->jump,
  				   INSN_LOCATOR (if_info->insn_a));
*************** noce_try_store_flag (struct noce_if_info
*** 777,782 ****
--- 788,794 ----
  	noce_emit_move_insn (if_info->x, target);
  
        seq = get_insns ();
+       unshare_ifcvt_sequence (if_info, seq);
        end_sequence ();
        emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
  
*************** noce_try_store_flag_constants (struct no
*** 907,912 ****
--- 919,925 ----
  	noce_emit_move_insn (if_info->x, target);
  
        seq = get_insns ();
+       unshare_ifcvt_sequence (if_info, seq);
        end_sequence ();
  
        if (seq_contains_jump (seq))
*************** noce_try_addcc (struct noce_if_info *if_
*** 944,952 ****
  	{
  	  start_sequence ();
  	  target = emit_conditional_add (if_info->x, code,
! 					 XEXP (cond, 0), XEXP (cond, 1),
  					 VOIDmode,
! 					 if_info->b, XEXP (if_info->a, 1),
  					 GET_MODE (if_info->x),
  					 (code == LTU || code == GEU
  					  || code == LEU || code == GTU));
--- 957,967 ----
  	{
  	  start_sequence ();
  	  target = emit_conditional_add (if_info->x, code,
! 					 XEXP (cond, 0),
! 					 XEXP (cond, 1),
  					 VOIDmode,
! 					 if_info->b,
! 					 XEXP (if_info->a, 1),
  					 GET_MODE (if_info->x),
  					 (code == LTU || code == GEU
  					  || code == LEU || code == GTU));
*************** noce_try_addcc (struct noce_if_info *if_
*** 956,961 ****
--- 971,977 ----
  		noce_emit_move_insn (if_info->x, target);
  
  	      seq = get_insns ();
+ 	      unshare_ifcvt_sequence (if_info, seq);
  	      end_sequence ();
  	      emit_insn_before_setloc (seq, if_info->jump,
  				      INSN_LOCATOR (if_info->insn_a));
*************** noce_try_addcc (struct noce_if_info *if_
*** 994,999 ****
--- 1010,1016 ----
  		noce_emit_move_insn (if_info->x, target);
  
  	      seq = get_insns ();
+ 	      unshare_ifcvt_sequence (if_info, seq);
  	      end_sequence ();
  
  	      if (seq_contains_jump (seq))
*************** noce_try_store_flag_mask (struct noce_if
*** 1037,1043 ****
  				     reversep, -1);
        if (target)
          target = expand_simple_binop (GET_MODE (if_info->x), AND,
! 				      if_info->x, target, if_info->x, 0,
  				      OPTAB_WIDEN);
  
        if (target)
--- 1054,1061 ----
  				     reversep, -1);
        if (target)
          target = expand_simple_binop (GET_MODE (if_info->x), AND,
! 				      if_info->x,
! 				      target, if_info->x, 0,
  				      OPTAB_WIDEN);
  
        if (target)
*************** noce_try_store_flag_mask (struct noce_if
*** 1046,1051 ****
--- 1064,1070 ----
  	    noce_emit_move_insn (if_info->x, target);
  
  	  seq = get_insns ();
+ 	  unshare_ifcvt_sequence (if_info, seq);
  	  end_sequence ();
  
  	  if (seq_contains_jump (seq))
*************** noce_try_cmove (struct noce_if_info *if_
*** 1143,1148 ****
--- 1162,1168 ----
  	    noce_emit_move_insn (if_info->x, target);
  
  	  seq = get_insns ();
+ 	  unshare_ifcvt_sequence (if_info, seq);
  	  end_sequence ();
  	  emit_insn_before_setloc (seq, if_info->jump,
  				  INSN_LOCATOR (if_info->insn_a));
*************** noce_try_cmove_arith (struct noce_if_inf
*** 1260,1266 ****
        if (is_mem)
  	{
            tmp = gen_reg_rtx (GET_MODE (b));
! 	  tmp = emit_insn (gen_rtx_SET (VOIDmode, tmp, b));
  	}
        else if (! insn_b)
  	goto end_seq_and_fail;
--- 1280,1288 ----
        if (is_mem)
  	{
            tmp = gen_reg_rtx (GET_MODE (b));
! 	  tmp = emit_insn (gen_rtx_SET (VOIDmode,
! 				  	tmp,
! 					b));
  	}
        else if (! insn_b)
  	goto end_seq_and_fail;
*************** noce_try_cmove_arith (struct noce_if_inf
*** 1305,1310 ****
--- 1327,1333 ----
      noce_emit_move_insn (x, target);
  
    tmp = get_insns ();
+   unshare_ifcvt_sequence (if_info, tmp);
    end_sequence ();
    emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATOR (if_info->insn_a));
    return TRUE;
*************** noce_try_minmax (struct noce_if_info *if
*** 1550,1555 ****
--- 1573,1579 ----
      noce_emit_move_insn (if_info->x, target);
  
    seq = get_insns ();
+   unshare_ifcvt_sequence (if_info, seq);
    end_sequence ();
  
    if (seq_contains_jump (seq))
*************** noce_try_abs (struct noce_if_info *if_in
*** 1667,1672 ****
--- 1691,1697 ----
      noce_emit_move_insn (if_info->x, target);
  
    seq = get_insns ();
+   unshare_ifcvt_sequence (if_info, seq);
    end_sequence ();
  
    if (seq_contains_jump (seq))
*************** noce_process_if_block (struct ce_if_bloc
*** 1988,1995 ****
    if (orig_x != x)
      {
        start_sequence ();
!       noce_emit_move_insn (copy_rtx (orig_x), x);
        insn_b = get_insns ();
        end_sequence ();
  
        emit_insn_after_setloc (insn_b, test_bb->end, INSN_LOCATOR (insn_a));
--- 2013,2022 ----
    if (orig_x != x)
      {
        start_sequence ();
!       noce_emit_move_insn (orig_x, x);
        insn_b = get_insns ();
+       set_used_flags (orig_x);
+       unshare_all_rtl_in_chain (insn_b);
        end_sequence ();
  
        emit_insn_after_setloc (insn_b, test_bb->end, INSN_LOCATOR (insn_a));
*************** find_cond_trap (basic_block test_bb, edg
*** 2585,2591 ****
      }
  
    /* Attempt to generate the conditional trap.  */
!   seq = gen_cond_trap (code, XEXP (cond, 0), XEXP (cond, 1),
  		       TRAP_CODE (PATTERN (trap)));
    if (seq == NULL)
      return FALSE;
--- 2612,2619 ----
      }
  
    /* Attempt to generate the conditional trap.  */
!   seq = gen_cond_trap (code, XEXP (cond, 0),
! 		       XEXP (cond, 1),
  		       TRAP_CODE (PATTERN (trap)));
    if (seq == NULL)
      return FALSE;
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.437
diff -c -3 -p -r1.437 rtl.h
*** rtl.h	18 Oct 2003 18:45:15 -0000	1.437
--- rtl.h	9 Nov 2003 15:19:39 -0000
*************** extern void delete_insns_since (rtx);
*** 2036,2041 ****
--- 2036,2042 ----
  extern void mark_reg_pointer (rtx, int);
  extern void mark_user_reg (rtx);
  extern void reset_used_flags (rtx);
+ extern void set_used_flags (rtx);
  extern void reorder_insns (rtx, rtx, rtx);
  extern void reorder_insns_nobb (rtx, rtx, rtx);
  extern int get_max_uid (void);
*************** extern void set_new_first_and_last_insn 
*** 2051,2056 ****
--- 2052,2059 ----
  extern void set_new_first_and_last_label_num (int, int);
  extern void set_new_last_label_num (int);
  extern void unshare_all_rtl_again (rtx);
+ extern void unshare_all_rtl_in_chain (rtx);
+ extern void verify_rtl_sharing (void);
  extern void set_first_insn (rtx);
  extern void set_last_insn (rtx);
  extern void link_cc0_insns (rtx);


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