[llvm] r185802 - [SystemZ] Use MVC for memcpy

Richard Sandiford rsandifo at linux.vnet.ibm.com
Mon Jul 8 02:35:23 PDT 2013


Author: rsandifo
Date: Mon Jul  8 04:35:23 2013
New Revision: 185802

URL: http://llvm.org/viewvc/llvm-project?rev=185802&view=rev
Log:
[SystemZ] Use MVC for memcpy

Use MVC for memcpy in cases where a single MVC is enough.  Using MVC is
a win for longer copies too, but I'll leave that for later.

Added:
    llvm/trunk/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp
    llvm/trunk/lib/Target/SystemZ/SystemZSelectionDAGInfo.h
    llvm/trunk/test/CodeGen/SystemZ/memcpy-01.ll
Modified:
    llvm/trunk/lib/Target/SystemZ/CMakeLists.txt
    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/SystemZOperands.td
    llvm/trunk/lib/Target/SystemZ/SystemZOperators.td
    llvm/trunk/lib/Target/SystemZ/SystemZTargetMachine.h

Modified: llvm/trunk/lib/Target/SystemZ/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/CMakeLists.txt?rev=185802&r1=185801&r2=185802&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/CMakeLists.txt (original)
+++ llvm/trunk/lib/Target/SystemZ/CMakeLists.txt Mon Jul  8 04:35:23 2013
@@ -22,6 +22,7 @@ add_llvm_target(SystemZCodeGen
   SystemZLongBranch.cpp
   SystemZMCInstLower.cpp
   SystemZRegisterInfo.cpp
+  SystemZSelectionDAGInfo.cpp
   SystemZSubtarget.cpp
   SystemZTargetMachine.cpp
   )

Modified: llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp?rev=185802&r1=185801&r2=185802&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp Mon Jul  8 04:35:23 2013
@@ -241,6 +241,12 @@ SystemZTargetLowering::SystemZTargetLowe
   setOperationAction(ISD::VASTART, MVT::Other, Custom);
   setOperationAction(ISD::VACOPY,  MVT::Other, Custom);
   setOperationAction(ISD::VAEND,   MVT::Other, Expand);
+
+  // We want to use MVC in preference to even a single load/store pair.
+  MaxStoresPerMemcpy = 0;
+  MaxStoresPerMemcpyOptSize = 0;
+  MaxStoresPerMemmove = 0;
+  MaxStoresPerMemmoveOptSize = 0;
 }
 
 bool SystemZTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const {
@@ -1579,6 +1585,7 @@ const char *SystemZTargetLowering::getTa
     OPCODE(SDIVREM64);
     OPCODE(UDIVREM32);
     OPCODE(UDIVREM64);
+    OPCODE(MVC);
     OPCODE(ATOMIC_SWAPW);
     OPCODE(ATOMIC_LOADW_ADD);
     OPCODE(ATOMIC_LOADW_SUB);
@@ -2143,6 +2150,26 @@ SystemZTargetLowering::emitExt128(Machin
   return MBB;
 }
 
+MachineBasicBlock *
+SystemZTargetLowering::emitMVCWrapper(MachineInstr *MI,
+                                      MachineBasicBlock *MBB) const {
+  const SystemZInstrInfo *TII = TM.getInstrInfo();
+  DebugLoc DL = MI->getDebugLoc();
+
+  MachineOperand DestBase = MI->getOperand(0);
+  uint64_t       DestDisp = MI->getOperand(1).getImm();
+  MachineOperand SrcBase  = MI->getOperand(2);
+  uint64_t       SrcDisp  = MI->getOperand(3).getImm();
+  uint64_t       Length   = MI->getOperand(4).getImm();
+
+  BuildMI(*MBB, MI, DL, TII->get(SystemZ::MVC))
+    .addOperand(DestBase).addImm(DestDisp).addImm(Length)
+    .addOperand(SrcBase).addImm(SrcDisp);
+
+  MI->eraseFromParent();
+  return MBB;
+}
+
 MachineBasicBlock *SystemZTargetLowering::
 EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const {
   switch (MI->getOpcode()) {
@@ -2376,6 +2403,8 @@ EmitInstrWithCustomInserter(MachineInstr
                                    MI->getOperand(1).getMBB()))
       MI->eraseFromParent();
     return MBB;
+  case SystemZ::MVCWrapper:
+    return emitMVCWrapper(MI, MBB);
   default:
     llvm_unreachable("Unexpected instr type to insert");
   }

Modified: llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.h?rev=185802&r1=185801&r2=185802&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.h (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.h Mon Jul  8 04:35:23 2013
@@ -73,6 +73,13 @@ namespace SystemZISD {
     UDIVREM32,
     UDIVREM64,
 
+    // Use MVC to copy bytes from one memory location to another.
+    // The first operand is the target address, the second operand is the
+    // source address, and the third operand is the constant length.
+    // This isn't a memory opcode because we'd need to attach two
+    // MachineMemOperands rather than one.
+    MVC,
+
     // Wrappers around the inner loop of an 8- or 16-bit ATOMIC_SWAP or
     // ATOMIC_LOAD_<op>.
     //
@@ -221,6 +228,8 @@ private:
                                           unsigned BitSize) const;
   MachineBasicBlock *emitAtomicCmpSwapW(MachineInstr *MI,
                                         MachineBasicBlock *BB) const;
+  MachineBasicBlock *emitMVCWrapper(MachineInstr *MI,
+                                    MachineBasicBlock *BB) const;
 };
 } // end namespace llvm
 

Modified: llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td?rev=185802&r1=185801&r2=185802&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td Mon Jul  8 04:35:23 2013
@@ -288,6 +288,12 @@ let mayLoad = 1, mayStore = 1 in
                                       bdaddr12only:$BD2),
                    "mvc\t$BDL1, $BD2", []>;
 
+let mayLoad = 1, mayStore = 1, usesCustomInserter = 1 in
+  def MVCWrapper : Pseudo<(outs), (ins bdaddr12only:$dest, bdaddr12only:$src,
+                                       imm32len8:$length),
+                          [(z_mvc bdaddr12only:$dest, bdaddr12only:$src,
+                                  imm32len8:$length)]>;
+
 //===----------------------------------------------------------------------===//
 // Sign extensions
 //===----------------------------------------------------------------------===//

Modified: llvm/trunk/lib/Target/SystemZ/SystemZOperands.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZOperands.td?rev=185802&r1=185801&r2=185802&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZOperands.td (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZOperands.td Mon Jul  8 04:35:23 2013
@@ -219,6 +219,11 @@ def uimm8    : Immediate<i8, [{}], UIMM8
 // i32 immediates
 //===----------------------------------------------------------------------===//
 
+// Immediates for 8-bit lengths.
+def imm32len8 : Immediate<i32, [{
+  return isUInt<8>(N->getZExtValue() - 1);
+}], NOOP_SDNodeXForm, "U32Imm">;
+
 // Immediates for the lower and upper 16 bits of an i32, with the other
 // bits of the i32 being zero.
 def imm32ll16 : Immediate<i32, [{

Modified: llvm/trunk/lib/Target/SystemZ/SystemZOperators.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZOperators.td?rev=185802&r1=185801&r2=185802&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZOperators.td (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZOperators.td Mon Jul  8 04:35:23 2013
@@ -52,6 +52,10 @@ def SDT_ZAtomicCmpSwapW     : SDTypeProf
                                              SDTCisVT<4, i32>,
                                              SDTCisVT<5, i32>,
                                              SDTCisVT<6, i32>]>;
+def SDT_ZCopy               : SDTypeProfile<0, 3,
+                                            [SDTCisPtrTy<0>,
+                                             SDTCisPtrTy<1>,
+                                             SDTCisVT<2, i32>]>;
 
 //===----------------------------------------------------------------------===//
 // Node definitions
@@ -103,6 +107,9 @@ def z_atomic_loadw_umin : AtomicWOp<"ATO
 def z_atomic_loadw_umax : AtomicWOp<"ATOMIC_LOADW_UMAX">;
 def z_atomic_cmp_swapw  : AtomicWOp<"ATOMIC_CMP_SWAPW", SDT_ZAtomicCmpSwapW>;
 
+def z_mvc               : SDNode<"SystemZISD::MVC", SDT_ZCopy,
+                                 [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
+
 //===----------------------------------------------------------------------===//
 // Pattern fragments
 //===----------------------------------------------------------------------===//

Added: llvm/trunk/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp?rev=185802&view=auto
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp (added)
+++ llvm/trunk/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp Mon Jul  8 04:35:23 2013
@@ -0,0 +1,46 @@
+//===-- SystemZSelectionDAGInfo.cpp - SystemZ SelectionDAG Info -----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SystemZSelectionDAGInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "systemz-selectiondag-info"
+#include "SystemZTargetMachine.h"
+#include "llvm/CodeGen/SelectionDAG.h"
+
+using namespace llvm;
+
+SystemZSelectionDAGInfo::
+SystemZSelectionDAGInfo(const SystemZTargetMachine &TM)
+  : TargetSelectionDAGInfo(TM) {
+}
+
+SystemZSelectionDAGInfo::~SystemZSelectionDAGInfo() {
+}
+
+SDValue SystemZSelectionDAGInfo::
+EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc DL, SDValue Chain,
+                        SDValue Dst, SDValue Src, SDValue Size, unsigned Align,
+                        bool IsVolatile, bool AlwaysInline,
+                        MachinePointerInfo DstPtrInfo,
+                        MachinePointerInfo SrcPtrInfo) const {
+  if (IsVolatile)
+    return SDValue();
+
+  if (ConstantSDNode *CSize = dyn_cast<ConstantSDNode>(Size)) {
+    uint64_t Bytes = CSize->getZExtValue();
+    if (Bytes >= 1 && Bytes <= 0x100) {
+      // A single MVC.
+      return DAG.getNode(SystemZISD::MVC, DL, MVT::Other,
+                         Chain, Dst, Src, Size);
+    }
+  }
+  return SDValue();
+}

Added: llvm/trunk/lib/Target/SystemZ/SystemZSelectionDAGInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZSelectionDAGInfo.h?rev=185802&view=auto
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZSelectionDAGInfo.h (added)
+++ llvm/trunk/lib/Target/SystemZ/SystemZSelectionDAGInfo.h Mon Jul  8 04:35:23 2013
@@ -0,0 +1,40 @@
+//===-- SystemZSelectionDAGInfo.h - SystemZ SelectionDAG Info ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the SystemZ subclass for TargetSelectionDAGInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SYSTEMZSELECTIONDAGINFO_H
+#define SYSTEMZSELECTIONDAGINFO_H
+
+#include "llvm/Target/TargetSelectionDAGInfo.h"
+
+namespace llvm {
+
+class SystemZTargetMachine;
+
+class SystemZSelectionDAGInfo : public TargetSelectionDAGInfo {
+public:
+  explicit SystemZSelectionDAGInfo(const SystemZTargetMachine &TM);
+  ~SystemZSelectionDAGInfo();
+
+  virtual
+  SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc DL, SDValue Chain,
+                                  SDValue Dst, SDValue Src,
+                                  SDValue Size, unsigned Align,
+                                  bool IsVolatile, bool AlwaysInline,
+                                  MachinePointerInfo DstPtrInfo,
+                                  MachinePointerInfo SrcPtrInfo) const
+    LLVM_OVERRIDE;
+};
+
+}
+
+#endif

Modified: llvm/trunk/lib/Target/SystemZ/SystemZTargetMachine.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZTargetMachine.h?rev=185802&r1=185801&r2=185802&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZTargetMachine.h (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZTargetMachine.h Mon Jul  8 04:35:23 2013
@@ -20,10 +20,10 @@
 #include "SystemZInstrInfo.h"
 #include "SystemZRegisterInfo.h"
 #include "SystemZSubtarget.h"
+#include "SystemZSelectionDAGInfo.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/Target/TargetFrameLowering.h"
 #include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetSelectionDAGInfo.h"
 
 namespace llvm {
 
@@ -32,7 +32,7 @@ class SystemZTargetMachine : public LLVM
   const DataLayout        DL;
   SystemZInstrInfo        InstrInfo;
   SystemZTargetLowering   TLInfo;
-  TargetSelectionDAGInfo  TSInfo;
+  SystemZSelectionDAGInfo TSInfo;
   SystemZFrameLowering    FrameLowering;
 
 public:

Added: llvm/trunk/test/CodeGen/SystemZ/memcpy-01.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/memcpy-01.ll?rev=185802&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/memcpy-01.ll (added)
+++ llvm/trunk/test/CodeGen/SystemZ/memcpy-01.ll Mon Jul  8 04:35:23 2013
@@ -0,0 +1,82 @@
+; Test memcpy using MVC.
+;
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8 *nocapture, i8 *nocapture, i32, i32, i1) nounwind
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8 *nocapture, i8 *nocapture, i64, i32, i1) nounwind
+
+define void @f1(i8 *%dest, i8 *%src) {
+; CHECK: f1:
+; CHECK-NOT: %r2
+; CHECK-NOT: %r3
+; CHECK: br %r14
+  call void @llvm.memcpy.p0i8.p0i8.i32(i8 *%dest, i8 *%src, i32 0, i32 1,
+                                       i1 false)
+  ret void
+}
+
+define void @f2(i8 *%dest, i8 *%src) {
+; CHECK: f2:
+; CHECK-NOT: %r2
+; CHECK-NOT: %r3
+; CHECK: br %r14
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8 *%dest, i8 *%src, i64 0, i32 1,
+                                       i1 false)
+  ret void
+}
+
+define void @f3(i8 *%dest, i8 *%src) {
+; CHECK: f3:
+; CHECK: mvc 0(1,%r2), 0(%r3)
+; CHECK: br %r14
+  call void @llvm.memcpy.p0i8.p0i8.i32(i8 *%dest, i8 *%src, i32 1, i32 1,
+                                       i1 false)
+  ret void
+}
+
+define void @f4(i8 *%dest, i8 *%src) {
+; CHECK: f4:
+; CHECK: mvc 0(1,%r2), 0(%r3)
+; CHECK: br %r14
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8 *%dest, i8 *%src, i64 1, i32 1,
+                                       i1 false)
+  ret void
+}
+
+define void @f5(i8 *%dest, i8 *%src) {
+; CHECK: f5:
+; CHECK: mvc 0(256,%r2), 0(%r3)
+; CHECK: br %r14
+  call void @llvm.memcpy.p0i8.p0i8.i32(i8 *%dest, i8 *%src, i32 256, i32 1,
+                                       i1 false)
+  ret void
+}
+
+define void @f6(i8 *%dest, i8 *%src) {
+; CHECK: f6:
+; CHECK: mvc 0(256,%r2), 0(%r3)
+; CHECK: br %r14
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8 *%dest, i8 *%src, i64 256, i32 1,
+                                       i1 false)
+  ret void
+}
+
+; 257 bytes is too big for a single MVC.  For now expect none, so that
+; the test fails and gets updated when large copies are implemented.
+define void @f7(i8 *%dest, i8 *%src) {
+; CHECK: f7:
+; CHECK-NOT: mvc
+; CHECK: br %r14
+  call void @llvm.memcpy.p0i8.p0i8.i32(i8 *%dest, i8 *%src, i32 257, i32 1,
+                                       i1 false)
+  ret void
+}
+
+define void @f8(i8 *%dest, i8 *%src) {
+; CHECK: f8:
+; CHECK-NOT: mvc
+; CHECK: br %r14
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8 *%dest, i8 *%src, i64 257, i32 1,
+                                       i1 false)
+  ret void
+}





More information about the llvm-commits mailing list