ipa-devirt.c (polymorphic_call_target_d): Add SPECULATIVE; reorder for better storage.
* ipa-devirt.c (polymorphic_call_target_d): Add SPECULATIVE; reorder for better storage. (polymorphic_call_target_hasher::hash): Hash SPECULATIVE. (possible_polymorphic_call_targets): Instead of computing both speculative and non-speculative answers, do just one at a time. Replace NONSPECULATIVE_TARGETSP parameter with SPECULATIVE flag. (dump_targets): Break out from ... (dump_possible_polymorphic_call_targets): ... here; dump both speculative and non-speculative lists. (ipa_devirt): Update for new possible_polymorphic_call_targets API. * ipa-utils.h (possible_polymorphic_call_targets): Update. * testsuite/g++.dg/ipa/devirt-34.C: Update template. From-SVN: r215614
This commit is contained in:
parent
0be35aa0a1
commit
2f28755fbf
@ -1,3 +1,17 @@
|
||||
2014-09-25 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
* ipa-devirt.c (polymorphic_call_target_d): Add SPECULATIVE; reorder
|
||||
for better storage.
|
||||
(polymorphic_call_target_hasher::hash): Hash SPECULATIVE.
|
||||
(possible_polymorphic_call_targets): Instead of computing both
|
||||
speculative and non-speculative answers, do just one at a time.
|
||||
Replace NONSPECULATIVE_TARGETSP parameter with SPECULATIVE flag.
|
||||
(dump_targets): Break out from ...
|
||||
(dump_possible_polymorphic_call_targets): ... here; dump both speculative
|
||||
and non-speculative lists.
|
||||
(ipa_devirt): Update for new possible_polymorphic_call_targets API.
|
||||
* ipa-utils.h (possible_polymorphic_call_targets): Update.
|
||||
|
||||
2014-09-25 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
PR rtl-optimization/63348
|
||||
|
324
gcc/ipa-devirt.c
324
gcc/ipa-devirt.c
@ -1884,10 +1884,10 @@ struct polymorphic_call_target_d
|
||||
ipa_polymorphic_call_context context;
|
||||
odr_type type;
|
||||
vec <cgraph_node *> targets;
|
||||
int speculative_targets;
|
||||
bool complete;
|
||||
int type_warning;
|
||||
tree decl_warning;
|
||||
int type_warning;
|
||||
bool complete;
|
||||
bool speculative;
|
||||
};
|
||||
|
||||
/* Polymorphic call target cache helpers. */
|
||||
@ -1917,6 +1917,7 @@ polymorphic_call_target_hasher::hash (const value_type *odr_query)
|
||||
hstate.merge_hash (TYPE_UID (odr_query->context.speculative_outer_type));
|
||||
hstate.add_wide_int (odr_query->context.speculative_offset);
|
||||
}
|
||||
hstate.add_flag (odr_query->speculative);
|
||||
hstate.add_flag (odr_query->context.maybe_in_construction);
|
||||
hstate.add_flag (odr_query->context.maybe_derived_type);
|
||||
hstate.add_flag (odr_query->context.speculative_maybe_derived_type);
|
||||
@ -1931,6 +1932,7 @@ polymorphic_call_target_hasher::equal (const value_type *t1,
|
||||
const compare_type *t2)
|
||||
{
|
||||
return (t1->type == t2->type && t1->otr_token == t2->otr_token
|
||||
&& t1->speculative == t2->speculative
|
||||
&& t1->context.offset == t2->context.offset
|
||||
&& t1->context.speculative_offset == t2->context.speculative_offset
|
||||
&& t1->context.outer_type == t2->context.outer_type
|
||||
@ -3667,10 +3669,8 @@ struct final_warning_record *final_warning_records;
|
||||
in the target cache. If user needs to visit every target list
|
||||
just once, it can memoize them.
|
||||
|
||||
SPECULATION_TARGETS specify number of targets that are speculatively
|
||||
likely. These include targets specified by the speculative part
|
||||
of polymoprhic call context and also exclude all targets for classes
|
||||
in construction.
|
||||
If SPECULATIVE is set, the list will not contain targets that
|
||||
are not speculatively taken.
|
||||
|
||||
Returned vector is placed into cache. It is NOT caller's responsibility
|
||||
to free it. The vector can be freed on cgraph_remove_node call if
|
||||
@ -3682,7 +3682,7 @@ possible_polymorphic_call_targets (tree otr_type,
|
||||
ipa_polymorphic_call_context context,
|
||||
bool *completep,
|
||||
void **cache_token,
|
||||
int *speculative_targetsp)
|
||||
bool speculative)
|
||||
{
|
||||
static struct cgraph_node_hook_list *node_removal_hook_holder;
|
||||
vec <cgraph_node *> nodes = vNULL;
|
||||
@ -3706,13 +3706,11 @@ possible_polymorphic_call_targets (tree otr_type,
|
||||
*completep = context.invalid;
|
||||
if (cache_token)
|
||||
*cache_token = NULL;
|
||||
if (speculative_targetsp)
|
||||
*speculative_targetsp = 0;
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/* Do not bother to compute speculative info when user do not asks for it. */
|
||||
if (!speculative_targetsp || !context.speculative_outer_type)
|
||||
if (!speculative || !context.speculative_outer_type)
|
||||
context.clear_speculation ();
|
||||
|
||||
type = get_odr_type (otr_type, true);
|
||||
@ -3730,8 +3728,6 @@ possible_polymorphic_call_targets (tree otr_type,
|
||||
*completep = true;
|
||||
if (cache_token)
|
||||
*cache_token = NULL;
|
||||
if (speculative_targetsp)
|
||||
*speculative_targetsp = 0;
|
||||
return nodes;
|
||||
}
|
||||
gcc_assert (!context.invalid);
|
||||
@ -3783,6 +3779,7 @@ possible_polymorphic_call_targets (tree otr_type,
|
||||
/* Lookup cached answer. */
|
||||
key.type = type;
|
||||
key.otr_token = otr_token;
|
||||
key.speculative = speculative;
|
||||
key.context = context;
|
||||
slot = polymorphic_call_target_hash->find_slot (&key, INSERT);
|
||||
if (cache_token)
|
||||
@ -3791,15 +3788,13 @@ possible_polymorphic_call_targets (tree otr_type,
|
||||
{
|
||||
if (completep)
|
||||
*completep = (*slot)->complete;
|
||||
if (speculative_targetsp)
|
||||
*speculative_targetsp = (*slot)->speculative_targets;
|
||||
if ((*slot)->type_warning && final_warning_records)
|
||||
{
|
||||
final_warning_records->type_warnings[(*slot)->type_warning - 1].count++;
|
||||
final_warning_records->type_warnings[(*slot)->type_warning - 1].dyn_count
|
||||
+= final_warning_records->dyn_count;
|
||||
}
|
||||
if ((*slot)->decl_warning && final_warning_records)
|
||||
if (!speculative && (*slot)->decl_warning && final_warning_records)
|
||||
{
|
||||
struct decl_warn_count *c =
|
||||
final_warning_records->decl_warnings.get ((*slot)->decl_warning);
|
||||
@ -3819,7 +3814,7 @@ possible_polymorphic_call_targets (tree otr_type,
|
||||
(*slot)->type = type;
|
||||
(*slot)->otr_token = otr_token;
|
||||
(*slot)->context = context;
|
||||
(*slot)->speculative_targets = 0;
|
||||
(*slot)->speculative = speculative;
|
||||
|
||||
hash_set<tree> inserted;
|
||||
hash_set<tree> matched_vtables;
|
||||
@ -3864,137 +3859,136 @@ possible_polymorphic_call_targets (tree otr_type,
|
||||
&speculation_complete,
|
||||
bases_to_consider,
|
||||
false);
|
||||
(*slot)->speculative_targets = nodes.length();
|
||||
}
|
||||
|
||||
/* First see virtual method of type itself. */
|
||||
binfo = get_binfo_at_offset (TYPE_BINFO (outer_type->type),
|
||||
context.offset, otr_type);
|
||||
if (binfo)
|
||||
target = gimple_get_virt_method_for_binfo (otr_token, binfo,
|
||||
&can_refer);
|
||||
else
|
||||
if (!speculative || !nodes.length ())
|
||||
{
|
||||
gcc_assert (odr_violation_reported);
|
||||
target = NULL;
|
||||
}
|
||||
|
||||
/* Destructors are never called through construction virtual tables,
|
||||
because the type is always known. */
|
||||
if (target && DECL_CXX_DESTRUCTOR_P (target))
|
||||
context.maybe_in_construction = false;
|
||||
|
||||
if (target)
|
||||
{
|
||||
/* In the case we get complete method, we don't need
|
||||
to walk derivations. */
|
||||
if (DECL_FINAL_P (target))
|
||||
context.maybe_derived_type = false;
|
||||
}
|
||||
|
||||
/* If OUTER_TYPE is abstract, we know we are not seeing its instance. */
|
||||
if (type_possibly_instantiated_p (outer_type->type))
|
||||
maybe_record_node (nodes, target, &inserted, can_refer, &complete);
|
||||
else
|
||||
skipped = true;
|
||||
|
||||
if (binfo)
|
||||
matched_vtables.add (BINFO_VTABLE (binfo));
|
||||
|
||||
/* Next walk recursively all derived types. */
|
||||
if (context.maybe_derived_type)
|
||||
{
|
||||
for (i = 0; i < outer_type->derived_types.length(); i++)
|
||||
possible_polymorphic_call_targets_1 (nodes, &inserted,
|
||||
&matched_vtables,
|
||||
otr_type,
|
||||
outer_type->derived_types[i],
|
||||
otr_token, outer_type->type,
|
||||
context.offset, &complete,
|
||||
bases_to_consider,
|
||||
context.maybe_in_construction);
|
||||
|
||||
if (!outer_type->all_derivations_known)
|
||||
/* First see virtual method of type itself. */
|
||||
binfo = get_binfo_at_offset (TYPE_BINFO (outer_type->type),
|
||||
context.offset, otr_type);
|
||||
if (binfo)
|
||||
target = gimple_get_virt_method_for_binfo (otr_token, binfo,
|
||||
&can_refer);
|
||||
else
|
||||
{
|
||||
if (final_warning_records)
|
||||
{
|
||||
if (complete
|
||||
&& nodes.length () == 1
|
||||
&& warn_suggest_final_types
|
||||
&& !outer_type->derived_types.length ())
|
||||
{
|
||||
if (outer_type->id >= (int)final_warning_records->type_warnings.length ())
|
||||
final_warning_records->type_warnings.safe_grow_cleared
|
||||
(odr_types.length ());
|
||||
final_warning_records->type_warnings[outer_type->id].count++;
|
||||
final_warning_records->type_warnings[outer_type->id].dyn_count
|
||||
+= final_warning_records->dyn_count;
|
||||
final_warning_records->type_warnings[outer_type->id].type
|
||||
= outer_type->type;
|
||||
(*slot)->type_warning = outer_type->id + 1;
|
||||
}
|
||||
if (complete
|
||||
&& warn_suggest_final_methods
|
||||
&& nodes.length () == 1
|
||||
&& types_same_for_odr (DECL_CONTEXT (nodes[0]->decl),
|
||||
outer_type->type))
|
||||
{
|
||||
bool existed;
|
||||
struct decl_warn_count &c =
|
||||
final_warning_records->decl_warnings.get_or_insert
|
||||
(nodes[0]->decl, &existed);
|
||||
gcc_assert (odr_violation_reported);
|
||||
target = NULL;
|
||||
}
|
||||
|
||||
if (existed)
|
||||
/* Destructors are never called through construction virtual tables,
|
||||
because the type is always known. */
|
||||
if (target && DECL_CXX_DESTRUCTOR_P (target))
|
||||
context.maybe_in_construction = false;
|
||||
|
||||
if (target)
|
||||
{
|
||||
/* In the case we get complete method, we don't need
|
||||
to walk derivations. */
|
||||
if (DECL_FINAL_P (target))
|
||||
context.maybe_derived_type = false;
|
||||
}
|
||||
|
||||
/* If OUTER_TYPE is abstract, we know we are not seeing its instance. */
|
||||
if (type_possibly_instantiated_p (outer_type->type))
|
||||
maybe_record_node (nodes, target, &inserted, can_refer, &complete);
|
||||
else
|
||||
skipped = true;
|
||||
|
||||
if (binfo)
|
||||
matched_vtables.add (BINFO_VTABLE (binfo));
|
||||
|
||||
/* Next walk recursively all derived types. */
|
||||
if (context.maybe_derived_type)
|
||||
{
|
||||
for (i = 0; i < outer_type->derived_types.length(); i++)
|
||||
possible_polymorphic_call_targets_1 (nodes, &inserted,
|
||||
&matched_vtables,
|
||||
otr_type,
|
||||
outer_type->derived_types[i],
|
||||
otr_token, outer_type->type,
|
||||
context.offset, &complete,
|
||||
bases_to_consider,
|
||||
context.maybe_in_construction);
|
||||
|
||||
if (!outer_type->all_derivations_known)
|
||||
{
|
||||
if (!speculative && final_warning_records)
|
||||
{
|
||||
if (complete
|
||||
&& nodes.length () == 1
|
||||
&& warn_suggest_final_types
|
||||
&& !outer_type->derived_types.length ())
|
||||
{
|
||||
c.count++;
|
||||
c.dyn_count += final_warning_records->dyn_count;
|
||||
if (outer_type->id >= (int)final_warning_records->type_warnings.length ())
|
||||
final_warning_records->type_warnings.safe_grow_cleared
|
||||
(odr_types.length ());
|
||||
final_warning_records->type_warnings[outer_type->id].count++;
|
||||
final_warning_records->type_warnings[outer_type->id].dyn_count
|
||||
+= final_warning_records->dyn_count;
|
||||
final_warning_records->type_warnings[outer_type->id].type
|
||||
= outer_type->type;
|
||||
(*slot)->type_warning = outer_type->id + 1;
|
||||
}
|
||||
else
|
||||
if (complete
|
||||
&& warn_suggest_final_methods
|
||||
&& nodes.length () == 1
|
||||
&& types_same_for_odr (DECL_CONTEXT (nodes[0]->decl),
|
||||
outer_type->type))
|
||||
{
|
||||
c.count = 1;
|
||||
c.dyn_count = final_warning_records->dyn_count;
|
||||
c.decl = nodes[0]->decl;
|
||||
bool existed;
|
||||
struct decl_warn_count &c =
|
||||
final_warning_records->decl_warnings.get_or_insert
|
||||
(nodes[0]->decl, &existed);
|
||||
|
||||
if (existed)
|
||||
{
|
||||
c.count++;
|
||||
c.dyn_count += final_warning_records->dyn_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
c.count = 1;
|
||||
c.dyn_count = final_warning_records->dyn_count;
|
||||
c.decl = nodes[0]->decl;
|
||||
}
|
||||
(*slot)->decl_warning = nodes[0]->decl;
|
||||
}
|
||||
(*slot)->decl_warning = nodes[0]->decl;
|
||||
}
|
||||
complete = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!speculative)
|
||||
{
|
||||
/* Destructors are never called through construction virtual tables,
|
||||
because the type is always known. One of entries may be cxa_pure_virtual
|
||||
so look to at least two of them. */
|
||||
if (context.maybe_in_construction)
|
||||
for (i =0 ; i < MIN (nodes.length (), 2); i++)
|
||||
if (DECL_CXX_DESTRUCTOR_P (nodes[i]->decl))
|
||||
context.maybe_in_construction = false;
|
||||
if (context.maybe_in_construction)
|
||||
{
|
||||
if (type != outer_type
|
||||
&& (!skipped
|
||||
|| (context.maybe_derived_type
|
||||
&& !type_all_derivations_known_p (outer_type->type))))
|
||||
record_targets_from_bases (otr_type, otr_token, outer_type->type,
|
||||
context.offset, nodes, &inserted,
|
||||
&matched_vtables, &complete);
|
||||
if (skipped)
|
||||
maybe_record_node (nodes, target, &inserted, can_refer, &complete);
|
||||
for (i = 0; i < bases_to_consider.length(); i++)
|
||||
maybe_record_node (nodes, bases_to_consider[i], &inserted, can_refer, &complete);
|
||||
}
|
||||
complete = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally walk bases, if asked to. */
|
||||
if (!(*slot)->speculative_targets)
|
||||
(*slot)->speculative_targets = nodes.length();
|
||||
|
||||
/* Destructors are never called through construction virtual tables,
|
||||
because the type is always known. One of entries may be cxa_pure_virtual
|
||||
so look to at least two of them. */
|
||||
if (context.maybe_in_construction)
|
||||
for (i =0 ; i < MIN (nodes.length (), 2); i++)
|
||||
if (DECL_CXX_DESTRUCTOR_P (nodes[i]->decl))
|
||||
context.maybe_in_construction = false;
|
||||
if (context.maybe_in_construction)
|
||||
{
|
||||
if (type != outer_type
|
||||
&& (!skipped
|
||||
|| (context.maybe_derived_type
|
||||
&& !type_all_derivations_known_p (outer_type->type))))
|
||||
record_targets_from_bases (otr_type, otr_token, outer_type->type,
|
||||
context.offset, nodes, &inserted,
|
||||
&matched_vtables, &complete);
|
||||
if (skipped)
|
||||
maybe_record_node (nodes, target, &inserted, can_refer, &complete);
|
||||
for (i = 0; i < bases_to_consider.length(); i++)
|
||||
maybe_record_node (nodes, bases_to_consider[i], &inserted, can_refer, &complete);
|
||||
}
|
||||
bases_to_consider.release();
|
||||
|
||||
(*slot)->targets = nodes;
|
||||
(*slot)->complete = complete;
|
||||
if (completep)
|
||||
*completep = complete;
|
||||
if (speculative_targetsp)
|
||||
*speculative_targetsp = (*slot)->speculative_targets;
|
||||
|
||||
timevar_pop (TV_IPA_VIRTUAL_CALL);
|
||||
return nodes;
|
||||
@ -4008,6 +4002,29 @@ add_decl_warning (const tree &key ATTRIBUTE_UNUSED, const decl_warn_count &value
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Dump target list TARGETS into FILE. */
|
||||
|
||||
static void
|
||||
dump_targets (FILE *f, vec <cgraph_node *> targets)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < targets.length (); i++)
|
||||
{
|
||||
char *name = NULL;
|
||||
if (in_lto_p)
|
||||
name = cplus_demangle_v3 (targets[i]->asm_name (), 0);
|
||||
fprintf (f, " %s/%i", name ? name : targets[i]->name (), targets[i]->order);
|
||||
if (in_lto_p)
|
||||
free (name);
|
||||
if (!targets[i]->definition)
|
||||
fprintf (f, " (no definition%s)",
|
||||
DECL_DECLARED_INLINE_P (targets[i]->decl)
|
||||
? " inline" : "");
|
||||
}
|
||||
fprintf (f, "\n");
|
||||
}
|
||||
|
||||
/* Dump all possible targets of a polymorphic call. */
|
||||
|
||||
void
|
||||
@ -4019,14 +4036,13 @@ dump_possible_polymorphic_call_targets (FILE *f,
|
||||
vec <cgraph_node *> targets;
|
||||
bool final;
|
||||
odr_type type = get_odr_type (TYPE_MAIN_VARIANT (otr_type), false);
|
||||
unsigned int i;
|
||||
int speculative;
|
||||
unsigned int len;
|
||||
|
||||
if (!type)
|
||||
return;
|
||||
targets = possible_polymorphic_call_targets (otr_type, otr_token,
|
||||
ctx,
|
||||
&final, NULL, &speculative);
|
||||
&final, NULL, false);
|
||||
fprintf (f, " Targets of polymorphic call of type %i:", type->id);
|
||||
print_generic_expr (f, type->type, TDF_SLIM);
|
||||
fprintf (f, " token %i\n", (int)otr_token);
|
||||
@ -4039,23 +4055,19 @@ dump_possible_polymorphic_call_targets (FILE *f,
|
||||
ctx.maybe_in_construction ? " (base types included)" : "",
|
||||
ctx.maybe_derived_type ? " (derived types included)" : "",
|
||||
ctx.speculative_maybe_derived_type ? " (speculative derived types included)" : "");
|
||||
for (i = 0; i < targets.length (); i++)
|
||||
len = targets.length ();
|
||||
dump_targets (f, targets);
|
||||
|
||||
targets = possible_polymorphic_call_targets (otr_type, otr_token,
|
||||
ctx,
|
||||
&final, NULL, true);
|
||||
gcc_assert (targets.length () <= len);
|
||||
if (targets.length () != len)
|
||||
{
|
||||
char *name = NULL;
|
||||
if (i == (unsigned)speculative)
|
||||
fprintf (f, "\n Targets that are not likely:\n"
|
||||
" ");
|
||||
if (in_lto_p)
|
||||
name = cplus_demangle_v3 (targets[i]->asm_name (), 0);
|
||||
fprintf (f, " %s/%i", name ? name : targets[i]->name (), targets[i]->order);
|
||||
if (in_lto_p)
|
||||
free (name);
|
||||
if (!targets[i]->definition)
|
||||
fprintf (f, " (no definition%s)",
|
||||
DECL_DECLARED_INLINE_P (targets[i]->decl)
|
||||
? " inline" : "");
|
||||
fprintf (f, " Speculative targets:");
|
||||
dump_targets (f, targets);
|
||||
}
|
||||
fprintf (f, "\n\n");
|
||||
fprintf (f, "\n");
|
||||
}
|
||||
|
||||
|
||||
@ -4241,16 +4253,19 @@ ipa_devirt (void)
|
||||
struct cgraph_node *likely_target = NULL;
|
||||
void *cache_token;
|
||||
bool final;
|
||||
int speculative_targets;
|
||||
|
||||
if (final_warning_records)
|
||||
final_warning_records->dyn_count = e->count;
|
||||
|
||||
vec <cgraph_node *>targets
|
||||
= possible_polymorphic_call_targets
|
||||
(e, &final, &cache_token, &speculative_targets);
|
||||
(e, &final, &cache_token, true);
|
||||
unsigned int i;
|
||||
|
||||
/* Trigger warnings by calculating non-speculative targets. */
|
||||
if (warn_suggest_final_methods || warn_suggest_final_types)
|
||||
possible_polymorphic_call_targets (e);
|
||||
|
||||
if (dump_file)
|
||||
dump_possible_polymorphic_call_targets
|
||||
(dump_file, e);
|
||||
@ -4289,13 +4304,10 @@ ipa_devirt (void)
|
||||
{
|
||||
if (likely_target)
|
||||
{
|
||||
if (i < (unsigned) speculative_targets)
|
||||
{
|
||||
likely_target = NULL;
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "More than one likely target\n\n");
|
||||
nmultiple++;
|
||||
}
|
||||
likely_target = NULL;
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "More than one likely target\n\n");
|
||||
nmultiple++;
|
||||
break;
|
||||
}
|
||||
likely_target = targets[i];
|
||||
|
@ -62,7 +62,7 @@ possible_polymorphic_call_targets (tree, HOST_WIDE_INT,
|
||||
ipa_polymorphic_call_context,
|
||||
bool *copletep = NULL,
|
||||
void **cache_token = NULL,
|
||||
int *nonconstruction_targets = NULL);
|
||||
bool speuclative = false);
|
||||
odr_type get_odr_type (tree, bool insert = false);
|
||||
bool possible_polymorphic_call_target_p (tree ref, gimple stmt, struct cgraph_node *n);
|
||||
void dump_possible_polymorphic_call_targets (FILE *, tree, HOST_WIDE_INT,
|
||||
@ -92,7 +92,7 @@ inline vec <cgraph_node *>
|
||||
possible_polymorphic_call_targets (struct cgraph_edge *e,
|
||||
bool *completep = NULL,
|
||||
void **cache_token = NULL,
|
||||
int *nonconstruction_targets = NULL)
|
||||
bool speculative = false)
|
||||
{
|
||||
ipa_polymorphic_call_context context(e);
|
||||
|
||||
@ -100,7 +100,7 @@ possible_polymorphic_call_targets (struct cgraph_edge *e,
|
||||
e->indirect_info->otr_token,
|
||||
context,
|
||||
completep, cache_token,
|
||||
nonconstruction_targets);
|
||||
speculative);
|
||||
}
|
||||
|
||||
/* Same as above but taking OBJ_TYPE_REF as an parameter. */
|
||||
|
@ -1,3 +1,7 @@
|
||||
2014-09-25 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
* testsuite/g++.dg/ipa/devirt-34.C: Update template.
|
||||
|
||||
2014-09-25 James Greenhalgh <james.greenhalgh@arm.com>
|
||||
|
||||
* gcc.target/aarch64/simd/vqshlb_1.c: New.
|
||||
|
@ -15,6 +15,6 @@ t(struct B *b)
|
||||
/* We should guess that the pointer of type B probably points to an instance
|
||||
of B or its derivates and exclude A::t from list of likely targets. */
|
||||
|
||||
/* { dg-final { scan-ipa-dump "Targets that are not likely" "devirt" } } */
|
||||
/* { dg-final { scan-ipa-dump "Speculative targets" "devirt" } } */
|
||||
/* { dg-final { scan-ipa-dump "1 speculatively devirtualized" "devirt" } } */
|
||||
/* { dg-final { cleanup-ipa-dump "devirt" } } */
|
||||
|
Loading…
Reference in New Issue
Block a user