From: Kyrylo Tkachov <[email protected]>
The A - B -> A + (-B) rule uses negate_expr_p to decide whether B can be
negated cheaply. The predicate rejects non-wrapping integral vector
constants, even when every encoded element can be negated without overflow.
This leaves vector subtraction in a noncanonical form and can hide an
encodable constant from target expansion.
typedef int v4si __attribute__ ((vector_size (16)));
v4si
f (v4si x)
{
return x - (v4si) { -16711935, -16711935, -16711935, -16711935 };
}
aarch64 -O2 before:
f:
adrp x0, .LC0
ldr q31, [x0, #:lo12:.LC0]
sub v0.4s, v0.4s, v31.4s
ret
The function also needs a 16-byte constant in .rodata.
After:
f:
movi v31.8h, 0xff
add v0.4s, v0.4s, v31.4s
ret
Accept a non-stepped integral vector constant when every encoded element can
be negated without overflow. A stepped encoding can extrapolate an unencoded
signed minimum, so keep it in subtraction form. Unsigned and -fwrapv vectors
already wrap and do not need an element scan. Reject fixed-point vectors
before testing overflow wrapping. Keep a signed minimum element and an
overflow-sanitized subtraction.
The canonical form remains visible before dead-code elimination in one
existing forwprop dump. Adjust its addition count.
Bootstrapped and tested on aarch64-none-linux-gnu and x86_64-pc-linux-gnu.
Ok for trunk?
Thanks,
Kyrill
gcc/ChangeLog:
* match.pd (negate_expr_p): Handle non-wrapping integral vector
constants.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/forwprop-27.c: Adjust the expected addition count.
* gcc.dg/tree-ssa/vector-sub-const-1.c: New test.
* gcc.dg/tree-ssa/vector-sub-const-2.c: Likewise.
Signed-off-by: Kyrylo Tkachov <[email protected]>
---
gcc/match.pd | 28 ++++++++++--
gcc/testsuite/gcc.dg/tree-ssa/forwprop-27.c | 2 +-
.../gcc.dg/tree-ssa/vector-sub-const-1.c | 43 +++++++++++++++++++
.../gcc.dg/tree-ssa/vector-sub-const-2.c | 12 ++++++
4 files changed, 81 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vector-sub-const-1.c
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vector-sub-const-2.c
diff --git a/gcc/match.pd b/gcc/match.pd
index eae8717bcfe..2c88e56b366 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2428,11 +2428,33 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(match negate_expr_p
REAL_CST
(if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (t)))))
-/* VECTOR_CST handling of non-wrapping types would recurse in unsupported
- ways. */
+/* A non-stepped, non-wrapping integral vector constant can be negated when
+ none of its encoded elements is the minimum value. */
(match negate_expr_p
VECTOR_CST
- (if (FLOAT_TYPE_P (TREE_TYPE (type)) || TYPE_OVERFLOW_WRAPS (type))))
+ (with
+ {
+ tree etype = TREE_TYPE (type);
+ bool negatable = (FLOAT_TYPE_P (etype)
+ || (INTEGRAL_TYPE_P (etype)
+ && TYPE_OVERFLOW_WRAPS (type)));
+ if (!negatable
+ && INTEGRAL_TYPE_P (etype)
+ && !TYPE_OVERFLOW_SANITIZED (etype)
+ && !VECTOR_CST_STEPPED_P (t))
+ {
+ negatable = true;
+ for (unsigned int i = 0; i < vector_cst_encoded_nelts (t); ++i)
+ if (TREE_CODE (VECTOR_CST_ENCODED_ELT (t, i)) != INTEGER_CST
+ || !may_negate_without_overflow_p
+ (VECTOR_CST_ENCODED_ELT (t, i)))
+ {
+ negatable = false;
+ break;
+ }
+ }
+ }
+ (if (negatable))))
(match negate_expr_p
(minus @0 @1)
(if ((ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type))
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-27.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-27.c
index 6c71a4fc81c..29d39c67c79 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-27.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-27.c
@@ -33,7 +33,7 @@ void i (V *v1, V *v2){
*v2 = (c1-*v2)+c2;
}
-/* { dg-final { scan-tree-dump-times "\\\+" 1 "forwprop1"} } */
+/* { dg-final { scan-tree-dump-times "\\\+" 2 "forwprop1"} } */
/* { dg-final { scan-tree-dump "{ 0, 4 }" "forwprop1"} } */
/* { dg-final { scan-tree-dump "{ 37, -5 }" "forwprop1"} } */
/* { dg-final { scan-tree-dump "{ 27, 23 }" "forwprop1"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vector-sub-const-1.c b/gcc/testsuite/gcc.dg/tree-ssa/vector-sub-const-1.c
new file mode 100644
index 00000000000..56e1c146d70
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vector-sub-const-1.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-psabi -fdump-tree-forwprop1" } */
+
+typedef __INT32_TYPE__ v4si __attribute__ ((vector_size (16)));
+typedef __UINT32_TYPE__ v4ui __attribute__ ((vector_size (16)));
+
+v4si
+sub_splat (v4si x)
+{
+ return x - (v4si) { 1, 1, 1, 1 };
+}
+
+v4si
+sub_mixed (v4si x)
+{
+ return x - (v4si) { 1, -2, 3, -4 };
+}
+
+v4si
+sub_encodable (v4si x)
+{
+ return x - (v4si) { -16711935, -16711935, -16711935, -16711935 };
+}
+
+v4si
+keep_min (v4si x)
+{
+ return x - (v4si) { -__INT32_MAX__ - 1, 1, 1, 1 };
+}
+
+v4si
+keep_stepped_min (v4si x)
+{
+ return x - (v4si) ((v4ui) { 2147483644u, 2147483645u,
+ 2147483646u, 2147483647u }
+ + (v4ui) { 1, 1, 1, 1 });
+}
+
+/* { dg-final { scan-tree-dump-times " \\+ \\{ -1, -1, -1, -1 \\}" 1 "forwprop1" } } */
+/* { dg-final { scan-tree-dump-times " \\+ \\{ -1, 2, -3, 4 \\}" 1 "forwprop1" } } */
+/* { dg-final { scan-tree-dump-times " \\+ \\{ 16711935, 16711935, 16711935, 16711935 \\}" 1 "forwprop1" } } */
+/* { dg-final { scan-tree-dump-times " - \\{ -2147483648, 1, 1, 1 \\}" 1 "forwprop1" } } */
+/* { dg-final { scan-tree-dump-times " - \\{ 2147483645, 2147483646, 2147483647, -2147483648 \\}" 1 "forwprop1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vector-sub-const-2.c b/gcc/testsuite/gcc.dg/tree-ssa/vector-sub-const-2.c
new file mode 100644
index 00000000000..27de9e77be2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vector-sub-const-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-psabi -fsanitize=signed-integer-overflow -fdump-tree-forwprop1" } */
+
+typedef __INT32_TYPE__ v4si __attribute__ ((vector_size (16)));
+
+v4si
+f (v4si x)
+{
+ return x - (v4si) { 1, 1, 1, 1 };
+}
+
+/* { dg-final { scan-tree-dump-times "\\.UBSAN_CHECK_SUB" 1 "forwprop1" } } */
--
2.50.1 (Apple Git-155)
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.