From 2fbb4579d6d6bbde8387283b78307c2ea477a312 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 21 Aug 2005 18:50:37 +0000 Subject: [PATCH] Implement selection for branches. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22951 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 83 ++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 03028822d8e..449297a80a3 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -69,6 +69,10 @@ namespace { bool Negate = false); SDNode *SelectBitfieldInsert(SDNode *N); + /// SelectCC - Select a comparison of the specified values with the + /// specified condition code, returning the CR# of the expression. + SDOperand SelectCC(SDOperand LHS, SDOperand RHS, ISD::CondCode CC); + /// InstructionSelectBasicBlock - This callback is invoked by /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) { @@ -353,6 +357,47 @@ SDNode *PPC32DAGToDAGISel::SelectIntImmediateExpr(SDOperand LHS, SDOperand RHS, } +/// SelectCC - Select a comparison of the specified values with the specified +/// condition code, returning the CR# of the expression. +SDOperand PPC32DAGToDAGISel::SelectCC(SDOperand LHS, SDOperand RHS, + ISD::CondCode CC) { + // Always select the LHS. + LHS = Select(LHS); + + // Use U to determine whether the SETCC immediate range is signed or not. + if (MVT::isInteger(LHS.getValueType())) { + bool U = ISD::isUnsignedIntSetCC(CC); + unsigned Imm; + if (isIntImmediate(RHS, Imm) && + ((U && isUInt16(Imm)) || (!U && isInt16(Imm)))) + return CurDAG->getTargetNode(U ? PPC::CMPLWI : PPC::CMPWI, MVT::i32, + LHS, getI32Imm(Lo16(Imm))); + return CurDAG->getTargetNode(U ? PPC::CMPLW : PPC::CMPW, MVT::i32, + LHS, Select(RHS)); + } else { + return CurDAG->getTargetNode(PPC::FCMPU, MVT::i32, LHS, Select(RHS)); + } +} + +/// getBCCForSetCC - Returns the PowerPC condition branch mnemonic corresponding +/// to Condition. +static unsigned getBCCForSetCC(ISD::CondCode CC) { + switch (CC) { + default: assert(0 && "Unknown condition!"); abort(); + case ISD::SETEQ: return PPC::BEQ; + case ISD::SETNE: return PPC::BNE; + case ISD::SETULT: + case ISD::SETLT: return PPC::BLT; + case ISD::SETULE: + case ISD::SETLE: return PPC::BLE; + case ISD::SETUGT: + case ISD::SETGT: return PPC::BGT; + case ISD::SETUGE: + case ISD::SETGE: return PPC::BGE; + } + return 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) { @@ -790,6 +835,44 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { CurDAG->SelectNodeTo(N, MVT::Other, PPC::BLR, Chain); break; } + + case ISD::BR_CC: + case ISD::BRTWOWAY_CC: { + SDOperand Chain = Select(N->getOperand(0)); + MachineBasicBlock *Dest = + 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 CB = CurDAG->getTargetNode(PPC::COND_BRANCH, MVT::Other, + CondCode, getI32Imm(Opc), + N->getOperand(4), N->getOperand(5), + Chain); + CurDAG->SelectNodeTo(N, MVT::Other, PPC::B, N->getOperand(5), CB); + } else { + // Iterate to the next basic block + ilist::iterator It = BB; + ++It; + + // If the fallthrough path is off the end of the function, which would be + // undefined behavior, set it to be the same as the current block because + // we have nothing better to set it to, and leaving it alone will cause + // the PowerPC Branch Selection pass to crash. + if (It == BB->getParent()->end()) It = Dest; + CurDAG->SelectNodeTo(N, MVT::Other, PPC::COND_BRANCH, CondCode, + getI32Imm(Opc), N->getOperand(4), + CurDAG->getBasicBlock(It), Chain); + } + break; + } } return SDOperand(N, 0); }