https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127410

            Bug ID: 127410
           Summary: SLP node data recording is not idempotent; re-analysis
                    discards the recorded result
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ptomsich at gcc dot gnu.org
  Target Milestone: ---

vect_slp_analyze_node_operations adds each node to visited_set, but when
analysis fails it pops the whole recursion back off again:

  if (!res)
    {
      while (visited_vec.length () >= visited_rec_start)
        visited_set.remove (visited_vec.pop ());
      cost_vec->truncate (cost_vec_rec_start);
    }

Nodes popped there can already carry analysis data: vect_slp_analyze_node_
operations_1 ran for them before a later sibling failed.  Once they are out
of visited_set, a later traversal analyzes them again.

The recording is not written for that:

  SLP_TREE_TYPE (slp_node) = call_simd_clone_vec_info_type;
  slp_node->data = new vect_simd_clone_data (std::move (_data));

On the second analysis get_data returns the object installed by the first, so
every update above lands in it, and this store then replaces it with the
untouched local _data.  For simd clones that is a correctness problem.

I have no testcase that reaches this on unmodified trunk.  It was found with
some experimental work (for astcenc_r) that retries cost-rejected BB-SLP 
subgraphs with shared children demoted (and re-analyzing): we were working to
address that vect_bb_partition_graph fuses SLP instances that share nodes into
one subgraph with an all-or-nothing cost verdict ... for this, we salvage an
instance out of a rejected subgraph and rscore after editing operands.

The open design question is: is re-analysis allowed or is a node analyzed at
most once?  If re-analysis is allowed (and that's how I read it), then the 
recording has to be idempotent with a change like the following:

  @@ vectorizable_simd_clone_call
         data.clone = bestn;
         data.clone_inbranch = bestn_inbranch;

  +      simd_clone_info.truncate (0);
         simd_clone_info.safe_push (NULL_TREE);
  @@
         SLP_TREE_TYPE (slp_node) = call_simd_clone_vec_info_type;
  -      slp_node->data = new vect_simd_clone_data (std::move (_data));
  +      if (!slp_node->data)
  +     slp_node->data = new vect_simd_clone_data (std::move (_data));
  @@ struct vect_simd_clone_data
  -  cgraph_node *clone;
  -  cgraph_node *clone_inbranch;
  +  cgraph_node *clone = nullptr;
  +  cgraph_node *clone_inbranch = nullptr;

Reply via email to