diff options
author | Martin Jambor <mjambor@suse.cz> | 2010-12-22 13:56:54 +0100 |
---|---|---|
committer | Martin Jambor <jamborm@gcc.gnu.org> | 2010-12-22 13:56:54 +0100 |
commit | 32aa622ca800f92d7250e1ab4be08d3e174ef953 (patch) | |
tree | a1cfc1bdd186a3e0990698cbae0cf216e7ac85d0 | |
parent | 5eeac8330cbea6aa8d170473b7eab105734fb1d8 (diff) | |
download | gcc-32aa622ca800f92d7250e1ab4be08d3e174ef953.zip gcc-32aa622ca800f92d7250e1ab4be08d3e174ef953.tar.gz gcc-32aa622ca800f92d7250e1ab4be08d3e174ef953.tar.bz2 |
re PR tree-optimization/45934 (g++.old-deja/g++.other/dtor5.C FAILs with -finline-small-functions)
2010-12-22 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/45934
PR tree-optimization/46302
PR tree-optimization/46987
* gimple-fold.c (get_base_binfo_for_type): Removed.
(gimple_get_relevant_ref_binfo): Likewise.
(gimple_fold_obj_type_ref_call): Dumb down to 4.5 functionality,
removed parameter inplace, updated the caller.
* gimple.h (gimple_get_relevant_ref_binfo): Remove declaration.
* ipa-cp.c (ipcp_propagate_types): Do not derive types from constants.
(ipcp_discover_new_direct_edges): Do not do devirtualization based on
constants.
* ipa-prop.c (compute_known_type_jump_func): Use
get_ref_base_and_extent and get_binfo_at_offset instead of
gimple_get_relevant_ref_binfo.
(compute_known_type_jump_func): Likewise.
(update_jump_functions_after_inlining): Do not derive types from
constants.
(try_make_edge_direct_virtual_call): Likewise.
* tree.c (get_binfo_at_offset): Get type from non-artificial fields.
* testsuite/g++.dg/ipa/ipcp-ivi-1.C: Removed.
* testsuite/g++.dg/ipa/ivinline-6.C: Likewise.
* testsuite/g++.dg/otr-fold-1.C: Likewise.
* testsuite/g++.dg/otr-fold-2.C: Likewise.
* testsuite/g++.dg/tree-ssa/pr43411.C: Xfail dump scan.
* testsuite/g++.dg/tree-ssa/pr45605.C: Likewise.
* testsuite/g++.dg/tree-ssa/pr46987.C: New test.
From-SVN: r168168
-rw-r--r-- | gcc/ChangeLog | 22 | ||||
-rw-r--r-- | gcc/gimple-fold.c | 110 | ||||
-rw-r--r-- | gcc/gimple.h | 1 | ||||
-rw-r--r-- | gcc/ipa-cp.c | 40 | ||||
-rw-r--r-- | gcc/ipa-prop.c | 56 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ipa/ipcp-ivi-1.C | 65 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ipa/ivinline-6.C | 58 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/otr-fold-1.C | 76 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/otr-fold-2.C | 88 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/tree-ssa/pr43411.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/tree-ssa/pr45605.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/tree-ssa/pr46987.C | 22 | ||||
-rw-r--r-- | gcc/tree.c | 13 |
14 files changed, 108 insertions, 460 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a88274e4..cbbd5ae 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2010-12-22 Martin Jambor <mjambor@suse.cz> + + PR tree-optimization/45934 + PR tree-optimization/46302 + PR tree-optimization/46987 + * gimple-fold.c (get_base_binfo_for_type): Removed. + (gimple_get_relevant_ref_binfo): Likewise. + (gimple_fold_obj_type_ref_call): Dumb down to 4.5 functionality, + removed parameter inplace, updated the caller. + * gimple.h (gimple_get_relevant_ref_binfo): Remove declaration. + * ipa-cp.c (ipcp_propagate_types): Do not derive types from constants. + (ipcp_discover_new_direct_edges): Do not do devirtualization based on + constants. + * ipa-prop.c (compute_known_type_jump_func): Use + get_ref_base_and_extent and get_binfo_at_offset instead of + gimple_get_relevant_ref_binfo. + (compute_known_type_jump_func): Likewise. + (update_jump_functions_after_inlining): Do not derive types from + constants. + (try_make_edge_direct_virtual_call): Likewise. + * tree.c (get_binfo_at_offset): Get type from non-artificial fields. + 2010-12-22 Joseph Myers <joseph@codesourcery.com> * config/svr4.h: Remove. diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index b6c06fc..16a2092 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -1364,88 +1364,6 @@ gimple_fold_builtin (gimple stmt) return result; } -/* Search for a base binfo of BINFO that corresponds to TYPE and return it if - it is found or NULL_TREE if it is not. */ - -static tree -get_base_binfo_for_type (tree binfo, tree type) -{ - int i; - tree base_binfo; - tree res = NULL_TREE; - - for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) - if (TREE_TYPE (base_binfo) == type) - { - gcc_assert (!res); - res = base_binfo; - } - - return res; -} - -/* Return a binfo describing the part of object referenced by expression REF. - Return NULL_TREE if it cannot be determined. REF can consist of a series of - COMPONENT_REFs of a declaration or of an INDIRECT_REF or it can also be just - a simple declaration, indirect reference or an SSA_NAME. If the function - discovers an INDIRECT_REF or an SSA_NAME, it will assume that the - encapsulating type is described by KNOWN_BINFO, if it is not NULL_TREE. - Otherwise the first non-artificial field declaration or the base declaration - will be examined to get the encapsulating type. */ - -tree -gimple_get_relevant_ref_binfo (tree ref, tree known_binfo) -{ - while (true) - { - if (TREE_CODE (ref) == COMPONENT_REF) - { - tree par_type; - tree binfo; - tree field = TREE_OPERAND (ref, 1); - - if (!DECL_ARTIFICIAL (field)) - { - tree type = TREE_TYPE (field); - if (TREE_CODE (type) == RECORD_TYPE) - return TYPE_BINFO (type); - else - return NULL_TREE; - } - - par_type = TREE_TYPE (TREE_OPERAND (ref, 0)); - binfo = TYPE_BINFO (par_type); - if (!binfo - || BINFO_N_BASE_BINFOS (binfo) == 0) - return NULL_TREE; - - /* Offset 0 indicates the primary base, whose vtable contents are - represented in the binfo for the derived class. */ - if (int_bit_position (field) != 0) - { - tree d_binfo; - - /* Get descendant binfo. */ - d_binfo = gimple_get_relevant_ref_binfo (TREE_OPERAND (ref, 0), - known_binfo); - if (!d_binfo) - return NULL_TREE; - return get_base_binfo_for_type (d_binfo, TREE_TYPE (field)); - } - - ref = TREE_OPERAND (ref, 0); - } - else if (DECL_P (ref) && TREE_CODE (TREE_TYPE (ref)) == RECORD_TYPE) - return TYPE_BINFO (TREE_TYPE (ref)); - else if (known_binfo - && (TREE_CODE (ref) == SSA_NAME - || TREE_CODE (ref) == MEM_REF)) - return known_binfo; - else - return NULL_TREE; - } -} - /* Return a declaration of a function which an OBJ_TYPE_REF references. TOKEN is integer form of OBJ_TYPE_REF_TOKEN of the reference expression. KNOWN_BINFO carries the binfo describing the true type of @@ -1529,7 +1447,7 @@ gimple_adjust_this_by_delta (gimple_stmt_iterator *gsi, tree delta) INPLACE is false. Return true iff the statement was changed. */ static bool -gimple_fold_obj_type_ref_call (gimple_stmt_iterator *gsi, bool inplace) +gimple_fold_obj_type_ref_call (gimple_stmt_iterator *gsi) { gimple stmt = gsi_stmt (*gsi); tree ref = gimple_call_fn (stmt); @@ -1537,27 +1455,21 @@ gimple_fold_obj_type_ref_call (gimple_stmt_iterator *gsi, bool inplace) tree binfo, fndecl, delta; HOST_WIDE_INT token; - if (TREE_CODE (obj) == ADDR_EXPR) - obj = TREE_OPERAND (obj, 0); - else + if (TREE_CODE (obj) != ADDR_EXPR) return false; - - binfo = gimple_get_relevant_ref_binfo (obj, NULL_TREE); + obj = TREE_OPERAND (obj, 0); + if (!DECL_P (obj) + || TREE_CODE (TREE_TYPE (obj)) != RECORD_TYPE) + return false; + binfo = TYPE_BINFO (TREE_TYPE (obj)); if (!binfo) return false; + token = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1); - fndecl = gimple_get_virt_mehtod_for_binfo (token, binfo, &delta, - !DECL_P (obj)); + fndecl = gimple_get_virt_mehtod_for_binfo (token, binfo, &delta, false); if (!fndecl) return false; - - if (integer_nonzerop (delta)) - { - if (inplace) - return false; - gimple_adjust_this_by_delta (gsi, delta); - } - + gcc_assert (integer_zerop (delta)); gimple_call_set_fndecl (stmt, fndecl); return true; } @@ -1595,7 +1507,7 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) here where we can just smash the call operand. */ callee = gimple_call_fn (stmt); if (TREE_CODE (callee) == OBJ_TYPE_REF) - return gimple_fold_obj_type_ref_call (gsi, inplace); + return gimple_fold_obj_type_ref_call (gsi); } return false; diff --git a/gcc/gimple.h b/gcc/gimple.h index c114e7c..cc35b60 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -892,7 +892,6 @@ unsigned get_gimple_rhs_num_ops (enum tree_code); gimple gimple_alloc_stat (enum gimple_code, unsigned MEM_STAT_DECL); const char *gimple_decl_printable_name (tree, int); bool gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace); -tree gimple_get_relevant_ref_binfo (tree ref, tree known_binfo); tree gimple_get_virt_mehtod_for_binfo (HOST_WIDE_INT, tree, tree *, bool); void gimple_adjust_this_by_delta (gimple_stmt_iterator *, tree); /* Returns true iff T is a valid GIMPLE statement. */ diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 24ccb92..ce6fd59 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -781,26 +781,16 @@ ipcp_propagate_types (struct ipa_node_params *caller_info, struct ipa_node_params *callee_info, struct ipa_jump_func *jf, int i) { - tree cst, binfo; - switch (jf->type) { case IPA_JF_UNKNOWN: case IPA_JF_CONST_MEMBER_PTR: + case IPA_JF_CONST: break; case IPA_JF_KNOWN_TYPE: return ipcp_add_param_type (callee_info, i, jf->value.base_binfo); - case IPA_JF_CONST: - cst = jf->value.constant; - if (TREE_CODE (cst) != ADDR_EXPR) - break; - binfo = gimple_get_relevant_ref_binfo (TREE_OPERAND (cst, 0), NULL_TREE); - if (!binfo) - break; - return ipcp_add_param_type (callee_info, i, binfo); - case IPA_JF_PASS_THROUGH: case IPA_JF_ANCESTOR: return ipcp_copy_types (caller_info, callee_info, i, jf); @@ -1292,35 +1282,13 @@ ipcp_discover_new_direct_edges (struct cgraph_node *node, int index, tree cst) for (ie = node->indirect_calls; ie; ie = next_ie) { struct cgraph_indirect_call_info *ici = ie->indirect_info; - tree target, delta = NULL_TREE; next_ie = ie->next_callee; - if (ici->param_index != index) + if (ici->param_index != index + || ici->polymorphic) continue; - if (ici->polymorphic) - { - tree binfo; - HOST_WIDE_INT token; - - if (TREE_CODE (cst) != ADDR_EXPR) - continue; - - binfo = gimple_get_relevant_ref_binfo (TREE_OPERAND (cst, 0), - NULL_TREE); - if (!binfo) - continue; - gcc_assert (ie->indirect_info->anc_offset == 0); - token = ie->indirect_info->otr_token; - target = gimple_get_virt_mehtod_for_binfo (token, binfo, &delta, - true); - if (!target) - continue; - } - else - target = cst; - - ipa_make_edge_direct_to_target (ie, target, delta); + ipa_make_edge_direct_to_target (ie, cst, NULL_TREE); } } diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index f0a5c60..b6e3f37 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -362,7 +362,7 @@ compute_complex_assign_jump_func (struct ipa_node_params *info, gimple stmt, tree name) { HOST_WIDE_INT offset, size, max_size; - tree op1, op2, type; + tree op1, op2, base, type; int index; op1 = gimple_assign_rhs1 (stmt); @@ -404,20 +404,21 @@ compute_complex_assign_jump_func (struct ipa_node_params *info, type = TREE_TYPE (op1); if (TREE_CODE (type) != RECORD_TYPE) return; - op1 = get_ref_base_and_extent (op1, &offset, &size, &max_size); - if (TREE_CODE (op1) != MEM_REF + base = get_ref_base_and_extent (op1, &offset, &size, &max_size); + if (TREE_CODE (base) != MEM_REF /* If this is a varying address, punt. */ || max_size == -1 || max_size != size) return; - offset += mem_ref_offset (op1).low * BITS_PER_UNIT; - op1 = TREE_OPERAND (op1, 0); - if (TREE_CODE (op1) != SSA_NAME - || !SSA_NAME_IS_DEFAULT_DEF (op1) + offset += mem_ref_offset (base).low * BITS_PER_UNIT; + base = TREE_OPERAND (base, 0); + if (TREE_CODE (base) != SSA_NAME + || !SSA_NAME_IS_DEFAULT_DEF (base) || offset < 0) return; - index = ipa_get_param_decl_index (info, SSA_NAME_VAR (op1)); + /* Dynamic types are changed only in constructors and destructors and */ + index = ipa_get_param_decl_index (info, SSA_NAME_VAR (base)); if (index >= 0) { jfunc->type = IPA_JF_ANCESTOR; @@ -534,13 +535,26 @@ compute_complex_ancestor_jump_func (struct ipa_node_params *info, static void compute_known_type_jump_func (tree op, struct ipa_jump_func *jfunc) { - tree binfo; + HOST_WIDE_INT offset, size, max_size; + tree base, binfo; - if (TREE_CODE (op) != ADDR_EXPR) + if (TREE_CODE (op) != ADDR_EXPR + || TREE_CODE (TREE_TYPE (TREE_TYPE (op))) != RECORD_TYPE) return; op = TREE_OPERAND (op, 0); - binfo = gimple_get_relevant_ref_binfo (op, NULL_TREE); + base = get_ref_base_and_extent (op, &offset, &size, &max_size); + if (!DECL_P (base) + || max_size == -1 + || max_size != size + || TREE_CODE (TREE_TYPE (base)) != RECORD_TYPE + || is_global_var (base)) + return; + + binfo = TYPE_BINFO (TREE_TYPE (base)); + if (!binfo) + return; + binfo = get_binfo_at_offset (binfo, offset, TREE_TYPE (op)); if (binfo) { jfunc->type = IPA_JF_KNOWN_TYPE; @@ -1420,17 +1434,6 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs, src = ipa_get_ith_jump_func (top, dst->value.ancestor.formal_id); if (src->type == IPA_JF_KNOWN_TYPE) combine_known_type_and_ancestor_jfs (src, dst); - else if (src->type == IPA_JF_CONST) - { - struct ipa_jump_func kt_func; - - kt_func.type = IPA_JF_UNKNOWN; - compute_known_type_jump_func (src->value.constant, &kt_func); - if (kt_func.type == IPA_JF_KNOWN_TYPE) - combine_known_type_and_ancestor_jfs (&kt_func, dst); - else - dst->type = IPA_JF_UNKNOWN; - } else if (src->type == IPA_JF_PASS_THROUGH && src->value.pass_through.operation == NOP_EXPR) dst->value.ancestor.formal_id = src->value.pass_through.formal_id; @@ -1543,15 +1546,6 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie, if (jfunc->type == IPA_JF_KNOWN_TYPE) binfo = jfunc->value.base_binfo; - else if (jfunc->type == IPA_JF_CONST) - { - tree cst = jfunc->value.constant; - if (TREE_CODE (cst) == ADDR_EXPR) - binfo = gimple_get_relevant_ref_binfo (TREE_OPERAND (cst, 0), - NULL_TREE); - else - return NULL; - } else return NULL; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1af0c54..dd58aa5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,16 @@ +2010-12-22 Martin Jambor <mjambor@suse.cz> + + PR tree-optimization/45934 + PR tree-optimization/46302 + PR tree-optimization/46987 + * g++.dg/ipa/ipcp-ivi-1.C: Removed. + * g++.dg/ipa/ivinline-6.C: Likewise. + * g++.dg/otr-fold-1.C: Likewise. + * g++.dg/otr-fold-2.C: Likewise. + * g++.dg/tree-ssa/pr43411.C: Xfail dump scan. + * g++.dg/tree-ssa/pr45605.C: Likewise. + * g++.dg/tree-ssa/pr46987.C: New test. + 2010-12-22 Steven Bosscher <steven@gcc.gnu.org> * gfortran.dg/pr46755.f: Fix test case. diff --git a/gcc/testsuite/g++.dg/ipa/ipcp-ivi-1.C b/gcc/testsuite/g++.dg/ipa/ipcp-ivi-1.C deleted file mode 100644 index 5b12a15..0000000 --- a/gcc/testsuite/g++.dg/ipa/ipcp-ivi-1.C +++ /dev/null @@ -1,65 +0,0 @@ -/* Verify that simple virtual calls are inlined even without early - inlining. */ -/* { dg-do run } */ -/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining" } */ - -extern "C" void abort (void); - -class A -{ -public: - int data; - virtual int foo (int i); -}; - -class B : public A -{ -public: - virtual int foo (int i); -}; - -class C : public A -{ -public: - virtual int foo (int i); -}; - -int A::foo (int i) -{ - return i + 1; -} - -int B::foo (int i) -{ - return i + 2; -} - -int C::foo (int i) -{ - return i + 3; -} - -int __attribute__ ((noinline)) middleman (class A *obj, int i) -{ - return obj->foo (i); -} - -int __attribute__ ((noinline,noclone)) get_input(void) -{ - return 1; -} - -class B b; - -int main (int argc, char *argv[]) -{ - int i; - - for (i = 0; i < get_input (); i++) - if (middleman (&b, get_input ()) != 3) - abort (); - return 0; -} - -/* { dg-final { scan-ipa-dump "B::foo\[^\\n\]*inline copy in int.*middleman" "inline" } } */ -/* { dg-final { cleanup-ipa-dump "inline" } } */ diff --git a/gcc/testsuite/g++.dg/ipa/ivinline-6.C b/gcc/testsuite/g++.dg/ipa/ivinline-6.C deleted file mode 100644 index 202e9e1..0000000 --- a/gcc/testsuite/g++.dg/ipa/ivinline-6.C +++ /dev/null @@ -1,58 +0,0 @@ -/* Verify that virtual call inlining works also when it has to get the - type from an ipa invariant and that even in this case it does not - pick a wrong method when there is a user defined ancestor in an - object. */ -/* { dg-do run } */ -/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp" } */ - -extern "C" void abort (void); - -class A -{ -public: - int data; - virtual int foo (int i); -}; - -class B : public A -{ -public: - class A confusion; - virtual int foo (int i); -}; - -int A::foo (int i) -{ - return i + 1; -} - -int B::foo (int i) -{ - return i + 2; -} - -int middleman (class A *obj, int i) -{ - return obj->foo (i); -} - -int __attribute__ ((noinline,noclone)) get_input(void) -{ - return 1; -} - -class B b; - -int main (int argc, char *argv[]) -{ - int i, j = get_input (); - - for (i = 0; i < j; i++) - if ((middleman (&b, j) + 100 * middleman (&b.confusion, j)) != 203) - abort (); - return 0; -} - -/* { dg-final { scan-ipa-dump "A::foo\[^\\n\]*inline copy in int main" "inline" } } */ -/* { dg-final { scan-ipa-dump "B::foo\[^\\n\]*inline copy in int main" "inline" } } */ -/* { dg-final { cleanup-ipa-dump "inline" } } */ diff --git a/gcc/testsuite/g++.dg/otr-fold-1.C b/gcc/testsuite/g++.dg/otr-fold-1.C deleted file mode 100644 index 2364730..0000000 --- a/gcc/testsuite/g++.dg/otr-fold-1.C +++ /dev/null @@ -1,76 +0,0 @@ -/* Verify that virtual calls are folded even when a typecast to an - ancestor is involved along the way. */ -/* { dg-do run } */ -/* { dg-options "-O -fdump-tree-optimized-slim" } */ - -extern "C" void abort (void); - -class Distraction -{ -public: - float f; - double d; - Distraction () - { - f = 8.3; - d = 10.2; - } - virtual float bar (float z); -}; - -class A -{ -public: - int data; - virtual int foo (int i); -}; - - -class B : public Distraction, public A -{ -public: - virtual int foo (int i); -}; - -float Distraction::bar (float z) -{ - f += z; - return f/2; -} - -int A::foo (int i) -{ - return i + 1; -} - -int B::foo (int i) -{ - return i + 2; -} - -int __attribute__ ((noinline,noclone)) get_input(void) -{ - return 1; -} - -static inline int middleman_1 (class A *obj, int i) -{ - return obj->foo (i); -} - -static inline int middleman_2 (class B *obj, int i) -{ - return middleman_1 (obj, i); -} - -int main (int argc, char *argv[]) -{ - class B b; - - if (middleman_2 (&b, get_input ()) != 3) - abort (); - return 0; -} - -/* { dg-final { scan-tree-dump "= B::.*foo" "optimized" } } */ -/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/g++.dg/otr-fold-2.C b/gcc/testsuite/g++.dg/otr-fold-2.C deleted file mode 100644 index a3cd1b5..0000000 --- a/gcc/testsuite/g++.dg/otr-fold-2.C +++ /dev/null @@ -1,88 +0,0 @@ -/* Verify that virtual calls are folded even when a typecast to an - ancestor is involved along the way. */ -/* { dg-do run } */ -/* { dg-options "-O -fdump-tree-optimized-slim" } */ - -extern "C" void abort (void); - -class Distraction -{ -public: - float f; - double d; - Distraction () - { - f = 8.3; - d = 10.2; - } - virtual float bar (float z); -}; - -class A -{ -public: - int data; - virtual int foo (int i); -}; - -class A_2 : public A -{ -public: - int data_2; - virtual int baz (int i); -}; - - -class B : public Distraction, public A_2 -{ -public: - virtual int foo (int i); -}; - -float Distraction::bar (float z) -{ - f += z; - return f/2; -} - -int A::foo (int i) -{ - return i + 1; -} - -int A_2::baz (int i) -{ - return i * 15; -} - -int B::foo (int i) -{ - return i + 2; -} - -int __attribute__ ((noinline,noclone)) get_input(void) -{ - return 1; -} - -static inline int middleman_1 (class A *obj, int i) -{ - return obj->foo (i); -} - -static inline int middleman_2 (class A *obj, int i) -{ - return middleman_1 (obj, i); -} - -int main (int argc, char *argv[]) -{ - class B b; - - if (middleman_2 (&b, get_input ()) != 3) - abort (); - return 0; -} - -/* { dg-final { scan-tree-dump "= B::.*foo" "optimized" } } */ -/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr43411.C b/gcc/testsuite/g++.dg/tree-ssa/pr43411.C index fcf1358..476e16a 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/pr43411.C +++ b/gcc/testsuite/g++.dg/tree-ssa/pr43411.C @@ -25,5 +25,5 @@ void testInlinePsub() { sink1 = v(p); } -// { dg-final { scan-tree-dump-not "OBJ_TYPE_REF" "optimized" } } +// { dg-final { scan-tree-dump-not "OBJ_TYPE_REF" "optimized" { xfail *-*-* } } } // { dg-final { cleanup-tree-dump "optimized" } } diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr45605.C b/gcc/testsuite/g++.dg/tree-ssa/pr45605.C index 20c4ba8..861b122 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/pr45605.C +++ b/gcc/testsuite/g++.dg/tree-ssa/pr45605.C @@ -33,5 +33,5 @@ int main() { /* We should devirtualize call to D::Run */ -/* { dg-final { scan-tree-dump-times "D::Run \\(" 1 "ssa"} } */ +/* { dg-final { scan-tree-dump-times "D::Run \\(" 1 "ssa" { xfail *-*-* } } } */ /* { dg-final { cleanup-tree-dump "ssa" } } */ diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr46987.C b/gcc/testsuite/g++.dg/tree-ssa/pr46987.C new file mode 100644 index 0000000..7163915 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr46987.C @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct A { + virtual A *getThis(); +}; + +struct B { + virtual B *getThis(); +}; + +struct AB : public A, public B { + virtual AB *getThis() { return 0; } +}; + +void foo () +{ + AB ab; + B *b = &ab; + b->getThis(); +} + @@ -10949,8 +10949,7 @@ get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type) if (type == expected_type) return binfo; - if (TREE_CODE (type) != RECORD_TYPE - || offset < 0) + if (offset < 0) return NULL_TREE; for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld)) @@ -10963,12 +10962,18 @@ get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type) if (pos <= offset && (pos + size) > offset) break; } - if (!fld || !DECL_ARTIFICIAL (fld)) + if (!fld || TREE_CODE (TREE_TYPE (fld)) != RECORD_TYPE) return NULL_TREE; + if (!DECL_ARTIFICIAL (fld)) + { + binfo = TYPE_BINFO (TREE_TYPE (fld)); + if (!binfo) + return NULL_TREE; + } /* Offset 0 indicates the primary base, whose vtable contents are represented in the binfo for the derived class. */ - if (offset != 0) + else if (offset != 0) { tree base_binfo, found_binfo = NULL_TREE; for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) |