mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-03 08:51:43 +00:00
Add support for ext and ins.
llvm-svn: 137804
This commit is contained in:
parent
2a11307687
commit
0179c7fa68
@ -35,6 +35,24 @@
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
// If I is a shifted mask, set the size (Size) and the first bit of the
|
||||
// mask (Pos), and return true.
|
||||
bool IsShiftedMask(uint64_t I, unsigned SizeInBits, uint64_t &Pos,
|
||||
uint64_t &Size) {
|
||||
assert(SizeInBits == 32 || SizeInBits == 64);
|
||||
bool Is32Bits = (SizeInBits == 32);
|
||||
|
||||
if ((Is32Bits == 32 && !isShiftedMask_32(I)) ||
|
||||
(!Is32Bits && !isShiftedMask_64(I)))
|
||||
return false;
|
||||
|
||||
Size = Is32Bits ? CountPopulation_32(I) : CountPopulation_64(I);
|
||||
Pos = Is32Bits ? CountTrailingZeros_32(I) : CountTrailingZeros_64(I);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
switch (Opcode) {
|
||||
case MipsISD::JmpLink: return "MipsISD::JmpLink";
|
||||
@ -62,6 +80,8 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case MipsISD::WrapperPIC: return "MipsISD::WrapperPIC";
|
||||
case MipsISD::DynAlloc: return "MipsISD::DynAlloc";
|
||||
case MipsISD::Sync: return "MipsISD::Sync";
|
||||
case MipsISD::Ext: return "MipsISD::Ext";
|
||||
case MipsISD::Ins: return "MipsISD::Ins";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
@ -111,6 +131,8 @@ MipsTargetLowering(MipsTargetMachine &TM)
|
||||
setOperationAction(ISD::BRCOND, MVT::Other, Custom);
|
||||
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom);
|
||||
setOperationAction(ISD::VASTART, MVT::Other, Custom);
|
||||
setOperationAction(ISD::AND, MVT::i32, Custom);
|
||||
setOperationAction(ISD::OR, MVT::i32, Custom);
|
||||
|
||||
setOperationAction(ISD::SDIV, MVT::i32, Expand);
|
||||
setOperationAction(ISD::SREM, MVT::i32, Expand);
|
||||
@ -539,6 +561,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const
|
||||
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
|
||||
case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG);
|
||||
case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG);
|
||||
case ISD::AND: return LowerAND(Op, DAG);
|
||||
case ISD::OR: return LowerOR(Op, DAG);
|
||||
}
|
||||
return SDValue();
|
||||
}
|
||||
@ -1556,6 +1580,98 @@ SDValue MipsTargetLowering::LowerATOMIC_FENCE(SDValue Op,
|
||||
DAG.getConstant(SType, MVT::i32));
|
||||
}
|
||||
|
||||
SDValue MipsTargetLowering::LowerAND(SDValue Op, SelectionDAG& DAG) const {
|
||||
// Pattern match EXT.
|
||||
// $dst = and ((sra or srl) $src , pos), (2**size - 1)
|
||||
// => ext $dst, $src, size, pos
|
||||
if (!Subtarget->isMips32r2())
|
||||
return Op;
|
||||
|
||||
SDValue ShiftRight = Op.getOperand(0), Mask = Op.getOperand(1);
|
||||
|
||||
// Op's first operand must be a shift right.
|
||||
if (ShiftRight.getOpcode() != ISD::SRA && ShiftRight.getOpcode() != ISD::SRL)
|
||||
return Op;
|
||||
|
||||
// The second operand of the shift must be an immediate.
|
||||
uint64_t Pos;
|
||||
ConstantSDNode *CN;
|
||||
if (!(CN = dyn_cast<ConstantSDNode>(ShiftRight.getOperand(1))))
|
||||
return Op;
|
||||
|
||||
Pos = CN->getZExtValue();
|
||||
|
||||
uint64_t SMPos, SMSize;
|
||||
// Op's second operand must be a shifted mask.
|
||||
if (!(CN = dyn_cast<ConstantSDNode>(Mask)) ||
|
||||
!IsShiftedMask(CN->getZExtValue(), 32, SMPos, SMSize))
|
||||
return Op;
|
||||
|
||||
// Return if the shifted mask does not start at bit 0 or the sum of its size
|
||||
// and Pos exceeds the word's size.
|
||||
if (SMPos != 0 || Pos + SMSize > 32)
|
||||
return Op;
|
||||
|
||||
return DAG.getNode(MipsISD::Ext, Op.getDebugLoc(), MVT::i32,
|
||||
ShiftRight.getOperand(0),
|
||||
DAG.getConstant(SMSize, MVT::i32),
|
||||
DAG.getConstant(Pos, MVT::i32));
|
||||
}
|
||||
|
||||
SDValue MipsTargetLowering::LowerOR(SDValue Op, SelectionDAG& DAG) const {
|
||||
// Pattern match INS.
|
||||
// $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1),
|
||||
// where mask1 = (2**size - 1) << pos, mask0 = ~mask1
|
||||
// => ins $dst, $src, size, pos
|
||||
if (!Subtarget->isMips32r2())
|
||||
return Op;
|
||||
|
||||
SDValue And0 = Op.getOperand(0), And1 = Op.getOperand(1);
|
||||
uint64_t SMPos0, SMSize0, SMPos1, SMSize1;
|
||||
ConstantSDNode *CN;
|
||||
|
||||
// See if Op's first operand matches (and $src1 , mask0).
|
||||
if (And0.getOpcode() != ISD::AND)
|
||||
return Op;
|
||||
|
||||
if (!(CN = dyn_cast<ConstantSDNode>(And0.getOperand(1))) ||
|
||||
!IsShiftedMask(~CN->getZExtValue(), 32, SMPos0, SMSize0))
|
||||
return Op;
|
||||
|
||||
// See if Op's second operand matches (and (shl $src, pos), mask1).
|
||||
if (And1.getOpcode() != ISD::AND)
|
||||
return Op;
|
||||
|
||||
if (!(CN = dyn_cast<ConstantSDNode>(And1.getOperand(1))) ||
|
||||
!IsShiftedMask(CN->getZExtValue(), CN->getValueSizeInBits(0), SMPos1,
|
||||
SMSize1))
|
||||
return Op;
|
||||
|
||||
// The shift masks must have the same position and size.
|
||||
if (SMPos0 != SMPos1 || SMSize0 != SMSize1)
|
||||
return Op;
|
||||
|
||||
SDValue Shl = And1.getOperand(0);
|
||||
if (Shl.getOpcode() != ISD::SHL)
|
||||
return Op;
|
||||
|
||||
if (!(CN = dyn_cast<ConstantSDNode>(Shl.getOperand(1))))
|
||||
return Op;
|
||||
|
||||
unsigned Shamt = CN->getZExtValue();
|
||||
|
||||
// Return if the shift amount and the first bit position of mask are not the
|
||||
// same.
|
||||
if (Shamt != SMPos0)
|
||||
return Op;
|
||||
|
||||
return DAG.getNode(MipsISD::Ins, Op.getDebugLoc(), MVT::i32,
|
||||
Shl.getOperand(0),
|
||||
DAG.getConstant(SMSize0, MVT::i32),
|
||||
DAG.getConstant(SMPos0, MVT::i32),
|
||||
And0.getOperand(0));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Calling Convention Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -83,7 +83,10 @@ namespace llvm {
|
||||
|
||||
DynAlloc,
|
||||
|
||||
Sync
|
||||
Sync,
|
||||
|
||||
Ext,
|
||||
Ins
|
||||
};
|
||||
}
|
||||
|
||||
@ -134,6 +137,8 @@ namespace llvm {
|
||||
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const;
|
||||
SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const;
|
||||
SDValue LowerAND(SDValue Op, SelectionDAG& DAG) const;
|
||||
SDValue LowerOR(SDValue Op, SelectionDAG& DAG) const;
|
||||
|
||||
virtual SDValue
|
||||
LowerFormalArguments(SDValue Chain,
|
||||
|
@ -102,6 +102,28 @@ class FJ<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
let Inst{25-0} = addr;
|
||||
}
|
||||
|
||||
// Ext and Ins
|
||||
class ExtIns<bits<6> _funct, string instr_asm, dag Outs, dag Ins,
|
||||
list<dag> pattern, InstrItinClass itin>:
|
||||
MipsInst<Outs, Ins, !strconcat(instr_asm, "\t$dst, $src, $pos, $size"),
|
||||
pattern, itin>
|
||||
{
|
||||
bits<5> rt;
|
||||
bits<5> rs;
|
||||
bits<5> sz;
|
||||
bits<5> pos;
|
||||
bits<6> funct;
|
||||
|
||||
let opcode = 0x1f;
|
||||
let funct = _funct;
|
||||
|
||||
let Inst{25-21} = rs;
|
||||
let Inst{20-16} = rt;
|
||||
let Inst{15-11} = sz;
|
||||
let Inst{10-6} = pos;
|
||||
let Inst{5-0} = funct;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// FLOATING POINT INSTRUCTION FORMATS
|
||||
|
@ -43,6 +43,12 @@ def SDT_MipsDynAlloc : SDTypeProfile<1, 1, [SDTCisVT<0, i32>,
|
||||
SDTCisVT<1, iPTR>]>;
|
||||
def SDT_Sync : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
|
||||
|
||||
def SDT_Ext : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>,
|
||||
SDTCisInt<2>, SDTCisSameAs<2, 3>]>;
|
||||
def SDT_Ins : SDTypeProfile<1, 4, [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>,
|
||||
SDTCisInt<2>, SDTCisSameAs<2, 3>,
|
||||
SDTCisSameAs<0, 4>]>;
|
||||
|
||||
// Call
|
||||
def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink,
|
||||
[SDNPHasChain, SDNPOutGlue, SDNPOptInGlue,
|
||||
@ -109,6 +115,9 @@ def MipsDynAlloc : SDNode<"MipsISD::DynAlloc", SDT_MipsDynAlloc,
|
||||
|
||||
def MipsSync : SDNode<"MipsISD::Sync", SDT_Sync, [SDNPHasChain]>;
|
||||
|
||||
def MipsExt : SDNode<"MipsISD::Ext", SDT_Ext>;
|
||||
def MipsIns : SDNode<"MipsISD::Ins", SDT_Ins>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Mips Instruction Predicate Definitions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -661,6 +670,23 @@ def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul, 1>, Requires<[IsMips32]>;
|
||||
|
||||
def RDHWR : ReadHardware;
|
||||
|
||||
let Predicates = [IsMips32r2] in {
|
||||
def Ext : ExtIns<0b000000, "ext", (outs CPURegs:$dst),
|
||||
(ins CPURegs:$src, uimm16:$size, uimm16:$pos),
|
||||
[(set CPURegs:$dst,
|
||||
(MipsExt CPURegs:$src, immZExt5:$size, immZExt5:$pos))],
|
||||
NoItinerary>;
|
||||
let Constraints = "$src1 = $dst" in
|
||||
def Ins : ExtIns<0b000100, "ins",
|
||||
(outs CPURegs:$dst),
|
||||
(ins CPURegs:$src, uimm16:$size, uimm16:$pos,
|
||||
CPURegs:$src1),
|
||||
[(set CPURegs:$dst,
|
||||
(MipsIns CPURegs:$src, immZExt5:$size, immZExt5:$pos,
|
||||
CPURegs:$src1))],
|
||||
NoItinerary>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Arbitrary patterns that map to one or more instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
21
test/CodeGen/Mips/extins.ll
Normal file
21
test/CodeGen/Mips/extins.ll
Normal file
@ -0,0 +1,21 @@
|
||||
; RUN: llc -march=mips -mcpu=4ke < %s | FileCheck %s
|
||||
|
||||
define i32 @ext0_5_9(i32 %s, i32 %pos, i32 %sz) nounwind readnone {
|
||||
entry:
|
||||
; CHECK: ext ${{[0-9]+}}, $4, 5, 9
|
||||
%shr = lshr i32 %s, 5
|
||||
%and = and i32 %shr, 511
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
define void @ins2_5_9(i32 %s, i32* nocapture %d) nounwind {
|
||||
entry:
|
||||
; CHECK: ins ${{[0-9]+}}, $4, 5, 9
|
||||
%and = shl i32 %s, 5
|
||||
%shl = and i32 %and, 16352
|
||||
%tmp3 = load i32* %d, align 4
|
||||
%and5 = and i32 %tmp3, -16353
|
||||
%or = or i32 %and5, %shl
|
||||
store i32 %or, i32* %d, align 4
|
||||
ret void
|
||||
}
|
Loading…
Reference in New Issue
Block a user