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

Reply via email to