mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
[SystemZ] Use SLLK, SRLK and SRAK for codegen
This patch uses the instructions added in r186680 for codegen. llvm-svn: 186681
This commit is contained in:
parent
36b6ee625e
commit
499b1e1400
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
63
test/CodeGen/SystemZ/shift-09.ll
Normal file
63
test/CodeGen/SystemZ/shift-09.ll
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user