OSDN Git Service

* config/xtensa/xtensa.c (xtensa_init_machine_status): Fix
[pf3gnuchains/gcc-fork.git] / gcc / sibcall.c
index fe76865..a626e15 100644 (file)
@@ -1,5 +1,5 @@
 /* Generic sibling call optimization support
-   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -31,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "basic-block.h"
 #include "output.h"
 #include "except.h"
+#include "tree.h"
 
 /* In case alternate_exit_block contains copy from pseudo, to return value,
    record the pseudo here.  In such case the pseudo must be set to function
@@ -85,7 +86,7 @@ identify_call_return_value (cp, p_hard_return, p_soft_return)
   /* If we didn't get a single hard register (e.g. a parallel), give up.  */
   if (GET_CODE (hard) != REG)
     return 0;
-    
+
   /* Stack adjustment done after call may appear here.  */
   insn = skip_stack_adjustment (insn);
   if (! insn)
@@ -100,7 +101,7 @@ identify_call_return_value (cp, p_hard_return, p_soft_return)
   insn = NEXT_INSN (insn);
   if (! insn)
     return 0;
-  
+
   /* We're looking for a source of the hard return register.  */
   set = single_set (insn);
   if (! set || SET_SRC (set) != hard)
@@ -167,7 +168,7 @@ skip_copy_to_return_value (orig_insn)
 
   /* The destination must be the same as the called function's return
      value to ensure that any return value is put in the same place by the
-     current function and the function we're calling. 
+     current function and the function we're calling.
 
      Further, the source must be the same as the pseudo into which the
      called function's return value was copied.  Otherwise we're returning
@@ -546,14 +547,14 @@ replace_call_placeholder (insn, use)
   else if (use == sibcall_use_normal)
     emit_insns_before (XEXP (PATTERN (insn), 0), insn);
   else
-    abort();
+    abort ();
 
   /* Turn off LABEL_PRESERVE_P for the tail recursion label if it
      exists.  We only had to set it long enough to keep the jump
      pass above from deleting it as unused.  */
   if (XEXP (PATTERN (insn), 3))
     LABEL_PRESERVE_P (XEXP (PATTERN (insn), 3)) = 0;
-  
+
   /* "Delete" the placeholder insn.  */
   remove_insn (insn);
 }
@@ -572,29 +573,25 @@ optimize_sibling_and_tail_recursive_calls ()
 {
   rtx insn, insns;
   basic_block alternate_exit = EXIT_BLOCK_PTR;
-  int current_function_uses_addressof;
+  bool no_sibcalls_this_function = false;
   int successful_sibling_call = 0;
   int replaced_call_placeholder = 0;
   edge e;
 
   insns = get_insns ();
 
-  /* We do not perform these calls when flag_exceptions is true, so this
-     is probably a NOP at the current time.  However, we may want to support
-     sibling and tail recursion optimizations in the future, so let's plan
-     ahead and find all the EH labels.  */
-  find_exception_handler_labels ();
-
-  rebuild_jump_labels (insns);
-  /* We need cfg information to determine which blocks are succeeded
-     only by the epilogue.  */
-  find_basic_blocks (insns, max_reg_num (), 0);
   cleanup_cfg (CLEANUP_PRE_SIBCALL | CLEANUP_PRE_LOOP);
 
   /* If there are no basic blocks, then there is nothing to do.  */
   if (n_basic_blocks == 0)
     return;
 
+  /* If we are using sjlj exceptions, we may need to add a call to
+     _Unwind_SjLj_Unregister at exit of the function.  Which means
+     that we cannot do any sibcall transformations.  */
+  if (USING_SJLJ_EXCEPTIONS && current_function_has_exception_handlers ())
+    no_sibcalls_this_function = true;
+
   return_value_pseudo = NULL_RTX;
 
   /* Find the exit block.
@@ -613,7 +610,7 @@ optimize_sibling_and_tail_recursive_calls ()
 
       /* Walk forwards through the last normal block and see if it
         does nothing except fall into the exit block.  */
-      for (insn = BLOCK_HEAD (n_basic_blocks - 1);
+      for (insn = EXIT_BLOCK_PTR->prev_bb->head;
           insn;
           insn = NEXT_INSN (insn))
        {
@@ -655,7 +652,7 @@ optimize_sibling_and_tail_recursive_calls ()
 
   /* If the function uses ADDRESSOF, we can't (easily) determine
      at this point if the value will end up on the stack.  */
-  current_function_uses_addressof = sequence_uses_addressof (insns);
+  no_sibcalls_this_function |= sequence_uses_addressof (insns);
 
   /* Walk the insn chain and find any CALL_PLACEHOLDER insns.  We need to
      select one of the insn sequences attached to each CALL_PLACEHOLDER.
@@ -679,17 +676,16 @@ optimize_sibling_and_tail_recursive_calls ()
             sibling call optimizations, but not tail recursion.
             Similarly if we use varargs or stdarg since they implicitly
             may take the address of an argument.  */
-         if (current_function_calls_alloca
+         if (current_function_calls_alloca
              || current_function_varargs || current_function_stdarg)
            sibcall = 0;
 
          /* See if there are any reasons we can't perform either sibling or
             tail call optimizations.  We must be careful with stack slots
-            which are live at potential optimization sites.  ??? The first
-            test is overly conservative and should be replaced.  */
-         if (frame_offset
-             /* Can't take address of local var if used by recursive call.  */
-             || current_function_uses_addressof
+            which are live at potential optimization sites.  */
+         if (no_sibcalls_this_function
+             /* ??? Overly conservative.  */
+             || frame_offset
              /* Any function that calls setjmp might have longjmp called from
                 any called function.  ??? We really should represent this
                 properly in the CFG so that this needn't be special cased.  */
@@ -713,8 +709,8 @@ optimize_sibling_and_tail_recursive_calls ()
            successful_sibling_call = 1;
 
          replaced_call_placeholder = 1;
-         replace_call_placeholder (insn, 
-                                   tailrecursion != 0 
+         replace_call_placeholder (insn,
+                                   tailrecursion != 0
                                      ? sibcall_use_tail_recursion
                                      : sibcall != 0
                                         ? sibcall_use_sibcall
@@ -725,13 +721,14 @@ optimize_sibling_and_tail_recursive_calls ()
   if (successful_sibling_call)
     {
       rtx insn;
+      tree arg;
 
       /* A sibling call sequence invalidates any REG_EQUIV notes made for
-        this function's incoming arguments. 
+        this function's incoming arguments.
 
         At the start of RTL generation we know the only REG_EQUIV notes
         in the rtl chain are those for incoming arguments, so we can safely
-        flush any REG_EQUIV note. 
+        flush any REG_EQUIV note.
 
         This is (slight) overkill.  We could keep track of the highest
         argument we clobber and be more selective in removing notes, but it
@@ -741,7 +738,7 @@ optimize_sibling_and_tail_recursive_calls ()
       /* A sibling call sequence also may invalidate RTX_UNCHANGING_P
         flag of some incoming arguments MEM RTLs, because it can write into
         those slots.  We clear all those bits now.
-        
+
         This is (slight) overkill, we could keep track of which arguments
         we actually write into.  */
       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
@@ -749,9 +746,19 @@ optimize_sibling_and_tail_recursive_calls ()
          if (INSN_P (insn))
            purge_mem_unchanging_flag (PATTERN (insn));
        }
+
+      /* Similarly, invalidate RTX_UNCHANGING_P for any incoming
+        arguments passed in registers.  */
+      for (arg = DECL_ARGUMENTS (current_function_decl);
+          arg;
+          arg = TREE_CHAIN (arg))
+       {
+         if (REG_P (DECL_RTL (arg)))
+           RTX_UNCHANGING_P (DECL_RTL (arg)) = false;
+       }
     }
 
-  /* There may have been NOTE_INSN_BLOCK_{BEGIN,END} notes in the 
+  /* There may have been NOTE_INSN_BLOCK_{BEGIN,END} notes in the
      CALL_PLACEHOLDER alternatives that we didn't emit.  Rebuild the
      lexical block tree to correspond to the notes that still exist.  */
   if (replaced_call_placeholder)
@@ -759,4 +766,5 @@ optimize_sibling_and_tail_recursive_calls ()
 
   /* This information will be invalid after inline expansion.  Kill it now.  */
   free_basic_block_vars (0);
+  free_EXPR_LIST_list (&tail_recursion_label_list);
 }