analyzer: add -param=analyzer-max-constraints=
authorDavid Malcolm <dmalcolm@redhat.com>
Sun, 13 Sep 2020 23:35:28 +0000 (19:35 -0400)
committerDavid Malcolm <dmalcolm@redhat.com>
Mon, 14 Sep 2020 16:29:35 +0000 (12:29 -0400)
On attempting to run the full test suite with -fanalyzer via
  make check RUNTESTFLAGS="-v -v --target_board=unix/-fanalyzer"
I saw it get stuck on:
  gcc.c-torture/compile/20001226-1.c
It turns out this was on a debug build, rather than a release build;
but a release build with -fanalyzer took:
  real 1m33.689s
  user 1m30.239s
  sys  0m2.727s
as compared to:
  real 0m2.361s
  user 0m2.107s
  sys  0m0.214s
without -fanalyzer.

This torture test performs 64 * 64 uniqely-coded comparisons between
elements of a pair of arrays until it finds an element that's different,
leading to an accumulation of 4096 constraints along the path where
no difference is found.

"perf" shows most of the time is spent in canonicalizing and copying
constraint_manager instances, presumably as it copies and merges states
with increasingly more complex sets of constraints as it analyzes
further along the "no differences yet" path.

This patch crudely works around this by adding a
  -param=analyzer-max-constraints=
limit, defaulting to 20, above which constraints will be silently
dropped.  With this -fanalyzer takes:
  real 0m6.935s
  user 0m6.413s
  sys  0m0.396s
on the above case.

gcc/analyzer/ChangeLog:
* analyzer.opt (-param=analyzer-max-constraints=): New param.
* constraint-manager.cc
(constraint_manager::add_constraint_internal): Silently reject
attempts to add constraints when the above limit is reached.

gcc/analyzer/analyzer.opt
gcc/analyzer/constraint-manager.cc

index 07bff33921713e61696a040c53540ce355e684d7..94a686db6b349c18e8d158bc8ef6dfd2a0c978d0 100644 (file)
@@ -30,6 +30,10 @@ The maximum number of 'after supernode' exploded nodes within the analyzer per s
 Common Joined UInteger Var(param_analyzer_max_enodes_per_program_point) Init(8) Param
 The maximum number of exploded nodes per program point within the analyzer, before terminating analysis of that point.
 
+-param=analyzer-max-constraints=
+Common Joined UInteger Var(param_analyzer_max_constraints) Init(20) Param
+The maximum number of constraints per state.
+
 -param=analyzer-max-recursion-depth=
 Common Joined UInteger Var(param_analyzer_max_recursion_depth) Init(2) Param
 The maximum number of times a callsite can appear in a call stack within the analyzer, before terminating analysis of a call that would recurse deeper.
index c10b770f29465762294dc5fe9182d8339b96ab22..e578e0502f2d919e4a1d013e770f6e8747b8ea05 100644 (file)
@@ -940,6 +940,9 @@ constraint_manager::add_constraint_internal (equiv_class_id lhs_id,
                                              enum constraint_op c_op,
                                              equiv_class_id rhs_id)
 {
+  if (m_constraints.length () >= param_analyzer_max_constraints)
+    return;
+
   constraint new_c (lhs_id, c_op, rhs_id);
 
   /* Remove existing constraints that would be implied by the