Skip to content

Commit 6a27c43

Browse files
committed
expand: Fix up IFN_ATOMIC_{BIT*,*CMP_0} expansion [PR105951]
Both IFN_ATOMIC_BIT_TEST_AND_* and IFN_ATOMIC_*_FETCH_CMP_0 ifns are matched if their corresponding optab is implemented for the particular mode. The fact that those optabs are implemented doesn't guarantee they will succeed though, they can just FAIL in their expansion. The expansion in that case uses expand_atomic_fetch_op as fallback, but as has been reported and and can be reproduced on the testcases, even those can fail and we didn't have any fallback after that. For IFN_ATOMIC_BIT_TEST_AND_* we actually have such calls. One is done whenever we lost lhs of the ifn at some point in between matching it in tree-ssa-ccp.cc and expansion. The following patch for that case just falls through and expands as if there was a lhs, creates a temporary for it. For the other expand_atomic_fetch_op call in the same expander and for the only expand_atomic_fetch_op call in the other, this falls back the hard way, by constructing a CALL_EXPR to the call from which the ifn has been matched and expanding that. Either it is lucky and manages to expand inline, or it emits a libatomic API call. So that we don't have to rediscover which builtin function to call in the fallback, we record at tree-ssa-ccp.cc time gimple_call_fn (call) in an extra argument to the ifn. 2022-06-16 Jakub Jelinek <[email protected]> PR middle-end/105951 * tree-ssa-ccp.cc (optimize_atomic_bit_test_and, optimize_atomic_op_fetch_cmp_0): Remember gimple_call_fn (call) as last argument to the internal functions. * builtins.cc (expand_ifn_atomic_bit_test_and): Adjust for the extra call argument to ifns. If expand_atomic_fetch_op fails for the lhs == NULL_TREE case, fall through into the optab code with gen_reg_rtx (mode) as target. If second expand_atomic_fetch_op fails, construct a CALL_EXPR and expand that. (expand_ifn_atomic_op_fetch_cmp_0): Adjust for the extra call argument to ifns. If expand_atomic_fetch_op fails, construct a CALL_EXPR and expand that. * gcc.target/i386/pr105951-1.c: New test. * gcc.target/i386/pr105951-2.c: New test.
1 parent 8d1c6e7 commit 6a27c43

File tree

4 files changed

+64
-16
lines changed

4 files changed

+64
-16
lines changed

gcc/builtins.cc

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6224,7 +6224,7 @@ expand_ifn_atomic_bit_test_and (gcall *call)
62246224

62256225
gcc_assert (flag_inline_atomics);
62266226

6227-
if (gimple_call_num_args (call) == 4)
6227+
if (gimple_call_num_args (call) == 5)
62286228
model = get_memmodel (gimple_call_arg (call, 3));
62296229

62306230
rtx mem = get_builtin_sync_mem (ptr, mode);
@@ -6250,15 +6250,19 @@ expand_ifn_atomic_bit_test_and (gcall *call)
62506250

62516251
if (lhs == NULL_TREE)
62526252
{
6253-
val = expand_simple_binop (mode, ASHIFT, const1_rtx,
6254-
val, NULL_RTX, true, OPTAB_DIRECT);
6253+
rtx val2 = expand_simple_binop (mode, ASHIFT, const1_rtx,
6254+
val, NULL_RTX, true, OPTAB_DIRECT);
62556255
if (code == AND)
6256-
val = expand_simple_unop (mode, NOT, val, NULL_RTX, true);
6257-
expand_atomic_fetch_op (const0_rtx, mem, val, code, model, false);
6258-
return;
6256+
val2 = expand_simple_unop (mode, NOT, val2, NULL_RTX, true);
6257+
if (expand_atomic_fetch_op (const0_rtx, mem, val2, code, model, false))
6258+
return;
62596259
}
62606260

6261-
rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
6261+
rtx target;
6262+
if (lhs)
6263+
target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
6264+
else
6265+
target = gen_reg_rtx (mode);
62626266
enum insn_code icode = direct_optab_handler (optab, mode);
62636267
gcc_assert (icode != CODE_FOR_nothing);
62646268
create_output_operand (&ops[0], target, mode);
@@ -6277,6 +6281,22 @@ expand_ifn_atomic_bit_test_and (gcall *call)
62776281
val = expand_simple_unop (mode, NOT, val, NULL_RTX, true);
62786282
rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, val,
62796283
code, model, false);
6284+
if (!result)
6285+
{
6286+
bool is_atomic = gimple_call_num_args (call) == 5;
6287+
tree tcall = gimple_call_arg (call, 3 + is_atomic);
6288+
tree fndecl = gimple_call_addr_fndecl (tcall);
6289+
tree type = TREE_TYPE (TREE_TYPE (fndecl));
6290+
tree exp = build_call_nary (type, tcall, 2 + is_atomic, ptr,
6291+
make_tree (type, val),
6292+
is_atomic
6293+
? gimple_call_arg (call, 3)
6294+
: integer_zero_node);
6295+
result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX,
6296+
mode, !lhs);
6297+
}
6298+
if (!lhs)
6299+
return;
62806300
if (integer_onep (flag))
62816301
{
62826302
result = expand_simple_binop (mode, ASHIFTRT, result, bitval,
@@ -6308,7 +6328,7 @@ expand_ifn_atomic_op_fetch_cmp_0 (gcall *call)
63086328

63096329
gcc_assert (flag_inline_atomics);
63106330

6311-
if (gimple_call_num_args (call) == 4)
6331+
if (gimple_call_num_args (call) == 5)
63126332
model = get_memmodel (gimple_call_arg (call, 3));
63136333

63146334
rtx mem = get_builtin_sync_mem (ptr, mode);
@@ -6369,6 +6389,21 @@ expand_ifn_atomic_op_fetch_cmp_0 (gcall *call)
63696389

63706390
rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, op,
63716391
code, model, true);
6392+
if (!result)
6393+
{
6394+
bool is_atomic = gimple_call_num_args (call) == 5;
6395+
tree tcall = gimple_call_arg (call, 3 + is_atomic);
6396+
tree fndecl = gimple_call_addr_fndecl (tcall);
6397+
tree type = TREE_TYPE (TREE_TYPE (fndecl));
6398+
tree exp = build_call_nary (type, tcall,
6399+
2 + is_atomic, ptr, arg,
6400+
is_atomic
6401+
? gimple_call_arg (call, 3)
6402+
: integer_zero_node);
6403+
result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX,
6404+
mode, !lhs);
6405+
}
6406+
63726407
if (lhs)
63736408
{
63746409
result = emit_store_flag_force (target, comp, result, const0_rtx, mode,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/* PR middle-end/105951 */
2+
/* { dg-do compile { target ia32 } } */
3+
/* { dg-options "-O2 -march=i386" } */
4+
5+
#include "pr98737-2.c"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/* PR middle-end/105951 */
2+
/* { dg-do compile { target ia32 } } */
3+
/* { dg-options "-O2 -march=i386" } */
4+
5+
#include "pr98737-4.c"

gcc/tree-ssa-ccp.cc

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3789,11 +3789,12 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip,
37893789
tree new_lhs = make_ssa_name (TREE_TYPE (lhs));
37903790
tree flag = build_int_cst (TREE_TYPE (lhs), use_bool);
37913791
if (has_model_arg)
3792-
g = gimple_build_call_internal (fn, 4, gimple_call_arg (call, 0),
3793-
bit, flag, gimple_call_arg (call, 2));
3792+
g = gimple_build_call_internal (fn, 5, gimple_call_arg (call, 0),
3793+
bit, flag, gimple_call_arg (call, 2),
3794+
gimple_call_fn (call));
37943795
else
3795-
g = gimple_build_call_internal (fn, 3, gimple_call_arg (call, 0),
3796-
bit, flag);
3796+
g = gimple_build_call_internal (fn, 4, gimple_call_arg (call, 0),
3797+
bit, flag, gimple_call_fn (call));
37973798
gimple_call_set_lhs (g, new_lhs);
37983799
gimple_set_location (g, gimple_location (call));
37993800
gimple_move_vops (g, call);
@@ -4003,14 +4004,16 @@ optimize_atomic_op_fetch_cmp_0 (gimple_stmt_iterator *gsip,
40034004
gimple *g;
40044005
tree flag = build_int_cst (TREE_TYPE (lhs), encoded);
40054006
if (has_model_arg)
4006-
g = gimple_build_call_internal (fn, 4, flag,
4007+
g = gimple_build_call_internal (fn, 5, flag,
40074008
gimple_call_arg (call, 0),
40084009
gimple_call_arg (call, 1),
4009-
gimple_call_arg (call, 2));
4010+
gimple_call_arg (call, 2),
4011+
gimple_call_fn (call));
40104012
else
4011-
g = gimple_build_call_internal (fn, 3, flag,
4013+
g = gimple_build_call_internal (fn, 4, flag,
40124014
gimple_call_arg (call, 0),
4013-
gimple_call_arg (call, 1));
4015+
gimple_call_arg (call, 1),
4016+
gimple_call_fn (call));
40144017
gimple_call_set_lhs (g, new_lhs);
40154018
gimple_set_location (g, gimple_location (call));
40164019
gimple_move_vops (g, call);

0 commit comments

Comments
 (0)