On Fri, Nov 17, 2017 at 3:03 PM, Richard Sandiford
<richard.sandif...@linaro.org> wrote:
> ivopts previously treated pointer arguments to internal functions
> like IFN_MASK_LOAD and IFN_MASK_STORE as normal gimple values.
> This patch makes it treat them as addresses instead.  This makes
> a significant difference to the code quality for SVE loops,
> since we can then use loads and stores with scaled indices.
Thanks for working on this.  This can be extended to other internal
functions which eventually
are expanded into memory references.  I believe (at least) both x86
and AArch64 has such
requirement.

>
> The patch also adds support for ADDR_EXPRs of TARGET_MEM_REFs,
> which are the natural way of representing the result of the
> ivopts transformation.
>
> Tested on aarch64-linux-gnu (with and without SVE), x86_64-linux-gnu
> and powerpc64le-linux-gnu.  OK to install?
>
> Richard
>
>
> 2017-11-17  Richard Sandiford  <richard.sandif...@linaro.org>
>             Alan Hayward  <alan.hayw...@arm.com>
>             David Sherwood  <david.sherw...@arm.com>
>
> gcc/
>         * expr.c (expand_expr_addr_expr_1): Handle ADDR_EXPRs of
>         TARGET_MEM_REFs.
>         * gimple-expr.h (is_gimple_addressable: Likewise.
>         * gimple-expr.c (is_gimple_address): Likewise.
>         * internal-fn.c (expand_call_mem_ref): New function.
>         (expand_mask_load_optab_fn): Use it.
>         (expand_mask_store_optab_fn): Likewise.
>         * tree-ssa-loop-ivopts.c (USE_ADDRESS): Split into...
>         (USE_REF_ADDRESS, USE_PTR_ADDRESS): ...these new use types.
>         (dump_groups): Update accordingly.
>         (iv_use::mem_type): New member variable.
>         (address_p): New function.
>         (record_use): Add a mem_type argument and initialize the new
>         mem_type field.
>         (record_group_use): Add a mem_type argument.  Use address_p.
>         Update call to record_use.
>         (find_interesting_uses_op): Update call to record_group_use.
>         (find_interesting_uses_cond): Likewise.
>         (find_interesting_uses_address): Likewise.
>         (get_mem_type_for_internal_fn): New function.
>         (find_address_like_use): Likewise.
>         (find_interesting_uses_stmt): Try find_address_like_use before
>         calling find_interesting_uses_op.
>         (addr_offset_valid_p): Use the iv mem_type field as the type
>         of the addressed memory.
>         (add_autoinc_candidates): Likewise.
>         (get_address_cost): Likewise.
>         (split_small_address_groups_p): Use address_p.
>         (split_address_groups): Likewise.
>         (add_iv_candidate_for_use): Likewise.
>         (autoinc_possible_for_pair): Likewise.
>         (rewrite_groups): Likewise.
>         (get_use_type): Check for USE_REF_ADDRESS instead of USE_ADDRESS.
>         (determine_group_iv_cost): Update after split of USE_ADDRESS.
>         (get_alias_ptr_type_for_ptr_address): New function.
>         (rewrite_use_address): Rewrite address uses in calls that were
>         identified by find_address_like_use.
>
> gcc/testsuite/
>         * gcc.dg/tree-ssa/scev-9.c: Expected REFERENCE ADDRESS
>         instead of just ADDRESS.
>         * gcc.dg/tree-ssa/scev-10.c: Likewise.
>         * gcc.dg/tree-ssa/scev-11.c: Likewise.
>         * gcc.dg/tree-ssa/scev-12.c: Likewise.
>         * gcc.target/aarch64/sve_index_offset_1.c: New test.
>         * gcc.target/aarch64/sve_index_offset_1_run.c: Likewise.
>         * gcc.target/aarch64/sve_loop_add_2.c: Likewise.
>         * gcc.target/aarch64/sve_loop_add_3.c: Likewise.
>         * gcc.target/aarch64/sve_while_1.c: Check for indexed addressing 
> modes.
>         * gcc.target/aarch64/sve_while_2.c: Likewise.
>         * gcc.target/aarch64/sve_while_3.c: Likewise.
>         * gcc.target/aarch64/sve_while_4.c: Likewise.
>
> Index: gcc/expr.c
> ===================================================================
> --- gcc/expr.c  2017-11-17 09:49:36.191354637 +0000
> +++ gcc/expr.c  2017-11-17 15:02:12.868132458 +0000
> @@ -7814,6 +7814,9 @@ expand_expr_addr_expr_1 (tree exp, rtx t
>         return expand_expr (tem, target, tmode, modifier);
>        }
>
> +    case TARGET_MEM_REF:
> +      return addr_for_mem_ref (exp, as, true);
> +
>      case CONST_DECL:
>        /* Expand the initializer like constants above.  */
>        result = XEXP (expand_expr_constant (DECL_INITIAL (exp),
> Index: gcc/gimple-expr.h
> ===================================================================
> --- gcc/gimple-expr.h   2017-11-17 09:40:43.520567009 +0000
> +++ gcc/gimple-expr.h   2017-11-17 15:02:12.868132458 +0000
> @@ -119,6 +119,7 @@ virtual_operand_p (tree op)
>  is_gimple_addressable (tree t)
>  {
>    return (is_gimple_id (t) || handled_component_p (t)
> +         || TREE_CODE (t) == TARGET_MEM_REF
>           || TREE_CODE (t) == MEM_REF);
>  }
>
> Index: gcc/gimple-expr.c
> ===================================================================
> --- gcc/gimple-expr.c   2017-10-13 10:23:39.845432950 +0100
> +++ gcc/gimple-expr.c   2017-11-17 15:02:12.868132458 +0000
> @@ -631,7 +631,9 @@ is_gimple_address (const_tree t)
>        op = TREE_OPERAND (op, 0);
>      }
>
> -  if (CONSTANT_CLASS_P (op) || TREE_CODE (op) == MEM_REF)
> +  if (CONSTANT_CLASS_P (op)
> +      || TREE_CODE (op) == TARGET_MEM_REF
> +      || TREE_CODE (op) == MEM_REF)
>      return true;
>
>    switch (TREE_CODE (op))
> Index: gcc/internal-fn.c
> ===================================================================
> --- gcc/internal-fn.c   2017-11-17 14:57:36.436527536 +0000
> +++ gcc/internal-fn.c   2017-11-17 15:02:12.869042409 +0000
> @@ -2367,15 +2367,47 @@ expand_LOOP_DIST_ALIAS (internal_fn, gca
>    gcc_unreachable ();
>  }
>
> +/* Return a memory reference of type TYPE for argument INDEX of STMT.
> +   Use argument INDEX + 1 to derive the second (TBAA) operand.  */
> +
> +static tree
> +expand_call_mem_ref (tree type, gcall *stmt, int index)
> +{
> +  tree addr = gimple_call_arg (stmt, index);
> +  tree alias_ptr_type = TREE_TYPE (gimple_call_arg (stmt, index + 1));
> +  unsigned int align = tree_to_shwi (gimple_call_arg (stmt, index + 1));
> +  if (TYPE_ALIGN (type) != align)
> +    type = build_aligned_type (type, align);
> +
> +  tree tmp = addr;
> +  if (TREE_CODE (tmp) == SSA_NAME)
> +    {
> +      gimple *def = SSA_NAME_DEF_STMT (tmp);
> +      if (gimple_assign_single_p (def))
> +       tmp = gimple_assign_rhs1 (def);
> +    }
> +
> +  if (TREE_CODE (tmp) == ADDR_EXPR)
> +    {
> +      tree mem = TREE_OPERAND (tmp, 0);
> +      if (TREE_CODE (mem) == TARGET_MEM_REF
> +         && types_compatible_p (TREE_TYPE (mem), type)
> +         && alias_ptr_type == TREE_TYPE (TMR_OFFSET (mem))
> +         && integer_zerop (TMR_OFFSET (mem)))
> +       return mem;
> +    }
> +
> +  return fold_build2 (MEM_REF, type, addr, build_int_cst (alias_ptr_type, 
> 0));
> +}
> +
>  /* Expand MASK_LOAD{,_LANES} call STMT using optab OPTAB.  */
>
>  static void
>  expand_mask_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
>  {
>    struct expand_operand ops[3];
> -  tree type, lhs, rhs, maskt, ptr;
> +  tree type, lhs, rhs, maskt;
>    rtx mem, target, mask;
> -  unsigned align;
>    insn_code icode;
>
>    maskt = gimple_call_arg (stmt, 2);
> @@ -2383,11 +2415,7 @@ expand_mask_load_optab_fn (internal_fn,
>    if (lhs == NULL_TREE)
>      return;
>    type = TREE_TYPE (lhs);
> -  ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), 0);
> -  align = tree_to_shwi (gimple_call_arg (stmt, 1));
> -  if (TYPE_ALIGN (type) != align)
> -    type = build_aligned_type (type, align);
> -  rhs = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0), ptr);
> +  rhs = expand_call_mem_ref (type, stmt, 0);
>
>    if (optab == vec_mask_load_lanes_optab)
>      icode = get_multi_vector_move (type, optab);
> @@ -2413,19 +2441,14 @@ #define expand_mask_load_lanes_optab_fn
>  expand_mask_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
>  {
>    struct expand_operand ops[3];
> -  tree type, lhs, rhs, maskt, ptr;
> +  tree type, lhs, rhs, maskt;
>    rtx mem, reg, mask;
> -  unsigned align;
>    insn_code icode;
>
>    maskt = gimple_call_arg (stmt, 2);
>    rhs = gimple_call_arg (stmt, 3);
>    type = TREE_TYPE (rhs);
> -  ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), 0);
> -  align = tree_to_shwi (gimple_call_arg (stmt, 1));
> -  if (TYPE_ALIGN (type) != align)
> -    type = build_aligned_type (type, align);
> -  lhs = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0), ptr);
> +  lhs = expand_call_mem_ref (type, stmt, 0);
>
>    if (optab == vec_mask_store_lanes_optab)
>      icode = get_multi_vector_move (type, optab);
Support for TARGET_MEM_REF and refactoring of expand_call_* in above
code looks independent
to IVOPTs change?  If so, coule you split it into two patches?  I can
approve IVOPTs part patch with
below comments.

> Index: gcc/tree-ssa-loop-ivopts.c
> ===================================================================
> --- gcc/tree-ssa-loop-ivopts.c  2017-11-17 09:05:59.900349210 +0000
> +++ gcc/tree-ssa-loop-ivopts.c  2017-11-17 15:02:12.870862310 +0000
> @@ -166,7 +166,11 @@ struct version_info
>  enum use_type
>  {
>    USE_NONLINEAR_EXPR,  /* Use in a nonlinear expression.  */
> -  USE_ADDRESS,         /* Use in an address.  */
> +  USE_REF_ADDRESS,     /* Use is an address for an explicit memory
> +                          reference.  */
> +  USE_PTR_ADDRESS,     /* Use is a pointer argument to a function in
> +                          cases where the expansion of the function
> +                          will turn the argument into a normal address.  */
>    USE_COMPARE          /* Use is a compare.  */
>  };
>
> @@ -362,6 +366,9 @@ struct iv_use
>    unsigned id;         /* The id of the use.  */
>    unsigned group_id;   /* The group id the use belongs to.  */
>    enum use_type type;  /* Type of the use.  */
> +  tree mem_type;       /* The memory type to use when testing whether an
> +                          address is legitimate, and what the address's
> +                          cost is.  */
>    struct iv *iv;       /* The induction variable it is based on.  */
>    gimple *stmt;                /* Statement in that it occurs.  */
>    tree *op_p;          /* The place where it occurs.  */
> @@ -506,6 +513,14 @@ struct iv_inv_expr_hasher : free_ptr_has
>    static inline bool equal (const iv_inv_expr_ent *, const iv_inv_expr_ent 
> *);
>  };
>
> +/* Return true if uses of type TYPE represent some form of address.  */
> +
> +inline bool
> +address_p (use_type type)
> +{
> +  return type == USE_REF_ADDRESS || type == USE_PTR_ADDRESS;
> +}
> +
>  /* Hash function for loop invariant expressions.  */
>
>  inline hashval_t
> @@ -768,8 +783,10 @@ dump_groups (FILE *file, struct ivopts_d
>        fprintf (file, "Group %d:\n", group->id);
>        if (group->type == USE_NONLINEAR_EXPR)
>         fprintf (file, "  Type:\tGENERIC\n");
> -      else if (group->type == USE_ADDRESS)
> -       fprintf (file, "  Type:\tADDRESS\n");
> +      else if (group->type == USE_REF_ADDRESS)
> +       fprintf (file, "  Type:\tREFERENCE ADDRESS\n");
> +      else if (group->type == USE_PTR_ADDRESS)
> +       fprintf (file, "  Type:\tPOINTER ARGUMENT ADDRESS\n");
>        else
>         {
>           gcc_assert (group->type == USE_COMPARE);
> @@ -1502,19 +1519,21 @@ find_induction_variables (struct ivopts_
>
>  /* Records a use of TYPE at *USE_P in STMT whose value is IV in GROUP.
>     For address type use, ADDR_BASE is the stripped IV base, ADDR_OFFSET
> -   is the const offset stripped from IV base; for other types use, both
> -   are zero by default.  */
> +   is the const offset stripped from IV base and MEM_TYPE is the type
> +   of the memory being addressed.  For uses of other types, ADDR_BASE
> +   and ADDR_OFFSET are zero by default and MEM_TYPE is NULL_TREE.  */
>
>  static struct iv_use *
>  record_use (struct iv_group *group, tree *use_p, struct iv *iv,
> -           gimple *stmt, enum use_type type, tree addr_base,
> -           poly_uint64 addr_offset)
> +           gimple *stmt, enum use_type type, tree mem_type,
> +           tree addr_base, poly_uint64 addr_offset)
>  {
>    struct iv_use *use = XCNEW (struct iv_use);
>
>    use->id = group->vuses.length ();
>    use->group_id = group->id;
>    use->type = type;
> +  use->mem_type = mem_type;
>    use->iv = iv;
>    use->stmt = stmt;
>    use->op_p = use_p;
> @@ -1569,18 +1588,21 @@ record_group (struct ivopts_data *data,
>  }
>
>  /* Record a use of TYPE at *USE_P in STMT whose value is IV in a group.
> -   New group will be created if there is no existing group for the use.  */
> +   New group will be created if there is no existing group for the use.
> +   MEM_TYPE is the type of memory being addressed, or NULL if this
> +   isn't an address reference.  */
>
>  static struct iv_use *
>  record_group_use (struct ivopts_data *data, tree *use_p,
> -                 struct iv *iv, gimple *stmt, enum use_type type)
> +                 struct iv *iv, gimple *stmt, enum use_type type,
> +                 tree mem_type)
>  {
>    tree addr_base = NULL;
>    struct iv_group *group = NULL;
>    poly_uint64 addr_offset = 0;
>
>    /* Record non address type use in a new group.  */
> -  if (type == USE_ADDRESS && iv->base_object)
> +  if (address_p (type) && iv->base_object)
I forgot to somplify this condition given (address_p (type) &&
!iv->base_object) is not allowed now.
You can simplify this after below comment on base_object if you want.
>      {
>        unsigned int i;
>
> @@ -1591,7 +1613,7 @@ record_group_use (struct ivopts_data *da
>
>           group = data->vgroups[i];
>           use = group->vuses[0];
> -         if (use->type != USE_ADDRESS || !use->iv->base_object)
And here.

> +         if (!address_p (use->type) || !use->iv->base_object)
>             continue;
>
>           /* Check if it has the same stripped base and step.  */
> @@ -1607,7 +1629,8 @@ record_group_use (struct ivopts_data *da
>    if (!group)
>      group = record_group (data, type);
>
> -  return record_use (group, use_p, iv, stmt, type, addr_base, addr_offset);
> +  return record_use (group, use_p, iv, stmt, type, mem_type,
> +                    addr_base, addr_offset);
>  }
>
>  /* Checks whether the use OP is interesting and if so, records it.  */
> @@ -1641,7 +1664,7 @@ find_interesting_uses_op (struct ivopts_
>    stmt = SSA_NAME_DEF_STMT (op);
>    gcc_assert (gimple_code (stmt) == GIMPLE_PHI || is_gimple_assign (stmt));
>
> -  use = record_group_use (data, NULL, iv, stmt, USE_NONLINEAR_EXPR);
> +  use = record_group_use (data, NULL, iv, stmt, USE_NONLINEAR_EXPR, 
> NULL_TREE);
>    iv->nonlin_use = use;
>    return use;
>  }
> @@ -1757,10 +1780,10 @@ find_interesting_uses_cond (struct ivopt
>        return;
>      }
>
> -  record_group_use (data, var_p, var_iv, stmt, USE_COMPARE);
> +  record_group_use (data, var_p, var_iv, stmt, USE_COMPARE, NULL_TREE);
>    /* Record compare type iv_use for iv on the other side of comparison.  */
>    if (ret == COMP_IV_EXPR_2)
> -    record_group_use (data, bound_p, bound_iv, stmt, USE_COMPARE);
> +    record_group_use (data, bound_p, bound_iv, stmt, USE_COMPARE, NULL_TREE);
>  }
>
>  /* Returns the outermost loop EXPR is obviously invariant in
> @@ -2375,7 +2398,7 @@ find_interesting_uses_address (struct iv
>    if (civ->base_object == NULL_TREE)
>      goto fail;
>
> -  record_group_use (data, op_p, civ, stmt, USE_ADDRESS);
> +  record_group_use (data, op_p, civ, stmt, USE_REF_ADDRESS, TREE_TYPE 
> (*op_p));
>    return;
>
>  fail:
> @@ -2398,6 +2421,51 @@ find_invariants_stmt (struct ivopts_data
>      }
>  }
>
> +/* CALL calls an internal function.  If operand *OP_P will become an
> +   address when the call is expanded, return the type of the memory
> +   being addressed, otherwise return null.  */
> +
> +static tree
> +get_mem_type_for_internal_fn (gcall *call, tree *op_p)
> +{
> +  switch (gimple_call_internal_fn (call))
> +    {
> +    case IFN_MASK_LOAD:
> +      if (op_p == gimple_call_arg_ptr (call, 0))
> +       return TREE_TYPE (gimple_call_lhs (call));
> +      return NULL_TREE;
> +
> +    case IFN_MASK_STORE:
> +      if (op_p == gimple_call_arg_ptr (call, 0))
> +       return TREE_TYPE (gimple_call_arg (call, 3));
> +      return NULL_TREE;
> +
> +    default:
> +      return NULL_TREE;
> +    }
> +}
> +
> +/* IV is a (non-address) iv that describes operand *OP_P of STMT.
> +   Return true if the operand will become an address when STMT
> +   is expanded and record the associated address use if so.  */
> +
> +static bool
> +find_address_like_use (struct ivopts_data *data, gimple *stmt, tree *op_p,
> +                      struct iv *iv)
> +{
> +  tree mem_type = NULL_TREE;
> +  if (gcall *call = dyn_cast <gcall *> (stmt))
> +    if (gimple_call_internal_p (call))
> +      mem_type = get_mem_type_for_internal_fn (call, op_p);
> +  if (mem_type)
> +    {
> +      iv = alloc_iv (data, iv->base, iv->step);
We now don't allow address type iv_use without base_object.  So
checking code like below
is needed here:

  /* Fail if base object of this memory reference is unknown.  */
  if (iv->base_object == NULL_TREE)
    return false;

IVOPTs part is OK with this change.

Thanks,
bin
> +      record_group_use (data, op_p, iv, stmt, USE_PTR_ADDRESS, mem_type);
> +      return true;
> +    }
> +  return false;
> +}
> +
>  /* Finds interesting uses of induction variables in the statement STMT.  */
>
>  static void
> @@ -2482,7 +2550,8 @@ find_interesting_uses_stmt (struct ivopt
>        if (!iv)
>         continue;
>
> -      find_interesting_uses_op (data, op);
> +      if (!find_address_like_use (data, stmt, use_p->use, iv))
> +       find_interesting_uses_op (data, op);
>      }
>  }
>
> @@ -2516,7 +2585,7 @@ addr_offset_valid_p (struct iv_use *use,
>    rtx reg, addr;
>    unsigned list_index;
>    addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (use->iv->base));
> -  machine_mode addr_mode, mem_mode = TYPE_MODE (TREE_TYPE (*use->op_p));
> +  machine_mode addr_mode, mem_mode = TYPE_MODE (use->mem_type);
>
>    list_index = (unsigned) as * MAX_MACHINE_MODE + (unsigned) mem_mode;
>    if (list_index >= vec_safe_length (addr_list))
> @@ -2573,7 +2642,7 @@ split_small_address_groups_p (struct ivo
>        if (group->vuses.length () == 1)
>         continue;
>
> -      gcc_assert (group->type == USE_ADDRESS);
> +      gcc_assert (address_p (group->type));
>        if (group->vuses.length () == 2)
>         {
>           if (compare_sizes_for_sort (group->vuses[0]->addr_offset,
> @@ -2625,7 +2694,7 @@ split_address_groups (struct ivopts_data
>        if (group->vuses.length () == 1)
>         continue;
>
> -      gcc_assert (group->type == USE_ADDRESS);
> +      gcc_assert (address_p (use->type));
>
>        for (j = 1; j < group->vuses.length ();)
>         {
> @@ -3145,7 +3214,7 @@ add_autoinc_candidates (struct ivopts_da
>
>    cstepi = int_cst_value (step);
>
> -  mem_mode = TYPE_MODE (TREE_TYPE (*use->op_p));
> +  mem_mode = TYPE_MODE (use->mem_type);
>    if (((USE_LOAD_PRE_INCREMENT (mem_mode)
>         || USE_STORE_PRE_INCREMENT (mem_mode))
>         && must_eq (GET_MODE_SIZE (mem_mode), cstepi))
> @@ -3436,7 +3505,7 @@ add_iv_candidate_for_use (struct ivopts_
>    /* At last, add auto-incremental candidates.  Make such variables
>       important since other iv uses with same base object may be based
>       on it.  */
> -  if (use != NULL && use->type == USE_ADDRESS)
> +  if (use != NULL && address_p (use->type))
>      add_autoinc_candidates (data, iv->base, iv->step, true, use);
>  }
>
> @@ -3903,7 +3972,7 @@ get_use_type (struct iv_use *use)
>    tree base_type = TREE_TYPE (use->iv->base);
>    tree type;
>
> -  if (use->type == USE_ADDRESS)
> +  if (use->type == USE_REF_ADDRESS)
>      {
>        /* The base_type may be a void pointer.  Create a pointer type based on
>          the mem_ref instead.  */
> @@ -4331,7 +4400,7 @@ get_address_cost (struct ivopts_data *da
>    struct mem_address parts = {NULL_TREE, integer_one_node,
>                               NULL_TREE, NULL_TREE, NULL_TREE};
>    machine_mode addr_mode = TYPE_MODE (type);
> -  machine_mode mem_mode = TYPE_MODE (TREE_TYPE (*use->op_p));
> +  machine_mode mem_mode = TYPE_MODE (use->mem_type);
>    addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (use->iv->base));
>    /* Only true if ratio != 1.  */
>    bool ok_with_ratio_p = false;
> @@ -5220,7 +5289,8 @@ determine_group_iv_cost (struct ivopts_d
>      case USE_NONLINEAR_EXPR:
>        return determine_group_iv_cost_generic (data, group, cand);
>
> -    case USE_ADDRESS:
> +    case USE_REF_ADDRESS:
> +    case USE_PTR_ADDRESS:
>        return determine_group_iv_cost_address (data, group, cand);
>
>      case USE_COMPARE:
> @@ -5238,7 +5308,7 @@ determine_group_iv_cost (struct ivopts_d
>  autoinc_possible_for_pair (struct ivopts_data *data, struct iv_use *use,
>                            struct iv_cand *cand)
>  {
> -  if (use->type != USE_ADDRESS)
> +  if (!address_p (use->type))
>      return false;
>
>    bool can_autoinc = false;
> @@ -6997,6 +7067,27 @@ adjust_iv_update_pos (struct iv_cand *ca
>    cand->incremented_at = use->stmt;
>  }
>
> +/* Return the alias pointer type that should be used for a MEM_REF
> +   associated with USE, which has type USE_PTR_ADDRESS.  */
> +
> +static tree
> +get_alias_ptr_type_for_ptr_address (iv_use *use)
> +{
> +  gcall *call = as_a <gcall *> (use->stmt);
> +  switch (gimple_call_internal_fn (call))
> +    {
> +    case IFN_MASK_LOAD:
> +    case IFN_MASK_STORE:
> +      /* 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));
> +
> +    default:
> +      gcc_unreachable ();
> +    }
> +}
> +
> +
>  /* Rewrites USE (address that is an iv) using candidate CAND.  */
>
>  static void
> @@ -7025,16 +7116,31 @@ rewrite_use_address (struct ivopts_data
>    tree iv = var_at_stmt (data->current_loop, cand, use->stmt);
>    tree base_hint = (cand->iv->base_object) ? iv : NULL_TREE;
>    gimple_stmt_iterator bsi = gsi_for_stmt (use->stmt);
> -  tree type = TREE_TYPE (*use->op_p);
> -  unsigned int align = get_object_alignment (*use->op_p);
> -  if (align != TYPE_ALIGN (type))
> -    type = build_aligned_type (type, align);
> -
> -  tree ref = create_mem_ref (&bsi, type, &aff,
> -                            reference_alias_ptr_type (*use->op_p),
> +  tree type = use->mem_type;
> +  tree alias_ptr_type;
> +  if (use->type == USE_PTR_ADDRESS)
> +    alias_ptr_type = get_alias_ptr_type_for_ptr_address (use);
> +  else
> +    {
> +      gcc_assert (type == TREE_TYPE (*use->op_p));
> +      unsigned int align = get_object_alignment (*use->op_p);
> +      if (align != TYPE_ALIGN (type))
> +       type = build_aligned_type (type, align);
> +      alias_ptr_type = reference_alias_ptr_type (*use->op_p);
> +    }
> +  tree ref = create_mem_ref (&bsi, type, &aff, alias_ptr_type,
>                              iv, base_hint, data->speed);
>
> -  copy_ref_info (ref, *use->op_p);
> +  if (use->type == USE_PTR_ADDRESS)
> +    {
> +      ref = fold_build1 (ADDR_EXPR, build_pointer_type (use->mem_type), ref);
> +      ref = fold_convert (get_use_type (use), ref);
> +      ref = force_gimple_operand_gsi (&bsi, ref, true, NULL_TREE,
> +                                     true, GSI_SAME_STMT);
> +    }
> +  else
> +    copy_ref_info (ref, *use->op_p);
> +
>    *use->op_p = ref;
>  }
>
> @@ -7110,7 +7216,7 @@ rewrite_groups (struct ivopts_data *data
>               update_stmt (group->vuses[j]->stmt);
>             }
>         }
> -      else if (group->type == USE_ADDRESS)
> +      else if (address_p (group->type))
>         {
>           for (j = 0; j < group->vuses.length (); j++)
>             {
> Index: gcc/testsuite/gcc.dg/tree-ssa/scev-9.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/tree-ssa/scev-9.c      2016-05-02 10:44:33.000000000 
> +0100
> +++ gcc/testsuite/gcc.dg/tree-ssa/scev-9.c      2017-11-17 15:02:12.869042409 
> +0000
> @@ -18,5 +18,5 @@ foo (unsigned char s, unsigned char l)
>  }
>
>  /* Address of array reference is scev.  */
> -/* { dg-final { scan-tree-dump-times "  Type:\\tADDRESS\n  Use 
> \[0-9\].\[0-9\]:" 1 "ivopts" } } */
> +/* { dg-final { scan-tree-dump-times "  Type:\\tREFERENCE ADDRESS\n  Use 
> \[0-9\].\[0-9\]:" 1 "ivopts" } } */
>
> Index: gcc/testsuite/gcc.dg/tree-ssa/scev-10.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/tree-ssa/scev-10.c     2016-05-02 10:44:33.000000000 
> +0100
> +++ gcc/testsuite/gcc.dg/tree-ssa/scev-10.c     2017-11-17 15:02:12.869042409 
> +0000
> @@ -18,5 +18,5 @@ foo (signed char s, signed char l)
>  }
>
>  /* Address of array reference is scev.  */
> -/* { dg-final { scan-tree-dump-times "  Type:\\tADDRESS\n  Use 
> \[0-9\].\[0-9\]:" 1 "ivopts" } } */
> +/* { dg-final { scan-tree-dump-times "  Type:\\tREFERENCE ADDRESS\n  Use 
> \[0-9\].\[0-9\]:" 1 "ivopts" } } */
>
> Index: gcc/testsuite/gcc.dg/tree-ssa/scev-11.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/tree-ssa/scev-11.c     2016-05-02 10:44:33.000000000 
> +0100
> +++ gcc/testsuite/gcc.dg/tree-ssa/scev-11.c     2017-11-17 15:02:12.869042409 
> +0000
> @@ -23,4 +23,4 @@ foo (int n)
>  }
>
>  /* Address of array reference to b is scev.  */
> -/* { dg-final { scan-tree-dump-times "  Type:\\tADDRESS\n  Use 
> \[0-9\].\[0-9\]:" 2 "ivopts" } } */
> +/* { dg-final { scan-tree-dump-times "  Type:\\tREFERENCE ADDRESS\n  Use 
> \[0-9\].\[0-9\]:" 2 "ivopts" } } */
> Index: gcc/testsuite/gcc.dg/tree-ssa/scev-12.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/tree-ssa/scev-12.c     2016-05-02 10:44:33.000000000 
> +0100
> +++ gcc/testsuite/gcc.dg/tree-ssa/scev-12.c     2017-11-17 15:02:12.869042409 
> +0000
> @@ -24,4 +24,4 @@ foo (int x, int n)
>  }
>
>  /* Address of array reference to b is not scev.  */
> -/* { dg-final { scan-tree-dump-times "  Type:\\tADDRESS\n  Use 
> \[0-9\].\[0-9\]:" 1 "ivopts" } } */
> +/* { dg-final { scan-tree-dump-times "  Type:\\tREFERENCE ADDRESS\n  Use 
> \[0-9\].\[0-9\]:" 1 "ivopts" } } */
> Index: gcc/testsuite/gcc.target/aarch64/sve_index_offset_1.c
> ===================================================================
> --- /dev/null   2017-11-14 14:28:07.424493901 +0000
> +++ gcc/testsuite/gcc.target/aarch64/sve_index_offset_1.c       2017-11-17 
> 15:02:12.869042409 +0000
> @@ -0,0 +1,49 @@
> +/* { dg-do compile } */
> +/* { dg-options "-std=c99 -ftree-vectorize -O2 -fno-inline 
> -march=armv8-a+sve -msve-vector-bits=256" } */
> +
> +#define SIZE 15*8+3
> +
> +#define INDEX_OFFSET_TEST_1(SIGNED, TYPE, ITERTYPE) \
> +void set_##SIGNED##_##TYPE##_##ITERTYPE (SIGNED TYPE *__restrict out, \
> +                                        SIGNED TYPE *__restrict in) \
> +{ \
> +  SIGNED ITERTYPE i; \
> +  for (i = 0; i < SIZE; i++) \
> +  { \
> +    out[i] = in[i]; \
> +  } \
> +} \
> +void set_##SIGNED##_##TYPE##_##ITERTYPE##_var (SIGNED TYPE *__restrict out, \
> +                                              SIGNED TYPE *__restrict in, \
> +                                              SIGNED ITERTYPE n) \
> +{\
> +  SIGNED ITERTYPE i;\
> +  for (i = 0; i < n; i++)\
> +  {\
> +    out[i] = in[i];\
> +  }\
> +}
> +
> +#define INDEX_OFFSET_TEST(SIGNED, TYPE)\
> +  INDEX_OFFSET_TEST_1 (SIGNED, TYPE, char) \
> +  INDEX_OFFSET_TEST_1 (SIGNED, TYPE, short) \
> +  INDEX_OFFSET_TEST_1 (SIGNED, TYPE, int) \
> +  INDEX_OFFSET_TEST_1 (SIGNED, TYPE, long)
> +
> +INDEX_OFFSET_TEST (signed, long)
> +INDEX_OFFSET_TEST (unsigned, long)
> +INDEX_OFFSET_TEST (signed, int)
> +INDEX_OFFSET_TEST (unsigned, int)
> +INDEX_OFFSET_TEST (signed, short)
> +INDEX_OFFSET_TEST (unsigned, short)
> +INDEX_OFFSET_TEST (signed, char)
> +INDEX_OFFSET_TEST (unsigned, char)
> +
> +/* { dg-final { scan-assembler-times "ld1d\\tz\[0-9\]+.d, p\[0-9\]+/z, 
> \\\[x\[0-9\]+, x\[0-9\]+, lsl 3\\\]" 16 } } */
> +/* { dg-final { scan-assembler-times "st1d\\tz\[0-9\]+.d, p\[0-9\]+, 
> \\\[x\[0-9\]+, x\[0-9\]+, lsl 3\\\]" 16 } } */
> +/* { dg-final { scan-assembler-times "ld1w\\tz\[0-9\]+.s, p\[0-9\]+/z, 
> \\\[x\[0-9\]+, x\[0-9\]+, lsl 2\\\]" 16 } } */
> +/* { dg-final { scan-assembler-times "st1w\\tz\[0-9\]+.s, p\[0-9\]+, 
> \\\[x\[0-9\]+, x\[0-9\]+, lsl 2\\\]" 16 } } */
> +/* { dg-final { scan-assembler-times "ld1h\\tz\[0-9\]+.h, p\[0-9\]+/z, 
> \\\[x\[0-9\]+, x\[0-9\]+, lsl 1\\\]" 16 } } */
> +/* { dg-final { scan-assembler-times "st1h\\tz\[0-9\]+.h, p\[0-9\]+, 
> \\\[x\[0-9\]+, x\[0-9\]+, lsl 1\\\]" 16 } } */
> +/* { dg-final { scan-assembler-times "ld1b\\tz\[0-9\]+.b, p\[0-9\]+/z, 
> \\\[x\[0-9\]+, x\[0-9\]+\\\]" 16 } } */
> +/* { dg-final { scan-assembler-times "st1b\\tz\[0-9\]+.b, p\[0-9\]+, 
> \\\[x\[0-9\]+, x\[0-9\]+\\\]" 16 } } */
> Index: gcc/testsuite/gcc.target/aarch64/sve_index_offset_1_run.c
> ===================================================================
> --- /dev/null   2017-11-14 14:28:07.424493901 +0000
> +++ gcc/testsuite/gcc.target/aarch64/sve_index_offset_1_run.c   2017-11-17 
> 15:02:12.869042409 +0000
> @@ -0,0 +1,48 @@
> +/* { dg-do run { target aarch64_sve_hw } } */
> +/* { dg-options "-std=c99 -ftree-vectorize -O2 -fno-inline 
> -march=armv8-a+sve" } */
> +/* { dg-options "-std=c99 -ftree-vectorize -O2 -fno-inline 
> -march=armv8-a+sve -msve-vector-bits=256" { target aarch64_sve256_hw } } */
> +
> +#include "sve_index_offset_1_run.c"
> +
> +#include <string.h>
> +
> +#define CALL_INDEX_OFFSET_TEST_1(SIGNED, TYPE, ITERTYPE)\
> +{\
> +  SIGNED TYPE out[SIZE + 1];\
> +  SIGNED TYPE in1[SIZE + 1];\
> +  SIGNED TYPE in2[SIZE + 1];\
> +  for (int i = 0; i < SIZE + 1; ++i)\
> +    {\
> +      in1[i] = (i * 4) ^ i;\
> +      in2[i] = (i * 2) ^ i;\
> +    }\
> +  out[SIZE] = 42;\
> +  set_##SIGNED##_##TYPE##_##ITERTYPE (out, in1); \
> +  if (0 != memcmp (out, in1, SIZE * sizeof (TYPE)))\
> +    return 1;\
> +  set_##SIGNED##_##TYPE##_##ITERTYPE##_var (out, in2, SIZE); \
> +  if (0 != memcmp (out, in2, SIZE * sizeof (TYPE)))\
> +    return 1;\
> +  if (out[SIZE] != 42)\
> +    return 1;\
> +}
> +
> +#define CALL_INDEX_OFFSET_TEST(SIGNED, TYPE)\
> +  CALL_INDEX_OFFSET_TEST_1 (SIGNED, TYPE, char) \
> +  CALL_INDEX_OFFSET_TEST_1 (SIGNED, TYPE, short) \
> +  CALL_INDEX_OFFSET_TEST_1 (SIGNED, TYPE, int) \
> +  CALL_INDEX_OFFSET_TEST_1 (SIGNED, TYPE, long)
> +
> +int
> +main (void)
> +{
> +  CALL_INDEX_OFFSET_TEST (signed, long)
> +  CALL_INDEX_OFFSET_TEST (unsigned, long)
> +  CALL_INDEX_OFFSET_TEST (signed, int)
> +  CALL_INDEX_OFFSET_TEST (unsigned, int)
> +  CALL_INDEX_OFFSET_TEST (signed, short)
> +  CALL_INDEX_OFFSET_TEST (unsigned, short)
> +  CALL_INDEX_OFFSET_TEST (signed, char)
> +  CALL_INDEX_OFFSET_TEST (unsigned, char)
> +  return 0;
> +}
> Index: gcc/testsuite/gcc.target/aarch64/sve_loop_add_2.c
> ===================================================================
> --- /dev/null   2017-11-14 14:28:07.424493901 +0000
> +++ gcc/testsuite/gcc.target/aarch64/sve_loop_add_2.c   2017-11-17 
> 15:02:12.869952359 +0000
> @@ -0,0 +1,12 @@
> +/* { dg-do compile } */
> +/* { dg-options "-std=c99 -O3 -march=armv8-a+sve" } */
> +
> +void
> +foo (int *__restrict a, int *__restrict b)
> +{
> +  for (int i = 0; i < 512; ++i)
> +    a[i] += b[i];
> +}
> +
> +/* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+.s, p[0-7]+/z, 
> \[x[0-9]+, x[0-9]+, lsl 2\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tst1w\tz[0-9]+.s, p[0-7]+, \[x[0-9]+, 
> x[0-9]+, lsl 2\]\n} 1 } } */
> Index: gcc/testsuite/gcc.target/aarch64/sve_loop_add_3.c
> ===================================================================
> --- /dev/null   2017-11-14 14:28:07.424493901 +0000
> +++ gcc/testsuite/gcc.target/aarch64/sve_loop_add_3.c   2017-11-17 
> 15:02:12.869952359 +0000
> @@ -0,0 +1,20 @@
> +/* { dg-do compile } */
> +/* { dg-options "-std=c99 -O3 -march=armv8-a+sve" } */
> +
> +void
> +f (int *__restrict a,
> +   int *__restrict b,
> +   int *__restrict c,
> +   int *__restrict d,
> +   int *__restrict e,
> +   int *__restrict f,
> +   int *__restrict g,
> +   int *__restrict h,
> +   int count)
> +{
> +  for (int i = 0; i < count; ++i)
> +    a[i] = b[i] + c[i] + d[i] + e[i] + f[i] + g[i] + h[i];
> +}
> +
> +/* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+.s, p[0-7]+/z, 
> \[x[0-9]+, x[0-9]+, lsl 2\]\n} 7 } } */
> +/* { dg-final { scan-assembler-times {\tst1w\tz[0-9]+.s, p[0-7]+, \[x[0-9]+, 
> x[0-9]+, lsl 2\]\n} 1 } } */
> Index: gcc/testsuite/gcc.target/aarch64/sve_while_1.c
> ===================================================================
> --- gcc/testsuite/gcc.target/aarch64/sve_while_1.c      2017-11-17 
> 14:54:06.035305786 +0000
> +++ gcc/testsuite/gcc.target/aarch64/sve_while_1.c      2017-11-17 
> 15:02:12.869952359 +0000
> @@ -34,3 +34,11 @@ TEST_ALL (ADD_LOOP)
>  /* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.s, x[0-9]+,} 3 } } 
> */
>  /* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.d, xzr,} 3 } } */
>  /* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.d, x[0-9]+,} 3 } } 
> */
> +/* { dg-final { scan-assembler-times {\tld1b\tz[0-9]+\.b, p[0-7]/z, \[x0, 
> x[0-9]+\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tst1b\tz[0-9]+\.b, p[0-7], \[x0, 
> x[0-9]+\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.h, p[0-7]/z, \[x0, 
> x[0-9]+, lsl 1\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tst1h\tz[0-9]+\.h, p[0-7], \[x0, 
> x[0-9]+, lsl 1\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.s, p[0-7]/z, \[x0, 
> x[0-9]+, lsl 2\]\n} 3 } } */
> +/* { dg-final { scan-assembler-times {\tst1w\tz[0-9]+\.s, p[0-7], \[x0, 
> x[0-9]+, lsl 2\]\n} 3 } } */
> +/* { dg-final { scan-assembler-times {\tld1d\tz[0-9]+\.d, p[0-7]/z, \[x0, 
> x[0-9]+, lsl 3\]\n} 3 } } */
> +/* { dg-final { scan-assembler-times {\tst1d\tz[0-9]+\.d, p[0-7], \[x0, 
> x[0-9]+, lsl 3\]\n} 3 } } */
> Index: gcc/testsuite/gcc.target/aarch64/sve_while_2.c
> ===================================================================
> --- gcc/testsuite/gcc.target/aarch64/sve_while_2.c      2017-11-17 
> 14:54:06.035305786 +0000
> +++ gcc/testsuite/gcc.target/aarch64/sve_while_2.c      2017-11-17 
> 15:02:12.869952359 +0000
> @@ -34,3 +34,11 @@ TEST_ALL (ADD_LOOP)
>  /* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.s, x[0-9]+,} 3 } } 
> */
>  /* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.d, xzr,} 3 } } */
>  /* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.d, x[0-9]+,} 3 } } 
> */
> +/* { dg-final { scan-assembler-times {\tld1b\tz[0-9]+\.b, p[0-7]/z, \[x0, 
> x[0-9]+\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tst1b\tz[0-9]+\.b, p[0-7], \[x0, 
> x[0-9]+\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.h, p[0-7]/z, \[x0, 
> x[0-9]+, lsl 1\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tst1h\tz[0-9]+\.h, p[0-7], \[x0, 
> x[0-9]+, lsl 1\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.s, p[0-7]/z, \[x0, 
> x[0-9]+, lsl 2\]\n} 3 } } */
> +/* { dg-final { scan-assembler-times {\tst1w\tz[0-9]+\.s, p[0-7], \[x0, 
> x[0-9]+, lsl 2\]\n} 3 } } */
> +/* { dg-final { scan-assembler-times {\tld1d\tz[0-9]+\.d, p[0-7]/z, \[x0, 
> x[0-9]+, lsl 3\]\n} 3 } } */
> +/* { dg-final { scan-assembler-times {\tst1d\tz[0-9]+\.d, p[0-7], \[x0, 
> x[0-9]+, lsl 3\]\n} 3 } } */
> Index: gcc/testsuite/gcc.target/aarch64/sve_while_3.c
> ===================================================================
> --- gcc/testsuite/gcc.target/aarch64/sve_while_3.c      2017-11-17 
> 14:54:06.035305786 +0000
> +++ gcc/testsuite/gcc.target/aarch64/sve_while_3.c      2017-11-17 
> 15:02:12.869952359 +0000
> @@ -34,3 +34,11 @@ TEST_ALL (ADD_LOOP)
>  /* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.s, x[0-9]+,} 3 } } 
> */
>  /* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.d, xzr,} 3 } } */
>  /* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.d, x[0-9]+,} 3 } } 
> */
> +/* { dg-final { scan-assembler-times {\tld1b\tz[0-9]+\.b, p[0-7]/z, \[x0, 
> x[0-9]+\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tst1b\tz[0-9]+\.b, p[0-7], \[x0, 
> x[0-9]+\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.h, p[0-7]/z, \[x0, 
> x[0-9]+, lsl 1\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tst1h\tz[0-9]+\.h, p[0-7], \[x0, 
> x[0-9]+, lsl 1\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.s, p[0-7]/z, \[x0, 
> x[0-9]+, lsl 2\]\n} 3 } } */
> +/* { dg-final { scan-assembler-times {\tst1w\tz[0-9]+\.s, p[0-7], \[x0, 
> x[0-9]+, lsl 2\]\n} 3 } } */
> +/* { dg-final { scan-assembler-times {\tld1d\tz[0-9]+\.d, p[0-7]/z, \[x0, 
> x[0-9]+, lsl 3\]\n} 3 } } */
> +/* { dg-final { scan-assembler-times {\tst1d\tz[0-9]+\.d, p[0-7], \[x0, 
> x[0-9]+, lsl 3\]\n} 3 } } */
> Index: gcc/testsuite/gcc.target/aarch64/sve_while_4.c
> ===================================================================
> --- gcc/testsuite/gcc.target/aarch64/sve_while_4.c      2017-11-17 
> 14:54:06.035305786 +0000
> +++ gcc/testsuite/gcc.target/aarch64/sve_while_4.c      2017-11-17 
> 15:02:12.869952359 +0000
> @@ -35,3 +35,11 @@ TEST_ALL (ADD_LOOP)
>  /* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.s, x[0-9]+,} 3 } } 
> */
>  /* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.d, xzr,} 3 } } */
>  /* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.d, x[0-9]+,} 3 } } 
> */
> +/* { dg-final { scan-assembler-times {\tld1b\tz[0-9]+\.b, p[0-7]/z, \[x0, 
> x[0-9]+\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tst1b\tz[0-9]+\.b, p[0-7], \[x0, 
> x[0-9]+\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.h, p[0-7]/z, \[x0, 
> x[0-9]+, lsl 1\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tst1h\tz[0-9]+\.h, p[0-7], \[x0, 
> x[0-9]+, lsl 1\]\n} 2 } } */
> +/* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.s, p[0-7]/z, \[x0, 
> x[0-9]+, lsl 2\]\n} 3 } } */
> +/* { dg-final { scan-assembler-times {\tst1w\tz[0-9]+\.s, p[0-7], \[x0, 
> x[0-9]+, lsl 2\]\n} 3 } } */
> +/* { dg-final { scan-assembler-times {\tld1d\tz[0-9]+\.d, p[0-7]/z, \[x0, 
> x[0-9]+, lsl 3\]\n} 3 } } */
> +/* { dg-final { scan-assembler-times {\tst1d\tz[0-9]+\.d, p[0-7], \[x0, 
> x[0-9]+, lsl 3\]\n} 3 } } */

Reply via email to