[SystemZ] Use DSGFR over DSGR in more cases
authorRichard Sandiford <rsandifo@linux.vnet.ibm.com>
Tue, 2 Jul 2013 15:40:22 +0000 (15:40 +0000)
committerRichard Sandiford <rsandifo@linux.vnet.ibm.com>
Tue, 2 Jul 2013 15:40:22 +0000 (15:40 +0000)
Fixes some cases where we were using full 64-bit division for (sdiv i32, i32)
and (sdiv i64, i32).

The "32" in "SDIVREM32" just refers to the second operand.  The first operand
of all *DIVREM*s is a GR128.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185435 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/SystemZ/SystemZISelLowering.cpp
lib/Target/SystemZ/SystemZISelLowering.h
lib/Target/SystemZ/SystemZInstrInfo.td
lib/Target/SystemZ/SystemZOperators.td
test/CodeGen/SystemZ/int-div-01.ll
test/CodeGen/SystemZ/int-div-03.ll

index 955b88e1630af085a501cdae0fb37ba2aff0dd9a..da4ad38e46567f0884c3e7b29378e6dac561ec99 100644 (file)
@@ -1269,18 +1269,23 @@ SDValue SystemZTargetLowering::lowerSDIVREM(SDValue Op,
   SDValue Op1 = Op.getOperand(1);
   EVT VT = Op.getValueType();
   SDLoc DL(Op);
+  unsigned Opcode;
 
   // We use DSGF for 32-bit division.
   if (is32Bit(VT)) {
     Op0 = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, Op0);
-    Op1 = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, Op1);
-  }
+    Opcode = SystemZISD::SDIVREM32;
+  } else if (DAG.ComputeNumSignBits(Op1) > 32) {
+    Op1 = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Op1);
+    Opcode = SystemZISD::SDIVREM32;
+  } else    
+    Opcode = SystemZISD::SDIVREM64;
 
   // DSG(F) takes a 64-bit dividend, so the even register in the GR128
   // input is "don't care".  The instruction returns the remainder in
   // the even register and the quotient in the odd register.
   SDValue Ops[2];
-  lowerGR128Binary(DAG, DL, VT, SystemZ::AEXT128_64, SystemZISD::SDIVREM64,
+  lowerGR128Binary(DAG, DL, VT, SystemZ::AEXT128_64, Opcode,
                    Op0, Op1, Ops[1], Ops[0]);
   return DAG.getMergeValues(Ops, 2, DL);
 }
index f6c49f066a92a095c37929105ef6f0dc1a894bb9..21b4d7245023adeaac797480920019e5eac4a506 100644 (file)
@@ -68,6 +68,7 @@ namespace SystemZISD {
     // first input operands are GR128s.  The trailing numbers are the
     // widths of the second operand in bits.
     UMUL_LOHI64,
+    SDIVREM32,
     SDIVREM64,
     UDIVREM32,
     UDIVREM64,
index 1b53eb0a428e7fc955264c014e1d5f5df09e2254..44be5da4e255122acfebb78390f36f47d4e873f3 100644 (file)
@@ -750,14 +750,13 @@ def MLG : BinaryRXY<"mlg", 0xE386, z_umul_lohi64, GR128, load>;
 //===----------------------------------------------------------------------===//
 
 // Division and remainder, from registers.
-def DSGFR : BinaryRRE<"dsgfr", 0xB91D, null_frag,   GR128, GR32>;
+def DSGFR : BinaryRRE<"dsgfr", 0xB91D, z_sdivrem32, GR128, GR32>;
 def DSGR  : BinaryRRE<"dsgr",  0xB90D, z_sdivrem64, GR128, GR64>;
 def DLR   : BinaryRRE<"dlr",   0xB997, z_udivrem32, GR128, GR32>;
 def DLGR  : BinaryRRE<"dlgr",  0xB987, z_udivrem64, GR128, GR64>;
-defm : SXB<z_sdivrem64, GR128, DSGFR>;
 
 // Division and remainder, from memory.
-def DSGF : BinaryRXY<"dsgf", 0xE31D, z_sdivrem64, GR128, sextloadi32>;
+def DSGF : BinaryRXY<"dsgf", 0xE31D, z_sdivrem32, GR128, load>;
 def DSG  : BinaryRXY<"dsg",  0xE30D, z_sdivrem64, GR128, load>;
 def DL   : BinaryRXY<"dl",   0xE397, z_udivrem32, GR128, load>;
 def DLG  : BinaryRXY<"dlg",  0xE387, z_udivrem64, GR128, load>;
index 021824e23c5da86ee86299d55c8423ba2fbdd10b..a84af7a806718053f3f63f5f283413781e5ec9b2 100644 (file)
@@ -81,6 +81,7 @@ def z_adjdynalloc       : SDNode<"SystemZISD::ADJDYNALLOC", SDT_ZAdjDynAlloc>;
 def z_extract_access    : SDNode<"SystemZISD::EXTRACT_ACCESS",
                                  SDT_ZExtractAccess>;
 def z_umul_lohi64       : SDNode<"SystemZISD::UMUL_LOHI64", SDT_ZGR128Binary64>;
+def z_sdivrem32         : SDNode<"SystemZISD::SDIVREM32", SDT_ZGR128Binary32>;
 def z_sdivrem64         : SDNode<"SystemZISD::SDIVREM64", SDT_ZGR128Binary64>;
 def z_udivrem32         : SDNode<"SystemZISD::UDIVREM32", SDT_ZGR128Binary32>;
 def z_udivrem64         : SDNode<"SystemZISD::UDIVREM64", SDT_ZGR128Binary64>;
index 492ece91497e3668417042359cd2270996386819..9a0066f0d0ae7e5ca31e04ce54ea1789efd73086 100644 (file)
@@ -2,6 +2,8 @@
 ;
 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
 
+declare i32 @foo()
+
 ; Test register division.  The result is in the second of the two registers.
 define void @f1(i32 *%dest, i32 %a, i32 %b) {
 ; CHECK: f1:
@@ -188,3 +190,19 @@ define i32 @f14(i32 %dummy, i32 %a, i64 %src, i64 %index) {
   %rem = srem i32 %a, %b
   ret i32 %rem
 }
+
+; Make sure that we still use DSGFR rather than DSGR in cases where
+; a load and division cannot be combined.
+define void @f15(i32 *%dest, i32 *%src) {
+; CHECK: f15:
+; CHECK: l [[B:%r[0-9]+]], 0(%r3)
+; CHECK: brasl %r14, foo@PLT
+; CHECK: lgfr %r1, %r2
+; CHECK: dsgfr %r0, [[B]]
+; CHECK: br %r14
+  %b = load i32 *%src
+  %a = call i32 @foo()
+  %div = sdiv i32 %a, %b
+  store i32 %div, i32 *%dest
+  ret void
+}
index b950f2b02035ded3fe46bac64b4d4dc9173d01af..652fddc1be316212dc8ac9e4d0ac9899bead1e70 100644 (file)
@@ -3,6 +3,8 @@
 ;
 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
 
+declare i64 @foo()
+
 ; Test register division.  The result is in the second of the two registers.
 define void @f1(i64 %dummy, i64 %a, i32 %b, i64 *%dest) {
 ; CHECK: f1:
@@ -187,3 +189,20 @@ define i64 @f14(i64 %dummy, i64 %a, i64 %src, i64 %index) {
   %rem = srem i64 %a, %bext
   ret i64 %rem
 }
+
+; Make sure that we still use DSGFR rather than DSGR in cases where
+; a load and division cannot be combined.
+define void @f15(i64 *%dest, i32 *%src) {
+; CHECK: f15:
+; CHECK: l [[B:%r[0-9]+]], 0(%r3)
+; CHECK: brasl %r14, foo@PLT
+; CHECK: lgr %r1, %r2
+; CHECK: dsgfr %r0, [[B]]
+; CHECK: br %r14
+  %b = load i32 *%src
+  %a = call i64 @foo()
+  %ext = sext i32 %b to i64
+  %div = sdiv i64 %a, %ext
+  store i64 %div, i64 *%dest
+  ret void
+}