X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FPowerPC%2FPPCISelDAGToDAG.cpp;h=ae32f9479e6861f2891fb434816660a37ba2f763;hb=222adac30a642b5ea4a916eb3e97d8d95eb32bea;hp=dd3fe514df25444a66abf742924cb0f6c42e2546;hpb=c09eeec0ebc378644bafd04916e5efafa7d98152;p=oota-llvm.git diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index dd3fe514df2..ae32f9479e6 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -83,23 +83,73 @@ namespace { /// InstructionSelectBasicBlock - This callback is invoked by /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. - virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) { - DEBUG(BB->dump()); - // Select target instructions for the DAG. - DAG.setRoot(Select(DAG.getRoot())); - DAG.RemoveDeadNodes(); - - // Emit machine code to BB. - ScheduleAndEmitDAG(DAG); - } - + virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); + virtual const char *getPassName() const { return "PowerPC DAG->DAG Pattern Instruction Selection"; } + +// Include the pieces autogenerated from the target description. +#include "PPC32GenDAGISel.inc" + +private: + SDOperand SelectDYNAMIC_STACKALLOC(SDOperand Op); + SDOperand SelectADD_PARTS(SDOperand Op); + SDOperand SelectSUB_PARTS(SDOperand Op); + SDOperand SelectSETCC(SDOperand Op); }; } -#include "PPC32GenDAGISel.inc" +/// InstructionSelectBasicBlock - This callback is invoked by +/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. +void PPC32DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { + DEBUG(BB->dump()); + + // The selection process is inherently a bottom-up recursive process (users + // select their uses before themselves). Given infinite stack space, we + // could just start selecting on the root and traverse the whole graph. In + // practice however, this causes us to run out of stack space on large basic + // blocks. To avoid this problem, select the entry node, then all its uses, + // iteratively instead of recursively. + std::vector Worklist; + Worklist.push_back(DAG.getEntryNode()); + + // Note that we can do this in the PPC target (scanning forward across token + // chain edges) because no nodes ever get folded across these edges. On a + // target like X86 which supports load/modify/store operations, this would + // have to be more careful. + while (!Worklist.empty()) { + SDOperand Node = Worklist.back(); + Worklist.pop_back(); + + if ((Node.Val->getOpcode() >= ISD::BUILTIN_OP_END && + Node.Val->getOpcode() < PPCISD::FIRST_NUMBER) || + CodeGenMap.count(Node)) continue; + + for (SDNode::use_iterator UI = Node.Val->use_begin(), + E = Node.Val->use_end(); UI != E; ++UI) { + // Scan the values. If this use has a value that is a token chain, add it + // to the worklist. + SDNode *User = *UI; + for (unsigned i = 0, e = User->getNumValues(); i != e; ++i) + if (User->getValueType(i) == MVT::Other) { + Worklist.push_back(SDOperand(User, i)); + break; + } + } + + // Finally, legalize this node. + Select(Node); + } + + // Select target instructions for the DAG. + DAG.setRoot(Select(DAG.getRoot())); + CodeGenMap.clear(); + DAG.RemoveDeadNodes(); + + // Emit machine code to BB. + ScheduleAndEmitDAG(DAG); +} /// getGlobalBaseReg - Output the instructions required to put the /// base address to use for accessing globals into a register. @@ -440,8 +490,10 @@ SDOperand PPC32DAGToDAGISel::SelectCC(SDOperand LHS, SDOperand RHS, LHS, getI32Imm(Lo16(Imm))); return CurDAG->getTargetNode(U ? PPC::CMPLW : PPC::CMPW, MVT::i32, LHS, Select(RHS)); + } else if (LHS.getValueType() == MVT::f32) { + return CurDAG->getTargetNode(PPC::FCMPUS, MVT::i32, LHS, Select(RHS)); } else { - return CurDAG->getTargetNode(PPC::FCMPU, MVT::i32, LHS, Select(RHS)); + return CurDAG->getTargetNode(PPC::FCMPUD, MVT::i32, LHS, Select(RHS)); } } @@ -627,6 +679,211 @@ SDOperand PPC32DAGToDAGISel::BuildUDIVSequence(SDNode *N) { } } +SDOperand PPC32DAGToDAGISel::SelectDYNAMIC_STACKALLOC(SDOperand Op) { + SDNode *N = Op.Val; + + // FIXME: We are currently ignoring the requested alignment for handling + // greater than the stack alignment. This will need to be revisited at some + // point. Align = N.getOperand(2); + if (!isa(N->getOperand(2)) || + cast(N->getOperand(2))->getValue() != 0) { + std::cerr << "Cannot allocate stack object with greater alignment than" + << " the stack alignment yet!"; + abort(); + } + SDOperand Chain = Select(N->getOperand(0)); + SDOperand Amt = Select(N->getOperand(1)); + + SDOperand R1Reg = CurDAG->getRegister(PPC::R1, MVT::i32); + + SDOperand R1Val = CurDAG->getCopyFromReg(Chain, PPC::R1, MVT::i32); + Chain = R1Val.getValue(1); + + // Subtract the amount (guaranteed to be a multiple of the stack alignment) + // from the stack pointer, giving us the result pointer. + SDOperand Result = CurDAG->getTargetNode(PPC::SUBF, MVT::i32, Amt, R1Val); + + // Copy this result back into R1. + Chain = CurDAG->getNode(ISD::CopyToReg, MVT::Other, Chain, R1Reg, Result); + + // Copy this result back out of R1 to make sure we're not using the stack + // space without decrementing the stack pointer. + Result = CurDAG->getCopyFromReg(Chain, PPC::R1, MVT::i32); + + // Finally, replace the DYNAMIC_STACKALLOC with the copyfromreg. + CodeGenMap[Op.getValue(0)] = Result; + CodeGenMap[Op.getValue(1)] = Result.getValue(1); + return SDOperand(Result.Val, Op.ResNo); +} + +SDOperand PPC32DAGToDAGISel::SelectADD_PARTS(SDOperand Op) { + SDNode *N = Op.Val; + SDOperand LHSL = Select(N->getOperand(0)); + SDOperand LHSH = Select(N->getOperand(1)); + + unsigned Imm; + bool ME = false, ZE = false; + if (isIntImmediate(N->getOperand(3), Imm)) { + ME = (signed)Imm == -1; + ZE = Imm == 0; + } + + std::vector Result; + SDOperand CarryFromLo; + if (isIntImmediate(N->getOperand(2), Imm) && + ((signed)Imm >= -32768 || (signed)Imm < 32768)) { + // Codegen the low 32 bits of the add. Interestingly, there is no + // shifted form of add immediate carrying. + CarryFromLo = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, + LHSL, getI32Imm(Imm)); + } else { + CarryFromLo = CurDAG->getTargetNode(PPC::ADDC, MVT::i32, MVT::Flag, + LHSL, Select(N->getOperand(2))); + } + CarryFromLo = CarryFromLo.getValue(1); + + // Codegen the high 32 bits, adding zero, minus one, or the full value + // along with the carry flag produced by addc/addic. + SDOperand ResultHi; + if (ZE) + ResultHi = CurDAG->getTargetNode(PPC::ADDZE, MVT::i32, LHSH, CarryFromLo); + else if (ME) + ResultHi = CurDAG->getTargetNode(PPC::ADDME, MVT::i32, LHSH, CarryFromLo); + else + ResultHi = CurDAG->getTargetNode(PPC::ADDE, MVT::i32, LHSH, + Select(N->getOperand(3)), CarryFromLo); + Result.push_back(CarryFromLo.getValue(0)); + Result.push_back(ResultHi); + + CodeGenMap[Op.getValue(0)] = Result[0]; + CodeGenMap[Op.getValue(1)] = Result[1]; + return Result[Op.ResNo]; +} +SDOperand PPC32DAGToDAGISel::SelectSUB_PARTS(SDOperand Op) { + SDNode *N = Op.Val; + SDOperand LHSL = Select(N->getOperand(0)); + SDOperand LHSH = Select(N->getOperand(1)); + SDOperand RHSL = Select(N->getOperand(2)); + SDOperand RHSH = Select(N->getOperand(3)); + + std::vector Result; + Result.push_back(CurDAG->getTargetNode(PPC::SUBFC, MVT::i32, MVT::Flag, + RHSL, LHSL)); + Result.push_back(CurDAG->getTargetNode(PPC::SUBFE, MVT::i32, RHSH, LHSH, + Result[0].getValue(1))); + CodeGenMap[Op.getValue(0)] = Result[0]; + CodeGenMap[Op.getValue(1)] = Result[1]; + return Result[Op.ResNo]; +} + +SDOperand PPC32DAGToDAGISel::SelectSETCC(SDOperand Op) { + SDNode *N = Op.Val; + unsigned Imm; + ISD::CondCode CC = cast(N->getOperand(2))->get(); + if (isIntImmediate(N->getOperand(1), Imm)) { + // We can codegen setcc op, imm very efficiently compared to a brcond. + // Check for those cases here. + // setcc op, 0 + if (Imm == 0) { + SDOperand Op = Select(N->getOperand(0)); + switch (CC) { + default: assert(0 && "Unhandled SetCC condition"); abort(); + case ISD::SETEQ: + Op = CurDAG->getTargetNode(PPC::CNTLZW, MVT::i32, Op); + CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Op, getI32Imm(27), + getI32Imm(5), getI32Imm(31)); + break; + case ISD::SETNE: { + SDOperand AD = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, + Op, getI32Imm(~0U)); + CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, AD, Op, AD.getValue(1)); + break; + } + case ISD::SETLT: + CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Op, getI32Imm(1), + getI32Imm(31), getI32Imm(31)); + break; + case ISD::SETGT: { + SDOperand T = CurDAG->getTargetNode(PPC::NEG, MVT::i32, Op); + T = CurDAG->getTargetNode(PPC::ANDC, MVT::i32, T, Op);; + CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, T, getI32Imm(1), + getI32Imm(31), getI32Imm(31)); + break; + } + } + return SDOperand(N, 0); + } else if (Imm == ~0U) { // setcc op, -1 + SDOperand Op = Select(N->getOperand(0)); + switch (CC) { + default: assert(0 && "Unhandled SetCC condition"); abort(); + case ISD::SETEQ: + Op = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, + Op, getI32Imm(1)); + CurDAG->SelectNodeTo(N, PPC::ADDZE, MVT::i32, + CurDAG->getTargetNode(PPC::LI, MVT::i32, + getI32Imm(0)), + Op.getValue(1)); + break; + case ISD::SETNE: { + Op = CurDAG->getTargetNode(PPC::NOR, MVT::i32, Op, Op); + SDOperand AD = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, + Op, getI32Imm(~0U)); + CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, AD, Op, AD.getValue(1)); + break; + } + case ISD::SETLT: { + SDOperand AD = CurDAG->getTargetNode(PPC::ADDI, MVT::i32, Op, + getI32Imm(1)); + SDOperand AN = CurDAG->getTargetNode(PPC::AND, MVT::i32, AD, Op); + CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, AN, getI32Imm(1), + getI32Imm(31), getI32Imm(31)); + break; + } + case ISD::SETGT: + Op = CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, Op, getI32Imm(1), + getI32Imm(31), getI32Imm(31)); + CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Op, getI32Imm(1)); + break; + } + return SDOperand(N, 0); + } + } + + bool Inv; + unsigned Idx = getCRIdxForSetCC(CC, Inv); + SDOperand CCReg = SelectCC(N->getOperand(0), N->getOperand(1), CC); + SDOperand IntCR; + + // Force the ccreg into CR7. + SDOperand CR7Reg = CurDAG->getRegister(PPC::CR7, MVT::i32); + + std::vector VTs; + VTs.push_back(MVT::Other); + VTs.push_back(MVT::Flag); // NONSTANDARD CopyToReg node: defines a flag + std::vector Ops; + Ops.push_back(CurDAG->getEntryNode()); + Ops.push_back(CR7Reg); + Ops.push_back(CCReg); + CCReg = CurDAG->getNode(ISD::CopyToReg, VTs, Ops).getValue(1); + + if (TLI.getTargetMachine().getSubtarget().isGigaProcessor()) + IntCR = CurDAG->getTargetNode(PPC::MFOCRF, MVT::i32, CR7Reg, CCReg); + else + IntCR = CurDAG->getTargetNode(PPC::MFCR, MVT::i32, CCReg); + + if (!Inv) { + CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, IntCR, + getI32Imm(32-(3-Idx)), getI32Imm(31), getI32Imm(31)); + } else { + SDOperand Tmp = + CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, IntCR, + getI32Imm(32-(3-Idx)), getI32Imm(31),getI32Imm(31)); + CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Tmp, getI32Imm(1)); + } + + return SDOperand(N, 0); +} + // Select - Convert the specified operand from a target-independent to a // target-specific node if it hasn't already been changed. SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { @@ -634,18 +891,17 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { if (N->getOpcode() >= ISD::BUILTIN_OP_END && N->getOpcode() < PPCISD::FIRST_NUMBER) return Op; // Already selected. + + // If this has already been converted, use it. + std::map::iterator CGMI = CodeGenMap.find(Op); + if (CGMI != CodeGenMap.end()) return CGMI->second; switch (N->getOpcode()) { - default: - std::cerr << "Cannot yet select: "; - N->dump(); - std::cerr << "\n"; - abort(); - case ISD::EntryToken: // These leaves remain the same. - return Op; - case ISD::AssertSext: - case ISD::AssertZext: - return Select(N->getOperand(0)); + default: break; + case ISD::DYNAMIC_STACKALLOC: return SelectDYNAMIC_STACKALLOC(Op); + case ISD::ADD_PARTS: return SelectADD_PARTS(Op); + case ISD::SUB_PARTS: return SelectSUB_PARTS(Op); + case ISD::SETCC: return SelectSETCC(Op); case ISD::TokenFactor: { SDOperand New; if (N->getNumOperands() == 2) { @@ -659,11 +915,8 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { New = CurDAG->getNode(ISD::TokenFactor, MVT::Other, Ops); } - if (New.Val != N) { - CurDAG->ReplaceAllUsesWith(Op, New); - N = New.Val; - } - return SDOperand(N, 0); + if (!N->hasOneUse()) CodeGenMap[Op] = New; + return New; } case ISD::CopyFromReg: { SDOperand Chain = Select(N->getOperand(0)); @@ -676,38 +929,18 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { SDOperand Chain = Select(N->getOperand(0)); SDOperand Reg = N->getOperand(1); SDOperand Val = Select(N->getOperand(2)); - if (Chain != N->getOperand(0) || Val != N->getOperand(2)) { - SDOperand New = CurDAG->getNode(ISD::CopyToReg, MVT::Other, - Chain, Reg, Val); - CurDAG->ReplaceAllUsesWith(Op, New); - N = New.Val; - } - return SDOperand(N, 0); - } - case ISD::Constant: { - assert(N->getValueType(0) == MVT::i32); - unsigned v = (unsigned)cast(N)->getValue(); - - // NOTE: This doesn't use SelectNodeTo, because doing that will prevent - // folding shared immediates into other the second instruction that - // uses it. - if (isInt16(v)) - return CurDAG->getTargetNode(PPC::LI, MVT::i32, getI32Imm(v)); - - unsigned Hi = Hi16(v); - unsigned Lo = Lo16(v); - - if (!Lo) - return CurDAG->getTargetNode(PPC::LIS, MVT::i32, getI32Imm(Hi)); - - SDOperand Top = CurDAG->getTargetNode(PPC::LIS, MVT::i32, getI32Imm(Hi)); - return CurDAG->getTargetNode(PPC::ORI, MVT::i32, Top, getI32Imm(Lo)); + SDOperand New = CurDAG->getNode(ISD::CopyToReg, MVT::Other, + Chain, Reg, Val); + if (!N->hasOneUse()) CodeGenMap[Op] = New; + return New; } case ISD::UNDEF: if (N->getValueType(0) == MVT::i32) CurDAG->SelectNodeTo(N, PPC::IMPLICIT_DEF_GPR, MVT::i32); - else - CurDAG->SelectNodeTo(N, PPC::IMPLICIT_DEF_FP, N->getValueType(0)); + else if (N->getValueType(0) == MVT::f32) + CurDAG->SelectNodeTo(N, PPC::IMPLICIT_DEF_F4, MVT::f32); + else + CurDAG->SelectNodeTo(N, PPC::IMPLICIT_DEF_F8, MVT::f64); return SDOperand(N, 0); case ISD::FrameIndex: { int FI = cast(N)->getIndex(); @@ -741,60 +974,18 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { CurDAG->SelectNodeTo(N, PPC::LA, MVT::i32, Tmp, GA); return SDOperand(N, 0); } - case ISD::DYNAMIC_STACKALLOC: { - // FIXME: We are currently ignoring the requested alignment for handling - // greater than the stack alignment. This will need to be revisited at some - // point. Align = N.getOperand(2); - if (!isa(N->getOperand(2)) || - cast(N->getOperand(2))->getValue() != 0) { - std::cerr << "Cannot allocate stack object with greater alignment than" - << " the stack alignment yet!"; - abort(); - } - SDOperand Chain = Select(N->getOperand(0)); - SDOperand Amt = Select(N->getOperand(1)); - - SDOperand R1Reg = CurDAG->getRegister(PPC::R1, MVT::i32); - - SDOperand R1Val = CurDAG->getCopyFromReg(Chain, PPC::R1, MVT::i32); - Chain = R1Val.getValue(1); - - // Subtract the amount (guaranteed to be a multiple of the stack alignment) - // from the stack pointer, giving us the result pointer. - SDOperand Result = CurDAG->getTargetNode(PPC::SUBF, MVT::i32, Amt, R1Val); - - // Copy this result back into R1. - Chain = CurDAG->getNode(ISD::CopyToReg, MVT::Other, Chain, R1Reg, Result); - // Copy this result back out of R1 to make sure we're not using the stack - // space without decrementing the stack pointer. - Result = CurDAG->getCopyFromReg(Chain, PPC::R1, MVT::i32); + case PPCISD::FSEL: { + SDOperand Comparison = Select(N->getOperand(0)); + // Extend the comparison to 64-bits. + if (Comparison.getValueType() == MVT::f32) + Comparison = CurDAG->getTargetNode(PPC::FMRSD, MVT::f64, Comparison); - // Finally, replace the DYNAMIC_STACKALLOC with the copyfromreg. - CurDAG->ReplaceAllUsesWith(N, Result.Val); - return SDOperand(Result.Val, Op.ResNo); - } - case ISD::SIGN_EXTEND_INREG: - switch(cast(N->getOperand(1))->getVT()) { - default: assert(0 && "Illegal type in SIGN_EXTEND_INREG"); break; - case MVT::i16: - CurDAG->SelectNodeTo(N, PPC::EXTSH, MVT::i32, Select(N->getOperand(0))); - break; - case MVT::i8: - CurDAG->SelectNodeTo(N, PPC::EXTSB, MVT::i32, Select(N->getOperand(0))); - break; - } - return SDOperand(N, 0); - case ISD::CTLZ: - assert(N->getValueType(0) == MVT::i32); - CurDAG->SelectNodeTo(N, PPC::CNTLZW, MVT::i32, Select(N->getOperand(0))); - return SDOperand(N, 0); - case PPCISD::FSEL: - CurDAG->SelectNodeTo(N, PPC::FSEL, N->getValueType(0), - Select(N->getOperand(0)), - Select(N->getOperand(1)), - Select(N->getOperand(2))); + unsigned Opc = N->getValueType(0) == MVT::f32 ? PPC::FSELS : PPC::FSELD; + CurDAG->SelectNodeTo(N, Opc, N->getValueType(0), Comparison, + Select(N->getOperand(1)), Select(N->getOperand(2))); return SDOperand(N, 0); + } case PPCISD::FCFID: CurDAG->SelectNodeTo(N, PPC::FCFID, N->getValueType(0), Select(N->getOperand(0))); @@ -807,22 +998,10 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { CurDAG->SelectNodeTo(N, PPC::FCTIWZ, N->getValueType(0), Select(N->getOperand(0))); return SDOperand(N, 0); - case ISD::ADD: { + case ISD::FADD: { MVT::ValueType Ty = N->getValueType(0); - if (Ty == MVT::i32) { - if (SDNode *I = SelectIntImmediateExpr(N->getOperand(0), N->getOperand(1), - PPC::ADDIS, PPC::ADDI, true)) { - CurDAG->ReplaceAllUsesWith(Op, SDOperand(I, 0)); - N = I; - } else { - CurDAG->SelectNodeTo(N, PPC::ADD, MVT::i32, Select(N->getOperand(0)), - Select(N->getOperand(1))); - } - return SDOperand(N, 0); - } - if (!NoExcessFPPrecision) { // Match FMA ops - if (N->getOperand(0).getOpcode() == ISD::MUL && + if (N->getOperand(0).getOpcode() == ISD::FMUL && N->getOperand(0).Val->hasOneUse()) { ++FusedFP; // Statistic CurDAG->SelectNodeTo(N, Ty == MVT::f64 ? PPC::FMADD : PPC::FMADDS, Ty, @@ -830,7 +1009,7 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { Select(N->getOperand(0).getOperand(1)), Select(N->getOperand(1))); return SDOperand(N, 0); - } else if (N->getOperand(1).getOpcode() == ISD::MUL && + } else if (N->getOperand(1).getOpcode() == ISD::FMUL && N->getOperand(1).hasOneUse()) { ++FusedFP; // Statistic CurDAG->SelectNodeTo(N, Ty == MVT::f64 ? PPC::FMADD : PPC::FMADDS, Ty, @@ -845,31 +1024,11 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { Select(N->getOperand(0)), Select(N->getOperand(1))); return SDOperand(N, 0); } - case ISD::SUB: { + case ISD::FSUB: { MVT::ValueType Ty = N->getValueType(0); - if (Ty == MVT::i32) { - unsigned Imm; - if (isIntImmediate(N->getOperand(0), Imm) && isInt16(Imm)) { - if (0 == Imm) - CurDAG->SelectNodeTo(N, PPC::NEG, Ty, Select(N->getOperand(1))); - else - CurDAG->SelectNodeTo(N, PPC::SUBFIC, Ty, Select(N->getOperand(1)), - getI32Imm(Lo16(Imm))); - return SDOperand(N, 0); - } - if (SDNode *I = SelectIntImmediateExpr(N->getOperand(0), N->getOperand(1), - PPC::ADDIS, PPC::ADDI, true, true)) { - CurDAG->ReplaceAllUsesWith(Op, SDOperand(I, 0)); - N = I; - } else { - CurDAG->SelectNodeTo(N, PPC::SUBF, Ty, Select(N->getOperand(1)), - Select(N->getOperand(0))); - } - return SDOperand(N, 0); - } if (!NoExcessFPPrecision) { // Match FMA ops - if (N->getOperand(0).getOpcode() == ISD::MUL && + if (N->getOperand(0).getOpcode() == ISD::FMUL && N->getOperand(0).Val->hasOneUse()) { ++FusedFP; // Statistic CurDAG->SelectNodeTo(N, Ty == MVT::f64 ? PPC::FMSUB : PPC::FMSUBS, Ty, @@ -877,7 +1036,7 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { Select(N->getOperand(0).getOperand(1)), Select(N->getOperand(1))); return SDOperand(N, 0); - } else if (N->getOperand(1).getOpcode() == ISD::MUL && + } else if (N->getOperand(1).getOpcode() == ISD::FMUL && N->getOperand(1).Val->hasOneUse()) { ++FusedFP; // Statistic CurDAG->SelectNodeTo(N, Ty == MVT::f64 ? PPC::FNMSUB : PPC::FNMSUBS, Ty, @@ -892,23 +1051,6 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { Select(N->getOperand(1))); return SDOperand(N, 0); } - case ISD::MUL: { - unsigned Imm, Opc; - if (isIntImmediate(N->getOperand(1), Imm) && isInt16(Imm)) { - CurDAG->SelectNodeTo(N, PPC::MULLI, MVT::i32, - Select(N->getOperand(0)), getI32Imm(Lo16(Imm))); - return SDOperand(N, 0); - } - switch (N->getValueType(0)) { - default: assert(0 && "Unhandled multiply type!"); - case MVT::i32: Opc = PPC::MULLW; break; - case MVT::f32: Opc = PPC::FMULS; break; - case MVT::f64: Opc = PPC::FMUL; break; - } - CurDAG->SelectNodeTo(N, Opc, N->getValueType(0), Select(N->getOperand(0)), - Select(N->getOperand(1))); - return SDOperand(N, 0); - } case ISD::SDIV: { unsigned Imm; if (isIntImmediate(N->getOperand(1), Imm)) { @@ -932,23 +1074,13 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { return SDOperand(N, 0); } else if (Imm) { SDOperand Result = Select(BuildSDIVSequence(N)); - assert(Result.ResNo == 0); - CurDAG->ReplaceAllUsesWith(Op, Result); - N = Result.Val; - return SDOperand(N, 0); + CodeGenMap[Op] = Result; + return Result; } } - unsigned Opc; - switch (N->getValueType(0)) { - default: assert(0 && "Unknown type to ISD::SDIV"); - case MVT::i32: Opc = PPC::DIVW; break; - case MVT::f32: Opc = PPC::FDIVS; break; - case MVT::f64: Opc = PPC::FDIV; break; - } - CurDAG->SelectNodeTo(N, Opc, N->getValueType(0), Select(N->getOperand(0)), - Select(N->getOperand(1))); - return SDOperand(N, 0); + // Other cases are autogenerated. + break; } case ISD::UDIV: { // If this is a divide by constant, we can emit code using some magic @@ -956,26 +1088,13 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { unsigned Imm; if (isIntImmediate(N->getOperand(1), Imm) && Imm) { SDOperand Result = Select(BuildUDIVSequence(N)); - assert(Result.ResNo == 0); - CurDAG->ReplaceAllUsesWith(Op, Result); - N = Result.Val; - return SDOperand(N, 0); + CodeGenMap[Op] = Result; + return Result; } - CurDAG->SelectNodeTo(N, PPC::DIVWU, MVT::i32, Select(N->getOperand(0)), - Select(N->getOperand(1))); - return SDOperand(N, 0); + // Other cases are autogenerated. + break; } - case ISD::MULHS: - assert(N->getValueType(0) == MVT::i32); - CurDAG->SelectNodeTo(N, PPC::MULHW, MVT::i32, Select(N->getOperand(0)), - Select(N->getOperand(1))); - return SDOperand(N, 0); - case ISD::MULHU: - assert(N->getValueType(0) == MVT::i32); - CurDAG->SelectNodeTo(N, PPC::MULHWU, MVT::i32, Select(N->getOperand(0)), - Select(N->getOperand(1))); - return SDOperand(N, 0); case ISD::AND: { unsigned Imm; // If this is an and of a value rotated between 0 and 31 bits and then and'd @@ -995,83 +1114,21 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { getI32Imm(MB), getI32Imm(ME)); return SDOperand(N, 0); } - // Finally, check for the case where we are being asked to select - // and (not(a), b) or and (a, not(b)) which can be selected as andc. - if (isOprNot(N->getOperand(0).Val)) - CurDAG->SelectNodeTo(N, PPC::ANDC, MVT::i32, Select(N->getOperand(1)), - Select(N->getOperand(0).getOperand(0))); - else if (isOprNot(N->getOperand(1).Val)) - CurDAG->SelectNodeTo(N, PPC::ANDC, MVT::i32, Select(N->getOperand(0)), - Select(N->getOperand(1).getOperand(0))); - else - CurDAG->SelectNodeTo(N, PPC::AND, MVT::i32, Select(N->getOperand(0)), - Select(N->getOperand(1))); - return SDOperand(N, 0); + + // Other cases are autogenerated. + break; } case ISD::OR: - if (SDNode *I = SelectBitfieldInsert(N)) { - CurDAG->ReplaceAllUsesWith(Op, SDOperand(I, 0)); - N = I; - return SDOperand(N, 0); - } - if (SDNode *I = SelectIntImmediateExpr(N->getOperand(0), - N->getOperand(1), - PPC::ORIS, PPC::ORI)) { - CurDAG->ReplaceAllUsesWith(Op, SDOperand(I, 0)); - N = I; - return SDOperand(N, 0); - } - // Finally, check for the case where we are being asked to select - // 'or (not(a), b)' or 'or (a, not(b))' which can be selected as orc. - if (isOprNot(N->getOperand(0).Val)) - CurDAG->SelectNodeTo(N, PPC::ORC, MVT::i32, Select(N->getOperand(1)), - Select(N->getOperand(0).getOperand(0))); - else if (isOprNot(N->getOperand(1).Val)) - CurDAG->SelectNodeTo(N, PPC::ORC, MVT::i32, Select(N->getOperand(0)), - Select(N->getOperand(1).getOperand(0))); - else - CurDAG->SelectNodeTo(N, PPC::OR, MVT::i32, Select(N->getOperand(0)), - Select(N->getOperand(1))); - return SDOperand(N, 0); - case ISD::XOR: - // Check whether or not this node is a logical 'not'. This is represented - // by llvm as a xor with the constant value -1 (all bits set). If this is a - // 'not', then fold 'or' into 'nor', and so forth for the supported ops. - if (isOprNot(N)) { - unsigned Opc; - SDOperand Val = Select(N->getOperand(0)); - switch (Val.isTargetOpcode() ? Val.getTargetOpcode() : 0) { - default: Opc = 0; break; - case PPC::OR: Opc = PPC::NOR; break; - case PPC::AND: Opc = PPC::NAND; break; - case PPC::XOR: Opc = PPC::EQV; break; - } - if (Opc) - CurDAG->SelectNodeTo(N, Opc, MVT::i32, Val.getOperand(0), - Val.getOperand(1)); - else - CurDAG->SelectNodeTo(N, PPC::NOR, MVT::i32, Val, Val); - return SDOperand(N, 0); - } - // If this is a xor with an immediate other than -1, then codegen it as high - // and low 16 bit immediate xors. + if (SDNode *I = SelectBitfieldInsert(N)) + return CodeGenMap[Op] = SDOperand(I, 0); + if (SDNode *I = SelectIntImmediateExpr(N->getOperand(0), N->getOperand(1), - PPC::XORIS, PPC::XORI)) { - CurDAG->ReplaceAllUsesWith(Op, SDOperand(I, 0)); - N = I; - return SDOperand(N, 0); - } - // Finally, check for the case where we are being asked to select - // xor (not(a), b) which is equivalent to not(xor a, b), which is eqv - if (isOprNot(N->getOperand(0).Val)) - CurDAG->SelectNodeTo(N, PPC::EQV, MVT::i32, - Select(N->getOperand(0).getOperand(0)), - Select(N->getOperand(1))); - else - CurDAG->SelectNodeTo(N, PPC::XOR, MVT::i32, Select(N->getOperand(0)), - Select(N->getOperand(1))); - return SDOperand(N, 0); + PPC::ORIS, PPC::ORI)) + return CodeGenMap[Op] = SDOperand(I, 0); + + // Other cases are autogenerated. + break; case ISD::SHL: { unsigned Imm, SH, MB, ME; if (isOpcWithIntImmediate(N->getOperand(0).Val, ISD::AND, Imm) && @@ -1118,16 +1175,30 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { Select(N->getOperand(1))); return SDOperand(N, 0); } + case ISD::FMUL: { + unsigned Opc = N->getValueType(0) == MVT::f32 ? PPC::FMULS : PPC::FMUL; + CurDAG->SelectNodeTo(N, Opc, N->getValueType(0), Select(N->getOperand(0)), + Select(N->getOperand(1))); + return SDOperand(N, 0); + } + case ISD::FDIV: { + unsigned Opc = N->getValueType(0) == MVT::f32 ? PPC::FDIVS : PPC::FDIV; + CurDAG->SelectNodeTo(N, Opc, N->getValueType(0), Select(N->getOperand(0)), + Select(N->getOperand(1))); + return SDOperand(N, 0); + } case ISD::FABS: - CurDAG->SelectNodeTo(N, PPC::FABS, N->getValueType(0), - Select(N->getOperand(0))); + if (N->getValueType(0) == MVT::f32) + CurDAG->SelectNodeTo(N, PPC::FABSS, MVT::f32, Select(N->getOperand(0))); + else + CurDAG->SelectNodeTo(N, PPC::FABSD, MVT::f64, Select(N->getOperand(0))); return SDOperand(N, 0); case ISD::FP_EXTEND: assert(MVT::f64 == N->getValueType(0) && MVT::f32 == N->getOperand(0).getValueType() && "Illegal FP_EXTEND"); // We need to emit an FMR to make sure that the result has the right value // type. - CurDAG->SelectNodeTo(N, PPC::FMR, MVT::f64, Select(N->getOperand(0))); + CurDAG->SelectNodeTo(N, PPC::FMRSD, MVT::f64, Select(N->getOperand(0))); return SDOperand(N, 0); case ISD::FP_ROUND: assert(MVT::f32 == N->getValueType(0) && @@ -1141,7 +1212,8 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { unsigned Opc; switch (Val.isTargetOpcode() ? Val.getTargetOpcode() : 0) { default: Opc = 0; break; - case PPC::FABS: Opc = PPC::FNABS; break; + case PPC::FABSS: Opc = PPC::FNABSS; break; + case PPC::FABSD: Opc = PPC::FNABSD; break; case PPC::FMADD: Opc = PPC::FNMADD; break; case PPC::FMADDS: Opc = PPC::FNMADDS; break; case PPC::FMSUB: Opc = PPC::FNMSUB; break; @@ -1151,7 +1223,7 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { // inverted opcode and the original instruction's operands. Otherwise, // fall through and generate a fneg instruction. if (Opc) { - if (PPC::FNABS == Opc) + if (Opc == PPC::FNABSS || Opc == PPC::FNABSD) CurDAG->SelectNodeTo(N, Opc, Ty, Val.getOperand(0)); else CurDAG->SelectNodeTo(N, Opc, Ty, Val.getOperand(0), @@ -1159,7 +1231,10 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { return SDOperand(N, 0); } } - CurDAG->SelectNodeTo(N, PPC::FNEG, Ty, Val); + if (Ty == MVT::f32) + CurDAG->SelectNodeTo(N, PPC::FNEGS, MVT::f32, Val); + else + CurDAG->SelectNodeTo(N, PPC::FNEGD, MVT::f64, Val); return SDOperand(N, 0); } case ISD::FSQRT: { @@ -1168,62 +1243,7 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { Select(N->getOperand(0))); return SDOperand(N, 0); } - - case ISD::ADD_PARTS: { - SDOperand LHSL = Select(N->getOperand(0)); - SDOperand LHSH = Select(N->getOperand(1)); - - unsigned Imm; - bool ME = false, ZE = false; - if (isIntImmediate(N->getOperand(3), Imm)) { - ME = (signed)Imm == -1; - ZE = Imm == 0; - } - std::vector Result; - SDOperand CarryFromLo; - if (isIntImmediate(N->getOperand(2), Imm) && - ((signed)Imm >= -32768 || (signed)Imm < 32768)) { - // Codegen the low 32 bits of the add. Interestingly, there is no - // shifted form of add immediate carrying. - CarryFromLo = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, - LHSL, getI32Imm(Imm)); - } else { - CarryFromLo = CurDAG->getTargetNode(PPC::ADDC, MVT::i32, MVT::Flag, - LHSL, Select(N->getOperand(2))); - } - CarryFromLo = CarryFromLo.getValue(1); - - // Codegen the high 32 bits, adding zero, minus one, or the full value - // along with the carry flag produced by addc/addic. - SDOperand ResultHi; - if (ZE) - ResultHi = CurDAG->getTargetNode(PPC::ADDZE, MVT::i32, LHSH, CarryFromLo); - else if (ME) - ResultHi = CurDAG->getTargetNode(PPC::ADDME, MVT::i32, LHSH, CarryFromLo); - else - ResultHi = CurDAG->getTargetNode(PPC::ADDE, MVT::i32, LHSH, - Select(N->getOperand(3)), CarryFromLo); - Result.push_back(CarryFromLo.getValue(0)); - Result.push_back(ResultHi); - CurDAG->ReplaceAllUsesWith(N, Result); - return Result[Op.ResNo]; - } - case ISD::SUB_PARTS: { - SDOperand LHSL = Select(N->getOperand(0)); - SDOperand LHSH = Select(N->getOperand(1)); - SDOperand RHSL = Select(N->getOperand(2)); - SDOperand RHSH = Select(N->getOperand(3)); - - std::vector Result; - Result.push_back(CurDAG->getTargetNode(PPC::SUBFC, MVT::i32, MVT::Flag, - RHSL, LHSL)); - Result.push_back(CurDAG->getTargetNode(PPC::SUBFE, MVT::i32, RHSH, LHSH, - Result[0].getValue(1))); - CurDAG->ReplaceAllUsesWith(N, Result); - return Result[Op.ResNo]; - } - case ISD::LOAD: case ISD::EXTLOAD: case ISD::ZEXTLOAD: @@ -1250,9 +1270,26 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { case MVT::f64: Opc = isIdx ? PPC::LFDX : PPC::LFD; break; } - CurDAG->SelectNodeTo(N, Opc, N->getValueType(0), MVT::Other, - Op1, Op2, Select(N->getOperand(0))); - return SDOperand(N, Op.ResNo); + // If this is an f32 -> f64 load, emit the f32 load, then use an 'extending + // copy'. + if (TypeBeingLoaded != MVT::f32 || N->getOpcode() == ISD::LOAD) { + CurDAG->SelectNodeTo(N, Opc, N->getValueType(0), MVT::Other, + Op1, Op2, Select(N->getOperand(0))); + return SDOperand(N, Op.ResNo); + } else { + std::vector Ops; + Ops.push_back(Op1); + Ops.push_back(Op2); + Ops.push_back(Select(N->getOperand(0))); + SDOperand Res = CurDAG->getTargetNode(Opc, MVT::f32, MVT::Other, Ops); + SDOperand Ext = CurDAG->getTargetNode(PPC::FMRSD, MVT::f64, Res); + CodeGenMap[Op.getValue(0)] = Ext; + CodeGenMap[Op.getValue(1)] = Res.getValue(1); + if (Op.ResNo) + return Res.getValue(1); + else + return Ext; + } } case ISD::TRUNCSTORE: @@ -1271,7 +1308,6 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { } else { //ISD::TRUNCSTORE switch(cast(N->getOperand(4))->getVT()) { default: assert(0 && "unknown Type in store"); - case MVT::i1: case MVT::i8: Opc = isIdx ? PPC::STBX : PPC::STB; break; case MVT::i16: Opc = isIdx ? PPC::STHX : PPC::STH; break; } @@ -1282,113 +1318,6 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { return SDOperand(N, 0); } - case ISD::SETCC: { - unsigned Imm; - ISD::CondCode CC = cast(N->getOperand(2))->get(); - if (isIntImmediate(N->getOperand(1), Imm)) { - // We can codegen setcc op, imm very efficiently compared to a brcond. - // Check for those cases here. - // setcc op, 0 - if (Imm == 0) { - SDOperand Op = Select(N->getOperand(0)); - switch (CC) { - default: assert(0 && "Unhandled SetCC condition"); abort(); - case ISD::SETEQ: - Op = CurDAG->getTargetNode(PPC::CNTLZW, MVT::i32, Op); - CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Op, getI32Imm(27), - getI32Imm(5), getI32Imm(31)); - break; - case ISD::SETNE: { - SDOperand AD = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, - Op, getI32Imm(~0U)); - CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, AD, Op, AD.getValue(1)); - break; - } - case ISD::SETLT: - CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Op, getI32Imm(1), - getI32Imm(31), getI32Imm(31)); - break; - case ISD::SETGT: { - SDOperand T = CurDAG->getTargetNode(PPC::NEG, MVT::i32, Op); - T = CurDAG->getTargetNode(PPC::ANDC, MVT::i32, T, Op);; - CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, T, getI32Imm(1), - getI32Imm(31), getI32Imm(31)); - break; - } - } - return SDOperand(N, 0); - } else if (Imm == ~0U) { // setcc op, -1 - SDOperand Op = Select(N->getOperand(0)); - switch (CC) { - default: assert(0 && "Unhandled SetCC condition"); abort(); - case ISD::SETEQ: - Op = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, - Op, getI32Imm(1)); - CurDAG->SelectNodeTo(N, PPC::ADDZE, MVT::i32, - CurDAG->getTargetNode(PPC::LI, MVT::i32, - getI32Imm(0)), - Op.getValue(1)); - break; - case ISD::SETNE: { - Op = CurDAG->getTargetNode(PPC::NOR, MVT::i32, Op, Op); - SDOperand AD = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, - Op, getI32Imm(~0U)); - CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, AD, Op, AD.getValue(1)); - break; - } - case ISD::SETLT: { - SDOperand AD = CurDAG->getTargetNode(PPC::ADDI, MVT::i32, Op, - getI32Imm(1)); - SDOperand AN = CurDAG->getTargetNode(PPC::AND, MVT::i32, AD, Op); - CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, AN, getI32Imm(1), - getI32Imm(31), getI32Imm(31)); - break; - } - case ISD::SETGT: - Op = CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, Op, getI32Imm(1), - getI32Imm(31), getI32Imm(31)); - CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Op, getI32Imm(1)); - break; - } - return SDOperand(N, 0); - } - } - - bool Inv; - unsigned Idx = getCRIdxForSetCC(CC, Inv); - SDOperand CCReg = SelectCC(N->getOperand(0), N->getOperand(1), CC); - SDOperand IntCR; - - // Force the ccreg into CR7. - SDOperand CR7Reg = CurDAG->getRegister(PPC::CR7, MVT::i32); - - std::vector VTs; - VTs.push_back(MVT::Other); - VTs.push_back(MVT::Flag); // NONSTANDARD CopyToReg node: defines a flag - std::vector Ops; - Ops.push_back(CurDAG->getEntryNode()); - Ops.push_back(CR7Reg); - Ops.push_back(CCReg); - CCReg = CurDAG->getNode(ISD::CopyToReg, VTs, Ops).getValue(1); - - if (TLI.getTargetMachine().getSubtarget().isGigaProcessor()) - IntCR = CurDAG->getTargetNode(PPC::MFOCRF, MVT::i32, CR7Reg, CCReg); - else - IntCR = CurDAG->getTargetNode(PPC::MFCR, MVT::i32, CCReg); - - if (!Inv) { - CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, IntCR, - getI32Imm(32-(3-Idx)), getI32Imm(31), getI32Imm(31)); - } else { - SDOperand Tmp = - CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, IntCR, - getI32Imm(32-(3-Idx)), getI32Imm(31),getI32Imm(31)); - CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Tmp, getI32Imm(1)); - } - - return SDOperand(N, 0); - } - case ISD::SELECT_CC: { ISD::CondCode CC = cast(N->getOperand(4))->get(); @@ -1411,7 +1340,13 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { unsigned BROpc = getBCCForSetCC(CC); bool isFP = MVT::isFloatingPoint(N->getValueType(0)); - unsigned SelectCCOp = isFP ? PPC::SELECT_CC_FP : PPC::SELECT_CC_Int; + unsigned SelectCCOp; + if (MVT::isInteger(N->getValueType(0))) + SelectCCOp = PPC::SELECT_CC_Int; + else if (N->getValueType(0) == MVT::f32) + SelectCCOp = PPC::SELECT_CC_F4; + else + SelectCCOp = PPC::SELECT_CC_F8; CurDAG->SelectNodeTo(N, SelectCCOp, N->getValueType(0), CCReg, Select(N->getOperand(2)), Select(N->getOperand(3)), getI32Imm(BROpc)); @@ -1512,7 +1447,7 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { Chain.getValue(1)).getValue(1); CallResults.push_back(Chain.getValue(0)); Chain = CurDAG->getCopyFromReg(Chain, PPC::R3, MVT::i32, - Chain.getValue(1)).getValue(1); + Chain.getValue(2)).getValue(1); CallResults.push_back(Chain.getValue(0)); } else { Chain = CurDAG->getCopyFromReg(Chain, PPC::R3, MVT::i32, @@ -1529,7 +1464,8 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { } CallResults.push_back(Chain); - CurDAG->ReplaceAllUsesWith(N, CallResults); + for (unsigned i = 0, e = CallResults.size(); i != e; ++i) + CodeGenMap[Op.getValue(i)] = CallResults[i]; return CallResults[Op.ResNo]; } case ISD::RET: { @@ -1566,20 +1502,31 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { cast(N->getOperand(4))->getBasicBlock(); ISD::CondCode CC = cast(N->getOperand(1))->get(); SDOperand CondCode = SelectCC(N->getOperand(2), N->getOperand(3), CC); - unsigned Opc = getBCCForSetCC(CC); // If this is a two way branch, then grab the fallthrough basic block // argument and build a PowerPC branch pseudo-op, suitable for long branch // conversion if necessary by the branch selection pass. Otherwise, emit a // standard conditional branch. if (N->getOpcode() == ISD::BRTWOWAY_CC) { - MachineBasicBlock *Fallthrough = - cast(N->getOperand(5))->getBasicBlock(); + SDOperand CondTrueBlock = N->getOperand(4); + SDOperand CondFalseBlock = N->getOperand(5); + + // If the false case is the current basic block, then this is a self loop. + // We do not want to emit "Loop: ... brcond Out; br Loop", as it adds an + // extra dispatch group to the loop. Instead, invert the condition and + // emit "Loop: ... br!cond Loop; br Out + if (cast(CondFalseBlock)->getBasicBlock() == BB) { + std::swap(CondTrueBlock, CondFalseBlock); + CC = getSetCCInverse(CC, + MVT::isInteger(N->getOperand(2).getValueType())); + } + + unsigned Opc = getBCCForSetCC(CC); SDOperand CB = CurDAG->getTargetNode(PPC::COND_BRANCH, MVT::Other, CondCode, getI32Imm(Opc), - N->getOperand(4), N->getOperand(5), + CondTrueBlock, CondFalseBlock, Chain); - CurDAG->SelectNodeTo(N, PPC::B, MVT::Other, N->getOperand(5), CB); + CurDAG->SelectNodeTo(N, PPC::B, MVT::Other, CondFalseBlock, CB); } else { // Iterate to the next basic block ilist::iterator It = BB; @@ -1591,16 +1538,14 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { // the PowerPC Branch Selection pass to crash. if (It == BB->getParent()->end()) It = Dest; CurDAG->SelectNodeTo(N, PPC::COND_BRANCH, MVT::Other, CondCode, - getI32Imm(Opc), N->getOperand(4), + getI32Imm(getBCCForSetCC(CC)), N->getOperand(4), CurDAG->getBasicBlock(It), Chain); } return SDOperand(N, 0); } } - assert(0 && "Unreachable!"); - abort(); - return SDOperand(N, Op.ResNo); + return SelectCode(Op); }