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

Reply via email to