[llvm] [M68k] add 32 bit branch instrs and relaxations (PR #117371)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Nov 30 12:33:56 PST 2024
https://github.com/knickish updated https://github.com/llvm/llvm-project/pull/117371
>From 9400bffdea2641bfd54f5a0b91e45a1e885646f1 Mon Sep 17 00:00:00 2001
From: kirk <knickish at gmail.com>
Date: Fri, 22 Nov 2024 20:16:53 +0000
Subject: [PATCH] [M68k] add 32 bit branch instrs and allow x20 and later CPUs
to relax to 32 bit versions
---
llvm/lib/Target/M68k/M68kInstrControl.td | 13 +++
.../M68k/MCTargetDesc/M68kAsmBackend.cpp | 81 ++++++++++++++++---
llvm/test/MC/M68k/Control/bsr.s | 11 ---
llvm/test/MC/M68k/Control/bsr32.s | 35 ++++++++
llvm/test/MC/M68k/Relaxations/branch32.s | 63 +++++++++++++++
llvm/test/MC/M68k/Relocations/text-plt.s | 4 +-
6 files changed, 184 insertions(+), 23 deletions(-)
create mode 100644 llvm/test/MC/M68k/Control/bsr32.s
create mode 100644 llvm/test/MC/M68k/Relaxations/branch32.s
diff --git a/llvm/lib/Target/M68k/M68kInstrControl.td b/llvm/lib/Target/M68k/M68kInstrControl.td
index 6e116d7cfe4019..4e94b2ed3a0645 100644
--- a/llvm/lib/Target/M68k/M68kInstrControl.td
+++ b/llvm/lib/Target/M68k/M68kInstrControl.td
@@ -179,6 +179,8 @@ class MxBcc<string cc, Operand TARGET, dag disp_8, dag disp_16_32>
(descend 0b0110, !cast<MxEncCondOp>("MxCC"#cc).Value, disp_8),
disp_16_32
);
+
+ let Predicates = !if(!eq(TARGET, MxBrTarget32), [AtLeastM68020], []);
}
foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge",
@@ -190,6 +192,10 @@ foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge",
def B#cc#"16"
: MxBcc<cc, MxBrTarget16, (descend 0b0000, 0b0000),
(operand "$dst", 16, (encoder "encodePCRelImm<16>"))>;
+
+ def B#cc#"32"
+ : MxBcc<cc, MxBrTarget32, (descend 0b1111, 0b1111),
+ (operand "$dst", 32, (encoder "encodePCRelImm<32>"))>;
}
foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge",
@@ -215,6 +221,8 @@ class MxBra<Operand TARGET, dag disp_8, dag disp_16_32>
(descend 0b0110, 0b0000, disp_8),
disp_16_32
);
+
+ let Predicates = !if(!eq(TARGET, MxBrTarget32), [AtLeastM68020], []);
}
def BRA8 : MxBra<MxBrTarget8,
@@ -223,6 +231,10 @@ def BRA8 : MxBra<MxBrTarget8,
def BRA16 : MxBra<MxBrTarget16, (descend 0b0000, 0b0000),
(operand "$dst", 16, (encoder "encodePCRelImm<16>"))>;
+def BRA32 : MxBra<MxBrTarget32, (descend 0b1111, 0b1111),
+ (operand "$dst", 32, (encoder "encodePCRelImm<32>"),
+ (decoder "DecodeImm32"))>;
+
def : Pat<(br bb:$target), (BRA8 MxBrTarget8:$target)>;
/// -------------------------------------------------
@@ -242,6 +254,7 @@ class MxBsr<Operand TARGET, MxType TYPE, dag disp_8, dag disp_16_32>
(descend 0b0110, 0b0001, disp_8),
disp_16_32
);
+ let Predicates = !if(!eq(TARGET, MxBrTarget32), [AtLeastM68020], []);
}
def BSR8 : MxBsr<MxBrTarget8, MxType8,
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp b/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp
index 2c52fe07bb1119..298ec1cfc7c539 100644
--- a/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp
@@ -30,18 +30,26 @@
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
+#define DEBUG_TYPE "M68k-asm-backend"
+
namespace {
class M68kAsmBackend : public MCAsmBackend {
+ bool Allows32BitBranch;
public:
- M68kAsmBackend(const Target &T) : MCAsmBackend(llvm::endianness::big) {}
+ M68kAsmBackend(const Target &T, const MCSubtargetInfo &STI)
+ : MCAsmBackend(llvm::endianness::big),
+ Allows32BitBranch(llvm::StringSwitch<bool>(STI.getCPU())
+ .CasesLower("m68020", "m68030", "m68040", true)
+ .Default(false)) {}
unsigned getNumFixupKinds() const override { return 0; }
@@ -51,14 +59,26 @@ class M68kAsmBackend : public MCAsmBackend {
const MCSubtargetInfo *STI) const override {
unsigned Size = 1 << getFixupKindLog2Size(Fixup.getKind());
- assert(Fixup.getOffset() + Size <= Data.size() && "Invalid fixup offset!");
+ if (Fixup.getOffset() + Size > Data.size()) {
+ LLVM_DEBUG(dbgs() << "Fixup.getOffset(): " << Fixup.getOffset() << '\n');
+ LLVM_DEBUG(dbgs() << "Size: " << Size << '\n');
+ LLVM_DEBUG(dbgs() << "Data.size(): " << Data.size() << '\n');
+ assert(Fixup.getOffset() + Size <= Data.size() &&
+ "Invalid fixup offset!");
+ }
// Check that uppper bits are either all zeros or all ones.
// Specifically ignore overflow/underflow as long as the leakage is
// limited to the lower bits. This is to remain compatible with
// other assemblers.
- assert(isIntN(Size * 8 + 1, Value) &&
- "Value does not fit in the Fixup field");
+ if (!isIntN(Size * 8 + 1, Value)) {
+ LLVM_DEBUG(dbgs() << "Fixup.getOffset(): " << Fixup.getOffset() << '\n');
+ LLVM_DEBUG(dbgs() << "Size: " << Size << '\n');
+ LLVM_DEBUG(dbgs() << "Data.size(): " << Data.size() << '\n');
+ LLVM_DEBUG(dbgs() << "Value: " << Value << '\n');
+ assert(isIntN(Size * 8 + 1, Value) &&
+ "Value does not fit in the Fixup field");
+ }
// Write in Big Endian
for (unsigned i = 0; i != Size; ++i)
@@ -99,6 +119,8 @@ static unsigned getRelaxedOpcodeBranch(const MCInst &Inst) {
switch (Op) {
default:
return Op;
+
+ // 8 -> 16
case M68k::BRA8:
return M68k::BRA16;
case M68k::Bcc8:
@@ -129,6 +151,38 @@ static unsigned getRelaxedOpcodeBranch(const MCInst &Inst) {
return M68k::Ble16;
case M68k::Bvs8:
return M68k::Bvs16;
+
+ // 16 -> 32
+ case M68k::BRA16:
+ return M68k::BRA32;
+ case M68k::Bcc16:
+ return M68k::Bcc32;
+ case M68k::Bls16:
+ return M68k::Bls32;
+ case M68k::Blt16:
+ return M68k::Blt32;
+ case M68k::Beq16:
+ return M68k::Beq32;
+ case M68k::Bmi16:
+ return M68k::Bmi32;
+ case M68k::Bne16:
+ return M68k::Bne32;
+ case M68k::Bge16:
+ return M68k::Bge32;
+ case M68k::Bcs16:
+ return M68k::Bcs32;
+ case M68k::Bpl16:
+ return M68k::Bpl32;
+ case M68k::Bgt16:
+ return M68k::Bgt32;
+ case M68k::Bhi16:
+ return M68k::Bhi32;
+ case M68k::Bvc16:
+ return M68k::Bvc32;
+ case M68k::Ble16:
+ return M68k::Ble32;
+ case M68k::Bvs16:
+ return M68k::Bvs32;
}
}
@@ -167,8 +221,7 @@ bool M68kAsmBackend::mayNeedRelaxation(const MCInst &Inst,
bool M68kAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
uint64_t Value) const {
- // TODO Newer CPU can use 32 bit offsets, so check for this when ready
- if (!isInt<16>(Value)) {
+ if (!isInt<32>(Value) || (!Allows32BitBranch && !isInt<16>(Value))) {
llvm_unreachable("Cannot relax the instruction, value does not fit");
}
// Relax if the value is too big for a (signed) i8. This means that byte-wide
@@ -178,7 +231,15 @@ bool M68kAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
// A branch to the immediately following instruction automatically
// uses the 16-bit displacement format because the 8-bit
// displacement field contains $00 (zero offset).
- return Value == 0 || !isInt<8>(Value);
+ unsigned int KindLog2Size = getFixupKindLog2Size(Fixup.getKind());
+ bool FixupFieldTooSmall = false;
+ if (!isInt<8>(Value) && KindLog2Size == 0) {
+ FixupFieldTooSmall |= true;
+ } else if (!isInt<16>(Value) && KindLog2Size <= 1) {
+ FixupFieldTooSmall |= true;
+ }
+
+ return Value == 0 || FixupFieldTooSmall;
}
// NOTE Can tblgen help at all here to verify there aren't other instructions
@@ -218,8 +279,8 @@ namespace {
class M68kELFAsmBackend : public M68kAsmBackend {
public:
uint8_t OSABI;
- M68kELFAsmBackend(const Target &T, uint8_t OSABI)
- : M68kAsmBackend(T), OSABI(OSABI) {}
+ M68kELFAsmBackend(const Target &T, const MCSubtargetInfo &STI, uint8_t OSABI)
+ : M68kAsmBackend(T, STI), OSABI(OSABI) {}
std::unique_ptr<MCObjectTargetWriter>
createObjectTargetWriter() const override {
@@ -235,5 +296,5 @@ MCAsmBackend *llvm::createM68kAsmBackend(const Target &T,
const MCTargetOptions &Options) {
const Triple &TheTriple = STI.getTargetTriple();
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
- return new M68kELFAsmBackend(T, OSABI);
+ return new M68kELFAsmBackend(T, STI, OSABI);
}
diff --git a/llvm/test/MC/M68k/Control/bsr.s b/llvm/test/MC/M68k/Control/bsr.s
index a70c7fb9a96edf..6b7a7d5c6ecd94 100644
--- a/llvm/test/MC/M68k/Control/bsr.s
+++ b/llvm/test/MC/M68k/Control/bsr.s
@@ -8,10 +8,6 @@
; CHECK-SAME: encoding: [0x61,0x00,A,A]
; CHECK: fixup A - offset: 2, value: .LBB0_2, kind: FK_PCRel_2
bsr.w .LBB0_2
- ; CHECK: bsr.l .LBB0_3
- ; CHECK-SAME: encoding: [0x61,0xff,A,A,A,A]
- ; CHECK: fixup A - offset: 2, value: .LBB0_3, kind: FK_PCRel_4
- bsr.l .LBB0_3
.LBB0_1:
; CHECK: add.l #0, %d0
; CHECK-SAME: encoding: [0xd0,0xbc,0x00,0x00,0x00,0x00]
@@ -26,10 +22,3 @@
; CHECK: rts
; CHECK-SAME: encoding: [0x4e,0x75]
rts
-.LBB0_3:
- ; CHECK: add.l #1, %d0
- ; CHECK-SAME: encoding: [0xd0,0xbc,0x00,0x00,0x00,0x01]
- add.l #1, %d0
- ; CHECK: rts
- ; CHECK-SAME: encoding: [0x4e,0x75]
- rts
diff --git a/llvm/test/MC/M68k/Control/bsr32.s b/llvm/test/MC/M68k/Control/bsr32.s
new file mode 100644
index 00000000000000..58ed4a29a35318
--- /dev/null
+++ b/llvm/test/MC/M68k/Control/bsr32.s
@@ -0,0 +1,35 @@
+; RUN: llvm-mc -triple=m68k --mcpu=M68020 -show-encoding %s | FileCheck %s
+
+ ; CHECK: bsr.b .LBB0_1
+ ; CHECK-SAME: encoding: [0x61,A]
+ ; CHECK: fixup A - offset: 1, value: .LBB0_1-1, kind: FK_PCRel_1
+ bsr.b .LBB0_1
+ ; CHECK: bsr.w .LBB0_2
+ ; CHECK-SAME: encoding: [0x61,0x00,A,A]
+ ; CHECK: fixup A - offset: 2, value: .LBB0_2, kind: FK_PCRel_2
+ bsr.w .LBB0_2
+ ; CHECK: bsr.l .LBB0_3
+ ; CHECK-SAME: encoding: [0x61,0xff,A,A,A,A]
+ ; CHECK: fixup A - offset: 2, value: .LBB0_3, kind: FK_PCRel_4
+ bsr.l .LBB0_3
+.LBB0_1:
+ ; CHECK: add.l #0, %d0
+ ; CHECK-SAME: encoding: [0xd0,0xbc,0x00,0x00,0x00,0x00]
+ add.l #0, %d0
+ ; CHECK: rts
+ ; CHECK-SAME: encoding: [0x4e,0x75]
+ rts
+.LBB0_2:
+ ; CHECK: add.l #1, %d0
+ ; CHECK-SAME: encoding: [0xd0,0xbc,0x00,0x00,0x00,0x01]
+ add.l #1, %d0
+ ; CHECK: rts
+ ; CHECK-SAME: encoding: [0x4e,0x75]
+ rts
+.LBB0_3:
+ ; CHECK: add.l #1, %d0
+ ; CHECK-SAME: encoding: [0xd0,0xbc,0x00,0x00,0x00,0x01]
+ add.l #1, %d0
+ ; CHECK: rts
+ ; CHECK-SAME: encoding: [0x4e,0x75]
+ rts
diff --git a/llvm/test/MC/M68k/Relaxations/branch32.s b/llvm/test/MC/M68k/Relaxations/branch32.s
new file mode 100644
index 00000000000000..d8bb3d40e639e8
--- /dev/null
+++ b/llvm/test/MC/M68k/Relaxations/branch32.s
@@ -0,0 +1,63 @@
+; RUN: llvm-mc -triple=m68k --mcpu=M68020 -motorola-integers -filetype=obj < %s \
+; RUN: | llvm-objdump -d - | FileCheck %s
+
+; CHECK-LABEL: <TIGHT>:
+TIGHT:
+ ; CHECK: bra $78
+ bra .LBB0_2
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+.LBB0_2:
+ add.l #0, %d0
+ rts
+
+; CHECK-LABEL: <RELAXED>:
+RELAXED:
+ ; CHECK: bra $84
+ bra .LBB1_2
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+ move.l $0, $0
+.LBB1_2:
+ add.l #0, %d0
+ rts
+
+; CHECK-LABEL: <RELAXED_32>:
+RELAXED_32:
+ ; CHECK: bra $ff
+ ; CHECK-NEXT: 00 02
+ ; CHECK-NEXT: 00 00
+ bra .LBB3_1
+ .space 0x20000 ; Greater than u16::MAX.
+.LBB2_1:
+ add.l #0, %d0
+ rts
+
+; CHECK-LABEL: <ZERO>:
+ZERO:
+ ; CHECK: bra $2
+ bra .LBB3_1
+.LBB3_1:
+ add.l #0, %d0
+ rts
+
diff --git a/llvm/test/MC/M68k/Relocations/text-plt.s b/llvm/test/MC/M68k/Relocations/text-plt.s
index 9513519c33c670..7de04b8b2182a5 100644
--- a/llvm/test/MC/M68k/Relocations/text-plt.s
+++ b/llvm/test/MC/M68k/Relocations/text-plt.s
@@ -1,6 +1,6 @@
-; RUN: llvm-mc -triple m68k -filetype=obj %s -o - \
+; RUN: llvm-mc -triple m68k --mcpu=M68020 -filetype=obj %s -o - \
; RUN: | llvm-readobj -r - | FileCheck -check-prefix=RELOC %s
-; RUN: llvm-mc -triple m68k -show-encoding %s -o - \
+; RUN: llvm-mc -triple m68k --mcpu=M68020 -show-encoding %s -o - \
; RUN: | FileCheck -check-prefix=INSTR -check-prefix=FIXUP %s
; RELOC: R_68K_PLT16 target 0x0
More information about the llvm-commits
mailing list