The final patch of this series adds testcases for this new feature. It
demonstrates some of the capabilities of assumes while covering most of
the code added. The ipa-icf bug does not have a testcase here, because
it's already covered by the existing attr-assume testcases.
gcc/testsuite/ChangeLog:
* g++.dg/ipa/ipa-cp-assume-2.C: New test.
* g++.dg/ipa/ipa-cp-assume-3.C: New test.
* g++.dg/ipa/ipa-cp-assume.C: New test.
* g++.dg/ipa/ipa-sra-assume-2.C: New test.
* g++.dg/ipa/ipa-sra-assume-3.C: New test.
* g++.dg/ipa/ipa-sra-assume.C: New test.
* g++.dg/lto/ipa-cp-assume_0.C: New test.
* g++.dg/lto/ipa-cp-assume_1.C: New test.
* g++.dg/lto/ipa-sra-assume_0.C: New test.
* g++.dg/lto/ipa-sra-assume_1.C: New test.
Signed-off-by: Josef Melcr <[email protected]>
---
gcc/testsuite/g++.dg/ipa/ipa-cp-assume-2.C | 40 ++++++++++++++++
gcc/testsuite/g++.dg/ipa/ipa-cp-assume-3.C | 51 +++++++++++++++++++++
gcc/testsuite/g++.dg/ipa/ipa-cp-assume.C | 26 +++++++++++
gcc/testsuite/g++.dg/ipa/ipa-sra-assume-2.C | 33 +++++++++++++
gcc/testsuite/g++.dg/ipa/ipa-sra-assume-3.C | 34 ++++++++++++++
gcc/testsuite/g++.dg/ipa/ipa-sra-assume.C | 37 +++++++++++++++
gcc/testsuite/g++.dg/lto/ipa-cp-assume_0.C | 27 +++++++++++
gcc/testsuite/g++.dg/lto/ipa-cp-assume_1.C | 13 ++++++
gcc/testsuite/g++.dg/lto/ipa-sra-assume_0.C | 28 +++++++++++
gcc/testsuite/g++.dg/lto/ipa-sra-assume_1.C | 11 +++++
10 files changed, 300 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/ipa/ipa-cp-assume-2.C
create mode 100644 gcc/testsuite/g++.dg/ipa/ipa-cp-assume-3.C
create mode 100644 gcc/testsuite/g++.dg/ipa/ipa-cp-assume.C
create mode 100644 gcc/testsuite/g++.dg/ipa/ipa-sra-assume-2.C
create mode 100644 gcc/testsuite/g++.dg/ipa/ipa-sra-assume-3.C
create mode 100644 gcc/testsuite/g++.dg/ipa/ipa-sra-assume.C
create mode 100644 gcc/testsuite/g++.dg/lto/ipa-cp-assume_0.C
create mode 100644 gcc/testsuite/g++.dg/lto/ipa-cp-assume_1.C
create mode 100644 gcc/testsuite/g++.dg/lto/ipa-sra-assume_0.C
create mode 100644 gcc/testsuite/g++.dg/lto/ipa-sra-assume_1.C
diff --git a/gcc/testsuite/g++.dg/ipa/ipa-cp-assume-2.C
b/gcc/testsuite/g++.dg/ipa/ipa-cp-assume-2.C
new file mode 100644
index 00000000000..4c9a9ea216f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/ipa-cp-assume-2.C
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-ipa-cp-details -fdump-tree-optimized" } */
+
+/* Should propagate in chain baz -> foo -> assume and fold body of foo
+ accordingly. Works because bar can be inlined (otherwise we can't derive
the
+ value range for x). */
+
+void do_something ();
+
+inline bool
+bar (int x, int y)
+{
+ return x < y;
+}
+
+static bool __attribute__ ((noinline))
+foo (int x, int a)
+{
+ [[assume (bar (x, a))]];
+ bool ret = x < 42;
+
+ if (!__builtin_constant_p (ret))
+ __builtin_abort ();
+
+ return ret;
+}
+
+void
+baz (int x)
+{
+ bool should_do_something = false;
+ for (int i = 0; i < 1000000; i++)
+ should_do_something = foo (x, 42);
+
+ if (should_do_something)
+ do_something ();
+}
+
+/* { dg-final { scan-ipa-dump-times "replacing param #1 a with const 42" 2
"cp" } } */
+/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
diff --git a/gcc/testsuite/g++.dg/ipa/ipa-cp-assume-3.C
b/gcc/testsuite/g++.dg/ipa/ipa-cp-assume-3.C
new file mode 100644
index 00000000000..4b79480b4f3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/ipa-cp-assume-3.C
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-ipa-cp-details -fdump-ipa-sra-details
-fdump-tree-optimized" } */
+
+/* Should propagate baz -> foo -> assume, split the parameter, derive the range
+ for s->x and fold foo accordingly. */
+
+void something ();
+
+struct S
+{
+ int x, y;
+};
+
+inline bool
+bar (int x, int y)
+{
+ return x < y;
+}
+
+static bool __attribute__ ((noinline))
+foo (struct S *s)
+{
+ [[assume (bar (s->x, s->y))]];
+ bool ret = s->x < 42;
+ bool ahoj = s->x < s->y;
+
+ if (!__builtin_constant_p (ret))
+ __builtin_abort ();
+
+ if (!__builtin_constant_p (ahoj))
+ __builtin_abort ();
+
+ return ret;
+}
+
+void
+baz (int x)
+{
+ struct S s;
+ s.x = x;
+ s.y = 42;
+ bool shouldnt_do_something = foo (&s);
+
+ if (!shouldnt_do_something)
+ something ();
+}
+
+/* { dg-final { scan-ipa-dump "Aggregate replacements: 0\\\[4]=42" "cp" } } */
+/* { dg-final { scan-ipa-dump ".*assume.*constprop.* Will split parameter 0"
"sra" } } */
+/* { dg-final { scan-ipa-dump "assume.*constprop\\.isra" "sra" } } */
+/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
diff --git a/gcc/testsuite/g++.dg/ipa/ipa-cp-assume.C
b/gcc/testsuite/g++.dg/ipa/ipa-cp-assume.C
new file mode 100644
index 00000000000..6eeebd4ad5c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/ipa-cp-assume.C
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-ipa-cp-details -fdump-tree-optimized" } */
+
+/* Should propagate 'a' into the assume body and fold foo. */
+
+inline bool
+bar (int x, int y)
+{
+ return x < y;
+}
+
+bool
+foo (int x)
+{
+ int a = 42;
+ [[assume (bar (x, a))]];
+ bool ret = x < 42;
+
+ if (!__builtin_constant_p (ret))
+ __builtin_abort ();
+
+ return ret;
+}
+
+/* { dg-final { scan-ipa-dump "replacing param #1 a with const 42" "cp" } } */
+/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
diff --git a/gcc/testsuite/g++.dg/ipa/ipa-sra-assume-2.C
b/gcc/testsuite/g++.dg/ipa/ipa-sra-assume-2.C
new file mode 100644
index 00000000000..009b315ac42
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/ipa-sra-assume-2.C
@@ -0,0 +1,33 @@
+/* Test that the assume can be copied before creating the edges. */
+
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+struct S
+{
+ int x, y;
+};
+
+inline bool
+baz (S x)
+{
+ return x.x < 42;
+}
+
+inline bool
+qux (S x, int h)
+{
+ [[assume (baz (x))]];
+ return x.x < 42 && x.y > 52 && h < 50;
+}
+
+void
+corge (S x, S y, S z, bool *p)
+{
+ for (int i = 0; i < x.x + x.y; i++)
+ {
+ p[0] = qux (x, 41);
+ p[1] = qux (y, 60);
+ p[2] = qux (z, 20);
+ }
+}
diff --git a/gcc/testsuite/g++.dg/ipa/ipa-sra-assume-3.C
b/gcc/testsuite/g++.dg/ipa/ipa-sra-assume-3.C
new file mode 100644
index 00000000000..fd15c957794
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/ipa-sra-assume-3.C
@@ -0,0 +1,34 @@
+/* Test that the assume can be copied after creating the edges. */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-early-inlining" } */
+
+struct S
+{
+ int x, y;
+};
+
+inline bool
+baz (S x)
+{
+ return x.x < 42;
+}
+
+[[gnu::always_inline]]
+inline bool
+qux (S x, int h)
+{
+ [[assume (baz (x))]];
+ return x.x < 42 && x.y > 52 && h < 50;
+}
+
+void
+corge (S x, S y, S z, bool *p)
+{
+ for (int i = 0; i < x.x + x.y; i++)
+ {
+ p[0] = qux (x, 41);
+ p[1] = qux (y, 60);
+ p[2] = qux (z, 20);
+ }
+}
diff --git a/gcc/testsuite/g++.dg/ipa/ipa-sra-assume.C
b/gcc/testsuite/g++.dg/ipa/ipa-sra-assume.C
new file mode 100644
index 00000000000..91b6366eb6a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/ipa-sra-assume.C
@@ -0,0 +1,37 @@
+/* Test that ipa-sra can work with .ASSUME outlined bodies. */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -fipa-sra -fdump-ipa-sra-details -fdump-tree-optimized" }
*/
+
+struct S
+{
+ bool x;
+ int y;
+};
+
+void
+split_struct (struct S s)
+{
+ [[assume (!s.x)]];
+ if (s.x)
+ __builtin_abort ();
+}
+
+void
+remove_ptr (bool *x)
+{
+ [[assume (!*x)]];
+ if (*x)
+ __builtin_abort ();
+}
+
+void
+two_values (struct S s)
+{
+ [[assume (s.y == 3 || s.y == 4)]];
+ if (s.y == 5)
+ __builtin_abort ();
+}
+
+/* { dg-final { scan-ipa-dump-times "Will split parameter 0" 3 "sra" } } */
+/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
diff --git a/gcc/testsuite/g++.dg/lto/ipa-cp-assume_0.C
b/gcc/testsuite/g++.dg/lto/ipa-cp-assume_0.C
new file mode 100644
index 00000000000..3f69250f33b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/ipa-cp-assume_0.C
@@ -0,0 +1,27 @@
+/* { dg-lto-options {{ -O3 -flto -fdump-tree-optimized }} } */
+/* { dg-lto-do link } */
+
+/* The point of this test is to propagate the constant into the assume body in
+ the other file, infer the value range for 'x', evaluate bar to 0, meaning
+ that the loop will never run and the abort would never be executed. */
+
+int bar (int, int);
+
+void
+foo (int x, int y)
+{
+ int c = bar (x, y);
+ for (int i = 0; i < c; i++)
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ int x;
+ __builtin_scanf ("%d", &x);
+ foo (x, 67);
+ return 0;
+}
+
+/* { dg-final { scan-ltrans-tree-dump-not "__builtin_abort" "optimized" } } */
diff --git a/gcc/testsuite/g++.dg/lto/ipa-cp-assume_1.C
b/gcc/testsuite/g++.dg/lto/ipa-cp-assume_1.C
new file mode 100644
index 00000000000..4ac52422d37
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/ipa-cp-assume_1.C
@@ -0,0 +1,13 @@
+inline bool
+baz (int x, int y)
+{
+ return x < y;
+}
+
+int
+bar (int x, int y)
+{
+ [[assume (baz (x, y))]];
+ __builtin_printf ("%d %d", x, y);
+ return x > y;
+}
diff --git a/gcc/testsuite/g++.dg/lto/ipa-sra-assume_0.C
b/gcc/testsuite/g++.dg/lto/ipa-sra-assume_0.C
new file mode 100644
index 00000000000..c4de5f86d3c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/ipa-sra-assume_0.C
@@ -0,0 +1,28 @@
+/* { dg-lto-options {{ -O3 -flto -fdump-tree-optimized }} } */
+/* { dg-lto-do link } */
+
+struct S
+{
+ int x;
+};
+
+int bar (struct S);
+
+void
+foo (struct S s)
+{
+ int c = bar (s);
+ for (int i = 0; i < c; i++)
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ int x;
+ __builtin_scanf ("%d", &x);
+ foo ({x});
+ return 0;
+}
+
+/* { dg-final { scan-ltrans-tree-dump-not "__builtin_abort" "optimized" } } */
diff --git a/gcc/testsuite/g++.dg/lto/ipa-sra-assume_1.C
b/gcc/testsuite/g++.dg/lto/ipa-sra-assume_1.C
new file mode 100644
index 00000000000..a33ed888a32
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/ipa-sra-assume_1.C
@@ -0,0 +1,11 @@
+struct S
+{
+ int x;
+};
+
+int
+bar (struct S s)
+{
+ [[assume (s.x < 0)]];
+ return s.x;
+}
--
2.55.0