cgraphunit.c (add_new_function): Fix logic when adding from late IPA pass.
authorJan Hubicka <jh@suse.cz>
Sat, 3 Aug 2013 11:02:37 +0000 (13:02 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sat, 3 Aug 2013 11:02:37 +0000 (11:02 +0000)
* cgraphunit.c (add_new_function): Fix logic when adding from
late IPA pass.
(assemble_thunk): Rename to ...
(expand_thunk); .. this one; export; get it working with general functions;
make produced gimple valid.
* cgraph.h (expand_thunk): Declare.

From-SVN: r201463

gcc/ChangeLog
gcc/cgraph.h
gcc/cgraphunit.c

index f54c696bcf1500673dfc105c4b5d627e0cc9a82a..1d48fc0da36938d0094469a122370b852c83df1d 100644 (file)
@@ -1,3 +1,12 @@
+2013-08-02  Jan Hubicka  <jh@suse.cz>
+
+       * cgraphunit.c (add_new_function): Fix logic when adding from
+       late IPA pass.
+       (assemble_thunk): Rename to ...
+       (expand_thunk); .. this one; export; get it working with general functions;
+       make produced gimple valid.
+       * cgraph.h (expand_thunk): Declare.
+
 2013-08-02  Jan Hubicka  <jh@suse.cz>
 
        * ipa-cp.c (gather_context_independent_values): Use ipa_get_param_move_cost.
index 4e4dddc0c3eef1c81b8a8b536c87e98c52b3b198..734f556cd9f6bf5fa38e9b26a51ece7ec26759f0 100644 (file)
@@ -716,6 +716,7 @@ void fixup_same_cpp_alias_visibility (symtab_node, symtab_node target, tree);
     IN_SSA is true if the gimple is in SSA.  */
 basic_block init_lowered_empty_function (tree, bool);
 void cgraph_reset_node (struct cgraph_node *);
+void expand_thunk (struct cgraph_node *);
 
 /* In cgraphclones.c  */
 
index de7bb93d2c37b2b535963935f290365e780b9a73..e308b5248504036562e6c6d1fa916af4c77a2e6d 100644 (file)
@@ -323,13 +323,10 @@ cgraph_process_new_functions (void)
          if (!node->symbol.analyzed)
            analyze_function (node);
          push_cfun (DECL_STRUCT_FUNCTION (fndecl));
-         if ((cgraph_state == CGRAPH_STATE_IPA_SSA
+         if (cgraph_state == CGRAPH_STATE_IPA_SSA
              && !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
-             /* When not optimizing, be sure we run early local passes anyway
-                to expand OMP.  */
-             || !optimize)
            execute_pass_list (pass_early_local_passes.pass.sub);
-         else
+         else if (inline_summary_vec != NULL)
            compute_inline_parameters (node, true);
          free_dominance_info (CDI_POST_DOMINATORS);
          free_dominance_info (CDI_DOMINATORS);
@@ -1327,8 +1324,8 @@ thunk_adjust (gimple_stmt_iterator * bsi,
 
 /* Produce assembler for thunk NODE.  */
 
-static void
-assemble_thunk (struct cgraph_node *node)
+void
+expand_thunk (struct cgraph_node *node)
 {
   bool this_adjusting = node->thunk.this_adjusting;
   HOST_WIDE_INT fixed_offset = node->thunk.fixed_offset;
@@ -1420,7 +1417,9 @@ assemble_thunk (struct cgraph_node *node)
       /* Build call to the function being thunked.  */
       if (!VOID_TYPE_P (restype))
        {
-         if (!is_gimple_reg_type (restype))
+         if (DECL_BY_REFERENCE (resdecl))
+           restmp = gimple_fold_indirect_ref (resdecl);
+         else if (!is_gimple_reg_type (restype))
            {
              restmp = resdecl;
              add_local_decl (cfun, restmp);
@@ -1436,74 +1435,91 @@ assemble_thunk (struct cgraph_node *node)
       if (this_adjusting)
         vargs.quick_push (thunk_adjust (&bsi, a, 1, fixed_offset,
                                        virtual_offset));
-      else
+      else if (nargs)
         vargs.quick_push (a);
-      for (i = 1, arg = DECL_CHAIN (a); i < nargs; i++, arg = DECL_CHAIN (arg))
-       vargs.quick_push (arg);
+
+      if (nargs)
+        for (i = 1, arg = DECL_CHAIN (a); i < nargs; i++, arg = DECL_CHAIN (arg))
+         vargs.quick_push (arg);
       call = gimple_build_call_vec (build_fold_addr_expr_loc (0, alias), vargs);
       vargs.release ();
       gimple_call_set_from_thunk (call, true);
       if (restmp)
-        gimple_call_set_lhs (call, restmp);
+       {
+          gimple_call_set_lhs (call, restmp);
+         gcc_assert (useless_type_conversion_p (TREE_TYPE (restmp),
+                                                TREE_TYPE (TREE_TYPE (alias))));
+       }
       gsi_insert_after (&bsi, call, GSI_NEW_STMT);
+      if (!(gimple_call_flags (call) & ECF_NORETURN))
+       {
+         if (restmp && !this_adjusting
+             && (fixed_offset || virtual_offset))
+           {
+             tree true_label = NULL_TREE;
 
-      if (restmp && !this_adjusting)
-        {
-         tree true_label = NULL_TREE;
+             if (TREE_CODE (TREE_TYPE (restmp)) == POINTER_TYPE)
+               {
+                 gimple stmt;
+                 /* If the return type is a pointer, we need to
+                    protect against NULL.  We know there will be an
+                    adjustment, because that's why we're emitting a
+                    thunk.  */
+                 then_bb = create_basic_block (NULL, (void *) 0, bb);
+                 return_bb = create_basic_block (NULL, (void *) 0, then_bb);
+                 else_bb = create_basic_block (NULL, (void *) 0, else_bb);
+                 add_bb_to_loop (then_bb, bb->loop_father);
+                 add_bb_to_loop (return_bb, bb->loop_father);
+                 add_bb_to_loop (else_bb, bb->loop_father);
+                 remove_edge (single_succ_edge (bb));
+                 true_label = gimple_block_label (then_bb);
+                 stmt = gimple_build_cond (NE_EXPR, restmp,
+                                           build_zero_cst (TREE_TYPE (restmp)),
+                                           NULL_TREE, NULL_TREE);
+                 gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
+                 make_edge (bb, then_bb, EDGE_TRUE_VALUE);
+                 make_edge (bb, else_bb, EDGE_FALSE_VALUE);
+                 make_edge (return_bb, EXIT_BLOCK_PTR, 0);
+                 make_edge (then_bb, return_bb, EDGE_FALLTHRU);
+                 make_edge (else_bb, return_bb, EDGE_FALLTHRU);
+                 bsi = gsi_last_bb (then_bb);
+               }
 
-         if (TREE_CODE (TREE_TYPE (restmp)) == POINTER_TYPE)
-           {
-             gimple stmt;
-             /* If the return type is a pointer, we need to
-                protect against NULL.  We know there will be an
-                adjustment, because that's why we're emitting a
-                thunk.  */
-             then_bb = create_basic_block (NULL, (void *) 0, bb);
-             return_bb = create_basic_block (NULL, (void *) 0, then_bb);
-             else_bb = create_basic_block (NULL, (void *) 0, else_bb);
-             add_bb_to_loop (then_bb, bb->loop_father);
-             add_bb_to_loop (return_bb, bb->loop_father);
-             add_bb_to_loop (else_bb, bb->loop_father);
-             remove_edge (single_succ_edge (bb));
-             true_label = gimple_block_label (then_bb);
-             stmt = gimple_build_cond (NE_EXPR, restmp,
-                                       build_zero_cst (TREE_TYPE (restmp)),
-                                       NULL_TREE, NULL_TREE);
-             gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
-             make_edge (bb, then_bb, EDGE_TRUE_VALUE);
-             make_edge (bb, else_bb, EDGE_FALSE_VALUE);
-             make_edge (return_bb, EXIT_BLOCK_PTR, 0);
-             make_edge (then_bb, return_bb, EDGE_FALLTHRU);
-             make_edge (else_bb, return_bb, EDGE_FALLTHRU);
-             bsi = gsi_last_bb (then_bb);
+             restmp = thunk_adjust (&bsi, restmp, /*this_adjusting=*/0,
+                                    fixed_offset, virtual_offset);
+             if (true_label)
+               {
+                 gimple stmt;
+                 bsi = gsi_last_bb (else_bb);
+                 stmt = gimple_build_assign (restmp,
+                                             build_zero_cst (TREE_TYPE (restmp)));
+                 gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
+                 bsi = gsi_last_bb (return_bb);
+               }
            }
+         else
+           gimple_call_set_tail (call, true);
 
-         restmp = thunk_adjust (&bsi, restmp, /*this_adjusting=*/0,
-                                fixed_offset, virtual_offset);
-         if (true_label)
-           {
-             gimple stmt;
-             bsi = gsi_last_bb (else_bb);
-             stmt = gimple_build_assign (restmp,
-                                         build_zero_cst (TREE_TYPE (restmp)));
-             gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
-             bsi = gsi_last_bb (return_bb);
-           }
+         /* Build return value.  */
+         ret = gimple_build_return (restmp);
+         gsi_insert_after (&bsi, ret, GSI_NEW_STMT);
        }
       else
-        gimple_call_set_tail (call, true);
-
-      /* Build return value.  */
-      ret = gimple_build_return (restmp);
-      gsi_insert_after (&bsi, ret, GSI_NEW_STMT);
+       {
+         gimple_call_set_tail (call, true);
+         remove_edge (single_succ_edge (bb));
+       }
 
       delete_unreachable_blocks ();
       update_ssa (TODO_update_ssa);
+#ifdef ENABLE_CHECKING
+      verify_flow_info ();
+#endif
 
       /* Since we want to emit the thunk, we explicitly mark its name as
         referenced.  */
       node->thunk.thunk_p = false;
-      cgraph_node_remove_callees (node);
+      rebuild_cgraph_edges ();
       cgraph_add_new_function (thunk_fndecl, true);
       bitmap_obstack_release (NULL);
     }
@@ -1511,8 +1527,6 @@ assemble_thunk (struct cgraph_node *node)
   set_cfun (NULL);
 }
 
-
-
 /* Assemble thunks and aliases associated to NODE.  */
 
 static void
@@ -1529,7 +1543,7 @@ assemble_thunks_and_aliases (struct cgraph_node *node)
 
        e = e->next_caller;
        assemble_thunks_and_aliases (thunk);
-        assemble_thunk (thunk);
+        expand_thunk (thunk);
       }
     else
       e = e->next_caller;