]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/109609 - correctly interpret arg size in fnspec
authorRichard Biener <rguenther@suse.de>
Tue, 25 Apr 2023 12:56:44 +0000 (14:56 +0200)
committerRichard Biener <rguenther@suse.de>
Tue, 25 Apr 2023 14:53:06 +0000 (16:53 +0200)
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.

gcc/attr-fnspec.h
gcc/testsuite/gcc.dg/torture/pr109609.c [new file with mode: 0644]
gcc/tree-ssa-alias.cc

index acf1c5f6be739767ebef35e7bf8e75a95d6e73ec..99d5f896e8b075fd3542ff6a29c489800e91daba 100644 (file)
@@ -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 (file)
index 0000000..0e191cd
--- /dev/null
@@ -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;
+}
index 8a1ec9091fa7d1327a581b60adf2c9234e602d79..e0693e146bf318edd7751a4164cfd81ae6e1a937 100644 (file)
@@ -2726,9 +2726,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;
              }