[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:
Akira Hatanaka 2013-03-30 01:36:35 +00:00
parent 9cf0724cc3
commit f5926fd844
7 changed files with 199 additions and 70 deletions

View File

@ -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

View File

@ -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
//===----------------------------------------------------------------------===//

View File

@ -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,

View File

@ -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
//===----------------------------------------------------------------------===//

View File

@ -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);

View File

@ -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:

View File

@ -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;
};