Provide "wide" muls and divs/rems
authorAnton Korobeynikov <asl@math.spbu.ru>
Thu, 16 Jul 2009 13:56:42 +0000 (13:56 +0000)
committerAnton Korobeynikov <asl@math.spbu.ru>
Thu, 16 Jul 2009 13:56:42 +0000 (13:56 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75958 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/SystemZ/SystemZISelLowering.cpp
lib/Target/SystemZ/SystemZInstrInfo.cpp
lib/Target/SystemZ/SystemZInstrInfo.td
test/CodeGen/SystemZ/08-DivRem.ll [new file with mode: 0644]

index a5999feaa3e2a83147545dda22dd0cedfef8fbc9..62bd46b011cd9f686d8dfd449ca19d3932d33592 100644 (file)
@@ -41,8 +41,9 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) :
   RegInfo = TM.getRegisterInfo();
 
   // Set up the register classes.
-  addRegisterClass(MVT::i32, SystemZ::GR32RegisterClass);
-  addRegisterClass(MVT::i64, SystemZ::GR64RegisterClass);
+  addRegisterClass(MVT::i32,  SystemZ::GR32RegisterClass);
+  addRegisterClass(MVT::i64,  SystemZ::GR64RegisterClass);
+  addRegisterClass(MVT::i128, SystemZ::GR128RegisterClass);
 
   // Compute derived properties from the register classes
   computeRegisterProperties();
@@ -73,16 +74,10 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) :
   setOperationAction(ISD::SELECT_CC,        MVT::i32, Custom);
   setOperationAction(ISD::SELECT_CC,        MVT::i64, Custom);
 
-  // FIXME: We can lower this better
-  setOperationAction(ISD::MULHS,            MVT::i32, Expand);
+  // Funny enough: we don't have 64-bit signed versions of these stuff, but have
+  // unsigned.
   setOperationAction(ISD::MULHS,            MVT::i64, Expand);
-  setOperationAction(ISD::MULHU,            MVT::i32, Expand);
-  setOperationAction(ISD::MULHU,            MVT::i64, Expand);
-
-  setOperationAction(ISD::SMUL_LOHI,        MVT::i32, Expand);
   setOperationAction(ISD::SMUL_LOHI,        MVT::i64, Expand);
-  setOperationAction(ISD::UMUL_LOHI,        MVT::i32, Expand);
-  setOperationAction(ISD::UMUL_LOHI,        MVT::i64, Expand);
 }
 
 SDValue SystemZTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
index 9734709c6b3f64fde73aad55b3b9d8172f16d667..0348e1e5ca898a77919b04060cec84475e5de80f 100644 (file)
@@ -83,18 +83,20 @@ bool SystemZInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
     CommonRC = 0;
 
   if (CommonRC) {
-    unsigned Opc;
     if (CommonRC == &SystemZ::GR64RegClass ||
         CommonRC == &SystemZ::ADDR64RegClass) {
-      Opc = SystemZ::MOV64rr;
+      BuildMI(MBB, I, DL, get(SystemZ::MOV64rr), DestReg).addReg(SrcReg);
     } else if (CommonRC == &SystemZ::GR32RegClass ||
                CommonRC == &SystemZ::ADDR32RegClass) {
-      Opc = SystemZ::MOV32rr;
+      BuildMI(MBB, I, DL, get(SystemZ::MOV32rr), DestReg).addReg(SrcReg);
+    } else if (CommonRC == &SystemZ::GR64PRegClass) {
+      BuildMI(MBB, I, DL, get(SystemZ::MOV64rrP), DestReg).addReg(SrcReg);
+    } else if (CommonRC == &SystemZ::GR128RegClass) {
+      BuildMI(MBB, I, DL, get(SystemZ::MOV128rr), DestReg).addReg(SrcReg);
     } else {
       return false;
     }
 
-    BuildMI(MBB, I, DL, get(Opc), DestReg).addReg(SrcReg);
     return true;
   }
 
@@ -126,6 +128,8 @@ SystemZInstrInfo::isMoveInstr(const MachineInstr& MI,
     return false;
   case SystemZ::MOV32rr:
   case SystemZ::MOV64rr:
+  case SystemZ::MOV64rrP:
+  case SystemZ::MOV128rr:
     assert(MI.getNumOperands() >= 2 &&
            MI.getOperand(0).isReg() &&
            MI.getOperand(1).isReg() &&
index 4b5a9ce3ba9b9bbb7da83e9f3715742786ef9231..f58021cf737ce591e896e43dea9ca8750e7cecae 100644 (file)
@@ -330,6 +330,16 @@ def MOV32rr : Pseudo<(outs GR32:$dst), (ins GR32:$src),
 def MOV64rr : Pseudo<(outs GR64:$dst), (ins GR64:$src),
                      "lgr\t{$dst, $src}",
                      []>;
+def MOV128rr : Pseudo<(outs GR128:$dst), (ins GR128:$src),
+                     "# MOV128 PSEUDO!"
+                     "lgr\t{$dst:subreg_odd, $src:subreg_odd}\n"
+                     "lgr\t{$dst:subreg_even, $src:subreg_even}",
+                     []>;
+def MOV64rrP : Pseudo<(outs GR64P:$dst), (ins GR64P:$src),
+                     "# MOV64P PSEUDO!"
+                     "lr\t{$dst:subreg_odd, $src:subreg_odd}\n"
+                     "lr\t{$dst:subreg_even, $src:subreg_even}",
+                     []>;
 }
 
 def MOVSX64rr32 : Pseudo<(outs GR64:$dst), (ins GR32:$src),
@@ -616,8 +626,19 @@ def MUL32rr : Pseudo<(outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
 def MUL64rr : Pseudo<(outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
                      "msgr\t{$dst, $src2}",
                      [(set GR64:$dst, (mul GR64:$src1, GR64:$src2))]>;
+
+def MUL64rrP   : Pseudo<(outs GR64P:$dst), (ins GR64P:$src1, GR32:$src2),
+                        "mr\t{$dst, $src2}",
+                        []>;
+def UMUL64rrP  : Pseudo<(outs GR64P:$dst), (ins GR64P:$src1, GR32:$src2),
+                         "mlr\t{$dst, $src2}",
+                         []>;
+def UMUL128rrP : Pseudo<(outs GR128:$dst), (ins GR128:$src1, GR64:$src2),
+                        "mlgr\t{$dst, $src2}",
+                        []>;
 }
 
+
 def MUL32ri16   : Pseudo<(outs GR32:$dst), (ins GR32:$src1, i32i16imm:$src2),
                          "mhi\t{$dst, $src2}",
                          [(set GR32:$dst, (mul GR32:$src1, i32immSExt16:$src2))]>;
@@ -641,6 +662,23 @@ def MUL64rm : Pseudo<(outs GR64:$dst), (ins GR64:$src1, rriaddr:$src2),
 def MULSX64rr32 : Pseudo<(outs GR64:$dst), (ins GR64:$src1, GR32:$src2),
                          "msgfr\t{$dst, $src2}",
                          [(set GR64:$dst, (mul GR64:$src1, (sext GR32:$src2)))]>;
+
+def SDIVREM64rrP  : Pseudo<(outs GR64P:$dst), (ins GR64P:$src1, GR32:$src2),
+                           "dr\t{$dst, $src2}",
+                           []>;
+
+def SDIVREM128rrP : Pseudo<(outs GR128:$dst), (ins GR128:$src1, GR64:$src2),
+                           "dsgr\t{$dst, $src2}",
+                           []>;
+
+def UDIVREM64rrP  : Pseudo<(outs GR64P:$dst), (ins GR64P:$src1, GR32:$src2),
+                           "dlr\t{$dst, $src2}",
+                           []>;
+
+def UDIVREM128rrP : Pseudo<(outs GR128:$dst), (ins GR128:$src1, GR64:$src2),
+                           "dlgr\t{$dst, $src2}",
+                           []>;
+
 } // isTwoAddress = 1
 
 //===----------------------------------------------------------------------===//
@@ -794,3 +832,67 @@ def : Pat<(SystemZcall (i64 tglobaladdr:$dst)),
           (CALLi tglobaladdr:$dst)>;
 def : Pat<(SystemZcall (i64 texternalsym:$dst)),
           (CALLi texternalsym:$dst)>;
+
+// muls
+def : Pat<(mulhs GR32:$src1, GR32:$src2),
+          (EXTRACT_SUBREG (MUL64rrP (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
+                                                   GR32:$src1, subreg_odd),
+                                    GR32:$src2),
+                          subreg_even)>;
+
+def : Pat<(mulhu GR32:$src1, GR32:$src2),
+          (EXTRACT_SUBREG (UMUL64rrP (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
+                                                    GR32:$src1, subreg_odd),
+                                     GR32:$src2),
+                          subreg_even)>;
+def : Pat<(mulhu GR64:$src1, GR64:$src2),
+          (EXTRACT_SUBREG (UMUL128rrP (INSERT_SUBREG (i128 (IMPLICIT_DEF)),
+                                                     GR64:$src1, subreg_odd),
+                                      GR64:$src2),
+                          subreg_even)>;
+
+// divs
+// FIXME: Add memory versions
+def : Pat<(sdiv GR32:$src1, GR32:$src2),
+          (EXTRACT_SUBREG (SDIVREM64rrP (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
+                                                       GR32:$src1, subreg_odd),
+                                         GR32:$src2),
+                          subreg_odd)>;
+def : Pat<(sdiv GR64:$src1, GR64:$src2),
+          (EXTRACT_SUBREG (SDIVREM128rrP (INSERT_SUBREG (i128 (IMPLICIT_DEF)),
+                                                        GR64:$src1, subreg_odd),
+                                         GR64:$src2),
+                          subreg_odd)>;
+def : Pat<(udiv GR32:$src1, GR32:$src2),
+          (EXTRACT_SUBREG (UDIVREM64rrP (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
+                                                       GR32:$src1, subreg_odd),
+                                         GR32:$src2),
+                          subreg_odd)>;
+def : Pat<(udiv GR64:$src1, GR64:$src2),
+          (EXTRACT_SUBREG (UDIVREM128rrP (INSERT_SUBREG (i128 (IMPLICIT_DEF)),
+                                                        GR64:$src1, subreg_odd),
+                                         GR64:$src2),
+                          subreg_odd)>;
+
+// rems
+// FIXME: Add memory versions
+def : Pat<(srem GR32:$src1, GR32:$src2),
+          (EXTRACT_SUBREG (SDIVREM64rrP (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
+                                                       GR32:$src1, subreg_odd),
+                                         GR32:$src2),
+                          subreg_even)>;
+def : Pat<(srem GR64:$src1, GR64:$src2),
+          (EXTRACT_SUBREG (SDIVREM128rrP (INSERT_SUBREG (i128 (IMPLICIT_DEF)),
+                                                        GR64:$src1, subreg_odd),
+                                         GR64:$src2),
+                          subreg_even)>;
+def : Pat<(urem GR32:$src1, GR32:$src2),
+          (EXTRACT_SUBREG (UDIVREM64rrP (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
+                                                       GR32:$src1, subreg_odd),
+                                         GR32:$src2),
+                          subreg_even)>;
+def : Pat<(urem GR64:$src1, GR64:$src2),
+          (EXTRACT_SUBREG (UDIVREM128rrP (INSERT_SUBREG (i128 (IMPLICIT_DEF)),
+                                                        GR64:$src1, subreg_odd),
+                                         GR64:$src2),
+                          subreg_even)>;
diff --git a/test/CodeGen/SystemZ/08-DivRem.ll b/test/CodeGen/SystemZ/08-DivRem.ll
new file mode 100644 (file)
index 0000000..ea9214f
--- /dev/null
@@ -0,0 +1,55 @@
+; RUN: llvm-as < %s | llc | grep dsgr | count 2
+; RUN: llvm-as < %s | llc | grep dr   | count 2
+; RUN: llvm-as < %s | llc | grep dlr  | count 2
+; RUN: llvm-as < %s | llc | grep dlgr | count 2
+
+target datalayout = "E-p:64:64:64-i1:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128"
+target triple = "s390x-unknown-linux-gnu"
+
+define i64 @div(i64 %a, i64 %b) nounwind readnone {
+entry:
+       %div = sdiv i64 %a, %b          ; <i64> [#uses=1]
+       ret i64 %div
+}
+
+define i32 @div1(i32 %a, i32 %b) nounwind readnone {
+entry:
+       %div = sdiv i32 %a, %b          ; <i32> [#uses=1]
+       ret i32 %div
+}
+
+define i64 @div2(i64 %a, i64 %b) nounwind readnone {
+entry:
+       %div = udiv i64 %a, %b          ; <i64> [#uses=1]
+       ret i64 %div
+}
+
+define i32 @div3(i32 %a, i32 %b) nounwind readnone {
+entry:
+       %div = udiv i32 %a, %b          ; <i32> [#uses=1]
+       ret i32 %div
+}
+
+define i64 @rem(i64 %a, i64 %b) nounwind readnone {
+entry:
+       %rem = srem i64 %a, %b          ; <i64> [#uses=1]
+       ret i64 %rem
+}
+
+define i32 @rem1(i32 %a, i32 %b) nounwind readnone {
+entry:
+       %rem = srem i32 %a, %b          ; <i32> [#uses=1]
+       ret i32 %rem
+}
+
+define i64 @rem2(i64 %a, i64 %b) nounwind readnone {
+entry:
+       %rem = urem i64 %a, %b          ; <i64> [#uses=1]
+       ret i64 %rem
+}
+
+define i32 @rem3(i32 %a, i32 %b) nounwind readnone {
+entry:
+       %rem = urem i32 %a, %b          ; <i32> [#uses=1]
+       ret i32 %rem
+}