Implement selection for branches.

llvm-svn: 22951
This commit is contained in:
Chris Lattner 2005-08-21 18:50:37 +00:00
parent 46059044c6
commit 2a1823d178
1 changed files with 83 additions and 0 deletions

View File

@ -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<BasicBlockSDNode>(N->getOperand(4))->getBasicBlock();
ISD::CondCode CC = cast<CondCodeSDNode>(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<BasicBlockSDNode>(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<MachineBasicBlock>::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);
}