diff gcc/calls.c @ 112:ab0bcb71f44d

merge gcc 7
author mir3636
date Fri, 10 Nov 2017 19:46:38 +0900
parents 04ced10e8804 4d6300120c29
children 367f9f4f266e
line wrap: on
line diff
--- a/gcc/calls.c	Fri Oct 27 22:46:09 2017 +0900
+++ b/gcc/calls.c	Fri Nov 10 19:46:38 2017 +0900
@@ -118,6 +118,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
@@ -2755,6 +2758,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.  */
 
@@ -3291,8 +3298,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;
@@ -3303,6 +3315,7 @@
     try_tail_call = 1;
 
   /*  Rest of purposes for tail call optimizations to fail.  */
+<<<<<<< local
   if (try_tail_call)
     try_tail_call = can_implement_as_sibling_call_p (exp,
 						     structure_value_addr,
@@ -3310,10 +3323,60 @@
 						     reg_parm_stack_space,
 						     fndecl,
 						     flags, addr, args_size);
+=======
+  if (
+#ifdef HAVE_sibcall_epilogue
+      !HAVE_sibcall_epilogue
+#else
+      1
+#endif
+      || !try_tail_call
+      /* Doing sibling call optimization needs some work, since
+	 structure_value_addr can be allocated on the stack.
+	 It does not seem worth the effort since few optimizable
+	 sibling calls will return a structure.  */
+      || structure_value_addr != NULL_RTX
+#ifdef REG_PARM_STACK_SPACE
+      /* If outgoing reg parm stack space changes, we can not do sibcall.  */
+      || (OUTGOING_REG_PARM_STACK_SPACE (funtype)
+	  != OUTGOING_REG_PARM_STACK_SPACE (TREE_TYPE (current_function_decl)))
+      || (reg_parm_stack_space != REG_PARM_STACK_SPACE (fndecl))
+#endif
+      /* Check whether the target is able to optimize the call
+	 into a sibcall.  */
+      || !targetm.function_ok_for_sibcall (fndecl, exp)
+      /* Functions that do not return exactly once may not be sibcall
+	 optimized.  */
+      || (flags & (ECF_RETURNS_TWICE | ECF_NORETURN))
+      || TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (addr)))
+      /* If the called function is nested in the current one, it might access
+	 some of the caller's arguments, but could clobber them beforehand if
+	 the argument areas are shared.  */
+      || (fndecl && decl_function_context (fndecl) == current_function_decl)
+      /* If this function requires more stack slots than the current
+	 function, we cannot change it into a sibling call.
+	 crtl->args.pretend_args_size is not part of the
+	 stack allocated by our caller.  */
+      || args_size.constant > (crtl->args.size
+                               - crtl->args.pretend_args_size)
+      /* If the callee pops its own arguments, then it must pop exactly
+	 the same number of arguments as the current function.  */
+      || (targetm.calls.return_pops_args (fndecl, funtype, args_size.constant)
+	  != targetm.calls.return_pops_args (current_function_decl,
+					     TREE_TYPE (current_function_decl),
+					     crtl->args.size))
+      || !lang_hooks.decls.ok_for_sibcall (fndecl))
+    try_tail_call = 0;
+>>>>>>> other
+
 
   /* Check if caller and callee disagree in promotion of function
      return value.  */
-  if (try_tail_call)
+#ifndef noCbC
+  if (try_tail_call && (!fndecl || !CbC_IS_CODE_SEGMENT (TREE_TYPE (fndecl))))
+#else
+    if (try_tail_call)
+#endif 
     {
       machine_mode caller_mode, caller_promoted_mode;
       machine_mode callee_mode, callee_promoted_mode;
@@ -3357,6 +3420,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.  */
@@ -3423,16 +3547,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;