[llvm] [M68k] add 32 bit branch instrs and relaxations (PR #117371)

via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 22 15:18:18 PST 2024


https://github.com/knickish updated https://github.com/llvm/llvm-project/pull/117371

>From 999119d15d3d920dcc84af270c7793ae33bcf00f Mon Sep 17 00:00:00 2001
From: kirk <knickish at gmail.com>
Date: Fri, 22 Nov 2024 20:16:53 +0000
Subject: [PATCH 1/2] [M68k] add 32 bit branch instrs and allow x20 and later
 CPUs to relax to 32 bit versions

---
 llvm/lib/Target/M68k/M68kInstrControl.td      | 14 +++++
 .../M68k/MCTargetDesc/M68kAsmBackend.cpp      | 53 ++++++++++++++++---
 llvm/test/MC/M68k/Relaxations/branch32.s      | 11 ++++
 3 files changed, 72 insertions(+), 6 deletions(-)
 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..0c895484433643 100644
--- a/llvm/lib/Target/M68k/M68kInstrControl.td
+++ b/llvm/lib/Target/M68k/M68kInstrControl.td
@@ -190,6 +190,12 @@ 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>"))>;
+
+  let Predicates = [AtLeastM68020] in {
+  def B#cc#"32"
+    : MxBcc<cc, MxBrTarget32, (descend 0b1111, 0b1111),
+            (operand "$dst", 16, (encoder "encodePCRelImm<32>"))>;
+  } // AtLeastM68020
 }
 
 foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge",
@@ -223,6 +229,12 @@ def BRA8  : MxBra<MxBrTarget8,
 def BRA16 : MxBra<MxBrTarget16, (descend 0b0000, 0b0000),
                   (operand "$dst", 16, (encoder "encodePCRelImm<16>"))>;
 
+let Predicates = [AtLeastM68020] in {
+def BRA32 : MxBra<MxBrTarget16, (descend 0b1111, 0b1111),
+                  (operand "$dst", 32, (encoder "encodePCRelImm<32>"),
+                                       (decoder "DecodeImm32"))>;
+} // AtLeastM68020
+
 def : Pat<(br bb:$target), (BRA8 MxBrTarget8:$target)>;
 
 /// -------------------------------------------------
@@ -250,9 +262,11 @@ def BSR8 : MxBsr<MxBrTarget8, MxType8,
 def BSR16 : MxBsr<MxBrTarget16, MxType16, (descend 0b0000, 0b0000),
                 (operand "$dst", 16, (encoder "encodePCRelImm<16>"))>;
 
+let Predicates = [AtLeastM68020] in {
 def BSR32 : MxBsr<MxBrTarget32, MxType32, (descend 0b1111, 0b1111),
                 (operand "$dst", 32, (encoder "encodePCRelImm<32>"),
                                      (decoder "DecodeImm32"))>;
+} // AtLeastM68020
 
 //===----------------------------------------------------------------------===//
 // Call
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp b/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp
index 2c52fe07bb1119..56a18534fde05b 100644
--- a/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp
@@ -39,9 +39,14 @@ using namespace llvm;
 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; }
 
@@ -129,6 +134,36 @@ static unsigned getRelaxedOpcodeBranch(const MCInst &Inst) {
     return M68k::Ble16;
   case M68k::Bvs8:
     return M68k::Bvs16;
+  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;
   }
 }
 
@@ -168,7 +203,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 +213,13 @@ 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;
+  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 +259,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 +276,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/Relaxations/branch32.s b/llvm/test/MC/M68k/Relaxations/branch32.s
new file mode 100644
index 00000000000000..4d92fe1001cc37
--- /dev/null
+++ b/llvm/test/MC/M68k/Relaxations/branch32.s
@@ -0,0 +1,11 @@
+; RUN: llvm-mc -triple=m68k --mcpu=m68020 -motorola-integers -filetype=obj < %s \
+; RUN:     | llvm-objdump -d - | FileCheck %s
+
+; CHECK-LABEL: <RELAXED_32>:
+RELAXED_32:
+	; CHECK: bra  $ff
+	bra	.LBB3_1
+	.space 0x20000  ; Greater than u16::MAX.
+.LBB3_1:
+	add.l	#0, %d0
+	rts
\ No newline at end of file

>From 8b2bd6052188983f8c63c1c124d65cae4a212e02 Mon Sep 17 00:00:00 2001
From: kirk <knickish at gmail.com>
Date: Fri, 22 Nov 2024 23:18:01 +0000
Subject: [PATCH 2/2] wip

---
 llvm/lib/Target/M68k/M68kInstrControl.td      | 15 +++---
 .../M68k/MCTargetDesc/M68kAsmBackend.cpp      | 32 ++++++++++--
 llvm/test/MC/M68k/Relaxations/branch.s        |  2 +-
 llvm/test/MC/M68k/Relaxations/branch32.s      | 51 ++++++++++++++++++-
 4 files changed, 85 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/Target/M68k/M68kInstrControl.td b/llvm/lib/Target/M68k/M68kInstrControl.td
index 0c895484433643..1d14b45bb6094a 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",
@@ -191,11 +193,9 @@ foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge",
     : MxBcc<cc, MxBrTarget16, (descend 0b0000, 0b0000),
             (operand "$dst", 16, (encoder "encodePCRelImm<16>"))>;
 
-  let Predicates = [AtLeastM68020] in {
   def B#cc#"32"
     : MxBcc<cc, MxBrTarget32, (descend 0b1111, 0b1111),
-            (operand "$dst", 16, (encoder "encodePCRelImm<32>"))>;
-  } // AtLeastM68020
+            (operand "$dst", 32, (encoder "encodePCRelImm<32>"))>;
 }
 
 foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge",
@@ -221,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,
@@ -229,11 +231,9 @@ def BRA8  : MxBra<MxBrTarget8,
 def BRA16 : MxBra<MxBrTarget16, (descend 0b0000, 0b0000),
                   (operand "$dst", 16, (encoder "encodePCRelImm<16>"))>;
 
-let Predicates = [AtLeastM68020] in {
-def BRA32 : MxBra<MxBrTarget16, (descend 0b1111, 0b1111),
+def BRA32 : MxBra<MxBrTarget32, (descend 0b1111, 0b1111),
                   (operand "$dst", 32, (encoder "encodePCRelImm<32>"),
                                        (decoder "DecodeImm32"))>;
-} // AtLeastM68020
 
 def : Pat<(br bb:$target), (BRA8 MxBrTarget8:$target)>;
 
@@ -254,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,
@@ -262,11 +263,9 @@ def BSR8 : MxBsr<MxBrTarget8, MxType8,
 def BSR16 : MxBsr<MxBrTarget16, MxType16, (descend 0b0000, 0b0000),
                 (operand "$dst", 16, (encoder "encodePCRelImm<16>"))>;
 
-let Predicates = [AtLeastM68020] in {
 def BSR32 : MxBsr<MxBrTarget32, MxType32, (descend 0b1111, 0b1111),
                 (operand "$dst", 32, (encoder "encodePCRelImm<32>"),
                                      (decoder "DecodeImm32"))>;
-} // AtLeastM68020
 
 //===----------------------------------------------------------------------===//
 // Call
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp b/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp
index 56a18534fde05b..170faebefe2754 100644
--- a/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp
@@ -30,12 +30,15 @@
 #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 {
@@ -56,14 +59,27 @@ 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) &&
+    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)
@@ -183,8 +199,10 @@ static unsigned getRelaxedOpcode(const MCInst &Inst) {
 bool M68kAsmBackend::mayNeedRelaxation(const MCInst &Inst,
                                        const MCSubtargetInfo &STI) const {
   // Branches can always be relaxed in either mode.
-  if (getRelaxedOpcodeBranch(Inst) != Inst.getOpcode())
+  if (getRelaxedOpcodeBranch(Inst) != Inst.getOpcode()) {
+    LLVM_DEBUG(dbgs() << "Relaxing: " << Inst << '\n');
     return true;
+  }
 
   // Check if this instruction is ever relaxable.
   if (getRelaxedOpcodeArith(Inst) == Inst.getOpcode())
@@ -215,10 +233,14 @@ bool M68kAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
   // displacement field contains $00 (zero offset).
   unsigned int KindLog2Size = getFixupKindLog2Size(Fixup.getKind());
   bool FixupFieldTooSmall = false;
-  if (!isInt<8>(Value) && KindLog2Size == 0)
+  if (!isInt<8>(Value) && KindLog2Size == 0) {
+    LLVM_DEBUG(dbgs() << "Needs relaxing, does not fit in 8 bits: " << Value << '\n');
     FixupFieldTooSmall |= true;
-  if (!isInt<16>(Value) && KindLog2Size <= 1)
+  } else if (!isInt<16>(Value) && KindLog2Size <= 1) {
+    LLVM_DEBUG(dbgs() << "Needs relaxing, does not fit in 16 bits: " << Value << '\n');
     FixupFieldTooSmall |= true;
+  }
+    
   return Value == 0 || FixupFieldTooSmall;
 }
 
diff --git a/llvm/test/MC/M68k/Relaxations/branch.s b/llvm/test/MC/M68k/Relaxations/branch.s
index 41f8efc1f48520..dd7e08c3cdab6b 100644
--- a/llvm/test/MC/M68k/Relaxations/branch.s
+++ b/llvm/test/MC/M68k/Relaxations/branch.s
@@ -23,7 +23,7 @@ TIGHT:
 
 ; CHECK-LABEL: <RELAXED>:
 RELAXED:
-        ; CHECK: bra  $84
+        ; CHECK: bra  $00
 	bra	.LBB1_2
 	move.l	$0, $0
 	move.l	$0, $0
diff --git a/llvm/test/MC/M68k/Relaxations/branch32.s b/llvm/test/MC/M68k/Relaxations/branch32.s
index 4d92fe1001cc37..3cfb2de7097d21 100644
--- a/llvm/test/MC/M68k/Relaxations/branch32.s
+++ b/llvm/test/MC/M68k/Relaxations/branch32.s
@@ -1,9 +1,58 @@
 ; 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: <ZERO>:
+ZERO:
+	; CHECK: bra  $2
+	bra	.LBB2_1
+.LBB2_1:
+	add.l	#0, %d0
+	rts
+
 ; CHECK-LABEL: <RELAXED_32>:
 RELAXED_32:
-	; CHECK: bra  $ff
+	; CHECK: bra  $20004
 	bra	.LBB3_1
 	.space 0x20000  ; Greater than u16::MAX.
 .LBB3_1:



More information about the llvm-commits mailing list