We can fold OBJ_TYPE_REFs to direct calls if the callee is known.  Even
easier now that we keep fntypes separately.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2011-04-18  Richard Guenther  <rguent...@suse.de>

        * gimple.h (gimple_call_addr_fndecl): New function.
        (gimple_call_fndecl): Use it.
        * gimple-fold.c (gimple_fold_call): Fold away OBJ_TYPE_REFs
        for direct calls.
        * tree-ssa-ccp.c (ccp_fold_stmt): Remove OBJ_TYPE_REF folding.
        * tree-ssa-pre.c (eliminate): Also simplify indirect OBJ_TYPE_REFs.

Index: gcc/gimple.h
===================================================================
*** gcc/gimple.h        (revision 172640)
--- gcc/gimple.h        (working copy)
*************** gimple_call_set_fndecl (gimple gs, tree
*** 2065,2070 ****
--- 2065,2088 ----
    gimple_set_op (gs, 1, build_fold_addr_expr_loc (gimple_location (gs), 
decl));
  }
  
+ /* Given a valid GIMPLE_CALL function address return the FUNCTION_DECL
+    associated with the callee if known.  Otherwise return NULL_TREE.  */
+ 
+ static inline tree
+ gimple_call_addr_fndecl (const_tree fn)
+ {
+   if (TREE_CODE (fn) == ADDR_EXPR)
+     {
+       tree fndecl = TREE_OPERAND (fn, 0);
+       if (TREE_CODE (fndecl) == MEM_REF
+         && TREE_CODE (TREE_OPERAND (fndecl, 0)) == ADDR_EXPR
+         && integer_zerop (TREE_OPERAND (fndecl, 1)))
+       fndecl = TREE_OPERAND (TREE_OPERAND (fndecl, 0), 0);
+       if (TREE_CODE (fndecl) == FUNCTION_DECL)
+       return fndecl;
+     }
+   return NULL_TREE;
+ }
  
  /* If a given GIMPLE_CALL's callee is a FUNCTION_DECL, return it.
     Otherwise return NULL.  This function is analogous to
*************** gimple_call_set_fndecl (gimple gs, tree
*** 2073,2093 ****
  static inline tree
  gimple_call_fndecl (const_gimple gs)
  {
!   tree addr = gimple_call_fn (gs);
!   if (TREE_CODE (addr) == ADDR_EXPR)
!     {
!       tree fndecl = TREE_OPERAND (addr, 0);
!       if (TREE_CODE (fndecl) == MEM_REF)
!       {
!         if (TREE_CODE (TREE_OPERAND (fndecl, 0)) == ADDR_EXPR
!             && integer_zerop (TREE_OPERAND (fndecl, 1)))
!           return TREE_OPERAND (TREE_OPERAND (fndecl, 0), 0);
!         else
!           return NULL_TREE;
!       }
!       return TREE_OPERAND (addr, 0);
!     }
!   return NULL_TREE;
  }
  
  
--- 2091,2097 ----
  static inline tree
  gimple_call_fndecl (const_gimple gs)
  {
!   return gimple_call_addr_fndecl (gimple_call_fn (gs));
  }
  
  
Index: gcc/gimple-fold.c
===================================================================
*** gcc/gimple-fold.c   (revision 172640)
--- gcc/gimple-fold.c   (working copy)
*************** bool
*** 1450,1460 ****
  gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
  {
    gimple stmt = gsi_stmt (*gsi);
! 
!   tree callee = gimple_call_fndecl (stmt);
  
    /* Check for builtins that CCP can handle using information not
       available in the generic fold routines.  */
    if (!inplace && callee && DECL_BUILT_IN (callee))
      {
        tree result = gimple_fold_builtin (stmt);
--- 1450,1460 ----
  gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
  {
    gimple stmt = gsi_stmt (*gsi);
!   tree callee;
  
    /* Check for builtins that CCP can handle using information not
       available in the generic fold routines.  */
+   callee = gimple_call_fndecl (stmt);
    if (!inplace && callee && DECL_BUILT_IN (callee))
      {
        tree result = gimple_fold_builtin (stmt);
*************** gimple_fold_call (gimple_stmt_iterator *
*** 1466,1471 ****
--- 1466,1481 ----
          return true;
        }
      }
+ 
+   /* Check for virtual calls that became direct calls.  */
+   callee = gimple_call_fn (stmt);
+   if (TREE_CODE (callee) == OBJ_TYPE_REF
+       && gimple_call_addr_fndecl (OBJ_TYPE_REF_EXPR (callee)) != NULL_TREE)
+     {
+       gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee));
+       return true;
+     }
+ 
    return false;
  }
  
Index: gcc/tree-ssa-ccp.c
===================================================================
*** gcc/tree-ssa-ccp.c  (revision 172640)
--- gcc/tree-ssa-ccp.c  (working copy)
*************** ccp_fold_stmt (gimple_stmt_iterator *gsi
*** 1702,1708 ****
        tree lhs = gimple_call_lhs (stmt);
        tree val;
        tree argt;
-       tree callee;
        bool changed = false;
        unsigned i;
  
--- 1702,1707 ----
*************** ccp_fold_stmt (gimple_stmt_iterator *gsi
*** 1743,1759 ****
              }
          }
  
-       callee = gimple_call_fn (stmt);
-       if (TREE_CODE (callee) == OBJ_TYPE_REF
-           && TREE_CODE (OBJ_TYPE_REF_EXPR (callee)) == SSA_NAME)
-         {
-           tree expr = OBJ_TYPE_REF_EXPR (callee);
-           OBJ_TYPE_REF_EXPR (callee) = valueize_op (expr);
-           if (gimple_fold_call (gsi, false))
-             changed = true;
-           OBJ_TYPE_REF_EXPR (callee) = expr;
-         }
- 
        return changed;
        }
  
--- 1742,1747 ----
Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c  (revision 172640)
--- gcc/tree-ssa-pre.c  (working copy)
*************** eliminate (void)
*** 4380,4392 ****
            }
          /* Visit indirect calls and turn them into direct calls if
             possible.  */
!         if (is_gimple_call (stmt)
!             && TREE_CODE (gimple_call_fn (stmt)) == SSA_NAME)
            {
              tree orig_fn = gimple_call_fn (stmt);
!             tree fn = VN_INFO (orig_fn)->valnum;
!             if (TREE_CODE (fn) == ADDR_EXPR
!                 && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
                  && useless_type_conversion_p (TREE_TYPE (orig_fn),
                                                TREE_TYPE (fn)))
                {
--- 4380,4397 ----
            }
          /* Visit indirect calls and turn them into direct calls if
             possible.  */
!         if (is_gimple_call (stmt))
            {
              tree orig_fn = gimple_call_fn (stmt);
!             tree fn;
!             if (TREE_CODE (orig_fn) == SSA_NAME)
!               fn = VN_INFO (orig_fn)->valnum;
!             else if (TREE_CODE (orig_fn) == OBJ_TYPE_REF
!                      && TREE_CODE (OBJ_TYPE_REF_EXPR (orig_fn)) == SSA_NAME)
!               fn = VN_INFO (OBJ_TYPE_REF_EXPR (orig_fn))->valnum;
!             else
!               continue;
!             if (gimple_call_addr_fndecl (fn) != NULL_TREE
                  && useless_type_conversion_p (TREE_TYPE (orig_fn),
                                                TREE_TYPE (fn)))
                {

Reply via email to