aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
diff options
context:
space:
mode:
authorManman Ren <manman.ren@gmail.com>2014-07-23 23:13:23 +0000
committerManman Ren <manman.ren@gmail.com>2014-07-23 23:13:23 +0000
commitedc60376edcc86bbfac132306581b10f3948af69 (patch)
tree4102cabcf104b8a2f87750c46266ab9fe730333a /llvm/lib/Transforms/Utils/SimplifyCFG.cpp
parent45bcf8a59c5415286efd587e0127f51e546fa772 (diff)
downloadllvm-edc60376edcc86bbfac132306581b10f3948af69.zip
llvm-edc60376edcc86bbfac132306581b10f3948af69.tar.gz
llvm-edc60376edcc86bbfac132306581b10f3948af69.tar.bz2
SimplifyCFG: fix a bug in switch to table conversion
We use gep to access the global array "switch.table", and the table index should be treated as unsigned. When the highest bit is 1, this commit zero-extends the index to an integer type with larger size. For a switch on i2, we used to generate: %switch.tableidx = sub i2 %0, -2 getelementptr inbounds [4 x i64]* @switch.table, i32 0, i2 %switch.tableidx It is incorrect when %switch.tableidx is 2 or 3. The fix is to generate %switch.tableidx = sub i2 %0, -2 %switch.tableidx.zext = zext i2 %switch.tableidx to i3 getelementptr inbounds [4 x i64]* @switch.table, i32 0, i3 %switch.tableidx.zext rdar://17735071 llvm-svn: 213815
Diffstat (limited to 'llvm/lib/Transforms/Utils/SimplifyCFG.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyCFG.cpp17
1 files changed, 13 insertions, 4 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 960b198..635117f 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3477,7 +3477,7 @@ namespace {
/// BuildLookup - Build instructions with Builder to retrieve the value at
/// the position given by Index in the lookup table.
- Value *BuildLookup(Value *Index, IRBuilder<> &Builder);
+ Value *BuildLookup(Value *Index, uint64_t TableSize, IRBuilder<> &Builder);
/// WouldFitInRegister - Return true if a table with TableSize elements of
/// type ElementType would fit in a target-legal register.
@@ -3598,7 +3598,8 @@ SwitchLookupTable::SwitchLookupTable(Module &M,
Kind = ArrayKind;
}
-Value *SwitchLookupTable::BuildLookup(Value *Index, IRBuilder<> &Builder) {
+Value *SwitchLookupTable::BuildLookup(Value *Index, uint64_t TableSize,
+ IRBuilder<> &Builder) {
switch (Kind) {
case SingleValueKind:
return SingleValue;
@@ -3624,6 +3625,14 @@ Value *SwitchLookupTable::BuildLookup(Value *Index, IRBuilder<> &Builder) {
"switch.masked");
}
case ArrayKind: {
+ // Make sure the table index will not overflow when treated as signed.
+ if (IntegerType *IT = dyn_cast<IntegerType>(Index->getType()))
+ if (TableSize > (1 << (IT->getBitWidth() - 1)))
+ Index = Builder.CreateZExt(Index,
+ IntegerType::get(IT->getContext(),
+ IT->getBitWidth() + 1),
+ "switch.tableidx.zext");
+
Value *GEPIndices[] = { Builder.getInt32(0), Index };
Value *GEP = Builder.CreateInBoundsGEP(Array, GEPIndices,
"switch.gep");
@@ -3823,7 +3832,7 @@ static bool SwitchToLookupTable(SwitchInst *SI,
SI->getDefaultDest()->removePredecessor(SI->getParent());
} else {
Value *Cmp = Builder.CreateICmpULT(TableIndex, ConstantInt::get(
- MinCaseVal->getType(), TableSize));
+ MinCaseVal->getType(), TableSize));
Builder.CreateCondBr(Cmp, LookupBB, SI->getDefaultDest());
}
@@ -3878,7 +3887,7 @@ static bool SwitchToLookupTable(SwitchInst *SI,
SwitchLookupTable Table(Mod, TableSize, MinCaseVal, ResultLists[PHI],
DV, DL);
- Value *Result = Table.BuildLookup(TableIndex, Builder);
+ Value *Result = Table.BuildLookup(TableIndex, TableSize, Builder);
// If the result is used to return immediately from the function, we want to
// do that right here.