[llvm-commits] [125252] Emit switch cases with a wide range as a conditional branch.
dpatel at apple.com
dpatel at apple.com
Thu Mar 22 16:02:12 PDT 2007
Revision: 125252
Author: dpatel
Date: 2007-03-22 16:02:12 -0700 (Thu, 22 Mar 2007)
Log Message:
-----------
Emit switch cases with a wide range as a conditional branch.
Patch by Duncan Sands.
Modified Paths:
--------------
apple-local/branches/llvm/gcc/llvm-convert.cpp
Modified: apple-local/branches/llvm/gcc/llvm-convert.cpp
===================================================================
--- apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-03-22 21:39:17 UTC (rev 125251)
+++ apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-03-22 23:02:12 UTC (rev 125252)
@@ -1666,6 +1666,7 @@
// Emit the condition.
Value *SwitchExp = Emit(SWITCH_COND(exp), 0);
+ bool ExpIsSigned = !TYPE_UNSIGNED(TREE_TYPE(SWITCH_COND(exp)));
// Emit the switch instruction.
SwitchInst *SI = new SwitchInst(SwitchExp, CurBB,
@@ -1673,39 +1674,68 @@
EmitBlock(new BasicBlock(""));
SI->setSuccessor(0, CurBB); // Default location starts out as fall-through
- // Output the body of the switch.
- if (SWITCH_BODY(exp))
- Emit(SWITCH_BODY(exp), 0);
-
+ assert(!SWITCH_BODY(exp) && "not a gimple switch?");
+
+ BasicBlock *DefaultDest = NULL;
for (unsigned i = 0, e = TREE_VEC_LENGTH(Cases); i != e; ++i) {
BasicBlock *Dest = getLabelDeclBlock(CASE_LABEL(TREE_VEC_ELT(Cases, i)));
- if (CASE_LOW(TREE_VEC_ELT(Cases, i)) == 0) {
- SI->setSuccessor(0, Dest); // Change the default destination.
+
+ tree low = CASE_LOW(TREE_VEC_ELT(Cases, i));
+ if (!low) {
+ DefaultDest = Dest;
continue;
}
// Convert the integer to the right type.
- Value *Val = Emit(CASE_LOW(TREE_VEC_ELT(Cases, i)), 0);
- Val = CastToSIntType(Val, SwitchExp->getType());
- ConstantInt *ValC = cast<ConstantInt>(Val);
- if (CASE_HIGH(TREE_VEC_ELT(Cases, i)) == 0) {
- SI->addCase(ValC, Dest); // Single destination.
+ Value *Val = Emit(low, 0);
+ Val = CastToAnyType(Val, !TYPE_UNSIGNED(TREE_TYPE(low)),
+ SwitchExp->getType(), ExpIsSigned);
+ ConstantInt *LowC = cast<ConstantInt>(Val);
+
+ tree high = CASE_HIGH(TREE_VEC_ELT(Cases, i));
+ if (!high) {
+ SI->addCase(LowC, Dest); // Single destination.
continue;
}
- // Otherwise, we have a range, like 'case 1 ... 17'. Add all of the
- // necessary successors to the switch.
- Val = Emit(CASE_HIGH(TREE_VEC_ELT(Cases, i)), 0);
- // Make sure the case value is the same type as the switch expression (int)
- Val = CastToSIntType(Val, SwitchExp->getType());
- ConstantInt *HiC = cast<ConstantInt>(Val);
- Constant *OneC = ConstantInt::get(ValC->getType(), 1);
- while (1) {
- SI->addCase(ValC, Dest);
- if (ValC == HiC) break; // Emitted the last one.
- ValC = cast<ConstantInt>(ConstantExpr::getAdd(ValC, OneC));
+ // Otherwise, we have a range, like 'case 1 ... 17'.
+ Val = Emit(high, 0);
+ // Make sure the case value is the same type as the switch expression
+ Val = CastToAnyType(Val, !TYPE_UNSIGNED(TREE_TYPE(high)),
+ SwitchExp->getType(), ExpIsSigned);
+ ConstantInt *HighC = cast<ConstantInt>(Val);
+
+ APInt Range = HighC->getValue() - LowC->getValue();
+ if (Range.ult(APInt(Range.getBitWidth(), 64))) {
+ // Add all of the necessary successors to the switch.
+ APInt CurrentValue = LowC->getValue();
+ while (1) {
+ SI->addCase(LowC, Dest);
+ if (LowC == HighC) break; // Emitted the last one.
+ CurrentValue++;
+ LowC = ConstantInt::get(CurrentValue);
+ }
+ } else {
+ // The range is too big to add to the switch - emit an "if".
+ Value *Diff = BinaryOperator::create(Instruction::Sub, SwitchExp, LowC,
+ "tmp", CurBB);
+ Value *Cond = new ICmpInst(ICmpInst::ICMP_ULE, Diff,
+ ConstantInt::get(Range), "tmp", CurBB);
+ BasicBlock *False_Block = new BasicBlock("case_false");
+ new BranchInst(Dest, False_Block, Cond, CurBB);
+ EmitBlock(False_Block);
}
}
+
+ if (DefaultDest)
+ if (SI->getSuccessor(0) == CurBB)
+ SI->setSuccessor(0, DefaultDest);
+ else {
+ new BranchInst(DefaultDest, CurBB);
+ // Emit a "fallthrough" block, which is almost certainly dead.
+ EmitBlock(new BasicBlock(""));
+ }
+
return 0;
}
More information about the llvm-commits
mailing list