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

Reply via email to