[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
This commit is contained in:
Richard Sandiford 2013-07-19 16:12:08 +00:00
parent eddfaad1ef
commit 93c2125c39
4 changed files with 136 additions and 5 deletions

View File

@ -34,6 +34,12 @@ class InstSystemZ<int size, dag outs, dag ins, string asmstr,
string OpKey = "";
string OpType = "none";
// Many distinct-operands instructions have older 2-operand equivalents.
// NumOpsKey uniquely identifies one of these 2-operand and 3-operand pairs,
// with NumOpsValue being "2" or "3" as appropriate.
string NumOpsKey = "";
string NumOpsValue = "none";
// True if this instruction is a simple D(X,B) load of a register
// (with no sign or zero extension).
bit SimpleBDXLoad = 0;
@ -86,6 +92,7 @@ def getDisp20Opcode : InstrMapping {
let ValueCols = [["20"]];
}
// Return the memory form of a register instruction.
def getMemOpcode : InstrMapping {
let FilterClass = "InstSystemZ";
let RowFields = ["OpKey"];
@ -94,6 +101,15 @@ def getMemOpcode : InstrMapping {
let ValueCols = [["mem"]];
}
// Return the 3-operand form of a 2-operand instruction.
def getThreeOperandOpcode : InstrMapping {
let FilterClass = "InstSystemZ";
let RowFields = ["NumOpsKey"];
let ColFields = ["NumOpsValue"];
let KeyCol = ["2"];
let ValueCols = [["3"]];
}
//===----------------------------------------------------------------------===//
// Instruction formats
//===----------------------------------------------------------------------===//
@ -833,9 +849,13 @@ class ShiftRSY<string mnemonic, bits<16> opcode, SDPatternOperator operator,
multiclass ShiftRSAndK<string mnemonic, bits<8> opcode1, bits<16> opcode2,
SDPatternOperator operator, RegisterOperand cls> {
def K : ShiftRSY<mnemonic##"k", opcode2, null_frag, cls>,
Requires<[FeatureDistinctOps]>;
def "" : ShiftRS<mnemonic, opcode1, operator, cls>;
let NumOpsKey = mnemonic in {
let NumOpsValue = "3" in
def K : ShiftRSY<mnemonic##"k", opcode2, null_frag, cls>,
Requires<[FeatureDistinctOps]>;
let NumOpsValue = "2", isConvertibleToThreeAddress = 1 in
def "" : ShiftRS<mnemonic, opcode1, operator, cls>;
}
}
class CompareRR<string mnemonic, bits<8> opcode, SDPatternOperator operator,

View File

@ -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,

View File

@ -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<unsigned> &Ops,

View File

@ -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
}