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.