[SystemZ] Perform instruction shortening for fused fp ops.
authorJonas Paulsson <paulsson@linux.vnet.ibm.com>
Wed, 18 Mar 2020 15:41:32 +0000 (16:41 +0100)
committerJonas Paulsson <paulsson@linux.vnet.ibm.com>
Mon, 23 Mar 2020 13:12:13 +0000 (14:12 +0100)
Replace single-lane (W... form) vector "multiply and add" and "multiply and
subtract" instructions with equivalent floating point instructions whenever
possible in SystemZShortenInst.

Review: Ulrich Weigand

Differential Revision: https://reviews.llvm.org/D76370

llvm/lib/Target/SystemZ/SystemZShortenInst.cpp
llvm/test/CodeGen/SystemZ/shorten-fused-fp-ops.mir [new file with mode: 0644]

index f6184ce..092d3a2 100644 (file)
@@ -46,6 +46,7 @@ private:
   bool shortenOn001(MachineInstr &MI, unsigned Opcode);
   bool shortenOn001AddCC(MachineInstr &MI, unsigned Opcode);
   bool shortenFPConv(MachineInstr &MI, unsigned Opcode);
+  bool shortenFusedFPOp(MachineInstr &MI, unsigned Opcode);
 
   const SystemZInstrInfo *TII;
   const TargetRegisterInfo *TRI;
@@ -175,6 +176,32 @@ bool SystemZShortenInst::shortenFPConv(MachineInstr &MI, unsigned Opcode) {
   return false;
 }
 
+bool SystemZShortenInst::shortenFusedFPOp(MachineInstr &MI, unsigned Opcode) {
+  MachineOperand &DstMO = MI.getOperand(0);
+  MachineOperand &LHSMO = MI.getOperand(1);
+  MachineOperand &RHSMO = MI.getOperand(2);
+  MachineOperand &AccMO = MI.getOperand(3);
+  if (SystemZMC::getFirstReg(DstMO.getReg()) < 16 &&
+      SystemZMC::getFirstReg(LHSMO.getReg()) < 16 &&
+      SystemZMC::getFirstReg(RHSMO.getReg()) < 16 &&
+      SystemZMC::getFirstReg(AccMO.getReg()) < 16 &&
+      DstMO.getReg() == AccMO.getReg()) {
+    MachineOperand Lhs(LHSMO);
+    MachineOperand Rhs(RHSMO);
+    MachineOperand Src(AccMO);
+    MI.RemoveOperand(3);
+    MI.RemoveOperand(2);
+    MI.RemoveOperand(1);
+    MI.setDesc(TII->get(Opcode));
+    MachineInstrBuilder(*MI.getParent()->getParent(), &MI)
+        .add(Src)
+        .add(Lhs)
+        .add(Rhs);
+    return true;
+  }
+  return false;
+}
+
 // Process all instructions in MBB.  Return true if something changed.
 bool SystemZShortenInst::processBlock(MachineBasicBlock &MBB) {
   bool Changed = false;
@@ -235,6 +262,22 @@ bool SystemZShortenInst::processBlock(MachineBasicBlock &MBB) {
       Changed |= shortenOn001(MI, SystemZ::MEEBR);
       break;
 
+    case SystemZ::WFMADB:
+      Changed |= shortenFusedFPOp(MI, SystemZ::MADBR);
+      break;
+
+    case SystemZ::WFMASB:
+      Changed |= shortenFusedFPOp(MI, SystemZ::MAEBR);
+      break;
+
+    case SystemZ::WFMSDB:
+      Changed |= shortenFusedFPOp(MI, SystemZ::MSDBR);
+      break;
+
+    case SystemZ::WFMSSB:
+      Changed |= shortenFusedFPOp(MI, SystemZ::MSEBR);
+      break;
+
     case SystemZ::WFLCDB:
       Changed |= shortenOn01(MI, SystemZ::LCDFR);
       break;
diff --git a/llvm/test/CodeGen/SystemZ/shorten-fused-fp-ops.mir b/llvm/test/CodeGen/SystemZ/shorten-fused-fp-ops.mir
new file mode 100644 (file)
index 0000000..c55bb78
--- /dev/null
@@ -0,0 +1,60 @@
+# RUN: llc -mtriple=s390x-linux-gnu -mcpu=z14 -start-before=postrapseudos %s -o - \
+# RUN:   | FileCheck %s
+#
+# Test shortening of fused fp operations.
+
+--- |
+  define double @fun0(double %f1, double %f2, double %acc) { ret double 0.0 }
+...
+
+# CHECK-LABEL: fun0:
+# CHECK:      madbr   %f0, %f4, %f2
+# CHECK-NEXT: wfmadb  %f0, %f4, %v16, %f0
+# CHECK-NEXT: wfmadb  %f0, %f4, %f0, %f2
+# CHECK-NEXT: maebr   %f0, %f4, %f2
+# CHECK-NEXT: wfmasb  %f0, %f4, %v16, %f0
+# CHECK-NEXT: wfmasb  %f0, %f4, %f0, %f2
+# CHECK-NEXT: msdbr   %f0, %f4, %f2
+# CHECK-NEXT: wfmsdb  %f0, %f4, %v16, %f0
+# CHECK-NEXT: wfmsdb  %f0, %f4, %f0, %f2
+# CHECK-NEXT: msebr   %f0, %f4, %f2
+# CHECK-NEXT: wfmssb  %f0, %f4, %v16, %f0
+# CHECK-NEXT: wfmssb  %f0, %f4, %f0, %f2
+# CHECK-NEXT: br      %r14
+---
+name:            fun0
+alignment:       16
+tracksRegLiveness: true
+liveins:
+  - { reg: '$f0d' }
+  - { reg: '$f2d' }
+  - { reg: '$f4d' }
+frameInfo:
+  maxAlignment:    1
+  maxCallFrameSize: 0
+fixedStack:
+  - { id: 0, offset: -160, size: 8, alignment: 8 }
+machineFunctionInfo: {}
+body:             |
+  bb.0 (%ir-block.0):
+    liveins: $f0d, $f2d, $f4d, $f16d
+  
+    renamable $f0d = nofpexcept WFMADB renamable $f4d, renamable $f2d, renamable $f0d, implicit $fpc
+    renamable $f0d = nofpexcept WFMADB renamable $f4d, renamable $f16d, renamable $f0d, implicit $fpc
+    renamable $f0d = nofpexcept WFMADB renamable $f4d, renamable $f0d, renamable $f2d, implicit $fpc
+
+    renamable $f0s = nofpexcept WFMASB renamable $f4s, renamable $f2s, renamable $f0s, implicit $fpc
+    renamable $f0s = nofpexcept WFMASB renamable $f4s, renamable $f16s, renamable $f0s, implicit $fpc
+    renamable $f0s = nofpexcept WFMASB renamable $f4s, renamable $f0s, renamable $f2s, implicit $fpc
+
+    renamable $f0d = nofpexcept WFMSDB renamable $f4d, renamable $f2d, renamable $f0d, implicit $fpc
+    renamable $f0d = nofpexcept WFMSDB renamable $f4d, renamable $f16d, renamable $f0d, implicit $fpc
+    renamable $f0d = nofpexcept WFMSDB renamable $f4d, renamable $f0d, renamable $f2d, implicit $fpc
+
+    renamable $f0s = nofpexcept WFMSSB renamable $f4s, renamable $f2s, renamable $f0s, implicit $fpc
+    renamable $f0s = nofpexcept WFMSSB renamable $f4s, renamable $f16s, renamable $f0s, implicit $fpc
+    renamable $f0s = nofpexcept WFMSSB renamable $f4s, renamable $f0s, renamable $f2s, implicit $fpc
+
+    Return implicit $f0d
+
+...