Skip to content

Commit 54d86df

Browse files
authored
[AArch64] Fallback to PRFUM for PRFM with negative or unaligned offset (#166756)
Section C3.2.2 (quoted below) in the ARMARM makes this a requirement of assemblers for load/stores with unscaled offset. It makes no mention of PRFM so I don't consider this to be a bug, although I can see why we would want to extend this behaviour to the unscaled variants of these instructions as well, as GCC does. This patch adds an alias for this. C3.2.2 Load/store register (unscaled offset) The load/store register instructions with an unscaled offset support only one addressing mode: Base plus an unscaled 9-bit signed immediate offset. See Load/store addressing modes. The load/store register (unscaled offset) instructions are required to disambiguate this instruction class from the load/store register instruction forms that support an addressing mode of base plus a scaled, unsigned 12-bit immediate offset, because that can represent some offset values in the same range. The ambiguous immediate offsets are byte offsets that are both: In the range 0-255, inclusive. Naturally aligned to the access size. Other byte offsets in the range -256 to 255 inclusive are unambiguous. An assembler program translating a load/store instruction, for example LDR, is required to encode an unambiguous offset using the unscaled 9-bit offset form, and to encode an ambiguous offset using the scaled 12-bit offset form. A programmer might force the generation of the unscaled 9-bit form by using one of the mnemonics in Table C.3.21. Arm recommends that a disassembler outputs all unscaled 9-bit offset forms using one of these mnemonics, but unambiguous offsets can be output using a load/store single register mnemonic, for example, LDR. Fixes #83226.
1 parent 0e6c8da commit 54d86df

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

llvm/lib/Target/AArch64/AArch64InstrInfo.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4444,6 +4444,11 @@ defm PRFUM : PrefetchUnscaled<0b11, 0, 0b10, "prfum",
44444444
[(AArch64Prefetch timm:$Rt,
44454445
(am_unscaled64 GPR64sp:$Rn, simm9:$offset))]>;
44464446

4447+
// PRFM falls back to PRFUM for negative or unaligned offsets (not a multiple
4448+
// of 8).
4449+
def : InstAlias<"prfm $Rt, [$Rn, $offset]",
4450+
(PRFUMi prfop:$Rt, GPR64sp:$Rn, simm9_offset_fb64:$offset), 0>;
4451+
44474452
//---
44484453
// (unscaled immediate, unprivileged)
44494454
defm LDTRX : LoadUnprivileged<0b11, 0, 0b01, GPR64, "ldtr">;

llvm/test/MC/AArch64/prfum.s

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: llvm-mc -triple=aarch64 -show-encoding --print-imm-hex=false < %s \
2+
// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
3+
// RUN: llvm-mc -triple=aarch64 -filetype=obj < %s \
4+
// RUN: | llvm-objdump -d --print-imm-hex=false - | FileCheck %s --check-prefix=CHECK-INST
5+
// Disassemble encoding and check the re-encoding (-show-encoding) matches.
6+
// RUN: llvm-mc -triple=aarch64 -show-encoding < %s \
7+
// RUN: | sed '/.text/d' | sed 's/.*encoding: //g' \
8+
// RUN: | llvm-mc -triple=aarch64 -disassemble -show-encoding --print-imm-hex=false \
9+
// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
10+
11+
// PRFM falls back to PRFUM for negative or unaligned offsets (not a multiple
12+
// of 8).
13+
14+
prfm pldl1keep, [x0, #-256]
15+
// CHECK-INST: prfum pldl1keep, [x0, #-256]
16+
// CHECK-ENCODING: [0x00,0x00,0x90,0xf8]
17+
18+
prfm pldl1keep, [x0, #-8]
19+
// CHECK-INST: prfum pldl1keep, [x0, #-8]
20+
// CHECK-ENCODING: [0x00,0x80,0x9f,0xf8]
21+
22+
prfm pldl1keep, [x0, #-1]
23+
// CHECK-INST: prfum pldl1keep, [x0, #-1]
24+
// CHECK-ENCODING: [0x00,0xf0,0x9f,0xf8]
25+
26+
prfm pldl1keep, [x0, #0]
27+
// CHECK-INST: prfm pldl1keep, [x0]
28+
// CHECK-ENCODING: [0x00,0x00,0x80,0xf9]
29+
30+
prfm pldl1keep, [x0, #1]
31+
// CHECK-INST: prfum pldl1keep, [x0, #1]
32+
// CHECK-ENCODING: [0x00,0x10,0x80,0xf8]
33+
34+
prfm pldl1keep, [x0, #8]
35+
// CHECK-INST: prfm pldl1keep, [x0, #8]
36+
// CHECK-ENCODING: [0x00,0x04,0x80,0xf9]
37+
38+
prfm pldl1keep, [x0, #255]
39+
// CHECK-INST: prfum pldl1keep, [x0, #255]
40+
// CHECK-ENCODING: [0x00,0xf0,0x8f,0xf8]
41+
42+
prfm pldl1keep, [x0, #256]
43+
// CHECK-INST: prfm pldl1keep, [x0, #256]
44+
// CHECK-ENCODING: [0x00,0x80,0x80,0xf9]

0 commit comments

Comments
 (0)