aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2023-04-25 14:56:44 +0200
committerRichard Biener <rguenther@suse.de>2023-04-26 11:35:14 +0200
commit2c7e89510fe41265b285e886d19f9895adf545e8 (patch)
tree2dfa22de8c1eac68f80d9b59227f58768342cbfd
parentef6051b36241bf130bf76af0b775248635dc616e (diff)
downloadgcc-2c7e89510fe41265b285e886d19f9895adf545e8.zip
gcc-2c7e89510fe41265b285e886d19f9895adf545e8.tar.gz
gcc-2c7e89510fe41265b285e886d19f9895adf545e8.tar.bz2
tree-optimization/109609 - correctly interpret arg size in fnspec
By majority vote and a hint from the API name which is arg_max_access_size_given_by_arg_p this interprets a memory access size specified as given as other argument such as for strncpy in the testcase which has "1cO313" as specifying the _maximum_ size read/written rather than the exact size. There are two uses interpreting it that way already and one differing. The following adjusts the differing and clarifies the documentation. PR tree-optimization/109609 * attr-fnspec.h (arg_max_access_size_given_by_arg_p): Clarify semantics. * tree-ssa-alias.cc (check_fnspec): Correctly interpret the size given by arg_max_access_size_given_by_arg_p as maximum, not exact, size. * gcc.dg/torture/pr109609.c: New testcase. (cherry picked from commit e8d00353017f895d03a9eabae3506fd126ce1a2d)
-rw-r--r--gcc/attr-fnspec.h4
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr109609.c26
-rw-r--r--gcc/tree-ssa-alias.cc18
3 files changed, 43 insertions, 5 deletions
diff --git a/gcc/attr-fnspec.h b/gcc/attr-fnspec.h
index d506c75..f12cada 100644
--- a/gcc/attr-fnspec.h
+++ b/gcc/attr-fnspec.h
@@ -54,7 +54,7 @@
' ' nothing is known
't' the size of value written/read corresponds to the size of
of the pointed-to type of the argument type
- '1'...'9' specifies the size of value written/read is given by the
+ '1'...'9' specifies the size of value written/read is bound by the
specified argument
*/
@@ -169,7 +169,7 @@ public:
&& str[idx] != 'x' && str[idx] != 'X';
}
- /* Return true if load of memory pointed to by argument I is specified
+ /* Return true if load of memory pointed to by argument I is bound
by another argument. In this case set ARG. */
bool
arg_max_access_size_given_by_arg_p (unsigned int i, unsigned int *arg)
diff --git a/gcc/testsuite/gcc.dg/torture/pr109609.c b/gcc/testsuite/gcc.dg/torture/pr109609.c
new file mode 100644
index 0000000..0e191cd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr109609.c
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+
+#define N 23
+#define MAX_LEN 13
+char dst[N + 1];
+
+void __attribute__((noipa))
+invert(const char *id)
+{
+ char buf[MAX_LEN];
+ char *ptr = buf + sizeof(buf); // start from the end of buf
+ *(--ptr) = '\0'; // terminate string
+ while (*id && ptr > buf) {
+ *(--ptr) = *(id++); // copy id backwards
+ }
+ __builtin_strncpy(dst, ptr, N); // copy ptr/buf to dst
+}
+
+
+int main()
+{
+ invert("abcde");
+ if (__builtin_strcmp(dst, "edcba"))
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/tree-ssa-alias.cc b/gcc/tree-ssa-alias.cc
index be7b597..1b404e0 100644
--- a/gcc/tree-ssa-alias.cc
+++ b/gcc/tree-ssa-alias.cc
@@ -2722,9 +2722,21 @@ check_fnspec (gcall *call, ao_ref *ref, bool clobber)
t = TREE_CHAIN (t);
size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_VALUE (t)));
}
- ao_ref_init_from_ptr_and_size (&dref,
- gimple_call_arg (call, i),
- size);
+ poly_int64 size_hwi;
+ if (size
+ && poly_int_tree_p (size, &size_hwi)
+ && coeffs_in_range_p (size_hwi, 0,
+ HOST_WIDE_INT_MAX / BITS_PER_UNIT))
+ {
+ size_hwi = size_hwi * BITS_PER_UNIT;
+ ao_ref_init_from_ptr_and_range (&dref,
+ gimple_call_arg (call, i),
+ true, 0, -1, size_hwi);
+ }
+ else
+ ao_ref_init_from_ptr_and_range (&dref,
+ gimple_call_arg (call, i),
+ false, 0, -1, -1);
if (refs_may_alias_p_1 (&dref, ref, false))
return 1;
}