Index: llvm/trunk/lib/Target/Sparc/SparcISelDAGToDAG.cpp =================================================================== --- llvm/trunk/lib/Target/Sparc/SparcISelDAGToDAG.cpp +++ llvm/trunk/lib/Target/Sparc/SparcISelDAGToDAG.cpp @@ -168,10 +168,9 @@ } 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 @@ 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; } } Index: llvm/trunk/lib/Target/Sparc/SparcInstrInfo.cpp =================================================================== --- llvm/trunk/lib/Target/Sparc/SparcInstrInfo.cpp +++ llvm/trunk/lib/Target/Sparc/SparcInstrInfo.cpp @@ -324,6 +324,15 @@ 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"); Index: llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td =================================================================== --- llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td +++ llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td @@ -560,12 +560,12 @@ } // 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>; } Index: llvm/trunk/lib/Target/Sparc/SparcRegisterInfo.td =================================================================== --- llvm/trunk/lib/Target/Sparc/SparcRegisterInfo.td +++ llvm/trunk/lib/Target/Sparc/SparcRegisterInfo.td @@ -249,4 +249,6 @@ // 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; +} Index: llvm/trunk/test/CodeGen/SPARC/basictest.ll =================================================================== --- llvm/trunk/test/CodeGen/SPARC/basictest.ll +++ llvm/trunk/test/CodeGen/SPARC/basictest.ll @@ -38,7 +38,7 @@ ; 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 Index: llvm/trunk/test/CodeGen/SPARC/multiple-div.ll =================================================================== --- llvm/trunk/test/CodeGen/SPARC/multiple-div.ll +++ llvm/trunk/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 +}