changeset 73:ce75bd9117e4

merge calls.c, cfgexpand.c, gcc.c, gimple.c, gimple.h and gimplify.c
author Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
date Mon, 22 Aug 2011 01:54:47 +0900
parents 20c18990c3e4
children f26ecf70364b
files gcc/calls.c gcc/cfgexpand.c gcc/gcc.c gcc/gimple.c gcc/gimple.h gcc/gimplify.c
diffstat 6 files changed, 154 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/gcc/calls.c	Sun Aug 21 22:22:32 2011 +0900
+++ b/gcc/calls.c	Mon Aug 22 01:54:47 2011 +0900
@@ -99,6 +99,9 @@
      word-sized pseudos we made.  */
   rtx *aligned_regs;
   int n_aligned_regs;
+#ifndef noCbC
+rtx exprs;
+#endif
 };
 
 /* A vector of one char per byte of stack space.  A byte if nonzero if
@@ -1893,6 +1896,10 @@
   return true;
 }
 
+#ifndef noCbC
+#include "cbc-tree.h"
+#endif
+
 /* If X is a likely-spilled register value, copy it to a pseudo
    register and return that register.  Return X otherwise.  */
 
@@ -2296,8 +2303,13 @@
      expanding a call, as that means we're an argument.  Don't try if
      there's cleanups, as we know there's code to follow the call.  */
 
+  // -O2オプションがないときも末尾最適化が行われるように(Code Segmentのみ)
   if (currently_expanding_call++ != 0
+#ifndef noCbC
+      || ((!fndecl || !CbC_IS_CODE_SEGMENT (TREE_TYPE (fndecl))) && !flag_optimize_sibling_calls)
+#else
       || !flag_optimize_sibling_calls
+#endif
       || args_size.var
       || dbg_cnt (tail_call) == false)
     try_tail_call = 0;
@@ -2388,6 +2400,67 @@
 
   preferred_unit_stack_boundary = preferred_stack_boundary / BITS_PER_UNIT;
 
+#ifndef noCbC
+  if ( fntype
+       && CbC_IS_CbC_GOTO (exp) // it's better? than CALL_EXPR_TAILCALL()
+       && CbC_IS_CODE_SEGMENT (TREE_TYPE (current_function_decl))
+     )
+    {
+
+      args_size.constant = CbC_PRETENDED_STACK_SIZE;
+      // try_tail_callを矯正的に立たせて末尾最適化を必ずうように変更
+      // -> expand_cbc_gotは不要に。
+      /* return expand_cbc_goto(exp, target, fndecl, funtype, fntype,
+       *         addr, ignore, flags, num_actuals, args, &args_size,
+       *         args_so_far,
+       *         old_stack_level, reg_parm_stack_space, old_pending_adj,
+       *         preferred_stack_boundary, preferred_unit_stack_boundary,
+       *         structure_value_addr, old_inhibit_defer_pop); */
+    }
+  else if ( CbC_IS_CbC_GOTO (exp) )
+    {
+      // TODO: 関数からコードセグメントへの遷移
+      /*
+      if (fndecl)
+        {
+          char *name_callee = IDENTIFIER_POINTER(DECL_NAME(fndecl));
+          warning(0, "no warning: code segment `%s' has been called from a function.", name_callee);
+        }
+      else
+        {
+          warning(0, "no warning: unnamed code segment has been called from a function.");
+        }
+        */
+      args_size.constant = CbC_PRETENDED_STACK_SIZE;
+    }
+  else if ( fndecl && CbC_IS_CODE_SEGMENT (TREE_TYPE (fndecl)) )
+    {
+      // 警告コードセグメントを関数呼び出し
+      //char *name= IDENTIFIER_POINTER(DECL_NAME(fndecl));
+      //warning (0, "code segment `%s' has been \"called\" instead \"goto\".", name);
+    }
+  else if (CbC_IS_CODE_SEGMENT(TREE_TYPE (current_function_decl)) )
+    {
+      // code segment内部からの関数呼び出し。なんも問題ない。
+      //warning (0, "no warning: normal call from a code segment.");
+    }
+#endif
+
+  // when tail call optimization flag was down, warn about them.
+  // and flag it to force a tail call optimize.
+#ifndef noCbC
+  if (fndecl && CbC_IS_CODE_SEGMENT (TREE_TYPE (fndecl))
+      && CbC_IS_CODE_SEGMENT (TREE_TYPE (current_function_decl))
+      && try_tail_call == 0)
+    {
+      location_t loc = EXPR_LOCATION (exp);
+      char *name_callee = IDENTIFIER_POINTER(DECL_NAME(fndecl));
+      warning_at (loc, 0, "transition to code segment \"%s\" with CbC goto, but tail call optimization was cut.",
+                        name_callee);
+      try_tail_call = 1;
+    }
+#endif
+
   /* We want to make two insn chains; one for a sibling call, the other
      for a normal call.  We will select one of the two chains after
      initial RTL generation is complete.  */
@@ -2454,16 +2527,31 @@
 
       adjusted_args_size = args_size;
       /* Compute the actual size of the argument block required.  The variable
-	 and constant sizes must be combined, the size may have to be rounded,
-	 and there may be a minimum required size.  When generating a sibcall
-	 pattern, do not round up, since we'll be re-using whatever space our
-	 caller provided.  */
+         and constant sizes must be combined, the size may have to be rounded,
+         and there may be a minimum required size.  When generating a sibcall
+         pattern, do not round up, since we'll be re-using whatever space our
+         caller provided.  */
+#ifndef noCbC
+      if ( fntype && CbC_IS_CODE_SEGMENT(fntype) )
+        {
+          unadjusted_args_size = args_size.constant;
+          adjusted_args_size.constant = CbC_PRETENDED_STACK_SIZE;
+          compute_argument_block_size (reg_parm_stack_space,
+              &adjusted_args_size,
+              fndecl, fntype,
+              (pass == 0 ? 0
+               : preferred_stack_boundary));
+        }
+      else
+#endif
+      {
       unadjusted_args_size
-	= compute_argument_block_size (reg_parm_stack_space,
-				       &adjusted_args_size,
-				       fndecl, fntype,
-				       (pass == 0 ? 0
-					: preferred_stack_boundary));
+        = compute_argument_block_size (reg_parm_stack_space,
+                                       &adjusted_args_size,
+                                       fndecl, fntype,
+                                       (pass == 0 ? 0
+                                        : preferred_stack_boundary));
+      }
 
       old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
 
--- a/gcc/cfgexpand.c	Sun Aug 21 22:22:32 2011 +0900
+++ b/gcc/cfgexpand.c	Mon Aug 22 01:54:47 2011 +0900
@@ -44,6 +44,9 @@
 #include "tree-inline.h"
 #include "value-prof.h"
 #include "target.h"
+#ifndef noCbC
+#include "cbc-tree.h"
+#endif
 #include "ssaexpand.h"
 #include "bitmap.h"
 #include "sbitmap.h"
--- a/gcc/gcc.c	Sun Aug 21 22:22:32 2011 +0900
+++ b/gcc/gcc.c	Mon Aug 22 01:54:47 2011 +0900
@@ -915,6 +915,9 @@
   {".go", "#Go", 0, 1, 0},
   /* Next come the entries for C.  */
   {".c", "@c", 0, 0, 1},
+#ifndef noCbC
+  {".cbc", "@c", 0, 1, 1},
+#endif
   {"@c",
    /* cc1 has an integrated ISO C preprocessor.  We should invoke the
       external preprocessor if -save-temps is given.  */
--- a/gcc/gimple.c	Sun Aug 21 22:22:32 2011 +0900
+++ b/gcc/gimple.c	Mon Aug 22 01:54:47 2011 +0900
@@ -33,6 +33,9 @@
 #include "tree-flow.h"
 #include "value-prof.h"
 #include "flags.h"
+#ifndef noCbC
+#include "cbc-tree.h"
+#endif
 #include "alias.h"
 #include "demangle.h"
 #include "langhooks.h"
@@ -304,7 +307,9 @@
   gimple_call_set_return_slot_opt (call, CALL_EXPR_RETURN_SLOT_OPT (t));
   gimple_call_set_from_thunk (call, CALL_FROM_THUNK_P (t));
   gimple_call_set_va_arg_pack (call, CALL_EXPR_VA_ARG_PACK (t));
-  gimple_call_set_nothrow (call, TREE_NOTHROW (t));
+#ifndef noCbC
+  gimple_call_set_cbc_goto (call, CALL_EXPR_CbC_GOTO (t));
+#endif
   gimple_set_no_warning (call, TREE_NO_WARNING (t));
 
   return call;
@@ -3127,6 +3132,10 @@
   gimple_call_copy_flags (new_stmt, stmt);
   gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
 
+#ifndef noCbC
+  gimple_call_set_cbc_goto (new_stmt, gimple_call_cbc_goto_p (stmt));
+#endif
+
   gimple_set_modified (new_stmt, true);
 
   return new_stmt;
--- a/gcc/gimple.h	Sun Aug 21 22:22:32 2011 +0900
+++ b/gcc/gimple.h	Mon Aug 22 01:54:47 2011 +0900
@@ -102,6 +102,9 @@
     GF_CALL_TAILCALL		= 1 << 3,
     GF_CALL_VA_ARG_PACK		= 1 << 4,
     GF_CALL_NOTHROW		= 1 << 5,
+#ifndef noCbC
+	GF_CALL_CBC_GOTO		= 1 << 5,
+#endif
     GF_OMP_PARALLEL_COMBINED	= 1 << 0,
 
     /* True on an GIMPLE_OMP_RETURN statement if the return does not require
@@ -2172,6 +2175,21 @@
     s->gsbase.subcode &= ~GF_CALL_TAILCALL;
 }
 
+#ifndef noCbC
+/* If CBCGOTO_P is true, mark call statement S as being a cbc goto
+   (i.e., a call just before the exit of a function).  These calls are
+   candidate for tail call optimization.  */
+
+static inline void
+gimple_call_set_cbc_goto (gimple s, bool cbcgoto_p)
+{
+  GIMPLE_CHECK (s, GIMPLE_CALL);
+  if (cbcgoto_p)
+    s->gsbase.subcode |= GF_CALL_CBC_GOTO;
+  else
+    s->gsbase.subcode &= ~GF_CALL_CBC_GOTO;
+}
+#endif
 
 /* Return true if GIMPLE_CALL S is marked as a tail call.  */
 
@@ -2182,6 +2200,16 @@
   return (s->gsbase.subcode & GF_CALL_TAILCALL) != 0;
 }
 
+#ifndef noCbC
+/* Return true if GIMPLE_CALL S is marked as a cbc goto.  */
+
+static inline bool
+gimple_call_cbc_goto_p (gimple s)
+{
+  GIMPLE_CHECK (s, GIMPLE_CALL);
+  return (s->gsbase.subcode & GF_CALL_CBC_GOTO) != 0;
+}
+#endif
 
 /* Set the inlinable status of GIMPLE_CALL S to INLINABLE_P.  */
 
--- a/gcc/gimplify.c	Sun Aug 21 22:22:32 2011 +0900
+++ b/gcc/gimplify.c	Mon Aug 22 01:54:47 2011 +0900
@@ -46,6 +46,9 @@
 #include "vec.h"
 #include "gimple.h"
 #include "tree-pass.h"
+#ifndef noCbC
+#include "cbc-tree.h"
+#endif
 
 #include "langhooks-def.h"	/* FIXME: for lhd_set_decl_assembler_name.  */
 #include "expr.h"		/* FIXME: for can_move_by_pieces
@@ -1234,7 +1237,16 @@
       return GS_ALL_DONE;
     }
 
-  if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
+  if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
+#ifndef noCbC
+      || ( ret_expr
+           && TREE_CODE(ret_expr)==CALL_EXPR
+       && CbC_IS_CbC_GOTO(ret_expr)
+       //&& !CbC_IS_CODE_SEGMENT(TREE_TYPE(current_function_decl)))
+       && !(current_function_decl&&CbC_IS_CODE_SEGMENT(TREE_TYPE(current_function_decl))))
+       //&& !(current_function_decl&&CbC_IS_CODE_SEGMENT(current_function_decl)))
+#endif
+     )
     result_decl = NULL_TREE;
   else
     {