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]

Sibcall tweek


Hi,
the following testcase
/* { dg-do compile { target "i?86-*-*" } } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-not "call" } } */
void q()
{ int a,b;
  if (a>3)
    a=5;
  t();
  if (a>3)
    b=5;
}
fails because the second comparison is not elliminated by dead code removal
because it sets flag register that is used by the first operand.  It is easy
enought to deal with this special case in sibcall.c

Bootstrapped/regtested i386 together with the previous patch.
Honza

Wed May 21 23:22:42 CEST 2003  Jan HUbicka  <jh@suse.cz>
	* sibcall.c (skip_dead_hard_reg_sets): New function
	(call_ends_block_p): Use it.
	* flow.c (mark_regs_live_at_end): Make global
	* basic-block.h (mark_regs_live_at_end): Declare.
*** /root/unit/gcc.old/gcc/gcc/sibcall.c	Tue Dec 24 09:30:31 2002
--- sibcall.c	Wed May 21 15:24:24 2003
*************** static rtx skip_use_of_return_value	PARA
*** 46,51 ****
--- 46,52 ----
  static rtx skip_stack_adjustment	PARAMS ((rtx));
  static rtx skip_pic_restore		PARAMS ((rtx));
  static rtx skip_jump_insn		PARAMS ((rtx));
+ static rtx skip_dead_hard_reg_sets	PARAMS ((rtx));
  static int call_ends_block_p		PARAMS ((rtx, rtx));
  static int uses_addressof		PARAMS ((rtx));
  static int sequence_uses_addressof	PARAMS ((rtx));
*************** skip_stack_adjustment (orig_insn)
*** 292,297 ****
--- 293,334 ----
    return orig_insn;
  }
  
+ /* Simplifying the control flow graph often leads to the dead sets of
+    flags.  delete_trivially_dead_insns does not remove such sets as dead
+    when flags are used elsewhere in the function and they are normally 
+    removed in the liveness pass.  It is easy to determine the special case
+    of sibling calls here.  */
+ 
+ static rtx
+ skip_dead_hard_reg_sets (orig_insn)
+      rtx orig_insn;
+ {
+   rtx insn = orig_insn, set = NULL_RTX;
+   regset_head regs_live_head;
+   regset regs_live;
+ 
+   regs_live = INITIALIZE_REG_SET (regs_live_head);
+   mark_regs_live_at_end (regs_live);
+ 
+   while (orig_insn == insn)
+     {
+       insn = next_nonnote_insn (orig_insn);
+ 
+       if (insn)
+ 	set = single_set (insn);
+ 
+       if (insn
+ 	  && set
+ 	  && GET_CODE (SET_DEST (set)) == REG
+ 	  && REGNO (SET_DEST (set)) < FIRST_PSEUDO_REGISTER
+ 	  && !REGNO_REG_SET_P (regs_live, REGNO (SET_DEST (set)))
+ 	  && !side_effects_p (SET_SRC (set)))
+ 	orig_insn = insn;
+      }
+   FREE_REG_SET (regs_live);
+ 
+   return orig_insn;
+ }
+ 
  /* If the first real insn after ORIG_INSN sets the pic register,
     return it.  Otherwise return ORIG_INSN.  */
  
*************** call_ends_block_p (insn, end)
*** 367,372 ****
--- 404,414 ----
    if (insn == end)
      return 1;
  
+   /* Skip possible dead garbage at the end of block.  */
+   insn = skip_dead_hard_reg_sets (insn);
+   if (insn == end)
+     return 1;
+ 
    /* Skip over a CLOBBER of the return value as a hard reg.  */
    insn = skip_use_of_return_value (insn, CLOBBER);
    if (insn == end)
*** /root/unit/gcc.old/gcc/gcc/flow.c	Sat May  3 16:25:21 2003
--- flow.c	Wed May 21 15:07:01 2003
*************** static void verify_local_live_at_start	P
*** 292,298 ****
  static void notice_stack_pointer_modification_1 PARAMS ((rtx, rtx, void *));
  static void notice_stack_pointer_modification PARAMS ((rtx));
  static void mark_reg			PARAMS ((rtx, void *));
! static void mark_regs_live_at_end	PARAMS ((regset));
  static int set_phi_alternative_reg      PARAMS ((rtx, int, int, void *));
  static void calculate_global_regs_live	PARAMS ((sbitmap, sbitmap, int));
  static void propagate_block_delete_insn PARAMS ((rtx));
--- 292,297 ----
  static void notice_stack_pointer_modification_1 PARAMS ((rtx, rtx, void *));
  static void notice_stack_pointer_modification PARAMS ((rtx));
  static void mark_reg			PARAMS ((rtx, void *));
  static int set_phi_alternative_reg      PARAMS ((rtx, int, int, void *));
  static void calculate_global_regs_live	PARAMS ((sbitmap, sbitmap, int));
  static void propagate_block_delete_insn PARAMS ((rtx));
*************** mark_reg (reg, xset)
*** 978,984 ****
  /* Mark those regs which are needed at the end of the function as live
     at the end of the last basic block.  */
  
! static void
  mark_regs_live_at_end (set)
       regset set;
  {
--- 978,984 ----
  /* Mark those regs which are needed at the end of the function as live
     at the end of the last basic block.  */
  
! void
  mark_regs_live_at_end (set)
       regset set;
  {
*** /root/unit/gcc.old/gcc/gcc/basic-block.h	Wed Apr 23 16:05:11 2003
--- basic-block.h	Wed May 21 15:28:24 2003
*************** extern void alloc_aux_for_edge		PARAMS (
*** 582,587 ****
--- 582,588 ----
  extern void alloc_aux_for_edges		PARAMS ((int));
  extern void clear_aux_for_edges		PARAMS ((void));
  extern void free_aux_for_edges		PARAMS ((void));
+ extern void mark_regs_live_at_end	PARAMS ((regset));
  
  /* This function is always defined so it can be called from the
     debugger, and it is declared extern so we don't get warnings about


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