From: Kugan Vivekanandarajah <kugan.vivekanandara...@linaro.org> gcc/ChangeLog:
2019-05-15 Kugan Vivekanandarajah <kugan.vivekanandara...@linaro.org> PR target/88834 * tree-ssa-loop-ivopts.c (get_mem_type_for_internal_fn): Handle IFN_MASK_LOAD_LANES and IFN_MASK_STORE_LANES. (find_interesting_uses_stmt): Likewise. (get_alias_ptr_type_for_ptr_address): Likewise. (add_iv_candidate_for_use): Add scaled index candidate if useful. Change-Id: I8e8151fe2dde2845dedf38b090103694da6fc9d1 --- gcc/tree-ssa-loop-ivopts.c | 60 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 9864b59..115a70c 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -2451,11 +2451,13 @@ get_mem_type_for_internal_fn (gcall *call, tree *op_p) switch (gimple_call_internal_fn (call)) { case IFN_MASK_LOAD: + case IFN_MASK_LOAD_LANES: if (op_p == gimple_call_arg_ptr (call, 0)) return TREE_TYPE (gimple_call_lhs (call)); return NULL_TREE; case IFN_MASK_STORE: + case IFN_MASK_STORE_LANES: if (op_p == gimple_call_arg_ptr (call, 0)) return TREE_TYPE (gimple_call_arg (call, 3)); return NULL_TREE; @@ -2545,7 +2547,7 @@ find_interesting_uses_stmt (struct ivopts_data *data, gimple *stmt) return; } - /* TODO -- we should also handle address uses of type + /* TODO -- we should also handle all address uses of type memory = call (whatever); @@ -2553,6 +2555,27 @@ find_interesting_uses_stmt (struct ivopts_data *data, gimple *stmt) call (memory). */ } + else if (is_gimple_call (stmt)) + { + gcall *call = dyn_cast <gcall *> (stmt); + if (call + && gimple_call_internal_p (call) + && (gimple_call_internal_fn (call) == IFN_MASK_LOAD_LANES + || gimple_call_internal_fn (call) == IFN_MASK_STORE_LANES)) + { + tree *arg = gimple_call_arg_ptr (call, 0); + struct iv *civ = get_iv (data, *arg); + tree mem_type = get_mem_type_for_internal_fn (call, arg); + if (civ && mem_type) + { + civ = alloc_iv (data, civ->base, civ->step); + record_group_use (data, arg, civ, stmt, USE_PTR_ADDRESS, + mem_type); + return; + } + } + } + if (gimple_code (stmt) == GIMPLE_PHI && gimple_bb (stmt) == data->current_loop->header) @@ -3500,6 +3523,39 @@ add_iv_candidate_for_use (struct ivopts_data *data, struct iv_use *use) basetype = sizetype; record_common_cand (data, build_int_cst (basetype, 0), iv->step, use); + /* Compare the cost of an address with an unscaled index with the cost of + an address with a scaled index and add candidate if useful. */ + if (use != NULL && use->type == USE_PTR_ADDRESS) + { + struct mem_address parts = {NULL_TREE, integer_one_node, + NULL_TREE, NULL_TREE, NULL_TREE}; + poly_uint64 temp; + poly_int64 fact; + bool speed = optimize_loop_for_speed_p (data->current_loop); + poly_int64 poly_step = tree_to_poly_int64 (iv->step); + machine_mode mem_mode = TYPE_MODE (use->mem_type); + addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (use->iv->base)); + + fact = GET_MODE_SIZE (GET_MODE_INNER (TYPE_MODE (use->mem_type))); + parts.index = integer_one_node; + + if (fact.is_constant () + && can_div_trunc_p (poly_step, fact, &temp)) + { + /* Addressing mode "base + index". */ + rtx addr = addr_for_mem_ref (&parts, as, false); + unsigned cost = address_cost (addr, mem_mode, as, speed); + tree step = wide_int_to_tree (sizetype, + exact_div (poly_step, fact)); + parts.step = wide_int_to_tree (sizetype, fact); + /* Addressing mode "base + index << scale". */ + addr = addr_for_mem_ref (&parts, as, false); + unsigned new_cost = address_cost (addr, mem_mode, as, speed); + if (new_cost < cost) + add_candidate (data, size_int (0), step, true, NULL); + } + } + /* Record common candidate with constant offset stripped in base. Like the use itself, we also add candidate directly for it. */ base = strip_offset (iv->base, &offset); @@ -7112,6 +7168,8 @@ get_alias_ptr_type_for_ptr_address (iv_use *use) { case IFN_MASK_LOAD: case IFN_MASK_STORE: + case IFN_MASK_LOAD_LANES: + case IFN_MASK_STORE_LANES: /* The second argument contains the correct alias type. */ gcc_assert (use->op_p = gimple_call_arg_ptr (call, 0)); return TREE_TYPE (gimple_call_arg (call, 1)); -- 2.7.4