[llvm] [AVR] Offset relative jumps by -2 (PR #102936)
Patryk Wychowaniec via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 12 09:59:55 PDT 2024
https://github.com/Patryk27 created https://github.com/llvm/llvm-project/pull/102936
AVR relative jumps are encoded relative to the *end* of the current instruction (i.e. `rjmp 0` skips one instruction forward), while LLVM by default seems to assume jumps happen at the beginning of the instruction - fixing this requires offseting them by `-2`, which is what this commit does.
(note that strictly speaking we have to offset just `-1`, because the jump's encoding utilizes fact that AVR instructions take two bytes and so it's already divided by two.)
This wasn't a problem up until 6859685a87ad093d60c8bed60b116143c0a684c7 (or rather 84428dafc0941e3a31303fa1b286835ab2b8e234), because the AVR backend used to encode _all_ jumps (including those between basic blocks) using relocations, so the problematic code path simply wasn't triggered.
>From e5aa4b63c8baff8741c15744695248723444c598 Mon Sep 17 00:00:00 2001
From: Patryk Wychowaniec <pwychowaniec at pm.me>
Date: Mon, 12 Aug 2024 18:47:44 +0200
Subject: [PATCH] [AVR] Offset relative jumps by -2
AVR relative jumps are encoded relative to the *end* of the current
instruction (i.e. `rjmp 0` skips one instruction forward), while LLVM by
default seems to assume jumps happen at the beginning of the instruction
- fixing this requires offseting them by `-2`, which is what this commit
does.
(note that strictly speaking we have to offset just `-1`, because the
jump's encoding utilizes fact that AVR instructions take two
bytes and so it's already divided by two.)
This wasn't a problem up until
6859685a87ad093d60c8bed60b116143c0a684c7 (or rather
84428dafc0941e3a31303fa1b286835ab2b8e234), because the AVR backend used
to encode _all_ jumps (including those between basic blocks) using
relocations, so the problematic code path wasn't triggered.
---
.../Target/AVR/MCTargetDesc/AVRAsmBackend.cpp | 3 +++
llvm/test/CodeGen/AVR/jmp.ll | 24 +++++++++++++++++++
2 files changed, 27 insertions(+)
create mode 100644 llvm/test/CodeGen/AVR/jmp.ll
diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
index 0d29912bee2646..c983c21afb7fcf 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
@@ -94,6 +94,9 @@ static void adjustRelativeBranch(unsigned Size, const MCFixup &Fixup,
// Rightshifts the value by one.
AVR::fixups::adjustBranchTarget(Value);
+
+ // Jumps are relative to the current instruction.
+ Value -= 1;
}
/// 22-bit absolute fixup.
diff --git a/llvm/test/CodeGen/AVR/jmp.ll b/llvm/test/CodeGen/AVR/jmp.ll
new file mode 100644
index 00000000000000..2630660c3e7090
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/jmp.ll
@@ -0,0 +1,24 @@
+; RUN: llc -filetype=obj -mtriple=avr < %s | llvm-objdump -d --disassemble-symbols=foo --no-show-raw-insn - | FileCheck %s
+
+define i8 @foo(i8 %a) {
+bb0:
+ %0 = tail call i8 @bar(i8 %a)
+ %1 = icmp eq i8 %0, 123
+ br i1 %1, label %bb1, label %bb2
+
+bb1:
+ ret i8 100
+
+bb2:
+ ret i8 200
+}
+
+declare i8 @bar(i8);
+
+; CHECK: rcall .-2
+; CHECK-NEXT: cpi r24, 0x7b
+; CHECK-NEXT: brne .+4
+; CHECK-NEXT: ldi r24, 0x64
+; CHECK-NEXT: ret
+; CHECK-NEXT: ldi r24, 0xc8
+; CHECK-NEXT: ret
More information about the llvm-commits
mailing list