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: [PATCH][RFC] Do some vectorizer-friendly canonicalization before vectorization


>
> Currently, especially with -funsafe-math-optimizations, we pessimize
> vectorization by canonicalizing multiplications to calls to pow ().
> This patch addresses this by doing a different canonicalization (or
> tree-level expansion dependent on how you view this) before
> vectorization.
>

funny - we just stumbled into such an occurrence - had to avoid using
-fast-math in order to be able to vectorize an x*x that was converted to
pow(x,2).

> This is a simple prototype hooked into the vectorizer and only
> transforming loop bodies.  The only transformations implemented
> for this are pow (x, 2) to x * x and pow (x, 0.5) to sqrt (x) because
> both x * x and sqrt (x) are easy to vectorize.
>
> Does this look like a reasonable approach?
>

Actually, I envision this type of transformation taking place as part of
our idiom-recognition pass in the vectorizer. In vect_pattern_recog() we
already scan all the stmts in the loop, looking for a certain pattern
(dot-product, widening-multiplication, maybe saturation in the future, and
possibly pow in this case), and replace it with a new stmt (the
'pattern_stmt') that represents/implements the pattern (multiply/sqrt in
this case). In fact, we don't really replace the original stmts - we add
the 'pattern_stmt' with its def unused, and just mark the original stmts
that they were recognized as part of a pattern to be replaced by the
'pattern_stmt'. Later on, the vectorizer knows to vectorize the
pattern_stmt rather than the original stmts. So, if the loop doesn't get
vectorized, the code doesn't change. This is explained in detail in
tree-vect-patterns.c.

If you agree that this transformation fits with the vect_pattern_recog
approach, what you need to do is basically:
- update VECT_NUM_PATTERNS
- add a new function in tree-vect-patterns.c, say -
"vect_recog_unsafe_math_patterns".
- add the above function to the initialization of the
vect_vect_recog_func_ptrs array

The content of vect_recog_unsafe_math_patterns would basically be your
maybe_replace_pow_expr function, expect instead of replacing the expr, just
return it.

dorit

> Thanks,
> Richard.
>
> --
> Richard Guenther <rguenther@suse.de>
> Novell / SUSE Labs
>
> 2006-11-20  Richard Guenther  <rguenther@suse.de>
>
>    * tree-vectorizer.c (maybe_replace_pow_expr): New static
>    helper.
>    (vect_prepare_loop): New function.
>    (vectorize_loops): Call vect_prepare_loop to canonicalize
>    some statements in a vectorizer friendly manner.
>
> Index: tree-vectorizer.c
> ===================================================================
> *** tree-vectorizer.c   (revision 119010)
> --- tree-vectorizer.c   (working copy)
> *************** vect_is_simple_iv_evolution (unsigned lo
> *** 2141,2146 ****
> --- 2141,2220 ----
>     return true;
>   }
>
> + /* Replace a pow or powi expression by multiplication and/or sqrt.
> +    This basically does pow expansion on trees.  */
> +
> + static void
> + maybe_replace_pow_expr (block_stmt_iterator *bsi)
> + {
> +   tree stmt = bsi_stmt (*bsi);
> +   tree fn = get_callee_fndecl (TREE_OPERAND (stmt, 1));
> +   tree arglist = TREE_OPERAND (TREE_OPERAND (stmt, 1), 1);
> +   tree base = TREE_VALUE (arglist);
> +   tree exp = TREE_VALUE (TREE_CHAIN (arglist));
> +
> +   /* Catch squaring.  */
> +   if ((host_integerp (exp, 0)
> +        && TREE_INT_CST_LOW (exp) == 2)
> +       || (TREE_CODE (exp) == REAL_CST
> +      && REAL_VALUES_EQUAL (TREE_REAL_CST (exp), dconst2)))
> +     {
> +       TREE_OPERAND (stmt, 1) = build2 (MULT_EXPR, TREE_TYPE (base),
> +                    base, base);
> +       return;
> +     }
> +
> +   /* Catch square root.  */
> +   if (TREE_CODE (exp) == REAL_CST
> +       && REAL_VALUES_EQUAL (TREE_REAL_CST (exp), dconsthalf))
> +     {
> +       tree newfn = mathfn_built_in (TREE_TYPE (base), BUILT_IN_SQRT);
> +       tree newarglist = build_tree_list (NULL_TREE, base);
> +       TREE_OPERAND (stmt, 1) = build_function_call_expr (newfn,
newarglist);
> +       return;
> +     }
> +
> +   /* TODO: Catch stuff that requires flag_unsafe_math_optimizations.
*/
> + }
> +
> + /* Prepare LOOP for vectorizer analysis by transforming harder
> +    to vectorize statements into easier ones.  */
> +
> + static void
> + vect_prepare_loop (struct loop *loop)
> + {
> +   basic_block *bbs = get_loop_body (loop);
> +   unsigned i;
> +
> +   for (i = 0; i < loop->num_nodes; ++i)
> +     {
> +       block_stmt_iterator bsi;
> +
> +       for (bsi = bsi_start (bbs[i]); !bsi_end_p (bsi); bsi_next (&bsi))
> +    {
> +      tree fn, arglist;
> +      tree stmt = bsi_stmt (bsi);
> +
> +      /* We only care about calls and math.  */
> +      if (TREE_CODE (stmt) != MODIFY_EXPR
> +          || TREE_CODE (TREE_OPERAND (stmt, 1)) != CALL_EXPR)
> +        continue;
> +
> +      fn = get_callee_fndecl (TREE_OPERAND (stmt, 1));
> +      arglist = TREE_OPERAND (TREE_OPERAND (stmt, 1), 1);
> +      switch (DECL_FUNCTION_CODE (fn))
> +        {
> +        case BUILT_IN_POWF:
> +        case BUILT_IN_POW:
> +          if (TREE_CODE (TREE_VALUE (TREE_CHAIN (arglist))) == REAL_CST
> +         || TREE_CODE (TREE_VALUE (TREE_CHAIN (arglist))) ==
INTEGER_CST)
> +       maybe_replace_pow_expr (&bsi);
> +
> +        default:;
> +        }
> +    }
> +     }
> + }
>
>   /* Function vectorize_loops.
>
> *************** vectorize_loops (struct loops *loops)
> *** 2174,2179 ****
> --- 2248,2254 ----
>           continue;
>
>         vect_loop_location = find_loop_location (loop);
> +       vect_prepare_loop (loop);
>         loop_vinfo = vect_analyze_loop (loop);
>         loop->aux = loop_vinfo;
>


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