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  <jakub@redhat.com>

	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.
This commit is contained in:
Jakub Jelinek 2025-10-09 18:06:39 +02:00 committed by Jakub Jelinek
parent 0558c6028e
commit 579de8f529
2 changed files with 38 additions and 1 deletions

View File

@ -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;

View File

@ -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 ();
}