[PATCH] Builtins handling in IVOPT
Bin.Cheng
amker.cheng@gmail.com
Thu Nov 21 10:50:00 GMT 2013
I don't know very much about the problem but willing to study since I
am looking into IVO recently :)
> --- tree-ssa-loop-ivopts.c (revision 204792)
> +++ tree-ssa-loop-ivopts.c (working copy)
> @@ -135,6 +135,8 @@ struct iv
> tree ssa_name; /* The ssa name with the value. */
> bool biv_p; /* Is it a biv? */
> bool have_use_for; /* Do we already have a use for it? */
> + bool builtin_mem_param; /* Used as param of a builtin, so it could not be
> + removed by remove_unused_ivs. */
As comment below, address parameter may be not limited to builtin
function only, how about a variable name more generic?
> unsigned use_id; /* The identifier in the use if it is the case. */
> };
>
> @@ -952,6 +954,7 @@ alloc_iv (tree base, tree step)
> iv->step = step;
> iv->biv_p = false;
> iv->have_use_for = false;
> + iv->builtin_mem_param = false;
> iv->use_id = 0;
> iv->ssa_name = NULL_TREE;
>
> @@ -1874,13 +1877,36 @@ find_invariants_stmt (struct ivopts_data
> }
> }
>
> +/* Find whether the Ith param of the BUILTIN is a mem
> + reference. If I is -1, it returns whether the BUILTIN
> + contains any mem reference type param. */
> +
> +static bool
> +builtin_has_mem_ref_p (gimple builtin, int i)
> +{
> + tree fndecl = gimple_call_fndecl (builtin);
> + if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
> + {
> + switch (DECL_FUNCTION_CODE (fndecl))
> + {
> + case BUILT_IN_PREFETCH:
> + if (i == -1 || i == 0)
> + return true;
> + }
This switch looks strange, could be refactored I think.
> + }
> + else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
> + return targetm.builtin_has_mem_ref_p ((int) DECL_FUNCTION_CODE
> (fndecl), i);
> +
> + return false;
> +}
> +
> /* Finds interesting uses of induction variables in the statement STMT. */
>
> static void
> find_interesting_uses_stmt (struct ivopts_data *data, gimple stmt)
> {
> struct iv *iv;
> - tree op, *lhs, *rhs;
> + tree op, *lhs, *rhs, callee;
> ssa_op_iter iter;
> use_operand_p use_p;
> enum tree_code code;
> @@ -1937,6 +1963,74 @@ find_interesting_uses_stmt (struct ivopt
>
> call (memory). */
> }
> + else if (is_gimple_call (stmt)
> + && (callee = gimple_call_fndecl (stmt))
> + && is_builtin_fn (callee)
> + && builtin_has_mem_ref_p (stmt, -1))
> + {
I noticed the preceding comments about call(memory), is your change a
specific case of the mention one?
> + size_t i;
> + for (i = 0; i < gimple_call_num_args (stmt); i++)
> + {
> + if (builtin_has_mem_ref_p (stmt, i))
> + {
> + gimple def, g;
> + gimple_seq seq = NULL;
> + tree type, mem, addr, rhs;
> + tree *arg = gimple_call_arg_ptr (stmt, i);
> + location_t loc = gimple_location (stmt);
> + gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
> +
> + if (TREE_CODE (*arg) != SSA_NAME)
> + continue;
> +
> + def = SSA_NAME_DEF_STMT (*arg);
> + gcc_assert (gimple_code (def) == GIMPLE_PHI
> + || is_gimple_assign (def));
> + /* Suppose we have the case:
> + arg = expr;
> + call (arg)
> + If the expr is not like the form: &MEM(...), change it to:
> + arg = expr;
> + tmp = &MEM(arg);
> + call(tmp);
> + then try to find interesting uses address in MEM(arg). */
> + if (is_gimple_assign (def)
> + && (rhs = gimple_assign_rhs1(def))
> + && TREE_CODE (rhs) == ADDR_EXPR
> + && REFERENCE_CLASS_P (TREE_OPERAND (rhs, 0)))
> + {
> + iv = get_iv (data, *arg);
> + if (iv && !iv->builtin_mem_param)
> + iv->builtin_mem_param = true;
> +
> + find_interesting_uses_address (data, def,
> + &TREE_OPERAND (rhs, 0));
> + }
> + else
> + {
> + mem = build2 (MEM_REF, TREE_TYPE (*arg), *arg,
> + build_int_cst (TREE_TYPE (*arg), 0));
> + type = build_pointer_type (TREE_TYPE (*arg));
> + addr = build1 (ADDR_EXPR, type, mem);
> + g = gimple_build_assign_with_ops (ADDR_EXPR,
> + make_ssa_name (type, NULL),
> + addr, NULL);
> + gimple_call_set_arg (stmt, i, gimple_assign_lhs (g));
> + update_stmt (stmt);
> + gimple_set_location (g, loc);
> + gimple_seq_add_stmt_without_update (&seq, g);
> + gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
> + find_interesting_uses_address (data, g,
> &TREE_OPERAND (addr, 0));
This would be the only code changes gimple before iv use rewriting and
seems not a good practice.
> + }
> + }
> + else
> + {
> + tree arg = gimple_call_arg (stmt, i);
> + find_interesting_uses_op (data, arg);
> + }
> + }
> + return;
> + }
>
> if (gimple_code (stmt) == GIMPLE_PHI
> && gimple_bb (stmt) == data->current_loop->header)
> @@ -6507,10 +6601,10 @@ remove_unused_ivs (struct ivopts_data *d
> && !integer_zerop (info->iv->step)
> && !info->inv_id
> && !info->iv->have_use_for
> + && !info->iv->builtin_mem_param
> && !info->preserve_biv)
> {
Thanks,
bin
--
Best Regards.
More information about the Gcc-patches
mailing list