[gcc(refs/vendors/ARM/heads/morello)] morello: Adjust aarch64_legitimize_address for capabilities

Matthew Malcomson matmal01@gcc.gnu.org
Wed Apr 6 09:59:48 GMT 2022


https://gcc.gnu.org/g:7eb0aa658f9337d1585a28bb469fc26d55072274

commit 7eb0aa658f9337d1585a28bb469fc26d55072274
Author: Alex Coplan <alex.coplan@arm.com>
Date:   Tue Mar 15 22:27:57 2022 +0000

    morello: Adjust aarch64_legitimize_address for capabilities
    
    The execution test added with this patch would previously fail at
    runtime, since we would emit the following code for f at -O2 on purecap
    Morello:
    
    f:
            sub     c0, c0, #65536
            ldr     c0, [c0, 65264]
            ret
    
    This codegen is due to the aarch64_anchor_offset optimization. While
    valid for standard AArch64, the large subtraction can cause the
    capability to become invalid, and the subsequent load will then trap.
    
    This patch avoids performing this transformation in
    aarch64_legitimize_address if the base pointer has a capability mode. We
    adjust aarch64_anchor_offset to only perform adjustments that should not
    take us out of bounds. With the patch, we now generate:
    
    f:
            sub     c0, c0, #272
            ldr     c0, [c0]
            ret
    
    and the execution test passes.
    
    gcc/ChangeLog:
    
            * config/aarch64/aarch64.c (aarch64_anchor_offset): Add cap
            parameter. If this flag is set, only produce an anchor that's
            guaranteed to be in bounds of the original base.
            (aarch64_legitimize_address): Update call to
            aarch64_anchor_offset to set new cap flag.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/aarch64/morello/bounds-anchor.c: New test.

Diff:
---
 gcc/config/aarch64/aarch64.c                       | 22 +++++++++++++++++-----
 .../gcc.target/aarch64/morello/bounds-anchor.c     | 18 ++++++++++++++++++
 2 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 5f9b51e03b3..734c9b88f28 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -11388,16 +11388,25 @@ aarch64_regno_regclass (unsigned regno)
 
 static HOST_WIDE_INT
 aarch64_anchor_offset (HOST_WIDE_INT offset, HOST_WIDE_INT size,
-		       machine_mode mode)
+		       machine_mode mode, bool cap)
 {
+  /* If the base is a capability, punt on negative offsets for now to
+     avoid invalidating the capability: we could potentially add some
+     round-towards-zero behaviour for negative offsets later on.  */
+  if (cap && offset < 0)
+    return 0;
+
   /* Does it look like we'll need a 16-byte load/store-pair operation?  */
   if (size > 16)
-    return (offset + 0x400) & ~0x7f0;
+    return cap ? (offset & ~0x3f0) : ((offset + 0x400) & ~0x7f0);
 
   /* For offsets that aren't a multiple of the access size, the limit is
      -256...255.  */
   if (offset & (size - 1))
     {
+      if (cap)
+	return offset & ((mode == BLKmode) ? ~0x1ff : ~0xff);
+
       /* BLKmode typically uses LDP of X-registers.  */
       if (mode == BLKmode)
 	return (offset + 512) & ~0x3ff;
@@ -11409,7 +11418,7 @@ aarch64_anchor_offset (HOST_WIDE_INT offset, HOST_WIDE_INT size,
     return 0;
 
   if (mode == TImode || mode == TFmode)
-    return (offset + 0x100) & ~0x1ff;
+    return cap ? (offset & ~0xff) : ((offset + 0x100) & ~0x1ff);
 
   /* Use 12-bit offset by access size.  */
   return offset & (~0xfff * size);
@@ -11470,8 +11479,11 @@ aarch64_legitimize_address (rtx x, rtx /* orig_x  */, machine_mode mode)
       HOST_WIDE_INT size;
       if (GET_MODE_SIZE (mode).is_constant (&size))
 	{
-	  HOST_WIDE_INT base_offset = aarch64_anchor_offset (offset, size,
-							     mode);
+	  bool cap = CAPABILITY_MODE_P (GET_MODE (base));
+	  HOST_WIDE_INT base_offset = aarch64_anchor_offset (offset,
+							     size,
+							     mode,
+							     cap);
 	  if (base_offset != 0)
 	    {
 	      base = plus_constant (Pmode, base, base_offset);
diff --git a/gcc/testsuite/gcc.target/aarch64/morello/bounds-anchor.c b/gcc/testsuite/gcc.target/aarch64/morello/bounds-anchor.c
new file mode 100644
index 00000000000..56215a89531
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/morello/bounds-anchor.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+
+/* This function previously caused aarch64_anchor_offset to emit a large
+   sub followed by a large indexed load, which means we end up
+   dereferencing an invalid capability.  */
+__attribute__((noipa))
+int *f(int **p) {
+  return p[-17];
+}
+
+int *arr[18];
+int main(void) {
+  int x = 42;
+  arr[0] = &x;
+  if (*f(arr + 17) != 42)
+    __builtin_abort ();
+  return 0;
+}


More information about the Gcc-cvs mailing list