From 93c2125c3979bcb4656daf3c2fb5748fb3973e1a Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Fri, 19 Jul 2013 16:12:08 +0000 Subject: [PATCH] [SystemZ] Use SLLK, SRLK and SRAK for codegen This patch uses the instructions added in r186680 for codegen. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186681 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/SystemZ/SystemZInstrFormats.td | 26 ++++++++-- lib/Target/SystemZ/SystemZInstrInfo.cpp | 47 ++++++++++++++++- lib/Target/SystemZ/SystemZInstrInfo.h | 5 ++ test/CodeGen/SystemZ/shift-09.ll | 63 +++++++++++++++++++++++ 4 files changed, 136 insertions(+), 5 deletions(-) create mode 100644 test/CodeGen/SystemZ/shift-09.ll diff --git a/lib/Target/SystemZ/SystemZInstrFormats.td b/lib/Target/SystemZ/SystemZInstrFormats.td index 45147c1a919..b0301821a31 100644 --- a/lib/Target/SystemZ/SystemZInstrFormats.td +++ b/lib/Target/SystemZ/SystemZInstrFormats.td @@ -34,6 +34,12 @@ class InstSystemZ opcode, SDPatternOperator operator, multiclass ShiftRSAndK opcode1, bits<16> opcode2, SDPatternOperator operator, RegisterOperand cls> { - def K : ShiftRSY, - Requires<[FeatureDistinctOps]>; - def "" : ShiftRS; + let NumOpsKey = mnemonic in { + let NumOpsValue = "3" in + def K : ShiftRSY, + Requires<[FeatureDistinctOps]>; + let NumOpsValue = "2", isConvertibleToThreeAddress = 1 in + def "" : ShiftRS; + } } class CompareRR opcode, SDPatternOperator operator, diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index bbac73fcaff..3a502a0117b 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -12,9 +12,10 @@ //===----------------------------------------------------------------------===// #include "SystemZInstrInfo.h" +#include "SystemZTargetMachine.h" #include "SystemZInstrBuilder.h" +#include "llvm/CodeGen/LiveVariables.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/Target/TargetMachine.h" #define GET_INSTRINFO_CTOR #define GET_INSTRMAP_INFO @@ -24,7 +25,7 @@ using namespace llvm; SystemZInstrInfo::SystemZInstrInfo(SystemZTargetMachine &tm) : SystemZGenInstrInfo(SystemZ::ADJCALLSTACKDOWN, SystemZ::ADJCALLSTACKUP), - RI(tm) { + RI(tm), TM(tm) { } // MI is a 128-bit load or store. Split it into two 64-bit loads or stores, @@ -351,6 +352,48 @@ static bool isSimpleBD12Move(const MachineInstr *MI, unsigned Flag) { MI->getOperand(3).getReg() == 0); } +MachineInstr * +SystemZInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, + MachineBasicBlock::iterator &MBBI, + LiveVariables *LV) const { + MachineInstr *MI = MBBI; + MachineBasicBlock *MBB = MI->getParent(); + + unsigned Opcode = MI->getOpcode(); + unsigned NumOps = MI->getNumOperands(); + + // Try to convert something like SLL into SLLK, if supported. + // We prefer to keep the two-operand form where possible both + // because it tends to be shorter and because some instructions + // have memory forms that can be used during spilling. + if (TM.getSubtargetImpl()->hasDistinctOps()) { + int ThreeOperandOpcode = SystemZ::getThreeOperandOpcode(Opcode); + if (ThreeOperandOpcode >= 0) { + unsigned DestReg = MI->getOperand(0).getReg(); + MachineOperand &Src = MI->getOperand(1); + MachineInstrBuilder MIB = BuildMI(*MBB, MBBI, MI->getDebugLoc(), + get(ThreeOperandOpcode), DestReg); + // Keep the kill state, but drop the tied flag. + MIB.addReg(Src.getReg(), getKillRegState(Src.isKill())); + // Keep the remaining operands as-is. + for (unsigned I = 2; I < NumOps; ++I) + MIB.addOperand(MI->getOperand(I)); + MachineInstr *NewMI = MIB; + + // Transfer killing information to the new instruction. + if (LV) { + for (unsigned I = 1; I < NumOps; ++I) { + MachineOperand &Op = MI->getOperand(I); + if (Op.isReg() && Op.isKill()) + LV->replaceKillInstruction(Op.getReg(), MI, NewMI); + } + } + return MIB; + } + } + return 0; +} + MachineInstr * SystemZInstrInfo::foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI, diff --git a/lib/Target/SystemZ/SystemZInstrInfo.h b/lib/Target/SystemZ/SystemZInstrInfo.h index 3fe71d88547..2050e8ec7c6 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.h +++ b/lib/Target/SystemZ/SystemZInstrInfo.h @@ -79,6 +79,7 @@ namespace SystemZII { class SystemZInstrInfo : public SystemZGenInstrInfo { const SystemZRegisterInfo RI; + SystemZTargetMachine &TM; void splitMove(MachineBasicBlock::iterator MI, unsigned NewOpcode) const; void splitAdjDynAlloc(MachineBasicBlock::iterator MI) const; @@ -119,6 +120,10 @@ public: unsigned DestReg, int FrameIdx, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const LLVM_OVERRIDE; + virtual MachineInstr * + convertToThreeAddress(MachineFunction::iterator &MFI, + MachineBasicBlock::iterator &MBBI, + LiveVariables *LV) const; virtual MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI, const SmallVectorImpl &Ops, diff --git a/test/CodeGen/SystemZ/shift-09.ll b/test/CodeGen/SystemZ/shift-09.ll new file mode 100644 index 00000000000..c87cf0d9a1e --- /dev/null +++ b/test/CodeGen/SystemZ/shift-09.ll @@ -0,0 +1,63 @@ +; Test three-operand shifts. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s + +; Check that we use SLLK over SLL where useful. +define i32 @f1(i32 %a, i32 %b, i32 %amt) { +; CHECK-LABEL: f1: +; CHECK: sllk %r2, %r3, 15(%r4) +; CHECK: br %r14 + %add = add i32 %amt, 15 + %shift = shl i32 %b, %add + ret i32 %shift +} + +; Check that we use SLL over SLLK where possible. +define i32 @f2(i32 %a, i32 %amt) { +; CHECK-LABEL: f2: +; CHECK: sll %r2, 15(%r3) +; CHECK: br %r14 + %add = add i32 %amt, 15 + %shift = shl i32 %a, %add + ret i32 %shift +} + +; Check that we use SRLK over SRL where useful. +define i32 @f3(i32 %a, i32 %b, i32 %amt) { +; CHECK-LABEL: f3: +; CHECK: srlk %r2, %r3, 15(%r4) +; CHECK: br %r14 + %add = add i32 %amt, 15 + %shift = lshr i32 %b, %add + ret i32 %shift +} + +; Check that we use SRL over SRLK where possible. +define i32 @f4(i32 %a, i32 %amt) { +; CHECK-LABEL: f4: +; CHECK: srl %r2, 15(%r3) +; CHECK: br %r14 + %add = add i32 %amt, 15 + %shift = lshr i32 %a, %add + ret i32 %shift +} + +; Check that we use SRAK over SRA where useful. +define i32 @f5(i32 %a, i32 %b, i32 %amt) { +; CHECK-LABEL: f5: +; CHECK: srak %r2, %r3, 15(%r4) +; CHECK: br %r14 + %add = add i32 %amt, 15 + %shift = ashr i32 %b, %add + ret i32 %shift +} + +; Check that we use SRA over SRAK where possible. +define i32 @f6(i32 %a, i32 %amt) { +; CHECK-LABEL: f6: +; CHECK: sra %r2, 15(%r3) +; CHECK: br %r14 + %add = add i32 %amt, 15 + %shift = ashr i32 %a, %add + ret i32 %shift +}