mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-28 06:00:28 +00:00
[mips] Fix definitions of multiply, multiply-add/sub and divide instructions.
The new instructions have explicit register output operands and use table-gen patterns instead of C++ code to do instruction selection. Mips16's instructions are unaffected by this change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178403 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9cf0724cc3
commit
f5926fd844
@ -1466,14 +1466,14 @@ def: Mips16Pat<(i32 immZExt16:$in), (LiRxImmX16 immZExt16:$in)>;
|
||||
// MipsDivRem
|
||||
//
|
||||
def: Mips16Pat
|
||||
<(MipsDivRem CPU16Regs:$rx, CPU16Regs:$ry),
|
||||
<(MipsDivRem16 CPU16Regs:$rx, CPU16Regs:$ry),
|
||||
(DivRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>;
|
||||
|
||||
//
|
||||
// MipsDivRemU
|
||||
//
|
||||
def: Mips16Pat
|
||||
<(MipsDivRemU CPU16Regs:$rx, CPU16Regs:$ry),
|
||||
<(MipsDivRemU16 CPU16Regs:$rx, CPU16Regs:$ry),
|
||||
(DivuRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>;
|
||||
|
||||
// signed a,b
|
||||
|
@ -187,10 +187,16 @@ def DMULT : Mult<"dmult", IIImul, CPU64RegsOpnd, [HI64, LO64]>,
|
||||
MULT_FM<0, 0x1c>;
|
||||
def DMULTu : Mult<"dmultu", IIImul, CPU64RegsOpnd, [HI64, LO64]>,
|
||||
MULT_FM<0, 0x1d>;
|
||||
def DSDIV : Div<MipsDivRem, "ddiv", IIIdiv, CPU64RegsOpnd, [HI64, LO64]>,
|
||||
MULT_FM<0, 0x1e>;
|
||||
def DUDIV : Div<MipsDivRemU, "ddivu", IIIdiv, CPU64RegsOpnd, [HI64, LO64]>,
|
||||
MULT_FM<0, 0x1f>;
|
||||
def PseudoDMULT : MultDivPseudo<DMULT, ACRegs128, CPU64RegsOpnd, MipsMult,
|
||||
IIImul>;
|
||||
def PseudoDMULTu : MultDivPseudo<DMULTu, ACRegs128, CPU64RegsOpnd, MipsMultu,
|
||||
IIImul>;
|
||||
def DSDIV : Div<"ddiv", IIIdiv, CPU64RegsOpnd, [HI64, LO64]>, MULT_FM<0, 0x1e>;
|
||||
def DUDIV : Div<"ddivu", IIIdiv, CPU64RegsOpnd, [HI64, LO64]>, MULT_FM<0, 0x1f>;
|
||||
def PseudoDSDIV : MultDivPseudo<DSDIV, ACRegs128, CPU64RegsOpnd, MipsDivRem,
|
||||
IIIdiv, 0>;
|
||||
def PseudoDUDIV : MultDivPseudo<DUDIV, ACRegs128, CPU64RegsOpnd, MipsDivRemU,
|
||||
IIIdiv, 0>;
|
||||
|
||||
def MTHI64 : MoveToLOHI<"mthi", CPU64Regs, [HI64]>, MTLO_FM<0x11>;
|
||||
def MTLO64 : MoveToLOHI<"mtlo", CPU64Regs, [LO64]>, MTLO_FM<0x13>;
|
||||
@ -314,6 +320,10 @@ def : MipsPat<(i64 (sext_inreg CPU64Regs:$src, i32)),
|
||||
// bswap MipsPattern
|
||||
def : MipsPat<(bswap CPU64Regs:$rt), (DSHD (DSBH CPU64Regs:$rt))>;
|
||||
|
||||
// mflo/hi patterns.
|
||||
def : MipsPat<(i64 (ExtractLOHI ACRegs128:$ac, imm:$lohi_idx)),
|
||||
(EXTRACT_SUBREG ACRegs128:$ac, imm:$lohi_idx)>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction aliases
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -461,28 +461,32 @@ static bool selectMADD(SDNode *ADDENode, SelectionDAG *CurDAG) {
|
||||
SDValue Chain = CurDAG->getEntryNode();
|
||||
DebugLoc DL = ADDENode->getDebugLoc();
|
||||
|
||||
// Initialize accumulator.
|
||||
SDValue ACCIn = CurDAG->getNode(MipsISD::InsertLOHI, DL, MVT::Untyped,
|
||||
ADDCNode->getOperand(1),
|
||||
ADDENode->getOperand(1));
|
||||
|
||||
// create MipsMAdd(u) node
|
||||
MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MAddu : MipsISD::MAdd;
|
||||
|
||||
SDValue MAdd = CurDAG->getNode(MultOpc, DL, MVT::Glue,
|
||||
SDValue MAdd = CurDAG->getNode(MultOpc, DL, MVT::Untyped,
|
||||
MultNode->getOperand(0),// Factor 0
|
||||
MultNode->getOperand(1),// Factor 1
|
||||
ADDCNode->getOperand(1),// Lo0
|
||||
ADDENode->getOperand(1));// Hi0
|
||||
|
||||
// create CopyFromReg nodes
|
||||
SDValue CopyFromLo = CurDAG->getCopyFromReg(Chain, DL, Mips::LO, MVT::i32,
|
||||
MAdd);
|
||||
SDValue CopyFromHi = CurDAG->getCopyFromReg(CopyFromLo.getValue(1), DL,
|
||||
Mips::HI, MVT::i32,
|
||||
CopyFromLo.getValue(2));
|
||||
ACCIn);
|
||||
|
||||
// replace uses of adde and addc here
|
||||
if (!SDValue(ADDCNode, 0).use_empty())
|
||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), CopyFromLo);
|
||||
|
||||
if (!SDValue(ADDENode, 0).use_empty())
|
||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), CopyFromHi);
|
||||
if (!SDValue(ADDCNode, 0).use_empty()) {
|
||||
SDValue LoIdx = CurDAG->getConstant(Mips::sub_lo, MVT::i32);
|
||||
SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MAdd,
|
||||
LoIdx);
|
||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), LoOut);
|
||||
}
|
||||
if (!SDValue(ADDENode, 0).use_empty()) {
|
||||
SDValue HiIdx = CurDAG->getConstant(Mips::sub_hi, MVT::i32);
|
||||
SDValue HiOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MAdd,
|
||||
HiIdx);
|
||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), HiOut);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -534,28 +538,32 @@ static bool selectMSUB(SDNode *SUBENode, SelectionDAG *CurDAG) {
|
||||
SDValue Chain = CurDAG->getEntryNode();
|
||||
DebugLoc DL = SUBENode->getDebugLoc();
|
||||
|
||||
// Initialize accumulator.
|
||||
SDValue ACCIn = CurDAG->getNode(MipsISD::InsertLOHI, DL, MVT::Untyped,
|
||||
SUBCNode->getOperand(0),
|
||||
SUBENode->getOperand(0));
|
||||
|
||||
// create MipsSub(u) node
|
||||
MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MSubu : MipsISD::MSub;
|
||||
|
||||
SDValue MSub = CurDAG->getNode(MultOpc, DL, MVT::Glue,
|
||||
MultNode->getOperand(0),// Factor 0
|
||||
MultNode->getOperand(1),// Factor 1
|
||||
SUBCNode->getOperand(0),// Lo0
|
||||
SUBENode->getOperand(0));// Hi0
|
||||
|
||||
// create CopyFromReg nodes
|
||||
SDValue CopyFromLo = CurDAG->getCopyFromReg(Chain, DL, Mips::LO, MVT::i32,
|
||||
MSub);
|
||||
SDValue CopyFromHi = CurDAG->getCopyFromReg(CopyFromLo.getValue(1), DL,
|
||||
Mips::HI, MVT::i32,
|
||||
CopyFromLo.getValue(2));
|
||||
ACCIn);
|
||||
|
||||
// replace uses of sube and subc here
|
||||
if (!SDValue(SUBCNode, 0).use_empty())
|
||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), CopyFromLo);
|
||||
|
||||
if (!SDValue(SUBENode, 0).use_empty())
|
||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), CopyFromHi);
|
||||
if (!SDValue(SUBCNode, 0).use_empty()) {
|
||||
SDValue LoIdx = CurDAG->getConstant(Mips::sub_lo, MVT::i32);
|
||||
SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MSub,
|
||||
LoIdx);
|
||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), LoOut);
|
||||
}
|
||||
if (!SDValue(SUBENode, 0).use_empty()) {
|
||||
SDValue HiIdx = CurDAG->getConstant(Mips::sub_hi, MVT::i32);
|
||||
SDValue HiOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MSub,
|
||||
HiIdx);
|
||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), HiOut);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -595,8 +603,8 @@ static SDValue performDivRemCombine(SDNode *N, SelectionDAG &DAG,
|
||||
EVT Ty = N->getValueType(0);
|
||||
unsigned LO = (Ty == MVT::i32) ? Mips::LO : Mips::LO64;
|
||||
unsigned HI = (Ty == MVT::i32) ? Mips::HI : Mips::HI64;
|
||||
unsigned Opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem :
|
||||
MipsISD::DivRemU;
|
||||
unsigned Opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem16 :
|
||||
MipsISD::DivRemU16;
|
||||
DebugLoc DL = N->getDebugLoc();
|
||||
|
||||
SDValue DivRem = DAG.getNode(Opc, DL, MVT::Glue,
|
||||
|
@ -23,13 +23,16 @@ def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>,
|
||||
SDTCisInt<4>]>;
|
||||
def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
|
||||
def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
|
||||
def SDT_MipsMAddMSub : SDTypeProfile<0, 4,
|
||||
[SDTCisVT<0, i32>, SDTCisSameAs<0, 1>,
|
||||
SDTCisSameAs<1, 2>,
|
||||
SDTCisSameAs<2, 3>]>;
|
||||
def SDT_MipsDivRem : SDTypeProfile<0, 2,
|
||||
[SDTCisInt<0>,
|
||||
SDTCisSameAs<0, 1>]>;
|
||||
def SDT_ExtractLOHI : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVT<1, untyped>,
|
||||
SDTCisVT<2, i32>]>;
|
||||
def SDT_InsertLOHI : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>,
|
||||
SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>;
|
||||
def SDT_MipsMultDiv : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>, SDTCisInt<1>,
|
||||
SDTCisSameAs<1, 2>]>;
|
||||
def SDT_MipsMAddMSub : SDTypeProfile<1, 3,
|
||||
[SDTCisVT<0, untyped>, SDTCisSameAs<0, 3>,
|
||||
SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>;
|
||||
def SDT_MipsDivRem16 : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisSameAs<0, 1>]>;
|
||||
|
||||
def SDT_MipsThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>;
|
||||
|
||||
@ -82,20 +85,27 @@ def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd,
|
||||
[SDNPHasChain, SDNPSideEffect,
|
||||
SDNPOptInGlue, SDNPOutGlue]>;
|
||||
|
||||
// Node used to extract integer from LO/HI register.
|
||||
def ExtractLOHI : SDNode<"MipsISD::ExtractLOHI", SDT_ExtractLOHI>;
|
||||
|
||||
// Node used to insert 32-bit integers to LOHI register pair.
|
||||
def InsertLOHI : SDNode<"MipsISD::InsertLOHI", SDT_InsertLOHI>;
|
||||
|
||||
// Mult nodes.
|
||||
def MipsMult : SDNode<"MipsISD::Mult", SDT_MipsMultDiv>;
|
||||
def MipsMultu : SDNode<"MipsISD::Multu", SDT_MipsMultDiv>;
|
||||
|
||||
// MAdd*/MSub* nodes
|
||||
def MipsMAdd : SDNode<"MipsISD::MAdd", SDT_MipsMAddMSub,
|
||||
[SDNPOptInGlue, SDNPOutGlue]>;
|
||||
def MipsMAddu : SDNode<"MipsISD::MAddu", SDT_MipsMAddMSub,
|
||||
[SDNPOptInGlue, SDNPOutGlue]>;
|
||||
def MipsMSub : SDNode<"MipsISD::MSub", SDT_MipsMAddMSub,
|
||||
[SDNPOptInGlue, SDNPOutGlue]>;
|
||||
def MipsMSubu : SDNode<"MipsISD::MSubu", SDT_MipsMAddMSub,
|
||||
[SDNPOptInGlue, SDNPOutGlue]>;
|
||||
def MipsMAdd : SDNode<"MipsISD::MAdd", SDT_MipsMAddMSub>;
|
||||
def MipsMAddu : SDNode<"MipsISD::MAddu", SDT_MipsMAddMSub>;
|
||||
def MipsMSub : SDNode<"MipsISD::MSub", SDT_MipsMAddMSub>;
|
||||
def MipsMSubu : SDNode<"MipsISD::MSubu", SDT_MipsMAddMSub>;
|
||||
|
||||
// DivRem(u) nodes
|
||||
def MipsDivRem : SDNode<"MipsISD::DivRem", SDT_MipsDivRem,
|
||||
[SDNPOutGlue]>;
|
||||
def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsDivRem,
|
||||
def MipsDivRem : SDNode<"MipsISD::DivRem", SDT_MipsMultDiv>;
|
||||
def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsMultDiv>;
|
||||
def MipsDivRem16 : SDNode<"MipsISD::DivRem16", SDT_MipsDivRem16, [SDNPOutGlue]>;
|
||||
def MipsDivRemU16 : SDNode<"MipsISD::DivRemU16", SDT_MipsDivRem16,
|
||||
[SDNPOutGlue]>;
|
||||
|
||||
// Target constant nodes that are not part of any isel patterns and remain
|
||||
@ -382,10 +392,9 @@ class ArithLogicI<string opstr, Operand Od, RegisterOperand RO,
|
||||
}
|
||||
|
||||
// Arithmetic Multiply ADD/SUB
|
||||
class MArithR<string opstr, SDPatternOperator op = null_frag, bit isComm = 0> :
|
||||
class MArithR<string opstr, bit isComm = 0> :
|
||||
InstSE<(outs), (ins CPURegsOpnd:$rs, CPURegsOpnd:$rt),
|
||||
!strconcat(opstr, "\t$rs, $rt"),
|
||||
[(op CPURegsOpnd:$rs, CPURegsOpnd:$rt, LO, HI)], IIImul, FrmR> {
|
||||
!strconcat(opstr, "\t$rs, $rt"), [], IIImul, FrmR> {
|
||||
let Defs = [HI, LO];
|
||||
let Uses = [HI, LO];
|
||||
let isCommutable = isComm;
|
||||
@ -629,11 +638,34 @@ class Mult<string opstr, InstrItinClass itin, RegisterOperand RO,
|
||||
let neverHasSideEffects = 1;
|
||||
}
|
||||
|
||||
class Div<SDNode op, string opstr, InstrItinClass itin, RegisterOperand RO,
|
||||
// Pseudo multiply/divide instruction with explicit accumulator register
|
||||
// operands.
|
||||
class MultDivPseudo<Instruction RealInst, RegisterClass R0, RegisterOperand R1,
|
||||
SDPatternOperator OpNode, InstrItinClass Itin,
|
||||
bit IsComm = 1, bit HasSideEffects = 0> :
|
||||
PseudoSE<(outs R0:$ac), (ins R1:$rs, R1:$rt),
|
||||
[(set R0:$ac, (OpNode R1:$rs, R1:$rt))], Itin>,
|
||||
PseudoInstExpansion<(RealInst R1:$rs, R1:$rt)> {
|
||||
let isCommutable = IsComm;
|
||||
let hasSideEffects = HasSideEffects;
|
||||
}
|
||||
|
||||
// Pseudo multiply add/sub instruction with explicit accumulator register
|
||||
// operands.
|
||||
class MAddSubPseudo<Instruction RealInst, SDPatternOperator OpNode>
|
||||
: PseudoSE<(outs ACRegs:$ac),
|
||||
(ins CPURegsOpnd:$rs, CPURegsOpnd:$rt, ACRegs:$acin),
|
||||
[(set ACRegs:$ac,
|
||||
(OpNode CPURegsOpnd:$rs, CPURegsOpnd:$rt, ACRegs:$acin))],
|
||||
IIImul>,
|
||||
PseudoInstExpansion<(RealInst CPURegsOpnd:$rs, CPURegsOpnd:$rt)> {
|
||||
string Constraints = "$acin = $ac";
|
||||
}
|
||||
|
||||
class Div<string opstr, InstrItinClass itin, RegisterOperand RO,
|
||||
list<Register> DefRegs> :
|
||||
InstSE<(outs), (ins RO:$rs, RO:$rt),
|
||||
!strconcat(opstr, "\t$$zero, $rs, $rt"), [(op RO:$rs, RO:$rt)], itin,
|
||||
FrmR> {
|
||||
InstSE<(outs), (ins RO:$rs, RO:$rt), !strconcat(opstr, "\t$$zero, $rs, $rt"),
|
||||
[], itin, FrmR> {
|
||||
let Defs = DefRegs;
|
||||
}
|
||||
|
||||
@ -934,10 +966,13 @@ let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1 in {
|
||||
/// Multiply and Divide Instructions.
|
||||
def MULT : Mult<"mult", IIImul, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x18>;
|
||||
def MULTu : Mult<"multu", IIImul, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x19>;
|
||||
def SDIV : Div<MipsDivRem, "div", IIIdiv, CPURegsOpnd, [HI, LO]>,
|
||||
MULT_FM<0, 0x1a>;
|
||||
def UDIV : Div<MipsDivRemU, "divu", IIIdiv, CPURegsOpnd, [HI, LO]>,
|
||||
MULT_FM<0, 0x1b>;
|
||||
def PseudoMULT : MultDivPseudo<MULT, ACRegs, CPURegsOpnd, MipsMult, IIImul>;
|
||||
def PseudoMULTu : MultDivPseudo<MULTu, ACRegs, CPURegsOpnd, MipsMultu, IIImul>;
|
||||
def SDIV : Div<"div", IIIdiv, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x1a>;
|
||||
def UDIV : Div<"divu", IIIdiv, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x1b>;
|
||||
def PseudoSDIV : MultDivPseudo<SDIV, ACRegs, CPURegsOpnd, MipsDivRem, IIIdiv, 0>;
|
||||
def PseudoUDIV : MultDivPseudo<UDIV, ACRegs, CPURegsOpnd, MipsDivRemU, IIIdiv,
|
||||
0>;
|
||||
|
||||
def MTHI : MoveToLOHI<"mthi", CPURegs, [HI]>, MTLO_FM<0x11>;
|
||||
def MTLO : MoveToLOHI<"mtlo", CPURegs, [LO]>, MTLO_FM<0x13>;
|
||||
@ -965,10 +1000,14 @@ def NOP : PseudoSE<(outs), (ins), []>, PseudoInstExpansion<(SLL ZERO, ZERO, 0)>;
|
||||
def LEA_ADDiu : EffectiveAddress<"addiu", CPURegs, mem_ea>, LW_FM<9>;
|
||||
|
||||
// MADD*/MSUB*
|
||||
def MADD : MArithR<"madd", MipsMAdd, 1>, MULT_FM<0x1c, 0>;
|
||||
def MADDU : MArithR<"maddu", MipsMAddu, 1>, MULT_FM<0x1c, 1>;
|
||||
def MSUB : MArithR<"msub", MipsMSub>, MULT_FM<0x1c, 4>;
|
||||
def MSUBU : MArithR<"msubu", MipsMSubu>, MULT_FM<0x1c, 5>;
|
||||
def MADD : MArithR<"madd", 1>, MULT_FM<0x1c, 0>;
|
||||
def MADDU : MArithR<"maddu", 1>, MULT_FM<0x1c, 1>;
|
||||
def MSUB : MArithR<"msub">, MULT_FM<0x1c, 4>;
|
||||
def MSUBU : MArithR<"msubu">, MULT_FM<0x1c, 5>;
|
||||
def PseudoMADD : MAddSubPseudo<MADD, MipsMAdd>;
|
||||
def PseudoMADDU : MAddSubPseudo<MADDU, MipsMAddu>;
|
||||
def PseudoMSUB : MAddSubPseudo<MSUB, MipsMSub>;
|
||||
def PseudoMSUBU : MAddSubPseudo<MSUBU, MipsMSubu>;
|
||||
|
||||
def RDHWR : ReadHardware<CPURegs, HWRegsOpnd>, RDHWR_FM;
|
||||
|
||||
@ -1240,6 +1279,10 @@ defm : SetgeImmPats<CPURegs, SLTi, SLTiu>;
|
||||
// bswap pattern
|
||||
def : MipsPat<(bswap CPURegs:$rt), (ROTR (WSBH CPURegs:$rt), 16)>;
|
||||
|
||||
// mflo/hi patterns.
|
||||
def : MipsPat<(i32 (ExtractLOHI ACRegs:$ac, imm:$lohi_idx)),
|
||||
(EXTRACT_SUBREG ACRegs:$ac, imm:$lohi_idx)>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Floating Point Support
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -450,6 +450,19 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
|
||||
ReplaceUses(SDValue(Node, 0), ResNode);
|
||||
return std::make_pair(true, ResNode.getNode());
|
||||
}
|
||||
|
||||
case MipsISD::InsertLOHI: {
|
||||
unsigned RCID = Subtarget.hasDSP() ? Mips::ACRegsDSPRegClassID :
|
||||
Mips::ACRegsRegClassID;
|
||||
SDValue RegClass = CurDAG->getTargetConstant(RCID, MVT::i32);
|
||||
SDValue LoIdx = CurDAG->getTargetConstant(Mips::sub_lo, MVT::i32);
|
||||
SDValue HiIdx = CurDAG->getTargetConstant(Mips::sub_hi, MVT::i32);
|
||||
const SDValue Ops[] = { RegClass, Node->getOperand(0), LoIdx,
|
||||
Node->getOperand(1), HiIdx };
|
||||
SDNode *Res = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL,
|
||||
MVT::Untyped, Ops, 5);
|
||||
return std::make_pair(true, Res);
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair(false, (SDNode*)NULL);
|
||||
|
@ -60,6 +60,18 @@ MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM)
|
||||
}
|
||||
}
|
||||
|
||||
setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom);
|
||||
setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom);
|
||||
setOperationAction(ISD::MULHS, MVT::i32, Custom);
|
||||
setOperationAction(ISD::MULHU, MVT::i32, Custom);
|
||||
|
||||
if (HasMips64)
|
||||
setOperationAction(ISD::MUL, MVT::i64, Custom);
|
||||
|
||||
setOperationAction(ISD::SDIVREM, MVT::i32, Custom);
|
||||
setOperationAction(ISD::UDIVREM, MVT::i32, Custom);
|
||||
setOperationAction(ISD::SDIVREM, MVT::i64, Custom);
|
||||
setOperationAction(ISD::UDIVREM, MVT::i64, Custom);
|
||||
setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom);
|
||||
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
|
||||
setOperationAction(ISD::LOAD, MVT::i32, Custom);
|
||||
@ -89,6 +101,21 @@ MipsSETargetLowering::allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const {
|
||||
}
|
||||
}
|
||||
|
||||
SDValue MipsSETargetLowering::LowerOperation(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
switch(Op.getOpcode()) {
|
||||
case ISD::SMUL_LOHI: return lowerMulDiv(Op, MipsISD::Mult, true, true, DAG);
|
||||
case ISD::UMUL_LOHI: return lowerMulDiv(Op, MipsISD::Multu, true, true, DAG);
|
||||
case ISD::MULHS: return lowerMulDiv(Op, MipsISD::Mult, false, true, DAG);
|
||||
case ISD::MULHU: return lowerMulDiv(Op, MipsISD::Multu, false, true, DAG);
|
||||
case ISD::MUL: return lowerMulDiv(Op, MipsISD::Mult, true, false, DAG);
|
||||
case ISD::SDIVREM: return lowerMulDiv(Op, MipsISD::DivRem, true, true, DAG);
|
||||
case ISD::UDIVREM: return lowerMulDiv(Op, MipsISD::DivRemU, true, true, DAG);
|
||||
}
|
||||
|
||||
return MipsTargetLowering::LowerOperation(Op, DAG);
|
||||
}
|
||||
|
||||
MachineBasicBlock *
|
||||
MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||
MachineBasicBlock *BB) const {
|
||||
@ -133,6 +160,29 @@ getOpndList(SmallVectorImpl<SDValue> &Ops,
|
||||
InternalLinkage, CLI, Callee, Chain);
|
||||
}
|
||||
|
||||
SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc,
|
||||
bool HasLo, bool HasHi,
|
||||
SelectionDAG &DAG) const {
|
||||
EVT Ty = Op.getOperand(0).getValueType();
|
||||
DebugLoc DL = Op.getDebugLoc();
|
||||
SDValue Mult = DAG.getNode(NewOpc, DL, MVT::Untyped,
|
||||
Op.getOperand(0), Op.getOperand(1));
|
||||
SDValue Lo, Hi;
|
||||
|
||||
if (HasLo)
|
||||
Lo = DAG.getNode(MipsISD::ExtractLOHI, DL, Ty, Mult,
|
||||
DAG.getConstant(Mips::sub_lo, MVT::i32));
|
||||
if (HasHi)
|
||||
Hi = DAG.getNode(MipsISD::ExtractLOHI, DL, Ty, Mult,
|
||||
DAG.getConstant(Mips::sub_hi, MVT::i32));
|
||||
|
||||
if (!HasLo || !HasHi)
|
||||
return HasLo ? Lo : Hi;
|
||||
|
||||
SDValue Vals[] = { Lo, Hi };
|
||||
return DAG.getMergeValues(Vals, 2, DL);
|
||||
}
|
||||
|
||||
MachineBasicBlock * MipsSETargetLowering::
|
||||
emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{
|
||||
// $bb:
|
||||
|
@ -24,6 +24,8 @@ namespace llvm {
|
||||
|
||||
virtual bool allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const;
|
||||
|
||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
virtual MachineBasicBlock *
|
||||
EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const;
|
||||
|
||||
@ -47,6 +49,9 @@ namespace llvm {
|
||||
bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
|
||||
CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const;
|
||||
|
||||
SDValue lowerMulDiv(SDValue Op, unsigned NewOpc, bool HasLo, bool HasHi,
|
||||
SelectionDAG &DAG) const;
|
||||
|
||||
MachineBasicBlock *emitBPOSGE32(MachineInstr *MI,
|
||||
MachineBasicBlock *BB) const;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user