diff options
author | Bruno Cardoso Lopes <bruno.cardoso@gmail.com> | 2008-06-06 06:37:31 +0000 |
---|---|---|
committer | Bruno Cardoso Lopes <bruno.cardoso@gmail.com> | 2008-06-06 06:37:31 +0000 |
commit | 0af5e095ad16091457c35edd015fe2931023f58b (patch) | |
tree | 2564e5299596cf64239b5e5540258d66061ca4f9 /lib | |
parent | 07cec75913b74d04df40ff7fecf51f87175076c1 (diff) | |
download | external_llvm-0af5e095ad16091457c35edd015fe2931023f58b.zip external_llvm-0af5e095ad16091457c35edd015fe2931023f58b.tar.gz external_llvm-0af5e095ad16091457c35edd015fe2931023f58b.tar.bz2 |
Added custom isel for MUL, SDIVREM, UDIVREM, SMUL_LOHI and UMUL_LOHI nodes
MUL is not anymore directly matched because its a pseudoinstruction.
LogicI class fixed to zero-extend immediates.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@52036 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/Mips/MipsISelDAGToDAG.cpp | 127 | ||||
-rw-r--r-- | lib/Target/Mips/MipsInstrInfo.td | 5 |
2 files changed, 76 insertions, 56 deletions
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index 8043f7b..ceb4bed 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -226,14 +226,24 @@ Select(SDOperand N) default: break; + case ISD::SUBE: case ISD::ADDE: { - // ADDE is usally attached with a ADDC instruction, we must - // compare ADDC operands and set a register if we have a carry. - SDOperand InFlag = Node->getOperand(2); - unsigned Opc = InFlag.getOpcode(); - assert((Opc == ISD::ADDC || Opc == ISD::ADDE) && - "ADDE flag operand must come from a ADDC or ADDE"); - SDOperand Ops[] = { InFlag.getValue(0), InFlag.getOperand(1) }; + 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); @@ -245,34 +255,45 @@ Select(SDOperand N) SDNode *AddCarry = CurDAG->getTargetNode(Mips::ADDu, VT, SDOperand(Carry,0), RHS); - return CurDAG->SelectNodeTo(N.Val, Mips::ADDu, VT, MVT::Flag, + return CurDAG->SelectNodeTo(N.Val, MOp, VT, MVT::Flag, LHS, SDOperand(AddCarry,0)); } - case ISD::SUBE: { - // SUBE is usally attached with a SUBC instruction, we must - // compare SUBC operands and set a register if we have a carry. - SDOperand InFlag = Node->getOperand(2); - unsigned Opc = InFlag.getOpcode(); - assert((Opc == ISD::SUBC || Opc == ISD::SUBE) && - "SUBE flag operand must come from a SUBC or SUBE"); - SDOperand Ops[] = { InFlag.getOperand(0), InFlag.getOperand(1) }; + /// 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); - SDOperand LHS = Node->getOperand(0); - SDOperand RHS = Node->getOperand(1); - AddToISelQueue(LHS); - AddToISelQueue(RHS); + 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); - MVT::ValueType VT = LHS.getValueType(); - SDNode *Carry = CurDAG->getTargetNode(Mips::SLTu, VT, Ops, 2); - SDNode *AddCarry = CurDAG->getTargetNode(Mips::ADDu, VT, - SDOperand(Carry,0), RHS); + SDNode *Node = CurDAG->getTargetNode(Op, MVT::Flag, Op1, Op2); - return CurDAG->SelectNodeTo(N.Val, Mips::SUBu, VT, MVT::Flag, - LHS, SDOperand(AddCarry,0)); + 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 Mul operations + /// Special Muls + case ISD::MUL: case ISD::MULHS: case ISD::MULHU: { SDOperand MulOp1 = Node->getOperand(0); @@ -283,38 +304,36 @@ Select(SDOperand N) 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. diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index b469167..57f24ad 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -172,7 +172,7 @@ class LogicI<bits<6> op, string instr_asm, SDNode OpNode>: (outs CPURegs:$dst), (ins CPURegs:$b, uimm16:$c), !strconcat(instr_asm, " $dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, immSExt16:$c))], IIAlu>; + [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt16:$c))], IIAlu>; class LogicNOR<bits<6> op, bits<6> func, string instr_asm>: FR< op, @@ -392,9 +392,10 @@ let usesCustomDAGSchedInserter = 1 in { // ADDiu just accept 16-bit immediates but we handle this on Pat's. // immZExt32 is used here so it can match GlobalAddress immediates. +// MUL is a assembly macro in the current used ISAs. def ADDiu : ArithI<0x09, "addiu", add, uimm16, immZExt16>; def ADDi : ArithI<0x08, "addi", add, simm16, immSExt16>; -def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul>; +//def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul>; def ADDu : ArithR<0x00, 0x21, "addu", add, IIAlu>; def SUBu : ArithR<0x00, 0x23, "subu", sub, IIAlu>; def ADD : ArithOverflowR<0x00, 0x20, "add">; |