https://gcc.gnu.org/g:579de8f5295b05573d05f6e4102f1428f35c9f17

commit r16-4331-g579de8f5295b05573d05f6e4102f1428f35c9f17
Author: Jakub Jelinek <[email protected]>
Date:   Thu Oct 9 18:06:39 2025 +0200

    gimplify: Fix up side-effect handling in 2nd __builtin_c[lt]zg argument 
[PR122188]
    
    The patch from yesterday made me think about side-effects in the second
    argument of __builtin_c[lt]zg.  When we change
    __builtin_c[lt]zg (x, y)
    when y is not INTEGER_CST into
    x ? __builtin_c[lt]zg (x) : y
    with evaluating x only once, we omit the side-effects in y unless x is not
    0.  That looks undesirable, we should evaluate side-effects in y
    unconditionally.
    
    2025-10-09  Jakub Jelinek  <[email protected]>
    
            PR c/122188
            * c-gimplify.cc (c_gimplify_expr): Also gimplify the second operand
            before the COND_EXPR and use in COND_EXPR result of gimplification.
    
            * gcc.dg/torture/pr122188.c: New test.

Diff:
---
 gcc/c-family/c-gimplify.cc              |  6 +++++-
 gcc/testsuite/gcc.dg/torture/pr122188.c | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/gcc/c-family/c-gimplify.cc b/gcc/c-family/c-gimplify.cc
index 6fcd45830562..2249c101cf56 100644
--- a/gcc/c-family/c-gimplify.cc
+++ b/gcc/c-family/c-gimplify.cc
@@ -1040,6 +1040,10 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p 
ATTRIBUTE_UNUSED,
            if (gimplify_expr (&a, pre_p, post_p, is_gimple_val, fb_rvalue)
                == GS_ERROR)
              return GS_ERROR;
+           tree b = CALL_EXPR_ARG (*expr_p, 1);
+           if (gimplify_expr (&b, pre_p, post_p, is_gimple_val, fb_rvalue)
+               == GS_ERROR)
+             return GS_ERROR;
            tree c = build_call_expr_loc (EXPR_LOCATION (*expr_p),
                                          fndecl, 1, a);
            *expr_p = build3_loc (EXPR_LOCATION (*expr_p), COND_EXPR,
@@ -1047,7 +1051,7 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p 
ATTRIBUTE_UNUSED,
                                  build2_loc (EXPR_LOCATION (*expr_p),
                                              NE_EXPR, boolean_type_node, a,
                                              build_zero_cst (TREE_TYPE (a))),
-                                 c, CALL_EXPR_ARG (*expr_p, 1));
+                                 c, b);
            return GS_OK;
          }
        break;
diff --git a/gcc/testsuite/gcc.dg/torture/pr122188.c 
b/gcc/testsuite/gcc.dg/torture/pr122188.c
new file mode 100644
index 000000000000..2c549630f9de
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr122188.c
@@ -0,0 +1,33 @@
+/* PR c/122188 */
+/* { dg-do run } */
+
+int
+foo (unsigned x, int y)
+{
+  unsigned a = x;
+  int b = y;
+  int ret = __builtin_ctzg (x++, y++);
+  if (x != a + 1 || y != b + 1)
+    __builtin_abort ();
+  return ret;
+}
+
+int
+bar (unsigned x, int y)
+{
+  unsigned a = x;
+  int b = y;
+  int ret = __builtin_clzg (x++, y++);
+  if (x != a + 1 || y != b + 1)
+    __builtin_abort ();
+  return ret;
+}
+
+int
+main ()
+{
+  if (foo (0, 42) != 42 || foo (1, 5) != 0 || foo (4, 17) != 2)
+    __builtin_abort ();
+  if (bar (0, 42) != 42 || bar (~0U, 5) != 0 || bar (~0U >> 4, 17) != 4)
+    __builtin_abort ();
+}

Reply via email to