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]

Re: Vectorize 2*x as x+x if needed


On Sun, Jun 12, 2016 at 11:19 AM, Marc Glisse <marc.glisse@inria.fr> wrote:
> Hello,
>
> canonicalizing x+x to x*2 made us regress some vectorization tests on sparc.
> As suggested by Richard, this lets the vectorizer handle x*2 as x+x if that
> helps. Let me copy a few remarks I had in the PR:
>
> Â We could probably also handle x*3 as x+x+x, but where to stop?
>
> I don't understand why the optab test for LSHIFT_EXPR was using
> optab_vector, as far as I understand we are creating vec<<3, so optab_scalar
> makes more sense.

I think it should test both (ok if either one is available) and the
current optab_vector makes more sense
since it is more generic.

Ok with either not changing optab_vector to optab_scalar or testing both with ||

Thanks,
Richard.

> I gave priority to x+x over x<<1, not sure if that's right, it probably
> doesn't matter much as one will probably be turned into the other in later
> passes. Â
>
> Rainer bootstrapped and regtested the patch on sparc. As a bonus, it now
> vectorizes one more loop in gcc.dg/vect/vect-iv-9.c, I'll let someone else
> tweak the test (which will temporarily appear as a FAIL).
>
> 2016-06-13  Marc Glisse  <marc.glisse@inria.fr>
>
>         PR tree-optimization/70923
>         * tree-vect-patterns.c (vect_recog_mult_pattern): Use optab_scalar
>         for LSHIFT_EXPR. Handle 2 * X as X + X.
>
> --
> Marc Glisse
> Index: gcc/tree-vect-patterns.c
> ===================================================================
> *** gcc/tree-vect-patterns.c    (revision 237336)
> --- gcc/tree-vect-patterns.c    (working copy)
> *************** vect_recog_vector_vector_shift_pattern (
> *** 2166,2189 ****
>
>     * Return value: A new stmt that will be used to replace the
> multiplication
>       S1 or S2 stmt.  */
>
>   static gimple *
>   vect_recog_mult_pattern (vec<gimple *> *stmts,
>                          tree *type_in, tree *type_out)
>   {
>     gimple *last_stmt = stmts->pop ();
>     tree oprnd0, oprnd1, vectype, itype;
> !   gimple *pattern_stmt, *def_stmt;
>     optab optab;
>     stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
> !   int power2_val, power2_neg_val;
>     tree shift;
>
>     if (!is_gimple_assign (last_stmt))
>       return NULL;
>
>     if (gimple_assign_rhs_code (last_stmt) != MULT_EXPR)
>       return NULL;
>
>     oprnd0 = gimple_assign_rhs1 (last_stmt);
>     oprnd1 = gimple_assign_rhs2 (last_stmt);
> --- 2166,2189 ----
>
>     * Return value: A new stmt that will be used to replace the
> multiplication
>       S1 or S2 stmt.  */
>
>   static gimple *
>   vect_recog_mult_pattern (vec<gimple *> *stmts,
>                          tree *type_in, tree *type_out)
>   {
>     gimple *last_stmt = stmts->pop ();
>     tree oprnd0, oprnd1, vectype, itype;
> !   gimple *pattern_stmt;
>     optab optab;
>     stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
> !   int power2_val;
>     tree shift;
>
>     if (!is_gimple_assign (last_stmt))
>       return NULL;
>
>     if (gimple_assign_rhs_code (last_stmt) != MULT_EXPR)
>       return NULL;
>
>     oprnd0 = gimple_assign_rhs1 (last_stmt);
>     oprnd1 = gimple_assign_rhs2 (last_stmt);
> *************** vect_recog_mult_pattern (vec<gimple *> *
> *** 2203,2261 ****
>        don't attempt to optimize this.  */
>     optab = optab_for_tree_code (MULT_EXPR, vectype, optab_default);
>     if (optab != unknown_optab)
>       {
>         machine_mode vec_mode = TYPE_MODE (vectype);
>         int icode = (int) optab_handler (optab, vec_mode);
>         if (icode != CODE_FOR_nothing)
>         return NULL;
>       }
>
> !   /* If target cannot handle vector left shift then we cannot
> !      optimize and bail out.  */
> !   optab = optab_for_tree_code (LSHIFT_EXPR, vectype, optab_vector);
> !   if (!optab
> !       || optab_handler (optab, TYPE_MODE (vectype)) == CODE_FOR_nothing)
> !     return NULL;
> !
> !   power2_val = wi::exact_log2 (oprnd1);
> !   power2_neg_val = wi::exact_log2 (wi::neg (oprnd1));
>
> !   /* Handle constant operands that are postive or negative powers of 2.
> */
> !   if (power2_val != -1)
> !     {
> !       shift = build_int_cst (itype, power2_val);
> !       pattern_stmt
> !       = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
> !                              LSHIFT_EXPR, oprnd0, shift);
> !     }
> !   else if (power2_neg_val != -1)
>       {
>         /* If the target cannot handle vector NEGATE then we cannot
>          do the optimization.  */
> !       optab = optab_for_tree_code (NEGATE_EXPR, vectype, optab_vector);
>         if (!optab
>           || optab_handler (optab, TYPE_MODE (vectype)) == CODE_FOR_nothing)
>         return NULL;
>
> !       shift = build_int_cst (itype, power2_neg_val);
> !       def_stmt
>         = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
> !                              LSHIFT_EXPR, oprnd0, shift);
> !       new_pattern_def_seq (stmt_vinfo, def_stmt);
>         pattern_stmt
> !        = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
> !                               NEGATE_EXPR, gimple_assign_lhs (def_stmt));
>       }
>     else
>       return NULL;
>
>     /* Pattern detected.  */
>     if (dump_enabled_p ())
>       dump_printf_loc (MSG_NOTE, vect_location,
>                      "vect_recog_mult_pattern: detected:\n");
>
>     if (dump_enabled_p ())
>       dump_gimple_stmt_loc (MSG_NOTE, vect_location, TDF_SLIM,
>                           pattern_stmt,0);
>
>     stmts->safe_push (last_stmt);
> --- 2203,2271 ----
>        don't attempt to optimize this.  */
>     optab = optab_for_tree_code (MULT_EXPR, vectype, optab_default);
>     if (optab != unknown_optab)
>       {
>         machine_mode vec_mode = TYPE_MODE (vectype);
>         int icode = (int) optab_handler (optab, vec_mode);
>         if (icode != CODE_FOR_nothing)
>         return NULL;
>       }
>
> !   bool negate = wi::neg_p (oprnd1, TYPE_SIGN (TREE_TYPE (oprnd1)));
>
> !   if (negate)
>       {
>         /* If the target cannot handle vector NEGATE then we cannot
>          do the optimization.  */
> !       optab = optab_for_tree_code (NEGATE_EXPR, vectype, optab_default);
>         if (!optab
>           || optab_handler (optab, TYPE_MODE (vectype)) == CODE_FOR_nothing)
>         return NULL;
> +       power2_val = wi::exact_log2 (wi::neg (oprnd1));
> +     }
> +   else
> +     {
> +       power2_val = wi::exact_log2 (oprnd1);
> +     }
>
> !   /* Handle constant operands +-2 if target can handle vector addition.
> */
> !   if (power2_val == 1
> !       && (optab = optab_for_tree_code (PLUS_EXPR, vectype, optab_default))
> !       && optab_handler (optab, TYPE_MODE (vectype)) != CODE_FOR_nothing)
> !     {
> !       pattern_stmt
>         = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
> !                              PLUS_EXPR, oprnd0, oprnd0);
> !     }
> !   /* Handle constant operands that are positive or negative powers of 2
> !      if target can handle vector left shift.  */
> !   else if (power2_val != -1
> !          && (optab = optab_for_tree_code (LSHIFT_EXPR, vectype,
> optab_scalar))
> !          && optab_handler (optab, TYPE_MODE (vectype)) !=
> CODE_FOR_nothing)
> !     {
> !       shift = build_int_cst (itype, power2_val);
>         pattern_stmt
> !       = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
> !                              LSHIFT_EXPR, oprnd0, shift);
>       }
>     else
>       return NULL;
>
> +   if (negate)
> +     {
> +       tree tmp_var = gimple_assign_lhs (pattern_stmt);
> +       new_pattern_def_seq (stmt_vinfo, pattern_stmt);
> +       pattern_stmt
> +        = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
> +                               NEGATE_EXPR, tmp_var);
> +     }
> +
>     /* Pattern detected.  */
>     if (dump_enabled_p ())
>       dump_printf_loc (MSG_NOTE, vect_location,
>                      "vect_recog_mult_pattern: detected:\n");
>
>     if (dump_enabled_p ())
>       dump_gimple_stmt_loc (MSG_NOTE, vect_location, TDF_SLIM,
>                           pattern_stmt,0);
>
>     stmts->safe_push (last_stmt);
>


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