public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/vendors/ARM/heads/morello)] Factor out internal-fn idiom
@ 2022-06-16 13:46 Richard Sandiford
0 siblings, 0 replies; only message in thread
From: Richard Sandiford @ 2022-06-16 13:46 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:fca8a0765bd8e4e037c947687fb70d561a93f2bb
commit fca8a0765bd8e4e037c947687fb70d561a93f2bb
Author: Richard Sandiford <richard.sandiford@arm.com>
Date: Thu Jun 16 14:42:39 2022 +0100
Factor out internal-fn idiom
This patch splits out most of expand_direct_optab_fn into a new
function called expand_direct_optab_fn. We can then reuse the
function for expand_CAP_GLOBAL_DATA_GET, but the main purpose
is to allow a later patch to reuse it too.
Diff:
---
gcc/internal-fn.c | 148 ++++++++++++++++++++++++++++++------------------------
1 file changed, 83 insertions(+), 65 deletions(-)
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index cdf51ccd732..f203bb3944b 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -136,6 +136,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. */
@@ -3029,14 +3109,10 @@ expand_REPLACE_ADDRESS_VALUE (internal_fn, gcall *gc)
global capability. */
static void
-expand_CAP_GLOBAL_DATA_GET (internal_fn, gcall *gc)
+expand_CAP_GLOBAL_DATA_GET (internal_fn, gcall *stmt)
{
- tree result = gimple_call_lhs (gc);
- /* Has no side-effects, hence if return value not used just return now. */
- gcc_assert (result);
gcc_assert (targetm.have_cap_global_data_get ());
- rtx target = expand_expr (result, NULL_RTX, VOIDmode, EXPAND_WRITE);
- emit_insn (targetm.gen_cap_global_data_get (target));
+ expand_fn_using_insn (stmt, targetm.code_for_cap_global_data_get, 1, 0);
}
/* Expand a NOP. */
@@ -3080,67 +3156,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. */
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-06-16 13:46 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-16 13:46 [gcc(refs/vendors/ARM/heads/morello)] Factor out internal-fn idiom Richard Sandiford
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).