[llvm] r241686 - [SPARC] Cleanup handling of the Y/ASR registers.

James Y Knight jyknight at google.com
Wed Jul 8 09:25:12 PDT 2015


Author: jyknight
Date: Wed Jul  8 11:25:12 2015
New Revision: 241686

URL: http://llvm.org/viewvc/llvm-project?rev=241686&view=rev
Log:
[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

Added:
    llvm/trunk/test/CodeGen/SPARC/multiple-div.ll
Modified:
    llvm/trunk/lib/Target/Sparc/SparcISelDAGToDAG.cpp
    llvm/trunk/lib/Target/Sparc/SparcInstrInfo.cpp
    llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td
    llvm/trunk/lib/Target/Sparc/SparcRegisterInfo.td
    llvm/trunk/test/CodeGen/SPARC/basictest.ll

Modified: llvm/trunk/lib/Target/Sparc/SparcISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Sparc/SparcISelDAGToDAG.cpp?rev=241686&r1=241685&r2=241686&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Sparc/SparcISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/Sparc/SparcISelDAGToDAG.cpp Wed Jul  8 11:25:12 2015
@@ -168,10 +168,9 @@ SDNode *SparcDAGToDAGISel::Select(SDNode
     } 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
     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;
   }
   }
 

Modified: llvm/trunk/lib/Target/Sparc/SparcInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Sparc/SparcInstrInfo.cpp?rev=241686&r1=241685&r2=241686&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Sparc/SparcInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/Sparc/SparcInstrInfo.cpp Wed Jul  8 11:25:12 2015
@@ -324,6 +324,15 @@ void SparcInstrInfo::copyPhysReg(Machine
       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");
 

Modified: llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td?rev=241686&r1=241685&r2=241686&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td (original)
+++ llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td Wed Jul  8 11:25:12 2015
@@ -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>;
 }

Modified: llvm/trunk/lib/Target/Sparc/SparcRegisterInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Sparc/SparcRegisterInfo.td?rev=241686&r1=241685&r2=241686&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Sparc/SparcRegisterInfo.td (original)
+++ llvm/trunk/lib/Target/Sparc/SparcRegisterInfo.td Wed Jul  8 11:25:12 2015
@@ -249,4 +249,6 @@ def FCCRegs : RegisterClass<"SP", [i1],
 
 // 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;
+}

Modified: llvm/trunk/test/CodeGen/SPARC/basictest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SPARC/basictest.ll?rev=241686&r1=241685&r2=241686&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SPARC/basictest.ll (original)
+++ llvm/trunk/test/CodeGen/SPARC/basictest.ll Wed Jul  8 11:25:12 2015
@@ -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

Added: llvm/trunk/test/CodeGen/SPARC/multiple-div.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SPARC/multiple-div.ll?rev=241686&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/SPARC/multiple-div.ll (added)
+++ llvm/trunk/test/CodeGen/SPARC/multiple-div.ll Wed Jul  8 11:25:12 2015
@@ -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
+}





More information about the llvm-commits mailing list