Commit 65dd1346 by Richard Sandiford Committed by Richard Sandiford

Allow ADDR_EXPRs of TARGET_MEM_REFs

This patch allows ADDR_EXPR <TARGET_MEM_REF ...>, which is useful
when calling internal functions that take pointers to memory that
is conditionally loaded or stored.  This is a prerequisite to the
following ivopts patch.

2018-01-13  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.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>

From-SVN: r256627
parent 0972596e
...@@ -2,6 +2,18 @@ ...@@ -2,6 +2,18 @@
Alan Hayward <alan.hayward@arm.com> Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com> David Sherwood <david.sherwood@arm.com>
* 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.
2018-01-13 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
* doc/md.texi (cond_add@var{mode}, cond_sub@var{mode}) * doc/md.texi (cond_add@var{mode}, cond_sub@var{mode})
(cond_and@var{mode}, cond_ior@var{mode}, cond_xor@var{mode}) (cond_and@var{mode}, cond_ior@var{mode}, cond_xor@var{mode})
(cond_smin@var{mode}, cond_smax@var{mode}, cond_umin@var{mode}) (cond_smin@var{mode}, cond_smax@var{mode}, cond_umin@var{mode})
......
...@@ -7885,6 +7885,9 @@ expand_expr_addr_expr_1 (tree exp, rtx target, scalar_int_mode tmode, ...@@ -7885,6 +7885,9 @@ expand_expr_addr_expr_1 (tree exp, rtx target, scalar_int_mode tmode,
return expand_expr (tem, target, tmode, modifier); return expand_expr (tem, target, tmode, modifier);
} }
case TARGET_MEM_REF:
return addr_for_mem_ref (exp, as, true);
case CONST_DECL: case CONST_DECL:
/* Expand the initializer like constants above. */ /* Expand the initializer like constants above. */
result = XEXP (expand_expr_constant (DECL_INITIAL (exp), result = XEXP (expand_expr_constant (DECL_INITIAL (exp),
......
...@@ -631,7 +631,9 @@ is_gimple_address (const_tree t) ...@@ -631,7 +631,9 @@ is_gimple_address (const_tree t)
op = TREE_OPERAND (op, 0); 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; return true;
switch (TREE_CODE (op)) switch (TREE_CODE (op))
......
...@@ -119,6 +119,7 @@ static inline bool ...@@ -119,6 +119,7 @@ static inline bool
is_gimple_addressable (tree t) is_gimple_addressable (tree t)
{ {
return (is_gimple_id (t) || handled_component_p (t) return (is_gimple_id (t) || handled_component_p (t)
|| TREE_CODE (t) == TARGET_MEM_REF
|| TREE_CODE (t) == MEM_REF); || TREE_CODE (t) == MEM_REF);
} }
......
...@@ -2412,15 +2412,54 @@ expand_LOOP_DIST_ALIAS (internal_fn, gcall *) ...@@ -2412,15 +2412,54 @@ expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
gcc_unreachable (); 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))
{
tree offset = TMR_OFFSET (mem);
if (alias_ptr_type != TREE_TYPE (offset) || !integer_zerop (offset))
{
mem = copy_node (mem);
TMR_OFFSET (mem) = wide_int_to_tree (alias_ptr_type,
wi::to_poly_wide (offset));
}
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. */ /* Expand MASK_LOAD{,_LANES} call STMT using optab OPTAB. */
static void static void
expand_mask_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab) expand_mask_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
{ {
struct expand_operand ops[3]; struct expand_operand ops[3];
tree type, lhs, rhs, maskt, ptr; tree type, lhs, rhs, maskt;
rtx mem, target, mask; rtx mem, target, mask;
unsigned align;
insn_code icode; insn_code icode;
maskt = gimple_call_arg (stmt, 2); maskt = gimple_call_arg (stmt, 2);
...@@ -2428,11 +2467,7 @@ expand_mask_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab) ...@@ -2428,11 +2467,7 @@ expand_mask_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
if (lhs == NULL_TREE) if (lhs == NULL_TREE)
return; return;
type = TREE_TYPE (lhs); type = TREE_TYPE (lhs);
ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), 0); rhs = expand_call_mem_ref (type, stmt, 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);
if (optab == vec_mask_load_lanes_optab) if (optab == vec_mask_load_lanes_optab)
icode = get_multi_vector_move (type, optab); icode = get_multi_vector_move (type, optab);
...@@ -2458,19 +2493,14 @@ static void ...@@ -2458,19 +2493,14 @@ static void
expand_mask_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab) expand_mask_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
{ {
struct expand_operand ops[3]; struct expand_operand ops[3];
tree type, lhs, rhs, maskt, ptr; tree type, lhs, rhs, maskt;
rtx mem, reg, mask; rtx mem, reg, mask;
unsigned align;
insn_code icode; insn_code icode;
maskt = gimple_call_arg (stmt, 2); maskt = gimple_call_arg (stmt, 2);
rhs = gimple_call_arg (stmt, 3); rhs = gimple_call_arg (stmt, 3);
type = TREE_TYPE (rhs); type = TREE_TYPE (rhs);
ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), 0); lhs = expand_call_mem_ref (type, stmt, 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);
if (optab == vec_mask_store_lanes_optab) if (optab == vec_mask_store_lanes_optab)
icode = get_multi_vector_move (type, optab); icode = get_multi_vector_move (type, optab);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment