[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
Chris Lattner
sabre at nondot.org
Fri Oct 27 14:36:18 PDT 2006
Changes in directory llvm/lib/CodeGen/SelectionDAG:
SelectionDAGISel.cpp updated: 1.299 -> 1.300
---
Log message:
Turn conditions like x<Y|z==q into multiple blocks.
This compiles Regression/CodeGen/X86/or-branch.ll into:
_foo:
subl $12, %esp
call L_bar$stub
movl 20(%esp), %eax
movl 16(%esp), %ecx
cmpl $5, %eax
jl LBB1_1 #cond_true
LBB1_3: #entry
testl %ecx, %ecx
jne LBB1_2 #UnifiedReturnBlock
LBB1_1: #cond_true
call L_bar$stub
addl $12, %esp
ret
LBB1_2: #UnifiedReturnBlock
addl $12, %esp
ret
instead of:
_foo:
subl $12, %esp
call L_bar$stub
movl 20(%esp), %eax
movl 16(%esp), %ecx
cmpl $4, %eax
setg %al
testl %ecx, %ecx
setne %cl
testb %cl, %al
jne LBB1_2 #UnifiedReturnBlock
LBB1_1: #cond_true
call L_bar$stub
addl $12, %esp
ret
LBB1_2: #UnifiedReturnBlock
addl $12, %esp
ret
And on ppc to:
cmpwi cr0, r29, 5
blt cr0, LBB1_1 ;cond_true
LBB1_3: ;entry
cmplwi cr0, r30, 0
bne cr0, LBB1_2 ;UnifiedReturnBlock
instead of:
cmpwi cr7, r4, 4
mfcr r2
addic r4, r3, -1
subfe r30, r4, r3
rlwinm r29, r2, 30, 31, 31
and r2, r29, r30
cmplwi cr0, r2, 0
bne cr0, LBB1_2 ;UnifiedReturnBlock
---
Diffs of the changes: (+185 -19)
SelectionDAGISel.cpp | 204 ++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 185 insertions(+), 19 deletions(-)
Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.299 llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.300
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.299 Thu Oct 26 01:15:43 2006
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Fri Oct 27 16:36:01 2006
@@ -184,6 +184,12 @@
unsigned MakeReg(MVT::ValueType VT) {
return RegMap->createVirtualRegister(TLI.getRegClassFor(VT));
}
+
+ /// isExportedInst - Return true if the specified value is an instruction
+ /// exported from its block.
+ bool isExportedInst(const Value *V) {
+ return ValueMap.count(V);
+ }
unsigned CreateRegForValue(const Value *V);
@@ -203,6 +209,7 @@
BasicBlock *BB = I->getParent();
for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; ++UI)
if (cast<Instruction>(*UI)->getParent() != BB || isa<PHINode>(*UI) ||
+ // FIXME: Remove switchinst special case.
isa<SwitchInst>(*UI))
return true;
return false;
@@ -448,6 +455,8 @@
return Root;
}
+ SDOperand CopyValueToVirtualRegister(Value *V, unsigned Reg);
+
void visit(Instruction &I) { visit(I.getOpcode(), I); }
void visit(unsigned Opcode, User &I) {
@@ -485,6 +494,11 @@
std::set<unsigned> &OutputRegs,
std::set<unsigned> &InputRegs);
+ void FindMergedConditions(Value *Cond, MachineBasicBlock *TBB,
+ MachineBasicBlock *FBB, MachineBasicBlock *CurBB,
+ unsigned Opc);
+ void ExportFromCurrentBlock(Value *V);
+
// Terminator instructions.
void visitRet(ReturnInst &I);
void visitBr(BranchInst &I);
@@ -770,6 +784,128 @@
&NewValues[0], NewValues.size()));
}
+/// ExportFromCurrentBlock - If this condition isn't known to be exported from
+/// the current basic block, add it to ValueMap now so that we'll get a
+/// CopyTo/FromReg.
+void SelectionDAGLowering::ExportFromCurrentBlock(Value *V) {
+ // No need to export constants.
+ if (!isa<Instruction>(V) && !isa<Argument>(V)) return;
+
+ // Already exported?
+ if (FuncInfo.isExportedInst(V)) return;
+
+ unsigned Reg = FuncInfo.InitializeRegForValue(V);
+ PendingLoads.push_back(CopyValueToVirtualRegister(V, Reg));
+}
+
+/// FindMergedConditions - If Cond is an expression like
+void SelectionDAGLowering::FindMergedConditions(Value *Cond,
+ MachineBasicBlock *TBB,
+ MachineBasicBlock *FBB,
+ MachineBasicBlock *CurBB,
+ unsigned Opc) {
+ // FIXME: HANDLE AND.
+ // FIXME: HANDLE NOT
+
+ // If this node is not part of the or/and tree, emit it as a branch.
+ BinaryOperator *BOp = dyn_cast<BinaryOperator>(Cond);
+
+ if (!BOp || (unsigned)BOp->getOpcode() != Opc || !BOp->hasOneUse() ||
+ BOp->getParent() != CurBB->getBasicBlock()) {
+ const BasicBlock *BB = CurBB->getBasicBlock();
+
+ // If the leaf of the tree is a setcond inst, merge the condition into the
+ // caseblock.
+ if (BOp && isa<SetCondInst>(BOp) &&
+ // The operands of the setcc have to be in this block. We don't know
+ // how to export them from some other block.
+ (!isa<Instruction>(BOp->getOperand(0)) ||
+ cast<Instruction>(BOp->getOperand(0))->getParent() == BB ||
+ FuncInfo.isExportedInst(BOp->getOperand(0))) &&
+ (!isa<Instruction>(BOp->getOperand(1)) ||
+ cast<Instruction>(BOp->getOperand(1))->getParent() == BB ||
+ FuncInfo.isExportedInst(BOp->getOperand(1)))) {
+ ExportFromCurrentBlock(BOp->getOperand(0));
+ ExportFromCurrentBlock(BOp->getOperand(1));
+
+ ISD::CondCode SignCond, UnsCond, FPCond, Condition;
+ switch (BOp->getOpcode()) {
+ default: assert(0 && "Unknown setcc opcode!");
+ case Instruction::SetEQ:
+ SignCond = ISD::SETEQ;
+ UnsCond = ISD::SETEQ;
+ FPCond = ISD::SETOEQ;
+ break;
+ case Instruction::SetNE:
+ SignCond = ISD::SETNE;
+ UnsCond = ISD::SETNE;
+ FPCond = ISD::SETUNE;
+ break;
+ case Instruction::SetLE:
+ SignCond = ISD::SETLE;
+ UnsCond = ISD::SETULE;
+ FPCond = ISD::SETOLE;
+ break;
+ case Instruction::SetGE:
+ SignCond = ISD::SETGE;
+ UnsCond = ISD::SETUGE;
+ FPCond = ISD::SETOGE;
+ break;
+ case Instruction::SetLT:
+ SignCond = ISD::SETLT;
+ UnsCond = ISD::SETULT;
+ FPCond = ISD::SETOLT;
+ break;
+ case Instruction::SetGT:
+ SignCond = ISD::SETGT;
+ UnsCond = ISD::SETUGT;
+ FPCond = ISD::SETOGT;
+ break;
+ }
+
+ const Type *OpType = BOp->getOperand(0)->getType();
+ if (const PackedType *PTy = dyn_cast<PackedType>(OpType))
+ OpType = PTy->getElementType();
+
+ if (!FiniteOnlyFPMath() && OpType->isFloatingPoint())
+ Condition = FPCond;
+ else if (OpType->isUnsigned())
+ Condition = UnsCond;
+ else
+ Condition = SignCond;
+
+ SelectionDAGISel::CaseBlock CB(Condition, BOp->getOperand(0),
+ BOp->getOperand(1), TBB, FBB, CurBB);
+ SwitchCases.push_back(CB);
+ return;
+ }
+
+ // Create a CaseBlock record representing this branch.
+ SelectionDAGISel::CaseBlock CB(ISD::SETEQ, Cond, ConstantBool::getTrue(),
+ TBB, FBB, CurBB);
+ SwitchCases.push_back(CB);
+ ExportFromCurrentBlock(Cond);
+ return;
+ }
+
+ // Codegen X | Y as:
+ // jmp_if_X TBB
+ // TmpBB:
+ // jmp_if_Y TBB
+ // jmp FBB
+ //
+ // This requires creation of TmpBB after CurBB.
+ MachineFunction::iterator BBI = CurBB;
+ MachineBasicBlock *TmpBB = new MachineBasicBlock(CurBB->getBasicBlock());
+ CurBB->getParent()->getBasicBlockList().insert(++BBI, TmpBB);
+
+ // Emit the LHS condition.
+ FindMergedConditions(BOp->getOperand(0), TBB, TmpBB, CurBB, Opc);
+
+ // Emit the RHS condition into TmpBB.
+ FindMergedConditions(BOp->getOperand(1), TBB, FBB, TmpBB, Opc);
+}
+
void SelectionDAGLowering::visitBr(BranchInst &I) {
// Update machine-CFG edges.
MachineBasicBlock *Succ0MBB = FuncInfo.MBBMap[I.getSuccessor(0)];
@@ -796,9 +932,38 @@
// now.
Value *CondVal = I.getCondition();
MachineBasicBlock *Succ1MBB = FuncInfo.MBBMap[I.getSuccessor(1)];
+
+ // If this is a series of conditions that are or'd or and'd together, emit
+ // this as a sequence of branches instead of setcc's with and/or operations.
+ // For example, instead of something like:
+ // cmp A, B
+ // C = seteq
+ // cmp D, E
+ // F = setle
+ // or C, F
+ // jnz foo
+ // Emit:
+ // cmp A, B
+ // je foo
+ // cmp D, E
+ // jle foo
+ //
+ if (BinaryOperator *BOp = dyn_cast<BinaryOperator>(CondVal)) {
+ if (BOp->hasOneUse() &&
+ (/*BOp->getOpcode() == Instruction::And ||*/
+ BOp->getOpcode() == Instruction::Or)) {
+ FindMergedConditions(BOp, Succ0MBB, Succ1MBB, CurMBB, BOp->getOpcode());
+ //std::cerr << "FOUND: " << SwitchCases.size() << " merged conditions:\n";
+ //I.getParent()->dump();
+
+ visitSwitchCase(SwitchCases[0]);
+ SwitchCases.erase(SwitchCases.begin());
+ return;
+ }
+ }
// Create a CaseBlock record representing this branch.
- SelectionDAGISel::CaseBlock CB(ISD::SETEQ, CondVal, 0,
+ SelectionDAGISel::CaseBlock CB(ISD::SETEQ, CondVal, ConstantBool::getTrue(),
Succ0MBB, Succ1MBB, CurMBB);
// Use visitSwitchCase to actually insert the fast branch sequence for this
// cond branch.
@@ -811,12 +976,15 @@
SDOperand Cond;
SDOperand CondLHS = getValue(CB.CmpLHS);
- // If the CaseBlock has both LHS/RHS comparisons, build the setcc now,
- // otherwise, just use the LHS value as a bool comparison value.
- if (CB.CmpRHS)
- Cond = DAG.getSetCC(MVT::i1, CondLHS, getValue(CB.CmpRHS), CB.CC);
- else
+ // Build the setcc now, fold "(X == true)" to X and "(X == false)" to !X to
+ // handle common cases produced by branch lowering.
+ if (CB.CmpRHS == ConstantBool::getTrue() && CB.CC == ISD::SETEQ)
Cond = CondLHS;
+ else if (CB.CmpRHS == ConstantBool::getFalse() && CB.CC == ISD::SETEQ) {
+ SDOperand True = DAG.getConstant(1, CondLHS.getValueType());
+ Cond = DAG.getNode(ISD::XOR, CondLHS.getValueType(), CondLHS, True);
+ } else
+ Cond = DAG.getSetCC(MVT::i1, CondLHS, getValue(CB.CmpRHS), CB.CC);
// Set NextBlock to be the MBB immediately after the current one, if any.
// This is used to avoid emitting unnecessary branches to the next block.
@@ -3385,10 +3553,9 @@
return true;
}
-
-SDOperand SelectionDAGISel::
-CopyValueToVirtualRegister(SelectionDAGLowering &SDL, Value *V, unsigned Reg) {
- SDOperand Op = SDL.getValue(V);
+SDOperand SelectionDAGLowering::CopyValueToVirtualRegister(Value *V,
+ unsigned Reg) {
+ SDOperand Op = getValue(V);
assert((Op.getOpcode() != ISD::CopyFromReg ||
cast<RegisterSDNode>(Op.getOperand(1))->getReg() != Reg) &&
"Copy from a reg to the same reg!");
@@ -3397,9 +3564,8 @@
// register use.
MVT::ValueType SrcVT = Op.getValueType();
MVT::ValueType DestVT = TLI.getTypeToTransformTo(SrcVT);
- SelectionDAG &DAG = SDL.DAG;
if (SrcVT == DestVT) {
- return DAG.getCopyToReg(SDL.getRoot(), Reg, Op);
+ return DAG.getCopyToReg(getRoot(), Reg, Op);
} else if (SrcVT == MVT::Vector) {
// Handle copies from generic vectors to registers.
MVT::ValueType PTyElementVT, PTyLegalElementVT;
@@ -3416,7 +3582,7 @@
// VEXTRACT_VECTOR_ELT'ing them, converting them to PTyLegalElementVT, then
// copying them into output registers.
SmallVector<SDOperand, 8> OutChains;
- SDOperand Root = SDL.getRoot();
+ SDOperand Root = getRoot();
for (unsigned i = 0; i != NE; ++i) {
SDOperand Elt = DAG.getNode(ISD::VEXTRACT_VECTOR_ELT, PTyElementVT,
Op, DAG.getConstant(i, TLI.getPointerTy()));
@@ -3449,14 +3615,14 @@
Op = DAG.getNode(ISD::FP_EXTEND, DestVT, Op);
else
Op = DAG.getNode(ISD::ANY_EXTEND, DestVT, Op);
- return DAG.getCopyToReg(SDL.getRoot(), Reg, Op);
+ return DAG.getCopyToReg(getRoot(), Reg, Op);
} else {
// The src value is expanded into multiple registers.
SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DestVT,
Op, DAG.getConstant(0, TLI.getPointerTy()));
SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DestVT,
Op, DAG.getConstant(1, TLI.getPointerTy()));
- Op = DAG.getCopyToReg(SDL.getRoot(), Reg, Lo);
+ Op = DAG.getCopyToReg(getRoot(), Reg, Lo);
return DAG.getCopyToReg(Op, Reg+1, Hi);
}
}
@@ -3480,7 +3646,7 @@
// whereever we got it to the vreg that other BB's will reference it as.
if (FuncInfo.ValueMap.count(AI)) {
SDOperand Copy =
- CopyValueToVirtualRegister(SDL, AI, FuncInfo.ValueMap[AI]);
+ SDL.CopyValueToVirtualRegister(AI, FuncInfo.ValueMap[AI]);
UnorderedChains.push_back(Copy);
}
}
@@ -3516,7 +3682,7 @@
std::map<const Value*, unsigned>::iterator VMI =FuncInfo.ValueMap.find(I);
if (VMI != FuncInfo.ValueMap.end())
UnorderedChains.push_back(
- CopyValueToVirtualRegister(SDL, I, VMI->second));
+ SDL.CopyValueToVirtualRegister(I, VMI->second));
}
// Handle PHI nodes in successor blocks. Emit code into the SelectionDAG to
@@ -3553,7 +3719,7 @@
if (RegOut == 0) {
RegOut = FuncInfo.CreateRegForValue(C);
UnorderedChains.push_back(
- CopyValueToVirtualRegister(SDL, C, RegOut));
+ SDL.CopyValueToVirtualRegister(C, RegOut));
}
Reg = RegOut;
} else {
@@ -3564,7 +3730,7 @@
"Didn't codegen value into a register!??");
Reg = FuncInfo.CreateRegForValue(PHIOp);
UnorderedChains.push_back(
- CopyValueToVirtualRegister(SDL, PHIOp, Reg));
+ SDL.CopyValueToVirtualRegister(PHIOp, Reg));
}
}
More information about the llvm-commits
mailing list