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]

unshare_all_rtl missed some rtl



The m68k port has a (broken) pattern that looks like this:

(define_insn "divmodsi4"
  [(set (match_operand:SI 0 "general_operand" "=d")
	(div:SI (match_operand:SI 1 "general_operand" "0")
		(match_operand:SI 2 "general_src_operand" "dmSTK")))
   (set (match_operand:SI 3 "general_operand" "=d")
	(mod:SI (match_dup 1) (match_dup 2)))]
  "TARGET_68020 && !TARGET_5200"
  "*
{
  if (find_reg_note (insn, REG_UNUSED, operands[3]))
    return \"divs%.l %2,%0\";
  else
    return \"divsl%.l %2,%3:%0\";
}")

and various test-cases were failing because:

- the constraint allows a memory operand, like an incoming argument; 
- the rtx for incoming arguments are shared between the DECL_RTL of
  the function's arguments as trees and the actual rtl of the
  function;
- these rtx are (mem ...) and are therefore _not_ shared inside the
  rtl of the function;
- what would happen is that with -O0, in a function like 

  int dodiv (int a, int b) { return a / b; }

  you would get a divmodsi4 expansion with 'a' and 'b' as operands 1
  and 2; then these would be unshared; then the first instance of 'a'
  and 'b' in the pattern would be substituted by instantiate_decls
  (because it is shared with the DECL_RTL of the arguments)
  then instantiate_virtual_regs would substitute 'a' everywhere in the
  pattern, notice it had been changed, and try to re-recognise it,
  which would fail because 'b' had not been substituted for the second
  time it was used.

This patch fixes one of the problems by not sharing RTL between
function parameters and RTL of the function.  It also does some
tidying up.  I have checked it on m68k and it fixes several
test failures.  It was suggested by Jim Wilson (about a month ago).

Is it OK to commit?


Of course, this wouldn't have been happening if the m68k port had used
register_operand instead of general_operand.  I will soon be
submitting a much more extensive patch to change this.  The fix below
is still a good idea because one day someone will write some huge
pattern "yeah, I wanted to expand printf() inline" and will trip over
this.

-- 
- Geoffrey Keating <geoffk@cygnus.com>

===File ~geoffkc/patches/egcs-manymem-1.patch===============
md5sum: 3c90566426c14d0f 50cc4f33e479b20c 537996
Index: egcs/gcc/ChangeLog
0a
Sat Jan  8 17:15:04 2000  Geoffrey Keating  <geoffk@makita.cygnus.com>

	* emit-rtl.c (unshare_all_rtl): Unshare virtual parameters too.
	Use unshare_all_rtl_1.
	(unshare_all_rtl_again): New function.
	(unshare_all_rtl_1): New function split out of unshare_all_rtl.

	* function.c (purge_addressof_1): Use unshare_all_rtl_again
	rather than resetting the 'used' flags ourself.

	* toplev.c (rest_of_compilation): Add current_function_decl
	to the unshare_all_rtl call.
	* tree.h: Prototype unshare_all_rtl.
	* rtl.h: Prototype unshare_all_rtl_again here.

.
Changed files:
egcs/gcc/ChangeLog
egcs/gcc/emit-rtl.c
egcs/gcc/function.c
egcs/gcc/integrate.c
egcs/gcc/rtl.h
egcs/gcc/toplev.c
egcs/gcc/tree.h
md5sum: 8053d8596b25820f 46b5fea988ff2b3b 105985
*** /bluey/co/egcs-mainline/egcs/gcc/emit-rtl.c	Tue Dec 28 12:21:13 1999
--- egcs/gcc/emit-rtl.c	Sat Jan  8 17:19:40 2000
*************** static rtx make_jump_insn_raw		PROTO((rt
*** 170,175 ****
--- 170,176 ----
  static rtx make_call_insn_raw		PROTO((rtx));
  static rtx find_line_note		PROTO((rtx));
  static void mark_sequence_stack         PROTO((struct sequence_stack *));
+ static void unshare_all_rtl_1		PROTO((rtx));
  
  /* There are some RTL codes that require special attention; the generation
     functions do the raw handling.  If you add to this list, modify
*************** free_emit_status (f)
*** 1601,1623 ****
    f->emit = NULL;
  }
  
! /* Go through all the RTL insn bodies and copy any invalid shared structure.
!    It does not work to do this twice, because the mark bits set here
!    are not cleared afterwards.  */
  
  void
! unshare_all_rtl (insn)
!      register rtx insn;
  {
!   for (; insn; insn = NEXT_INSN (insn))
!     if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
! 	|| GET_CODE (insn) == CALL_INSN)
!       {
! 	PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
! 	REG_NOTES (insn) = copy_rtx_if_shared (REG_NOTES (insn));
! 	LOG_LINKS (insn) = copy_rtx_if_shared (LOG_LINKS (insn));
!       }
  
    /* Make sure the addresses of stack slots found outside the insn chain
       (such as, in DECL_RTL of a variable) are not shared
       with the insn chain.
--- 1602,1626 ----
    f->emit = NULL;
  }
  
! /* Go through all the RTL insn bodies and copy any invalid shared 
!    structure.  This routine should only be called once.  */
  
  void
! unshare_all_rtl (fndecl, insn)
!      tree fndecl;
!      rtx insn;
  {
!   tree decl;
! 
!   /* Make sure that virtual parameters are not shared.  */
!   for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl))
!     {
!       copy_rtx_if_shared (DECL_RTL (decl));
!     }
  
+   /* 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
       with the insn chain.
*************** unshare_all_rtl (insn)
*** 1625,1632 ****
       This special care is necessary when the stack slot MEM does not
       actually appear in the insn chain.  If it does appear, its address
       is unshared from all else at that point.  */
- 
    copy_rtx_if_shared (stack_slot_list);
  }
  
  /* Mark ORIG as in use, and return a copy of it if it was already in use.
--- 1628,1669 ----
       This special care is necessary when the stack slot MEM does not
       actually appear in the insn chain.  If it does appear, its address
       is unshared from all else at that point.  */
    copy_rtx_if_shared (stack_slot_list);
+ }
+ 
+ /* Go through all the RTL insn bodies and copy any invalid shared 
+    structure, again.  This is a fairly expensive thing to do so it
+    should be done sparingly.  */
+ 
+ void
+ unshare_all_rtl_again (insn)
+      rtx insn;
+ {
+   rtx p;
+   for (p = insn; p; p = NEXT_INSN (p))
+     if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
+       {
+ 	reset_used_flags (PATTERN (p));
+ 	reset_used_flags (REG_NOTES (p));
+ 	reset_used_flags (LOG_LINKS (p));
+       }
+   unshare_all_rtl_1 (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 (insn)
+      rtx insn;
+ {
+   for (; insn; insn = NEXT_INSN (insn))
+     if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+       {
+ 	PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
+ 	REG_NOTES (insn) = copy_rtx_if_shared (REG_NOTES (insn));
+ 	LOG_LINKS (insn) = copy_rtx_if_shared (LOG_LINKS (insn));
+       }
  }
  
  /* Mark ORIG as in use, and return a copy of it if it was already in use.
md5sum: 05d7d61afe467419 babe70ada008e89c 216132
*** /bluey/co/egcs-mainline/egcs/gcc/function.c	Mon Jan  3 15:34:55 2000
--- egcs/gcc/function.c	Sat Jan  8 17:12:21 2000
*************** static boolean
*** 2970,2982 ****
  
  		  /* Make sure to unshare any shared rtl that store_bit_field
  		     might have created.  */
! 		  for (p = get_insns(); p; p = NEXT_INSN (p))
! 		    {
! 		      reset_used_flags (PATTERN (p));
! 		      reset_used_flags (REG_NOTES (p));
! 		      reset_used_flags (LOG_LINKS (p));
! 		    }
! 		  unshare_all_rtl (get_insns ());
  
  		  seq = gen_sequence ();
  		  end_sequence ();
--- 2970,2976 ----
  
  		  /* Make sure to unshare any shared rtl that store_bit_field
  		     might have created.  */
! 		  unshare_all_rtl_again (get_insns ());
  
  		  seq = gen_sequence ();
  		  end_sequence ();
md5sum: 80aec68dcf2a4980 80aec68dcf2a4980 86797
md5sum: 282ae4586b820548 b534cd3561b6e8ac 69317
*** /bluey/co/egcs-mainline/egcs/gcc/rtl.h	Tue Dec 28 12:21:15 1999
--- egcs/gcc/rtl.h	Sat Jan  8 17:12:21 2000
*************** extern void reverse_comparison			PROTO (
*** 1444,1450 ****
  extern void set_new_first_and_last_insn		PROTO ((rtx, rtx));
  extern void set_new_first_and_last_label_num	PROTO ((int, int));
  extern void set_new_last_label_num		PROTO ((int));
! extern void unshare_all_rtl			PROTO ((rtx));
  extern void set_last_insn			PROTO ((rtx));
  extern void link_cc0_insns			PROTO ((rtx));
  extern void add_insn				PROTO ((rtx));
--- 1444,1450 ----
  extern void set_new_first_and_last_insn		PROTO ((rtx, rtx));
  extern void set_new_first_and_last_label_num	PROTO ((int, int));
  extern void set_new_last_label_num		PROTO ((int));
! extern void unshare_all_rtl_again		PROTO ((rtx));
  extern void set_last_insn			PROTO ((rtx));
  extern void link_cc0_insns			PROTO ((rtx));
  extern void add_insn				PROTO ((rtx));
md5sum: c65334929ead051d a87504eef523d8c4 148305
*** /bluey/co/egcs-mainline/egcs/gcc/toplev.c	Tue Dec 28 12:21:15 1999
--- egcs/gcc/toplev.c	Sat Jan  8 17:12:21 2000
*************** rest_of_compilation (decl)
*** 2948,2954 ****
  
    /* Copy any shared structure that should not be shared.  */
  
!   unshare_all_rtl (insns);
  
    init_EXPR_INSN_LIST_cache ();
  
--- 2948,2954 ----
  
    /* Copy any shared structure that should not be shared.  */
  
!   unshare_all_rtl (current_function_decl, insns);
  
    init_EXPR_INSN_LIST_cache ();
  
md5sum: 3f02da04d06b9e78 d7ce262c4357c793 98748
*** /bluey/co/egcs-mainline/egcs/gcc/tree.h	Mon Jan  3 12:11:36 2000
--- egcs/gcc/tree.h	Sat Jan  8 17:12:21 2000
*************** extern int aggregate_value_p		PROTO ((tr
*** 2379,2384 ****
--- 2379,2385 ----
  extern tree reorder_blocks		PROTO ((tree,
  						struct rtx_def *));
  extern void free_temps_for_rtl_expr	PROTO ((tree));
+ extern void unshare_all_rtl		PROTO ((tree, struct rtx_def *));
  extern void instantiate_virtual_regs	PROTO ((tree, struct rtx_def *));
  extern int max_parm_reg_num		PROTO ((void));
  extern void push_function_context	PROTO ((void));
============================================================

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