This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Make ivopts handle calls to internal functions
- From: Richard Sandiford <richard dot sandiford at linaro dot org>
- To: gcc-patches at gcc dot gnu dot org
- Cc: bin dot cheng at arm dot com
- Date: Fri, 17 Nov 2017 15:03:55 +0000
- Subject: Make ivopts handle calls to internal functions
- Authentication-results: sourceware.org; auth=none
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.
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.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@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);
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)
{
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)
+ 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);
+ 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 } } */