Support shr long/ulong.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@18173 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/Sparc/SparcV8ISelSimple.cpp b/lib/Target/Sparc/SparcV8ISelSimple.cpp
index 840c7a3..bca63db 100644
--- a/lib/Target/Sparc/SparcV8ISelSimple.cpp
+++ b/lib/Target/Sparc/SparcV8ISelSimple.cpp
@@ -1119,58 +1119,124 @@
   bool isSigned = I.getType()->isSigned();
 
   switch (I.getOpcode ()) {
+  case Instruction::Shr: {
+    unsigned CarryReg = makeAnotherReg (Type::IntTy),
+             ThirtyTwo = makeAnotherReg (Type::IntTy),
+             HalfShiftReg = makeAnotherReg (Type::IntTy),
+             NegHalfShiftReg = makeAnotherReg (Type::IntTy),
+             TempReg = makeAnotherReg (Type::IntTy);
+    unsigned OneShiftOutReg = makeAnotherReg (Type::ULongTy),
+             TwoShiftsOutReg = makeAnotherReg (Type::ULongTy);
+
+    MachineBasicBlock *thisMBB = BB;
+    const BasicBlock *LLVM_BB = BB->getBasicBlock ();
+    MachineBasicBlock *shiftMBB = new MachineBasicBlock (LLVM_BB);
+    F->getBasicBlockList ().push_back (shiftMBB);
+    MachineBasicBlock *oneShiftMBB = new MachineBasicBlock (LLVM_BB);
+    F->getBasicBlockList ().push_back (oneShiftMBB);
+    MachineBasicBlock *twoShiftsMBB = new MachineBasicBlock (LLVM_BB);
+    F->getBasicBlockList ().push_back (twoShiftsMBB);
+    MachineBasicBlock *continueMBB = new MachineBasicBlock (LLVM_BB);
+    F->getBasicBlockList ().push_back (continueMBB);
+
+    // .lshr_begin:
+    //   ...
+    //   subcc %g0, ShiftAmtReg, %g0                   ! Is ShAmt == 0?
+    //   be .lshr_continue                             ! Then don't shift.
+    //   ba .lshr_shift                                ! else shift.
+
+    BuildMI (BB, V8::SUBCCrr, 2, V8::G0).addReg (V8::G0)
+      .addReg (ShiftAmtReg);
+    BuildMI (BB, V8::BE, 1).addMBB (continueMBB);
+    BuildMI (BB, V8::BA, 1).addMBB (shiftMBB);
+
+    // Update machine-CFG edges
+    BB->addSuccessor (continueMBB);
+    BB->addSuccessor (shiftMBB);
+
+    // .lshr_shift: ! [preds: begin]
+    //   or %g0, 32, ThirtyTwo
+    //   subcc ThirtyTwo, ShiftAmtReg, HalfShiftReg    ! Calculate 32 - shamt
+    //   bg .lshr_two_shifts                           ! If >0, b two_shifts
+    //   ba .lshr_one_shift                            ! else one_shift.
+
+    BB = shiftMBB;
+
+    BuildMI (BB, V8::ORri, 2, ThirtyTwo).addReg (V8::G0).addSImm (32);
+    BuildMI (BB, V8::SUBCCrr, 2, HalfShiftReg).addReg (ThirtyTwo)
+      .addReg (ShiftAmtReg);
+    BuildMI (BB, V8::BG, 1).addMBB (twoShiftsMBB);
+    BuildMI (BB, V8::BA, 1).addMBB (oneShiftMBB);
+
+    // Update machine-CFG edges
+    BB->addSuccessor (twoShiftsMBB);
+    BB->addSuccessor (oneShiftMBB);
+
+    // .lshr_two_shifts: ! [preds: shift]
+    //   sll SrcReg, HalfShiftReg, CarryReg            ! Save the borrows
+    //  ! <SHIFT> in following is sra if signed, srl if unsigned
+    //   <SHIFT> SrcReg, ShiftAmtReg, TwoShiftsOutReg  ! Shift top half
+    //   srl SrcReg+1, ShiftAmtReg, TempReg            ! Shift bottom half
+    //   or TempReg, CarryReg, TwoShiftsOutReg+1       ! Restore the borrows
+    //   ba .lshr_continue
+    unsigned ShiftOpcode = (isSigned ? V8::SRArr : V8::SRLrr);
+
+    BB = twoShiftsMBB;
+
+    BuildMI (BB, V8::SLLrr, 2, CarryReg).addReg (SrcReg)
+      .addReg (HalfShiftReg);
+    BuildMI (BB, ShiftOpcode, 2, TwoShiftsOutReg).addReg (SrcReg)
+      .addReg (ShiftAmtReg);
+    BuildMI (BB, V8::SRLrr, 2, TempReg).addReg (SrcReg+1)
+      .addReg (ShiftAmtReg);
+    BuildMI (BB, V8::ORrr, 2, TwoShiftsOutReg+1).addReg (TempReg)
+      .addReg (CarryReg);
+    BuildMI (BB, V8::BA, 1).addMBB (continueMBB);
+
+    // Update machine-CFG edges
+    BB->addSuccessor (continueMBB);
+
+    // .lshr_one_shift: ! [preds: shift]
+    //  ! if unsigned:
+    //   or %g0, %g0, OneShiftOutReg                       ! Zero top half
+    //  ! or, if signed:
+    //   sra SrcReg, 31, OneShiftOutReg                    ! Sign-ext top half
+    //   sub %g0, HalfShiftReg, NegHalfShiftReg            ! Make ShiftAmt >0
+    //   <SHIFT> SrcReg, NegHalfShiftReg, OneShiftOutReg+1 ! Shift bottom half
+    //   ba .lshr_continue
+
+    BB = oneShiftMBB;
+    
+    if (isSigned)
+      BuildMI (BB, V8::SRAri, 2, OneShiftOutReg).addReg (SrcReg).addZImm (31);
+    else
+      BuildMI (BB, V8::ORrr, 2, OneShiftOutReg).addReg (V8::G0)
+        .addReg (V8::G0);
+    BuildMI (BB, V8::SUBrr, 2, NegHalfShiftReg).addReg (V8::G0)
+      .addReg (HalfShiftReg);
+    BuildMI (BB, ShiftOpcode, 2, OneShiftOutReg+1).addReg (SrcReg)
+      .addReg (NegHalfShiftReg);
+    BuildMI (BB, V8::BA, 1).addMBB (continueMBB);
+
+    // Update machine-CFG edges
+    BB->addSuccessor (continueMBB);
+
+    // .lshr_continue: ! [preds: begin, do_one_shift, do_two_shifts]
+    //   phi (SrcReg, begin), (TwoShiftsOutReg, two_shifts),
+    //       (OneShiftOutReg, one_shift), DestReg      ! Phi top half...
+    //   phi (SrcReg+1, begin), (TwoShiftsOutReg+1, two_shifts),
+    //       (OneShiftOutReg+1, one_shift), DestReg+1  ! And phi bottom half.
+
+    BB = continueMBB;
+    BuildMI (BB, V8::PHI, 6, DestReg).addReg (SrcReg).addMBB (thisMBB)
+      .addReg (TwoShiftsOutReg).addMBB (twoShiftsMBB)
+      .addReg (OneShiftOutReg).addMBB (oneShiftMBB);
+    BuildMI (BB, V8::PHI, 6, DestReg+1).addReg (SrcReg+1).addMBB (thisMBB)
+      .addReg (TwoShiftsOutReg+1).addMBB (twoShiftsMBB)
+      .addReg (OneShiftOutReg+1).addMBB (oneShiftMBB);
+    return;
+  }
   case Instruction::Shl:
-  case Instruction::Shr:
-    if (!isSigned) {
-      unsigned CarryReg = makeAnotherReg (Type::IntTy),
-               ThirtyTwo = makeAnotherReg (Type::IntTy),
-               HalfShiftReg = makeAnotherReg (Type::IntTy),
-               NegHalfShiftReg = makeAnotherReg (Type::IntTy),
-               TempReg = makeAnotherReg (Type::IntTy);
-      unsigned OneShiftOutReg = makeAnotherReg (Type::ULongTy),
-               TwoShiftsOutReg = makeAnotherReg (Type::ULongTy);
-
-      /*
-      .lshr_begin:
-      ...
-      // Check whether the shift amount is zero:
-      V8::G0 = V8::SUBCCrr V8::G0, ShiftAmountReg
-      V8::BE .lshr_continue
-      V8::BA .lshr_shift
-
-      .lshr_shift: // [preds: begin]
-      // Calculate 32 - shamt:
-      ThirtyTwo = V8::ORri V8::G0, 32
-      HalfShiftReg = V8::SUBCCrr ThirtyTwo, ShiftAmountReg
-      // See whether it was greater than 0:
-      V8::BG .lshr_two_shifts
-      V8::BA .lshr_one_shift
-
-      .lshr_two_shifts: // [preds: shift]
-      CarryReg = V8::SLLrr SrcReg, HalfShiftReg
-      TwoShiftsOutReg = V8::SRLrr SrcReg, ShiftAmountReg
-      TempReg = V8::SRLrr SrcReg+1, ShiftAmountReg
-      TwoShiftsOutReg+1 = V8::ORrr TempReg, CarryReg
-      V8::BA .lshr_continue
-
-      .lshr_one_shift: // [preds: shift]
-      OneShiftOutReg = V8::ORrr V8::G0, V8::G0
-      NegHalfShiftReg = V8::SUBrr V8::G0, HalfShiftReg
-      OneShiftOutReg+1 = V8::SRLrr SrcReg, NegHalfShiftReg
-      V8::BA .lshr_continue
-
-      .lshr_continue: // [preds: begin, do_one_shift, do_two_shifts]
-      DestReg = V8::PHI (SrcReg, begin), (TwoShiftsOutReg, two_shifts),
-                        (OneShiftOutReg, one_shift)
-      DestReg+1 = V8::PHI (SrcReg+1, begin), (TwoShiftsOutReg+1, two_shifts),
-                          (OneShiftOutReg+1, one_shift)
-      ...
-      */
-
-      std::cerr << "Sorry, 64-bit lshr is not yet supported:\n" << I;
-      abort ();
-      return;
-    }
   default:
     std::cerr << "Sorry, 64-bit shifts are not yet supported:\n" << I;
     abort ();