aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/testsuite/ChangeLog17
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-over-widen-10.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-over-widen-11.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-over-widen-12.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-over-widen-13.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-over-widen-14.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-over-widen-15.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-over-widen-16.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-over-widen-22.c53
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-over-widen-5.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-over-widen-6.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-over-widen-7.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-over-widen-8.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-over-widen-9.c1
-rw-r--r--gcc/tree-vect-patterns.c103
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)