diff options
author | Richard Biener <rguenther@suse.de> | 2019-10-24 15:01:45 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2019-10-24 15:01:45 +0000 |
commit | 4352288a3df915575a2b820f702242908740106f (patch) | |
tree | 575af1eed28449217962628ae5ea192898d39358 /gcc/tree-vect-slp.c | |
parent | 5ce55f3ff5d04834e436a72fb2be84b31aa89def (diff) |
tree-vect-slp.c (vect_get_and_check_slp_defs): For reduction chains try harder with operand swapping and instead of putting a...
2019-10-24 Richard Biener <rguenther@suse.de>
* tree-vect-slp.c (vect_get_and_check_slp_defs): For reduction
chains try harder with operand swapping and instead of
putting a shifted chain into the reduction operands put
a repetition of the final reduction op there as if we'd
reassociate the expression.
* gcc.dg/vect/slp-reduc-10a.c: New testcase.
* gcc.dg/vect/slp-reduc-10b.c: Likewise.
* gcc.dg/vect/slp-reduc-10c.c: Likewise.
* gcc.dg/vect/slp-reduc-10d.c: Likewise.
* gcc.dg/vect/slp-reduc-10e.c: Likewise.
From-SVN: r277406
Diffstat (limited to 'gcc/tree-vect-slp.c')
-rw-r--r-- | gcc/tree-vect-slp.c | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index 0af51197a84..3db08fac400 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -433,20 +433,35 @@ again: the def-stmt/s of the first stmt. Allow different definition types for reduction chains: the first stmt must be a vect_reduction_def (a phi node), and the rest - vect_internal_def. */ + end in the reduction chain. */ tree type = TREE_TYPE (oprnd); if ((oprnd_info->first_dt != dt && !(oprnd_info->first_dt == vect_reduction_def - && dt == vect_internal_def) + && !STMT_VINFO_DATA_REF (stmt_info) + && REDUC_GROUP_FIRST_ELEMENT (stmt_info) + && def_stmt_info + && !STMT_VINFO_DATA_REF (def_stmt_info) + && (REDUC_GROUP_FIRST_ELEMENT (def_stmt_info) + == REDUC_GROUP_FIRST_ELEMENT (stmt_info))) && !((oprnd_info->first_dt == vect_external_def || oprnd_info->first_dt == vect_constant_def) && (dt == vect_external_def || dt == vect_constant_def))) - || !types_compatible_p (oprnd_info->first_op_type, type)) + || !types_compatible_p (oprnd_info->first_op_type, type) + || (!STMT_VINFO_DATA_REF (stmt_info) + && REDUC_GROUP_FIRST_ELEMENT (stmt_info) + && ((!def_stmt_info + || STMT_VINFO_DATA_REF (def_stmt_info) + || (REDUC_GROUP_FIRST_ELEMENT (def_stmt_info) + != REDUC_GROUP_FIRST_ELEMENT (stmt_info))) + != (oprnd_info->first_dt != vect_reduction_def)))) { /* Try swapping operands if we got a mismatch. */ if (i == commutative_op && !swapped) { + if (dump_enabled_p ()) + dump_printf_loc (MSG_NOTE, vect_location, + "trying swapped operands\n"); swapped = true; goto again; } @@ -484,9 +499,26 @@ again: oprnd_info->ops.quick_push (oprnd); break; + case vect_internal_def: case vect_reduction_def: + if (oprnd_info->first_dt == vect_reduction_def + && !STMT_VINFO_DATA_REF (stmt_info) + && REDUC_GROUP_FIRST_ELEMENT (stmt_info) + && !STMT_VINFO_DATA_REF (def_stmt_info) + && (REDUC_GROUP_FIRST_ELEMENT (def_stmt_info) + == REDUC_GROUP_FIRST_ELEMENT (stmt_info))) + { + /* For a SLP reduction chain we want to duplicate the + reduction to each of the chain members. That gets + us a sane SLP graph (still the stmts are not 100% + correct wrt the initial values). */ + gcc_assert (!first); + oprnd_info->def_stmts.quick_push (oprnd_info->def_stmts[0]); + oprnd_info->ops.quick_push (oprnd_info->ops[0]); + break; + } + /* Fallthru. */ case vect_induction_def: - case vect_internal_def: oprnd_info->def_stmts.quick_push (def_stmt_info); oprnd_info->ops.quick_push (oprnd); break; @@ -1182,15 +1214,8 @@ vect_build_slp_tree_2 (vec_info *vinfo, /* Else def types have to match. */ stmt_vec_info other_info; FOR_EACH_VEC_ELT (stmts, i, other_info) - { - /* But for reduction chains only check on the first stmt. */ - if (!STMT_VINFO_DATA_REF (other_info) - && REDUC_GROUP_FIRST_ELEMENT (other_info) - && REDUC_GROUP_FIRST_ELEMENT (other_info) != stmt_info) - continue; - if (STMT_VINFO_DEF_TYPE (other_info) != def_type) - return NULL; - } + if (STMT_VINFO_DEF_TYPE (other_info) != def_type) + return NULL; } else return NULL; |