mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
[SPARC] Cleanup handling of the Y/ASR registers.
- Implement copying ASR to/from GPR regs. - Mark ASRs as non-allocatable, so it won't try to arbitrarily use them inappropriately. - Instead of inserting explicit WRASR/RDASR nodes in the MUL/DIV routines, just do normal register copies. - Also...mark div as using Y, not just writing it. Added a test case with some code which previously died with an assertion failure (with -O0), or produced wrong code (otherwise). (Third time's the charm?) Differential Revision: http://reviews.llvm.org/D10401 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241686 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
cf8f6a296f
commit
8eb1aaac9c
@ -168,10 +168,9 @@ SDNode *SparcDAGToDAGISel::Select(SDNode *N) {
|
|||||||
} else {
|
} else {
|
||||||
TopPart = CurDAG->getRegister(SP::G0, MVT::i32);
|
TopPart = CurDAG->getRegister(SP::G0, MVT::i32);
|
||||||
}
|
}
|
||||||
TopPart = SDValue(CurDAG->getMachineNode(SP::WRASRrr, dl, MVT::i32,
|
TopPart = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, SP::Y, TopPart,
|
||||||
TopPart,
|
SDValue())
|
||||||
CurDAG->getRegister(SP::G0, MVT::i32)), 0);
|
.getValue(1);
|
||||||
TopPart = CurDAG->getCopyToReg(TopPart, dl, SP::Y, TopPart, SDValue()).getValue(1);
|
|
||||||
|
|
||||||
// FIXME: Handle div by immediate.
|
// FIXME: Handle div by immediate.
|
||||||
unsigned Opcode = N->getOpcode() == ISD::SDIV ? SP::SDIVrr : SP::UDIVrr;
|
unsigned Opcode = N->getOpcode() == ISD::SDIV ? SP::SDIVrr : SP::UDIVrr;
|
||||||
@ -184,12 +183,11 @@ SDNode *SparcDAGToDAGISel::Select(SDNode *N) {
|
|||||||
SDValue MulLHS = N->getOperand(0);
|
SDValue MulLHS = N->getOperand(0);
|
||||||
SDValue MulRHS = N->getOperand(1);
|
SDValue MulRHS = N->getOperand(1);
|
||||||
unsigned Opcode = N->getOpcode() == ISD::MULHU ? SP::UMULrr : SP::SMULrr;
|
unsigned Opcode = N->getOpcode() == ISD::MULHU ? SP::UMULrr : SP::SMULrr;
|
||||||
SDNode *Mul = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Glue,
|
SDNode *Mul =
|
||||||
MulLHS, MulRHS);
|
CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32, MulLHS, MulRHS);
|
||||||
// The high part is in the Y register.
|
SDValue ResultHigh = SDValue(Mul, 1);
|
||||||
return CurDAG->SelectNodeTo(N, SP::RDASR, MVT::i32,
|
ReplaceUses(SDValue(N, 0), ResultHigh);
|
||||||
CurDAG->getRegister(SP::Y, MVT::i32),
|
return nullptr;
|
||||||
SDValue(Mul, 1));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,6 +324,15 @@ void SparcInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
|||||||
numSubRegs = 4;
|
numSubRegs = 4;
|
||||||
movOpc = SP::FMOVS;
|
movOpc = SP::FMOVS;
|
||||||
}
|
}
|
||||||
|
} else if (SP::ASRRegsRegClass.contains(DestReg) &&
|
||||||
|
SP::IntRegsRegClass.contains(SrcReg)) {
|
||||||
|
BuildMI(MBB, I, DL, get(SP::WRASRrr), DestReg)
|
||||||
|
.addReg(SP::G0)
|
||||||
|
.addReg(SrcReg, getKillRegState(KillSrc));
|
||||||
|
} else if (SP::IntRegsRegClass.contains(DestReg) &&
|
||||||
|
SP::ASRRegsRegClass.contains(SrcReg)) {
|
||||||
|
BuildMI(MBB, I, DL, get(SP::RDASR), DestReg)
|
||||||
|
.addReg(SrcReg, getKillRegState(KillSrc));
|
||||||
} else
|
} else
|
||||||
llvm_unreachable("Impossible reg-to-reg copy");
|
llvm_unreachable("Impossible reg-to-reg copy");
|
||||||
|
|
||||||
|
@ -560,12 +560,12 @@ let Defs = [Y, ICC] in {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Section B.19 - Divide Instructions, p. 115
|
// Section B.19 - Divide Instructions, p. 115
|
||||||
let Defs = [Y] in {
|
let Uses = [Y], Defs = [Y] in {
|
||||||
defm UDIV : F3_12np<"udiv", 0b001110>;
|
defm UDIV : F3_12np<"udiv", 0b001110>;
|
||||||
defm SDIV : F3_12np<"sdiv", 0b001111>;
|
defm SDIV : F3_12np<"sdiv", 0b001111>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Defs = [Y, ICC] in {
|
let Uses = [Y], Defs = [Y, ICC] in {
|
||||||
defm UDIVCC : F3_12np<"udivcc", 0b011110>;
|
defm UDIVCC : F3_12np<"udivcc", 0b011110>;
|
||||||
defm SDIVCC : F3_12np<"sdivcc", 0b011111>;
|
defm SDIVCC : F3_12np<"sdivcc", 0b011111>;
|
||||||
}
|
}
|
||||||
|
@ -249,4 +249,6 @@ def FCCRegs : RegisterClass<"SP", [i1], 1, (sequence "FCC%u", 0, 3)>;
|
|||||||
|
|
||||||
// Ancillary state registers
|
// Ancillary state registers
|
||||||
def ASRRegs : RegisterClass<"SP", [i32], 32,
|
def ASRRegs : RegisterClass<"SP", [i32], 32,
|
||||||
(add Y, (sequence "ASR%u", 1, 31))>;
|
(add Y, (sequence "ASR%u", 1, 31))> {
|
||||||
|
let isAllocatable = 0;
|
||||||
|
}
|
||||||
|
@ -38,7 +38,7 @@ entry:
|
|||||||
|
|
||||||
; CHECK-LABEL: signed_divide:
|
; CHECK-LABEL: signed_divide:
|
||||||
; CHECK: sra %o0, 31, %o2
|
; CHECK: sra %o0, 31, %o2
|
||||||
; CHECK: wr %o2, %g0, %y
|
; CHECK: wr %g0, %o2, %y
|
||||||
; CHECK: sdiv %o0, %o1, %o0
|
; CHECK: sdiv %o0, %o1, %o0
|
||||||
define i32 @signed_divide(i32 %a, i32 %b) {
|
define i32 @signed_divide(i32 %a, i32 %b) {
|
||||||
%r = sdiv i32 %a, %b
|
%r = sdiv i32 %a, %b
|
||||||
|
21
test/CodeGen/SPARC/multiple-div.ll
Normal file
21
test/CodeGen/SPARC/multiple-div.ll
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
; RUN: llc < %s -march=sparc | FileCheck %s
|
||||||
|
; RUN: llc -O0 < %s -march=sparc | FileCheck %s
|
||||||
|
|
||||||
|
;; llc -O0 used to try to spill Y to the stack, which isn't possible,
|
||||||
|
;; and then crashed. Additionally, in -O1, it would omit the second
|
||||||
|
;; apparently-redundant wr to %y, which is not actually redundant
|
||||||
|
;; because the spec says to treat %y as potentially-written by udiv.
|
||||||
|
|
||||||
|
; CHECK-LABEL: two_divides:
|
||||||
|
; CHECK: wr %g0, %g0, %y
|
||||||
|
; CHECK: udiv
|
||||||
|
; CHECK: wr %g0, %g0, %y
|
||||||
|
; CHECK: udiv
|
||||||
|
; CHECK: add
|
||||||
|
|
||||||
|
define i32 @two_divides(i32 %a, i32 %b) {
|
||||||
|
%r = udiv i32 %a, %b
|
||||||
|
%r2 = udiv i32 %b, %a
|
||||||
|
%r3 = add i32 %r, %r2
|
||||||
|
ret i32 %r3
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user