diff --git a/llvm/lib/Target/SystemZ/SystemZShortenInst.cpp b/llvm/lib/Target/SystemZ/SystemZShortenInst.cpp --- a/llvm/lib/Target/SystemZ/SystemZShortenInst.cpp +++ b/llvm/lib/Target/SystemZ/SystemZShortenInst.cpp @@ -46,6 +46,7 @@ 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 @@ 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 @@ 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 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/shorten-fused-fp-ops.mir @@ -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 + +...