[PATCH] expand: Fix up IFN_ATOMIC_{BIT*,*CMP_0} expansion [PR105951]

Jakub Jelinek jakub@redhat.com
Wed Jun 15 09:16:25 GMT 2022


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



More information about the Gcc-patches mailing list