From 62a12e10d23725070ab147e940fa21af86c2f0be Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Sat, 20 Feb 2021 12:14:08 +0000 Subject: [PATCH] aarch64, Darwin : Restrict offsets for prfm. The current LLVM-based assemblers reject offsets that are not suitable for prfm as written in the local section. However, there is advice elsewhere that says that this category of instruction should attempt to use the 9bit unscaled version before falling back to the scaled one. In the short-term reject values that the assembler will not accept. This partially addresses Issue #43 gcc/ * config/aarch64/aarch64.c (aarch64_address_valid_for_prefetch_p): Reject values incompatible with pfrum and out of range for pfrm. For Mach-O, reject values that require prfum. --- gcc/config/aarch64/aarch64.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index f8f37101884d..3cc031c3d8d6 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -10051,9 +10051,31 @@ aarch64_address_valid_for_prefetch_p (rtx x, bool strict_p) if (!res) return false; - /* Darwinpcs allows addresses on the stack that are not DImode aligned. */ - if (TARGET_MACHO && addr.offset && (INTVAL (addr.offset) & 0x07)) - return false; + /* For ELF targets using GAS, we emit prfm unconditionally; GAS will alter + the instruction to pick the prfum form where possible (i.e. when the + offset is in the range -256..255) and fall back to prfm otherwise. + We can reject cases where the offset exceeds the range usable by both + insns [-256..32760], or for offsets > 255 when the value is not divisible + by 8. + For Mach-O (Darwin) where the assembler uses the LLVM back end, that does + not yet do the substitution, so we must reject all prfum cases. */ + if (addr.offset) + { + HOST_WIDE_INT offs = INTVAL (addr.offset); + if (offs < -256) /* Out of range for both prfum and prfm. */ + return false; + if (offs > 32760) /* Out of range for prfm. */ + return false; + if (offs & 0x07) /* We cannot use prfm. */ + { + if (offs > 255) /* Out of range for prfum. */ + return false; + if (TARGET_MACHO) + return false; + } + if (TARGET_MACHO && offs < 0) + return false; + } /* ... except writeback forms. */ return addr.type != ADDRESS_REG_WB;