/// Subtarget - Keep a pointer to the MipsSubtarget around so that we can
/// make the right decision when generating code for different targets.
- //TODO: add initialization on constructor
- //const MipsSubtarget *Subtarget;
+ const MipsSubtarget &Subtarget;
public:
- MipsDAGToDAGISel(MipsTargetMachine &tm) :
- SelectionDAGISel(MipsLowering),
- TM(tm), MipsLowering(*TM.getTargetLowering()) {}
+ MipsDAGToDAGISel(MipsTargetMachine &tm) : SelectionDAGISel(MipsLowering),
+ TM(tm), MipsLowering(*TM.getTargetLowering()),
+ Subtarget(tm.getSubtarget<MipsSubtarget>()) {}
- virtual void InstructionSelectBasicBlock(SelectionDAG &SD);
+ virtual void InstructionSelect(SelectionDAG &SD);
// Pass Name
virtual const char *getPassName() const {
}
-/// InstructionSelectBasicBlock - This callback is invoked by
+/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void MipsDAGToDAGISel::
-InstructionSelectBasicBlock(SelectionDAG &SD)
+InstructionSelect(SelectionDAG &SD)
{
DEBUG(BB->dump());
// Codegen the basic block.
#endif
SD.RemoveDeadNodes();
-
- // Emit machine code to BB.
- ScheduleAndEmitDAG(SD);
}
/// getGlobalBaseReg - Output the instructions required to put the
default: break;
- /// Special Mul operations
+ case ISD::SUBE:
+ case ISD::ADDE: {
+ SDOperand InFlag = Node->getOperand(2), CmpLHS;
+ unsigned Opc = InFlag.getOpcode(), MOp;
+
+ assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) ||
+ (Opc == ISD::SUBC || Opc == ISD::SUBE)) &&
+ "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn");
+
+ if (Opcode == ISD::ADDE) {
+ CmpLHS = InFlag.getValue(0);
+ MOp = Mips::ADDu;
+ } else {
+ CmpLHS = InFlag.getOperand(0);
+ MOp = Mips::SUBu;
+ }
+
+ SDOperand Ops[] = { CmpLHS, InFlag.getOperand(1) };
+
+ SDOperand LHS = Node->getOperand(0);
+ SDOperand RHS = Node->getOperand(1);
+ AddToISelQueue(LHS);
+ AddToISelQueue(RHS);
+
+ MVT VT = LHS.getValueType();
+ SDNode *Carry = CurDAG->getTargetNode(Mips::SLTu, VT, Ops, 2);
+ SDNode *AddCarry = CurDAG->getTargetNode(Mips::ADDu, VT,
+ SDOperand(Carry,0), RHS);
+
+ return CurDAG->SelectNodeTo(N.Val, MOp, VT, MVT::Flag,
+ LHS, SDOperand(AddCarry,0));
+ }
+
+ /// Mul/Div with two results
+ case ISD::SDIVREM:
+ case ISD::UDIVREM:
+ case ISD::SMUL_LOHI:
+ case ISD::UMUL_LOHI: {
+ SDOperand Op1 = Node->getOperand(0);
+ SDOperand Op2 = Node->getOperand(1);
+ AddToISelQueue(Op1);
+ AddToISelQueue(Op2);
+
+ unsigned Op;
+ if (Opcode == ISD::UMUL_LOHI || Opcode == ISD::SMUL_LOHI)
+ Op = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT);
+ else
+ Op = (Opcode == ISD::UDIVREM ? Mips::DIVu : Mips::DIV);
+
+ SDNode *Node = CurDAG->getTargetNode(Op, MVT::Flag, Op1, Op2);
+
+ SDOperand InFlag = SDOperand(Node, 0);
+ SDNode *Lo = CurDAG->getTargetNode(Mips::MFLO, MVT::i32, MVT::Flag, InFlag);
+
+ InFlag = SDOperand(Lo,1);
+ SDNode *Hi = CurDAG->getTargetNode(Mips::MFHI, MVT::i32, InFlag);
+
+ if (!N.getValue(0).use_empty())
+ ReplaceUses(N.getValue(0), SDOperand(Lo,0));
+
+ if (!N.getValue(1).use_empty())
+ ReplaceUses(N.getValue(1), SDOperand(Hi,0));
+
+ return NULL;
+ }
+
+ /// Special Muls
+ case ISD::MUL:
case ISD::MULHS:
case ISD::MULHU: {
SDOperand MulOp1 = Node->getOperand(0);
unsigned MulOp = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT);
SDNode *MulNode = CurDAG->getTargetNode(MulOp, MVT::Flag, MulOp1, MulOp2);
- SDOperand MFInFlag = SDOperand(MulNode, 0);
- return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag);
+ SDOperand InFlag = SDOperand(MulNode, 0);
+
+ if (MulOp == ISD::MUL)
+ return CurDAG->getTargetNode(Mips::MFLO, MVT::i32, InFlag);
+ else
+ return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, InFlag);
}
- /// Div operations
+ /// Div/Rem operations
+ case ISD::SREM:
+ case ISD::UREM:
case ISD::SDIV:
case ISD::UDIV: {
- SDOperand DivOp1 = Node->getOperand(0);
- SDOperand DivOp2 = Node->getOperand(1);
- AddToISelQueue(DivOp1);
- AddToISelQueue(DivOp2);
-
- unsigned DivOp = (Opcode == ISD::SDIV ? Mips::DIV : Mips::DIVu);
- SDNode *DivNode = CurDAG->getTargetNode(DivOp, MVT::Flag, DivOp1, DivOp2);
-
- SDOperand MFInFlag = SDOperand(DivNode, 0);
- return CurDAG->getTargetNode(Mips::MFLO, MVT::i32, MFInFlag);
- }
+ SDOperand Op1 = Node->getOperand(0);
+ SDOperand Op2 = Node->getOperand(1);
+ AddToISelQueue(Op1);
+ AddToISelQueue(Op2);
+
+ unsigned Op, MOp;
+ if (Opcode == ISD::SDIV || Opcode == ISD::UDIV) {
+ Op = (Opcode == ISD::SDIV ? Mips::DIV : Mips::DIVu);
+ MOp = Mips::MFLO;
+ } else {
+ Op = (Opcode == ISD::SREM ? Mips::DIV : Mips::DIVu);
+ MOp = Mips::MFHI;
+ }
+ SDNode *Node = CurDAG->getTargetNode(Op, MVT::Flag, Op1, Op2);
- /// Rem operations
- case ISD::SREM:
- case ISD::UREM: {
- SDOperand RemOp1 = Node->getOperand(0);
- SDOperand RemOp2 = Node->getOperand(1);
- AddToISelQueue(RemOp1);
- AddToISelQueue(RemOp2);
-
- unsigned RemOp = (Opcode == ISD::SREM ? Mips::DIV : Mips::DIVu);
- SDNode *RemNode = CurDAG->getTargetNode(RemOp, MVT::Flag, RemOp1, RemOp2);
-
- SDOperand MFInFlag = SDOperand(RemNode, 0);
- return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag);
+ SDOperand InFlag = SDOperand(Node, 0);
+ return CurDAG->getTargetNode(MOp, MVT::i32, InFlag);
}
// Get target GOT address.