/// 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.
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;
"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");
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());
}
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.
--- /dev/null
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+; rdar://17735071
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-darwin12.0.0"
+
+; When tableindex can't fit into i2, we should extend the type to i3.
+; CHECK-LABEL: @_TFO6reduce1E5toRawfS0_FT_Si
+; CHECK: entry:
+; CHECK-NEXT: sub i2 %0, -2
+; CHECK-NEXT: zext i2 %switch.tableidx to i3
+; CHECK-NEXT: getelementptr inbounds [4 x i64]* @switch.table, i32 0, i3 %switch.tableidx.zext
+; CHECK-NEXT: load i64* %switch.gep
+; CHECK-NEXT: ret i64 %switch.load
+define i64 @_TFO6reduce1E5toRawfS0_FT_Si(i2) {
+entry:
+ switch i2 %0, label %1 [
+ i2 0, label %2
+ i2 1, label %3
+ i2 -2, label %4
+ i2 -1, label %5
+ ]
+
+; <label>:1 ; preds = %entry
+ unreachable
+
+; <label>:2 ; preds = %2
+ br label %6
+
+; <label>:3 ; preds = %4
+ br label %6
+
+; <label>:4 ; preds = %6
+ br label %6
+
+; <label>:5 ; preds = %8
+ br label %6
+
+; <label>:6 ; preds = %3, %5, %7, %9
+ %7 = phi i64 [ 3, %5 ], [ 2, %4 ], [ 1, %3 ], [ 0, %2 ]
+ ret i64 %7
+}