Limit the number of relations registered per basic block.
authorAndrew MacLeod <amacleod@redhat.com>
Mon, 17 Jan 2022 17:03:18 +0000 (12:03 -0500)
committerAndrew MacLeod <amacleod@redhat.com>
Tue, 18 Jan 2022 15:02:02 +0000 (10:02 -0500)
In pathological cases, the number of transitive relations being added is
potentially quadratic.  Lookups for relations in a block is linear in
nature, so simply limit the number of relations to some reasonable number.

PR tree-optimization/104038
* doc/invoke.texi (relation-block-limit): New.
* params.opt (relation-block-limit): New.
* value-relation.cc (dom_oracle::register_relation): Check for NULL
record before invoking transitive registery.
(dom_oracle::set_one_relation): Check limit before creating record.
(dom_oracle::register_transitives): Stop when no record created.
* value-relation.h (relation_chain_head::m_num_relations): New.

gcc/doc/invoke.texi
gcc/params.opt
gcc/value-relation.cc
gcc/value-relation.h

index 96a64f3..58751c4 100644 (file)
@@ -15088,6 +15088,9 @@ per supernode, before terminating analysis.
 Maximum depth of logical expression evaluation ranger will look through
 when evaluating outgoing edge ranges.
 
+@item relation-block-limit
+Maximum number of relations the oracle will register in a basic block.
+
 @item openacc-kernels
 Specify mode of OpenACC `kernels' constructs handling.
 With @option{--param=openacc-kernels=decompose}, OpenACC `kernels'
index 665071f..b07663d 100644 (file)
@@ -915,6 +915,10 @@ Common Joined UInteger Var(param_ranger_logical_depth) Init(6) IntegerRange(1, 9
 Maximum depth of logical expression evaluation ranger will look through when
 evaluating outgoing edge ranges.
 
+-param=relation-block-limit=
+Common Joined UInteger Var(param_relation_block_limit) Init(200) IntegerRange(0, 9999) Param Optimization
+Maximum number of relations the oracle will register in a basic block.
+
 -param=rpo-vn-max-loop-depth=
 Common Joined UInteger Var(param_rpo_vn_max_loop_depth) Init(7) IntegerRange(2, 65536) Param Optimization
 Maximum depth of a loop nest to fully value-number optimistically.
index 1e495bd..32ca693 100644 (file)
@@ -889,13 +889,14 @@ dom_oracle::register_relation (basic_block bb, relation_kind k, tree op1,
   else
     {
       relation_chain *ptr = set_one_relation (bb, k, op1, op2);
-      register_transitives (bb, *ptr);
+      if (ptr)
+       register_transitives (bb, *ptr);
     }
 }
 
 // Register relation K between OP! and OP2 in block BB.
 // This creates the record and searches for existing records in the dominator
-// tree to merge with.
+// tree to merge with.  Return the record, or NULL if no record was created.
 
 relation_chain *
 dom_oracle::set_one_relation (basic_block bb, relation_kind k, tree op1,
@@ -940,6 +941,13 @@ dom_oracle::set_one_relation (basic_block bb, relation_kind k, tree op1,
     }
   else
     {
+      if (m_relations[bbi].m_num_relations >= param_relation_block_limit)
+       {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           fprintf (dump_file, "  Not registered due to bb being full\n");
+         return NULL;
+       }
+      m_relations[bbi].m_num_relations++;
       // Check for an existing relation further up the DOM chain.
       // By including dominating relations, The first one found in any search
       // will be the aggregate of all the previous ones.
@@ -1040,7 +1048,8 @@ dom_oracle::register_transitives (basic_block root_bb,
          value_relation nr (relation.kind (), r1, r2);
          if (nr.apply_transitive (*ptr))
            {
-             set_one_relation (root_bb, nr.kind (), nr.op1 (), nr.op2 ());
+             if (!set_one_relation (root_bb, nr.kind (), nr.op1 (), nr.op2 ()))
+               return;
              if (dump_file && (dump_flags & TDF_DETAILS))
                {
                  fprintf (dump_file, "   Registering transitive relation ");
index 207defa..44d0796 100644 (file)
@@ -157,6 +157,7 @@ class relation_chain_head
 public:
   bitmap m_names;              // ssa_names with relations in this block.
   class relation_chain *m_head; // List of relations in block.
+  int m_num_relations;         // Number of relations in block.
   relation_kind find_relation (const_bitmap b1, const_bitmap b2) const;
 };