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


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213815 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Manman Ren
2014-07-23 23:13:23 +00:00
parent 48b8c128df
commit 4cae9cb034
2 changed files with 54 additions and 4 deletions

View File

@ -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.