mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-15 22:28:18 +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:
@@ -1466,14 +1466,14 @@ def: Mips16Pat<(i32 immZExt16:$in), (LiRxImmX16 immZExt16:$in)>;
|
|||||||
// MipsDivRem
|
// MipsDivRem
|
||||||
//
|
//
|
||||||
def: Mips16Pat
|
def: Mips16Pat
|
||||||
<(MipsDivRem CPU16Regs:$rx, CPU16Regs:$ry),
|
<(MipsDivRem16 CPU16Regs:$rx, CPU16Regs:$ry),
|
||||||
(DivRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>;
|
(DivRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>;
|
||||||
|
|
||||||
//
|
//
|
||||||
// MipsDivRemU
|
// MipsDivRemU
|
||||||
//
|
//
|
||||||
def: Mips16Pat
|
def: Mips16Pat
|
||||||
<(MipsDivRemU CPU16Regs:$rx, CPU16Regs:$ry),
|
<(MipsDivRemU16 CPU16Regs:$rx, CPU16Regs:$ry),
|
||||||
(DivuRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>;
|
(DivuRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>;
|
||||||
|
|
||||||
// signed a,b
|
// signed a,b
|
||||||
|
@@ -187,10 +187,16 @@ def DMULT : Mult<"dmult", IIImul, CPU64RegsOpnd, [HI64, LO64]>,
|
|||||||
MULT_FM<0, 0x1c>;
|
MULT_FM<0, 0x1c>;
|
||||||
def DMULTu : Mult<"dmultu", IIImul, CPU64RegsOpnd, [HI64, LO64]>,
|
def DMULTu : Mult<"dmultu", IIImul, CPU64RegsOpnd, [HI64, LO64]>,
|
||||||
MULT_FM<0, 0x1d>;
|
MULT_FM<0, 0x1d>;
|
||||||
def DSDIV : Div<MipsDivRem, "ddiv", IIIdiv, CPU64RegsOpnd, [HI64, LO64]>,
|
def PseudoDMULT : MultDivPseudo<DMULT, ACRegs128, CPU64RegsOpnd, MipsMult,
|
||||||
MULT_FM<0, 0x1e>;
|
IIImul>;
|
||||||
def DUDIV : Div<MipsDivRemU, "ddivu", IIIdiv, CPU64RegsOpnd, [HI64, LO64]>,
|
def PseudoDMULTu : MultDivPseudo<DMULTu, ACRegs128, CPU64RegsOpnd, MipsMultu,
|
||||||
MULT_FM<0, 0x1f>;
|
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 MTHI64 : MoveToLOHI<"mthi", CPU64Regs, [HI64]>, MTLO_FM<0x11>;
|
||||||
def MTLO64 : MoveToLOHI<"mtlo", CPU64Regs, [LO64]>, MTLO_FM<0x13>;
|
def MTLO64 : MoveToLOHI<"mtlo", CPU64Regs, [LO64]>, MTLO_FM<0x13>;
|
||||||
@@ -314,6 +320,10 @@ def : MipsPat<(i64 (sext_inreg CPU64Regs:$src, i32)),
|
|||||||
// bswap MipsPattern
|
// bswap MipsPattern
|
||||||
def : MipsPat<(bswap CPU64Regs:$rt), (DSHD (DSBH CPU64Regs:$rt))>;
|
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
|
// Instruction aliases
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@@ -461,28 +461,32 @@ static bool selectMADD(SDNode *ADDENode, SelectionDAG *CurDAG) {
|
|||||||
SDValue Chain = CurDAG->getEntryNode();
|
SDValue Chain = CurDAG->getEntryNode();
|
||||||
DebugLoc DL = ADDENode->getDebugLoc();
|
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
|
// create MipsMAdd(u) node
|
||||||
MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MAddu : MipsISD::MAdd;
|
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(0),// Factor 0
|
||||||
MultNode->getOperand(1),// Factor 1
|
MultNode->getOperand(1),// Factor 1
|
||||||
ADDCNode->getOperand(1),// Lo0
|
ACCIn);
|
||||||
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));
|
|
||||||
|
|
||||||
// replace uses of adde and addc here
|
// replace uses of adde and addc here
|
||||||
if (!SDValue(ADDCNode, 0).use_empty())
|
if (!SDValue(ADDCNode, 0).use_empty()) {
|
||||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), CopyFromLo);
|
SDValue LoIdx = CurDAG->getConstant(Mips::sub_lo, MVT::i32);
|
||||||
|
SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MAdd,
|
||||||
if (!SDValue(ADDENode, 0).use_empty())
|
LoIdx);
|
||||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), CopyFromHi);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -534,28 +538,32 @@ static bool selectMSUB(SDNode *SUBENode, SelectionDAG *CurDAG) {
|
|||||||
SDValue Chain = CurDAG->getEntryNode();
|
SDValue Chain = CurDAG->getEntryNode();
|
||||||
DebugLoc DL = SUBENode->getDebugLoc();
|
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
|
// create MipsSub(u) node
|
||||||
MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MSubu : MipsISD::MSub;
|
MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MSubu : MipsISD::MSub;
|
||||||
|
|
||||||
SDValue MSub = CurDAG->getNode(MultOpc, DL, MVT::Glue,
|
SDValue MSub = CurDAG->getNode(MultOpc, DL, MVT::Glue,
|
||||||
MultNode->getOperand(0),// Factor 0
|
MultNode->getOperand(0),// Factor 0
|
||||||
MultNode->getOperand(1),// Factor 1
|
MultNode->getOperand(1),// Factor 1
|
||||||
SUBCNode->getOperand(0),// Lo0
|
ACCIn);
|
||||||
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));
|
|
||||||
|
|
||||||
// replace uses of sube and subc here
|
// replace uses of sube and subc here
|
||||||
if (!SDValue(SUBCNode, 0).use_empty())
|
if (!SDValue(SUBCNode, 0).use_empty()) {
|
||||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), CopyFromLo);
|
SDValue LoIdx = CurDAG->getConstant(Mips::sub_lo, MVT::i32);
|
||||||
|
SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MSub,
|
||||||
if (!SDValue(SUBENode, 0).use_empty())
|
LoIdx);
|
||||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), CopyFromHi);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -595,8 +603,8 @@ static SDValue performDivRemCombine(SDNode *N, SelectionDAG &DAG,
|
|||||||
EVT Ty = N->getValueType(0);
|
EVT Ty = N->getValueType(0);
|
||||||
unsigned LO = (Ty == MVT::i32) ? Mips::LO : Mips::LO64;
|
unsigned LO = (Ty == MVT::i32) ? Mips::LO : Mips::LO64;
|
||||||
unsigned HI = (Ty == MVT::i32) ? Mips::HI : Mips::HI64;
|
unsigned HI = (Ty == MVT::i32) ? Mips::HI : Mips::HI64;
|
||||||
unsigned Opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem :
|
unsigned Opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem16 :
|
||||||
MipsISD::DivRemU;
|
MipsISD::DivRemU16;
|
||||||
DebugLoc DL = N->getDebugLoc();
|
DebugLoc DL = N->getDebugLoc();
|
||||||
|
|
||||||
SDValue DivRem = DAG.getNode(Opc, DL, MVT::Glue,
|
SDValue DivRem = DAG.getNode(Opc, DL, MVT::Glue,
|
||||||
|
@@ -23,13 +23,16 @@ def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>,
|
|||||||
SDTCisInt<4>]>;
|
SDTCisInt<4>]>;
|
||||||
def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
|
def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
|
||||||
def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
|
def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
|
||||||
def SDT_MipsMAddMSub : SDTypeProfile<0, 4,
|
def SDT_ExtractLOHI : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVT<1, untyped>,
|
||||||
[SDTCisVT<0, i32>, SDTCisSameAs<0, 1>,
|
SDTCisVT<2, i32>]>;
|
||||||
SDTCisSameAs<1, 2>,
|
def SDT_InsertLOHI : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>,
|
||||||
SDTCisSameAs<2, 3>]>;
|
SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>;
|
||||||
def SDT_MipsDivRem : SDTypeProfile<0, 2,
|
def SDT_MipsMultDiv : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>, SDTCisInt<1>,
|
||||||
[SDTCisInt<0>,
|
SDTCisSameAs<1, 2>]>;
|
||||||
SDTCisSameAs<0, 1>]>;
|
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>]>;
|
def SDT_MipsThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>;
|
||||||
|
|
||||||
@@ -82,20 +85,27 @@ def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd,
|
|||||||
[SDNPHasChain, SDNPSideEffect,
|
[SDNPHasChain, SDNPSideEffect,
|
||||||
SDNPOptInGlue, SDNPOutGlue]>;
|
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
|
// MAdd*/MSub* nodes
|
||||||
def MipsMAdd : SDNode<"MipsISD::MAdd", SDT_MipsMAddMSub,
|
def MipsMAdd : SDNode<"MipsISD::MAdd", SDT_MipsMAddMSub>;
|
||||||
[SDNPOptInGlue, SDNPOutGlue]>;
|
def MipsMAddu : SDNode<"MipsISD::MAddu", SDT_MipsMAddMSub>;
|
||||||
def MipsMAddu : SDNode<"MipsISD::MAddu", SDT_MipsMAddMSub,
|
def MipsMSub : SDNode<"MipsISD::MSub", SDT_MipsMAddMSub>;
|
||||||
[SDNPOptInGlue, SDNPOutGlue]>;
|
def MipsMSubu : SDNode<"MipsISD::MSubu", SDT_MipsMAddMSub>;
|
||||||
def MipsMSub : SDNode<"MipsISD::MSub", SDT_MipsMAddMSub,
|
|
||||||
[SDNPOptInGlue, SDNPOutGlue]>;
|
|
||||||
def MipsMSubu : SDNode<"MipsISD::MSubu", SDT_MipsMAddMSub,
|
|
||||||
[SDNPOptInGlue, SDNPOutGlue]>;
|
|
||||||
|
|
||||||
// DivRem(u) nodes
|
// DivRem(u) nodes
|
||||||
def MipsDivRem : SDNode<"MipsISD::DivRem", SDT_MipsDivRem,
|
def MipsDivRem : SDNode<"MipsISD::DivRem", SDT_MipsMultDiv>;
|
||||||
[SDNPOutGlue]>;
|
def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsMultDiv>;
|
||||||
def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsDivRem,
|
def MipsDivRem16 : SDNode<"MipsISD::DivRem16", SDT_MipsDivRem16, [SDNPOutGlue]>;
|
||||||
|
def MipsDivRemU16 : SDNode<"MipsISD::DivRemU16", SDT_MipsDivRem16,
|
||||||
[SDNPOutGlue]>;
|
[SDNPOutGlue]>;
|
||||||
|
|
||||||
// Target constant nodes that are not part of any isel patterns and remain
|
// 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
|
// 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),
|
InstSE<(outs), (ins CPURegsOpnd:$rs, CPURegsOpnd:$rt),
|
||||||
!strconcat(opstr, "\t$rs, $rt"),
|
!strconcat(opstr, "\t$rs, $rt"), [], IIImul, FrmR> {
|
||||||
[(op CPURegsOpnd:$rs, CPURegsOpnd:$rt, LO, HI)], IIImul, FrmR> {
|
|
||||||
let Defs = [HI, LO];
|
let Defs = [HI, LO];
|
||||||
let Uses = [HI, LO];
|
let Uses = [HI, LO];
|
||||||
let isCommutable = isComm;
|
let isCommutable = isComm;
|
||||||
@@ -629,11 +638,34 @@ class Mult<string opstr, InstrItinClass itin, RegisterOperand RO,
|
|||||||
let neverHasSideEffects = 1;
|
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> :
|
list<Register> DefRegs> :
|
||||||
InstSE<(outs), (ins RO:$rs, RO:$rt),
|
InstSE<(outs), (ins RO:$rs, RO:$rt), !strconcat(opstr, "\t$$zero, $rs, $rt"),
|
||||||
!strconcat(opstr, "\t$$zero, $rs, $rt"), [(op RO:$rs, RO:$rt)], itin,
|
[], itin, FrmR> {
|
||||||
FrmR> {
|
|
||||||
let Defs = DefRegs;
|
let Defs = DefRegs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -934,10 +966,13 @@ let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1 in {
|
|||||||
/// Multiply and Divide Instructions.
|
/// Multiply and Divide Instructions.
|
||||||
def MULT : Mult<"mult", IIImul, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x18>;
|
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 MULTu : Mult<"multu", IIImul, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x19>;
|
||||||
def SDIV : Div<MipsDivRem, "div", IIIdiv, CPURegsOpnd, [HI, LO]>,
|
def PseudoMULT : MultDivPseudo<MULT, ACRegs, CPURegsOpnd, MipsMult, IIImul>;
|
||||||
MULT_FM<0, 0x1a>;
|
def PseudoMULTu : MultDivPseudo<MULTu, ACRegs, CPURegsOpnd, MipsMultu, IIImul>;
|
||||||
def UDIV : Div<MipsDivRemU, "divu", IIIdiv, CPURegsOpnd, [HI, LO]>,
|
def SDIV : Div<"div", IIIdiv, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x1a>;
|
||||||
MULT_FM<0, 0x1b>;
|
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 MTHI : MoveToLOHI<"mthi", CPURegs, [HI]>, MTLO_FM<0x11>;
|
||||||
def MTLO : MoveToLOHI<"mtlo", CPURegs, [LO]>, MTLO_FM<0x13>;
|
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>;
|
def LEA_ADDiu : EffectiveAddress<"addiu", CPURegs, mem_ea>, LW_FM<9>;
|
||||||
|
|
||||||
// MADD*/MSUB*
|
// MADD*/MSUB*
|
||||||
def MADD : MArithR<"madd", MipsMAdd, 1>, MULT_FM<0x1c, 0>;
|
def MADD : MArithR<"madd", 1>, MULT_FM<0x1c, 0>;
|
||||||
def MADDU : MArithR<"maddu", MipsMAddu, 1>, MULT_FM<0x1c, 1>;
|
def MADDU : MArithR<"maddu", 1>, MULT_FM<0x1c, 1>;
|
||||||
def MSUB : MArithR<"msub", MipsMSub>, MULT_FM<0x1c, 4>;
|
def MSUB : MArithR<"msub">, MULT_FM<0x1c, 4>;
|
||||||
def MSUBU : MArithR<"msubu", MipsMSubu>, MULT_FM<0x1c, 5>;
|
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;
|
def RDHWR : ReadHardware<CPURegs, HWRegsOpnd>, RDHWR_FM;
|
||||||
|
|
||||||
@@ -1240,6 +1279,10 @@ defm : SetgeImmPats<CPURegs, SLTi, SLTiu>;
|
|||||||
// bswap pattern
|
// bswap pattern
|
||||||
def : MipsPat<(bswap CPURegs:$rt), (ROTR (WSBH CPURegs:$rt), 16)>;
|
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
|
// Floating Point Support
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@@ -450,6 +450,19 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
|
|||||||
ReplaceUses(SDValue(Node, 0), ResNode);
|
ReplaceUses(SDValue(Node, 0), ResNode);
|
||||||
return std::make_pair(true, ResNode.getNode());
|
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);
|
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::MEMBARRIER, MVT::Other, Custom);
|
||||||
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
|
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
|
||||||
setOperationAction(ISD::LOAD, MVT::i32, 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 *
|
MachineBasicBlock *
|
||||||
MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||||
MachineBasicBlock *BB) const {
|
MachineBasicBlock *BB) const {
|
||||||
@@ -133,6 +160,29 @@ getOpndList(SmallVectorImpl<SDValue> &Ops,
|
|||||||
InternalLinkage, CLI, Callee, Chain);
|
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::
|
MachineBasicBlock * MipsSETargetLowering::
|
||||||
emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{
|
emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{
|
||||||
// $bb:
|
// $bb:
|
||||||
|
@@ -24,6 +24,8 @@ namespace llvm {
|
|||||||
|
|
||||||
virtual bool allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const;
|
virtual bool allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const;
|
||||||
|
|
||||||
|
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
|
||||||
|
|
||||||
virtual MachineBasicBlock *
|
virtual MachineBasicBlock *
|
||||||
EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const;
|
EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const;
|
||||||
|
|
||||||
@@ -47,6 +49,9 @@ namespace llvm {
|
|||||||
bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
|
bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
|
||||||
CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const;
|
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 *emitBPOSGE32(MachineInstr *MI,
|
||||||
MachineBasicBlock *BB) const;
|
MachineBasicBlock *BB) const;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user