[email protected] writes:
> From: Pan Li <[email protected]>
>
> The direct_internal_fn_supported_p has no restrictions for the type
> modes. For example the bitfield like below will be recog as .SAT_TRUNC.
>
> struct e
> {
> unsigned pre : 12;
> unsigned a : 4;
> };
>
> __attribute__((noipa))
> void bug (e * v, unsigned def, unsigned use) {
> e & defE = *v;
> defE.a = min_u (use + 1, 0xf);
> }
>
> This patch would like to add checks for the direct_internal_fn_supported_p,
> and only allows the tree types describled by modes.
>
> The below test suites are passed for this patch:
> 1. The rv64gcv fully regression tests.
> 2. The x86 bootstrap tests.
> 3. The x86 fully regression tests.
>
> PR target/115961
>
> gcc/ChangeLog:
>
> * internal-fn.cc (mode_describle_type_precision_p): Add new func
> impl to check if mode describle the tree type.
> (direct_internal_fn_supported_p): Add above check for the first
> and second tree type of tree pair.
>
> gcc/testsuite/ChangeLog:
>
> * g++.target/i386/pr115961-run-1.C: New test.
> * g++.target/riscv/rvv/base/pr115961-run-1.C: New test.
>
> Signed-off-by: Pan Li <[email protected]>
> ---
> gcc/internal-fn.cc | 21 ++++++++++++
> .../g++.target/i386/pr115961-run-1.C | 34 +++++++++++++++++++
> .../riscv/rvv/base/pr115961-run-1.C | 34 +++++++++++++++++++
> 3 files changed, 89 insertions(+)
> create mode 100644 gcc/testsuite/g++.target/i386/pr115961-run-1.C
> create mode 100644 gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
>
> diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc
> index 95946bfd683..4dc69264a24 100644
> --- a/gcc/internal-fn.cc
> +++ b/gcc/internal-fn.cc
> @@ -4164,6 +4164,23 @@ direct_internal_fn_optab (internal_fn fn)
> gcc_unreachable ();
> }
>
> +/* Return true if the mode describes the precision of tree type, or false.
> */
> +
> +static bool
> +mode_describle_type_precision_p (const_tree type)
Bit pedantic, but it's not really just about precision. For floats
and vectors it's also about format. Maybe:
/* Return true if TYPE's mode has the same format as TYPE, and if there is
a 1:1 correspondence between the values that the mode can store and the
values that the type can store. */
And maybe my mode_describes_type_p suggestion wasn't the best,
but given that it's not just about precision, I'm not sure about
mode_describle_type_precision_p either. How about:
type_strictly_matches_mode_p
? I'm open to other suggestions.
> +{
> + if (VECTOR_TYPE_P (type))
> + return VECTOR_MODE_P (TYPE_MODE (type));
> +
> + if (INTEGRAL_TYPE_P (type))
> + return type_has_mode_precision_p (type);
> +
> + if (SCALAR_FLOAT_TYPE_P (type) || COMPLEX_FLOAT_TYPE_P (type))
> + return true;
> +
> + return false;
> +}
> +
> /* Return true if FN is supported for the types in TYPES when the
> optimization type is OPT_TYPE. The types are those associated with
> the "type0" and "type1" fields of FN's direct_internal_fn_info
> @@ -4173,6 +4190,10 @@ bool
> direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
> optimization_type opt_type)
> {
> + if (!mode_describle_type_precision_p (types.first)
> + || !mode_describle_type_precision_p (types.second))
Formatting nit: the "||" should line up with the "!".
LGTM otherwise.
Thanks,
Richard
> + return false;
> +
> switch (fn)
> {
> #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
> diff --git a/gcc/testsuite/g++.target/i386/pr115961-run-1.C
> b/gcc/testsuite/g++.target/i386/pr115961-run-1.C
> new file mode 100644
> index 00000000000..b8c8aef3b17
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/pr115961-run-1.C
> @@ -0,0 +1,34 @@
> +/* PR target/115961 */
> +/* { dg-do run } */
> +/* { dg-options "-O3 -fdump-rtl-expand-details" } */
> +
> +struct e
> +{
> + unsigned pre : 12;
> + unsigned a : 4;
> +};
> +
> +static unsigned min_u (unsigned a, unsigned b)
> +{
> + return (b < a) ? b : a;
> +}
> +
> +__attribute__((noipa))
> +void bug (e * v, unsigned def, unsigned use) {
> + e & defE = *v;
> + defE.a = min_u (use + 1, 0xf);
> +}
> +
> +__attribute__((noipa, optimize(0)))
> +int main(void)
> +{
> + e v = { 0xded, 3 };
> +
> + bug(&v, 32, 33);
> +
> + if (v.a != 0xf)
> + __builtin_abort ();
> +
> + return 0;
> +}
> +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */
> diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
> b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
> new file mode 100644
> index 00000000000..b8c8aef3b17
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
> @@ -0,0 +1,34 @@
> +/* PR target/115961 */
> +/* { dg-do run } */
> +/* { dg-options "-O3 -fdump-rtl-expand-details" } */
> +
> +struct e
> +{
> + unsigned pre : 12;
> + unsigned a : 4;
> +};
> +
> +static unsigned min_u (unsigned a, unsigned b)
> +{
> + return (b < a) ? b : a;
> +}
> +
> +__attribute__((noipa))
> +void bug (e * v, unsigned def, unsigned use) {
> + e & defE = *v;
> + defE.a = min_u (use + 1, 0xf);
> +}
> +
> +__attribute__((noipa, optimize(0)))
> +int main(void)
> +{
> + e v = { 0xded, 3 };
> +
> + bug(&v, 32, 33);
> +
> + if (v.a != 0xf)
> + __builtin_abort ();
> +
> + return 0;
> +}
> +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */