Remove BRTWOWAY*

Make the PPC backend not dependent on BRTWOWAY_CC and make the branch
selector smarter about the code it generates, fixing a case in the
readme.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26814 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nate Begeman 2006-03-17 01:40:33 +00:00
parent e261c474ca
commit 81e8097377
15 changed files with 21 additions and 283 deletions

View File

@ -302,25 +302,12 @@ namespace ISD {
// to if the condition is true.
BRCOND,
// BRCONDTWOWAY - Two-way conditional branch. The first operand is the
// chain, the second is the condition, the third is the block to branch to
// if true, and the forth is the block to branch to if false. Targets
// usually do not implement this, preferring to have legalize demote the
// operation to BRCOND/BR pairs when necessary.
BRCONDTWOWAY,
// BR_CC - Conditional branch. The behavior is like that of SELECT_CC, in
// that the condition is represented as condition code, and two nodes to
// compare, rather than as a combined SetCC node. The operands in order are
// chain, cc, lhs, rhs, block to branch to if condition is true.
BR_CC,
// BRTWOWAY_CC - Two-way conditional branch. The operands in order are
// chain, cc, lhs, rhs, block to branch to if condition is true, block to
// branch to if condition is false. Targets usually do not implement this,
// preferring to have legalize demote the operation to BRCOND/BR pairs.
BRTWOWAY_CC,
// RET - Return from function. The first operand is the chain,
// and any subsequent operands are the return values for the
// function. This operation can have variable number of operands.

View File

@ -206,9 +206,7 @@ namespace {
SDOperand visitFNEG(SDNode *N);
SDOperand visitFABS(SDNode *N);
SDOperand visitBRCOND(SDNode *N);
SDOperand visitBRCONDTWOWAY(SDNode *N);
SDOperand visitBR_CC(SDNode *N);
SDOperand visitBRTWOWAY_CC(SDNode *N);
SDOperand visitLOAD(SDNode *N);
SDOperand visitSTORE(SDNode *N);
@ -639,9 +637,7 @@ SDOperand DAGCombiner::visit(SDNode *N) {
case ISD::FNEG: return visitFNEG(N);
case ISD::FABS: return visitFABS(N);
case ISD::BRCOND: return visitBRCOND(N);
case ISD::BRCONDTWOWAY: return visitBRCONDTWOWAY(N);
case ISD::BR_CC: return visitBR_CC(N);
case ISD::BRTWOWAY_CC: return visitBRTWOWAY_CC(N);
case ISD::LOAD: return visitLOAD(N);
case ISD::STORE: return visitSTORE(N);
}
@ -2219,35 +2215,6 @@ SDOperand DAGCombiner::visitBRCOND(SDNode *N) {
return SDOperand();
}
SDOperand DAGCombiner::visitBRCONDTWOWAY(SDNode *N) {
SDOperand Chain = N->getOperand(0);
SDOperand N1 = N->getOperand(1);
SDOperand N2 = N->getOperand(2);
SDOperand N3 = N->getOperand(3);
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
// unconditional branch to true mbb
if (N1C && N1C->getValue() == 1)
return DAG.getNode(ISD::BR, MVT::Other, Chain, N2);
// unconditional branch to false mbb
if (N1C && N1C->isNullValue())
return DAG.getNode(ISD::BR, MVT::Other, Chain, N3);
// fold a brcondtwoway with a setcc condition into a BRTWOWAY_CC node if
// BRTWOWAY_CC is legal on the target.
if (N1.getOpcode() == ISD::SETCC &&
TLI.isOperationLegal(ISD::BRTWOWAY_CC, MVT::Other)) {
std::vector<SDOperand> Ops;
Ops.push_back(Chain);
Ops.push_back(N1.getOperand(2));
Ops.push_back(N1.getOperand(0));
Ops.push_back(N1.getOperand(1));
Ops.push_back(N2);
Ops.push_back(N3);
return DAG.getNode(ISD::BRTWOWAY_CC, MVT::Other, Ops);
}
return SDOperand();
}
// Operand List for BR_CC: Chain, CondCC, CondLHS, CondRHS, DestBB.
//
SDOperand DAGCombiner::visitBR_CC(SDNode *N) {
@ -2273,41 +2240,6 @@ SDOperand DAGCombiner::visitBR_CC(SDNode *N) {
return SDOperand();
}
SDOperand DAGCombiner::visitBRTWOWAY_CC(SDNode *N) {
SDOperand Chain = N->getOperand(0);
SDOperand CCN = N->getOperand(1);
SDOperand LHS = N->getOperand(2);
SDOperand RHS = N->getOperand(3);
SDOperand N4 = N->getOperand(4);
SDOperand N5 = N->getOperand(5);
SDOperand SCC = SimplifySetCC(TLI.getSetCCResultTy(), LHS, RHS,
cast<CondCodeSDNode>(CCN)->get(), false);
ConstantSDNode *SCCC = dyn_cast_or_null<ConstantSDNode>(SCC.Val);
// fold select_cc lhs, rhs, x, x, cc -> x
if (N4 == N5)
return DAG.getNode(ISD::BR, MVT::Other, Chain, N4);
// fold select_cc true, x, y -> x
if (SCCC && SCCC->getValue())
return DAG.getNode(ISD::BR, MVT::Other, Chain, N4);
// fold select_cc false, x, y -> y
if (SCCC && SCCC->isNullValue())
return DAG.getNode(ISD::BR, MVT::Other, Chain, N5);
// fold to a simpler setcc
if (SCC.Val && SCC.getOpcode() == ISD::SETCC) {
std::vector<SDOperand> Ops;
Ops.push_back(Chain);
Ops.push_back(SCC.getOperand(2));
Ops.push_back(SCC.getOperand(0));
Ops.push_back(SCC.getOperand(1));
Ops.push_back(N4);
Ops.push_back(N5);
return DAG.getNode(ISD::BRTWOWAY_CC, MVT::Other, Ops);
}
return SDOperand();
}
SDOperand DAGCombiner::visitLOAD(SDNode *N) {
SDOperand Chain = N->getOperand(0);
SDOperand Ptr = N->getOperand(1);

View File

@ -945,100 +945,6 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
break;
}
break;
case ISD::BRCONDTWOWAY:
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
switch (getTypeAction(Node->getOperand(1).getValueType())) {
case Expand: assert(0 && "It's impossible to expand bools");
case Legal:
Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the condition.
break;
case Promote:
Tmp2 = PromoteOp(Node->getOperand(1)); // Promote the condition.
break;
}
// If this target does not support BRCONDTWOWAY, lower it to a BRCOND/BR
// pair.
switch (TLI.getOperationAction(ISD::BRCONDTWOWAY, MVT::Other)) {
case TargetLowering::Promote:
default: assert(0 && "This action is not supported yet!");
case TargetLowering::Legal:
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Node->getOperand(2),
Node->getOperand(3));
break;
case TargetLowering::Expand:
// If BRTWOWAY_CC is legal for this target, then simply expand this node
// to that. Otherwise, skip BRTWOWAY_CC and expand directly to a
// BRCOND/BR pair.
if (TLI.isOperationLegal(ISD::BRTWOWAY_CC, MVT::Other)) {
if (Tmp2.getOpcode() == ISD::SETCC) {
Tmp3 = Tmp2.getOperand(0);
Tmp4 = Tmp2.getOperand(1);
Tmp2 = Tmp2.getOperand(2);
} else {
Tmp3 = Tmp2;
Tmp4 = DAG.getConstant(0, Tmp2.getValueType());
Tmp2 = DAG.getCondCode(ISD::SETNE);
}
std::vector<SDOperand> Ops;
Ops.push_back(Tmp1);
Ops.push_back(Tmp2);
Ops.push_back(Tmp3);
Ops.push_back(Tmp4);
Ops.push_back(Node->getOperand(2));
Ops.push_back(Node->getOperand(3));
Result = DAG.getNode(ISD::BRTWOWAY_CC, MVT::Other, Ops);
} else {
Result = DAG.getNode(ISD::BRCOND, MVT::Other, Tmp1, Tmp2,
Node->getOperand(2));
Result = DAG.getNode(ISD::BR, MVT::Other, Result, Node->getOperand(3));
}
break;
}
break;
case ISD::BRTWOWAY_CC: {
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
// Ensure that libcalls are emitted before a branch.
Tmp1 = DAG.getNode(ISD::TokenFactor, MVT::Other, Tmp1, LastCALLSEQ_END);
Tmp1 = LegalizeOp(Tmp1);
LastCALLSEQ_END = DAG.getEntryNode();
Tmp2 = Node->getOperand(2); // LHS
Tmp3 = Node->getOperand(3); // RHS
Tmp4 = Node->getOperand(1); // CC
LegalizeSetCCOperands(Tmp2, Tmp3, Tmp4);
// If we didn't get both a LHS and RHS back from LegalizeSetCCOperands,
// the LHS is a legal SETCC itself. In this case, we need to compare
// the result against zero to select between true and false values.
if (Tmp3.Val == 0) {
Tmp3 = DAG.getConstant(0, Tmp2.getValueType());
Tmp4 = DAG.getCondCode(ISD::SETNE);
}
std::vector<SDOperand> Ops;
Ops.push_back(Tmp1);
Ops.push_back(Tmp4);
Ops.push_back(Tmp2);
Ops.push_back(Tmp3);
Ops.push_back(Node->getOperand(4));
Ops.push_back(Node->getOperand(5));
Result = DAG.UpdateNodeOperands(Result, Ops);
// Everything is legal, see if we should expand this op or something.
switch (TLI.getOperationAction(ISD::BRTWOWAY_CC, MVT::Other)) {
default: assert(0 && "This action is not supported yet!");
case TargetLowering::Legal: break;
case TargetLowering::Expand:
Result = DAG.getNode(ISD::BRCOND, MVT::Other, Tmp1,
DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), Tmp2,
Tmp3, Tmp4),
Result.getOperand(4));
Result = DAG.getNode(ISD::BR, MVT::Other, Result, Result.getOperand(5));
break;
}
break;
}
case ISD::LOAD: {
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the pointer.

View File

@ -1486,18 +1486,6 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(Ops[1].Val);
switch (Opcode) {
default: break;
case ISD::BRCONDTWOWAY:
if (N1C)
if (N1C->getValue()) // Unconditional branch to true dest.
return getNode(ISD::BR, MVT::Other, Ops[0], Ops[2]);
else // Unconditional branch to false dest.
return getNode(ISD::BR, MVT::Other, Ops[0], Ops[3]);
break;
case ISD::BRTWOWAY_CC:
assert(Ops.size() == 6 && "BRTWOWAY_CC takes 6 operands!");
assert(Ops[2].getValueType() == Ops[3].getValueType() &&
"LHS and RHS of comparison must have same type!");
break;
case ISD::TRUNCSTORE: {
assert(Ops.size() == 5 && "TRUNCSTORE takes 5 operands!");
MVT::ValueType EVT = cast<VTSDNode>(Ops[4])->getVT();
@ -2692,9 +2680,7 @@ const char *SDNode::getOperationName(const SelectionDAG *G) const {
// Control flow instructions
case ISD::BR: return "br";
case ISD::BRCOND: return "brcond";
case ISD::BRCONDTWOWAY: return "brcondtwoway";
case ISD::BR_CC: return "br_cc";
case ISD::BRTWOWAY_CC: return "brtwoway_cc";
case ISD::BR_CC: return "br_cc";
case ISD::RET: return "ret";
case ISD::CALLSEQ_START: return "callseq_start";
case ISD::CALLSEQ_END: return "callseq_end";

View File

@ -691,10 +691,10 @@ void SelectionDAGLowering::visitBr(BranchInst &I) {
SDOperand True = DAG.getConstant(1, Cond.getValueType());
Cond = DAG.getNode(ISD::XOR, Cond.getValueType(), Cond, True);
}
Ops.push_back(Cond);
Ops.push_back(DAG.getBasicBlock(Succ0MBB));
Ops.push_back(DAG.getBasicBlock(Succ1MBB));
DAG.setRoot(DAG.getNode(ISD::BRCONDTWOWAY, MVT::Other, Ops));
SDOperand True = DAG.getNode(ISD::BRCOND, MVT::Other, getRoot(), Cond,
DAG.getBasicBlock(Succ0MBB));
DAG.setRoot(DAG.getNode(ISD::BR, MVT::Other, True,
DAG.getBasicBlock(Succ1MBB)));
}
}
}

View File

@ -48,8 +48,6 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM)
addRegisterClass(MVT::f64, Alpha::F8RCRegisterClass);
addRegisterClass(MVT::f32, Alpha::F4RCRegisterClass);
setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);
setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand);
setOperationAction(ISD::BR_CC, MVT::Other, Expand);
setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);

View File

@ -36,8 +36,6 @@ IA64TargetLowering::IA64TargetLowering(TargetMachine &TM)
addRegisterClass(MVT::i1, IA64::PRRegisterClass);
setOperationAction(ISD::BR_CC , MVT::Other, Expand);
setOperationAction(ISD::BRCONDTWOWAY , MVT::Other, Expand);
setOperationAction(ISD::BRTWOWAY_CC , MVT::Other, Expand);
setOperationAction(ISD::FP_ROUND_INREG , MVT::f32 , Expand);
// ia64 uses SELECT not SELECT_CC

View File

@ -48,10 +48,10 @@ FunctionPass *llvm::createPPCBranchSelectionPass() {
static unsigned getNumBytesForInstruction(MachineInstr *MI) {
switch (MI->getOpcode()) {
case PPC::COND_BRANCH:
// while this will be 4 most of the time, if we emit 12 it is just a
// while this will be 4 most of the time, if we emit 8 it is just a
// minor pessimization that saves us from having to worry about
// keeping the offsets up to date later when we emit long branch glue.
return 12;
return 8;
case PPC::IMPLICIT_DEF_GPR: // no asm emitted
case PPC::IMPLICIT_DEF_F4: // no asm emitted
case PPC::IMPLICIT_DEF_F8: // no asm emitted
@ -102,7 +102,6 @@ bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
// long branch:
// bInverseCC $PC+8
// b .L_TARGET_MBB
// b .L_FALLTHROUGH_MBB
for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
++MFI) {
MachineBasicBlock *MBB = MFI;
@ -123,8 +122,6 @@ bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
// 3. fallthrough MBB
MachineBasicBlock *trueMBB =
MBBI->getOperand(2).getMachineBasicBlock();
MachineBasicBlock *falseMBB =
MBBI->getOperand(3).getMachineBasicBlock();
int Displacement = OffsetMap[trueMBB] - ByteCount;
unsigned Opcode = MBBI->getOperand(1).getImmedValue();
@ -136,7 +133,6 @@ bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
} else {
BuildMI(*MBB, MBBJ, Inverted, 2).addReg(CRReg).addSImm(8);
BuildMI(*MBB, MBBJ, PPC::B, 1).addMBB(trueMBB);
BuildMI(*MBB, MBBJ, PPC::B, 1).addMBB(falseMBB);
}
// Erase the psuedo COND_BRANCH instruction, and then back up the

View File

@ -1105,44 +1105,14 @@ void PPCDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) {
N2, N3, getI32Imm(BROpc));
return;
}
case ISD::BR_CC:
case ISD::BRTWOWAY_CC: {
case ISD::BR_CC: {
SDOperand Chain;
Select(Chain, 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);
// 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) {
SDOperand CondTrueBlock = N->getOperand(4);
SDOperand CondFalseBlock = N->getOperand(5);
unsigned Opc = getBCCForSetCC(CC);
SDOperand CB =
SDOperand(CurDAG->getTargetNode(PPC::COND_BRANCH, MVT::Other,
CondCode, getI32Imm(Opc),
CondTrueBlock, CondFalseBlock,
Chain), 0);
Result = CurDAG->SelectNodeTo(N, PPC::B, MVT::Other, CondFalseBlock, 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;
Result = CurDAG->SelectNodeTo(N, PPC::COND_BRANCH, MVT::Other, CondCode,
getI32Imm(getBCCForSetCC(CC)),
N->getOperand(4), CurDAG->getBasicBlock(It),
Chain);
}
Result = CurDAG->SelectNodeTo(N, PPC::COND_BRANCH, MVT::Other,
CondCode, getI32Imm(getBCCForSetCC(CC)),
N->getOperand(4), Chain);
return;
}
}

View File

@ -94,9 +94,8 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM)
// PowerPC wants to optimize integer setcc a bit
setOperationAction(ISD::SETCC, MVT::i32, Custom);
// PowerPC does not have BRCOND* which requires SetCC
setOperationAction(ISD::BRCOND, MVT::Other, Expand);
setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);
// PowerPC does not have BRCOND which requires SetCC
setOperationAction(ISD::BRCOND, MVT::Other, Expand);
// PowerPC turns FP_TO_SINT into FCTIWZ and some load/stores.
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);

View File

@ -245,8 +245,7 @@ let Defs = [LR] in
let isBranch = 1, isTerminator = 1, hasCtrlDep = 1,
noResults = 1, PPC970_Unit = 7 in {
def COND_BRANCH : Pseudo<(ops CRRC:$crS, u16imm:$opc,
target:$true, target:$false),
def COND_BRANCH : Pseudo<(ops CRRC:$crS, u16imm:$opc, target:$true),
"; COND_BRANCH", []>;
def B : IForm<18, 0, 0, (ops target:$dst),
"b $dst", BrB,

View File

@ -10,41 +10,8 @@ still a codesize win.
===-------------------------------------------------------------------------===
Should hint to the branch select pass that it doesn't need to print the second
unconditional branch, so we don't end up with things like:
b .LBBl42__2E_expand_function_8_674 ; loopentry.24
b .LBBl42__2E_expand_function_8_42 ; NewDefault
b .LBBl42__2E_expand_function_8_42 ; NewDefault
This occurs in SPASS.
The power of diet coke came up with a solution to this today:
We know the only two cases that can happen here are either:
a) we have a conditional branch followed by a fallthrough to the next BB
b) we have a conditional branch followed by an unconditional branch
We also invented the BRTWOWAY node to model (b).
Currently, these are modeled by the PPC_BRCOND node which is a 12-byte pseudo
that codegens to
bccinv false
true:
b truebb
false:
b falsebb
However, realizing that for (a), we can bccinv directly to the fallthrough
block, and for (b) we will already have another unconditional branch after
the conditional branch (see SPASS case above), then we know that we don't need
BRTWOWAY at all, and can just codegen PPC_BRCOND as
bccinv +8
b truebb
This will also allow us to selectively not run the ppc branch selector, by just
selecting PPC_BRCOND pseudo directly to the correct conditional branch
instruction for small functions.
Teach the .td file to pattern match PPC::BR_COND to appropriate bc variant, so
we don't have to always run the branch selector for small functions.
===-------------------------------------------------------------------------===

View File

@ -17,7 +17,11 @@ We currently compile this into a memcpy from a static array into 'm', then
a bunch of loads from m. It would be better to avoid the memcpy and just do
loads from the static array.
===-------------------------------------------------------------------------===
//===---------------------------------------------------------------------===//
Make the PPC branch selector target independant
//===---------------------------------------------------------------------===//
Get the C front-end to expand hypot(x,y) -> llvm.sqrt(x*x+y*y) when errno and
precision don't matter (ffastmath). Misc/mandel will like this. :)

View File

@ -166,8 +166,6 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
// Sparc doesn't have BRCOND either, it has BR_CC.
setOperationAction(ISD::BRCOND, MVT::Other, Expand);
setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);
setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand);
setOperationAction(ISD::BR_CC, MVT::i32, Custom);
setOperationAction(ISD::BR_CC, MVT::f32, Custom);
setOperationAction(ISD::BR_CC, MVT::f64, Custom);

View File

@ -125,8 +125,6 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
setOperationAction(ISD::BIT_CONVERT , MVT::i32 , Expand);
setOperationAction(ISD::BRCOND , MVT::Other, Custom);
setOperationAction(ISD::BRCONDTWOWAY , MVT::Other, Expand);
setOperationAction(ISD::BRTWOWAY_CC , MVT::Other, Expand);
setOperationAction(ISD::BR_CC , MVT::Other, Expand);
setOperationAction(ISD::SELECT_CC , MVT::Other, Expand);
setOperationAction(ISD::MEMMOVE , MVT::Other, Expand);