-
Notifications
You must be signed in to change notification settings - Fork 12.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[M68k] Handle 16 bit MOVs to and from CCR #114714
Conversation
8bdc22f
to
bc80cba
Compare
@llvm/pr-subscribers-backend-m68k Author: None (knickish) ChangesFull diff: https://github.com/llvm/llvm-project/pull/114714.diff 4 Files Affected:
diff --git a/llvm/lib/Target/M68k/M68kInstrData.td b/llvm/lib/Target/M68k/M68kInstrData.td
index dc777a933e2786..adaa8c85eefb9c 100644
--- a/llvm/lib/Target/M68k/M68kInstrData.td
+++ b/llvm/lib/Target/M68k/M68kInstrData.td
@@ -419,6 +419,8 @@ class MxMoveFromCCR_M<MxOperand MEMOp, MxEncMemOp DST_ENC>
class MxMoveFromCCRPseudo<MxOperand MEMOp>
: MxPseudo<(outs), (ins MEMOp:$dst, CCRC:$src)>;
+class MxMoveFromCCR_RPseudo<MxOperand MEMOp>
+ : MxPseudo<(outs MEMOp:$dst), (ins CCRC:$src)>;
} // let Uses = [CCR]
let mayStore = 1 in
@@ -432,7 +434,7 @@ foreach AM = MxMoveSupportedAMs in {
// Only data register is allowed.
def MOV16dc : MxMoveFromCCR_R;
-def MOV8dc : MxMoveFromCCRPseudo<MxOp8AddrMode_d.Op>;
+def MOV8dc : MxMoveFromCCR_RPseudo<MxOp8AddrMode_d.Op>;
//===----------------------------------------------------------------------===//
// LEA
diff --git a/llvm/lib/Target/M68k/M68kInstrInfo.cpp b/llvm/lib/Target/M68k/M68kInstrInfo.cpp
index 2d9285f89b74ae..25b7b0bdb2a0c5 100644
--- a/llvm/lib/Target/M68k/M68kInstrInfo.cpp
+++ b/llvm/lib/Target/M68k/M68kInstrInfo.cpp
@@ -23,7 +23,9 @@
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGenTypes/MachineValueType.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Regex.h"
@@ -571,6 +573,17 @@ bool M68kInstrInfo::ExpandPUSH_POP(MachineInstrBuilder &MIB,
}
bool M68kInstrInfo::ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const {
+ switch (MIB->getOpcode()) {
+ case M68k::MOV8cd: {
+ // Promote used register to the next class
+ auto &Opd = MIB->getOperand(1);
+ Opd.setReg(getRegisterInfo().getMatchingSuperReg(
+ Opd.getReg(), M68k::MxSubRegIndex8Lo, &M68k::DR16RegClass));
+ break;
+ }
+ default:
+ break;
+ }
// Replace the pseudo instruction with the real one
if (IsToCCR)
@@ -579,11 +592,6 @@ bool M68kInstrInfo::ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const {
// FIXME M68010 or later is required
MIB->setDesc(get(M68k::MOV16dc));
- // Promote used register to the next class
- auto &Opd = MIB->getOperand(1);
- Opd.setReg(getRegisterInfo().getMatchingSuperReg(
- Opd.getReg(), M68k::MxSubRegIndex8Lo, &M68k::DR16RegClass));
-
return true;
}
@@ -757,13 +765,27 @@ void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
bool ToSR = DstReg == M68k::SR;
if (FromCCR) {
- assert(M68k::DR8RegClass.contains(DstReg) &&
- "Need DR8 register to copy CCR");
- Opc = M68k::MOV8dc;
+ if (M68k::DR8RegClass.contains(DstReg)) {
+ Opc = M68k::MOV8dc;
+ } else if (M68k::DR16RegClass.contains(DstReg)) {
+ Opc = M68k::MOV16dc;
+ } else if (M68k::DR32RegClass.contains(DstReg)) {
+ Opc = M68k::MOV16dc;
+ } else {
+ LLVM_DEBUG(dbgs() << "Cannot copy CCR to " << RI.getName(DstReg) << '\n');
+ llvm_unreachable("Invalid register for MOVE from CCR");
+ }
} else if (ToCCR) {
- assert(M68k::DR8RegClass.contains(SrcReg) &&
- "Need DR8 register to copy CCR");
- Opc = M68k::MOV8cd;
+ if (M68k::DR8RegClass.contains(SrcReg)) {
+ Opc = M68k::MOV8cd;
+ } else if (M68k::DR16RegClass.contains(SrcReg)) {
+ Opc = M68k::MOV16cd;
+ } else if (M68k::DR32RegClass.contains(SrcReg)) {
+ Opc = M68k::MOV16cd;
+ } else {
+ LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to CCR\n");
+ llvm_unreachable("Invalid register for MOVE to CCR");
+ }
} else if (FromSR || ToSR)
llvm_unreachable("Cannot emit SR copy instruction");
diff --git a/llvm/lib/Target/M68k/M68kRegisterInfo.h b/llvm/lib/Target/M68k/M68kRegisterInfo.h
index 0cfab150d0c84b..51317683453666 100644
--- a/llvm/lib/Target/M68k/M68kRegisterInfo.h
+++ b/llvm/lib/Target/M68k/M68kRegisterInfo.h
@@ -101,7 +101,7 @@ class M68kRegisterInfo : public M68kGenRegisterInfo {
const TargetRegisterClass *
getCrossCopyRegClass(const TargetRegisterClass *RC) const override {
if (RC == &M68k::CCRCRegClass)
- return &M68k::DR32RegClass;
+ return &M68k::DR16RegClass;
return RC;
}
diff --git a/llvm/test/CodeGen/M68k/Control/non-cmov-switch.ll b/llvm/test/CodeGen/M68k/Control/non-cmov-switch.ll
new file mode 100644
index 00000000000000..90d2be017ecdb2
--- /dev/null
+++ b/llvm/test/CodeGen/M68k/Control/non-cmov-switch.ll
@@ -0,0 +1,126 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=m68k-linux -mcpu=M68020 --verify-machineinstrs | FileCheck %s
+
+define internal void @select_i32(i32 %self, ptr nonnull %value) {
+; CHECK-LABEL: select_i32:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0: ; %start
+; CHECK-NEXT: suba.l #4, %sp
+; CHECK-NEXT: .cfi_def_cfa_offset -8
+; CHECK-NEXT: movem.l %d2, (0,%sp) ; 8-byte Folded Spill
+; CHECK-NEXT: cmpi.l #0, (8,%sp)
+; CHECK-NEXT: move.w %ccr, %d2
+; CHECK-NEXT: sne %d1
+; CHECK-NEXT: move.l (12,%sp), %d0
+; CHECK-NEXT: move.w %d2, %ccr
+; CHECK-NEXT: bne .LBB0_2
+; CHECK-NEXT: ; %bb.1: ; %start
+; CHECK-NEXT: and.l #255, %d1
+; CHECK-NEXT: cmpi.l #0, %d1
+; CHECK-NEXT: bne .LBB0_3
+; CHECK-NEXT: .LBB0_2: ; %null
+; CHECK-NEXT: suba.l %a0, %a0
+; CHECK-NEXT: move.l %d0, (%a0)
+; CHECK-NEXT: .LBB0_3: ; %exit
+; CHECK-NEXT: movem.l (0,%sp), %d2 ; 8-byte Folded Reload
+; CHECK-NEXT: adda.l #4, %sp
+; CHECK-NEXT: rts
+start:
+ %2 = icmp eq i32 %self, 0
+ %3 = select i1 %2, i32 0, i32 1
+ switch i32 %3, label %exit [
+ i32 0, label %nonnull
+ i32 1, label %null
+ ]
+
+nonnull: ; preds = %start
+ store ptr %value, ptr null, align 2
+ br label %exit
+
+null: ; preds = %start
+ store ptr %value, ptr null, align 2
+ br label %exit
+
+exit: ; preds = %nonnull, %null
+ ret void
+}
+
+define internal void @select_i16(i16 %self, ptr nonnull %value) {
+; CHECK-LABEL: select_i16:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0: ; %start
+; CHECK-NEXT: suba.l #4, %sp
+; CHECK-NEXT: .cfi_def_cfa_offset -8
+; CHECK-NEXT: movem.l %d2, (0,%sp) ; 8-byte Folded Spill
+; CHECK-NEXT: cmpi.w #0, (10,%sp)
+; CHECK-NEXT: move.w %ccr, %d2
+; CHECK-NEXT: sne %d1
+; CHECK-NEXT: move.l (12,%sp), %d0
+; CHECK-NEXT: move.w %d2, %ccr
+; CHECK-NEXT: bne .LBB1_2
+; CHECK-NEXT: ; %bb.1: ; %start
+; CHECK-NEXT: and.l #255, %d1
+; CHECK-NEXT: cmpi.w #0, %d1
+; CHECK-NEXT: bne .LBB1_3
+; CHECK-NEXT: .LBB1_2: ; %null
+; CHECK-NEXT: suba.l %a0, %a0
+; CHECK-NEXT: move.l %d0, (%a0)
+; CHECK-NEXT: .LBB1_3: ; %exit
+; CHECK-NEXT: movem.l (0,%sp), %d2 ; 8-byte Folded Reload
+; CHECK-NEXT: adda.l #4, %sp
+; CHECK-NEXT: rts
+start:
+ %2 = icmp eq i16 %self, 0
+ %3 = select i1 %2, i16 0, i16 1
+ switch i16 %3, label %exit [
+ i16 0, label %nonnull
+ i16 1, label %null
+ ]
+
+nonnull: ; preds = %start
+ store ptr %value, ptr null, align 2
+ br label %exit
+
+null: ; preds = %start
+ store ptr %value, ptr null, align 2
+ br label %exit
+
+exit: ; preds = %nonnull, %null
+ ret void
+}
+
+define internal void @select_i8(i8 %self, ptr nonnull %value) {
+; CHECK-LABEL: select_i8:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0: ; %start
+; CHECK-NEXT: move.l (8,%sp), %d0
+; CHECK-NEXT: cmpi.b #0, (7,%sp)
+; CHECK-NEXT: sne %d1
+; CHECK-NEXT: bne .LBB2_2
+; CHECK-NEXT: ; %bb.1: ; %start
+; CHECK-NEXT: cmpi.b #0, %d1
+; CHECK-NEXT: bne .LBB2_3
+; CHECK-NEXT: .LBB2_2: ; %null
+; CHECK-NEXT: suba.l %a0, %a0
+; CHECK-NEXT: move.l %d0, (%a0)
+; CHECK-NEXT: .LBB2_3: ; %exit
+; CHECK-NEXT: rts
+start:
+ %2 = icmp eq i8 %self, 0
+ %3 = select i1 %2, i8 0, i8 1
+ switch i8 %3, label %exit [
+ i8 0, label %nonnull
+ i8 1, label %null
+ ]
+
+nonnull: ; preds = %start
+ store ptr %value, ptr null, align 2
+ br label %exit
+
+null: ; preds = %start
+ store ptr %value, ptr null, align 2
+ br label %exit
+
+exit: ; preds = %nonnull, %null
+ ret void
+}
|
Thanks a lot for the contribution! Could you start the subject with "[M68k]" and use a more descriptive title. I'll have a go at testing your changes later today. |
@glaubitz Thanks, much appreciated. I updated the title as requested. How are you testing these? I set up a docker container chroot thing based on your guide on the debian forums, but it's pretty unwieldy to be honest |
I'm currently doing cross-builds only as LLVM doesn't work natively on M68k at the moment due to the natural 2-byte alignment of the current ABI. We're working on switching the ABI to 4-byte alignment by default, but there has been some resistance from a few people who insist on ABI compatibility. However, both Debian and Gentoo agree that the port will only be maintainable in the future with 4-byte alignment by default. Having said that, are there any specific issues you need help with? |
I was just wondering what tests I should be running to verify that I'm not breaking anything, as the ones I have are super basic. The clang test suite maybe? |
Yes, running the testsuite is fine. FWIW, we have a buildbot for LLVM M68k to run integration tests. |
switch (MIB->getOpcode()) { | ||
case M68k::MOV8cd: { | ||
// Promote used register to the next class | ||
auto &Opd = MIB->getOperand(1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please spell out the type here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -571,6 +573,17 @@ bool M68kInstrInfo::ExpandPUSH_POP(MachineInstrBuilder &MIB, | |||
} | |||
|
|||
bool M68kInstrInfo::ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const { | |||
switch (MIB->getOpcode()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we just use if statement here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
switched to an if statement
Usually LLVM's regression tests should be sufficient: $ ninja check-llvm-codegen-m68k |
bc80cba
to
5fc6665
Compare
5fc6665
to
025b5a1
Compare
Ping @mshockwave, all PR comments have been addressed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM thanks!
Would someone be able to merge this? I don't have the ability to do that |
Builds on @TechnoElf 's CCR MOV pr #107591 and adds some tests.
Fixes #106210.