diff mbox series

[05/15] arm: [MVE intrinsics] Check immediate is a multiple in a range

Message ID 20241107091820.2010568-6-christophe.lyon@linaro.org
State New
Headers show
Series arm: [MVE intrinsics] Rework store_scatter and load_gather intrinsics | expand

Commit Message

Christophe Lyon Nov. 7, 2024, 9:18 a.m. UTC
This patch adds support to check that an immediate is a multiple of a
given value in a given range.

This will be used for instance by scatter_base to check that offset is
in +/-4*[0..127].

Unlike require_immediate_range, require_immediate_range_multiple
accepts signed range bounds to handle the above case.

gcc/ChangeLog:

	* config/arm/arm-mve-builtins.cc (report_out_of_range_multiple):
	New.
	(function_checker::require_signed_immediate): New.
	(function_checker::require_immediate_range_multiple): New.
	* config/arm/arm-mve-builtins.h
	(function_checker::require_immediate_range_multiple): New.
	(function_checker::require_signed_immediate): New.
---
 gcc/config/arm/arm-mve-builtins.cc | 60 ++++++++++++++++++++++++++++++
 gcc/config/arm/arm-mve-builtins.h  |  3 ++
 2 files changed, 63 insertions(+)
diff mbox series

Patch

diff --git a/gcc/config/arm/arm-mve-builtins.cc b/gcc/config/arm/arm-mve-builtins.cc
index 7b88ca6cce5..3b280228e66 100644
--- a/gcc/config/arm/arm-mve-builtins.cc
+++ b/gcc/config/arm/arm-mve-builtins.cc
@@ -633,6 +633,20 @@  report_out_of_range (location_t location, tree fndecl, unsigned int argno,
 	    min, max);
 }
 
+/* Report that LOCATION has a call to FNDECL in which argument ARGNO has the
+   value ACTUAL, whereas the function requires a value multiple of MULT in the
+   range [MIN, MAX].  ARGNO counts from zero.  */
+static void
+report_out_of_range_multiple (location_t location, tree fndecl,
+			      unsigned int argno,
+			      HOST_WIDE_INT actual, HOST_WIDE_INT min,
+			      HOST_WIDE_INT max, HOST_WIDE_INT mult)
+{
+  error_at (location, "passing %wd to argument %d of %qE, which expects"
+	    " a value multiple of %wd in the range [%wd, %wd]", actual,
+	    argno + 1, fndecl, mult, min, max);
+}
+
 /* Report that LOCATION has a call to FNDECL in which argument ARGNO has
    the value ACTUAL, whereas the function requires a valid value of
    enum type ENUMTYPE.  ARGNO counts from zero.  */
@@ -1977,6 +1991,26 @@  function_checker::require_immediate (unsigned int argno,
   return true;
 }
 
+/* Check that argument ARGNO is a signed integer constant expression and store
+   its value in VALUE_OUT if so.  The caller should first check that argument
+   ARGNO exists.  */
+bool
+function_checker::require_signed_immediate (unsigned int argno,
+					    HOST_WIDE_INT &value_out)
+{
+  gcc_assert (argno < m_nargs);
+  tree arg = m_args[argno];
+
+  if (!tree_fits_shwi_p (arg))
+    {
+      report_non_ice (location, fndecl, argno);
+      return false;
+    }
+
+  value_out = tree_to_shwi (arg);
+  return true;
+}
+
 /* Check that argument REL_ARGNO is an integer constant expression that has
    a valid value for enumeration type TYPE.  REL_ARGNO counts from the end
    of the predication arguments.  */
@@ -2064,6 +2098,32 @@  function_checker::require_immediate_range (unsigned int rel_argno,
   return true;
 }
 
+/* Check that argument REL_ARGNO is a signed integer constant expression in the
+   range [MIN, MAX].  Also check that REL_ARGNO is a multiple of MULT.  */
+bool
+function_checker::require_immediate_range_multiple (unsigned int rel_argno,
+						    HOST_WIDE_INT min,
+						    HOST_WIDE_INT max,
+						    HOST_WIDE_INT mult)
+{
+  unsigned int argno = m_base_arg + rel_argno;
+  if (!argument_exists_p (argno))
+    return true;
+
+  HOST_WIDE_INT actual;
+  if (!require_signed_immediate (argno, actual))
+    return false;
+
+  if (!IN_RANGE (actual, min, max)
+      || (actual % mult) != 0)
+    {
+      report_out_of_range_multiple (location, fndecl, argno, actual, min, max, mult);
+      return false;
+    }
+
+  return true;
+}
+
 /* Perform semantic checks on the call.  Return true if the call is valid,
    otherwise report a suitable error.  */
 bool
diff --git a/gcc/config/arm/arm-mve-builtins.h b/gcc/config/arm/arm-mve-builtins.h
index 3e0796f7c09..5a191b0cde3 100644
--- a/gcc/config/arm/arm-mve-builtins.h
+++ b/gcc/config/arm/arm-mve-builtins.h
@@ -436,6 +436,8 @@  public:
   bool require_immediate_one_of (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT,
 				 HOST_WIDE_INT, HOST_WIDE_INT);
   bool require_immediate_range (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT);
+  bool require_immediate_range_multiple (unsigned int, HOST_WIDE_INT,
+					 HOST_WIDE_INT, HOST_WIDE_INT);
 
   bool check ();
 
@@ -443,6 +445,7 @@  private:
   bool argument_exists_p (unsigned int);
 
   bool require_immediate (unsigned int, HOST_WIDE_INT &);
+  bool require_signed_immediate (unsigned int, HOST_WIDE_INT &);
 
   /* The type of the resolved function.  */
   tree m_fntype;