From 7cbd525ba85ebe440d15fa359ec940e404d14906 Mon Sep 17 00:00:00 2001 From: Nate Begeman Date: Tue, 16 Aug 2005 19:49:35 +0000 Subject: [PATCH] Implement BR_CC and BRTWOWAY_CC. This allows the removal of a rather nasty fixme from the PowerPC backend. Emit slightly better code for legalizing select_cc. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22805 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/SelectionDAG.h | 15 +++ include/llvm/CodeGen/SelectionDAGNodes.h | 12 ++ lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 143 ++++++++++++++++++++-- lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 8 +- lib/Target/Alpha/AlphaISelPattern.cpp | 1 + lib/Target/IA64/IA64ISelPattern.cpp | 1 + lib/Target/PowerPC/PPCISelLowering.cpp | 4 + lib/Target/PowerPC/PPCISelPattern.cpp | 25 ++-- lib/Target/Sparc/SparcV8ISelPattern.cpp | 1 + lib/Target/SparcV8/SparcV8ISelPattern.cpp | 1 + lib/Target/X86/X86ISelPattern.cpp | 1 + 11 files changed, 182 insertions(+), 30 deletions(-) diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index b05ae25e299..8ec9bcd2ed0 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -193,6 +193,21 @@ public: return getNode(ISD::SELECT_CC, VT, LHS, RHS, True, False,getCondCode(Cond)); } + /// getBR2Way_CC - Helper function to make it easier to build BRTWOWAY_CC + /// nodes. + /// + SDOperand getBR2Way_CC(SDOperand Chain, SDOperand CCNode, SDOperand LHS, + SDOperand RHS, SDOperand True, SDOperand False) { + std::vector Ops; + Ops.push_back(Chain); + Ops.push_back(CCNode); + Ops.push_back(LHS); + Ops.push_back(RHS); + Ops.push_back(True); + Ops.push_back(False); + return getNode(ISD::BRTWOWAY_CC, MVT::Other, Ops); + } + /// getLoad - Loads are not normal binary operators: their result type is not /// determined by their operands, and they produce a value AND a token chain. /// diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index ea193eeb259..d1c1a344397 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -233,6 +233,18 @@ namespace ISD { // 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. diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 63e7435074c..38e0d424ede 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -594,7 +594,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { case ISD::BRCOND: 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: @@ -604,10 +604,63 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { Tmp2 = PromoteOp(Node->getOperand(1)); // Promote the condition. break; } - // Basic block destination (Op#2) is always legal. - if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(1)) - Result = DAG.getNode(ISD::BRCOND, MVT::Other, Tmp1, Tmp2, - Node->getOperand(2)); + + switch (TLI.getOperationAction(ISD::BRCOND, MVT::Other)) { + default: assert(0 && "This action is not supported yet!"); + case TargetLowering::Expand: + // Expand brcond's setcc into its constituent parts and create a BR_CC + // Node. + if (Tmp2.getOpcode() == ISD::SETCC) { + Result = DAG.getNode(ISD::BR_CC, MVT::Other, Tmp1, Tmp2.getOperand(2), + Tmp2.getOperand(0), Tmp2.getOperand(1), + Node->getOperand(2)); + } else { + Result = DAG.getNode(ISD::BR_CC, MVT::Other, Tmp1, + DAG.getCondCode(ISD::SETNE), Tmp2, + DAG.getConstant(0, Tmp2.getValueType()), + Node->getOperand(2)); + } + break; + case TargetLowering::Legal: + // Basic block destination (Op#2) is always legal. + if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(1)) + Result = DAG.getNode(ISD::BRCOND, MVT::Other, Tmp1, Tmp2, + Node->getOperand(2)); + break; + } + break; + case ISD::BR_CC: + Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. + + if (getTypeAction(Node->getOperand(2).getValueType()) == Legal) { + Tmp2 = LegalizeOp(Node->getOperand(2)); // LHS + Tmp3 = LegalizeOp(Node->getOperand(3)); // RHS + if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(2) || + Tmp3 != Node->getOperand(3)) { + Result = DAG.getNode(ISD::BR_CC, MVT::Other, Tmp1, Node->getOperand(1), + Tmp2, Tmp3, Node->getOperand(4)); + } + break; + } else { + Tmp2 = LegalizeOp(DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), + Node->getOperand(2), // LHS + Node->getOperand(3), // RHS + Node->getOperand(1))); + // If we get a SETCC back from legalizing the SETCC node we just + // created, then use its LHS, RHS, and CC directly in creating a new + // node. Otherwise, select between the true and false value based on + // comparing the result of the legalized with zero. + if (Tmp2.getOpcode() == ISD::SETCC) { + Result = DAG.getNode(ISD::BR_CC, MVT::Other, Tmp1, Tmp2.getOperand(2), + Tmp2.getOperand(0), Tmp2.getOperand(1), + Node->getOperand(4)); + } else { + Result = DAG.getNode(ISD::BR_CC, MVT::Other, Tmp1, + DAG.getCondCode(ISD::SETNE), + Tmp2, DAG.getConstant(0, Tmp2.getValueType()), + Node->getOperand(4)); + } + } break; case ISD::BRCONDTWOWAY: Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. @@ -636,13 +689,71 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { } break; case TargetLowering::Expand: - Result = DAG.getNode(ISD::BRCOND, MVT::Other, Tmp1, Tmp2, + // 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.getOperationAction(ISD::BRTWOWAY_CC, MVT::Other) == + TargetLowering::Legal) { + if (Tmp2.getOpcode() == ISD::SETCC) { + Result = DAG.getBR2Way_CC(Tmp1, Tmp2.getOperand(2), + Tmp2.getOperand(0), Tmp2.getOperand(1), + Node->getOperand(2), Node->getOperand(3)); + } else { + Result = DAG.getBR2Way_CC(Tmp1, DAG.getCondCode(ISD::SETNE), Tmp2, + DAG.getConstant(0, Tmp2.getValueType()), + Node->getOperand(2), Node->getOperand(3)); + } + } else { + Result = DAG.getNode(ISD::BRCOND, MVT::Other, Tmp1, Tmp2, Node->getOperand(2)); - Result = DAG.getNode(ISD::BR, MVT::Other, Result, Node->getOperand(3)); + 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. + if (getTypeAction(Node->getOperand(2).getValueType()) == Legal) { + Tmp2 = LegalizeOp(Node->getOperand(2)); // LHS + Tmp3 = LegalizeOp(Node->getOperand(3)); // RHS + if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(2) || + Tmp3 != Node->getOperand(3)) { + Result = DAG.getBR2Way_CC(Tmp1, Node->getOperand(1), Tmp2, Tmp3, + Node->getOperand(4), Node->getOperand(5)); + } + break; + } else { + Tmp2 = LegalizeOp(DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), + Node->getOperand(2), // LHS + Node->getOperand(3), // RHS + Node->getOperand(1))); + // If this target does not support BRTWOWAY_CC, lower it to a BRCOND/BR + // pair. + switch (TLI.getOperationAction(ISD::BRTWOWAY_CC, MVT::Other)) { + default: assert(0 && "This action is not supported yet!"); + case TargetLowering::Legal: + // If we get a SETCC back from legalizing the SETCC node we just + // created, then use its LHS, RHS, and CC directly in creating a new + // node. Otherwise, select between the true and false value based on + // comparing the result of the legalized with zero. + if (Tmp2.getOpcode() == ISD::SETCC) { + Result = DAG.getBR2Way_CC(Tmp1, Tmp2.getOperand(2), + Tmp2.getOperand(0), Tmp2.getOperand(1), + Node->getOperand(4), Node->getOperand(5)); + } else { + Result = DAG.getBR2Way_CC(Tmp1, DAG.getCondCode(ISD::SETNE), Tmp2, + DAG.getConstant(0, Tmp2.getValueType()), + Node->getOperand(4), Node->getOperand(5)); + } + break; + case TargetLowering::Expand: + Result = DAG.getNode(ISD::BRCOND, MVT::Other, Tmp1, Tmp2, + Node->getOperand(4)); + Result = DAG.getNode(ISD::BR, MVT::Other, Result, Node->getOperand(5)); + break; + } + } + break; case ISD::LOAD: Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the pointer. @@ -967,9 +1078,19 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { Node->getOperand(0), // LHS Node->getOperand(1), // RHS Node->getOperand(4))); - Result = DAG.getSelectCC(Tmp1, - DAG.getConstant(0, Tmp1.getValueType()), - Tmp3, Tmp4, ISD::SETNE); + // If we get a SETCC back from legalizing the SETCC node we just + // created, then use its LHS, RHS, and CC directly in creating a new + // node. Otherwise, select between the true and false value based on + // comparing the result of the legalized with zero. + if (Tmp1.getOpcode() == ISD::SETCC) { + Result = DAG.getNode(ISD::SELECT_CC, Tmp3.getValueType(), + Tmp1.getOperand(0), Tmp1.getOperand(1), + Tmp3, Tmp4, Tmp1.getOperand(2)); + } else { + Result = DAG.getSelectCC(Tmp1, + DAG.getConstant(0, Tmp1.getValueType()), + Tmp3, Tmp4, ISD::SETNE); + } } break; case ISD::SETCC: diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index cf3cb706ecb..7a790c8df92 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1602,7 +1602,11 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, 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(Ops[4])->getVT(); @@ -1833,6 +1837,8 @@ const char *SDNode::getOperationName(const SelectionDAG *G) const { 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::RET: return "ret"; case ISD::CALL: return "call"; case ISD::TAILCALL:return "tailcall"; diff --git a/lib/Target/Alpha/AlphaISelPattern.cpp b/lib/Target/Alpha/AlphaISelPattern.cpp index e898916f805..c0ae2acf97c 100644 --- a/lib/Target/Alpha/AlphaISelPattern.cpp +++ b/lib/Target/Alpha/AlphaISelPattern.cpp @@ -90,6 +90,7 @@ namespace { addRegisterClass(MVT::f32, Alpha::FPRCRegisterClass); setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand); + setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand); setOperationAction(ISD::EXTLOAD, MVT::i1, Promote); setOperationAction(ISD::EXTLOAD, MVT::f32, Expand); diff --git a/lib/Target/IA64/IA64ISelPattern.cpp b/lib/Target/IA64/IA64ISelPattern.cpp index 5428a8b9ed9..f4231a3f853 100644 --- a/lib/Target/IA64/IA64ISelPattern.cpp +++ b/lib/Target/IA64/IA64ISelPattern.cpp @@ -57,6 +57,7 @@ namespace { addRegisterClass(MVT::i1, IA64::PRRegisterClass); setOperationAction(ISD::BRCONDTWOWAY , MVT::Other, Expand); + setOperationAction(ISD::BRTWOWAY_CC , MVT::Other, Expand); setOperationAction(ISD::FP_ROUND_INREG , MVT::f32 , Expand); setSetCCResultType(MVT::i1); diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index d06542d6b11..cd2fc16d09e 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -66,6 +66,10 @@ PPC32TargetLowering::PPC32TargetLowering(TargetMachine &TM) setOperationAction(ISD::SELECT, MVT::i32, Expand); setOperationAction(ISD::SELECT, MVT::f32, Expand); setOperationAction(ISD::SELECT, MVT::f64, Expand); + + // PowerPC does not have BRCOND* which requires SetCC + setOperationAction(ISD::BRCOND, MVT::Other, Expand); + setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand); // PowerPC does not have FP_TO_UINT setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); diff --git a/lib/Target/PowerPC/PPCISelPattern.cpp b/lib/Target/PowerPC/PPCISelPattern.cpp index 75f568f349a..4e674dc5690 100644 --- a/lib/Target/PowerPC/PPCISelPattern.cpp +++ b/lib/Target/PowerPC/PPCISelPattern.cpp @@ -713,22 +713,11 @@ unsigned ISel::SelectAddr(SDOperand N, unsigned& Reg, int& offset) void ISel::SelectBranchCC(SDOperand N) { MachineBasicBlock *Dest = - cast(N.getOperand(2))->getBasicBlock(); + cast(N.getOperand(4))->getBasicBlock(); Select(N.getOperand(0)); //chain - - // FIXME: Until we have Branch_CC and Branch_Twoway_CC, we're going to have to - // Fake it up by hand by checking to see if op 1 is a SetCC, or a boolean. - unsigned CCReg; - ISD::CondCode CC; - SDOperand Cond = N.getOperand(1); - if (Cond.getOpcode() == ISD::SETCC) { - CC = cast(Cond.getOperand(2))->get(); - CCReg = SelectCC(Cond.getOperand(0), Cond.getOperand(1), CC); - } else { - CC = ISD::SETNE; - CCReg = SelectCC(Cond, ISelDAG->getConstant(0, Cond.getValueType()), CC); - } + ISD::CondCode CC = cast(N.getOperand(1))->get(); + unsigned CCReg = SelectCC(N.getOperand(2), N.getOperand(3), CC); unsigned Opc = getBCCForSetCC(CC); // Iterate to the next basic block @@ -739,9 +728,9 @@ void ISel::SelectBranchCC(SDOperand N) // 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::BRCONDTWOWAY) { + if (N.getOpcode() == ISD::BRTWOWAY_CC) { MachineBasicBlock *Fallthrough = - cast(N.getOperand(3))->getBasicBlock(); + cast(N.getOperand(5))->getBasicBlock(); if (Dest != It) { BuildMI(BB, PPC::COND_BRANCH, 4).addReg(CCReg).addImm(Opc) .addMBB(Dest).addMBB(Fallthrough); @@ -1882,8 +1871,8 @@ void ISel::Select(SDOperand N) { BuildMI(BB, PPC::B, 1).addMBB(Dest); return; } - case ISD::BRCOND: - case ISD::BRCONDTWOWAY: + case ISD::BR_CC: + case ISD::BRTWOWAY_CC: SelectBranchCC(N); return; case ISD::CopyToReg: diff --git a/lib/Target/Sparc/SparcV8ISelPattern.cpp b/lib/Target/Sparc/SparcV8ISelPattern.cpp index 346f058cdcf..754c16b6ef5 100644 --- a/lib/Target/Sparc/SparcV8ISelPattern.cpp +++ b/lib/Target/Sparc/SparcV8ISelPattern.cpp @@ -55,6 +55,7 @@ namespace { addRegisterClass(MVT::f32, V8::FPRCRegisterClass); setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand); + setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand); setOperationAction(ISD::EXTLOAD, MVT::i1, Promote); setOperationAction(ISD::EXTLOAD, MVT::f32, Promote); diff --git a/lib/Target/SparcV8/SparcV8ISelPattern.cpp b/lib/Target/SparcV8/SparcV8ISelPattern.cpp index 346f058cdcf..754c16b6ef5 100644 --- a/lib/Target/SparcV8/SparcV8ISelPattern.cpp +++ b/lib/Target/SparcV8/SparcV8ISelPattern.cpp @@ -55,6 +55,7 @@ namespace { addRegisterClass(MVT::f32, V8::FPRCRegisterClass); setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand); + setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand); setOperationAction(ISD::EXTLOAD, MVT::i1, Promote); setOperationAction(ISD::EXTLOAD, MVT::f32, Promote); diff --git a/lib/Target/X86/X86ISelPattern.cpp b/lib/Target/X86/X86ISelPattern.cpp index db95e918644..6ff8c723f5f 100644 --- a/lib/Target/X86/X86ISelPattern.cpp +++ b/lib/Target/X86/X86ISelPattern.cpp @@ -152,6 +152,7 @@ namespace { setOperationAction(ISD::FP_TO_SINT , MVT::i16 , Promote); setOperationAction(ISD::BRCONDTWOWAY , MVT::Other, Expand); + setOperationAction(ISD::BRTWOWAY_CC , MVT::Other, Expand); setOperationAction(ISD::MEMMOVE , MVT::Other, Expand); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16 , Expand); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand); -- 2.34.1