Hi,
I am looking into testcases for individual code paths of ipa-devirt and my life
would be much easier if gimple-fold did not take some of them by old code.
This patch also improves code by doing devirtualization earlier in the game
since get_polymorphic_call_info is now supperset of
gimple_extract_devirt_binfo_from_cst but with more tricks in it.

I does some SSA graph walking that may break when folding is called with broken
SSA form, but since other places in gimple-fold does that, too, I hope it is
OK.

Bootstrapped/regtested x86_64-linux, OK?

Honza

        * ipa-utils.h (possible_polymorphic_call_targets): Determine context of
        the call.
        (gimple_fold_call): Use ipa-devirt to devirtualize.

Index: ipa-utils.h
===================================================================
*** ipa-utils.h (revision 205108)
--- ipa-utils.h (working copy)
*************** possible_polymorphic_call_targets (tree
*** 121,130 ****
                                   bool *final = NULL,
                                   void **cache_token = NULL)
  {
    return possible_polymorphic_call_targets (obj_type_ref_class (call),
                                            tree_to_uhwi
                                              (OBJ_TYPE_REF_TOKEN (call)),
!                                           ipa_dummy_polymorphic_call_context,
                                            final, cache_token);
  }
  
--- 121,137 ----
                                   bool *final = NULL,
                                   void **cache_token = NULL)
  {
+   tree otr_type;
+   HOST_WIDE_INT otr_token;
+   ipa_polymorphic_call_context context;
+ 
+   get_polymorphic_call_info (current_function_decl,
+                            call,
+                            &otr_type, &otr_token, &context);
    return possible_polymorphic_call_targets (obj_type_ref_class (call),
                                            tree_to_uhwi
                                              (OBJ_TYPE_REF_TOKEN (call)),
!                                           context,
                                            final, cache_token);
  }
  
Index: gimple-fold.c
===================================================================
*** gimple-fold.c       (revision 205108)
--- gimple-fold.c       (working copy)
*************** gimple_fold_call (gimple_stmt_iterator *
*** 1151,1174 ****
        }
        else if (virtual_method_call_p (callee))
        {
!         tree obj = OBJ_TYPE_REF_OBJECT (callee);
!         tree binfo = gimple_extract_devirt_binfo_from_cst
!                (obj, obj_type_ref_class (callee));
!         if (binfo)
            {
!             HOST_WIDE_INT token
!               = TREE_INT_CST_LOW (OBJ_TYPE_REF_TOKEN (callee));
!             tree fndecl = gimple_get_virt_method_for_binfo (token, binfo);
!             if (fndecl)
!               {
! #ifdef ENABLE_CHECKING
!                 gcc_assert (possible_polymorphic_call_target_p
!                                (callee, cgraph_get_node (fndecl)));
! 
! #endif
!                 gimple_call_set_fndecl (stmt, fndecl);
!                 changed = true;
!               }
            }
        }
      }
--- 1151,1168 ----
        }
        else if (virtual_method_call_p (callee))
        {
!         bool final;
!         vec <cgraph_node *>targets
!           = possible_polymorphic_call_targets (callee, &final);
!         if (final && targets.length () <= 1)
            {
!             tree fndecl;
!             if (targets.length () == 1)
!               fndecl = targets[0]->decl;
!             else
!               fndecl = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
!             gimple_call_set_fndecl (stmt, fndecl);
!             changed = true;
            }
        }
      }

Reply via email to