aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/M68k/M68kInstrInfo.cpp62
-rw-r--r--llvm/test/CodeGen/M68k/Arith/add.ll3
-rw-r--r--llvm/test/CodeGen/M68k/CConv/fastcc-call.ll4
-rw-r--r--llvm/test/CodeGen/M68k/Data/link-unlnk.ll (renamed from llvm/test/CodeGen/M68k/link-unlnk.ll)0
-rw-r--r--llvm/test/CodeGen/M68k/Data/load-extend.ll (renamed from llvm/test/CodeGen/M68k/load-extend.ll)0
-rw-r--r--llvm/test/CodeGen/M68k/Data/load-imm.ll149
-rw-r--r--llvm/test/CodeGen/M68k/Data/sext-i1.ll (renamed from llvm/test/CodeGen/M68k/Arith/sext-i1.ll)0
7 files changed, 208 insertions, 10 deletions
diff --git a/llvm/lib/Target/M68k/M68kInstrInfo.cpp b/llvm/lib/Target/M68k/M68kInstrInfo.cpp
index 23c5c76..2d9285f 100644
--- a/llvm/lib/Target/M68k/M68kInstrInfo.cpp
+++ b/llvm/lib/Target/M68k/M68kInstrInfo.cpp
@@ -346,8 +346,8 @@ void M68kInstrInfo::AddZExt(MachineBasicBlock &MBB,
BuildMI(MBB, I, DL, get(And), Reg).addReg(Reg).addImm(Mask);
}
-// Convert MOVI to MOVQ if the target is a data register and the immediate
-// fits in a sign-extended i8, otherwise emit a plain MOV.
+// Convert MOVI to the appropriate instruction (sequence) for setting
+// the register to an immediate value.
bool M68kInstrInfo::ExpandMOVI(MachineInstrBuilder &MIB, MVT MVTSize) const {
Register Reg = MIB->getOperand(0).getReg();
int64_t Imm = MIB->getOperand(1).getImm();
@@ -360,18 +360,66 @@ bool M68kInstrInfo::ExpandMOVI(MachineInstrBuilder &MIB, MVT MVTSize) const {
if (AR16->contains(Reg) || AR32->contains(Reg))
IsAddressReg = true;
+ // We need to assign to the full register to make IV happy
+ Register SReg =
+ MVTSize == MVT::i32
+ ? Reg
+ : Register(RI.getMatchingMegaReg(Reg, IsAddressReg ? AR32 : DR32));
+ assert(SReg && "No viable MEGA register available");
+
LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to ");
+ // Sign extention doesn't matter if we only use the bottom 8 bits
if (MVTSize == MVT::i8 || (!IsAddressReg && Imm >= -128 && Imm <= 127)) {
LLVM_DEBUG(dbgs() << "MOVEQ\n");
- // We need to assign to the full register to make IV happy
- Register SReg =
- MVTSize == MVT::i32 ? Reg : Register(RI.getMatchingMegaReg(Reg, DR32));
- assert(SReg && "No viable MEGA register available");
-
MIB->setDesc(get(M68k::MOVQ));
MIB->getOperand(0).setReg(SReg);
+
+ // Counter the effects of sign-extension with a bitwise not.
+ // This is only faster and smaller for 32 bit values.
+ } else if (DR32->contains(Reg) && isUInt<8>(Imm)) {
+ LLVM_DEBUG(dbgs() << "MOVEQ and NOT\n");
+
+ MachineBasicBlock &MBB = *MIB->getParent();
+ DebugLoc DL = MIB->getDebugLoc();
+
+ unsigned SubReg = RI.getSubReg(Reg, M68k::MxSubRegIndex8Lo);
+ assert(SubReg && "No viable SUB register available");
+
+ BuildMI(MBB, MIB.getInstr(), DL, get(M68k::MOVQ), SReg).addImm(~Imm & 0xFF);
+ BuildMI(MBB, MIB.getInstr(), DL, get(M68k::NOT8d), SubReg).addReg(SubReg);
+
+ MIB->removeFromParent();
+
+ // Special case for setting address register to NULL (0)
+ } else if (IsAddressReg && Imm == 0) {
+ LLVM_DEBUG(dbgs() << "SUBA\n");
+
+ MachineBasicBlock &MBB = *MIB->getParent();
+ DebugLoc DL = MIB->getDebugLoc();
+
+ BuildMI(MBB, MIB.getInstr(), DL, get(M68k::SUB32ar), SReg)
+ .addReg(SReg, RegState::Undef)
+ .addReg(SReg, RegState::Undef);
+
+ MIB->removeFromParent();
+
+ // movea.w implicitly sign extends to the full register width,
+ // so exploit that if the immediate fits in the correct range.
+ //
+ // TODO: use lea imm.w, %an for further constants when 16-bit
+ // absolute addressing is implemented.
+ } else if (AR32->contains(Reg) && isUInt<16>(Imm)) {
+ LLVM_DEBUG(dbgs() << "MOVEA w/ implicit extend\n");
+
+ unsigned SubReg = RI.getSubReg(Reg, M68k::MxSubRegIndex16Lo);
+ assert(SubReg && "No viable SUB register available");
+
+ MIB->setDesc(get(M68k::MOV16ai));
+ MIB->getOperand(0).setReg(SubReg);
+
+ // Fall back to a move with immediate
} else {
LLVM_DEBUG(dbgs() << "MOVE\n");
MIB->setDesc(get(MVTSize == MVT::i16 ? M68k::MOV16ri : M68k::MOV32ri));
diff --git a/llvm/test/CodeGen/M68k/Arith/add.ll b/llvm/test/CodeGen/M68k/Arith/add.ll
index a9eb0bb8..417fe8f 100644
--- a/llvm/test/CodeGen/M68k/Arith/add.ll
+++ b/llvm/test/CodeGen/M68k/Arith/add.ll
@@ -65,7 +65,8 @@ define fastcc void @test4(ptr inreg %a) nounwind {
; CHECK-NEXT: movem.l %d2, (0,%sp) ; 8-byte Folded Spill
; CHECK-NEXT: move.l (%a0), %d0
; CHECK-NEXT: moveq #0, %d1
-; CHECK-NEXT: move.l #128, %d2
+; CHECK-NEXT: moveq #127, %d2
+; CHECK-NEXT: not.b %d2
; CHECK-NEXT: add.l (4,%a0), %d2
; CHECK-NEXT: addx.l %d0, %d1
; CHECK-NEXT: move.l %d2, (4,%a0)
diff --git a/llvm/test/CodeGen/M68k/CConv/fastcc-call.ll b/llvm/test/CodeGen/M68k/CConv/fastcc-call.ll
index 8d40ebd..f67280c 100644
--- a/llvm/test/CodeGen/M68k/CConv/fastcc-call.ll
+++ b/llvm/test/CodeGen/M68k/CConv/fastcc-call.ll
@@ -13,8 +13,8 @@ define i32 @foo1() nounwind uwtable {
; CHECK-NEXT: move.l #5, (%sp)
; CHECK-NEXT: moveq #1, %d0
; CHECK-NEXT: moveq #2, %d1
-; CHECK-NEXT: move.l #3, %a0
-; CHECK-NEXT: move.l #4, %a1
+; CHECK-NEXT: move.w #3, %a0
+; CHECK-NEXT: move.w #4, %a1
; CHECK-NEXT: jsr (bar1@PLT,%pc)
; CHECK-NEXT: moveq #0, %d0
; CHECK-NEXT: adda.l #4, %sp
diff --git a/llvm/test/CodeGen/M68k/link-unlnk.ll b/llvm/test/CodeGen/M68k/Data/link-unlnk.ll
index fe39a9a..fe39a9a 100644
--- a/llvm/test/CodeGen/M68k/link-unlnk.ll
+++ b/llvm/test/CodeGen/M68k/Data/link-unlnk.ll
diff --git a/llvm/test/CodeGen/M68k/load-extend.ll b/llvm/test/CodeGen/M68k/Data/load-extend.ll
index 5115973..5115973 100644
--- a/llvm/test/CodeGen/M68k/load-extend.ll
+++ b/llvm/test/CodeGen/M68k/Data/load-extend.ll
diff --git a/llvm/test/CodeGen/M68k/Data/load-imm.ll b/llvm/test/CodeGen/M68k/Data/load-imm.ll
new file mode 100644
index 0000000..5105e55
--- /dev/null
+++ b/llvm/test/CodeGen/M68k/Data/load-imm.ll
@@ -0,0 +1,149 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc < %s -mtriple=m68k-linux -verify-machineinstrs | FileCheck %s
+
+define i1 @return_true() {
+; CHECK-LABEL: return_true:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: moveq #1, %d0
+; CHECK-NEXT: rts
+ ret i1 true
+}
+
+define i8 @return_0_i8() {
+; CHECK-LABEL: return_0_i8:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: moveq #0, %d0
+; CHECK-NEXT: rts
+ ret i8 0
+}
+
+define i16 @return_0_i16() {
+; CHECK-LABEL: return_0_i16:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: moveq #0, %d0
+; CHECK-NEXT: rts
+ ret i16 0
+}
+
+define i32 @return_0_i32() {
+; CHECK-LABEL: return_0_i32:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: moveq #0, %d0
+; CHECK-NEXT: rts
+ ret i32 0
+}
+
+define i64 @return_0_i64() {
+; CHECK-LABEL: return_0_i64:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: moveq #0, %d0
+; CHECK-NEXT: move.l %d0, %d1
+; CHECK-NEXT: rts
+ ret i64 0
+}
+
+define i16 @return_neg1_i16() {
+; CHECK-LABEL: return_neg1_i16:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: moveq #-1, %d0
+; CHECK-NEXT: rts
+ ret i16 -1
+}
+
+define i32 @return_neg1_i32() {
+; CHECK-LABEL: return_neg1_i32:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: moveq #-1, %d0
+; CHECK-NEXT: rts
+ ret i32 -1
+}
+
+define i8 @return_160_i8() {
+; CHECK-LABEL: return_160_i8:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: moveq #-96, %d0
+; CHECK-NEXT: rts
+ ret i8 160
+}
+
+define i16 @return_160_i16() {
+; CHECK-LABEL: return_160_i16:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: move.w #160, %d0
+; CHECK-NEXT: rts
+ ret i16 160
+}
+
+define i32 @return_160_i32() {
+; CHECK-LABEL: return_160_i32:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: moveq #95, %d0
+; CHECK-NEXT: not.b %d0
+; CHECK-NEXT: rts
+ ret i32 160
+}
+
+define i16 @return_14281_i16() {
+; CHECK-LABEL: return_14281_i16:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: move.w #14281, %d0
+; CHECK-NEXT: rts
+ ret i16 14281
+}
+
+define i32 @return_14281_i32() {
+; CHECK-LABEL: return_14281_i32:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: move.l #14281, %d0
+; CHECK-NEXT: rts
+ ret i32 14281
+}
+
+define i64 @return_14281_i64() {
+; CHECK-LABEL: return_14281_i64:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: moveq #0, %d0
+; CHECK-NEXT: move.l #14281, %d1
+; CHECK-NEXT: rts
+ ret i64 14281
+}
+
+define ptr @return_null() {
+; CHECK-LABEL: return_null:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: suba.l %a0, %a0
+; CHECK-NEXT: rts
+ ret ptr null
+}
+
+define ptr @return_nonnull() {
+; CHECK-LABEL: return_nonnull:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: move.w #200, %a0
+; CHECK-NEXT: rts
+ ret ptr inttoptr (i32 200 to ptr)
+}
+
+define ptr @return_large_nonnull() {
+; CHECK-LABEL: return_large_nonnull:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: move.l #74281, %a0
+; CHECK-NEXT: rts
+ ret ptr inttoptr (i32 74281 to ptr)
+} \ No newline at end of file
diff --git a/llvm/test/CodeGen/M68k/Arith/sext-i1.ll b/llvm/test/CodeGen/M68k/Data/sext-i1.ll
index 2be5224..2be5224 100644
--- a/llvm/test/CodeGen/M68k/Arith/sext-i1.ll
+++ b/llvm/test/CodeGen/M68k/Data/sext-i1.ll