https://gcc.gnu.org/g:b77ea2ba9799d74535ee111e04068a2a6758b9fb

commit r14-12093-gb77ea2ba9799d74535ee111e04068a2a6758b9fb
Author: Jakub Jelinek <[email protected]>
Date:   Wed Oct 8 09:58:41 2025 +0200

    gimplify: Fix up __builtin_c[lt]zg gimplification [PR122188]
    
    The following testcase ICEs during gimplification.
    The problem is that save_expr sometimes doesn't create a SAVE_EXPR but
    returns the original complex tree (COND_EXPR) and the code then uses that
    tree in 2 different spots without unsharing.  As this is done during
    gimplification it wasn't unshared when whole body is unshared and because
    gimplification is destructive, the first time we gimplify it we destruct it
    and second time we try to gimplify it we ICE on it.
    Now, we could replace one a use with unshare_expr (a), but because this
    is a gimplification hook, I think easier than trying to create a save_expr
    is just gimplify the argument, then we know it is is_gimple_val and so
    something without side-effects and can safely use it twice.  That argument
    would be the first thing to gimplify after return GS_OK anyway, so it
    doesn't change argument sequencing etc.
    
    2025-10-08  Jakub Jelinek  <[email protected]>
    
            PR c/122188
            * c-gimplify.cc (c_gimplify_expr): Gimplify CALL_EXPR_ARG (*expr_p, 
0)
            instead of calling save_expr on it.
    
            * c-c++-common/pr122188.c: New test.
    
    (cherry picked from commit bb22f7d4d63446c9095db32ca013a9b2182df7d9)

Diff:
---
 gcc/c-family/c-gimplify.cc            |  5 ++++-
 gcc/testsuite/c-c++-common/pr122188.c | 15 +++++++++++++++
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/gcc/c-family/c-gimplify.cc b/gcc/c-family/c-gimplify.cc
index 3f8ba37b863b..58110568e6f8 100644
--- a/gcc/c-family/c-gimplify.cc
+++ b/gcc/c-family/c-gimplify.cc
@@ -908,7 +908,10 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p 
ATTRIBUTE_UNUSED,
            && call_expr_nargs (*expr_p) == 2
            && TREE_CODE (CALL_EXPR_ARG (*expr_p, 1)) != INTEGER_CST)
          {
-           tree a = save_expr (CALL_EXPR_ARG (*expr_p, 0));
+           tree a = CALL_EXPR_ARG (*expr_p, 0);
+           if (gimplify_expr (&a, 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,
diff --git a/gcc/testsuite/c-c++-common/pr122188.c 
b/gcc/testsuite/c-c++-common/pr122188.c
new file mode 100644
index 000000000000..8c3fa1c30e55
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr122188.c
@@ -0,0 +1,15 @@
+/* PR c/122188 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int
+foo (const unsigned x, int y)
+{
+  return __builtin_ctzg (x ? x : 4081577U, y);
+}
+
+int
+bar (const unsigned x, int y)
+{
+  return __builtin_clzg (x ? x : 4081577U, y);
+}

Reply via email to