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;
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;
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;
--- /dev/null
+# 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
+
+...