Richard Biener <[email protected]> writes:
> On Mon, Nov 20, 2017 at 12:31 PM, Bin.Cheng <[email protected]> wrote:
>> On Fri, Nov 17, 2017 at 3:03 PM, Richard Sandiford
>> <[email protected]> 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.
>
> In addition to Bins comments I only have a single one (the rest of the
> middle-end
> changes look OK). The alias type of MEM_REFs and TARGET_MEM_REFs
> in ADDR_EXPR context is meaningless so you don't need to jump through hoops
> to get at it or preserve it in any way, likewise for CLIQUE/BASE if it
> were present.
Ah, OK.
> Maybe you can simplify code with this.
In the end it didn't really simplify the code, since internal-fn.c
uses the address to build a (TARGET_)MEM_REF, and the alias information
of that ref needs to be correct, since it gets carried across to the
MEM rtx. But it does mean that the alias_ptr_type check in the previous:
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;
made no sense: we should simply replace the TMR_OFFSET if it has
the wrong type.
> As you're introducing &TARGET_MEM_REF as a valid construct (it weren't
> before) you'll run into missing / misguided foldings eventually. So
> be prepared to fix up fallout.
OK :-) I haven't hit any new places yet, but like you say, I'll be on
the lookout.
Is the version below OK? Tested on aarch64-linux-gnu, x86_64-linux-gnu
and powerpc64le-linux-gnu.
Richard
2018-01-09 Richard Sandiford <[email protected]>
Alan Hayward <[email protected]>
David Sherwood <[email protected]>
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.
Index: gcc/expr.c
===================================================================
--- gcc/expr.c 2018-01-09 15:13:32.603106251 +0000
+++ gcc/expr.c 2018-01-09 15:13:32.784098242 +0000
@@ -7885,6 +7885,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 2018-01-09 15:13:32.603106251 +0000
+++ gcc/gimple-expr.h 2018-01-09 15:13:32.785098198 +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 2018-01-09 15:13:32.603106251 +0000
+++ gcc/gimple-expr.c 2018-01-09 15:13:32.784098242 +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 2018-01-09 15:13:32.603106251 +0000
+++ gcc/internal-fn.c 2018-01-09 15:13:32.785098198 +0000
@@ -2412,15 +2412,53 @@ 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)
+ && integer_zerop (TMR_OFFSET (mem)))
+ {
+ if (alias_ptr_type != TREE_TYPE (TMR_OFFSET (mem)))
+ {
+ mem = copy_node (mem);
+ TMR_OFFSET (mem) = build_int_cst (alias_ptr_type, 0);
+ }
+ 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);
@@ -2428,11 +2466,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);
@@ -2458,19 +2492,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);