public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/wschmidt/heads/builtins10)] rs6000: Builtin expansion, part 1
@ 2021-06-25 16:18 William Schmidt
0 siblings, 0 replies; 7+ messages in thread
From: William Schmidt @ 2021-06-25 16:18 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:33050d979b1daea306340b19a0cc8c17b54c6622
commit 33050d979b1daea306340b19a0cc8c17b54c6622
Author: Bill Schmidt <wschmidt@linux.ibm.com>
Date: Thu Jun 17 09:37:46 2021 -0500
rs6000: Builtin expansion, part 1
2021-06-17 Bill Schmidt <wschmidt@linux.ibm.com>
gcc/
* config/rs6000/rs6000-call.c (rs6000_expand_new_builtin): New
forward decl.
(rs6000_invalid_new_builtin): New stub function.
(rs6000_expand_builtin): Call rs6000_expand_new_builtin.
(rs6000_expand_ldst_mask): New stub function.
(new_cpu_expand_builtin): Likewise.
(elemrev_icode): Likewise.
(ldv_expand_builtin): Likewise.
(lxvrse_expand_builtin): Likewise.
(lxvrze_expand_builtin): Likewise.
(stv_expand_builtin): Likewise.
(new_mma_expand_builtin): Likewise.
(new_htm_expand_builtin): Likewise.
(rs6000_expand_new_builtin): New function.
Diff:
---
gcc/config/rs6000/rs6000-call.c | 526 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 526 insertions(+)
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index 52df3d165e1..8693836cd5a 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -190,6 +190,7 @@ static tree builtin_function_type (machine_mode, machine_mode,
static void rs6000_common_init_builtins (void);
static void htm_init_builtins (void);
static void mma_init_builtins (void);
+static rtx rs6000_expand_new_builtin (tree, rtx, rtx, machine_mode, int);
static bool rs6000_gimple_fold_new_builtin (gimple_stmt_iterator *gsi);
@@ -11664,6 +11665,14 @@ rs6000_invalid_builtin (enum rs6000_builtins fncode)
error ("%qs is not supported with the current options", name);
}
+/* Raise an error message for a builtin function that is called without the
+ appropriate target options being set. */
+
+static void
+rs6000_invalid_new_builtin (enum rs6000_gen_builtins fncode)
+{
+}
+
/* Target hook for early folding of built-ins, shamelessly stolen
from ia64.c. */
@@ -14193,6 +14202,9 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
machine_mode mode ATTRIBUTE_UNUSED,
int ignore ATTRIBUTE_UNUSED)
{
+ if (new_builtins_are_live)
+ return rs6000_expand_new_builtin (exp, target, subtarget, mode, ignore);
+
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
enum rs6000_builtins fcode
= (enum rs6000_builtins) DECL_MD_FUNCTION_CODE (fndecl);
@@ -14485,6 +14497,520 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
gcc_unreachable ();
}
+/* Expand ALTIVEC_BUILTIN_MASK_FOR_LOAD. */
+rtx
+rs6000_expand_ldst_mask (rtx target, tree arg0)
+ {
+ return target;
+ }
+
+/* Expand the CPU builtin in FCODE and store the result in TARGET. */
+static rtx
+new_cpu_expand_builtin (enum rs6000_gen_builtins fcode,
+ tree exp ATTRIBUTE_UNUSED, rtx target)
+{
+ return target;
+}
+
+static insn_code
+elemrev_icode (rs6000_gen_builtins fcode)
+{
+ return (insn_code) 0;
+}
+
+static rtx
+ldv_expand_builtin (rtx target, insn_code icode, rtx *op, machine_mode tmode)
+{
+ return target;
+}
+
+static rtx
+lxvrse_expand_builtin (rtx target, insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return target;
+}
+
+static rtx
+lxvrze_expand_builtin (rtx target, insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return target;
+}
+
+static rtx
+stv_expand_builtin (insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return NULL_RTX;
+}
+
+/* Expand the MMA built-in in EXP. */
+static rtx
+new_mma_expand_builtin (tree exp, rtx target, insn_code icode,
+ rs6000_gen_builtins fcode)
+{
+ return target;
+}
+
+/* Expand the HTM builtin in EXP and store the result in TARGET. */
+static rtx
+new_htm_expand_builtin (bifdata *bifaddr, rs6000_gen_builtins fcode,
+ tree exp, rtx target)
+{
+ return const0_rtx;
+}
+
+/* Expand an expression EXP that calls a built-in function,
+ with result going to TARGET if that's convenient
+ (and in mode MODE if that's convenient).
+ SUBTARGET may be used as the target for computing one of EXP's operands.
+ IGNORE is nonzero if the value is to be ignored.
+ Use the new builtin infrastructure. */
+static rtx
+rs6000_expand_new_builtin (tree exp, rtx target,
+ rtx subtarget ATTRIBUTE_UNUSED,
+ machine_mode ignore_mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
+{
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+ enum rs6000_gen_builtins fcode
+ = (enum rs6000_gen_builtins) DECL_MD_FUNCTION_CODE (fndecl);
+ size_t uns_fcode = (size_t)fcode;
+ enum insn_code icode = rs6000_builtin_info_x[uns_fcode].icode;
+
+ /* We have two different modes (KFmode, TFmode) that are the IEEE 128-bit
+ floating point type, depending on whether long double is the IBM extended
+ double (KFmode) or long double is IEEE 128-bit (TFmode). It is simpler if
+ we only define one variant of the built-in function, and switch the code
+ when defining it, rather than defining two built-ins and using the
+ overload table in rs6000-c.c to switch between the two. If we don't have
+ the proper assembler, don't do this switch because CODE_FOR_*kf* and
+ CODE_FOR_*tf* will be CODE_FOR_nothing. */
+ if (FLOAT128_IEEE_P (TFmode))
+ switch (icode)
+ {
+ default:
+ break;
+
+ case CODE_FOR_sqrtkf2_odd: icode = CODE_FOR_sqrttf2_odd; break;
+ case CODE_FOR_trunckfdf2_odd: icode = CODE_FOR_trunctfdf2_odd; break;
+ case CODE_FOR_addkf3_odd: icode = CODE_FOR_addtf3_odd; break;
+ case CODE_FOR_subkf3_odd: icode = CODE_FOR_subtf3_odd; break;
+ case CODE_FOR_mulkf3_odd: icode = CODE_FOR_multf3_odd; break;
+ case CODE_FOR_divkf3_odd: icode = CODE_FOR_divtf3_odd; break;
+ case CODE_FOR_fmakf4_odd: icode = CODE_FOR_fmatf4_odd; break;
+ case CODE_FOR_xsxexpqp_kf: icode = CODE_FOR_xsxexpqp_tf; break;
+ case CODE_FOR_xsxsigqp_kf: icode = CODE_FOR_xsxsigqp_tf; break;
+ case CODE_FOR_xststdcnegqp_kf: icode = CODE_FOR_xststdcnegqp_tf; break;
+ case CODE_FOR_xsiexpqp_kf: icode = CODE_FOR_xsiexpqp_tf; break;
+ case CODE_FOR_xsiexpqpf_kf: icode = CODE_FOR_xsiexpqpf_tf; break;
+ case CODE_FOR_xststdcqp_kf: icode = CODE_FOR_xststdcqp_tf; break;
+
+ case CODE_FOR_xscmpexpqp_eq_kf:
+ icode = CODE_FOR_xscmpexpqp_eq_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_lt_kf:
+ icode = CODE_FOR_xscmpexpqp_lt_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_gt_kf:
+ icode = CODE_FOR_xscmpexpqp_gt_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_unordered_kf:
+ icode = CODE_FOR_xscmpexpqp_unordered_tf;
+ break;
+ }
+
+ bifdata *bifaddr = &rs6000_builtin_info_x[uns_fcode];
+
+ /* In case of "#pragma target" changes, we initialize all builtins
+ but check for actual availability during expand time. For
+ invalid builtins, generate a normal call. */
+ switch (bifaddr->enable)
+ {
+ default:
+ gcc_unreachable ();
+ case ENB_ALWAYS:
+ break;
+ case ENB_P5:
+ if (!TARGET_POPCNTB)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P6:
+ if (!TARGET_CMPB)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_ALTIVEC:
+ if (!TARGET_ALTIVEC)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_CELL:
+ if (!TARGET_ALTIVEC || rs6000_cpu != PROCESSOR_CELL)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_VSX:
+ if (!TARGET_VSX)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P7:
+ if (!TARGET_POPCNTD)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P7_64:
+ if (!TARGET_POPCNTD || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P8:
+ if (!TARGET_DIRECT_MOVE)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P8V:
+ if (!TARGET_P8_VECTOR)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9:
+ if (!TARGET_MODULO)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9_64:
+ if (!TARGET_MODULO || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9V:
+ if (!TARGET_P9_VECTOR)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_IEEE128_HW:
+ if (!TARGET_FLOAT128_HW)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_DFP:
+ if (!TARGET_DFP)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_CRYPTO:
+ if (!TARGET_CRYPTO)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_HTM:
+ if (!TARGET_HTM)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P10:
+ if (!TARGET_POWER10)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P10_64:
+ if (!TARGET_POWER10 || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_MMA:
+ if (!TARGET_MMA)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ };
+
+ if (bif_is_nosoft (*bifaddr)
+ && rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT)
+ {
+ error ("%<%s%> not supported with %<-msoft-float%>",
+ bifaddr->bifname);
+ return const0_rtx;
+ }
+
+ if (bif_is_no32bit (*bifaddr) && TARGET_32BIT)
+ fatal_error (input_location,
+ "%<%s%> is not supported in 32-bit mode",
+ bifaddr->bifname);
+
+ if (bif_is_cpu (*bifaddr))
+ return new_cpu_expand_builtin (fcode, exp, target);
+
+ if (bif_is_init (*bifaddr))
+ return altivec_expand_vec_init_builtin (TREE_TYPE (exp), exp, target);
+
+ if (bif_is_set (*bifaddr))
+ return altivec_expand_vec_set_builtin (exp);
+
+ if (bif_is_extract (*bifaddr))
+ return altivec_expand_vec_ext_builtin (exp, target);
+
+ if (bif_is_predicate (*bifaddr))
+ return altivec_expand_predicate_builtin (icode, exp, target);
+
+ if (bif_is_htm (*bifaddr))
+ return new_htm_expand_builtin (bifaddr, fcode, exp, target);
+
+ rtx pat;
+ const int MAX_BUILTIN_ARGS = 6;
+ tree arg[MAX_BUILTIN_ARGS];
+ rtx op[MAX_BUILTIN_ARGS];
+ machine_mode mode[MAX_BUILTIN_ARGS + 1];
+ bool void_func = TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
+ int k;
+
+ int nargs = bifaddr->nargs;
+ gcc_assert (nargs <= MAX_BUILTIN_ARGS);
+
+ if (void_func)
+ k = 0;
+ else
+ {
+ k = 1;
+ mode[0] = insn_data[icode].operand[0].mode;
+ }
+
+ for (int i = 0; i < nargs; i++)
+ {
+ arg[i] = CALL_EXPR_ARG (exp, i);
+ if (arg[i] == error_mark_node)
+ return const0_rtx;
+ STRIP_NOPS (arg[i]);
+ op[i] = expand_normal (arg[i]);
+ /* We have a couple of pesky patterns that don't specify the mode... */
+ if (!insn_data[icode].operand[i+k].mode)
+ mode[i+k] = TARGET_64BIT ? Pmode : SImode;
+ else
+ mode[i+k] = insn_data[icode].operand[i+k].mode;
+ }
+
+ /* Check for restricted constant arguments. */
+ for (int i = 0; i < 2; i++)
+ {
+ switch (bifaddr->restr[i])
+ {
+ default:
+ case RES_NONE:
+ break;
+ case RES_BITS:
+ {
+ size_t mask = (1 << bifaddr->restr_val1[i]) - 1;
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || TREE_INT_CST_LOW (restr_arg) & ~mask)
+ {
+ error ("argument %d must be a %d-bit unsigned literal",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_RANGE:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || !IN_RANGE (tree_to_shwi (restr_arg),
+ bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be a literal between %d and %d,"
+ " inclusive",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_VAR_RANGE:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) == INTEGER_CST
+ && !IN_RANGE (tree_to_shwi (restr_arg),
+ bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be a variable or a literal "
+ "between %d and %d, inclusive",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_VALUES:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || (tree_to_shwi (restr_arg) != bifaddr->restr_val1[i]
+ && tree_to_shwi (restr_arg) != bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be either a literal %d or a "
+ "literal %d",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ }
+ }
+
+ if (bif_is_ldstmask (*bifaddr))
+ return rs6000_expand_ldst_mask (target, arg[0]);
+
+ if (bif_is_stvec (*bifaddr))
+ {
+ if (bif_is_reve (*bifaddr))
+ icode = elemrev_icode (fcode);
+ return stv_expand_builtin (icode, op, mode[0], mode[1]);
+ }
+
+ if (bif_is_ldvec (*bifaddr))
+ {
+ if (bif_is_reve (*bifaddr))
+ icode = elemrev_icode (fcode);
+ return ldv_expand_builtin (target, icode, op, mode[0]);
+ }
+
+ if (bif_is_lxvrse (*bifaddr))
+ return lxvrse_expand_builtin (target, icode, op, mode[0], mode[1]);
+
+ if (bif_is_lxvrze (*bifaddr))
+ return lxvrze_expand_builtin (target, icode, op, mode[0], mode[1]);
+
+ if (bif_is_mma (*bifaddr))
+ return new_mma_expand_builtin (exp, target, icode, fcode);
+
+ if (fcode == RS6000_BIF_PACK_IF
+ && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+ {
+ icode = CODE_FOR_packtf;
+ fcode = RS6000_BIF_PACK_TF;
+ uns_fcode = (size_t)fcode;
+ }
+ else if (fcode == RS6000_BIF_UNPACK_IF
+ && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+ {
+ icode = CODE_FOR_unpacktf;
+ fcode = RS6000_BIF_UNPACK_TF;
+ uns_fcode = (size_t)fcode;
+ }
+
+ if (TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node)
+ target = NULL_RTX;
+ else if (target == 0
+ || GET_MODE (target) != mode[0]
+ || !(*insn_data[icode].operand[0].predicate) (target, mode[0]))
+ target = gen_reg_rtx (mode[0]);
+
+ for (int i = 0; i < nargs; i++)
+ if (! (*insn_data[icode].operand[i+k].predicate) (op[i], mode[i+k]))
+ op[i] = copy_to_mode_reg (mode[i+k], op[i]);
+
+ switch (nargs)
+ {
+ default:
+ gcc_assert (MAX_BUILTIN_ARGS == 6);
+ gcc_unreachable ();
+ case 0:
+ pat = (void_func
+ ? GEN_FCN (icode) ()
+ : GEN_FCN (icode) (target));
+ break;
+ case 1:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0])
+ : GEN_FCN (icode) (target, op[0]));
+ break;
+ case 2:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1])
+ : GEN_FCN (icode) (target, op[0], op[1]));
+ break;
+ case 3:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2]));
+ break;
+ case 4:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]));
+ break;
+ case 5:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]));
+ break;
+ case 6:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5])
+ : GEN_FCN (icode) (target, op[0], op[1],
+ op[2], op[3], op[4], op[5]));
+ break;
+ }
+
+ if (!pat)
+ return 0;
+ emit_insn (pat);
+
+ return target;
+}
+
/* Create a builtin vector type with a name. Taking care not to give
the canonical type a name. */
^ permalink raw reply [flat|nested] 7+ messages in thread
* [gcc(refs/users/wschmidt/heads/builtins10)] rs6000: Builtin expansion, part 1
@ 2021-07-29 14:46 William Schmidt
0 siblings, 0 replies; 7+ messages in thread
From: William Schmidt @ 2021-07-29 14:46 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:b8d4f4c6b02ce3589b7373def3aa7fe0ae53685f
commit b8d4f4c6b02ce3589b7373def3aa7fe0ae53685f
Author: Bill Schmidt <wschmidt@linux.ibm.com>
Date: Thu Jun 17 09:37:46 2021 -0500
rs6000: Builtin expansion, part 1
2021-06-17 Bill Schmidt <wschmidt@linux.ibm.com>
gcc/
* config/rs6000/rs6000-call.c (rs6000_expand_new_builtin): New
forward decl.
(rs6000_invalid_new_builtin): New stub function.
(rs6000_expand_builtin): Call rs6000_expand_new_builtin.
(rs6000_expand_ldst_mask): New stub function.
(new_cpu_expand_builtin): Likewise.
(elemrev_icode): Likewise.
(ldv_expand_builtin): Likewise.
(lxvrse_expand_builtin): Likewise.
(lxvrze_expand_builtin): Likewise.
(stv_expand_builtin): Likewise.
(new_mma_expand_builtin): Likewise.
(new_htm_expand_builtin): Likewise.
(rs6000_expand_new_builtin): New function.
Diff:
---
gcc/config/rs6000/rs6000-call.c | 526 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 526 insertions(+)
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index f75b5c8176c..4719d074455 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -190,6 +190,7 @@ static tree builtin_function_type (machine_mode, machine_mode,
static void rs6000_common_init_builtins (void);
static void htm_init_builtins (void);
static void mma_init_builtins (void);
+static rtx rs6000_expand_new_builtin (tree, rtx, rtx, machine_mode, int);
static bool rs6000_gimple_fold_new_builtin (gimple_stmt_iterator *gsi);
@@ -11664,6 +11665,14 @@ rs6000_invalid_builtin (enum rs6000_builtins fncode)
error ("%qs is not supported with the current options", name);
}
+/* Raise an error message for a builtin function that is called without the
+ appropriate target options being set. */
+
+static void
+rs6000_invalid_new_builtin (enum rs6000_gen_builtins fncode)
+{
+}
+
/* Target hook for early folding of built-ins, shamelessly stolen
from ia64.c. */
@@ -14255,6 +14264,9 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
machine_mode mode ATTRIBUTE_UNUSED,
int ignore ATTRIBUTE_UNUSED)
{
+ if (new_builtins_are_live)
+ return rs6000_expand_new_builtin (exp, target, subtarget, mode, ignore);
+
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
enum rs6000_builtins fcode
= (enum rs6000_builtins) DECL_MD_FUNCTION_CODE (fndecl);
@@ -14547,6 +14559,520 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
gcc_unreachable ();
}
+/* Expand ALTIVEC_BUILTIN_MASK_FOR_LOAD. */
+rtx
+rs6000_expand_ldst_mask (rtx target, tree arg0)
+ {
+ return target;
+ }
+
+/* Expand the CPU builtin in FCODE and store the result in TARGET. */
+static rtx
+new_cpu_expand_builtin (enum rs6000_gen_builtins fcode,
+ tree exp ATTRIBUTE_UNUSED, rtx target)
+{
+ return target;
+}
+
+static insn_code
+elemrev_icode (rs6000_gen_builtins fcode)
+{
+ return (insn_code) 0;
+}
+
+static rtx
+ldv_expand_builtin (rtx target, insn_code icode, rtx *op, machine_mode tmode)
+{
+ return target;
+}
+
+static rtx
+lxvrse_expand_builtin (rtx target, insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return target;
+}
+
+static rtx
+lxvrze_expand_builtin (rtx target, insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return target;
+}
+
+static rtx
+stv_expand_builtin (insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return NULL_RTX;
+}
+
+/* Expand the MMA built-in in EXP. */
+static rtx
+new_mma_expand_builtin (tree exp, rtx target, insn_code icode,
+ rs6000_gen_builtins fcode)
+{
+ return target;
+}
+
+/* Expand the HTM builtin in EXP and store the result in TARGET. */
+static rtx
+new_htm_expand_builtin (bifdata *bifaddr, rs6000_gen_builtins fcode,
+ tree exp, rtx target)
+{
+ return const0_rtx;
+}
+
+/* Expand an expression EXP that calls a built-in function,
+ with result going to TARGET if that's convenient
+ (and in mode MODE if that's convenient).
+ SUBTARGET may be used as the target for computing one of EXP's operands.
+ IGNORE is nonzero if the value is to be ignored.
+ Use the new builtin infrastructure. */
+static rtx
+rs6000_expand_new_builtin (tree exp, rtx target,
+ rtx subtarget ATTRIBUTE_UNUSED,
+ machine_mode ignore_mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
+{
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+ enum rs6000_gen_builtins fcode
+ = (enum rs6000_gen_builtins) DECL_MD_FUNCTION_CODE (fndecl);
+ size_t uns_fcode = (size_t)fcode;
+ enum insn_code icode = rs6000_builtin_info_x[uns_fcode].icode;
+
+ /* We have two different modes (KFmode, TFmode) that are the IEEE 128-bit
+ floating point type, depending on whether long double is the IBM extended
+ double (KFmode) or long double is IEEE 128-bit (TFmode). It is simpler if
+ we only define one variant of the built-in function, and switch the code
+ when defining it, rather than defining two built-ins and using the
+ overload table in rs6000-c.c to switch between the two. If we don't have
+ the proper assembler, don't do this switch because CODE_FOR_*kf* and
+ CODE_FOR_*tf* will be CODE_FOR_nothing. */
+ if (FLOAT128_IEEE_P (TFmode))
+ switch (icode)
+ {
+ default:
+ break;
+
+ case CODE_FOR_sqrtkf2_odd: icode = CODE_FOR_sqrttf2_odd; break;
+ case CODE_FOR_trunckfdf2_odd: icode = CODE_FOR_trunctfdf2_odd; break;
+ case CODE_FOR_addkf3_odd: icode = CODE_FOR_addtf3_odd; break;
+ case CODE_FOR_subkf3_odd: icode = CODE_FOR_subtf3_odd; break;
+ case CODE_FOR_mulkf3_odd: icode = CODE_FOR_multf3_odd; break;
+ case CODE_FOR_divkf3_odd: icode = CODE_FOR_divtf3_odd; break;
+ case CODE_FOR_fmakf4_odd: icode = CODE_FOR_fmatf4_odd; break;
+ case CODE_FOR_xsxexpqp_kf: icode = CODE_FOR_xsxexpqp_tf; break;
+ case CODE_FOR_xsxsigqp_kf: icode = CODE_FOR_xsxsigqp_tf; break;
+ case CODE_FOR_xststdcnegqp_kf: icode = CODE_FOR_xststdcnegqp_tf; break;
+ case CODE_FOR_xsiexpqp_kf: icode = CODE_FOR_xsiexpqp_tf; break;
+ case CODE_FOR_xsiexpqpf_kf: icode = CODE_FOR_xsiexpqpf_tf; break;
+ case CODE_FOR_xststdcqp_kf: icode = CODE_FOR_xststdcqp_tf; break;
+
+ case CODE_FOR_xscmpexpqp_eq_kf:
+ icode = CODE_FOR_xscmpexpqp_eq_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_lt_kf:
+ icode = CODE_FOR_xscmpexpqp_lt_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_gt_kf:
+ icode = CODE_FOR_xscmpexpqp_gt_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_unordered_kf:
+ icode = CODE_FOR_xscmpexpqp_unordered_tf;
+ break;
+ }
+
+ bifdata *bifaddr = &rs6000_builtin_info_x[uns_fcode];
+
+ /* In case of "#pragma target" changes, we initialize all builtins
+ but check for actual availability during expand time. For
+ invalid builtins, generate a normal call. */
+ switch (bifaddr->enable)
+ {
+ default:
+ gcc_unreachable ();
+ case ENB_ALWAYS:
+ break;
+ case ENB_P5:
+ if (!TARGET_POPCNTB)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P6:
+ if (!TARGET_CMPB)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_ALTIVEC:
+ if (!TARGET_ALTIVEC)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_CELL:
+ if (!TARGET_ALTIVEC || rs6000_cpu != PROCESSOR_CELL)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_VSX:
+ if (!TARGET_VSX)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P7:
+ if (!TARGET_POPCNTD)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P7_64:
+ if (!TARGET_POPCNTD || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P8:
+ if (!TARGET_DIRECT_MOVE)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P8V:
+ if (!TARGET_P8_VECTOR)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9:
+ if (!TARGET_MODULO)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9_64:
+ if (!TARGET_MODULO || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9V:
+ if (!TARGET_P9_VECTOR)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_IEEE128_HW:
+ if (!TARGET_FLOAT128_HW)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_DFP:
+ if (!TARGET_DFP)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_CRYPTO:
+ if (!TARGET_CRYPTO)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_HTM:
+ if (!TARGET_HTM)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P10:
+ if (!TARGET_POWER10)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P10_64:
+ if (!TARGET_POWER10 || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_MMA:
+ if (!TARGET_MMA)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ };
+
+ if (bif_is_nosoft (*bifaddr)
+ && rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT)
+ {
+ error ("%<%s%> not supported with %<-msoft-float%>",
+ bifaddr->bifname);
+ return const0_rtx;
+ }
+
+ if (bif_is_no32bit (*bifaddr) && TARGET_32BIT)
+ fatal_error (input_location,
+ "%<%s%> is not supported in 32-bit mode",
+ bifaddr->bifname);
+
+ if (bif_is_cpu (*bifaddr))
+ return new_cpu_expand_builtin (fcode, exp, target);
+
+ if (bif_is_init (*bifaddr))
+ return altivec_expand_vec_init_builtin (TREE_TYPE (exp), exp, target);
+
+ if (bif_is_set (*bifaddr))
+ return altivec_expand_vec_set_builtin (exp);
+
+ if (bif_is_extract (*bifaddr))
+ return altivec_expand_vec_ext_builtin (exp, target);
+
+ if (bif_is_predicate (*bifaddr))
+ return altivec_expand_predicate_builtin (icode, exp, target);
+
+ if (bif_is_htm (*bifaddr))
+ return new_htm_expand_builtin (bifaddr, fcode, exp, target);
+
+ rtx pat;
+ const int MAX_BUILTIN_ARGS = 6;
+ tree arg[MAX_BUILTIN_ARGS];
+ rtx op[MAX_BUILTIN_ARGS];
+ machine_mode mode[MAX_BUILTIN_ARGS + 1];
+ bool void_func = TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
+ int k;
+
+ int nargs = bifaddr->nargs;
+ gcc_assert (nargs <= MAX_BUILTIN_ARGS);
+
+ if (void_func)
+ k = 0;
+ else
+ {
+ k = 1;
+ mode[0] = insn_data[icode].operand[0].mode;
+ }
+
+ for (int i = 0; i < nargs; i++)
+ {
+ arg[i] = CALL_EXPR_ARG (exp, i);
+ if (arg[i] == error_mark_node)
+ return const0_rtx;
+ STRIP_NOPS (arg[i]);
+ op[i] = expand_normal (arg[i]);
+ /* We have a couple of pesky patterns that don't specify the mode... */
+ if (!insn_data[icode].operand[i+k].mode)
+ mode[i+k] = TARGET_64BIT ? Pmode : SImode;
+ else
+ mode[i+k] = insn_data[icode].operand[i+k].mode;
+ }
+
+ /* Check for restricted constant arguments. */
+ for (int i = 0; i < 2; i++)
+ {
+ switch (bifaddr->restr[i])
+ {
+ default:
+ case RES_NONE:
+ break;
+ case RES_BITS:
+ {
+ size_t mask = (1 << bifaddr->restr_val1[i]) - 1;
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || TREE_INT_CST_LOW (restr_arg) & ~mask)
+ {
+ error ("argument %d must be a %d-bit unsigned literal",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_RANGE:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || !IN_RANGE (tree_to_shwi (restr_arg),
+ bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be a literal between %d and %d,"
+ " inclusive",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_VAR_RANGE:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) == INTEGER_CST
+ && !IN_RANGE (tree_to_shwi (restr_arg),
+ bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be a variable or a literal "
+ "between %d and %d, inclusive",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_VALUES:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || (tree_to_shwi (restr_arg) != bifaddr->restr_val1[i]
+ && tree_to_shwi (restr_arg) != bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be either a literal %d or a "
+ "literal %d",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ }
+ }
+
+ if (bif_is_ldstmask (*bifaddr))
+ return rs6000_expand_ldst_mask (target, arg[0]);
+
+ if (bif_is_stvec (*bifaddr))
+ {
+ if (bif_is_reve (*bifaddr))
+ icode = elemrev_icode (fcode);
+ return stv_expand_builtin (icode, op, mode[0], mode[1]);
+ }
+
+ if (bif_is_ldvec (*bifaddr))
+ {
+ if (bif_is_reve (*bifaddr))
+ icode = elemrev_icode (fcode);
+ return ldv_expand_builtin (target, icode, op, mode[0]);
+ }
+
+ if (bif_is_lxvrse (*bifaddr))
+ return lxvrse_expand_builtin (target, icode, op, mode[0], mode[1]);
+
+ if (bif_is_lxvrze (*bifaddr))
+ return lxvrze_expand_builtin (target, icode, op, mode[0], mode[1]);
+
+ if (bif_is_mma (*bifaddr))
+ return new_mma_expand_builtin (exp, target, icode, fcode);
+
+ if (fcode == RS6000_BIF_PACK_IF
+ && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+ {
+ icode = CODE_FOR_packtf;
+ fcode = RS6000_BIF_PACK_TF;
+ uns_fcode = (size_t)fcode;
+ }
+ else if (fcode == RS6000_BIF_UNPACK_IF
+ && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+ {
+ icode = CODE_FOR_unpacktf;
+ fcode = RS6000_BIF_UNPACK_TF;
+ uns_fcode = (size_t)fcode;
+ }
+
+ if (TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node)
+ target = NULL_RTX;
+ else if (target == 0
+ || GET_MODE (target) != mode[0]
+ || !(*insn_data[icode].operand[0].predicate) (target, mode[0]))
+ target = gen_reg_rtx (mode[0]);
+
+ for (int i = 0; i < nargs; i++)
+ if (! (*insn_data[icode].operand[i+k].predicate) (op[i], mode[i+k]))
+ op[i] = copy_to_mode_reg (mode[i+k], op[i]);
+
+ switch (nargs)
+ {
+ default:
+ gcc_assert (MAX_BUILTIN_ARGS == 6);
+ gcc_unreachable ();
+ case 0:
+ pat = (void_func
+ ? GEN_FCN (icode) ()
+ : GEN_FCN (icode) (target));
+ break;
+ case 1:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0])
+ : GEN_FCN (icode) (target, op[0]));
+ break;
+ case 2:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1])
+ : GEN_FCN (icode) (target, op[0], op[1]));
+ break;
+ case 3:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2]));
+ break;
+ case 4:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]));
+ break;
+ case 5:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]));
+ break;
+ case 6:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5])
+ : GEN_FCN (icode) (target, op[0], op[1],
+ op[2], op[3], op[4], op[5]));
+ break;
+ }
+
+ if (!pat)
+ return 0;
+ emit_insn (pat);
+
+ return target;
+}
+
/* Create a builtin vector type with a name. Taking care not to give
the canonical type a name. */
^ permalink raw reply [flat|nested] 7+ messages in thread
* [gcc(refs/users/wschmidt/heads/builtins10)] rs6000: Builtin expansion, part 1
@ 2021-06-15 17:19 William Schmidt
0 siblings, 0 replies; 7+ messages in thread
From: William Schmidt @ 2021-06-15 17:19 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:f836009b690b03ad4f98993b0aa009fcb771c2f0
commit f836009b690b03ad4f98993b0aa009fcb771c2f0
Author: Bill Schmidt <wschmidt@linux.ibm.com>
Date: Fri Apr 2 17:03:37 2021 -0500
rs6000: Builtin expansion, part 1
2021-04-02 Bill Schmidt <wschmidt@linux.ibm.com>
gcc/
* config/rs6000/rs6000-call.c (rs6000_expand_new_builtin): New
forward decl.
(rs6000_invalid_new_builtin): New stub function.
(rs6000_expand_builtin): Call rs6000_expand_new_builtin.
(rs6000_expand_ldst_mask): New stub function.
(new_cpu_expand_builtin): Likewise.
(elemrev_icode): Likewise.
(ldv_expand_builtin): Likewise.
(lxvrse_expand_builtin): Likewise.
(lxvrze_expand_builtin): Likewise.
(stv_expand_builtin): Likewise.
(new_mma_expand_builtin): Likewise.
(new_htm_expand_builtin): Likewise.
(rs6000_expand_new_builtin): New function.
Diff:
---
gcc/config/rs6000/rs6000-call.c | 525 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 525 insertions(+)
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index 2718ed7958a..201e730420a 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -190,6 +190,7 @@ static tree builtin_function_type (machine_mode, machine_mode,
static void rs6000_common_init_builtins (void);
static void htm_init_builtins (void);
static void mma_init_builtins (void);
+static rtx rs6000_expand_new_builtin (tree, rtx, rtx, machine_mode, int);
static bool rs6000_gimple_fold_new_builtin (gimple_stmt_iterator *gsi);
@@ -11653,6 +11654,14 @@ rs6000_invalid_builtin (enum rs6000_builtins fncode)
error ("%qs is not supported with the current options", name);
}
+/* Raise an error message for a builtin function that is called without the
+ appropriate target options being set. */
+
+static void
+rs6000_invalid_new_builtin (enum rs6000_gen_builtins fncode)
+{
+}
+
/* Target hook for early folding of built-ins, shamelessly stolen
from ia64.c. */
@@ -14182,6 +14191,9 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
machine_mode mode ATTRIBUTE_UNUSED,
int ignore ATTRIBUTE_UNUSED)
{
+ if (new_builtins_are_live)
+ return rs6000_expand_new_builtin (exp, target, subtarget, mode, ignore);
+
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
enum rs6000_builtins fcode
= (enum rs6000_builtins) DECL_MD_FUNCTION_CODE (fndecl);
@@ -14474,6 +14486,519 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
gcc_unreachable ();
}
+/* Expand ALTIVEC_BUILTIN_MASK_FOR_LOAD. */
+rtx
+rs6000_expand_ldst_mask (rtx target, tree arg0)
+ {
+ return target;
+ }
+
+/* Expand the CPU builtin in FCODE and store the result in TARGET. */
+static rtx
+new_cpu_expand_builtin (enum rs6000_gen_builtins fcode,
+ tree exp ATTRIBUTE_UNUSED, rtx target)
+{
+ return target;
+}
+
+static insn_code
+elemrev_icode (rs6000_gen_builtins fcode)
+{
+ return (insn_code) 0;
+}
+
+static rtx
+ldv_expand_builtin (rtx target, insn_code icode, rtx *op, machine_mode tmode)
+{
+ return target;
+}
+
+static rtx
+lxvrse_expand_builtin (rtx target, insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return target;
+}
+
+static rtx
+lxvrze_expand_builtin (rtx target, insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return target;
+}
+
+static rtx
+stv_expand_builtin (insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return NULL_RTX;
+}
+
+/* Expand the MMA built-in in EXP. */
+static rtx
+new_mma_expand_builtin (tree exp, rtx target, insn_code icode)
+{
+ return target;
+}
+
+/* Expand the HTM builtin in EXP and store the result in TARGET. */
+static rtx
+new_htm_expand_builtin (bifdata *bifaddr, rs6000_gen_builtins fcode,
+ tree exp, rtx target)
+{
+ return const0_rtx;
+}
+
+/* Expand an expression EXP that calls a built-in function,
+ with result going to TARGET if that's convenient
+ (and in mode MODE if that's convenient).
+ SUBTARGET may be used as the target for computing one of EXP's operands.
+ IGNORE is nonzero if the value is to be ignored.
+ Use the new builtin infrastructure. */
+static rtx
+rs6000_expand_new_builtin (tree exp, rtx target,
+ rtx subtarget ATTRIBUTE_UNUSED,
+ machine_mode ignore_mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
+{
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+ enum rs6000_gen_builtins fcode
+ = (enum rs6000_gen_builtins) DECL_MD_FUNCTION_CODE (fndecl);
+ size_t uns_fcode = (size_t)fcode;
+ enum insn_code icode = rs6000_builtin_info_x[uns_fcode].icode;
+
+ /* We have two different modes (KFmode, TFmode) that are the IEEE 128-bit
+ floating point type, depending on whether long double is the IBM extended
+ double (KFmode) or long double is IEEE 128-bit (TFmode). It is simpler if
+ we only define one variant of the built-in function, and switch the code
+ when defining it, rather than defining two built-ins and using the
+ overload table in rs6000-c.c to switch between the two. If we don't have
+ the proper assembler, don't do this switch because CODE_FOR_*kf* and
+ CODE_FOR_*tf* will be CODE_FOR_nothing. */
+ if (FLOAT128_IEEE_P (TFmode))
+ switch (icode)
+ {
+ default:
+ break;
+
+ case CODE_FOR_sqrtkf2_odd: icode = CODE_FOR_sqrttf2_odd; break;
+ case CODE_FOR_trunckfdf2_odd: icode = CODE_FOR_trunctfdf2_odd; break;
+ case CODE_FOR_addkf3_odd: icode = CODE_FOR_addtf3_odd; break;
+ case CODE_FOR_subkf3_odd: icode = CODE_FOR_subtf3_odd; break;
+ case CODE_FOR_mulkf3_odd: icode = CODE_FOR_multf3_odd; break;
+ case CODE_FOR_divkf3_odd: icode = CODE_FOR_divtf3_odd; break;
+ case CODE_FOR_fmakf4_odd: icode = CODE_FOR_fmatf4_odd; break;
+ case CODE_FOR_xsxexpqp_kf: icode = CODE_FOR_xsxexpqp_tf; break;
+ case CODE_FOR_xsxsigqp_kf: icode = CODE_FOR_xsxsigqp_tf; break;
+ case CODE_FOR_xststdcnegqp_kf: icode = CODE_FOR_xststdcnegqp_tf; break;
+ case CODE_FOR_xsiexpqp_kf: icode = CODE_FOR_xsiexpqp_tf; break;
+ case CODE_FOR_xsiexpqpf_kf: icode = CODE_FOR_xsiexpqpf_tf; break;
+ case CODE_FOR_xststdcqp_kf: icode = CODE_FOR_xststdcqp_tf; break;
+
+ case CODE_FOR_xscmpexpqp_eq_kf:
+ icode = CODE_FOR_xscmpexpqp_eq_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_lt_kf:
+ icode = CODE_FOR_xscmpexpqp_lt_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_gt_kf:
+ icode = CODE_FOR_xscmpexpqp_gt_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_unordered_kf:
+ icode = CODE_FOR_xscmpexpqp_unordered_tf;
+ break;
+ }
+
+ bifdata *bifaddr = &rs6000_builtin_info_x[uns_fcode];
+
+ /* In case of "#pragma target" changes, we initialize all builtins
+ but check for actual availability during expand time. For
+ invalid builtins, generate a normal call. */
+ switch (bifaddr->enable)
+ {
+ default:
+ gcc_unreachable ();
+ case ENB_ALWAYS:
+ break;
+ case ENB_P5:
+ if (!TARGET_POPCNTB)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P6:
+ if (!TARGET_CMPB)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_ALTIVEC:
+ if (!TARGET_ALTIVEC)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_CELL:
+ if (!TARGET_ALTIVEC || rs6000_cpu != PROCESSOR_CELL)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_VSX:
+ if (!TARGET_VSX)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P7:
+ if (!TARGET_POPCNTD)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P7_64:
+ if (!TARGET_POPCNTD || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P8:
+ if (!TARGET_DIRECT_MOVE)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P8V:
+ if (!TARGET_P8_VECTOR)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9:
+ if (!TARGET_MODULO)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9_64:
+ if (!TARGET_MODULO || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9V:
+ if (!TARGET_P9_VECTOR)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_IEEE128_HW:
+ if (!TARGET_FLOAT128_HW)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_DFP:
+ if (!TARGET_DFP)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_CRYPTO:
+ if (!TARGET_CRYPTO)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_HTM:
+ if (!TARGET_HTM)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P10:
+ if (!TARGET_POWER10)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P10_64:
+ if (!TARGET_POWER10 || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_MMA:
+ if (!TARGET_MMA)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ };
+
+ if (bif_is_nosoft (*bifaddr)
+ && rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT)
+ {
+ error ("%<%s%> not supported with %<-msoft-float%>",
+ bifaddr->bifname);
+ return const0_rtx;
+ }
+
+ if (bif_is_no32bit (*bifaddr) && TARGET_32BIT)
+ fatal_error (input_location,
+ "%<%s%> is not supported in 32-bit mode",
+ bifaddr->bifname);
+
+ if (bif_is_cpu (*bifaddr))
+ return new_cpu_expand_builtin (fcode, exp, target);
+
+ if (bif_is_init (*bifaddr))
+ return altivec_expand_vec_init_builtin (TREE_TYPE (exp), exp, target);
+
+ if (bif_is_set (*bifaddr))
+ return altivec_expand_vec_set_builtin (exp);
+
+ if (bif_is_extract (*bifaddr))
+ return altivec_expand_vec_ext_builtin (exp, target);
+
+ if (bif_is_predicate (*bifaddr))
+ return altivec_expand_predicate_builtin (icode, exp, target);
+
+ if (bif_is_htm (*bifaddr))
+ return new_htm_expand_builtin (bifaddr, fcode, exp, target);
+
+ rtx pat;
+ const int MAX_BUILTIN_ARGS = 6;
+ tree arg[MAX_BUILTIN_ARGS];
+ rtx op[MAX_BUILTIN_ARGS];
+ machine_mode mode[MAX_BUILTIN_ARGS + 1];
+ bool void_func = TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
+ int k;
+
+ int nargs = bifaddr->nargs;
+ gcc_assert (nargs <= MAX_BUILTIN_ARGS);
+
+ if (void_func)
+ k = 0;
+ else
+ {
+ k = 1;
+ mode[0] = insn_data[icode].operand[0].mode;
+ }
+
+ for (int i = 0; i < nargs; i++)
+ {
+ arg[i] = CALL_EXPR_ARG (exp, i);
+ if (arg[i] == error_mark_node)
+ return const0_rtx;
+ STRIP_NOPS (arg[i]);
+ op[i] = expand_normal (arg[i]);
+ /* We have a couple of pesky patterns that don't specify the mode... */
+ if (!insn_data[icode].operand[i+k].mode)
+ mode[i+k] = TARGET_64BIT ? Pmode : SImode;
+ else
+ mode[i+k] = insn_data[icode].operand[i+k].mode;
+ }
+
+ /* Check for restricted constant arguments. */
+ for (int i = 0; i < 2; i++)
+ {
+ switch (bifaddr->restr[i])
+ {
+ default:
+ case RES_NONE:
+ break;
+ case RES_BITS:
+ {
+ size_t mask = (1 << bifaddr->restr_val1[i]) - 1;
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || TREE_INT_CST_LOW (restr_arg) & ~mask)
+ {
+ error ("argument %d must be a %d-bit unsigned literal",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_RANGE:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || !IN_RANGE (tree_to_shwi (restr_arg),
+ bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be a literal between %d and %d,"
+ " inclusive",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_VAR_RANGE:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) == INTEGER_CST
+ && !IN_RANGE (tree_to_shwi (restr_arg),
+ bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be a variable or a literal "
+ "between %d and %d, inclusive",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_VALUES:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || (tree_to_shwi (restr_arg) != bifaddr->restr_val1[i]
+ && tree_to_shwi (restr_arg) != bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be either a literal %d or a "
+ "literal %d",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ }
+ }
+
+ if (bif_is_ldstmask (*bifaddr))
+ return rs6000_expand_ldst_mask (target, arg[0]);
+
+ if (bif_is_stvec (*bifaddr))
+ {
+ if (bif_is_reve (*bifaddr))
+ icode = elemrev_icode (fcode);
+ return stv_expand_builtin (icode, op, mode[0], mode[1]);
+ }
+
+ if (bif_is_ldvec (*bifaddr))
+ {
+ if (bif_is_reve (*bifaddr))
+ icode = elemrev_icode (fcode);
+ return ldv_expand_builtin (target, icode, op, mode[0]);
+ }
+
+ if (bif_is_lxvrse (*bifaddr))
+ return lxvrse_expand_builtin (target, icode, op, mode[0], mode[1]);
+
+ if (bif_is_lxvrze (*bifaddr))
+ return lxvrze_expand_builtin (target, icode, op, mode[0], mode[1]);
+
+ if (bif_is_mma (*bifaddr))
+ return new_mma_expand_builtin (exp, target, icode);
+
+ if (fcode == RS6000_BIF_PACK_IF
+ && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+ {
+ icode = CODE_FOR_packtf;
+ fcode = RS6000_BIF_PACK_TF;
+ uns_fcode = (size_t)fcode;
+ }
+ else if (fcode == RS6000_BIF_UNPACK_IF
+ && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+ {
+ icode = CODE_FOR_unpacktf;
+ fcode = RS6000_BIF_UNPACK_TF;
+ uns_fcode = (size_t)fcode;
+ }
+
+ if (TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node)
+ target = NULL_RTX;
+ else if (target == 0
+ || GET_MODE (target) != mode[0]
+ || !(*insn_data[icode].operand[0].predicate) (target, mode[0]))
+ target = gen_reg_rtx (mode[0]);
+
+ for (int i = 0; i < nargs; i++)
+ if (! (*insn_data[icode].operand[i+k].predicate) (op[i], mode[i+k]))
+ op[i] = copy_to_mode_reg (mode[i+k], op[i]);
+
+ switch (nargs)
+ {
+ default:
+ gcc_assert (MAX_BUILTIN_ARGS == 6);
+ gcc_unreachable ();
+ case 0:
+ pat = (void_func
+ ? GEN_FCN (icode) ()
+ : GEN_FCN (icode) (target));
+ break;
+ case 1:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0])
+ : GEN_FCN (icode) (target, op[0]));
+ break;
+ case 2:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1])
+ : GEN_FCN (icode) (target, op[0], op[1]));
+ break;
+ case 3:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2]));
+ break;
+ case 4:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]));
+ break;
+ case 5:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]));
+ break;
+ case 6:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5])
+ : GEN_FCN (icode) (target, op[0], op[1],
+ op[2], op[3], op[4], op[5]));
+ break;
+ }
+
+ if (!pat)
+ return 0;
+ emit_insn (pat);
+
+ return target;
+}
+
/* Create a builtin vector type with a name. Taking care not to give
the canonical type a name. */
^ permalink raw reply [flat|nested] 7+ messages in thread
* [gcc(refs/users/wschmidt/heads/builtins10)] rs6000: Builtin expansion, part 1
@ 2021-04-26 20:51 William Schmidt
0 siblings, 0 replies; 7+ messages in thread
From: William Schmidt @ 2021-04-26 20:51 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:38b2b1203c25fba2cfc49fd283f24e7dde83247b
commit 38b2b1203c25fba2cfc49fd283f24e7dde83247b
Author: Bill Schmidt <wschmidt@linux.ibm.com>
Date: Fri Apr 2 17:03:37 2021 -0500
rs6000: Builtin expansion, part 1
2021-04-02 Bill Schmidt <wschmidt@linux.ibm.com>
gcc/
* config/rs6000/rs6000-call.c (rs6000_expand_new_builtin): New
forward decl.
(rs6000_invalid_new_builtin): New stub function.
(rs6000_expand_builtin): Call rs6000_expand_new_builtin.
(rs6000_expand_ldst_mask): New stub function.
(new_cpu_expand_builtin): Likewise.
(elemrev_icode): Likewise.
(ldv_expand_builtin): Likewise.
(lxvrse_expand_builtin): Likewise.
(lxvrze_expand_builtin): Likewise.
(stv_expand_builtin): Likewise.
(new_mma_expand_builtin): Likewise.
(new_htm_expand_builtin): Likewise.
(rs6000_expand_new_builtin): New function.
Diff:
---
gcc/config/rs6000/rs6000-call.c | 525 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 525 insertions(+)
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index 197c611c592..d2aa64cc19d 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -190,6 +190,7 @@ static tree builtin_function_type (machine_mode, machine_mode,
static void rs6000_common_init_builtins (void);
static void htm_init_builtins (void);
static void mma_init_builtins (void);
+static rtx rs6000_expand_new_builtin (tree, rtx, rtx, machine_mode, int);
static bool rs6000_gimple_fold_new_builtin (gimple_stmt_iterator *gsi);
@@ -11552,6 +11553,14 @@ rs6000_invalid_builtin (enum rs6000_builtins fncode)
error ("%qs is not supported with the current options", name);
}
+/* Raise an error message for a builtin function that is called without the
+ appropriate target options being set. */
+
+static void
+rs6000_invalid_new_builtin (enum rs6000_gen_builtins fncode)
+{
+}
+
/* Target hook for early folding of built-ins, shamelessly stolen
from ia64.c. */
@@ -14069,6 +14078,9 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
machine_mode mode ATTRIBUTE_UNUSED,
int ignore ATTRIBUTE_UNUSED)
{
+ if (new_builtins_are_live)
+ return rs6000_expand_new_builtin (exp, target, subtarget, mode, ignore);
+
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
enum rs6000_builtins fcode
= (enum rs6000_builtins) DECL_MD_FUNCTION_CODE (fndecl);
@@ -14361,6 +14373,519 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
gcc_unreachable ();
}
+/* Expand ALTIVEC_BUILTIN_MASK_FOR_LOAD. */
+rtx
+rs6000_expand_ldst_mask (rtx target, tree arg0)
+ {
+ return target;
+ }
+
+/* Expand the CPU builtin in FCODE and store the result in TARGET. */
+static rtx
+new_cpu_expand_builtin (enum rs6000_gen_builtins fcode,
+ tree exp ATTRIBUTE_UNUSED, rtx target)
+{
+ return target;
+}
+
+static insn_code
+elemrev_icode (rs6000_gen_builtins fcode)
+{
+ return (insn_code) 0;
+}
+
+static rtx
+ldv_expand_builtin (rtx target, insn_code icode, rtx *op, machine_mode tmode)
+{
+ return target;
+}
+
+static rtx
+lxvrse_expand_builtin (rtx target, insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return target;
+}
+
+static rtx
+lxvrze_expand_builtin (rtx target, insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return target;
+}
+
+static rtx
+stv_expand_builtin (insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return NULL_RTX;
+}
+
+/* Expand the MMA built-in in EXP. */
+static rtx
+new_mma_expand_builtin (tree exp, rtx target, insn_code icode)
+{
+ return target;
+}
+
+/* Expand the HTM builtin in EXP and store the result in TARGET. */
+static rtx
+new_htm_expand_builtin (bifdata *bifaddr, rs6000_gen_builtins fcode,
+ tree exp, rtx target)
+{
+ return const0_rtx;
+}
+
+/* Expand an expression EXP that calls a built-in function,
+ with result going to TARGET if that's convenient
+ (and in mode MODE if that's convenient).
+ SUBTARGET may be used as the target for computing one of EXP's operands.
+ IGNORE is nonzero if the value is to be ignored.
+ Use the new builtin infrastructure. */
+static rtx
+rs6000_expand_new_builtin (tree exp, rtx target,
+ rtx subtarget ATTRIBUTE_UNUSED,
+ machine_mode ignore_mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
+{
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+ enum rs6000_gen_builtins fcode
+ = (enum rs6000_gen_builtins) DECL_MD_FUNCTION_CODE (fndecl);
+ size_t uns_fcode = (size_t)fcode;
+ enum insn_code icode = rs6000_builtin_info_x[uns_fcode].icode;
+
+ /* We have two different modes (KFmode, TFmode) that are the IEEE 128-bit
+ floating point type, depending on whether long double is the IBM extended
+ double (KFmode) or long double is IEEE 128-bit (TFmode). It is simpler if
+ we only define one variant of the built-in function, and switch the code
+ when defining it, rather than defining two built-ins and using the
+ overload table in rs6000-c.c to switch between the two. If we don't have
+ the proper assembler, don't do this switch because CODE_FOR_*kf* and
+ CODE_FOR_*tf* will be CODE_FOR_nothing. */
+ if (FLOAT128_IEEE_P (TFmode))
+ switch (icode)
+ {
+ default:
+ break;
+
+ case CODE_FOR_sqrtkf2_odd: icode = CODE_FOR_sqrttf2_odd; break;
+ case CODE_FOR_trunckfdf2_odd: icode = CODE_FOR_trunctfdf2_odd; break;
+ case CODE_FOR_addkf3_odd: icode = CODE_FOR_addtf3_odd; break;
+ case CODE_FOR_subkf3_odd: icode = CODE_FOR_subtf3_odd; break;
+ case CODE_FOR_mulkf3_odd: icode = CODE_FOR_multf3_odd; break;
+ case CODE_FOR_divkf3_odd: icode = CODE_FOR_divtf3_odd; break;
+ case CODE_FOR_fmakf4_odd: icode = CODE_FOR_fmatf4_odd; break;
+ case CODE_FOR_xsxexpqp_kf: icode = CODE_FOR_xsxexpqp_tf; break;
+ case CODE_FOR_xsxsigqp_kf: icode = CODE_FOR_xsxsigqp_tf; break;
+ case CODE_FOR_xststdcnegqp_kf: icode = CODE_FOR_xststdcnegqp_tf; break;
+ case CODE_FOR_xsiexpqp_kf: icode = CODE_FOR_xsiexpqp_tf; break;
+ case CODE_FOR_xsiexpqpf_kf: icode = CODE_FOR_xsiexpqpf_tf; break;
+ case CODE_FOR_xststdcqp_kf: icode = CODE_FOR_xststdcqp_tf; break;
+
+ case CODE_FOR_xscmpexpqp_eq_kf:
+ icode = CODE_FOR_xscmpexpqp_eq_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_lt_kf:
+ icode = CODE_FOR_xscmpexpqp_lt_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_gt_kf:
+ icode = CODE_FOR_xscmpexpqp_gt_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_unordered_kf:
+ icode = CODE_FOR_xscmpexpqp_unordered_tf;
+ break;
+ }
+
+ bifdata *bifaddr = &rs6000_builtin_info_x[uns_fcode];
+
+ /* In case of "#pragma target" changes, we initialize all builtins
+ but check for actual availability during expand time. For
+ invalid builtins, generate a normal call. */
+ switch (bifaddr->enable)
+ {
+ default:
+ gcc_unreachable ();
+ case ENB_ALWAYS:
+ break;
+ case ENB_P5:
+ if (!TARGET_POPCNTB)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P6:
+ if (!TARGET_CMPB)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_ALTIVEC:
+ if (!TARGET_ALTIVEC)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_CELL:
+ if (!TARGET_ALTIVEC || rs6000_cpu != PROCESSOR_CELL)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_VSX:
+ if (!TARGET_VSX)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P7:
+ if (!TARGET_POPCNTD)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P7_64:
+ if (!TARGET_POPCNTD || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P8:
+ if (!TARGET_DIRECT_MOVE)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P8V:
+ if (!TARGET_P8_VECTOR)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9:
+ if (!TARGET_MODULO)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9_64:
+ if (!TARGET_MODULO || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9V:
+ if (!TARGET_P9_VECTOR)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_IEEE128_HW:
+ if (!TARGET_FLOAT128_HW)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_DFP:
+ if (!TARGET_DFP)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_CRYPTO:
+ if (!TARGET_CRYPTO)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_HTM:
+ if (!TARGET_HTM)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P10:
+ if (!TARGET_POWER10)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P10_64:
+ if (!TARGET_POWER10 || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_MMA:
+ if (!TARGET_MMA)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ };
+
+ if (bif_is_nosoft (*bifaddr)
+ && rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT)
+ {
+ error ("%<%s%> not supported with %<-msoft-float%>",
+ bifaddr->bifname);
+ return const0_rtx;
+ }
+
+ if (bif_is_no32bit (*bifaddr) && TARGET_32BIT)
+ fatal_error (input_location,
+ "%<%s%> is not supported in 32-bit mode",
+ bifaddr->bifname);
+
+ if (bif_is_cpu (*bifaddr))
+ return new_cpu_expand_builtin (fcode, exp, target);
+
+ if (bif_is_init (*bifaddr))
+ return altivec_expand_vec_init_builtin (TREE_TYPE (exp), exp, target);
+
+ if (bif_is_set (*bifaddr))
+ return altivec_expand_vec_set_builtin (exp);
+
+ if (bif_is_extract (*bifaddr))
+ return altivec_expand_vec_ext_builtin (exp, target);
+
+ if (bif_is_predicate (*bifaddr))
+ return altivec_expand_predicate_builtin (icode, exp, target);
+
+ if (bif_is_htm (*bifaddr))
+ return new_htm_expand_builtin (bifaddr, fcode, exp, target);
+
+ rtx pat;
+ const int MAX_BUILTIN_ARGS = 6;
+ tree arg[MAX_BUILTIN_ARGS];
+ rtx op[MAX_BUILTIN_ARGS];
+ machine_mode mode[MAX_BUILTIN_ARGS + 1];
+ bool void_func = TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
+ int k;
+
+ int nargs = bifaddr->nargs;
+ gcc_assert (nargs <= MAX_BUILTIN_ARGS);
+
+ if (void_func)
+ k = 0;
+ else
+ {
+ k = 1;
+ mode[0] = insn_data[icode].operand[0].mode;
+ }
+
+ for (int i = 0; i < nargs; i++)
+ {
+ arg[i] = CALL_EXPR_ARG (exp, i);
+ if (arg[i] == error_mark_node)
+ return const0_rtx;
+ STRIP_NOPS (arg[i]);
+ op[i] = expand_normal (arg[i]);
+ /* We have a couple of pesky patterns that don't specify the mode... */
+ if (!insn_data[icode].operand[i+k].mode)
+ mode[i+k] = TARGET_64BIT ? Pmode : SImode;
+ else
+ mode[i+k] = insn_data[icode].operand[i+k].mode;
+ }
+
+ /* Check for restricted constant arguments. */
+ for (int i = 0; i < 2; i++)
+ {
+ switch (bifaddr->restr[i])
+ {
+ default:
+ case RES_NONE:
+ break;
+ case RES_BITS:
+ {
+ size_t mask = (1 << bifaddr->restr_val1[i]) - 1;
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || TREE_INT_CST_LOW (restr_arg) & ~mask)
+ {
+ error ("argument %d must be a %d-bit unsigned literal",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_RANGE:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || !IN_RANGE (tree_to_shwi (restr_arg),
+ bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be a literal between %d and %d,"
+ " inclusive",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_VAR_RANGE:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) == INTEGER_CST
+ && !IN_RANGE (tree_to_shwi (restr_arg),
+ bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be a variable or a literal "
+ "between %d and %d, inclusive",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_VALUES:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || (tree_to_shwi (restr_arg) != bifaddr->restr_val1[i]
+ && tree_to_shwi (restr_arg) != bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be either a literal %d or a "
+ "literal %d",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ }
+ }
+
+ if (bif_is_ldstmask (*bifaddr))
+ return rs6000_expand_ldst_mask (target, arg[0]);
+
+ if (bif_is_stvec (*bifaddr))
+ {
+ if (bif_is_reve (*bifaddr))
+ icode = elemrev_icode (fcode);
+ return stv_expand_builtin (icode, op, mode[0], mode[1]);
+ }
+
+ if (bif_is_ldvec (*bifaddr))
+ {
+ if (bif_is_reve (*bifaddr))
+ icode = elemrev_icode (fcode);
+ return ldv_expand_builtin (target, icode, op, mode[0]);
+ }
+
+ if (bif_is_lxvrse (*bifaddr))
+ return lxvrse_expand_builtin (target, icode, op, mode[0], mode[1]);
+
+ if (bif_is_lxvrze (*bifaddr))
+ return lxvrze_expand_builtin (target, icode, op, mode[0], mode[1]);
+
+ if (bif_is_mma (*bifaddr))
+ return new_mma_expand_builtin (exp, target, icode);
+
+ if (fcode == RS6000_BIF_PACK_IF
+ && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+ {
+ icode = CODE_FOR_packtf;
+ fcode = RS6000_BIF_PACK_TF;
+ uns_fcode = (size_t)fcode;
+ }
+ else if (fcode == RS6000_BIF_UNPACK_IF
+ && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+ {
+ icode = CODE_FOR_unpacktf;
+ fcode = RS6000_BIF_UNPACK_TF;
+ uns_fcode = (size_t)fcode;
+ }
+
+ if (TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node)
+ target = NULL_RTX;
+ else if (target == 0
+ || GET_MODE (target) != mode[0]
+ || !(*insn_data[icode].operand[0].predicate) (target, mode[0]))
+ target = gen_reg_rtx (mode[0]);
+
+ for (int i = 0; i < nargs; i++)
+ if (! (*insn_data[icode].operand[i+k].predicate) (op[i], mode[i+k]))
+ op[i] = copy_to_mode_reg (mode[i+k], op[i]);
+
+ switch (nargs)
+ {
+ default:
+ gcc_assert (MAX_BUILTIN_ARGS == 6);
+ gcc_unreachable ();
+ case 0:
+ pat = (void_func
+ ? GEN_FCN (icode) ()
+ : GEN_FCN (icode) (target));
+ break;
+ case 1:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0])
+ : GEN_FCN (icode) (target, op[0]));
+ break;
+ case 2:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1])
+ : GEN_FCN (icode) (target, op[0], op[1]));
+ break;
+ case 3:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2]));
+ break;
+ case 4:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]));
+ break;
+ case 5:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]));
+ break;
+ case 6:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5])
+ : GEN_FCN (icode) (target, op[0], op[1],
+ op[2], op[3], op[4], op[5]));
+ break;
+ }
+
+ if (!pat)
+ return 0;
+ emit_insn (pat);
+
+ return target;
+}
+
/* Create a builtin vector type with a name. Taking care not to give
the canonical type a name. */
^ permalink raw reply [flat|nested] 7+ messages in thread
* [gcc(refs/users/wschmidt/heads/builtins10)] rs6000: Builtin expansion, part 1
@ 2021-04-02 22:12 William Schmidt
0 siblings, 0 replies; 7+ messages in thread
From: William Schmidt @ 2021-04-02 22:12 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:938b3eecdd4441f5fa687f8bca6dda76d15edcf9
commit 938b3eecdd4441f5fa687f8bca6dda76d15edcf9
Author: Bill Schmidt <wschmidt@linux.ibm.com>
Date: Fri Apr 2 17:03:37 2021 -0500
rs6000: Builtin expansion, part 1
2021-04-02 Bill Schmidt <wschmidt@linux.ibm.com>
gcc/
* config/rs6000/rs6000-call.c (rs6000_expand_new_builtin): New
forward decl.
(rs6000_invalid_new_builtin): New stub function.
(rs6000_expand_builtin): Call rs6000_expand_new_builtin.
(rs6000_expand_ldst_mask): New stub function.
(new_cpu_expand_builtin): Likewise.
(elemrev_icode): Likewise.
(ldv_expand_builtin): Likewise.
(lxvrse_expand_builtin): Likewise.
(lxvrze_expand_builtin): Likewise.
(stv_expand_builtin): Likewise.
(new_mma_expand_builtin): Likewise.
(new_htm_expand_builtin): Likewise.
(rs6000_expand_new_builtin): New function.
Diff:
---
gcc/config/rs6000/rs6000-call.c | 525 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 525 insertions(+)
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index 197c611c592..d2aa64cc19d 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -190,6 +190,7 @@ static tree builtin_function_type (machine_mode, machine_mode,
static void rs6000_common_init_builtins (void);
static void htm_init_builtins (void);
static void mma_init_builtins (void);
+static rtx rs6000_expand_new_builtin (tree, rtx, rtx, machine_mode, int);
static bool rs6000_gimple_fold_new_builtin (gimple_stmt_iterator *gsi);
@@ -11552,6 +11553,14 @@ rs6000_invalid_builtin (enum rs6000_builtins fncode)
error ("%qs is not supported with the current options", name);
}
+/* Raise an error message for a builtin function that is called without the
+ appropriate target options being set. */
+
+static void
+rs6000_invalid_new_builtin (enum rs6000_gen_builtins fncode)
+{
+}
+
/* Target hook for early folding of built-ins, shamelessly stolen
from ia64.c. */
@@ -14069,6 +14078,9 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
machine_mode mode ATTRIBUTE_UNUSED,
int ignore ATTRIBUTE_UNUSED)
{
+ if (new_builtins_are_live)
+ return rs6000_expand_new_builtin (exp, target, subtarget, mode, ignore);
+
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
enum rs6000_builtins fcode
= (enum rs6000_builtins) DECL_MD_FUNCTION_CODE (fndecl);
@@ -14361,6 +14373,519 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
gcc_unreachable ();
}
+/* Expand ALTIVEC_BUILTIN_MASK_FOR_LOAD. */
+rtx
+rs6000_expand_ldst_mask (rtx target, tree arg0)
+ {
+ return target;
+ }
+
+/* Expand the CPU builtin in FCODE and store the result in TARGET. */
+static rtx
+new_cpu_expand_builtin (enum rs6000_gen_builtins fcode,
+ tree exp ATTRIBUTE_UNUSED, rtx target)
+{
+ return target;
+}
+
+static insn_code
+elemrev_icode (rs6000_gen_builtins fcode)
+{
+ return (insn_code) 0;
+}
+
+static rtx
+ldv_expand_builtin (rtx target, insn_code icode, rtx *op, machine_mode tmode)
+{
+ return target;
+}
+
+static rtx
+lxvrse_expand_builtin (rtx target, insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return target;
+}
+
+static rtx
+lxvrze_expand_builtin (rtx target, insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return target;
+}
+
+static rtx
+stv_expand_builtin (insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return NULL_RTX;
+}
+
+/* Expand the MMA built-in in EXP. */
+static rtx
+new_mma_expand_builtin (tree exp, rtx target, insn_code icode)
+{
+ return target;
+}
+
+/* Expand the HTM builtin in EXP and store the result in TARGET. */
+static rtx
+new_htm_expand_builtin (bifdata *bifaddr, rs6000_gen_builtins fcode,
+ tree exp, rtx target)
+{
+ return const0_rtx;
+}
+
+/* Expand an expression EXP that calls a built-in function,
+ with result going to TARGET if that's convenient
+ (and in mode MODE if that's convenient).
+ SUBTARGET may be used as the target for computing one of EXP's operands.
+ IGNORE is nonzero if the value is to be ignored.
+ Use the new builtin infrastructure. */
+static rtx
+rs6000_expand_new_builtin (tree exp, rtx target,
+ rtx subtarget ATTRIBUTE_UNUSED,
+ machine_mode ignore_mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
+{
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+ enum rs6000_gen_builtins fcode
+ = (enum rs6000_gen_builtins) DECL_MD_FUNCTION_CODE (fndecl);
+ size_t uns_fcode = (size_t)fcode;
+ enum insn_code icode = rs6000_builtin_info_x[uns_fcode].icode;
+
+ /* We have two different modes (KFmode, TFmode) that are the IEEE 128-bit
+ floating point type, depending on whether long double is the IBM extended
+ double (KFmode) or long double is IEEE 128-bit (TFmode). It is simpler if
+ we only define one variant of the built-in function, and switch the code
+ when defining it, rather than defining two built-ins and using the
+ overload table in rs6000-c.c to switch between the two. If we don't have
+ the proper assembler, don't do this switch because CODE_FOR_*kf* and
+ CODE_FOR_*tf* will be CODE_FOR_nothing. */
+ if (FLOAT128_IEEE_P (TFmode))
+ switch (icode)
+ {
+ default:
+ break;
+
+ case CODE_FOR_sqrtkf2_odd: icode = CODE_FOR_sqrttf2_odd; break;
+ case CODE_FOR_trunckfdf2_odd: icode = CODE_FOR_trunctfdf2_odd; break;
+ case CODE_FOR_addkf3_odd: icode = CODE_FOR_addtf3_odd; break;
+ case CODE_FOR_subkf3_odd: icode = CODE_FOR_subtf3_odd; break;
+ case CODE_FOR_mulkf3_odd: icode = CODE_FOR_multf3_odd; break;
+ case CODE_FOR_divkf3_odd: icode = CODE_FOR_divtf3_odd; break;
+ case CODE_FOR_fmakf4_odd: icode = CODE_FOR_fmatf4_odd; break;
+ case CODE_FOR_xsxexpqp_kf: icode = CODE_FOR_xsxexpqp_tf; break;
+ case CODE_FOR_xsxsigqp_kf: icode = CODE_FOR_xsxsigqp_tf; break;
+ case CODE_FOR_xststdcnegqp_kf: icode = CODE_FOR_xststdcnegqp_tf; break;
+ case CODE_FOR_xsiexpqp_kf: icode = CODE_FOR_xsiexpqp_tf; break;
+ case CODE_FOR_xsiexpqpf_kf: icode = CODE_FOR_xsiexpqpf_tf; break;
+ case CODE_FOR_xststdcqp_kf: icode = CODE_FOR_xststdcqp_tf; break;
+
+ case CODE_FOR_xscmpexpqp_eq_kf:
+ icode = CODE_FOR_xscmpexpqp_eq_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_lt_kf:
+ icode = CODE_FOR_xscmpexpqp_lt_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_gt_kf:
+ icode = CODE_FOR_xscmpexpqp_gt_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_unordered_kf:
+ icode = CODE_FOR_xscmpexpqp_unordered_tf;
+ break;
+ }
+
+ bifdata *bifaddr = &rs6000_builtin_info_x[uns_fcode];
+
+ /* In case of "#pragma target" changes, we initialize all builtins
+ but check for actual availability during expand time. For
+ invalid builtins, generate a normal call. */
+ switch (bifaddr->enable)
+ {
+ default:
+ gcc_unreachable ();
+ case ENB_ALWAYS:
+ break;
+ case ENB_P5:
+ if (!TARGET_POPCNTB)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P6:
+ if (!TARGET_CMPB)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_ALTIVEC:
+ if (!TARGET_ALTIVEC)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_CELL:
+ if (!TARGET_ALTIVEC || rs6000_cpu != PROCESSOR_CELL)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_VSX:
+ if (!TARGET_VSX)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P7:
+ if (!TARGET_POPCNTD)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P7_64:
+ if (!TARGET_POPCNTD || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P8:
+ if (!TARGET_DIRECT_MOVE)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P8V:
+ if (!TARGET_P8_VECTOR)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9:
+ if (!TARGET_MODULO)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9_64:
+ if (!TARGET_MODULO || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9V:
+ if (!TARGET_P9_VECTOR)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_IEEE128_HW:
+ if (!TARGET_FLOAT128_HW)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_DFP:
+ if (!TARGET_DFP)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_CRYPTO:
+ if (!TARGET_CRYPTO)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_HTM:
+ if (!TARGET_HTM)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P10:
+ if (!TARGET_POWER10)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P10_64:
+ if (!TARGET_POWER10 || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_MMA:
+ if (!TARGET_MMA)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ };
+
+ if (bif_is_nosoft (*bifaddr)
+ && rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT)
+ {
+ error ("%<%s%> not supported with %<-msoft-float%>",
+ bifaddr->bifname);
+ return const0_rtx;
+ }
+
+ if (bif_is_no32bit (*bifaddr) && TARGET_32BIT)
+ fatal_error (input_location,
+ "%<%s%> is not supported in 32-bit mode",
+ bifaddr->bifname);
+
+ if (bif_is_cpu (*bifaddr))
+ return new_cpu_expand_builtin (fcode, exp, target);
+
+ if (bif_is_init (*bifaddr))
+ return altivec_expand_vec_init_builtin (TREE_TYPE (exp), exp, target);
+
+ if (bif_is_set (*bifaddr))
+ return altivec_expand_vec_set_builtin (exp);
+
+ if (bif_is_extract (*bifaddr))
+ return altivec_expand_vec_ext_builtin (exp, target);
+
+ if (bif_is_predicate (*bifaddr))
+ return altivec_expand_predicate_builtin (icode, exp, target);
+
+ if (bif_is_htm (*bifaddr))
+ return new_htm_expand_builtin (bifaddr, fcode, exp, target);
+
+ rtx pat;
+ const int MAX_BUILTIN_ARGS = 6;
+ tree arg[MAX_BUILTIN_ARGS];
+ rtx op[MAX_BUILTIN_ARGS];
+ machine_mode mode[MAX_BUILTIN_ARGS + 1];
+ bool void_func = TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
+ int k;
+
+ int nargs = bifaddr->nargs;
+ gcc_assert (nargs <= MAX_BUILTIN_ARGS);
+
+ if (void_func)
+ k = 0;
+ else
+ {
+ k = 1;
+ mode[0] = insn_data[icode].operand[0].mode;
+ }
+
+ for (int i = 0; i < nargs; i++)
+ {
+ arg[i] = CALL_EXPR_ARG (exp, i);
+ if (arg[i] == error_mark_node)
+ return const0_rtx;
+ STRIP_NOPS (arg[i]);
+ op[i] = expand_normal (arg[i]);
+ /* We have a couple of pesky patterns that don't specify the mode... */
+ if (!insn_data[icode].operand[i+k].mode)
+ mode[i+k] = TARGET_64BIT ? Pmode : SImode;
+ else
+ mode[i+k] = insn_data[icode].operand[i+k].mode;
+ }
+
+ /* Check for restricted constant arguments. */
+ for (int i = 0; i < 2; i++)
+ {
+ switch (bifaddr->restr[i])
+ {
+ default:
+ case RES_NONE:
+ break;
+ case RES_BITS:
+ {
+ size_t mask = (1 << bifaddr->restr_val1[i]) - 1;
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || TREE_INT_CST_LOW (restr_arg) & ~mask)
+ {
+ error ("argument %d must be a %d-bit unsigned literal",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_RANGE:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || !IN_RANGE (tree_to_shwi (restr_arg),
+ bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be a literal between %d and %d,"
+ " inclusive",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_VAR_RANGE:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) == INTEGER_CST
+ && !IN_RANGE (tree_to_shwi (restr_arg),
+ bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be a variable or a literal "
+ "between %d and %d, inclusive",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_VALUES:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || (tree_to_shwi (restr_arg) != bifaddr->restr_val1[i]
+ && tree_to_shwi (restr_arg) != bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be either a literal %d or a "
+ "literal %d",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ }
+ }
+
+ if (bif_is_ldstmask (*bifaddr))
+ return rs6000_expand_ldst_mask (target, arg[0]);
+
+ if (bif_is_stvec (*bifaddr))
+ {
+ if (bif_is_reve (*bifaddr))
+ icode = elemrev_icode (fcode);
+ return stv_expand_builtin (icode, op, mode[0], mode[1]);
+ }
+
+ if (bif_is_ldvec (*bifaddr))
+ {
+ if (bif_is_reve (*bifaddr))
+ icode = elemrev_icode (fcode);
+ return ldv_expand_builtin (target, icode, op, mode[0]);
+ }
+
+ if (bif_is_lxvrse (*bifaddr))
+ return lxvrse_expand_builtin (target, icode, op, mode[0], mode[1]);
+
+ if (bif_is_lxvrze (*bifaddr))
+ return lxvrze_expand_builtin (target, icode, op, mode[0], mode[1]);
+
+ if (bif_is_mma (*bifaddr))
+ return new_mma_expand_builtin (exp, target, icode);
+
+ if (fcode == RS6000_BIF_PACK_IF
+ && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+ {
+ icode = CODE_FOR_packtf;
+ fcode = RS6000_BIF_PACK_TF;
+ uns_fcode = (size_t)fcode;
+ }
+ else if (fcode == RS6000_BIF_UNPACK_IF
+ && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+ {
+ icode = CODE_FOR_unpacktf;
+ fcode = RS6000_BIF_UNPACK_TF;
+ uns_fcode = (size_t)fcode;
+ }
+
+ if (TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node)
+ target = NULL_RTX;
+ else if (target == 0
+ || GET_MODE (target) != mode[0]
+ || !(*insn_data[icode].operand[0].predicate) (target, mode[0]))
+ target = gen_reg_rtx (mode[0]);
+
+ for (int i = 0; i < nargs; i++)
+ if (! (*insn_data[icode].operand[i+k].predicate) (op[i], mode[i+k]))
+ op[i] = copy_to_mode_reg (mode[i+k], op[i]);
+
+ switch (nargs)
+ {
+ default:
+ gcc_assert (MAX_BUILTIN_ARGS == 6);
+ gcc_unreachable ();
+ case 0:
+ pat = (void_func
+ ? GEN_FCN (icode) ()
+ : GEN_FCN (icode) (target));
+ break;
+ case 1:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0])
+ : GEN_FCN (icode) (target, op[0]));
+ break;
+ case 2:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1])
+ : GEN_FCN (icode) (target, op[0], op[1]));
+ break;
+ case 3:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2]));
+ break;
+ case 4:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]));
+ break;
+ case 5:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]));
+ break;
+ case 6:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5])
+ : GEN_FCN (icode) (target, op[0], op[1],
+ op[2], op[3], op[4], op[5]));
+ break;
+ }
+
+ if (!pat)
+ return 0;
+ emit_insn (pat);
+
+ return target;
+}
+
/* Create a builtin vector type with a name. Taking care not to give
the canonical type a name. */
^ permalink raw reply [flat|nested] 7+ messages in thread
* [gcc(refs/users/wschmidt/heads/builtins10)] rs6000: Builtin expansion, part 1
@ 2021-04-01 19:50 William Schmidt
0 siblings, 0 replies; 7+ messages in thread
From: William Schmidt @ 2021-04-01 19:50 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:cfa84acd1211a9bb1f4aa1969640c8961a2cdb12
commit cfa84acd1211a9bb1f4aa1969640c8961a2cdb12
Author: Bill Schmidt <wschmidt@linux.ibm.com>
Date: Wed Mar 24 18:09:22 2021 -0500
rs6000: Builtin expansion, part 1
The expansion support for built-ins is completely rewritten. This patch
contains the main function and stubs out other functions it depends on.
2021-03-24 Bill Schmidt <wschmidt@linux.ibm.com>
gcc/
* config/rs6000/rs6000-call.c (rs6000_expand_new_builtin): New
forward decl.
(rs6000_invalid_new_builtin): New stub function.
(rs6000_expand_builtin): Call rs6000_expand_new_builtin; add
comment suggesting fix for an old issue.
(rs6000_expand_ldst_mask): New stub function.
(new_cpu_expand_builtin): Likewise.
(elemrev_icode): Likewise.
(ldv_expand_builtin): Likewise.
(lxvrse_expand_builtin): Likewise.
(lxvrze_expand_builtin): Likewise.
(stv_expand_builtin): Likewise.
(new_mma_expand_builtin): Likewise.
(new_htm_expand_builtin): Likewise.
(rs6000_expand_new_builtin): New function.
Diff:
---
gcc/config/rs6000/rs6000-call.c | 529 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 527 insertions(+), 2 deletions(-)
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index 197c611c592..c6d954bec78 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -190,6 +190,7 @@ static tree builtin_function_type (machine_mode, machine_mode,
static void rs6000_common_init_builtins (void);
static void htm_init_builtins (void);
static void mma_init_builtins (void);
+static rtx rs6000_expand_new_builtin (tree, rtx, rtx, machine_mode, int);
static bool rs6000_gimple_fold_new_builtin (gimple_stmt_iterator *gsi);
@@ -11552,6 +11553,14 @@ rs6000_invalid_builtin (enum rs6000_builtins fncode)
error ("%qs is not supported with the current options", name);
}
+/* Raise an error message for a builtin function that is called without the
+ appropriate target options being set. */
+
+static void
+rs6000_invalid_new_builtin (enum rs6000_gen_builtins fncode)
+{
+}
+
/* Target hook for early folding of built-ins, shamelessly stolen
from ia64.c. */
@@ -14069,6 +14078,9 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
machine_mode mode ATTRIBUTE_UNUSED,
int ignore ATTRIBUTE_UNUSED)
{
+ if (new_builtins_are_live)
+ return rs6000_expand_new_builtin (exp, target, subtarget, mode, ignore);
+
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
enum rs6000_builtins fcode
= (enum rs6000_builtins) DECL_MD_FUNCTION_CODE (fndecl);
@@ -14265,8 +14277,8 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
case ALTIVEC_BUILTIN_VCFSX:
case ALTIVEC_BUILTIN_VCTUXS:
case ALTIVEC_BUILTIN_VCTSXS:
- /* FIXME: There's got to be a nicer way to handle this case than
- constructing a new CALL_EXPR. */
+ /* FIXME: There's got to be a nicer way to handle this case than
+ constructing a new CALL_EXPR. */
if (call_expr_nargs (exp) == 1)
{
exp = build_call_nary (TREE_TYPE (exp), CALL_EXPR_FN (exp),
@@ -14361,6 +14373,519 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
gcc_unreachable ();
}
+/* Expand ALTIVEC_BUILTIN_MASK_FOR_LOAD. */
+rtx
+rs6000_expand_ldst_mask (rtx target, tree arg0)
+ {
+ return target;
+ }
+
+/* Expand the CPU builtin in FCODE and store the result in TARGET. */
+static rtx
+new_cpu_expand_builtin (enum rs6000_gen_builtins fcode,
+ tree exp ATTRIBUTE_UNUSED, rtx target)
+{
+ return target;
+}
+
+static insn_code
+elemrev_icode (rs6000_gen_builtins fcode)
+{
+ return (insn_code) 0;
+}
+
+static rtx
+ldv_expand_builtin (rtx target, insn_code icode, rtx *op, machine_mode tmode)
+{
+ return target;
+}
+
+static rtx
+lxvrse_expand_builtin (rtx target, insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return target;
+}
+
+static rtx
+lxvrze_expand_builtin (rtx target, insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return target;
+}
+
+static rtx
+stv_expand_builtin (insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return NULL_RTX;
+}
+
+/* Expand the MMA built-in in EXP. */
+static rtx
+new_mma_expand_builtin (tree exp, rtx target, insn_code icode)
+{
+ return target;
+}
+
+/* Expand the HTM builtin in EXP and store the result in TARGET. */
+static rtx
+new_htm_expand_builtin (bifdata *bifaddr, rs6000_gen_builtins fcode,
+ tree exp, rtx target)
+{
+ return const0_rtx;
+}
+
+/* Expand an expression EXP that calls a built-in function,
+ with result going to TARGET if that's convenient
+ (and in mode MODE if that's convenient).
+ SUBTARGET may be used as the target for computing one of EXP's operands.
+ IGNORE is nonzero if the value is to be ignored.
+ Use the new builtin infrastructure. */
+static rtx
+rs6000_expand_new_builtin (tree exp, rtx target,
+ rtx subtarget ATTRIBUTE_UNUSED,
+ machine_mode ignore_mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
+{
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+ enum rs6000_gen_builtins fcode
+ = (enum rs6000_gen_builtins) DECL_MD_FUNCTION_CODE (fndecl);
+ size_t uns_fcode = (size_t)fcode;
+ enum insn_code icode = rs6000_builtin_info_x[uns_fcode].icode;
+
+ /* We have two different modes (KFmode, TFmode) that are the IEEE 128-bit
+ floating point type, depending on whether long double is the IBM extended
+ double (KFmode) or long double is IEEE 128-bit (TFmode). It is simpler if
+ we only define one variant of the built-in function, and switch the code
+ when defining it, rather than defining two built-ins and using the
+ overload table in rs6000-c.c to switch between the two. If we don't have
+ the proper assembler, don't do this switch because CODE_FOR_*kf* and
+ CODE_FOR_*tf* will be CODE_FOR_nothing. */
+ if (FLOAT128_IEEE_P (TFmode))
+ switch (icode)
+ {
+ default:
+ break;
+
+ case CODE_FOR_sqrtkf2_odd: icode = CODE_FOR_sqrttf2_odd; break;
+ case CODE_FOR_trunckfdf2_odd: icode = CODE_FOR_trunctfdf2_odd; break;
+ case CODE_FOR_addkf3_odd: icode = CODE_FOR_addtf3_odd; break;
+ case CODE_FOR_subkf3_odd: icode = CODE_FOR_subtf3_odd; break;
+ case CODE_FOR_mulkf3_odd: icode = CODE_FOR_multf3_odd; break;
+ case CODE_FOR_divkf3_odd: icode = CODE_FOR_divtf3_odd; break;
+ case CODE_FOR_fmakf4_odd: icode = CODE_FOR_fmatf4_odd; break;
+ case CODE_FOR_xsxexpqp_kf: icode = CODE_FOR_xsxexpqp_tf; break;
+ case CODE_FOR_xsxsigqp_kf: icode = CODE_FOR_xsxsigqp_tf; break;
+ case CODE_FOR_xststdcnegqp_kf: icode = CODE_FOR_xststdcnegqp_tf; break;
+ case CODE_FOR_xsiexpqp_kf: icode = CODE_FOR_xsiexpqp_tf; break;
+ case CODE_FOR_xsiexpqpf_kf: icode = CODE_FOR_xsiexpqpf_tf; break;
+ case CODE_FOR_xststdcqp_kf: icode = CODE_FOR_xststdcqp_tf; break;
+
+ case CODE_FOR_xscmpexpqp_eq_kf:
+ icode = CODE_FOR_xscmpexpqp_eq_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_lt_kf:
+ icode = CODE_FOR_xscmpexpqp_lt_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_gt_kf:
+ icode = CODE_FOR_xscmpexpqp_gt_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_unordered_kf:
+ icode = CODE_FOR_xscmpexpqp_unordered_tf;
+ break;
+ }
+
+ bifdata *bifaddr = &rs6000_builtin_info_x[uns_fcode];
+
+ /* In case of "#pragma target" changes, we initialize all builtins
+ but check for actual availability during expand time. For
+ invalid builtins, generate a normal call. */
+ switch (bifaddr->enable)
+ {
+ default:
+ gcc_unreachable ();
+ case ENB_ALWAYS:
+ break;
+ case ENB_P5:
+ if (!TARGET_POPCNTB)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P6:
+ if (!TARGET_CMPB)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_ALTIVEC:
+ if (!TARGET_ALTIVEC)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_CELL:
+ if (!TARGET_ALTIVEC || rs6000_cpu != PROCESSOR_CELL)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_VSX:
+ if (!TARGET_VSX)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P7:
+ if (!TARGET_POPCNTD)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P7_64:
+ if (!TARGET_POPCNTD || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P8:
+ if (!TARGET_DIRECT_MOVE)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P8V:
+ if (!TARGET_P8_VECTOR)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9:
+ if (!TARGET_MODULO)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9_64:
+ if (!TARGET_MODULO || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9V:
+ if (!TARGET_P9_VECTOR)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_IEEE128_HW:
+ if (!TARGET_FLOAT128_HW)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_DFP:
+ if (!TARGET_DFP)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_CRYPTO:
+ if (!TARGET_CRYPTO)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_HTM:
+ if (!TARGET_HTM)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P10:
+ if (!TARGET_POWER10)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P10_64:
+ if (!TARGET_POWER10 || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_MMA:
+ if (!TARGET_MMA)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ };
+
+ if (bif_is_nosoft (*bifaddr)
+ && rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT)
+ {
+ error ("%<%s%> not supported with %<-msoft-float%>",
+ bifaddr->bifname);
+ return const0_rtx;
+ }
+
+ if (bif_is_no32bit (*bifaddr) && TARGET_32BIT)
+ fatal_error (input_location,
+ "%<%s%> is not supported in 32-bit mode",
+ bifaddr->bifname);
+
+ if (bif_is_cpu (*bifaddr))
+ return new_cpu_expand_builtin (fcode, exp, target);
+
+ if (bif_is_init (*bifaddr))
+ return altivec_expand_vec_init_builtin (TREE_TYPE (exp), exp, target);
+
+ if (bif_is_set (*bifaddr))
+ return altivec_expand_vec_set_builtin (exp);
+
+ if (bif_is_extract (*bifaddr))
+ return altivec_expand_vec_ext_builtin (exp, target);
+
+ if (bif_is_predicate (*bifaddr))
+ return altivec_expand_predicate_builtin (icode, exp, target);
+
+ if (bif_is_htm (*bifaddr))
+ return new_htm_expand_builtin (bifaddr, fcode, exp, target);
+
+ rtx pat;
+ const int MAX_BUILTIN_ARGS = 6;
+ tree arg[MAX_BUILTIN_ARGS];
+ rtx op[MAX_BUILTIN_ARGS];
+ machine_mode mode[MAX_BUILTIN_ARGS + 1];
+ bool void_func = TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
+ int k;
+
+ int nargs = bifaddr->nargs;
+ gcc_assert (nargs <= MAX_BUILTIN_ARGS);
+
+ if (void_func)
+ k = 0;
+ else
+ {
+ k = 1;
+ mode[0] = insn_data[icode].operand[0].mode;
+ }
+
+ for (int i = 0; i < nargs; i++)
+ {
+ arg[i] = CALL_EXPR_ARG (exp, i);
+ if (arg[i] == error_mark_node)
+ return const0_rtx;
+ STRIP_NOPS (arg[i]);
+ op[i] = expand_normal (arg[i]);
+ /* We have a couple of pesky patterns that don't specify the mode... */
+ if (!insn_data[icode].operand[i+k].mode)
+ mode[i+k] = TARGET_64BIT ? Pmode : SImode;
+ else
+ mode[i+k] = insn_data[icode].operand[i+k].mode;
+ }
+
+ /* Check for restricted constant arguments. */
+ for (int i = 0; i < 2; i++)
+ {
+ switch (bifaddr->restr[i])
+ {
+ default:
+ case RES_NONE:
+ break;
+ case RES_BITS:
+ {
+ size_t mask = (1 << bifaddr->restr_val1[i]) - 1;
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || TREE_INT_CST_LOW (restr_arg) & ~mask)
+ {
+ error ("argument %d must be a %d-bit unsigned literal",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_RANGE:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || !IN_RANGE (tree_to_shwi (restr_arg),
+ bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be a literal between %d and %d,"
+ " inclusive",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_VAR_RANGE:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) == INTEGER_CST
+ && !IN_RANGE (tree_to_shwi (restr_arg),
+ bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be a variable or a literal "
+ "between %d and %d, inclusive",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_VALUES:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || (tree_to_shwi (restr_arg) != bifaddr->restr_val1[i]
+ && tree_to_shwi (restr_arg) != bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be either a literal %d or a "
+ "literal %d",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ }
+ }
+
+ if (bif_is_ldstmask (*bifaddr))
+ return rs6000_expand_ldst_mask (target, arg[0]);
+
+ if (bif_is_stvec (*bifaddr))
+ {
+ if (bif_is_reve (*bifaddr))
+ icode = elemrev_icode (fcode);
+ return stv_expand_builtin (icode, op, mode[0], mode[1]);
+ }
+
+ if (bif_is_ldvec (*bifaddr))
+ {
+ if (bif_is_reve (*bifaddr))
+ icode = elemrev_icode (fcode);
+ return ldv_expand_builtin (target, icode, op, mode[0]);
+ }
+
+ if (bif_is_lxvrse (*bifaddr))
+ return lxvrse_expand_builtin (target, icode, op, mode[0], mode[1]);
+
+ if (bif_is_lxvrze (*bifaddr))
+ return lxvrze_expand_builtin (target, icode, op, mode[0], mode[1]);
+
+ if (bif_is_mma (*bifaddr))
+ return new_mma_expand_builtin (exp, target, icode);
+
+ if (fcode == RS6000_BIF_PACK_IF
+ && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+ {
+ icode = CODE_FOR_packtf;
+ fcode = RS6000_BIF_PACK_TF;
+ uns_fcode = (size_t)fcode;
+ }
+ else if (fcode == RS6000_BIF_UNPACK_IF
+ && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+ {
+ icode = CODE_FOR_unpacktf;
+ fcode = RS6000_BIF_UNPACK_TF;
+ uns_fcode = (size_t)fcode;
+ }
+
+ if (TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node)
+ target = NULL_RTX;
+ else if (target == 0
+ || GET_MODE (target) != mode[0]
+ || !(*insn_data[icode].operand[0].predicate) (target, mode[0]))
+ target = gen_reg_rtx (mode[0]);
+
+ for (int i = 0; i < nargs; i++)
+ if (! (*insn_data[icode].operand[i+k].predicate) (op[i], mode[i+k]))
+ op[i] = copy_to_mode_reg (mode[i+k], op[i]);
+
+ switch (nargs)
+ {
+ default:
+ gcc_assert (MAX_BUILTIN_ARGS == 6);
+ gcc_unreachable ();
+ case 0:
+ pat = (void_func
+ ? GEN_FCN (icode) ()
+ : GEN_FCN (icode) (target));
+ break;
+ case 1:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0])
+ : GEN_FCN (icode) (target, op[0]));
+ break;
+ case 2:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1])
+ : GEN_FCN (icode) (target, op[0], op[1]));
+ break;
+ case 3:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2]));
+ break;
+ case 4:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]));
+ break;
+ case 5:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]));
+ break;
+ case 6:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5])
+ : GEN_FCN (icode) (target, op[0], op[1],
+ op[2], op[3], op[4], op[5]));
+ break;
+ }
+
+ if (!pat)
+ return 0;
+ emit_insn (pat);
+
+ return target;
+}
+
/* Create a builtin vector type with a name. Taking care not to give
the canonical type a name. */
^ permalink raw reply [flat|nested] 7+ messages in thread
* [gcc(refs/users/wschmidt/heads/builtins10)] rs6000: Builtin expansion, part 1
@ 2021-03-25 15:48 William Schmidt
0 siblings, 0 replies; 7+ messages in thread
From: William Schmidt @ 2021-03-25 15:48 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:1a0667a23c86c6524bcb97a0b1be0504b64a02c6
commit 1a0667a23c86c6524bcb97a0b1be0504b64a02c6
Author: Bill Schmidt <wschmidt@linux.ibm.com>
Date: Wed Mar 24 18:09:22 2021 -0500
rs6000: Builtin expansion, part 1
The expansion support for built-ins is completely rewritten. This patch
contains the main function and stubs out other functions it depends on.
2021-03-24 Bill Schmidt <wschmidt@linux.ibm.com>
gcc/
* config/rs6000/rs6000-call.c (rs6000_expand_new_builtin): New
forward decl.
(rs6000_invalid_new_builtin): New stub function.
(rs6000_expand_builtin): Call rs6000_expand_new_builtin; add
comment suggesting fix for an old issue.
(rs6000_expand_ldst_mask): New stub function.
(new_cpu_expand_builtin): Likewise.
(elemrev_icode): Likewise.
(ldv_expand_builtin): Likewise.
(lxvrse_expand_builtin): Likewise.
(lxvrze_expand_builtin): Likewise.
(stv_expand_builtin): Likewise.
(new_mma_expand_builtin): Likewise.
(new_htm_expand_builtin): Likewise.
(rs6000_expand_new_builtin): New function.
Diff:
---
gcc/config/rs6000/rs6000-call.c | 529 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 527 insertions(+), 2 deletions(-)
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index 197c611c592..c6d954bec78 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -190,6 +190,7 @@ static tree builtin_function_type (machine_mode, machine_mode,
static void rs6000_common_init_builtins (void);
static void htm_init_builtins (void);
static void mma_init_builtins (void);
+static rtx rs6000_expand_new_builtin (tree, rtx, rtx, machine_mode, int);
static bool rs6000_gimple_fold_new_builtin (gimple_stmt_iterator *gsi);
@@ -11552,6 +11553,14 @@ rs6000_invalid_builtin (enum rs6000_builtins fncode)
error ("%qs is not supported with the current options", name);
}
+/* Raise an error message for a builtin function that is called without the
+ appropriate target options being set. */
+
+static void
+rs6000_invalid_new_builtin (enum rs6000_gen_builtins fncode)
+{
+}
+
/* Target hook for early folding of built-ins, shamelessly stolen
from ia64.c. */
@@ -14069,6 +14078,9 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
machine_mode mode ATTRIBUTE_UNUSED,
int ignore ATTRIBUTE_UNUSED)
{
+ if (new_builtins_are_live)
+ return rs6000_expand_new_builtin (exp, target, subtarget, mode, ignore);
+
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
enum rs6000_builtins fcode
= (enum rs6000_builtins) DECL_MD_FUNCTION_CODE (fndecl);
@@ -14265,8 +14277,8 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
case ALTIVEC_BUILTIN_VCFSX:
case ALTIVEC_BUILTIN_VCTUXS:
case ALTIVEC_BUILTIN_VCTSXS:
- /* FIXME: There's got to be a nicer way to handle this case than
- constructing a new CALL_EXPR. */
+ /* FIXME: There's got to be a nicer way to handle this case than
+ constructing a new CALL_EXPR. */
if (call_expr_nargs (exp) == 1)
{
exp = build_call_nary (TREE_TYPE (exp), CALL_EXPR_FN (exp),
@@ -14361,6 +14373,519 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
gcc_unreachable ();
}
+/* Expand ALTIVEC_BUILTIN_MASK_FOR_LOAD. */
+rtx
+rs6000_expand_ldst_mask (rtx target, tree arg0)
+ {
+ return target;
+ }
+
+/* Expand the CPU builtin in FCODE and store the result in TARGET. */
+static rtx
+new_cpu_expand_builtin (enum rs6000_gen_builtins fcode,
+ tree exp ATTRIBUTE_UNUSED, rtx target)
+{
+ return target;
+}
+
+static insn_code
+elemrev_icode (rs6000_gen_builtins fcode)
+{
+ return (insn_code) 0;
+}
+
+static rtx
+ldv_expand_builtin (rtx target, insn_code icode, rtx *op, machine_mode tmode)
+{
+ return target;
+}
+
+static rtx
+lxvrse_expand_builtin (rtx target, insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return target;
+}
+
+static rtx
+lxvrze_expand_builtin (rtx target, insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return target;
+}
+
+static rtx
+stv_expand_builtin (insn_code icode, rtx *op,
+ machine_mode tmode, machine_mode smode)
+{
+ return NULL_RTX;
+}
+
+/* Expand the MMA built-in in EXP. */
+static rtx
+new_mma_expand_builtin (tree exp, rtx target, insn_code icode)
+{
+ return target;
+}
+
+/* Expand the HTM builtin in EXP and store the result in TARGET. */
+static rtx
+new_htm_expand_builtin (bifdata *bifaddr, rs6000_gen_builtins fcode,
+ tree exp, rtx target)
+{
+ return const0_rtx;
+}
+
+/* Expand an expression EXP that calls a built-in function,
+ with result going to TARGET if that's convenient
+ (and in mode MODE if that's convenient).
+ SUBTARGET may be used as the target for computing one of EXP's operands.
+ IGNORE is nonzero if the value is to be ignored.
+ Use the new builtin infrastructure. */
+static rtx
+rs6000_expand_new_builtin (tree exp, rtx target,
+ rtx subtarget ATTRIBUTE_UNUSED,
+ machine_mode ignore_mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
+{
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+ enum rs6000_gen_builtins fcode
+ = (enum rs6000_gen_builtins) DECL_MD_FUNCTION_CODE (fndecl);
+ size_t uns_fcode = (size_t)fcode;
+ enum insn_code icode = rs6000_builtin_info_x[uns_fcode].icode;
+
+ /* We have two different modes (KFmode, TFmode) that are the IEEE 128-bit
+ floating point type, depending on whether long double is the IBM extended
+ double (KFmode) or long double is IEEE 128-bit (TFmode). It is simpler if
+ we only define one variant of the built-in function, and switch the code
+ when defining it, rather than defining two built-ins and using the
+ overload table in rs6000-c.c to switch between the two. If we don't have
+ the proper assembler, don't do this switch because CODE_FOR_*kf* and
+ CODE_FOR_*tf* will be CODE_FOR_nothing. */
+ if (FLOAT128_IEEE_P (TFmode))
+ switch (icode)
+ {
+ default:
+ break;
+
+ case CODE_FOR_sqrtkf2_odd: icode = CODE_FOR_sqrttf2_odd; break;
+ case CODE_FOR_trunckfdf2_odd: icode = CODE_FOR_trunctfdf2_odd; break;
+ case CODE_FOR_addkf3_odd: icode = CODE_FOR_addtf3_odd; break;
+ case CODE_FOR_subkf3_odd: icode = CODE_FOR_subtf3_odd; break;
+ case CODE_FOR_mulkf3_odd: icode = CODE_FOR_multf3_odd; break;
+ case CODE_FOR_divkf3_odd: icode = CODE_FOR_divtf3_odd; break;
+ case CODE_FOR_fmakf4_odd: icode = CODE_FOR_fmatf4_odd; break;
+ case CODE_FOR_xsxexpqp_kf: icode = CODE_FOR_xsxexpqp_tf; break;
+ case CODE_FOR_xsxsigqp_kf: icode = CODE_FOR_xsxsigqp_tf; break;
+ case CODE_FOR_xststdcnegqp_kf: icode = CODE_FOR_xststdcnegqp_tf; break;
+ case CODE_FOR_xsiexpqp_kf: icode = CODE_FOR_xsiexpqp_tf; break;
+ case CODE_FOR_xsiexpqpf_kf: icode = CODE_FOR_xsiexpqpf_tf; break;
+ case CODE_FOR_xststdcqp_kf: icode = CODE_FOR_xststdcqp_tf; break;
+
+ case CODE_FOR_xscmpexpqp_eq_kf:
+ icode = CODE_FOR_xscmpexpqp_eq_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_lt_kf:
+ icode = CODE_FOR_xscmpexpqp_lt_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_gt_kf:
+ icode = CODE_FOR_xscmpexpqp_gt_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_unordered_kf:
+ icode = CODE_FOR_xscmpexpqp_unordered_tf;
+ break;
+ }
+
+ bifdata *bifaddr = &rs6000_builtin_info_x[uns_fcode];
+
+ /* In case of "#pragma target" changes, we initialize all builtins
+ but check for actual availability during expand time. For
+ invalid builtins, generate a normal call. */
+ switch (bifaddr->enable)
+ {
+ default:
+ gcc_unreachable ();
+ case ENB_ALWAYS:
+ break;
+ case ENB_P5:
+ if (!TARGET_POPCNTB)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P6:
+ if (!TARGET_CMPB)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_ALTIVEC:
+ if (!TARGET_ALTIVEC)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_CELL:
+ if (!TARGET_ALTIVEC || rs6000_cpu != PROCESSOR_CELL)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_VSX:
+ if (!TARGET_VSX)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P7:
+ if (!TARGET_POPCNTD)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P7_64:
+ if (!TARGET_POPCNTD || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P8:
+ if (!TARGET_DIRECT_MOVE)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P8V:
+ if (!TARGET_P8_VECTOR)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9:
+ if (!TARGET_MODULO)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9_64:
+ if (!TARGET_MODULO || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P9V:
+ if (!TARGET_P9_VECTOR)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_IEEE128_HW:
+ if (!TARGET_FLOAT128_HW)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_DFP:
+ if (!TARGET_DFP)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_CRYPTO:
+ if (!TARGET_CRYPTO)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_HTM:
+ if (!TARGET_HTM)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P10:
+ if (!TARGET_POWER10)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_P10_64:
+ if (!TARGET_POWER10 || !TARGET_POWERPC64)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ case ENB_MMA:
+ if (!TARGET_MMA)
+ {
+ rs6000_invalid_new_builtin (fcode);
+ return expand_call (exp, target, ignore);
+ }
+ break;
+ };
+
+ if (bif_is_nosoft (*bifaddr)
+ && rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT)
+ {
+ error ("%<%s%> not supported with %<-msoft-float%>",
+ bifaddr->bifname);
+ return const0_rtx;
+ }
+
+ if (bif_is_no32bit (*bifaddr) && TARGET_32BIT)
+ fatal_error (input_location,
+ "%<%s%> is not supported in 32-bit mode",
+ bifaddr->bifname);
+
+ if (bif_is_cpu (*bifaddr))
+ return new_cpu_expand_builtin (fcode, exp, target);
+
+ if (bif_is_init (*bifaddr))
+ return altivec_expand_vec_init_builtin (TREE_TYPE (exp), exp, target);
+
+ if (bif_is_set (*bifaddr))
+ return altivec_expand_vec_set_builtin (exp);
+
+ if (bif_is_extract (*bifaddr))
+ return altivec_expand_vec_ext_builtin (exp, target);
+
+ if (bif_is_predicate (*bifaddr))
+ return altivec_expand_predicate_builtin (icode, exp, target);
+
+ if (bif_is_htm (*bifaddr))
+ return new_htm_expand_builtin (bifaddr, fcode, exp, target);
+
+ rtx pat;
+ const int MAX_BUILTIN_ARGS = 6;
+ tree arg[MAX_BUILTIN_ARGS];
+ rtx op[MAX_BUILTIN_ARGS];
+ machine_mode mode[MAX_BUILTIN_ARGS + 1];
+ bool void_func = TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
+ int k;
+
+ int nargs = bifaddr->nargs;
+ gcc_assert (nargs <= MAX_BUILTIN_ARGS);
+
+ if (void_func)
+ k = 0;
+ else
+ {
+ k = 1;
+ mode[0] = insn_data[icode].operand[0].mode;
+ }
+
+ for (int i = 0; i < nargs; i++)
+ {
+ arg[i] = CALL_EXPR_ARG (exp, i);
+ if (arg[i] == error_mark_node)
+ return const0_rtx;
+ STRIP_NOPS (arg[i]);
+ op[i] = expand_normal (arg[i]);
+ /* We have a couple of pesky patterns that don't specify the mode... */
+ if (!insn_data[icode].operand[i+k].mode)
+ mode[i+k] = TARGET_64BIT ? Pmode : SImode;
+ else
+ mode[i+k] = insn_data[icode].operand[i+k].mode;
+ }
+
+ /* Check for restricted constant arguments. */
+ for (int i = 0; i < 2; i++)
+ {
+ switch (bifaddr->restr[i])
+ {
+ default:
+ case RES_NONE:
+ break;
+ case RES_BITS:
+ {
+ size_t mask = (1 << bifaddr->restr_val1[i]) - 1;
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || TREE_INT_CST_LOW (restr_arg) & ~mask)
+ {
+ error ("argument %d must be a %d-bit unsigned literal",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_RANGE:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || !IN_RANGE (tree_to_shwi (restr_arg),
+ bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be a literal between %d and %d,"
+ " inclusive",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_VAR_RANGE:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) == INTEGER_CST
+ && !IN_RANGE (tree_to_shwi (restr_arg),
+ bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be a variable or a literal "
+ "between %d and %d, inclusive",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ case RES_VALUES:
+ {
+ tree restr_arg = arg[bifaddr->restr_opnd[i] - 1];
+ STRIP_NOPS (restr_arg);
+ if (TREE_CODE (restr_arg) != INTEGER_CST
+ || (tree_to_shwi (restr_arg) != bifaddr->restr_val1[i]
+ && tree_to_shwi (restr_arg) != bifaddr->restr_val2[i]))
+ {
+ error ("argument %d must be either a literal %d or a "
+ "literal %d",
+ bifaddr->restr_opnd[i], bifaddr->restr_val1[i],
+ bifaddr->restr_val2[i]);
+ return CONST0_RTX (mode[0]);
+ }
+ break;
+ }
+ }
+ }
+
+ if (bif_is_ldstmask (*bifaddr))
+ return rs6000_expand_ldst_mask (target, arg[0]);
+
+ if (bif_is_stvec (*bifaddr))
+ {
+ if (bif_is_reve (*bifaddr))
+ icode = elemrev_icode (fcode);
+ return stv_expand_builtin (icode, op, mode[0], mode[1]);
+ }
+
+ if (bif_is_ldvec (*bifaddr))
+ {
+ if (bif_is_reve (*bifaddr))
+ icode = elemrev_icode (fcode);
+ return ldv_expand_builtin (target, icode, op, mode[0]);
+ }
+
+ if (bif_is_lxvrse (*bifaddr))
+ return lxvrse_expand_builtin (target, icode, op, mode[0], mode[1]);
+
+ if (bif_is_lxvrze (*bifaddr))
+ return lxvrze_expand_builtin (target, icode, op, mode[0], mode[1]);
+
+ if (bif_is_mma (*bifaddr))
+ return new_mma_expand_builtin (exp, target, icode);
+
+ if (fcode == RS6000_BIF_PACK_IF
+ && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+ {
+ icode = CODE_FOR_packtf;
+ fcode = RS6000_BIF_PACK_TF;
+ uns_fcode = (size_t)fcode;
+ }
+ else if (fcode == RS6000_BIF_UNPACK_IF
+ && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+ {
+ icode = CODE_FOR_unpacktf;
+ fcode = RS6000_BIF_UNPACK_TF;
+ uns_fcode = (size_t)fcode;
+ }
+
+ if (TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node)
+ target = NULL_RTX;
+ else if (target == 0
+ || GET_MODE (target) != mode[0]
+ || !(*insn_data[icode].operand[0].predicate) (target, mode[0]))
+ target = gen_reg_rtx (mode[0]);
+
+ for (int i = 0; i < nargs; i++)
+ if (! (*insn_data[icode].operand[i+k].predicate) (op[i], mode[i+k]))
+ op[i] = copy_to_mode_reg (mode[i+k], op[i]);
+
+ switch (nargs)
+ {
+ default:
+ gcc_assert (MAX_BUILTIN_ARGS == 6);
+ gcc_unreachable ();
+ case 0:
+ pat = (void_func
+ ? GEN_FCN (icode) ()
+ : GEN_FCN (icode) (target));
+ break;
+ case 1:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0])
+ : GEN_FCN (icode) (target, op[0]));
+ break;
+ case 2:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1])
+ : GEN_FCN (icode) (target, op[0], op[1]));
+ break;
+ case 3:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2]));
+ break;
+ case 4:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]));
+ break;
+ case 5:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4])
+ : GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]));
+ break;
+ case 6:
+ pat = (void_func
+ ? GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5])
+ : GEN_FCN (icode) (target, op[0], op[1],
+ op[2], op[3], op[4], op[5]));
+ break;
+ }
+
+ if (!pat)
+ return 0;
+ emit_insn (pat);
+
+ return target;
+}
+
/* Create a builtin vector type with a name. Taking care not to give
the canonical type a name. */
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2021-07-29 14:46 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-25 16:18 [gcc(refs/users/wschmidt/heads/builtins10)] rs6000: Builtin expansion, part 1 William Schmidt
-- strict thread matches above, loose matches on Subject: below --
2021-07-29 14:46 William Schmidt
2021-06-15 17:19 William Schmidt
2021-04-26 20:51 William Schmidt
2021-04-02 22:12 William Schmidt
2021-04-01 19:50 William Schmidt
2021-03-25 15:48 William Schmidt
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).