From: Pan Li <pan2...@intel.com> 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 check strictly for the direct_internal_fn_supported_p, and only allows the type matches mode for ifn type tree pair. 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 (type_strictly_matches_mode_p): Add new func impl to check type strictly matches mode or not. (type_pair_strictly_matches_mode_p): Ditto but for tree type pair. (direct_internal_fn_supported_p): Add above check for the tree type 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 <pan2...@intel.com> --- gcc/internal-fn.cc | 32 +++++++++++++++++ .../g++.target/i386/pr115961-run-1.C | 34 +++++++++++++++++++ .../riscv/rvv/base/pr115961-run-1.C | 34 +++++++++++++++++++ 3 files changed, 100 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..5c21249318e 100644 --- a/gcc/internal-fn.cc +++ b/gcc/internal-fn.cc @@ -4164,6 +4164,35 @@ direct_internal_fn_optab (internal_fn fn) gcc_unreachable (); } +/* 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. */ + +static bool +type_strictly_matches_mode_p (const_tree type) +{ + 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 both the first and the second type of tree pair are + strictly matches their modes, or return false. */ + +static bool +type_pair_strictly_matches_mode_p (tree_pair type_pair) +{ + return type_strictly_matches_mode_p (type_pair.first) + && type_strictly_matches_mode_p (type_pair.second); +} + /* 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 +4202,9 @@ bool direct_internal_fn_supported_p (internal_fn fn, tree_pair types, optimization_type opt_type) { + if (!type_pair_strictly_matches_mode_p (types)) + 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" } } */ -- 2.34.1