Hi, On Mon, Sep 21 2026, Josef Melcr wrote: > 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.
While I admit I have only superficially glanced over these, I believe they are OK (or we'll fix them up later). Nevertheless, please duplicate at least a few more basic ones of these into LTO tests in g++.dg/lto/ so that we also exercise streaming and the relevant code-paths in WPA mode. And then squash this into the final commit enabling IPA-SRA and IPA-CP of assumes. Thanks! Martin > > 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
