diff options
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-over-widen-10.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-over-widen-11.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-over-widen-12.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-over-widen-13.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-over-widen-14.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-over-widen-15.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-over-widen-16.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-over-widen-22.c | 53 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-over-widen-5.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-over-widen-6.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-over-widen-7.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-over-widen-8.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-over-widen-9.c | 1 | ||||
-rw-r--r-- | gcc/tree-vect-patterns.c | 103 |
16 files changed, 190 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ab97a84..fd928b0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,10 @@ 2018-07-03 Richard Sandiford <richard.sandiford@arm.com> + * tree-vect-patterns.c (vect_split_statement): New function. + (vect_convert_input): Use it to try to split an existing cast. + +2018-07-03 Richard Sandiford <richard.sandiford@arm.com> + * poly-int.h (print_hex): New function. * dumpfile.h (dump_dec, dump_hex): Declare. * dumpfile.c (dump_dec, dump_hex): New poly_wide_int functions. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0028d4f..90aa4d7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,22 @@ 2018-07-03 Richard Sandiford <richard.sandiford@arm.com> + * gcc.dg/vect/vect-over-widen-5.c: Test that the extensions + get split into two for use by the over-widening pattern. + * gcc.dg/vect/vect-over-widen-6.c: Likewise. + * gcc.dg/vect/vect-over-widen-7.c: Likewise. + * gcc.dg/vect/vect-over-widen-8.c: Likewise. + * gcc.dg/vect/vect-over-widen-9.c: Likewise. + * gcc.dg/vect/vect-over-widen-10.c: Likewise. + * gcc.dg/vect/vect-over-widen-11.c: Likewise. + * gcc.dg/vect/vect-over-widen-12.c: Likewise. + * gcc.dg/vect/vect-over-widen-13.c: Likewise. + * gcc.dg/vect/vect-over-widen-14.c: Likewise. + * gcc.dg/vect/vect-over-widen-15.c: Likewise. + * gcc.dg/vect/vect-over-widen-16.c: Likewise. + * gcc.dg/vect/vect-over-widen-22.c: New test. + +2018-07-03 Richard Sandiford <richard.sandiford@arm.com> + * gcc.dg/vect/vect-widen-mult-u8-u32.c: Check specifically for a widen_mult pattern. * gcc.dg/vect/vect-over-widen-1.c: Update the scan tests for new diff --git a/gcc/testsuite/gcc.dg/vect/vect-over-widen-10.c b/gcc/testsuite/gcc.dg/vect/vect-over-widen-10.c index 394a5a1..f0140e4 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-over-widen-10.c +++ b/gcc/testsuite/gcc.dg/vect/vect-over-widen-10.c @@ -11,6 +11,7 @@ #include "vect-over-widen-9.c" +/* { dg-final { scan-tree-dump {Splitting statement} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* \+ } "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* >> 1} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* >> 2} "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-over-widen-11.c b/gcc/testsuite/gcc.dg/vect/vect-over-widen-11.c index 97ab57f..222d854 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-over-widen-11.c +++ b/gcc/testsuite/gcc.dg/vect/vect-over-widen-11.c @@ -55,6 +55,7 @@ main (void) return 0; } +/* { dg-final { scan-tree-dump {Splitting statement} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* \+ } "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* >> 1} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* >> 2} "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-over-widen-12.c b/gcc/testsuite/gcc.dg/vect/vect-over-widen-12.c index 0d5473e..ddb3bd8 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-over-widen-12.c +++ b/gcc/testsuite/gcc.dg/vect/vect-over-widen-12.c @@ -11,6 +11,7 @@ #include "vect-over-widen-11.c" +/* { dg-final { scan-tree-dump {Splitting statement} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* \+ } "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* >> 1} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* >> 2} "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-over-widen-13.c b/gcc/testsuite/gcc.dg/vect/vect-over-widen-13.c index b89ed8b..b25db88 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-over-widen-13.c +++ b/gcc/testsuite/gcc.dg/vect/vect-over-widen-13.c @@ -43,6 +43,7 @@ main (void) return 0; } +/* { dg-final { scan-tree-dump {Splitting statement} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* \+} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* / 2} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_cast_forwprop_pattern: detected:[^\n]* = \(signed char\)} "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-over-widen-14.c b/gcc/testsuite/gcc.dg/vect/vect-over-widen-14.c index 7b5ba23..dfa09f5 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-over-widen-14.c +++ b/gcc/testsuite/gcc.dg/vect/vect-over-widen-14.c @@ -11,6 +11,7 @@ #include "vect-over-widen-13.c" +/* { dg-final { scan-tree-dump {Splitting statement} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* \+} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* >> 1} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_cast_forwprop_pattern: detected:[^\n]* = \(unsigned char\)} "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-over-widen-15.c b/gcc/testsuite/gcc.dg/vect/vect-over-widen-15.c index e898e87..d31050e 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-over-widen-15.c +++ b/gcc/testsuite/gcc.dg/vect/vect-over-widen-15.c @@ -45,6 +45,7 @@ main (void) return 0; } +/* { dg-final { scan-tree-dump {Splitting statement} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* \+} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* / 2} "vect" } } */ /* { dg-final { scan-tree-dump-not {vect_recog_cast_forwprop_pattern: detected} "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-over-widen-16.c b/gcc/testsuite/gcc.dg/vect/vect-over-widen-16.c index 0429345..4584c58 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-over-widen-16.c +++ b/gcc/testsuite/gcc.dg/vect/vect-over-widen-16.c @@ -11,6 +11,7 @@ #include "vect-over-widen-15.c" +/* { dg-final { scan-tree-dump {Splitting statement} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* \+} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* >> 1} "vect" } } */ /* { dg-final { scan-tree-dump-not {vect_recog_cast_forwprop_pattern: detected} "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-over-widen-22.c b/gcc/testsuite/gcc.dg/vect/vect-over-widen-22.c new file mode 100644 index 0000000..187bdf1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-over-widen-22.c @@ -0,0 +1,53 @@ +/* { dg-require-effective-target vect_int } */ +/* { dg-require-effective-target vect_shift } */ +/* { dg-require-effective-target vect_pack_trunc } */ +/* { dg-require-effective-target vect_unpack } */ + +#include "tree-vect.h" + +#define N 111 + +/* The addition should be narrowed to short. */ + +void __attribute__ ((noipa)) +f (unsigned int *restrict a, unsigned int *restrict b, + unsigned short *restrict c, unsigned char *restrict d, unsigned int e) +{ + e &= 0xff; + for (__INTPTR_TYPE__ i = 0; i < N; ++i) + { + unsigned int xor = d[i] ^ e; + a[i] = c[i] | xor; + b[i] = xor; + } +} + +int +main (void) +{ + check_vect (); + + unsigned int a[N], b[N]; + unsigned short c[N]; + unsigned char d[N]; + for (int i = 0; i < N; ++i) + { + c[i] = i * 11; + d[i] = i * 2 + 3; + asm volatile ("" ::: "memory"); + } + f (a, b, c, d, 0x73); + for (int i = 0; i < N; ++i) + if (b[i] != ((i * 2 + 3) ^ 0x73) + || a[i] != ((i * 11) | b[i])) + __builtin_abort (); + + return 0; +} + +/* { dg-final { scan-tree-dump {Splitting pattern statement} "vect" } } */ +/* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* \^} "vect" } } */ +/* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* \|} "vect" } } */ +/* { dg-final { scan-tree-dump {demoting [^\n]* to [^\n]*char} "vect" } } */ +/* { dg-final { scan-tree-dump {demoting [^\n]* to [^\n]*short} "vect" } } */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loop" 1 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-over-widen-5.c b/gcc/testsuite/gcc.dg/vect/vect-over-widen-5.c index 56d2396..269df53 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-over-widen-5.c +++ b/gcc/testsuite/gcc.dg/vect/vect-over-widen-5.c @@ -44,6 +44,7 @@ main (void) return 0; } +/* { dg-final { scan-tree-dump {Splitting statement} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* \+ } "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* >> 1} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_cast_forwprop_pattern: detected:[^\n]* \(signed char\)} "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-over-widen-6.c b/gcc/testsuite/gcc.dg/vect/vect-over-widen-6.c index 9fe0e05..bda92c9 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-over-widen-6.c +++ b/gcc/testsuite/gcc.dg/vect/vect-over-widen-6.c @@ -9,6 +9,7 @@ #include "vect-over-widen-5.c" +/* { dg-final { scan-tree-dump {Splitting statement} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* \+ } "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* >> 1} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_cast_forwprop_pattern: detected:[^\n]* \(unsigned char\)} "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-over-widen-7.c b/gcc/testsuite/gcc.dg/vect/vect-over-widen-7.c index a8166b3..314a682 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-over-widen-7.c +++ b/gcc/testsuite/gcc.dg/vect/vect-over-widen-7.c @@ -46,6 +46,7 @@ main (void) return 0; } +/* { dg-final { scan-tree-dump {Splitting statement} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* \+ } "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* >> 2} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_cast_forwprop_pattern: detected:[^\n]* \(signed char\)} "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-over-widen-8.c b/gcc/testsuite/gcc.dg/vect/vect-over-widen-8.c index 238f577..553c071 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-over-widen-8.c +++ b/gcc/testsuite/gcc.dg/vect/vect-over-widen-8.c @@ -12,6 +12,7 @@ #include "vect-over-widen-7.c" +/* { dg-final { scan-tree-dump {Splitting statement} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* \+ } "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* >> 2} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_cast_forwprop_pattern: detected:[^\n]* \(unsigned char\)} "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-over-widen-9.c b/gcc/testsuite/gcc.dg/vect/vect-over-widen-9.c index a50f819..5baba09 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-over-widen-9.c +++ b/gcc/testsuite/gcc.dg/vect/vect-over-widen-9.c @@ -50,6 +50,7 @@ main (void) return 0; } +/* { dg-final { scan-tree-dump {Splitting statement} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* \+ } "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* >> 1} "vect" } } */ /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* >> 2} "vect" } } */ diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index 91076f4..a1649d8 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -634,6 +634,97 @@ vect_recog_temp_ssa_var (tree type, gimple *stmt) return make_temp_ssa_name (type, stmt, "patt"); } +/* STMT2_INFO describes a type conversion that could be split into STMT1 + followed by a version of STMT2_INFO that takes NEW_RHS as its first + input. Try to do this using pattern statements, returning true on + success. */ + +static bool +vect_split_statement (stmt_vec_info stmt2_info, tree new_rhs, + gimple *stmt1, tree vectype) +{ + if (is_pattern_stmt_p (stmt2_info)) + { + /* STMT2_INFO is part of a pattern. Get the statement to which + the pattern is attached. */ + stmt_vec_info orig_stmt2_info + = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (stmt2_info)); + vect_init_pattern_stmt (stmt1, orig_stmt2_info, vectype); + + if (dump_enabled_p ()) + { + dump_printf_loc (MSG_NOTE, vect_location, + "Splitting pattern statement: "); + dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt2_info->stmt, 0); + } + + /* Since STMT2_INFO is a pattern statement, we can change it + in-situ without worrying about changing the code for the + containing block. */ + gimple_assign_set_rhs1 (stmt2_info->stmt, new_rhs); + + if (dump_enabled_p ()) + { + dump_printf_loc (MSG_NOTE, vect_location, "into: "); + dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt1, 0); + dump_printf_loc (MSG_NOTE, vect_location, "and: "); + dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt2_info->stmt, 0); + } + + gimple_seq *def_seq = &STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt2_info); + if (STMT_VINFO_RELATED_STMT (orig_stmt2_info) == stmt2_info->stmt) + /* STMT2_INFO is the actual pattern statement. Add STMT1 + to the end of the definition sequence. */ + gimple_seq_add_stmt_without_update (def_seq, stmt1); + else + { + /* STMT2_INFO belongs to the definition sequence. Insert STMT1 + before it. */ + gimple_stmt_iterator gsi = gsi_for_stmt (stmt2_info->stmt, def_seq); + gsi_insert_before_without_update (&gsi, stmt1, GSI_SAME_STMT); + } + return true; + } + else + { + /* STMT2_INFO doesn't yet have a pattern. Try to create a + two-statement pattern now. */ + gcc_assert (!STMT_VINFO_RELATED_STMT (stmt2_info)); + tree lhs_type = TREE_TYPE (gimple_get_lhs (stmt2_info->stmt)); + tree lhs_vectype = get_vectype_for_scalar_type (lhs_type); + if (!lhs_vectype) + return false; + + if (dump_enabled_p ()) + { + dump_printf_loc (MSG_NOTE, vect_location, + "Splitting statement: "); + dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt2_info->stmt, 0); + } + + /* Add STMT1 as a singleton pattern definition sequence. */ + gimple_seq *def_seq = &STMT_VINFO_PATTERN_DEF_SEQ (stmt2_info); + vect_init_pattern_stmt (stmt1, stmt2_info, vectype); + gimple_seq_add_stmt_without_update (def_seq, stmt1); + + /* Build the second of the two pattern statements. */ + tree new_lhs = vect_recog_temp_ssa_var (lhs_type, NULL); + gassign *new_stmt2 = gimple_build_assign (new_lhs, NOP_EXPR, new_rhs); + vect_set_pattern_stmt (new_stmt2, stmt2_info, lhs_vectype); + + if (dump_enabled_p ()) + { + dump_printf_loc (MSG_NOTE, vect_location, + "into pattern statements: "); + dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt1, 0); + dump_printf_loc (MSG_NOTE, vect_location, "and: "); + dump_gimple_stmt (MSG_NOTE, TDF_SLIM, new_stmt2, 0); + } + + return true; + } +} + /* Convert UNPROM to TYPE and return the result, adding new statements to STMT_INFO's pattern definition statements if no better way is available. VECTYPE is the vector form of TYPE. */ @@ -662,6 +753,18 @@ vect_convert_input (stmt_vec_info stmt_info, tree type, tree new_op = vect_recog_temp_ssa_var (type, NULL); gassign *new_stmt = gimple_build_assign (new_op, NOP_EXPR, unprom->op); + /* If the operation is the input to a vectorizable cast, try splitting + that cast into two, taking the required result as a mid-way point. */ + if (unprom->caster) + { + tree lhs = gimple_get_lhs (unprom->caster->stmt); + if (TYPE_PRECISION (TREE_TYPE (lhs)) > TYPE_PRECISION (type) + && TYPE_PRECISION (type) > TYPE_PRECISION (unprom->type) + && (TYPE_UNSIGNED (unprom->type) || !TYPE_UNSIGNED (type)) + && vect_split_statement (unprom->caster, new_op, new_stmt, vectype)) + return new_op; + } + /* If OP is an external value, see if we can insert the new statement on an incoming edge. */ if (unprom->dt == vect_external_def) |