public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 1/2] Factor out common internal-fn idiom
@ 2022-06-10  9:13 Richard Sandiford
  2022-06-12 18:05 ` Jeff Law
  0 siblings, 1 reply; 2+ messages in thread
From: Richard Sandiford @ 2022-06-10  9:13 UTC (permalink / raw)
  To: gcc-patches

internal-fn.c has quite a few functions that simply map the result
of the call to an instruction's output operand (if any) and map
each argument to an instruction's input operand, in order.
This patch adds a single function for doing that.  It's really
just a generalisation of expand_direct_optab_fn, but with the
output operand being optional.

Unfortunately, it isn't possible to do this for vcond_mask
because the internal function has a different argument order
from the optab.

Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?

Richard


gcc/
	* internal-fn.cc (expand_fn_using_insn): New function,
	split out and adapted from...
	(expand_direct_optab_fn): ...here.
	(expand_GOMP_SIMT_ENTER_ALLOC): Use it.
	(expand_GOMP_SIMT_EXIT): Likewise.
	(expand_GOMP_SIMT_LANE): Likewise.
	(expand_GOMP_SIMT_LAST_LANE): Likewise.
	(expand_GOMP_SIMT_ORDERED_PRED): Likewise.
	(expand_GOMP_SIMT_VOTE_ANY): Likewise.
	(expand_GOMP_SIMT_XCHG_BFLY): Likewise.
	(expand_GOMP_SIMT_XCHG_IDX): Likewise.
---
 gcc/internal-fn.cc | 243 +++++++++++++++++----------------------------
 1 file changed, 89 insertions(+), 154 deletions(-)

diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc
index 8b1733e20c4..ab2b1baa893 100644
--- a/gcc/internal-fn.cc
+++ b/gcc/internal-fn.cc
@@ -140,6 +140,86 @@ const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
   not_direct
 };
 
+/* Expand STMT using instruction ICODE.  The instruction has NOUTPUTS
+   output operands and NINPUTS input operands, where NOUTPUTS is either
+   0 or 1.  The output operand (if any) comes first, followed by the
+   NINPUTS input operands.  */
+
+static void
+expand_fn_using_insn (gcall *stmt, insn_code icode, unsigned int noutputs,
+		      unsigned int ninputs)
+{
+  gcc_assert (icode != CODE_FOR_nothing);
+
+  expand_operand *ops = XALLOCAVEC (expand_operand, noutputs + ninputs);
+  unsigned int opno = 0;
+  rtx lhs_rtx = NULL_RTX;
+  tree lhs = gimple_call_lhs (stmt);
+
+  if (noutputs)
+    {
+      gcc_assert (noutputs == 1);
+      if (lhs)
+	lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
+
+      /* Do not assign directly to a promoted subreg, since there is no
+	 guarantee that the instruction will leave the upper bits of the
+	 register in the state required by SUBREG_PROMOTED_SIGN.  */
+      rtx dest = lhs_rtx;
+      if (dest && GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
+	dest = NULL_RTX;
+      create_output_operand (&ops[opno], dest,
+			     insn_data[icode].operand[opno].mode);
+      opno += 1;
+    }
+  else
+    gcc_assert (!lhs);
+
+  for (unsigned int i = 0; i < ninputs; ++i)
+    {
+      tree rhs = gimple_call_arg (stmt, i);
+      tree rhs_type = TREE_TYPE (rhs);
+      rtx rhs_rtx = expand_normal (rhs);
+      if (INTEGRAL_TYPE_P (rhs_type))
+	create_convert_operand_from (&ops[opno], rhs_rtx,
+				     TYPE_MODE (rhs_type),
+				     TYPE_UNSIGNED (rhs_type));
+      else
+	create_input_operand (&ops[opno], rhs_rtx, TYPE_MODE (rhs_type));
+      opno += 1;
+    }
+
+  gcc_assert (opno == noutputs + ninputs);
+  expand_insn (icode, opno, ops);
+  if (lhs_rtx && !rtx_equal_p (lhs_rtx, ops[0].value))
+    {
+      /* If the return value has an integral type, convert the instruction
+	 result to that type.  This is useful for things that return an
+	 int regardless of the size of the input.  If the instruction result
+	 is smaller than required, assume that it is signed.
+
+	 If the return value has a nonintegral type, its mode must match
+	 the instruction result.  */
+      if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
+	{
+	  /* If this is a scalar in a register that is stored in a wider
+	     mode than the declared mode, compute the result into its
+	     declared mode and then convert to the wider mode.  */
+	  gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
+	  rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
+	  convert_move (SUBREG_REG (lhs_rtx), tmp,
+			SUBREG_PROMOTED_SIGN (lhs_rtx));
+	}
+      else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
+	emit_move_insn (lhs_rtx, ops[0].value);
+      else
+	{
+	  gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
+	  convert_move (lhs_rtx, ops[0].value, 0);
+	}
+    }
+}
+
 /* ARRAY_TYPE is an array of vector modes.  Return the associated insn
    for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none.  */
 
@@ -233,22 +313,8 @@ expand_GOMP_SIMT_ENTER (internal_fn, gcall *)
 static void
 expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
 {
-  rtx target;
-  tree lhs = gimple_call_lhs (stmt);
-  if (lhs)
-    target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
-  else
-    target = gen_reg_rtx (Pmode);
-  rtx size = expand_normal (gimple_call_arg (stmt, 0));
-  rtx align = expand_normal (gimple_call_arg (stmt, 1));
-  class expand_operand ops[3];
-  create_output_operand (&ops[0], target, Pmode);
-  create_input_operand (&ops[1], size, Pmode);
-  create_input_operand (&ops[2], align, Pmode);
   gcc_assert (targetm.have_omp_simt_enter ());
-  expand_insn (targetm.code_for_omp_simt_enter, 3, ops);
-  if (!rtx_equal_p (target, ops[0].value))
-    emit_move_insn (target, ops[0].value);
+  expand_fn_using_insn (stmt, targetm.code_for_omp_simt_enter, 1, 2);
 }
 
 /* Deallocate per-lane storage and leave non-uniform execution region.  */
@@ -256,12 +322,8 @@ expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
 static void
 expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
 {
-  gcc_checking_assert (!gimple_call_lhs (stmt));
-  rtx arg = expand_normal (gimple_call_arg (stmt, 0));
-  class expand_operand ops[1];
-  create_input_operand (&ops[0], arg, Pmode);
   gcc_assert (targetm.have_omp_simt_exit ());
-  expand_insn (targetm.code_for_omp_simt_exit, 1, ops);
+  expand_fn_using_insn (stmt, targetm.code_for_omp_simt_exit, 0, 1);
 }
 
 /* Lane index on SIMT targets: thread index in the warp on NVPTX.  On targets
@@ -270,13 +332,8 @@ expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
 static void
 expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
 {
-  tree lhs = gimple_call_lhs (stmt);
-  if (!lhs)
-    return;
-
-  rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
   gcc_assert (targetm.have_omp_simt_lane ());
-  emit_insn (targetm.gen_omp_simt_lane (target));
+  expand_fn_using_insn (stmt, targetm.code_for_omp_simt_lane, 1, 0);
 }
 
 /* This should get expanded in omp_device_lower pass.  */
@@ -294,20 +351,8 @@ expand_GOMP_SIMT_VF (internal_fn, gcall *)
 static void
 expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
 {
-  tree lhs = gimple_call_lhs (stmt);
-  if (!lhs)
-    return;
-
-  rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
-  rtx cond = expand_normal (gimple_call_arg (stmt, 0));
-  machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
-  class expand_operand ops[2];
-  create_output_operand (&ops[0], target, mode);
-  create_input_operand (&ops[1], cond, mode);
   gcc_assert (targetm.have_omp_simt_last_lane ());
-  expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
-  if (!rtx_equal_p (target, ops[0].value))
-    emit_move_insn (target, ops[0].value);
+  expand_fn_using_insn (stmt, targetm.code_for_omp_simt_last_lane, 1, 1);
 }
 
 /* Non-transparent predicate used in SIMT lowering of OpenMP "ordered".  */
@@ -315,20 +360,8 @@ expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
 static void
 expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
 {
-  tree lhs = gimple_call_lhs (stmt);
-  if (!lhs)
-    return;
-
-  rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
-  rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
-  machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
-  class expand_operand ops[2];
-  create_output_operand (&ops[0], target, mode);
-  create_input_operand (&ops[1], ctr, mode);
   gcc_assert (targetm.have_omp_simt_ordered ());
-  expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
-  if (!rtx_equal_p (target, ops[0].value))
-    emit_move_insn (target, ops[0].value);
+  expand_fn_using_insn (stmt, targetm.code_for_omp_simt_ordered, 1, 1);
 }
 
 /* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
@@ -337,20 +370,8 @@ expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
 static void
 expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
 {
-  tree lhs = gimple_call_lhs (stmt);
-  if (!lhs)
-    return;
-
-  rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
-  rtx cond = expand_normal (gimple_call_arg (stmt, 0));
-  machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
-  class expand_operand ops[2];
-  create_output_operand (&ops[0], target, mode);
-  create_input_operand (&ops[1], cond, mode);
   gcc_assert (targetm.have_omp_simt_vote_any ());
-  expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
-  if (!rtx_equal_p (target, ops[0].value))
-    emit_move_insn (target, ops[0].value);
+  expand_fn_using_insn (stmt, targetm.code_for_omp_simt_vote_any, 1, 1);
 }
 
 /* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
@@ -359,22 +380,8 @@ expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
 static void
 expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
 {
-  tree lhs = gimple_call_lhs (stmt);
-  if (!lhs)
-    return;
-
-  rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
-  rtx src = expand_normal (gimple_call_arg (stmt, 0));
-  rtx idx = expand_normal (gimple_call_arg (stmt, 1));
-  machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
-  class expand_operand ops[3];
-  create_output_operand (&ops[0], target, mode);
-  create_input_operand (&ops[1], src, mode);
-  create_input_operand (&ops[2], idx, SImode);
   gcc_assert (targetm.have_omp_simt_xchg_bfly ());
-  expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
-  if (!rtx_equal_p (target, ops[0].value))
-    emit_move_insn (target, ops[0].value);
+  expand_fn_using_insn (stmt, targetm.code_for_omp_simt_xchg_bfly, 1, 2);
 }
 
 /* Exchange between SIMT lanes according to given source lane index.  */
@@ -382,22 +389,8 @@ expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
 static void
 expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
 {
-  tree lhs = gimple_call_lhs (stmt);
-  if (!lhs)
-    return;
-
-  rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
-  rtx src = expand_normal (gimple_call_arg (stmt, 0));
-  rtx idx = expand_normal (gimple_call_arg (stmt, 1));
-  machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
-  class expand_operand ops[3];
-  create_output_operand (&ops[0], target, mode);
-  create_input_operand (&ops[1], src, mode);
-  create_input_operand (&ops[2], idx, SImode);
   gcc_assert (targetm.have_omp_simt_xchg_idx ());
-  expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
-  if (!rtx_equal_p (target, ops[0].value))
-    emit_move_insn (target, ops[0].value);
+  expand_fn_using_insn (stmt, targetm.code_for_omp_simt_xchg_idx, 1, 2);
 }
 
 /* This should get expanded in adjust_simduid_builtins.  */
@@ -3565,67 +3558,9 @@ static void
 expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
 			unsigned int nargs)
 {
-  expand_operand *ops = XALLOCAVEC (expand_operand, nargs + 1);
-
   tree_pair types = direct_internal_fn_types (fn, stmt);
   insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
-  gcc_assert (icode != CODE_FOR_nothing);
-
-  tree lhs = gimple_call_lhs (stmt);
-  rtx lhs_rtx = NULL_RTX;
-  if (lhs)
-    lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
-
-  /* Do not assign directly to a promoted subreg, since there is no
-     guarantee that the instruction will leave the upper bits of the
-     register in the state required by SUBREG_PROMOTED_SIGN.  */
-  rtx dest = lhs_rtx;
-  if (dest && GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
-    dest = NULL_RTX;
-
-  create_output_operand (&ops[0], dest, insn_data[icode].operand[0].mode);
-
-  for (unsigned int i = 0; i < nargs; ++i)
-    {
-      tree rhs = gimple_call_arg (stmt, i);
-      tree rhs_type = TREE_TYPE (rhs);
-      rtx rhs_rtx = expand_normal (rhs);
-      if (INTEGRAL_TYPE_P (rhs_type))
-	create_convert_operand_from (&ops[i + 1], rhs_rtx,
-				     TYPE_MODE (rhs_type),
-				     TYPE_UNSIGNED (rhs_type));
-      else
-	create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type));
-    }
-
-  expand_insn (icode, nargs + 1, ops);
-  if (lhs_rtx && !rtx_equal_p (lhs_rtx, ops[0].value))
-    {
-      /* If the return value has an integral type, convert the instruction
-	 result to that type.  This is useful for things that return an
-	 int regardless of the size of the input.  If the instruction result
-	 is smaller than required, assume that it is signed.
-
-	 If the return value has a nonintegral type, its mode must match
-	 the instruction result.  */
-      if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
-	{
-	  /* If this is a scalar in a register that is stored in a wider
-	     mode than the declared mode, compute the result into its
-	     declared mode and then convert to the wider mode.  */
-	  gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
-	  rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
-	  convert_move (SUBREG_REG (lhs_rtx), tmp,
-			SUBREG_PROMOTED_SIGN (lhs_rtx));
-	}
-      else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
-	emit_move_insn (lhs_rtx, ops[0].value);
-      else
-	{
-	  gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
-	  convert_move (lhs_rtx, ops[0].value, 0);
-	}
-    }
+  expand_fn_using_insn (stmt, icode, 1, nargs);
 }
 
 /* Expand WHILE_ULT call STMT using optab OPTAB.  */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH 1/2] Factor out common internal-fn idiom
  2022-06-10  9:13 [PATCH 1/2] Factor out common internal-fn idiom Richard Sandiford
@ 2022-06-12 18:05 ` Jeff Law
  0 siblings, 0 replies; 2+ messages in thread
From: Jeff Law @ 2022-06-12 18:05 UTC (permalink / raw)
  To: gcc-patches



On 6/10/2022 3:13 AM, Richard Sandiford via Gcc-patches wrote:
> internal-fn.c has quite a few functions that simply map the result
> of the call to an instruction's output operand (if any) and map
> each argument to an instruction's input operand, in order.
> This patch adds a single function for doing that.  It's really
> just a generalisation of expand_direct_optab_fn, but with the
> output operand being optional.
>
> Unfortunately, it isn't possible to do this for vcond_mask
> because the internal function has a different argument order
> from the optab.
>
> Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?
>
> Richard
>
>
> gcc/
> 	* internal-fn.cc (expand_fn_using_insn): New function,
> 	split out and adapted from...
> 	(expand_direct_optab_fn): ...here.
> 	(expand_GOMP_SIMT_ENTER_ALLOC): Use it.
> 	(expand_GOMP_SIMT_EXIT): Likewise.
> 	(expand_GOMP_SIMT_LANE): Likewise.
> 	(expand_GOMP_SIMT_LAST_LANE): Likewise.
> 	(expand_GOMP_SIMT_ORDERED_PRED): Likewise.
> 	(expand_GOMP_SIMT_VOTE_ANY): Likewise.
> 	(expand_GOMP_SIMT_XCHG_BFLY): Likewise.
> 	(expand_GOMP_SIMT_XCHG_IDX): Likewise.
OK
Jeff


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-06-12 18:05 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-10  9:13 [PATCH 1/2] Factor out common internal-fn idiom Richard Sandiford
2022-06-12 18:05 ` Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).