OSDN Git Service

2010-12-22 Martin Jambor <mjambor@suse.cz>
authorjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 22 Dec 2010 12:56:54 +0000 (12:56 +0000)
committerjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 22 Dec 2010 12:56:54 +0000 (12:56 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@168168 138bc75d-0d04-0410-961f-82ee72b054a4

14 files changed:
gcc/ChangeLog
gcc/gimple-fold.c
gcc/gimple.h
gcc/ipa-cp.c
gcc/ipa-prop.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ipa/ipcp-ivi-1.C [deleted file]
gcc/testsuite/g++.dg/ipa/ivinline-6.C [deleted file]
gcc/testsuite/g++.dg/otr-fold-1.C [deleted file]
gcc/testsuite/g++.dg/otr-fold-2.C [deleted file]
gcc/testsuite/g++.dg/tree-ssa/pr43411.C
gcc/testsuite/g++.dg/tree-ssa/pr45605.C
gcc/testsuite/g++.dg/tree-ssa/pr46987.C [new file with mode: 0644]
gcc/tree.c

index a88274e..cbbd5ae 100644 (file)
@@ -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.
index b6c06fc..16a2092 100644 (file)
@@ -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;
index c114e7c..cc35b60 100644 (file)
@@ -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.  */
index 24ccb92..ce6fd59 100644 (file)
@@ -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);
     }
 }
 
index f0a5c60..b6e3f37 100644 (file)
@@ -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;
 
index 1af0c54..dd58aa5 100644 (file)
@@ -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 (file)
index 5b12a15..0000000
+++ /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 (file)
index 202e9e1..0000000
+++ /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 (file)
index 2364730..0000000
+++ /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 (file)
index a3cd1b5..0000000
+++ /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" } } */
index fcf1358..476e16a 100644 (file)
@@ -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" } }
index 20c4ba8..861b122 100644 (file)
@@ -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 (file)
index 0000000..7163915
--- /dev/null
@@ -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();
+}
+
index 5ac7fb0..2662278 100644 (file)
@@ -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++)