summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorJames Y Knight <jyknight@google.com>2015-07-08 16:25:12 +0000
committerJames Y Knight <jyknight@google.com>2015-07-08 16:25:12 +0000
commitf238d176eb47a48b2775a3da4221afd5d5a05925 (patch)
tree64c70e2ec8c1de779f5967c5fc829a413b3f4e49 /llvm
parent51271bdc4ffc3986a0e9aa456bf254493f099f67 (diff)
downloadbcm5719-llvm-f238d176eb47a48b2775a3da4221afd5d5a05925.tar.gz
bcm5719-llvm-f238d176eb47a48b2775a3da4221afd5d5a05925.zip
[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 llvm-svn: 241686
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp18
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrInfo.cpp9
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrInfo.td4
-rw-r--r--llvm/lib/Target/Sparc/SparcRegisterInfo.td4
-rw-r--r--llvm/test/CodeGen/SPARC/basictest.ll2
-rw-r--r--llvm/test/CodeGen/SPARC/multiple-div.ll21
6 files changed, 44 insertions, 14 deletions
diff --git a/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp
index 9c594a9f0f6..1e3d10fe587 100644
--- a/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp
@@ -168,10 +168,9 @@ SDNode *SparcDAGToDAGISel::Select(SDNode *N) {
} else {
TopPart = CurDAG->getRegister(SP::G0, MVT::i32);
}
- TopPart = SDValue(CurDAG->getMachineNode(SP::WRASRrr, dl, MVT::i32,
- TopPart,
- CurDAG->getRegister(SP::G0, MVT::i32)), 0);
- TopPart = CurDAG->getCopyToReg(TopPart, dl, SP::Y, TopPart, SDValue()).getValue(1);
+ TopPart = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, SP::Y, TopPart,
+ SDValue())
+ .getValue(1);
// FIXME: Handle div by immediate.
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 MulRHS = N->getOperand(1);
unsigned Opcode = N->getOpcode() == ISD::MULHU ? SP::UMULrr : SP::SMULrr;
- SDNode *Mul = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Glue,
- MulLHS, MulRHS);
- // The high part is in the Y register.
- return CurDAG->SelectNodeTo(N, SP::RDASR, MVT::i32,
- CurDAG->getRegister(SP::Y, MVT::i32),
- SDValue(Mul, 1));
+ SDNode *Mul =
+ CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32, MulLHS, MulRHS);
+ SDValue ResultHigh = SDValue(Mul, 1);
+ ReplaceUses(SDValue(N, 0), ResultHigh);
+ return nullptr;
}
}
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
index f87cee43e31..6167c532db8 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
@@ -324,6 +324,15 @@ void SparcInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
numSubRegs = 4;
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
llvm_unreachable("Impossible reg-to-reg copy");
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td
index 653b1856774..3b9e048ea8b 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.td
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td
@@ -560,12 +560,12 @@ let Defs = [Y, ICC] in {
}
// Section B.19 - Divide Instructions, p. 115
-let Defs = [Y] in {
+let Uses = [Y], Defs = [Y] in {
defm UDIV : F3_12np<"udiv", 0b001110>;
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 SDIVCC : F3_12np<"sdivcc", 0b011111>;
}
diff --git a/llvm/lib/Target/Sparc/SparcRegisterInfo.td b/llvm/lib/Target/Sparc/SparcRegisterInfo.td
index e504da4d3b2..db8a7e86962 100644
--- a/llvm/lib/Target/Sparc/SparcRegisterInfo.td
+++ b/llvm/lib/Target/Sparc/SparcRegisterInfo.td
@@ -249,4 +249,6 @@ def FCCRegs : RegisterClass<"SP", [i1], 1, (sequence "FCC%u", 0, 3)>;
// Ancillary state registers
def ASRRegs : RegisterClass<"SP", [i32], 32,
- (add Y, (sequence "ASR%u", 1, 31))>;
+ (add Y, (sequence "ASR%u", 1, 31))> {
+ let isAllocatable = 0;
+}
diff --git a/llvm/test/CodeGen/SPARC/basictest.ll b/llvm/test/CodeGen/SPARC/basictest.ll
index 7b540074a35..3792100b2e6 100644
--- a/llvm/test/CodeGen/SPARC/basictest.ll
+++ b/llvm/test/CodeGen/SPARC/basictest.ll
@@ -38,7 +38,7 @@ entry:
; CHECK-LABEL: signed_divide:
; CHECK: sra %o0, 31, %o2
-; CHECK: wr %o2, %g0, %y
+; CHECK: wr %g0, %o2, %y
; CHECK: sdiv %o0, %o1, %o0
define i32 @signed_divide(i32 %a, i32 %b) {
%r = sdiv i32 %a, %b
diff --git a/llvm/test/CodeGen/SPARC/multiple-div.ll b/llvm/test/CodeGen/SPARC/multiple-div.ll
new file mode 100644
index 00000000000..6934f69ac18
--- /dev/null
+++ b/llvm/test/CodeGen/SPARC/multiple-div.ll
@@ -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
+}
OpenPOWER on IntegriCloud