aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Lyon <christophe.lyon@linaro.org>2024-11-04 21:41:47 +0000
committerChristophe Lyon <christophe.lyon@linaro.org>2024-12-13 14:23:30 +0000
commitc0ab34339836b779ea161f54cb3bb397cdbc6f10 (patch)
tree9ce23f756a61cfefda8db27e24282bc91d9d5931
parent294e5424f294cdbd79aa5dcd755f4c825fa814c9 (diff)
downloadgcc-c0ab34339836b779ea161f54cb3bb397cdbc6f10.zip
gcc-c0ab34339836b779ea161f54cb3bb397cdbc6f10.tar.gz
gcc-c0ab34339836b779ea161f54cb3bb397cdbc6f10.tar.bz2
arm: [MVE intrinsics] Check immediate is a multiple in a range
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.
-rw-r--r--gcc/config/arm/arm-mve-builtins.cc60
-rw-r--r--gcc/config/arm/arm-mve-builtins.h3
2 files changed, 63 insertions, 0 deletions
diff --git a/gcc/config/arm/arm-mve-builtins.cc b/gcc/config/arm/arm-mve-builtins.cc
index 8e6fff0..b050e26 100644
--- a/gcc/config/arm/arm-mve-builtins.cc
+++ b/gcc/config/arm/arm-mve-builtins.cc
@@ -639,6 +639,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. */
@@ -1983,6 +1997,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. */
@@ -2070,6 +2104,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 3e0796f..5a191b0 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;