On Wed, Jun 15, 2022 at 10:26:39AM +0200, Richard Biener wrote: > Ah, that might be a nice way to simplify the fallback indeed. > > > > The back-and-forth is a big ugly IMHO and it would suggest we can > > > always match to the IFN since we can fall back to the builtin > > > call as expansion...? > > > > We can, but if the optab isn't implemented, it won't improve the code in any > > way. So it would be wasted work. > > Indeed. So I guess OK with the suggested extra argument to the IFN.
Here is what I'll retest then: 2022-06-15 Jakub Jelinek <ja...@redhat.com> 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. --- gcc/tree-ssa-ccp.cc.jj 2022-05-23 10:59:06.200591718 +0200 +++ gcc/tree-ssa-ccp.cc 2022-06-15 10:51:43.956039519 +0200 @@ -3789,11 +3789,12 @@ optimize_atomic_bit_test_and (gimple_stm tree new_lhs = make_ssa_name (TREE_TYPE (lhs)); tree flag = build_int_cst (TREE_TYPE (lhs), use_bool); if (has_model_arg) - g = gimple_build_call_internal (fn, 4, gimple_call_arg (call, 0), - bit, flag, gimple_call_arg (call, 2)); + g = gimple_build_call_internal (fn, 5, gimple_call_arg (call, 0), + bit, flag, gimple_call_arg (call, 2), + gimple_call_fn (call)); else - g = gimple_build_call_internal (fn, 3, gimple_call_arg (call, 0), - bit, flag); + g = gimple_build_call_internal (fn, 4, gimple_call_arg (call, 0), + bit, flag, gimple_call_fn (call)); gimple_call_set_lhs (g, new_lhs); gimple_set_location (g, gimple_location (call)); gimple_move_vops (g, call); @@ -4003,14 +4004,16 @@ optimize_atomic_op_fetch_cmp_0 (gimple_s gimple *g; tree flag = build_int_cst (TREE_TYPE (lhs), encoded); if (has_model_arg) - g = gimple_build_call_internal (fn, 4, flag, + g = gimple_build_call_internal (fn, 5, flag, gimple_call_arg (call, 0), gimple_call_arg (call, 1), - gimple_call_arg (call, 2)); + gimple_call_arg (call, 2), + gimple_call_fn (call)); else - g = gimple_build_call_internal (fn, 3, flag, + g = gimple_build_call_internal (fn, 4, flag, gimple_call_arg (call, 0), - gimple_call_arg (call, 1)); + gimple_call_arg (call, 1), + gimple_call_fn (call)); gimple_call_set_lhs (g, new_lhs); gimple_set_location (g, gimple_location (call)); gimple_move_vops (g, call); --- gcc/builtins.cc.jj 2022-06-15 10:43:34.442073272 +0200 +++ gcc/builtins.cc 2022-06-15 11:12:20.865321490 +0200 @@ -6224,7 +6224,7 @@ expand_ifn_atomic_bit_test_and (gcall *c gcc_assert (flag_inline_atomics); - if (gimple_call_num_args (call) == 4) + if (gimple_call_num_args (call) == 5) model = get_memmodel (gimple_call_arg (call, 3)); rtx mem = get_builtin_sync_mem (ptr, mode); @@ -6250,15 +6250,19 @@ expand_ifn_atomic_bit_test_and (gcall *c if (lhs == NULL_TREE) { - val = expand_simple_binop (mode, ASHIFT, const1_rtx, - val, NULL_RTX, true, OPTAB_DIRECT); + rtx val2 = expand_simple_binop (mode, ASHIFT, const1_rtx, + val, NULL_RTX, true, OPTAB_DIRECT); if (code == AND) - val = expand_simple_unop (mode, NOT, val, NULL_RTX, true); - expand_atomic_fetch_op (const0_rtx, mem, val, code, model, false); - return; + val2 = expand_simple_unop (mode, NOT, val2, NULL_RTX, true); + if (expand_atomic_fetch_op (const0_rtx, mem, val2, code, model, false)) + return; } - rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE); + rtx target; + if (lhs) + target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE); + else + target = gen_reg_rtx (mode); enum insn_code icode = direct_optab_handler (optab, mode); gcc_assert (icode != CODE_FOR_nothing); create_output_operand (&ops[0], target, mode); @@ -6277,6 +6281,22 @@ expand_ifn_atomic_bit_test_and (gcall *c val = expand_simple_unop (mode, NOT, val, NULL_RTX, true); rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, val, code, model, false); + if (!result) + { + bool is_atomic = gimple_call_num_args (call) == 5; + tree tcall = gimple_call_arg (call, 3 + is_atomic); + tree fndecl = gimple_call_addr_fndecl (tcall); + tree type = TREE_TYPE (TREE_TYPE (fndecl)); + tree exp = build_call_nary (type, tcall, 2 + is_atomic, ptr, + make_tree (type, val), + is_atomic + ? gimple_call_arg (call, 3) + : integer_zero_node); + result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX, + mode, !lhs); + } + if (!lhs) + return; if (integer_onep (flag)) { result = expand_simple_binop (mode, ASHIFTRT, result, bitval, @@ -6308,7 +6328,7 @@ expand_ifn_atomic_op_fetch_cmp_0 (gcall gcc_assert (flag_inline_atomics); - if (gimple_call_num_args (call) == 4) + if (gimple_call_num_args (call) == 5) model = get_memmodel (gimple_call_arg (call, 3)); rtx mem = get_builtin_sync_mem (ptr, mode); @@ -6369,6 +6389,21 @@ expand_ifn_atomic_op_fetch_cmp_0 (gcall rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, op, code, model, true); + if (!result) + { + bool is_atomic = gimple_call_num_args (call) == 5; + tree tcall = gimple_call_arg (call, 3 + is_atomic); + tree fndecl = gimple_call_addr_fndecl (tcall); + tree type = TREE_TYPE (TREE_TYPE (fndecl)); + tree exp = build_call_nary (type, tcall, + 2 + is_atomic, ptr, arg, + is_atomic + ? gimple_call_arg (call, 3) + : integer_zero_node); + result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX, + mode, !lhs); + } + if (lhs) { result = emit_store_flag_force (target, comp, result, const0_rtx, mode, --- gcc/testsuite/gcc.target/i386/pr105951-1.c.jj 2022-06-15 10:46:58.953970222 +0200 +++ gcc/testsuite/gcc.target/i386/pr105951-1.c 2022-06-15 10:46:58.953970222 +0200 @@ -0,0 +1,5 @@ +/* PR middle-end/105951 */ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2 -march=i386" } */ + +#include "pr98737-2.c" --- gcc/testsuite/gcc.target/i386/pr105951-2.c.jj 2022-06-15 10:46:58.953970222 +0200 +++ gcc/testsuite/gcc.target/i386/pr105951-2.c 2022-06-15 10:46:58.953970222 +0200 @@ -0,0 +1,5 @@ +/* PR middle-end/105951 */ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2 -march=i386" } */ + +#include "pr98737-4.c" Jakub