mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-25 13:24:46 +00:00
[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:
@@ -34,6 +34,12 @@ class InstSystemZ<int size, dag outs, dag ins, string asmstr,
|
|||||||
string OpKey = "";
|
string OpKey = "";
|
||||||
string OpType = "none";
|
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
|
// True if this instruction is a simple D(X,B) load of a register
|
||||||
// (with no sign or zero extension).
|
// (with no sign or zero extension).
|
||||||
bit SimpleBDXLoad = 0;
|
bit SimpleBDXLoad = 0;
|
||||||
@@ -86,6 +92,7 @@ def getDisp20Opcode : InstrMapping {
|
|||||||
let ValueCols = [["20"]];
|
let ValueCols = [["20"]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the memory form of a register instruction.
|
||||||
def getMemOpcode : InstrMapping {
|
def getMemOpcode : InstrMapping {
|
||||||
let FilterClass = "InstSystemZ";
|
let FilterClass = "InstSystemZ";
|
||||||
let RowFields = ["OpKey"];
|
let RowFields = ["OpKey"];
|
||||||
@@ -94,6 +101,15 @@ def getMemOpcode : InstrMapping {
|
|||||||
let ValueCols = [["mem"]];
|
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
|
// 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,
|
multiclass ShiftRSAndK<string mnemonic, bits<8> opcode1, bits<16> opcode2,
|
||||||
SDPatternOperator operator, RegisterOperand cls> {
|
SDPatternOperator operator, RegisterOperand cls> {
|
||||||
def K : ShiftRSY<mnemonic##"k", opcode2, null_frag, cls>,
|
let NumOpsKey = mnemonic in {
|
||||||
Requires<[FeatureDistinctOps]>;
|
let NumOpsValue = "3" in
|
||||||
def "" : ShiftRS<mnemonic, opcode1, operator, cls>;
|
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,
|
class CompareRR<string mnemonic, bits<8> opcode, SDPatternOperator operator,
|
||||||
|
@@ -12,9 +12,10 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "SystemZInstrInfo.h"
|
#include "SystemZInstrInfo.h"
|
||||||
|
#include "SystemZTargetMachine.h"
|
||||||
#include "SystemZInstrBuilder.h"
|
#include "SystemZInstrBuilder.h"
|
||||||
|
#include "llvm/CodeGen/LiveVariables.h"
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
|
||||||
|
|
||||||
#define GET_INSTRINFO_CTOR
|
#define GET_INSTRINFO_CTOR
|
||||||
#define GET_INSTRMAP_INFO
|
#define GET_INSTRMAP_INFO
|
||||||
@@ -24,7 +25,7 @@ using namespace llvm;
|
|||||||
|
|
||||||
SystemZInstrInfo::SystemZInstrInfo(SystemZTargetMachine &tm)
|
SystemZInstrInfo::SystemZInstrInfo(SystemZTargetMachine &tm)
|
||||||
: SystemZGenInstrInfo(SystemZ::ADJCALLSTACKDOWN, SystemZ::ADJCALLSTACKUP),
|
: 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,
|
// 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);
|
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 *
|
MachineInstr *
|
||||||
SystemZInstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
|
SystemZInstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
|
||||||
MachineInstr *MI,
|
MachineInstr *MI,
|
||||||
|
@@ -79,6 +79,7 @@ namespace SystemZII {
|
|||||||
|
|
||||||
class SystemZInstrInfo : public SystemZGenInstrInfo {
|
class SystemZInstrInfo : public SystemZGenInstrInfo {
|
||||||
const SystemZRegisterInfo RI;
|
const SystemZRegisterInfo RI;
|
||||||
|
SystemZTargetMachine &TM;
|
||||||
|
|
||||||
void splitMove(MachineBasicBlock::iterator MI, unsigned NewOpcode) const;
|
void splitMove(MachineBasicBlock::iterator MI, unsigned NewOpcode) const;
|
||||||
void splitAdjDynAlloc(MachineBasicBlock::iterator MI) const;
|
void splitAdjDynAlloc(MachineBasicBlock::iterator MI) const;
|
||||||
@@ -119,6 +120,10 @@ public:
|
|||||||
unsigned DestReg, int FrameIdx,
|
unsigned DestReg, int FrameIdx,
|
||||||
const TargetRegisterClass *RC,
|
const TargetRegisterClass *RC,
|
||||||
const TargetRegisterInfo *TRI) const LLVM_OVERRIDE;
|
const TargetRegisterInfo *TRI) const LLVM_OVERRIDE;
|
||||||
|
virtual MachineInstr *
|
||||||
|
convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||||
|
MachineBasicBlock::iterator &MBBI,
|
||||||
|
LiveVariables *LV) const;
|
||||||
virtual MachineInstr *
|
virtual MachineInstr *
|
||||||
foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
|
foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
|
||||||
const SmallVectorImpl<unsigned> &Ops,
|
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
|
||||||
|
}
|
Reference in New Issue
Block a user