This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][RFC] Handle commutative operations in SLP tree build


This handles commutative operations during SLP tree build in the
way that if one configuration does not match, the build will
try again with commutated operands for.  This allows to remove
the special-casing of commutated loads in a complex addition
that was in the end handled as "permutation".  It of course
also applies more generally.  Permutation is currently limited
to 3 unsuccessful permutes to avoid running into the inherently
exponential complexity of tree matching.

The gcc.dg/vect/vect-complex-?.c testcases provide some testing
coverage (previously handled by the special-casing).  I have
seen failed SLP in the wild previously but it's usually on
larger testcases and dependent on operand order of commutative
operands.

I've discussed ideas to restrict the cases where we try a permutation
with Matz, but I'll rather defer that to an eventual followup.
(compute per SSA name a value dependent on the shape of its
use-def tree and use that as a quick check whether sub-trees
can possibly match)

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Any comments?

Thanks,
Richard.

2013-04-10  Richard Biener  <rguenther@suse.de>

	* tree-vect-slp.c (vect_build_slp_tree_1): Split out from ...
	(vect_build_slp_tree): ... here.
	(vect_build_slp_tree_1): Compute which stmts of the SLP group
	match.  Remove special-casing of mismatched complex loads.
	(vect_build_slp_tree): Based on the result from vect_build_slp_tree_1
	re-try the match with swapped commutative operands.
	(vect_supported_load_permutation_p): Remove special-casing of
	mismatched complex loads.
	(vect_analyze_slp_instance): Adjust.

Index: trunk/gcc/tree-vect-slp.c
===================================================================
*** trunk.orig/gcc/tree-vect-slp.c	2013-04-10 13:36:12.000000000 +0200
--- trunk/gcc/tree-vect-slp.c	2013-04-10 15:39:13.865325388 +0200
*************** vect_get_and_check_slp_defs (loop_vec_in
*** 376,400 ****
  }
  
  
! /* Recursively build an SLP tree starting from NODE.
!    Fail (and return FALSE) if def-stmts are not isomorphic, require data
!    permutation or are of unsupported types of operation.  Otherwise, return
!    TRUE.  */
  
  static bool
! vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
!                      slp_tree *node, unsigned int group_size,
!                      unsigned int *max_nunits,
!                      vec<slp_tree> *loads,
!                      unsigned int vectorization_factor)
  {
    unsigned int i;
-   vec<gimple> stmts = SLP_TREE_SCALAR_STMTS (*node);
    gimple stmt = stmts[0];
    enum tree_code first_stmt_code = ERROR_MARK, rhs_code = ERROR_MARK;
    enum tree_code first_cond_code = ERROR_MARK;
    tree lhs;
!   bool stop_recursion = false, need_same_oprnds = false;
    tree vectype, scalar_type, first_op1 = NULL_TREE;
    optab optab;
    int icode;
--- 376,400 ----
  }
  
  
! /* Verify if the scalar stmts STMTS are isomorphic, require data
!    permutation or are of unsupported types of operation.  Return
!    true if they are, otherwise return false and indicate in *MATCHES
!    which stmts are not isomorphic to the first one.  If MATCHES[0]
!    is false then this indicates the comparison could not be
!    carried out or the stmts will never be vectorized by SLP.  */
  
  static bool
! vect_build_slp_tree_1 (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
! 		       vec<gimple> stmts, unsigned int group_size,
! 		       unsigned nops, unsigned int *max_nunits,
! 		       unsigned int vectorization_factor, bool *matches)
  {
    unsigned int i;
    gimple stmt = stmts[0];
    enum tree_code first_stmt_code = ERROR_MARK, rhs_code = ERROR_MARK;
    enum tree_code first_cond_code = ERROR_MARK;
    tree lhs;
!   bool need_same_oprnds = false;
    tree vectype, scalar_type, first_op1 = NULL_TREE;
    optab optab;
    int icode;
*************** vect_build_slp_tree (loop_vec_info loop_
*** 403,429 ****
    struct data_reference *first_dr;
    HOST_WIDE_INT dummy;
    gimple first_load = NULL, prev_first_load = NULL, old_first_load = NULL;
-   vec<slp_oprnd_info> oprnds_info;
-   unsigned int nops;
-   slp_oprnd_info oprnd_info;
    tree cond;
  
-   if (is_gimple_call (stmt))
-     nops = gimple_call_num_args (stmt);
-   else if (is_gimple_assign (stmt))
-     {
-       nops = gimple_num_ops (stmt) - 1;
-       if (gimple_assign_rhs_code (stmt) == COND_EXPR)
- 	nops++;
-     }
-   else
-     return false;
- 
-   oprnds_info = vect_create_oprnd_info (nops, group_size);
- 
    /* For every stmt in NODE find its def stmt/s.  */
    FOR_EACH_VEC_ELT (stmts, i, stmt)
      {
        if (dump_enabled_p ())
  	{
  	  dump_printf_loc (MSG_NOTE, vect_location, "Build SLP for ");
--- 403,415 ----
    struct data_reference *first_dr;
    HOST_WIDE_INT dummy;
    gimple first_load = NULL, prev_first_load = NULL, old_first_load = NULL;
    tree cond;
  
    /* For every stmt in NODE find its def stmt/s.  */
    FOR_EACH_VEC_ELT (stmts, i, stmt)
      {
+       matches[i] = false;
+ 
        if (dump_enabled_p ())
  	{
  	  dump_printf_loc (MSG_NOTE, vect_location, "Build SLP for ");
*************** vect_build_slp_tree (loop_vec_info loop_
*** 439,446 ****
  			       "Build SLP failed: unvectorizable statement ");
                dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
              }
! 
! 	  vect_free_oprnd_info (oprnds_info);
            return false;
          }
  
--- 425,432 ----
  			       "Build SLP failed: unvectorizable statement ");
                dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
              }
! 	  /* Fatal mismatch.  */
! 	  matches[0] = false;
            return false;
          }
  
*************** vect_build_slp_tree (loop_vec_info loop_
*** 454,461 ****
  			       "GIMPLE_CALL ");
  	      dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
  	    }
! 
! 	  vect_free_oprnd_info (oprnds_info);
  	  return false;
  	}
  
--- 440,447 ----
  			       "GIMPLE_CALL ");
  	      dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
  	    }
! 	  /* Fatal mismatch.  */
! 	  matches[0] = false;
  	  return false;
  	}
  
*************** vect_build_slp_tree (loop_vec_info loop_
*** 471,478 ****
  			       "comparison ");
                dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
              }
! 
! 	  vect_free_oprnd_info (oprnds_info);
            return false;
          }
  
--- 457,464 ----
  			       "comparison ");
                dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
              }
! 	  /* Fatal mismatch.  */
! 	  matches[0] = false;
            return false;
          }
  
*************** vect_build_slp_tree (loop_vec_info loop_
*** 487,494 ****
                dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
  				 scalar_type);
              }
! 
! 	  vect_free_oprnd_info (oprnds_info);
            return false;
          }
  
--- 473,480 ----
                dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
  				 scalar_type);
              }
! 	  /* Fatal mismatch.  */
! 	  matches[0] = false;
            return false;
          }
  
*************** vect_build_slp_tree (loop_vec_info loop_
*** 515,522 ****
  				   "Build SLP failed: unsupported call type ");
  		  dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
  		}
! 
! 	      vect_free_oprnd_info (oprnds_info);
  	      return false;
  	    }
  	}
--- 501,508 ----
  				   "Build SLP failed: unsupported call type ");
  		  dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
  		}
! 	      /* Fatal mismatch.  */
! 	      matches[0] = false;
  	      return false;
  	    }
  	}
*************** vect_build_slp_tree (loop_vec_info loop_
*** 552,558 ****
  		      if (dump_enabled_p ())
  			dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
  					 "Build SLP failed: no optab.");
! 	  	      vect_free_oprnd_info (oprnds_info);
  		      return false;
  		    }
  		  icode = (int) optab_handler (optab, vec_mode);
--- 538,545 ----
  		      if (dump_enabled_p ())
  			dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
  					 "Build SLP failed: no optab.");
! 		      /* Fatal mismatch.  */
! 		      matches[0] = false;
  		      return false;
  		    }
  		  icode = (int) optab_handler (optab, vec_mode);
*************** vect_build_slp_tree (loop_vec_info loop_
*** 562,568 ****
  			dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
  					 "Build SLP failed: "
  					 "op not supported by target.");
! 	  	      vect_free_oprnd_info (oprnds_info);
  		      return false;
  		    }
  		  optab_op2_mode = insn_data[icode].operand[2].mode;
--- 549,556 ----
  			dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
  					 "Build SLP failed: "
  					 "op not supported by target.");
! 		      /* Fatal mismatch.  */
! 		      matches[0] = false;
  		      return false;
  		    }
  		  optab_op2_mode = insn_data[icode].operand[2].mode;
*************** vect_build_slp_tree (loop_vec_info loop_
*** 600,608 ****
  				   "in stmt ");
  		  dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
  		}
! 
! 	      vect_free_oprnd_info (oprnds_info);
! 	      return false;
  	    }
  
  	  if (need_same_oprnds
--- 588,595 ----
  				   "in stmt ");
  		  dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
  		}
! 	      /* Mismatch.  */
! 	      continue;
  	    }
  
  	  if (need_same_oprnds
*************** vect_build_slp_tree (loop_vec_info loop_
*** 615,623 ****
  				   "arguments in ");
  		  dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
  		}
! 
! 	      vect_free_oprnd_info (oprnds_info);
! 	      return false;
  	    }
  
  	  if (rhs_code == CALL_EXPR)
--- 602,609 ----
  				   "arguments in ");
  		  dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
  		}
! 	      /* Mismatch.  */
! 	      continue;
  	    }
  
  	  if (rhs_code == CALL_EXPR)
*************** vect_build_slp_tree (loop_vec_info loop_
*** 636,644 ****
  		      dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
  					stmt, 0);
  		    }
! 
! 		  vect_free_oprnd_info (oprnds_info);
! 		  return false;
  		}
  	    }
  	}
--- 622,629 ----
  		      dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
  					stmt, 0);
  		    }
! 		  /* Mismatch.  */
! 		  continue;
  		}
  	    }
  	}
*************** vect_build_slp_tree (loop_vec_info loop_
*** 649,660 ****
  	  if (REFERENCE_CLASS_P (lhs))
  	    {
  	      /* Store.  */
! 	      if (!vect_get_and_check_slp_defs (loop_vinfo, bb_vinfo,
! 						stmt, (i == 0), &oprnds_info))
! 		{
! 	  	  vect_free_oprnd_info (oprnds_info);
!  		  return false;
! 		}
  	    }
  	  else
  	    {
--- 634,640 ----
  	  if (REFERENCE_CLASS_P (lhs))
  	    {
  	      /* Store.  */
! 	      ;
  	    }
  	  else
  	    {
*************** vect_build_slp_tree (loop_vec_info loop_
*** 681,688 ****
                        dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
  					stmt, 0);
                      }
! 
! 	  	  vect_free_oprnd_info (oprnds_info);
                    return false;
                  }
  
--- 661,668 ----
                        dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
  					stmt, 0);
                      }
! 		  /* Fatal mismatch.  */
! 		  matches[0] = false;
                    return false;
                  }
  
*************** vect_build_slp_tree (loop_vec_info loop_
*** 705,712 ****
                        dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
  					stmt, 0);
                      }
! 
! 	  	  vect_free_oprnd_info (oprnds_info);
                    return false;
                  }
  
--- 685,692 ----
                        dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
  					stmt, 0);
                      }
! 		  /* Fatal mismatch.  */
! 		  matches[0] = false;
                    return false;
                  }
  
*************** vect_build_slp_tree (loop_vec_info loop_
*** 715,725 ****
                if (prev_first_load)
                  {
                    /* Check that there are no loads from different interleaving
!                      chains in the same node.  The only exception is complex
!                      numbers.  */
!                   if (prev_first_load != first_load
!                       && rhs_code != REALPART_EXPR
!                       && rhs_code != IMAGPART_EXPR)
                      {
                        if (dump_enabled_p ())
                          {
--- 695,702 ----
                if (prev_first_load)
                  {
                    /* Check that there are no loads from different interleaving
!                      chains in the same node.  */
!                   if (prev_first_load != first_load)
                      {
                        if (dump_enabled_p ())
                          {
*************** vect_build_slp_tree (loop_vec_info loop_
*** 730,738 ****
                            dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
  					    stmt, 0);
                          }
! 
! 	  	      vect_free_oprnd_info (oprnds_info);
!                       return false;
                      }
                  }
                else
--- 707,714 ----
                            dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
  					    stmt, 0);
                          }
! 		      /* Mismatch.  */
! 		      continue;
                      }
                  }
                else
*************** vect_build_slp_tree (loop_vec_info loop_
*** 755,769 ****
                            dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
  					    stmt, 0);
                          }
! 
! 	  	      vect_free_oprnd_info (oprnds_info);
                        return false;
                      }
                  }
- 
-               /* We stop the tree when we reach a group of loads.  */
-               stop_recursion = true;
-              continue;
             }
          } /* Grouped access.  */
        else
--- 731,741 ----
                            dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
  					    stmt, 0);
                          }
! 		      /* Fatal mismatch.  */
! 		      matches[0] = false;
                        return false;
                      }
                  }
             }
          } /* Grouped access.  */
        else
*************** vect_build_slp_tree (loop_vec_info loop_
*** 779,785 ****
  		}
  
  	      /* FORNOW: Not grouped loads are not supported.  */
! 	      vect_free_oprnd_info (oprnds_info);
  	      return false;
  	    }
  
--- 751,758 ----
  		}
  
  	      /* FORNOW: Not grouped loads are not supported.  */
! 	      /* Fatal mismatch.  */
! 	      matches[0] = false;
  	      return false;
  	    }
  
*************** vect_build_slp_tree (loop_vec_info loop_
*** 796,803 ****
  		  dump_printf (MSG_MISSED_OPTIMIZATION, " unsupported ");
  		  dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
  		}
! 
! 	      vect_free_oprnd_info (oprnds_info);
  	      return false;
  	    }
  
--- 769,776 ----
  		  dump_printf (MSG_MISSED_OPTIMIZATION, " unsupported ");
  		  dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
  		}
! 	      /* Fatal mismatch.  */
! 	      matches[0] = false;
  	      return false;
  	    }
  
*************** vect_build_slp_tree (loop_vec_info loop_
*** 817,869 ****
                        dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
  					stmt, 0);
                      }
! 
! 		  vect_free_oprnd_info (oprnds_info);
!                   return false;
  		}
              }
- 
- 	  /* Find the def-stmts.  */
- 	  if (!vect_get_and_check_slp_defs (loop_vinfo, bb_vinfo, stmt,
- 					    (i == 0), &oprnds_info))
- 	    {
- 	      vect_free_oprnd_info (oprnds_info);
- 	      return false;
- 	    }
  	}
      }
  
!   /* Grouped loads were reached - stop the recursion.  */
!   if (stop_recursion)
      {
        loads->safe_push (*node);
-       vect_free_oprnd_info (oprnds_info);
        return true;
      }
  
    /* Create SLP_TREE nodes for the definition node/s.  */
    FOR_EACH_VEC_ELT (oprnds_info, i, oprnd_info)
      {
        slp_tree child;
  
        if (oprnd_info->first_dt != vect_internal_def)
          continue;
  
        child = vect_create_new_slp_node (oprnd_info->def_stmts);
!       if (!child
!           || !vect_build_slp_tree (loop_vinfo, bb_vinfo, &child, group_size,
! 				   max_nunits, loads,
! 				   vectorization_factor))
!         {
! 	  if (child)
! 	    oprnd_info->def_stmts = vNULL;
! 	  vect_free_slp_tree (child);
  	  vect_free_oprnd_info (oprnds_info);
!    	  return false;
  	}
  
!       oprnd_info->def_stmts.create (0);
!       SLP_TREE_CHILDREN (*node).quick_push (child);
      }
  
    vect_free_oprnd_info (oprnds_info);
--- 790,950 ----
                        dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
  					stmt, 0);
                      }
! 		  /* Mismatch.  */
! 		  continue;
  		}
              }
  	}
+ 
+       matches[i] = true;
+     }
+ 
+   for (i = 0; i < group_size; ++i)
+     if (!matches[i])
+       return false;
+ 
+   return true;
+ }
+ 
+ /* Recursively build an SLP tree starting from NODE.
+    Fail (and return a value not equal to zero) if def-stmts are not
+    isomorphic, require data permutation or are of unsupported types of
+    operation.  Otherwise, return 0.
+    The value returned is the depth in the SLP tree where a mismatch
+    was found.  */
+ 
+ static bool
+ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
+                      slp_tree *node, unsigned int group_size,
+                      unsigned int *max_nunits,
+                      vec<slp_tree> *loads,
+                      unsigned int vectorization_factor,
+ 		     bool *matches, unsigned *npermutes)
+ {
+   unsigned nops, i, this_npermutes = 0;
+   gimple stmt;
+ 
+   if (!matches)
+     matches = XALLOCAVEC (bool, group_size);
+   if (!npermutes)
+     npermutes = &this_npermutes;
+ 
+   matches[0] = false;
+ 
+   stmt = SLP_TREE_SCALAR_STMTS (*node)[0];
+   if (is_gimple_call (stmt))
+     nops = gimple_call_num_args (stmt);
+   else if (is_gimple_assign (stmt))
+     {
+       nops = gimple_num_ops (stmt) - 1;
+       if (gimple_assign_rhs_code (stmt) == COND_EXPR)
+ 	nops++;
      }
+   else
+     return false;
+ 
+   if (!vect_build_slp_tree_1 (loop_vinfo, bb_vinfo,
+ 			      SLP_TREE_SCALAR_STMTS (*node), group_size, nops,
+ 			      max_nunits, vectorization_factor, matches))
+     return false;
  
!   /* If the SLP node is a load, terminate the recursion.  */
!   if (STMT_VINFO_GROUPED_ACCESS (vinfo_for_stmt (stmt))
!       && DR_IS_READ (STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt))))
      {
        loads->safe_push (*node);
        return true;
      }
  
+   /* Get at the operands, verifying they are compatible.  */
+   vec<slp_oprnd_info> oprnds_info = vect_create_oprnd_info (nops, group_size);
+   slp_oprnd_info oprnd_info;
+   FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (*node), i, stmt)
+     {
+       if (!vect_get_and_check_slp_defs (loop_vinfo, bb_vinfo,
+ 					stmt, (i == 0), &oprnds_info))
+ 	{
+ 	  vect_free_oprnd_info (oprnds_info);
+ 	  return false;
+ 	}
+     }
+ 
+   stmt = SLP_TREE_SCALAR_STMTS (*node)[0];
+ 
    /* Create SLP_TREE nodes for the definition node/s.  */
    FOR_EACH_VEC_ELT (oprnds_info, i, oprnd_info)
      {
        slp_tree child;
+       unsigned old_nloads = loads->length ();
+       unsigned old_max_nunits = *max_nunits;
  
        if (oprnd_info->first_dt != vect_internal_def)
          continue;
  
        child = vect_create_new_slp_node (oprnd_info->def_stmts);
!       if (!child)
! 	{
  	  vect_free_oprnd_info (oprnds_info);
! 	  return false;
! 	}
! 
!       bool *matches = XALLOCAVEC (bool, group_size);
!       if (vect_build_slp_tree (loop_vinfo, bb_vinfo, &child,
! 			       group_size, max_nunits, loads,
! 			       vectorization_factor, matches, npermutes))
! 	{
! 	  oprnd_info->def_stmts = vNULL;
! 	  SLP_TREE_CHILDREN (*node).quick_push (child);
! 	  continue;
  	}
  
!       /* If the SLP build for operand zero failed and operand zero
! 	 and one can be commutated try that for the scalar stmts
! 	 that failed the match.  */
!       if (i == 0
! 	  /* A first scalar stmt mismatch signals a fatal mismatch.  */
! 	  && matches[0]
! 	  /* ???  For COND_EXPRs we can swap the comparison operands
! 	     as well as the arms under some constraints.  */
! 	  && nops == 2
! 	  && oprnds_info[1]->first_dt == vect_internal_def
! 	  && is_gimple_assign (stmt)
! 	  && commutative_tree_code (gimple_assign_rhs_code (stmt))
! 	  /* Do so only if the number of not successful permutes was nor more
! 	     than a cut-ff as re-trying the recursive match on
! 	     possibly each level of the tree would expose exponential
! 	     behavior.  */
! 	  && *npermutes < 4)
! 	{
! 	  /* Roll back.  */
! 	  *max_nunits = old_max_nunits;
! 	  loads->truncate (old_nloads);
! 	  /* Swap mismatched definition stmts.  */
! 	  for (unsigned j = 0; j < group_size; ++j)
! 	    if (!matches[j])
! 	      {
! 		gimple tem = oprnds_info[0]->def_stmts[j];
! 		oprnds_info[0]->def_stmts[j] = oprnds_info[1]->def_stmts[j];
! 		oprnds_info[1]->def_stmts[j] = tem;
! 	      }
! 	  /* And try again ... */
! 	  if (vect_build_slp_tree (loop_vinfo, bb_vinfo, &child,
! 				   group_size, max_nunits, loads,
! 				   vectorization_factor,
! 				   matches, npermutes))
! 	    {
! 	      oprnd_info->def_stmts = vNULL;
! 	      SLP_TREE_CHILDREN (*node).quick_push (child);
! 	      continue;
! 	    }
! 
! 	  ++*npermutes;
! 	}
! 
!       oprnd_info->def_stmts = vNULL;
!       vect_free_slp_tree (child);
!       vect_free_oprnd_info (oprnds_info);
!       return false;
      }
  
    vect_free_oprnd_info (oprnds_info);
*************** vect_supported_load_permutation_p (slp_i
*** 1045,1053 ****
    int i = 0, j, prev = -1, next, k, number_of_groups;
    bool supported, bad_permutation = false;
    sbitmap load_index;
!   slp_tree node, other_complex_node;
!   gimple stmt, first = NULL, other_node_first, load, next_load, first_load;
!   unsigned complex_numbers = 0;
    struct data_reference *dr;
    bb_vec_info bb_vinfo;
  
--- 1126,1133 ----
    int i = 0, j, prev = -1, next, k, number_of_groups;
    bool supported, bad_permutation = false;
    sbitmap load_index;
!   slp_tree node;
!   gimple stmt, load, next_load, first_load;
    struct data_reference *dr;
    bb_vec_info bb_vinfo;
  
*************** vect_supported_load_permutation_p (slp_i
*** 1071,1136 ****
  
    /* Check that all the load nodes are of the same size.  */
    FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (slp_instn), i, node)
!     {
!       if (SLP_TREE_SCALAR_STMTS (node).length () != (unsigned) group_size)
!         return false;
! 
!       stmt = SLP_TREE_SCALAR_STMTS (node)[0];
!       if (is_gimple_assign (stmt) 
!           && (gimple_assign_rhs_code (stmt) == REALPART_EXPR
!               || gimple_assign_rhs_code (stmt) == IMAGPART_EXPR))
!         complex_numbers++;
!     }
! 
!   /* Complex operands can be swapped as following:
!       real_c = real_b + real_a;
!       imag_c = imag_a + imag_b;
!      i.e., we have {real_b, imag_a} and {real_a, imag_b} instead of 
!      {real_a, imag_a} and {real_b, imag_b}.  We check here that if interleaving
!      chains are mixed, they match the above pattern.  */
!   if (complex_numbers)
!     {
!       FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (slp_instn), i, node)
!         {
! 	  FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), j, stmt)
!             {
!               if (j == 0)
!                 first = stmt;
!               else
!                 {
!                   if (GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) != first)
!                     {
!                       if (complex_numbers != 2)
!                         return false;
! 
!                       if (i == 0)
!                         k = 1;
!                       else
!                         k = 0;
!  
!                       other_complex_node = SLP_INSTANCE_LOADS (slp_instn)[k];
!                       other_node_first = 
!                                 SLP_TREE_SCALAR_STMTS (other_complex_node)[0];
! 
!                       if (GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt))
!                           != other_node_first)
!                        return false;
!                     }
!                 }
!             }
!         }
!     }
  
-   /* We checked that this case ok, so there is no need to proceed with 
-      permutation tests.  */
-   if (complex_numbers == 2
-       && SLP_INSTANCE_LOADS (slp_instn).length () == 2)
-     {
-       SLP_INSTANCE_LOADS (slp_instn).release ();
-       SLP_INSTANCE_LOAD_PERMUTATION (slp_instn).release ();
-       return true;
-     }
-                    
    node = SLP_INSTANCE_TREE (slp_instn);
    stmt = SLP_TREE_SCALAR_STMTS (node)[0];
    /* LOAD_PERMUTATION is a list of indices of all the loads of the SLP
--- 1151,1159 ----
  
    /* Check that all the load nodes are of the same size.  */
    FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (slp_instn), i, node)
!     if (SLP_TREE_SCALAR_STMTS (node).length () != (unsigned) group_size)
!       return false;
  
    node = SLP_INSTANCE_TREE (slp_instn);
    stmt = SLP_TREE_SCALAR_STMTS (node)[0];
    /* LOAD_PERMUTATION is a list of indices of all the loads of the SLP
*************** vect_analyze_slp_instance (loop_vec_info
*** 1593,1599 ****
    /* Build the tree for the SLP instance.  */
    if (vect_build_slp_tree (loop_vinfo, bb_vinfo, &node, group_size,
  			   &max_nunits, &loads,
! 			   vectorization_factor))
      {
        /* Calculate the unrolling factor based on the smallest type.  */
        if (max_nunits > nunits)
--- 1616,1622 ----
    /* Build the tree for the SLP instance.  */
    if (vect_build_slp_tree (loop_vinfo, bb_vinfo, &node, group_size,
  			   &max_nunits, &loads,
! 			   vectorization_factor, NULL, NULL))
      {
        /* Calculate the unrolling factor based on the smallest type.  */
        if (max_nunits > nunits)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]