While working on a different patch, Sandra found out that
due to tree sharing, the user condition in a context
selector was only evaluated once - which is bad if it is
dynamic (here: global variable) that can be changed.

The included testcase is a slightly enhanced version of
hers, attached to the PR.

Committed to mainline as r16-3946-g97c1d2fa97afc5

I think this is a candidate for GCC 15 backporting
due to the badness vs. change size/risk

[As dynamic selectors are only supported since
GCC 15 [this function is new since r15-6895-g1294b819e1207c]),
it is strictly GCC 15.]

Thanks for the testcase and debugging Sandra!

Tobias
commit 97c1d2fa97afc59b02d2894b88069136145603e2
Author: Tobias Burnus <[email protected]>
Date:   Thu Sep 18 11:07:50 2025 +0200

    OpenMP: Unshare expr in context-selector condition [PR121922]
    
    As the testcase shows, a missing unshare_expr caused that the condition
    was only evaluated once instead of every time when a 'declare variant'
    was resolved.
    
            PR middle-end/121922
    
    gcc/ChangeLog:
    
            * omp-general.cc (omp_dynamic_cond): Use 'unshare_expr' for
            the user condition.
    
    libgomp/ChangeLog:
    
            * testsuite/libgomp.c-c++-common/declare-variant-1.c: New test.
    
    Co-authored-by: Sandra Loosemore <[email protected]>
---
 gcc/omp-general.cc                                 |  2 +-
 .../libgomp.c-c++-common/declare-variant-1.c       | 40 ++++++++++++++++++++++
 2 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc
index c799b8936f9..973b246cfdb 100644
--- a/gcc/omp-general.cc
+++ b/gcc/omp-general.cc
@@ -2733,7 +2733,7 @@ omp_dynamic_cond (tree ctx, tree supercontext)
 
       /* The user condition is not dynamic if it is constant.  */
       if (!tree_fits_shwi_p (expr))
-	user_cond = expr;
+	user_cond = unshare_expr (expr);
     }
 
   /* Build the "target_device" part of the dynamic selector.  In the
diff --git a/libgomp/testsuite/libgomp.c-c++-common/declare-variant-1.c b/libgomp/testsuite/libgomp.c-c++-common/declare-variant-1.c
new file mode 100644
index 00000000000..b6fc40ed46d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/declare-variant-1.c
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fdump-tree-gimple" } */
+
+/* PR middle-end/121922  */
+
+/* Failed to re-check the global flag due to tree sharing.  */
+
+extern int flag;
+int flag = 0;
+
+int
+test_with_flag ()
+{
+  return flag;
+}
+
+#pragma omp declare variant (test_with_flag) match (user={condition(score(10): flag > 1)})
+int
+test ()
+{
+  return 0;
+}
+
+void
+doit ()
+{
+  flag = 0;
+  if (test () != 0) __builtin_abort ();
+  flag = 1;
+  if (test () != 0) __builtin_abort ();
+  flag = 42;
+  if (test () != 42) __builtin_abort ();
+}
+
+int main ()
+{
+  doit ();
+}
+
+/* { dg-final { scan-tree-dump-times "flag\\.\[^=\]*= flag;\[\n\r\]+ *if \\(flag\\.\[^>\]*> 1\\)" 3 "gimple" } } */

Reply via email to