From 3b45a007ef93933c0c70c37cb87bf6097db68a32 Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Mon, 18 Apr 2011 11:59:34 +0000 Subject: [PATCH] gimple.h (gimple_call_addr_fndecl): New function. 2011-04-18 Richard Guenther * 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. From-SVN: r172644 --- gcc/ChangeLog | 9 +++++++++ gcc/gimple-fold.c | 14 ++++++++++++-- gcc/gimple.h | 34 +++++++++++++++++++--------------- gcc/tree-ssa-ccp.c | 12 ------------ gcc/tree-ssa-pre.c | 15 ++++++++++----- 5 files changed, 50 insertions(+), 34 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e2c4a019d07..49c04815325 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2011-04-18 Richard Guenther + + * 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. + 2011-04-18 Richard Guenther PR middle-end/48650 diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index f629fd565a1..9047f670e7d 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -1450,11 +1450,11 @@ bool gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) { gimple stmt = gsi_stmt (*gsi); - - tree callee = gimple_call_fndecl (stmt); + 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); @@ -1466,6 +1466,16 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) 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; } diff --git a/gcc/gimple.h b/gcc/gimple.h index 788ffe6d487..3146b70cb12 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -2065,6 +2065,24 @@ gimple_call_set_fndecl (gimple gs, tree decl) 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 @@ -2073,21 +2091,7 @@ gimple_call_set_fndecl (gimple gs, tree decl) 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; + return gimple_call_addr_fndecl (gimple_call_fn (gs)); } diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 4775a2a567f..3aa2773ad8f 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -1702,7 +1702,6 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi) tree lhs = gimple_call_lhs (stmt); tree val; tree argt; - tree callee; bool changed = false; unsigned i; @@ -1743,17 +1742,6 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi) } } - 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; } diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index e59a598348b..df2a13867d1 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -4380,13 +4380,18 @@ eliminate (void) } /* Visit indirect calls and turn them into direct calls if possible. */ - if (is_gimple_call (stmt) - && TREE_CODE (gimple_call_fn (stmt)) == SSA_NAME) + if (is_gimple_call (stmt)) { 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 + 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))) { -- 2.30.2