+2016-03-30 Michael Matz <matz@suse.de>
+ Richard Biener <rguenther@suse.de>
+
+ PR ipa/12392
+ * ipa-polymorphic-call.c (struct type_change_info): Change
+ speculative to an unsigned allowing to limit the work we do.
+ (csftc_abort_walking_p): New inline function..
+ (check_stmt_for_type_change): Limit the number of may-defs
+ skipped for speculative devirtualization to
+ max-speculative-devirt-maydefs.
+ * params.def (max-speculative-devirt-maydefs): New param.
+ * doc/invoke.texi (--param max-speculative-devirt-maydefs): Document.
+
2016-03-30 Mike Stump <mrs@gcc.gnu.org>
PR target/63890
#include "tree-dfa.h"
#include "gimple-pretty-print.h"
#include "tree-into-ssa.h"
+#include "params.h"
/* Return true when TYPE contains an polymorphic type and thus is interesting
for devirtualization machinery. */
tree known_current_type;
HOST_WIDE_INT known_current_offset;
+ /* Set to nonzero if we possibly missed some dynamic type changes and we
+ should consider the set to be speculative. */
+ unsigned speculative;
+
/* Set to true if dynamic type change has been detected. */
bool type_maybe_changed;
/* Set to true if multiple types have been encountered. known_current_type
must be disregarded in that case. */
bool multiple_types_encountered;
- /* Set to true if we possibly missed some dynamic type changes and we should
- consider the set to be speculative. */
- bool speculative;
bool seen_unanalyzed_store;
};
tci->type_maybe_changed = true;
}
+
+/* The maximum number of may-defs we visit when looking for a must-def
+ that changes the dynamic type in check_stmt_for_type_change. Tuned
+ after the PR12392 testcase which unlimited spends 40% time within
+ these alias walks and 8% with the following limit. */
+
+static inline bool
+csftc_abort_walking_p (unsigned speculative)
+{
+ unsigned max = PARAM_VALUE (PARAM_MAX_SPECULATIVE_DEVIRT_MAYDEFS);
+ return speculative > max ? true : false;
+}
+
/* Callback of walk_aliased_vdefs and a helper function for
detect_type_change to check whether a particular statement may modify
the virtual table pointer, and if possible also determine the new type of
&size, &max_size, &reverse);
if (size != max_size || max_size == -1)
{
- tci->speculative = true;
- return false;
+ tci->speculative++;
+ return csftc_abort_walking_p (tci->speculative);
}
if (op && TREE_CODE (op) == MEM_REF)
{
if (!tree_fits_shwi_p (TREE_OPERAND (op, 1)))
{
- tci->speculative = true;
- return false;
+ tci->speculative++;
+ return csftc_abort_walking_p (tci->speculative);
}
offset += tree_to_shwi (TREE_OPERAND (op, 1))
* BITS_PER_UNIT;
;
else
{
- tci->speculative = true;
- return false;
+ tci->speculative++;
+ return csftc_abort_walking_p (tci->speculative);
}
op = walk_ssa_copies (op);
}
fprintf (dump_file, " Function call may change dynamic type:");
print_gimple_stmt (dump_file, stmt, 0, 0);
}
- tci->speculative = true;
- return false;
+ tci->speculative++;
+ return csftc_abort_walking_p (tci->speculative);
}
/* Check for inlined virtual table store. */
else if (noncall_stmt_may_be_vtbl_ptr_store (stmt))
if (dump_file)
fprintf (dump_file, " Unanalyzed store may change type.\n");
tci->seen_unanalyzed_store = true;
- tci->speculative = true;
+ tci->speculative++;
}
else
record_known_type (tci, type, offset);
tci.otr_type = otr_type;
tci.type_maybe_changed = false;
tci.multiple_types_encountered = false;
- tci.speculative = false;
+ tci.speculative = 0;
tci.seen_unanalyzed_store = false;
walk_aliased_vdefs (&ao, gimple_vuse (stmt), check_stmt_for_type_change,