Hi! 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.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk and later backports? 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. --- gcc/c-family/c-gimplify.cc.jj 2025-08-15 17:41:34.401721395 +0200 +++ gcc/c-family/c-gimplify.cc 2025-10-07 18:24:14.611565348 +0200 @@ -1036,7 +1036,10 @@ c_gimplify_expr (tree *expr_p, gimple_se && 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, --- gcc/testsuite/c-c++-common/pr122188.c.jj 2025-10-07 18:27:53.928516188 +0200 +++ gcc/testsuite/c-c++-common/pr122188.c 2025-10-07 18:27:37.355746617 +0200 @@ -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); +} Jakub
