[llvm] r185435 - [SystemZ] Use DSGFR over DSGR in more cases

Richard Sandiford rsandifo at linux.vnet.ibm.com
Tue Jul 2 08:40:22 PDT 2013


Author: rsandifo
Date: Tue Jul  2 10:40:22 2013
New Revision: 185435

URL: http://llvm.org/viewvc/llvm-project?rev=185435&view=rev
Log:
[SystemZ] Use DSGFR over DSGR in more cases

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.

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

Modified: llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp?rev=185435&r1=185434&r2=185435&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp Tue Jul  2 10:40:22 2013
@@ -1269,18 +1269,23 @@ SDValue SystemZTargetLowering::lowerSDIV
   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);
 }

Modified: llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.h?rev=185435&r1=185434&r2=185435&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.h (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.h Tue Jul  2 10:40:22 2013
@@ -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,

Modified: llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td?rev=185435&r1=185434&r2=185435&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td Tue Jul  2 10:40:22 2013
@@ -750,14 +750,13 @@ def MLG : BinaryRXY<"mlg", 0xE386, z_umu
 //===----------------------------------------------------------------------===//
 
 // 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>;

Modified: llvm/trunk/lib/Target/SystemZ/SystemZOperators.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZOperators.td?rev=185435&r1=185434&r2=185435&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZOperators.td (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZOperators.td Tue Jul  2 10:40:22 2013
@@ -81,6 +81,7 @@ def z_adjdynalloc       : SDNode<"System
 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>;

Modified: llvm/trunk/test/CodeGen/SystemZ/int-div-01.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/int-div-01.ll?rev=185435&r1=185434&r2=185435&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/int-div-01.ll (original)
+++ llvm/trunk/test/CodeGen/SystemZ/int-div-01.ll Tue Jul  2 10:40:22 2013
@@ -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
   %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 at 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
+}

Modified: llvm/trunk/test/CodeGen/SystemZ/int-div-03.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/int-div-03.ll?rev=185435&r1=185434&r2=185435&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/int-div-03.ll (original)
+++ llvm/trunk/test/CodeGen/SystemZ/int-div-03.ll Tue Jul  2 10:40:22 2013
@@ -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
   %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 at 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
+}





More information about the llvm-commits mailing list