Skip to content

Commit d3c10b5

Browse files
authored
[M68k] Introduce more MOVI cases (#98377)
Add three more special cases for loading registers with immediates. The first allows values in the range of [-255, 255] to be loaded with MOVEQ, even if the register is more than 8 bits and the sign extention is unwanted. This is done by loading the bitwise complement of the desired value, then performing a NOT instruction on the loaded register. This special case is only used when a simple MOVEQ cannot be used, and is only used for 32 bit data registers. Address registers cannot support MOVEQ, and the two-instruction sequence is no faster or smaller than a plain MOVE instruction when loading 16 bit immediates on the 68000, and likely slower for more sophisticated microarchitectures. However, the instruction sequence is both smaller and faster than the corresponding MOVE instruction for 32 bit register widths. The second special case is for zeroing address registers. This simply expands to subtracting a register with itself, consuming one instruction word rather than 2-3, with a small improvement in speed as well. The last special case is for assigning sign-extended 16-bit values to a full address register. This takes advantage of the fact that the movea.w instruction sign extends the output, permitting the immediate to be smaller. This is similar to using lea with a 16-bit address, which is not added in this patch as 16-bit absolute addressing is not yet implemented. This is a v2 submission of #90817. It also creates a 'Data' test directory to better align with the backend's tablegen layout.
1 parent 98bb354 commit d3c10b5

File tree

7 files changed

+208
-10
lines changed

7 files changed

+208
-10
lines changed

llvm/lib/Target/M68k/M68kInstrInfo.cpp

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,8 @@ void M68kInstrInfo::AddZExt(MachineBasicBlock &MBB,
346346
BuildMI(MBB, I, DL, get(And), Reg).addReg(Reg).addImm(Mask);
347347
}
348348

349-
// Convert MOVI to MOVQ if the target is a data register and the immediate
350-
// fits in a sign-extended i8, otherwise emit a plain MOV.
349+
// Convert MOVI to the appropriate instruction (sequence) for setting
350+
// the register to an immediate value.
351351
bool M68kInstrInfo::ExpandMOVI(MachineInstrBuilder &MIB, MVT MVTSize) const {
352352
Register Reg = MIB->getOperand(0).getReg();
353353
int64_t Imm = MIB->getOperand(1).getImm();
@@ -360,18 +360,66 @@ bool M68kInstrInfo::ExpandMOVI(MachineInstrBuilder &MIB, MVT MVTSize) const {
360360
if (AR16->contains(Reg) || AR32->contains(Reg))
361361
IsAddressReg = true;
362362

363+
// We need to assign to the full register to make IV happy
364+
Register SReg =
365+
MVTSize == MVT::i32
366+
? Reg
367+
: Register(RI.getMatchingMegaReg(Reg, IsAddressReg ? AR32 : DR32));
368+
assert(SReg && "No viable MEGA register available");
369+
363370
LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to ");
364371

372+
// Sign extention doesn't matter if we only use the bottom 8 bits
365373
if (MVTSize == MVT::i8 || (!IsAddressReg && Imm >= -128 && Imm <= 127)) {
366374
LLVM_DEBUG(dbgs() << "MOVEQ\n");
367375

368-
// We need to assign to the full register to make IV happy
369-
Register SReg =
370-
MVTSize == MVT::i32 ? Reg : Register(RI.getMatchingMegaReg(Reg, DR32));
371-
assert(SReg && "No viable MEGA register available");
372-
373376
MIB->setDesc(get(M68k::MOVQ));
374377
MIB->getOperand(0).setReg(SReg);
378+
379+
// Counter the effects of sign-extension with a bitwise not.
380+
// This is only faster and smaller for 32 bit values.
381+
} else if (DR32->contains(Reg) && isUInt<8>(Imm)) {
382+
LLVM_DEBUG(dbgs() << "MOVEQ and NOT\n");
383+
384+
MachineBasicBlock &MBB = *MIB->getParent();
385+
DebugLoc DL = MIB->getDebugLoc();
386+
387+
unsigned SubReg = RI.getSubReg(Reg, M68k::MxSubRegIndex8Lo);
388+
assert(SubReg && "No viable SUB register available");
389+
390+
BuildMI(MBB, MIB.getInstr(), DL, get(M68k::MOVQ), SReg).addImm(~Imm & 0xFF);
391+
BuildMI(MBB, MIB.getInstr(), DL, get(M68k::NOT8d), SubReg).addReg(SubReg);
392+
393+
MIB->removeFromParent();
394+
395+
// Special case for setting address register to NULL (0)
396+
} else if (IsAddressReg && Imm == 0) {
397+
LLVM_DEBUG(dbgs() << "SUBA\n");
398+
399+
MachineBasicBlock &MBB = *MIB->getParent();
400+
DebugLoc DL = MIB->getDebugLoc();
401+
402+
BuildMI(MBB, MIB.getInstr(), DL, get(M68k::SUB32ar), SReg)
403+
.addReg(SReg, RegState::Undef)
404+
.addReg(SReg, RegState::Undef);
405+
406+
MIB->removeFromParent();
407+
408+
// movea.w implicitly sign extends to the full register width,
409+
// so exploit that if the immediate fits in the correct range.
410+
//
411+
// TODO: use lea imm.w, %an for further constants when 16-bit
412+
// absolute addressing is implemented.
413+
} else if (AR32->contains(Reg) && isUInt<16>(Imm)) {
414+
LLVM_DEBUG(dbgs() << "MOVEA w/ implicit extend\n");
415+
416+
unsigned SubReg = RI.getSubReg(Reg, M68k::MxSubRegIndex16Lo);
417+
assert(SubReg && "No viable SUB register available");
418+
419+
MIB->setDesc(get(M68k::MOV16ai));
420+
MIB->getOperand(0).setReg(SubReg);
421+
422+
// Fall back to a move with immediate
375423
} else {
376424
LLVM_DEBUG(dbgs() << "MOVE\n");
377425
MIB->setDesc(get(MVTSize == MVT::i16 ? M68k::MOV16ri : M68k::MOV32ri));

llvm/test/CodeGen/M68k/Arith/add.ll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ define fastcc void @test4(ptr inreg %a) nounwind {
6565
; CHECK-NEXT: movem.l %d2, (0,%sp) ; 8-byte Folded Spill
6666
; CHECK-NEXT: move.l (%a0), %d0
6767
; CHECK-NEXT: moveq #0, %d1
68-
; CHECK-NEXT: move.l #128, %d2
68+
; CHECK-NEXT: moveq #127, %d2
69+
; CHECK-NEXT: not.b %d2
6970
; CHECK-NEXT: add.l (4,%a0), %d2
7071
; CHECK-NEXT: addx.l %d0, %d1
7172
; CHECK-NEXT: move.l %d2, (4,%a0)

llvm/test/CodeGen/M68k/CConv/fastcc-call.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ define i32 @foo1() nounwind uwtable {
1313
; CHECK-NEXT: move.l #5, (%sp)
1414
; CHECK-NEXT: moveq #1, %d0
1515
; CHECK-NEXT: moveq #2, %d1
16-
; CHECK-NEXT: move.l #3, %a0
17-
; CHECK-NEXT: move.l #4, %a1
16+
; CHECK-NEXT: move.w #3, %a0
17+
; CHECK-NEXT: move.w #4, %a1
1818
; CHECK-NEXT: jsr (bar1@PLT,%pc)
1919
; CHECK-NEXT: moveq #0, %d0
2020
; CHECK-NEXT: adda.l #4, %sp
File renamed without changes.
File renamed without changes.
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
2+
; RUN: llc < %s -mtriple=m68k-linux -verify-machineinstrs | FileCheck %s
3+
4+
define i1 @return_true() {
5+
; CHECK-LABEL: return_true:
6+
; CHECK: .cfi_startproc
7+
; CHECK-NEXT: ; %bb.0:
8+
; CHECK-NEXT: moveq #1, %d0
9+
; CHECK-NEXT: rts
10+
ret i1 true
11+
}
12+
13+
define i8 @return_0_i8() {
14+
; CHECK-LABEL: return_0_i8:
15+
; CHECK: .cfi_startproc
16+
; CHECK-NEXT: ; %bb.0:
17+
; CHECK-NEXT: moveq #0, %d0
18+
; CHECK-NEXT: rts
19+
ret i8 0
20+
}
21+
22+
define i16 @return_0_i16() {
23+
; CHECK-LABEL: return_0_i16:
24+
; CHECK: .cfi_startproc
25+
; CHECK-NEXT: ; %bb.0:
26+
; CHECK-NEXT: moveq #0, %d0
27+
; CHECK-NEXT: rts
28+
ret i16 0
29+
}
30+
31+
define i32 @return_0_i32() {
32+
; CHECK-LABEL: return_0_i32:
33+
; CHECK: .cfi_startproc
34+
; CHECK-NEXT: ; %bb.0:
35+
; CHECK-NEXT: moveq #0, %d0
36+
; CHECK-NEXT: rts
37+
ret i32 0
38+
}
39+
40+
define i64 @return_0_i64() {
41+
; CHECK-LABEL: return_0_i64:
42+
; CHECK: .cfi_startproc
43+
; CHECK-NEXT: ; %bb.0:
44+
; CHECK-NEXT: moveq #0, %d0
45+
; CHECK-NEXT: move.l %d0, %d1
46+
; CHECK-NEXT: rts
47+
ret i64 0
48+
}
49+
50+
define i16 @return_neg1_i16() {
51+
; CHECK-LABEL: return_neg1_i16:
52+
; CHECK: .cfi_startproc
53+
; CHECK-NEXT: ; %bb.0:
54+
; CHECK-NEXT: moveq #-1, %d0
55+
; CHECK-NEXT: rts
56+
ret i16 -1
57+
}
58+
59+
define i32 @return_neg1_i32() {
60+
; CHECK-LABEL: return_neg1_i32:
61+
; CHECK: .cfi_startproc
62+
; CHECK-NEXT: ; %bb.0:
63+
; CHECK-NEXT: moveq #-1, %d0
64+
; CHECK-NEXT: rts
65+
ret i32 -1
66+
}
67+
68+
define i8 @return_160_i8() {
69+
; CHECK-LABEL: return_160_i8:
70+
; CHECK: .cfi_startproc
71+
; CHECK-NEXT: ; %bb.0:
72+
; CHECK-NEXT: moveq #-96, %d0
73+
; CHECK-NEXT: rts
74+
ret i8 160
75+
}
76+
77+
define i16 @return_160_i16() {
78+
; CHECK-LABEL: return_160_i16:
79+
; CHECK: .cfi_startproc
80+
; CHECK-NEXT: ; %bb.0:
81+
; CHECK-NEXT: move.w #160, %d0
82+
; CHECK-NEXT: rts
83+
ret i16 160
84+
}
85+
86+
define i32 @return_160_i32() {
87+
; CHECK-LABEL: return_160_i32:
88+
; CHECK: .cfi_startproc
89+
; CHECK-NEXT: ; %bb.0:
90+
; CHECK-NEXT: moveq #95, %d0
91+
; CHECK-NEXT: not.b %d0
92+
; CHECK-NEXT: rts
93+
ret i32 160
94+
}
95+
96+
define i16 @return_14281_i16() {
97+
; CHECK-LABEL: return_14281_i16:
98+
; CHECK: .cfi_startproc
99+
; CHECK-NEXT: ; %bb.0:
100+
; CHECK-NEXT: move.w #14281, %d0
101+
; CHECK-NEXT: rts
102+
ret i16 14281
103+
}
104+
105+
define i32 @return_14281_i32() {
106+
; CHECK-LABEL: return_14281_i32:
107+
; CHECK: .cfi_startproc
108+
; CHECK-NEXT: ; %bb.0:
109+
; CHECK-NEXT: move.l #14281, %d0
110+
; CHECK-NEXT: rts
111+
ret i32 14281
112+
}
113+
114+
define i64 @return_14281_i64() {
115+
; CHECK-LABEL: return_14281_i64:
116+
; CHECK: .cfi_startproc
117+
; CHECK-NEXT: ; %bb.0:
118+
; CHECK-NEXT: moveq #0, %d0
119+
; CHECK-NEXT: move.l #14281, %d1
120+
; CHECK-NEXT: rts
121+
ret i64 14281
122+
}
123+
124+
define ptr @return_null() {
125+
; CHECK-LABEL: return_null:
126+
; CHECK: .cfi_startproc
127+
; CHECK-NEXT: ; %bb.0:
128+
; CHECK-NEXT: suba.l %a0, %a0
129+
; CHECK-NEXT: rts
130+
ret ptr null
131+
}
132+
133+
define ptr @return_nonnull() {
134+
; CHECK-LABEL: return_nonnull:
135+
; CHECK: .cfi_startproc
136+
; CHECK-NEXT: ; %bb.0:
137+
; CHECK-NEXT: move.w #200, %a0
138+
; CHECK-NEXT: rts
139+
ret ptr inttoptr (i32 200 to ptr)
140+
}
141+
142+
define ptr @return_large_nonnull() {
143+
; CHECK-LABEL: return_large_nonnull:
144+
; CHECK: .cfi_startproc
145+
; CHECK-NEXT: ; %bb.0:
146+
; CHECK-NEXT: move.l #74281, %a0
147+
; CHECK-NEXT: rts
148+
ret ptr inttoptr (i32 74281 to ptr)
149+
}
File renamed without changes.

0 commit comments

Comments
 (0)