[llvm] [SimplifyCFG] Truncate integers in switch lookup tables (PR #120893)

via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 22 04:33:20 PST 2024


https://github.com/DaMatrix created https://github.com/llvm/llvm-project/pull/120893

Real-world switches often return integer values in a much smaller range than the actual range of the integer type being returned. This change enables us to detect when all integer values in a switch lookup table only differ from each other in a smaller subset of the possible bit positions, truncate the lookup table elements to a narrower width and extend them at runtime.

This has two main benefits:  
- Reduces the memory footprint of lookup tables without additional runtime overhead (most architectures have zero-extending widening load instructions), resulting in smaller executable sizes and less cache pollution
- Makes a many more lookup tables small enough to fit into a bitmap, eliminating the need for any loads

>From 5cc0170e2c7a25da793235ea4a9edebb3585d5d0 Mon Sep 17 00:00:00 2001
From: DaPorkchop_ <daporkchop at daporkchop.net>
Date: Thu, 19 Dec 2024 16:18:08 +0100
Subject: [PATCH 1/2] [SimplifyCFG] Precommit tests for truncated integer
 lookup tables

---
 .../SimplifyCFG/X86/switch_to_lookup_table.ll | 110 ++++++++++++++++--
 .../X86/switch_to_lookup_table_big.ll         |  28 ++---
 2 files changed, 112 insertions(+), 26 deletions(-)

diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
index 7f484e2ec29d7d..2110bd31259f40 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
@@ -39,6 +39,9 @@ target triple = "x86_64-unknown-linux-gnu"
 ; CHECK: @switch.table.covered_switch_with_bit_tests = private unnamed_addr constant [8 x i32] [i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 1, i32 1], align 4
 ; CHECK: @switch.table.signed_overflow1 = private unnamed_addr constant [4 x i32] [i32 3333, i32 4444, i32 1111, i32 2222], align 4
 ; CHECK: @switch.table.signed_overflow2 = private unnamed_addr constant [4 x i32] [i32 3333, i32 4444, i32 2222, i32 2222], align 4
+; CHECK: @switch.table.truncatedint_shift_mask = private unnamed_addr constant [4 x i32] [i32 33578, i32 33594, i32 33658, i32 33626], align 4
+; CHECK: @switch.table.truncatedint_shift_nsw = private unnamed_addr constant [5 x i32] [i32 8483, i32 12579, i32 28963, i32 33059, i32 37155], align 4
+; CHECK: @switch.table.truncatedint_shift_not_nsw = private unnamed_addr constant [5 x i16] [i16 8483, i16 12579, i16 28963, i16 -32477, i16 -28381], align 2
 ;.
 define i32 @f(i32 %c) {
 ; CHECK-LABEL: @f(
@@ -219,13 +222,13 @@ define i32 @earlyreturncrash(i32 %x)  {
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[SW_EPILOG:%.*]]
 ; CHECK:       switch.lookup:
 ; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.earlyreturncrash, i32 0, i32 [[X]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
 ; CHECK-NEXT:    [[SWITCH_GEP1:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.earlyreturncrash.1, i32 0, i32 [[X]]
-; CHECK-NEXT:    [[SWITCH_LOAD2:%.*]] = load i32, ptr [[SWITCH_GEP1]], align 4
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST4:%.*]] = load i32, ptr [[SWITCH_GEP1]], align 4
 ; CHECK-NEXT:    br label [[SW_EPILOG]]
 ; CHECK:       sw.epilog:
-; CHECK-NEXT:    [[A_0:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 7, [[ENTRY:%.*]] ]
-; CHECK-NEXT:    [[B_0:%.*]] = phi i32 [ [[SWITCH_LOAD2]], [[SWITCH_LOOKUP]] ], [ 10, [[ENTRY]] ]
+; CHECK-NEXT:    [[A_0:%.*]] = phi i32 [ [[SWITCH_TRUNCATEDINT_CAST]], [[SWITCH_LOOKUP]] ], [ 7, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[B_0:%.*]] = phi i32 [ [[SWITCH_TRUNCATEDINT_CAST4]], [[SWITCH_LOOKUP]] ], [ 10, [[ENTRY]] ]
 ; CHECK-NEXT:    ret i32 [[A_0]]
 ;
 entry:
@@ -402,10 +405,10 @@ define i32 @large(i32 %x) {
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
 ; CHECK:       switch.lookup:
 ; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [199 x i32], ptr @switch.table.large, i32 0, i32 [[SWITCH_TABLEIDX]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
 ; CHECK-NEXT:    br label [[RETURN]]
 ; CHECK:       return:
-; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ]
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SWITCH_TRUNCATEDINT_CAST]], [[SWITCH_LOOKUP]] ]
 ; CHECK-NEXT:    ret i32 [[RETVAL_0]]
 ;
 entry:
@@ -918,8 +921,8 @@ define i32 @unreachable_default(i32 %x)  {
 ; CHECK-LABEL: @unreachable_default(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.unreachable_default, i32 0, i32 [[X:%.*]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
-; CHECK-NEXT:    ret i32 [[SWITCH_LOAD]]
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    ret i32 [[SWITCH_TRUNCATEDINT_CAST]]
 ;
 entry:
   switch i32 %x, label %default [
@@ -1714,8 +1717,8 @@ define i32 @signed_overflow1(i8 %n) {
 ; CHECK-NEXT:    [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TRUNC]], -2
 ; CHECK-NEXT:    [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i3
 ; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.signed_overflow1, i32 0, i3 [[SWITCH_TABLEIDX_ZEXT]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
-; CHECK-NEXT:    ret i32 [[SWITCH_LOAD]]
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    ret i32 [[SWITCH_TRUNCATEDINT_CAST]]
 ;
 start:
   %trunc = trunc i8 %n to i2
@@ -1750,8 +1753,8 @@ define i32 @signed_overflow2(i8 %n) {
 ; CHECK-NEXT:    [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TRUNC]], -2
 ; CHECK-NEXT:    [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i3
 ; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.signed_overflow2, i32 0, i3 [[SWITCH_TABLEIDX_ZEXT]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
-; CHECK-NEXT:    ret i32 [[SWITCH_LOAD]]
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    ret i32 [[SWITCH_TRUNCATEDINT_CAST]]
 ;
 start:
   %trunc = trunc i8 %n to i2
@@ -2184,3 +2187,86 @@ return:                                           ; preds = %sw.default, %entry,
   %retval.0 = phi { i8, i8 } [ undef, %entry ], [ undef, %entry ], [ undef, %entry ], [ %1, %sw.default ]
   ret { i8, i8 } %retval.0
 }
+
+define i32 @truncatedint_shift_mask(i32 %c) {
+; CHECK-LABEL: @truncatedint_shift_mask(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.truncatedint_shift_mask, i32 0, i32 [[C:%.*]]
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_MASK:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    ret i32 [[SWITCH_TRUNCATEDINT_MASK]]
+;
+entry:
+  switch i32 %c, label %sw.default [
+  i32 0, label %bb0
+  i32 1, label %bb1
+  i32 2, label %bb2
+  i32 3, label %bb3
+  ]
+
+sw.default: unreachable
+bb0: br label %return
+bb1: br label %return
+bb2: br label %return
+bb3: br label %return
+
+return:
+  %x = phi i32 [ u0x832A, %bb0 ], [ u0x833A, %bb1 ], [ u0x837A, %bb2 ], [ u0x835A, %bb3 ]
+  ret i32 %x
+}
+
+define i32 @truncatedint_shift_nsw(i32 %c) {
+; CHECK-LABEL: @truncatedint_shift_nsw(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.truncatedint_shift_nsw, i32 0, i32 [[C:%.*]]
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    ret i32 [[SWITCH_LOAD]]
+;
+entry:
+  switch i32 %c, label %sw.default [
+  i32 0, label %bb0
+  i32 1, label %bb1
+  i32 2, label %bb2
+  i32 3, label %bb3
+  i32 4, label %bb4
+  ]
+
+sw.default: unreachable
+bb0: br label %return
+bb1: br label %return
+bb2: br label %return
+bb3: br label %return
+bb4: br label %return
+
+return:
+  %x = phi i32 [ u0x2123, %bb0 ], [ u0x3123, %bb1 ], [ u0x7123, %bb2 ], [ u0x8123, %bb3 ], [ u0x9123, %bb4 ]
+  ret i32 %x
+}
+
+; Same as @truncatedint_shift_nsw, but the return type is i16 so the NSW flag shouldn't be set on shl
+define i16 @truncatedint_shift_not_nsw(i32 %c) {
+; CHECK-LABEL: @truncatedint_shift_not_nsw(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i16], ptr @switch.table.truncatedint_shift_not_nsw, i32 0, i32 [[C:%.*]]
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i16, ptr [[SWITCH_GEP]], align 2
+; CHECK-NEXT:    ret i16 [[SWITCH_LOAD]]
+;
+entry:
+  switch i32 %c, label %sw.default [
+  i32 0, label %bb0
+  i32 1, label %bb1
+  i32 2, label %bb2
+  i32 3, label %bb3
+  i32 4, label %bb4
+  ]
+
+sw.default: unreachable
+bb0: br label %return
+bb1: br label %return
+bb2: br label %return
+bb3: br label %return
+bb4: br label %return
+
+return:
+  %x = phi i16 [ u0x2123, %bb0 ], [ u0x3123, %bb1 ], [ u0x7123, %bb2 ], [ u0x8123, %bb3 ], [ u0x9123, %bb4 ]
+  ret i16 %x
+}
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table_big.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table_big.ll
index 7988e3057a2c23..e5e7d916cfdd9b 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table_big.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table_big.ll
@@ -20,10 +20,10 @@ define i32 @reachable_default_dense_0to31(i32 %x, i32 %y) {
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
 ; CHECK:       switch.lookup:
 ; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [32 x i32], ptr @switch.table.reachable_default_dense_0to31, i32 0, i32 [[X]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
 ; CHECK-NEXT:    br label [[RETURN]]
 ; CHECK:       return:
-; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ [[Y:%.*]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ [[SWITCH_TRUNCATEDINT_CAST]], [[SWITCH_LOOKUP]] ], [ [[Y:%.*]], [[ENTRY:%.*]] ]
 ; CHECK-NEXT:    ret i32 [[RES]]
 ;
 entry:
@@ -83,8 +83,8 @@ define i32 @unreachable_default_dense_0to31(i32 %x, i32 %y) {
 ; CHECK-LABEL: @unreachable_default_dense_0to31(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [32 x i32], ptr @switch.table.unreachable_default_dense_0to31, i32 0, i32 [[X:%.*]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
-; CHECK-NEXT:    ret i32 [[SWITCH_LOAD]]
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    ret i32 [[SWITCH_TRUNCATEDINT_CAST]]
 ;
 entry:
   switch i32 %x, label %sw.default [
@@ -150,10 +150,10 @@ define i32 @reachable_default_holes_0to31(i32 %x, i32 %y) {
 ; CHECK-NEXT:    br i1 [[SWITCH_LOBIT]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN]]
 ; CHECK:       switch.lookup:
 ; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [32 x i32], ptr @switch.table.reachable_default_holes_0to31, i32 0, i32 [[X]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
 ; CHECK-NEXT:    br label [[RETURN]]
 ; CHECK:       return:
-; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ [[Y:%.*]], [[SWITCH_HOLE_CHECK]] ], [ [[Y]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ [[SWITCH_TRUNCATEDINT_CAST]], [[SWITCH_LOOKUP]] ], [ [[Y:%.*]], [[SWITCH_HOLE_CHECK]] ], [ [[Y]], [[ENTRY:%.*]] ]
 ; CHECK-NEXT:    ret i32 [[RES]]
 ;
 entry:
@@ -207,8 +207,8 @@ define i32 @unreachable_default_holes_0to31(i32 %x, i32 %y) {
 ; CHECK-LABEL: @unreachable_default_holes_0to31(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [32 x i32], ptr @switch.table.unreachable_default_holes_0to31, i32 0, i32 [[X:%.*]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
-; CHECK-NEXT:    ret i32 [[SWITCH_LOAD]]
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    ret i32 [[SWITCH_TRUNCATEDINT_CAST]]
 ;
 entry:
   switch i32 %x, label %sw.default [
@@ -264,10 +264,10 @@ define i32 @reachable_default_dense_0to32(i32 %x, i32 %y) {
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
 ; CHECK:       switch.lookup:
 ; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [33 x i32], ptr @switch.table.reachable_default_dense_0to32, i32 0, i32 [[X]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
 ; CHECK-NEXT:    br label [[RETURN]]
 ; CHECK:       return:
-; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ [[Y:%.*]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ [[SWITCH_TRUNCATEDINT_CAST]], [[SWITCH_LOOKUP]] ], [ [[Y:%.*]], [[ENTRY:%.*]] ]
 ; CHECK-NEXT:    ret i32 [[RES]]
 ;
 entry:
@@ -328,8 +328,8 @@ define i32 @unreachable_default_dense_0to32(i32 %x, i32 %y) {
 ; CHECK-LABEL: @unreachable_default_dense_0to32(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [33 x i32], ptr @switch.table.unreachable_default_dense_0to32, i32 0, i32 [[X:%.*]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
-; CHECK-NEXT:    ret i32 [[SWITCH_LOAD]]
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    ret i32 [[SWITCH_TRUNCATEDINT_CAST]]
 ;
 entry:
   switch i32 %x, label %sw.default [
@@ -491,8 +491,8 @@ define i32 @unreachable_default_holes_0to32(i32 %x, i32 %y) {
 ; CHECK-LABEL: @unreachable_default_holes_0to32(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [33 x i32], ptr @switch.table.unreachable_default_holes_0to32, i32 0, i32 [[X:%.*]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
-; CHECK-NEXT:    ret i32 [[SWITCH_LOAD]]
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    ret i32 [[SWITCH_TRUNCATEDINT_CAST]]
 ;
 entry:
   switch i32 %x, label %sw.default [

>From 3c0ec21254739fa0051f6cc1fb151237bb0e29d2 Mon Sep 17 00:00:00 2001
From: DaPorkchop_ <daporkchop at daporkchop.net>
Date: Sun, 22 Dec 2024 13:23:26 +0100
Subject: [PATCH 2/2] [SimplifyCFG] Truncate integer values in switch lookup
 tables if possible

Real-world switches often return integer values in a much smaller range than the actual range of the integer type being returned. This change enables us to detect when all integer values in a switch lookup table only differ from each other in a smaller subset of the possible bit positions, truncate the lookup table elements to a narrower width and extend them at runtime.

This has two main benefits:
- Reduces the memory footprint of lookup tables without additional runtime overhead (most architectures have zero-extending widening load instructions), resulting in smaller executable sizes and less cache pollution
- Makes a many more lookup tables small enough to fit into a bitmap, eliminating the need for any loads
---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp     | 160 ++++++++++++++++++
 .../SimplifyCFG/ARM/switch-to-lookup-table.ll |   2 +-
 .../Hexagon/switch-to-lookup-table.ll         |   5 +-
 .../RISCV/switch-of-powers-of-two.ll          |   7 +-
 .../SimplifyCFG/X86/switch-covered-bug.ll     |   8 +-
 .../SimplifyCFG/X86/switch-table-bug.ll       |   5 +-
 .../X86/switch-to-lookup-large-types.ll       |  14 +-
 .../SimplifyCFG/X86/switch_to_lookup_table.ll | 106 +++++++-----
 .../X86/switch_to_lookup_table_big.ll         |  49 +++---
 .../switch-dead-default-lookup-table.ll       |   7 +-
 .../Transforms/SimplifyCFG/switch_mask.ll     |   7 +-
 11 files changed, 282 insertions(+), 88 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 17f4b396f753b4..7e6c87d4a6bb1c 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -196,6 +196,8 @@ static cl::opt<unsigned> MaxSwitchCasesPerResult(
 STATISTIC(NumBitMaps, "Number of switch instructions turned into bitmaps");
 STATISTIC(NumLinearMaps,
           "Number of switch instructions turned into linear mapping");
+STATISTIC(NumTruncatedInts, "Number of switch instructions turned into lookup "
+                            "tables with a truncated value");
 STATISTIC(NumLookupTables,
           "Number of switch instructions turned into lookup tables");
 STATISTIC(
@@ -6486,6 +6488,13 @@ class SwitchLookupTable {
     // shift and mask operations.
     BitMapKind,
 
+    // For tables with integer elements which only differ in a small subset
+    // of their bits, we can truncate the values to a smaller type to discard
+    // the bits which are the same for all values, saving memory. Values are
+    // retrieved by retrieving the truncated value from a lookup table, then
+    // extending and OR-ing to re-construct the original values.
+    TruncatedIntKind,
+
     // The table is stored as an array of values. Values are retrieved by load
     // instructions from the table.
     ArrayKind
@@ -6503,6 +6512,14 @@ class SwitchLookupTable {
   ConstantInt *LinearMultiplier = nullptr;
   bool LinearMapValWrapped = false;
 
+  // For TruncatedIntKind, these are the truncated lookup table and the
+  // constants used to reconstruct original values from their truncated forms.
+  std::unique_ptr<SwitchLookupTable> TruncatedLookupTable = nullptr;
+  IntegerType *TruncatedOrigTy = nullptr;
+  ConstantInt *TruncatedShift = nullptr;
+  ConstantInt *TruncatedMask = nullptr;
+  bool TruncatedValWrapped = false;
+
   // For ArrayKind, this is the array.
   GlobalVariable *Array = nullptr;
 };
@@ -6622,6 +6639,132 @@ SwitchLookupTable::SwitchLookupTable(
     return;
   }
 
+  // Check if we can truncate the value to a smaller form by discarding leading
+  // and trailing bits which are the same for all values.
+  if (isa<IntegerType>(ValueType)) {
+    IntegerType *IT = cast<IntegerType>(ValueType);
+    unsigned OrigWidth = IT->getBitWidth();
+
+    // Figure out which bits are always the same.
+    APInt AlwaysOneBits = APInt::getAllOnes(OrigWidth);
+    APInt AlwaysZeroBits = APInt::getAllOnes(OrigWidth);
+    for (Constant *TableEntry : TableContents) {
+      // Each entry in the lookup table may be a constant integer, otherwise
+      // it must be undefined (Undef or poison) in which case we can simply
+      // skip it.
+      if (isa<ConstantInt>(TableEntry)) {
+        const APInt &Val = cast<ConstantInt>(TableEntry)->getValue();
+        AlwaysOneBits &= Val;
+        AlwaysZeroBits &= ~Val;
+      }
+    }
+    assert((AlwaysOneBits & AlwaysZeroBits).isZero() &&
+           "A bit cannot be both zero and one in every case");
+    APInt NotChangingBits = AlwaysOneBits | AlwaysZeroBits;
+
+    unsigned DiscardedHighBits = NotChangingBits.countLeadingOnes();
+    unsigned DiscardedLowBits = NotChangingBits.countTrailingOnes();
+    unsigned TotalDiscardedBits = DiscardedHighBits + DiscardedLowBits;
+    unsigned TruncatedWidth = OrigWidth - TotalDiscardedBits;
+
+    // If the original type's width is a power of two, we want to ensure
+    // that the truncated size is also a power of two. Otherwise, the higher
+    // cost of indexing into the array with non-power-of-two-sized elements is
+    // probably going to cancel out any benefits we might get from making the
+    // table smaller.
+    if (has_single_bit(OrigWidth)) {
+      unsigned OldTruncatedWidth = TruncatedWidth;
+      TruncatedWidth = bit_ceil(TruncatedWidth);
+
+      // If the truncated size increased, we need to decrease DiscardedHighBits
+      // and/or DiscardedLowBits accordingly.
+      unsigned TruncatedWidthIncrease = TruncatedWidth - OldTruncatedWidth;
+      if (TruncatedWidthIncrease) {
+        TotalDiscardedBits -= TruncatedWidthIncrease;
+
+        // Prioritize decreasing the number of least significant bits discarded:
+        // if we can get this to 0, we won't need to shift left
+        unsigned LowBitsDecrease =
+            std::min(TruncatedWidthIncrease, DiscardedLowBits);
+        DiscardedLowBits -= LowBitsDecrease;
+
+        unsigned HighBitsDecrease = std::min(
+            TruncatedWidthIncrease - LowBitsDecrease, DiscardedHighBits);
+        DiscardedHighBits -= HighBitsDecrease;
+
+        assert(TruncatedWidthIncrease == LowBitsDecrease + HighBitsDecrease);
+
+        assert(DiscardedHighBits + DiscardedLowBits == TotalDiscardedBits &&
+               TotalDiscardedBits + TruncatedWidth == OrigWidth);
+      }
+    }
+
+    // We'll only truncate the values if the truncated values would be less than
+    // half the size of the original values, as otherwise there's unlikely to be
+    // any benefit.
+    if (TruncatedWidth <= OrigWidth / 2) {
+      IntegerType *TruncatedTy =
+          IntegerType::get(M.getContext(), TruncatedWidth);
+
+      PoisonValue *TruncatedPoison = PoisonValue::get(TruncatedTy);
+
+      // Truncate the values and build a new lookup table containing them
+      SmallVector<std::pair<ConstantInt *, Constant *>, 64> TruncatedValues(
+          TableSize);
+      for (uint64_t I = 0; I < TableSize; ++I) {
+        ConstantInt *CaseVal =
+            ConstantInt::get(M.getContext(), Offset->getValue() + I);
+        Constant *CaseRes = TableContents[I];
+
+        Constant *TruncatedCaseRes;
+        if (ConstantInt *IntCaseRes = dyn_cast<ConstantInt>(CaseRes)) {
+          APInt TruncatedVal = IntCaseRes->getValue().extractBits(
+              TruncatedWidth, DiscardedLowBits);
+          TruncatedCaseRes = ConstantInt::get(M.getContext(), TruncatedVal);
+        } else if (isa<PoisonValue>(CaseRes)) {
+          TruncatedCaseRes = TruncatedPoison;
+        } else {
+          assert(isa<UndefValue>(CaseRes));
+          // To avoid making a call to the deprecated
+          // 'UndefValue ::get(TruncatedTy)', we'll simply replace undefined
+          // table entries with zero.
+          TruncatedCaseRes =
+              ConstantInt::get(M.getContext(), APInt::getZero(TruncatedWidth));
+        }
+
+        assert(TruncatedCaseRes->getType() == TruncatedTy);
+
+        TruncatedValues[I] = {CaseVal, TruncatedCaseRes};
+      }
+
+      // Recursively construct a new lookup table with the truncated values.
+      // This enables us to use more efficient table kinds which weren't
+      // possible originally, such as a bitmap.
+      TruncatedLookupTable = std::make_unique<SwitchLookupTable>(
+          M, TableSize, Offset, TruncatedValues, TruncatedPoison, DL,
+          ("switch.truncated." + FuncName).str());
+      TruncatedOrigTy = IT;
+
+      if (DiscardedLowBits > 0) {
+        TruncatedShift = ConstantInt::get(IT, DiscardedLowBits);
+        TruncatedValWrapped = DiscardedHighBits == 0;
+      }
+
+      // The mask we OR on at the end consists of all the bits which are always
+      // one, excluding the bits which fit into the truncated value and didn't
+      // need to be changed.
+      APInt Mask =
+          AlwaysOneBits & ~APInt::getBitsSet(OrigWidth, DiscardedLowBits,
+                                             OrigWidth - DiscardedHighBits);
+      if (!Mask.isZero())
+        TruncatedMask = ConstantInt::get(M.getContext(), Mask);
+
+      Kind = TruncatedIntKind;
+      ++NumTruncatedInts;
+      return;
+    }
+  }
+
   // Store the table in an array.
   ArrayType *ArrayTy = ArrayType::get(ValueType, TableSize);
   Constant *Initializer = ConstantArray::get(ArrayTy, TableContents);
@@ -6677,6 +6820,23 @@ Value *SwitchLookupTable::buildLookup(Value *Index, IRBuilder<> &Builder) {
     // Mask off.
     return Builder.CreateTrunc(DownShifted, BitMapElementTy, "switch.masked");
   }
+  case TruncatedIntKind: {
+    // Load the truncated value from the lookup table
+    Value *TruncatedVal = TruncatedLookupTable->buildLookup(Index, Builder);
+
+    // Derive the original value from the truncated version
+    Value *Result = Builder.CreateIntCast(TruncatedVal, TruncatedOrigTy, false,
+                                          "switch.truncatedint.cast");
+    if (TruncatedShift)
+      Result =
+          Builder.CreateShl(Result, TruncatedShift, "switch.truncatedint.shift",
+                            /*HasNUW =*/true,
+                            /*HasNSW =*/!TruncatedValWrapped);
+    if (TruncatedMask)
+      Result =
+          Builder.CreateOr(Result, TruncatedMask, "switch.truncatedint.mask");
+    return Result;
+  }
   case ArrayKind: {
     // Make sure the table index will not overflow when treated as signed.
     IntegerType *IT = cast<IntegerType>(Index->getType());
diff --git a/llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll b/llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll
index 6def8f4eeb0891..8a910f30601112 100644
--- a/llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll
+++ b/llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll
@@ -10,7 +10,7 @@
 ; RUN: opt -S -passes='simplifycfg<switch-to-lookup>' -mtriple=arm -relocation-model=rwpi      < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
 ; RUN: opt -S -passes='simplifycfg<switch-to-lookup>' -mtriple=arm -relocation-model=ropi-rwpi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
 
-; CHECK:       @{{.*}} = private unnamed_addr constant [3 x i32] [i32 1234, i32 5678, i32 15532]
+; CHECK:       @{{.*}} = private unnamed_addr constant [3 x i16] [i16 1234, i16 5678, i16 15532]
 ; ENABLE:      @{{.*}} = private unnamed_addr constant [3 x ptr] [ptr @c1, ptr @c2, ptr @c3]
 ; DISABLE-NOT: @{{.*}} = private unnamed_addr constant [3 x ptr] [ptr @c1, ptr @c2, ptr @c3]
 ; ENABLE:      @{{.*}} = private unnamed_addr constant [3 x ptr] [ptr @g1, ptr @g2, ptr @g3]
diff --git a/llvm/test/Transforms/SimplifyCFG/Hexagon/switch-to-lookup-table.ll b/llvm/test/Transforms/SimplifyCFG/Hexagon/switch-to-lookup-table.ll
index 349a18148460f4..9975c051d71270 100644
--- a/llvm/test/Transforms/SimplifyCFG/Hexagon/switch-to-lookup-table.ll
+++ b/llvm/test/Transforms/SimplifyCFG/Hexagon/switch-to-lookup-table.ll
@@ -13,8 +13,9 @@ define i32 @foo(i32 %x) #0 section ".tcm_text" {
 ; ENABLE-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 6
 ; ENABLE-NEXT:    br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
 ; ENABLE:       switch.lookup:
-; ENABLE-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds nuw [6 x i32], ptr @switch.table.foo, i32 0, i32 [[X]]
-; ENABLE-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; ENABLE-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds nuw [6 x i8], ptr @switch.table.switch.truncated.foo, i32 0, i32 [[X]]
+; ENABLE-NEXT:    [[SWITCH_LOAD1:%.*]] = load i8, ptr [[SWITCH_GEP]], align 1
+; ENABLE-NEXT:    [[SWITCH_LOAD:%.*]] = zext i8 [[SWITCH_LOAD1]] to i32
 ; ENABLE-NEXT:    br label [[RETURN]]
 ; ENABLE:       return:
 ; ENABLE-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 19, [[ENTRY:%.*]] ]
diff --git a/llvm/test/Transforms/SimplifyCFG/RISCV/switch-of-powers-of-two.ll b/llvm/test/Transforms/SimplifyCFG/RISCV/switch-of-powers-of-two.ll
index 2ac94afd959105..f1a51bdfe331a8 100644
--- a/llvm/test/Transforms/SimplifyCFG/RISCV/switch-of-powers-of-two.ll
+++ b/llvm/test/Transforms/SimplifyCFG/RISCV/switch-of-powers-of-two.ll
@@ -34,8 +34,11 @@ define i32 @switch_of_powers(i32 %x) {
 ; RV64ZBB-LABEL: @switch_of_powers(
 ; RV64ZBB-NEXT:  entry:
 ; RV64ZBB-NEXT:    [[TMP0:%.*]] = call i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true)
-; RV64ZBB-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], ptr @switch.table.switch_of_powers, i32 0, i32 [[TMP0]]
-; RV64ZBB-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; RV64ZBB-NEXT:    [[SWITCH_CAST:%.*]] = zext i32 [[TMP0]] to i56
+; RV64ZBB-NEXT:    [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i56 [[SWITCH_CAST]], 8
+; RV64ZBB-NEXT:    [[SWITCH_DOWNSHIFT:%.*]] = lshr i56 11821953350566659, [[SWITCH_SHIFTAMT]]
+; RV64ZBB-NEXT:    [[SWITCH_MASKED:%.*]] = trunc i56 [[SWITCH_DOWNSHIFT]] to i8
+; RV64ZBB-NEXT:    [[SWITCH_LOAD:%.*]] = zext i8 [[SWITCH_MASKED]] to i32
 ; RV64ZBB-NEXT:    ret i32 [[SWITCH_LOAD]]
 ;
 entry:
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll
index cf244e6b63457c..df1425798a219e 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll
@@ -10,9 +10,11 @@ define i64 @test(i3 %arg) {
 ; CHECK-LABEL: @test(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[SWITCH_TABLEIDX:%.*]] = sub i3 [[ARG:%.*]], -4
-; CHECK-NEXT:    [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i4
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [8 x i64], ptr @switch.table.test, i32 0, i4 [[SWITCH_TABLEIDX_ZEXT]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i64, ptr [[SWITCH_GEP]], align 8
+; CHECK-NEXT:    [[SWITCH_CAST:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i32
+; CHECK-NEXT:    [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i32 [[SWITCH_CAST]], 4
+; CHECK-NEXT:    [[SWITCH_DOWNSHIFT:%.*]] = lshr i32 -638023754, [[SWITCH_SHIFTAMT]]
+; CHECK-NEXT:    [[SWITCH_MASKED:%.*]] = trunc i32 [[SWITCH_DOWNSHIFT]] to i4
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = zext i4 [[SWITCH_MASKED]] to i64
 ; CHECK-NEXT:    [[V3:%.*]] = add i64 [[SWITCH_LOAD]], 0
 ; CHECK-NEXT:    ret i64 [[V3]]
 ;
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll
index 37001f4fba2aa8..d32ad9b9351bec 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll
@@ -10,9 +10,8 @@ define i64 @_TFO6reduce1E5toRawfS0_FT_Si(i2) {
 ; CHECK-LABEL: @_TFO6reduce1E5toRawfS0_FT_Si(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TMP0:%.*]], -2
-; CHECK-NEXT:    [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i3
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i64], ptr @switch.table._TFO6reduce1E5toRawfS0_FT_Si, i32 0, i3 [[SWITCH_TABLEIDX_ZEXT]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i64, ptr [[SWITCH_GEP]], align 8
+; CHECK-NEXT:    [[SWITCH_OFFSET:%.*]] = add i2 [[SWITCH_TABLEIDX]], -2
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = zext i2 [[SWITCH_OFFSET]] to i64
 ; CHECK-NEXT:    ret i64 [[SWITCH_LOAD]]
 ;
 entry:
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-large-types.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-large-types.ll
index e188cd8057df2d..b5220844986801 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-large-types.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-large-types.ll
@@ -5,8 +5,8 @@
 target triple = "x86_64-unknown-linux-gnu"
 
 ;.
-; CHECK: @switch.table.switch_to_lookup_i64 = private unnamed_addr constant [3 x i8] c"\03\01\02", align 1
-; CHECK: @switch.table.switch_to_lookup_i128 = private unnamed_addr constant [3 x i8] c"\03\01\02", align 1
+; CHECK: @switch.table.switch.truncated.switch_to_lookup_i64 = private unnamed_addr constant [3 x i2] [i2 -1, i2 1, i2 -2], align 1
+; CHECK: @switch.table.switch.truncated.switch_to_lookup_i128 = private unnamed_addr constant [3 x i2] [i2 -1, i2 1, i2 -2], align 1
 ;.
 define i8 @switch_to_lookup_i64(i64 %x){
 ; CHECK-LABEL: @switch_to_lookup_i64(
@@ -17,8 +17,9 @@ define i8 @switch_to_lookup_i64(i64 %x){
 ; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i8 [ [[SWITCH_LOAD:%.*]], [[SWITCH_LOOKUP]] ], [ 10, [[START:%.*]] ]
 ; CHECK-NEXT:    ret i8 [[COMMON_RET_OP]]
 ; CHECK:       switch.lookup:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i8], ptr @switch.table.switch_to_lookup_i64, i32 0, i64 [[X]]
-; CHECK-NEXT:    [[SWITCH_LOAD]] = load i8, ptr [[SWITCH_GEP]], align 1
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i2], ptr @switch.table.switch.truncated.switch_to_lookup_i64, i32 0, i64 [[X]]
+; CHECK-NEXT:    [[SWITCH_LOAD1:%.*]] = load i2, ptr [[SWITCH_GEP]], align 1
+; CHECK-NEXT:    [[SWITCH_LOAD]] = zext i2 [[SWITCH_LOAD1]] to i8
 ; CHECK-NEXT:    br label [[COMMON_RET]]
 ;
 ; INLINE-LABEL: @switch_to_lookup_i64(
@@ -61,8 +62,9 @@ define i8 @switch_to_lookup_i128(i128 %x){
 ; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i8 [ [[SWITCH_LOAD:%.*]], [[SWITCH_LOOKUP]] ], [ 10, [[START:%.*]] ]
 ; CHECK-NEXT:    ret i8 [[COMMON_RET_OP]]
 ; CHECK:       switch.lookup:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i8], ptr @switch.table.switch_to_lookup_i128, i32 0, i128 [[X]]
-; CHECK-NEXT:    [[SWITCH_LOAD]] = load i8, ptr [[SWITCH_GEP]], align 1
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i2], ptr @switch.table.switch.truncated.switch_to_lookup_i128, i32 0, i128 [[X]]
+; CHECK-NEXT:    [[SWITCH_LOAD1:%.*]] = load i2, ptr [[SWITCH_GEP]], align 1
+; CHECK-NEXT:    [[SWITCH_LOAD]] = zext i2 [[SWITCH_LOAD1]] to i8
 ; CHECK-NEXT:    br label [[COMMON_RET]]
 ;
 ; INLINE-LABEL: @switch_to_lookup_i128(
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
index 2110bd31259f40..ceeb16561dbc6c 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
@@ -27,21 +27,11 @@ target triple = "x86_64-unknown-linux-gnu"
 ; CHECK: @switch.table.char = private unnamed_addr constant [9 x i8] c"7{\00\FF\1B>\01!T", align 1
 ; CHECK: @switch.table.h = private unnamed_addr constant [4 x float] [float 0x40091EB860000000, float 0x3FF3BE76C0000000, float 0x4012449BA0000000, float 0x4001AE1480000000], align 4
 ; CHECK: @switch.table.foostring = private unnamed_addr constant [4 x ptr] [ptr @.str, ptr @.str1, ptr @.str2, ptr @.str3], align 8
-; CHECK: @switch.table.earlyreturncrash = private unnamed_addr constant [4 x i32] [i32 42, i32 9, i32 88, i32 5], align 4
-; CHECK: @switch.table.earlyreturncrash.1 = private unnamed_addr constant [4 x i32] [i32 3, i32 4, i32 1, i32 5], align 4
-; CHECK: @switch.table.large = private unnamed_addr constant [199 x i32] [i32 1, i32 4, i32 9, i32 16, i32 25, i32 36, i32 49, i32 64, i32 81, i32 100, i32 121, i32 144, i32 169, i32 196, i32 225, i32 256, i32 289, i32 342, i32 361, i32 400, i32 441, i32 484, i32 529, i32 576, i32 625, i32 676, i32 729, i32 784, i32 841, i32 900, i32 961, i32 1024, i32 1089, i32 1156, i32 1260, i32 1296, i32 1369, i32 1444, i32 1521, i32 1600, i32 1681, i32 1764, i32 1849, i32 1980, i32 2025, i32 2116, i32 2209, i32 2304, i32 2401, i32 2500, i32 2601, i32 2704, i32 2809, i32 2970, i32 3025, i32 3136, i32 3249, i32 3364, i32 3481, i32 3600, i32 3721, i32 3844, i32 3969, i32 4096, i32 4225, i32 4356, i32 4489, i32 4624, i32 4761, i32 4900, i32 5112, i32 5184, i32 5329, i32 5476, i32 5625, i32 5776, i32 5929, i32 6084, i32 6241, i32 6400, i32 6561, i32 6724, i32 6889, i32 7056, i32 7225, i32 7396, i32 7569, i32 7744, i32 7921, i32 8100, i32 8281, i32 8464, i32 8649, i32 8836, i32 9025, i32 9216, i32 9409, i32 9604, i32 9801, i32 10000, i32 10201, i32 10404, i32 10609, i32 10816, i32 11025, i32 11236, i32 11449, i32 11664, i32 11881, i32 12100, i32 12321, i32 12544, i32 12769, i32 12996, i32 13225, i32 13456, i32 13689, i32 13924, i32 14161, i32 14400, i32 14641, i32 14884, i32 15129, i32 15376, i32 15625, i32 15876, i32 16129, i32 16384, i32 16641, i32 16900, i32 17161, i32 17424, i32 17689, i32 17956, i32 18225, i32 18496, i32 18769, i32 19044, i32 19321, i32 19600, i32 19881, i32 20164, i32 20449, i32 20736, i32 21025, i32 21316, i32 21609, i32 21904, i32 22201, i32 22500, i32 22801, i32 23104, i32 23409, i32 23716, i32 24025, i32 24336, i32 24649, i32 24964, i32 25281, i32 25600, i32 25921, i32 26244, i32 26569, i32 26896, i32 27225, i32 27556, i32 27889, i32 28224, i32 28561, i32 28900, i32 29241, i32 29584, i32 29929, i32 30276, i32 30625, i32 30976, i32 31329, i32 31684, i32 32041, i32 32400, i32 32761, i32 33124, i32 33489, i32 33856, i32 34225, i32 34596, i32 34969, i32 35344, i32 35721, i32 36100, i32 36481, i32 36864, i32 37249, i32 37636, i32 38025, i32 38416, i32 38809, i32 39204, i32 39601], align 4
+; CHECK: @switch.table.switch.truncated.large = private unnamed_addr constant [199 x i16] [i16 1, i16 4, i16 9, i16 16, i16 25, i16 36, i16 49, i16 64, i16 81, i16 100, i16 121, i16 144, i16 169, i16 196, i16 225, i16 256, i16 289, i16 342, i16 361, i16 400, i16 441, i16 484, i16 529, i16 576, i16 625, i16 676, i16 729, i16 784, i16 841, i16 900, i16 961, i16 1024, i16 1089, i16 1156, i16 1260, i16 1296, i16 1369, i16 1444, i16 1521, i16 1600, i16 1681, i16 1764, i16 1849, i16 1980, i16 2025, i16 2116, i16 2209, i16 2304, i16 2401, i16 2500, i16 2601, i16 2704, i16 2809, i16 2970, i16 3025, i16 3136, i16 3249, i16 3364, i16 3481, i16 3600, i16 3721, i16 3844, i16 3969, i16 4096, i16 4225, i16 4356, i16 4489, i16 4624, i16 4761, i16 4900, i16 5112, i16 5184, i16 5329, i16 5476, i16 5625, i16 5776, i16 5929, i16 6084, i16 6241, i16 6400, i16 6561, i16 6724, i16 6889, i16 7056, i16 7225, i16 7396, i16 7569, i16 7744, i16 7921, i16 8100, i16 8281, i16 8464, i16 8649, i16 8836, i16 9025, i16 9216, i16 9409, i16 9604, i16 9801, i16 10000, i16 10201, i16 10404, i16 10609, i16 10816, i16 11025, i16 11236, i16 11449, i16 11664, i16 11881, i16 12100, i16 12321, i16 12544, i16 12769, i16 12996, i16 13225, i16 13456, i16 13689, i16 13924, i16 14161, i16 14400, i16 14641, i16 14884, i16 15129, i16 15376, i16 15625, i16 15876, i16 16129, i16 16384, i16 16641, i16 16900, i16 17161, i16 17424, i16 17689, i16 17956, i16 18225, i16 18496, i16 18769, i16 19044, i16 19321, i16 19600, i16 19881, i16 20164, i16 20449, i16 20736, i16 21025, i16 21316, i16 21609, i16 21904, i16 22201, i16 22500, i16 22801, i16 23104, i16 23409, i16 23716, i16 24025, i16 24336, i16 24649, i16 24964, i16 25281, i16 25600, i16 25921, i16 26244, i16 26569, i16 26896, i16 27225, i16 27556, i16 27889, i16 28224, i16 28561, i16 28900, i16 29241, i16 29584, i16 29929, i16 30276, i16 30625, i16 30976, i16 31329, i16 31684, i16 32041, i16 32400, i16 32761, i16 -32412, i16 -32047, i16 -31680, i16 -31311, i16 -30940, i16 -30567, i16 -30192, i16 -29815, i16 -29436, i16 -29055, i16 -28672, i16 -28287, i16 -27900, i16 -27511, i16 -27120, i16 -26727, i16 -26332, i16 -25935], align 2
 ; CHECK: @switch.table.cprop = private unnamed_addr constant [7 x i32] [i32 5, i32 42, i32 126, i32 -452, i32 128, i32 6, i32 7], align 4
 ; CHECK: @switch.table.unreachable_case = private unnamed_addr constant [9 x i32] [i32 0, i32 0, i32 0, i32 2, i32 -1, i32 1, i32 1, i32 1, i32 1], align 4
-; CHECK: @switch.table.unreachable_default = private unnamed_addr constant [4 x i32] [i32 42, i32 52, i32 1, i32 2], align 4
 ; CHECK: @switch.table.nodefaultnoholes = private unnamed_addr constant [4 x i32] [i32 55, i32 123, i32 0, i32 -1], align 4
 ; CHECK: @switch.table.nodefaultwithholes = private unnamed_addr constant [6 x i32] [i32 55, i32 123, i32 0, i32 -1, i32 55, i32 -1], align 4
-; CHECK: @switch.table.threecases = private unnamed_addr constant [3 x i32] [i32 10, i32 7, i32 5], align 4
-; CHECK: @switch.table.covered_switch_with_bit_tests = private unnamed_addr constant [8 x i32] [i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 1, i32 1], align 4
-; CHECK: @switch.table.signed_overflow1 = private unnamed_addr constant [4 x i32] [i32 3333, i32 4444, i32 1111, i32 2222], align 4
-; CHECK: @switch.table.signed_overflow2 = private unnamed_addr constant [4 x i32] [i32 3333, i32 4444, i32 2222, i32 2222], align 4
-; CHECK: @switch.table.truncatedint_shift_mask = private unnamed_addr constant [4 x i32] [i32 33578, i32 33594, i32 33658, i32 33626], align 4
-; CHECK: @switch.table.truncatedint_shift_nsw = private unnamed_addr constant [5 x i32] [i32 8483, i32 12579, i32 28963, i32 33059, i32 37155], align 4
-; CHECK: @switch.table.truncatedint_shift_not_nsw = private unnamed_addr constant [5 x i16] [i16 8483, i16 12579, i16 28963, i16 -32477, i16 -28381], align 2
 ;.
 define i32 @f(i32 %c) {
 ; CHECK-LABEL: @f(
@@ -221,10 +211,15 @@ define i32 @earlyreturncrash(i32 %x)  {
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[SW_EPILOG:%.*]]
 ; CHECK:       switch.lookup:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.earlyreturncrash, i32 0, i32 [[X]]
-; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
-; CHECK-NEXT:    [[SWITCH_GEP1:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.earlyreturncrash.1, i32 0, i32 [[X]]
-; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST4:%.*]] = load i32, ptr [[SWITCH_GEP1]], align 4
+; CHECK-NEXT:    [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i32 [[X]], 8
+; CHECK-NEXT:    [[SWITCH_DOWNSHIFT:%.*]] = lshr i32 89655594, [[SWITCH_SHIFTAMT]]
+; CHECK-NEXT:    [[SWITCH_MASKED:%.*]] = trunc i32 [[SWITCH_DOWNSHIFT]] to i8
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i8 [[SWITCH_MASKED]] to i32
+; CHECK-NEXT:    [[SWITCH_CAST:%.*]] = trunc i32 [[X]] to i16
+; CHECK-NEXT:    [[SWITCH_SHIFTAMT1:%.*]] = mul nuw nsw i16 [[SWITCH_CAST]], 4
+; CHECK-NEXT:    [[SWITCH_DOWNSHIFT2:%.*]] = lshr i16 20803, [[SWITCH_SHIFTAMT1]]
+; CHECK-NEXT:    [[SWITCH_MASKED3:%.*]] = trunc i16 [[SWITCH_DOWNSHIFT2]] to i4
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST4:%.*]] = zext i4 [[SWITCH_MASKED3]] to i32
 ; CHECK-NEXT:    br label [[SW_EPILOG]]
 ; CHECK:       sw.epilog:
 ; CHECK-NEXT:    [[A_0:%.*]] = phi i32 [ [[SWITCH_TRUNCATEDINT_CAST]], [[SWITCH_LOOKUP]] ], [ 7, [[ENTRY:%.*]] ]
@@ -404,8 +399,9 @@ define i32 @large(i32 %x) {
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 199
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
 ; CHECK:       switch.lookup:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [199 x i32], ptr @switch.table.large, i32 0, i32 [[SWITCH_TABLEIDX]]
-; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [199 x i16], ptr @switch.table.switch.truncated.large, i32 0, i32 [[SWITCH_TABLEIDX]]
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i16, ptr [[SWITCH_GEP]], align 2
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i16 [[SWITCH_LOAD]] to i32
 ; CHECK-NEXT:    br label [[RETURN]]
 ; CHECK:       return:
 ; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SWITCH_TRUNCATEDINT_CAST]], [[SWITCH_LOOKUP]] ]
@@ -920,8 +916,10 @@ return:
 define i32 @unreachable_default(i32 %x)  {
 ; CHECK-LABEL: @unreachable_default(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.unreachable_default, i32 0, i32 [[X:%.*]]
-; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i32 [[X:%.*]], 8
+; CHECK-NEXT:    [[SWITCH_DOWNSHIFT:%.*]] = lshr i32 33633322, [[SWITCH_SHIFTAMT]]
+; CHECK-NEXT:    [[SWITCH_MASKED:%.*]] = trunc i32 [[SWITCH_DOWNSHIFT]] to i8
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i8 [[SWITCH_MASKED]] to i32
 ; CHECK-NEXT:    ret i32 [[SWITCH_TRUNCATEDINT_CAST]]
 ;
 entry:
@@ -1101,13 +1099,12 @@ define i32 @threecases(i32 %c) {
 ; CHECK-LABEL: @threecases(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[C:%.*]], 3
-; CHECK-NEXT:    br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
-; CHECK:       switch.lookup:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i32], ptr @switch.table.threecases, i32 0, i32 [[C]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
-; CHECK-NEXT:    br label [[RETURN]]
-; CHECK:       return:
-; CHECK-NEXT:    [[X:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 3, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[SWITCH_CAST:%.*]] = trunc i32 [[C]] to i12
+; CHECK-NEXT:    [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i12 [[SWITCH_CAST]], 4
+; CHECK-NEXT:    [[SWITCH_DOWNSHIFT:%.*]] = lshr i12 1402, [[SWITCH_SHIFTAMT]]
+; CHECK-NEXT:    [[SWITCH_MASKED:%.*]] = trunc i12 [[SWITCH_DOWNSHIFT]] to i4
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i4 [[SWITCH_MASKED]] to i32
+; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_TRUNCATEDINT_CAST]], i32 3
 ; CHECK-NEXT:    ret i32 [[X]]
 ;
 entry:
@@ -1560,14 +1557,12 @@ define i32 @covered_switch_with_bit_tests(i3) {
 ; CHECK-NEXT:    [[SWITCH_MASKINDEX:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i8
 ; CHECK-NEXT:    [[SWITCH_SHIFTED:%.*]] = lshr i8 -61, [[SWITCH_MASKINDEX]]
 ; CHECK-NEXT:    [[SWITCH_LOBIT:%.*]] = trunc i8 [[SWITCH_SHIFTED]] to i1
-; CHECK-NEXT:    br i1 [[SWITCH_LOBIT]], label [[SWITCH_LOOKUP:%.*]], label [[L6:%.*]]
-; CHECK:       switch.lookup:
-; CHECK-NEXT:    [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i4
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [8 x i32], ptr @switch.table.covered_switch_with_bit_tests, i32 0, i4 [[SWITCH_TABLEIDX_ZEXT]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
-; CHECK-NEXT:    br label [[L6]]
-; CHECK:       l6:
-; CHECK-NEXT:    [[R:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ]
+; CHECK-NEXT:    [[SWITCH_CAST:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i16
+; CHECK-NEXT:    [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i16 [[SWITCH_CAST]], 2
+; CHECK-NEXT:    [[SWITCH_DOWNSHIFT:%.*]] = lshr i16 23210, [[SWITCH_SHIFTAMT]]
+; CHECK-NEXT:    [[SWITCH_MASKED:%.*]] = trunc i16 [[SWITCH_DOWNSHIFT]] to i2
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i2 [[SWITCH_MASKED]] to i32
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[SWITCH_LOBIT]], i32 [[SWITCH_TRUNCATEDINT_CAST]], i32 0
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
 entry:
@@ -1715,9 +1710,11 @@ define i32 @signed_overflow1(i8 %n) {
 ; CHECK-NEXT:  start:
 ; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i8 [[N:%.*]] to i2
 ; CHECK-NEXT:    [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TRUNC]], -2
-; CHECK-NEXT:    [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i3
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.signed_overflow1, i32 0, i3 [[SWITCH_TABLEIDX_ZEXT]]
-; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_CAST:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i64
+; CHECK-NEXT:    [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i64 [[SWITCH_CAST]], 16
+; CHECK-NEXT:    [[SWITCH_DOWNSHIFT:%.*]] = lshr i64 625442170250988805, [[SWITCH_SHIFTAMT]]
+; CHECK-NEXT:    [[SWITCH_MASKED:%.*]] = trunc i64 [[SWITCH_DOWNSHIFT]] to i16
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i16 [[SWITCH_MASKED]] to i32
 ; CHECK-NEXT:    ret i32 [[SWITCH_TRUNCATEDINT_CAST]]
 ;
 start:
@@ -1751,9 +1748,11 @@ define i32 @signed_overflow2(i8 %n) {
 ; CHECK-NEXT:  start:
 ; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i8 [[N:%.*]] to i2
 ; CHECK-NEXT:    [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TRUNC]], -2
-; CHECK-NEXT:    [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i3
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.signed_overflow2, i32 0, i3 [[SWITCH_TABLEIDX_ZEXT]]
-; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_CAST:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i64
+; CHECK-NEXT:    [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i64 [[SWITCH_CAST]], 16
+; CHECK-NEXT:    [[SWITCH_DOWNSHIFT:%.*]] = lshr i64 625446941959654661, [[SWITCH_SHIFTAMT]]
+; CHECK-NEXT:    [[SWITCH_MASKED:%.*]] = trunc i64 [[SWITCH_DOWNSHIFT]] to i16
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i16 [[SWITCH_MASKED]] to i32
 ; CHECK-NEXT:    ret i32 [[SWITCH_TRUNCATEDINT_CAST]]
 ;
 start:
@@ -2191,8 +2190,13 @@ return:                                           ; preds = %sw.default, %entry,
 define i32 @truncatedint_shift_mask(i32 %c) {
 ; CHECK-LABEL: @truncatedint_shift_mask(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.truncatedint_shift_mask, i32 0, i32 [[C:%.*]]
-; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_MASK:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_CAST:%.*]] = trunc i32 [[C:%.*]] to i16
+; CHECK-NEXT:    [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i16 [[SWITCH_CAST]], 4
+; CHECK-NEXT:    [[SWITCH_DOWNSHIFT:%.*]] = lshr i16 -16523, [[SWITCH_SHIFTAMT]]
+; CHECK-NEXT:    [[SWITCH_MASKED:%.*]] = trunc i16 [[SWITCH_DOWNSHIFT]] to i4
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i4 [[SWITCH_MASKED]] to i32
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_SHIFT:%.*]] = shl nuw nsw i32 [[SWITCH_TRUNCATEDINT_CAST]], 3
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_MASK:%.*]] = or i32 [[SWITCH_TRUNCATEDINT_SHIFT]], 33538
 ; CHECK-NEXT:    ret i32 [[SWITCH_TRUNCATEDINT_MASK]]
 ;
 entry:
@@ -2217,8 +2221,13 @@ return:
 define i32 @truncatedint_shift_nsw(i32 %c) {
 ; CHECK-LABEL: @truncatedint_shift_nsw(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.truncatedint_shift_nsw, i32 0, i32 [[C:%.*]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_CAST:%.*]] = trunc i32 [[C:%.*]] to i20
+; CHECK-NEXT:    [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i20 [[SWITCH_CAST]], 4
+; CHECK-NEXT:    [[SWITCH_DOWNSHIFT:%.*]] = lshr i20 -424142, [[SWITCH_SHIFTAMT]]
+; CHECK-NEXT:    [[SWITCH_MASKED:%.*]] = trunc i20 [[SWITCH_DOWNSHIFT]] to i4
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i4 [[SWITCH_MASKED]] to i32
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_SHIFT:%.*]] = shl nuw nsw i32 [[SWITCH_TRUNCATEDINT_CAST]], 12
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = or i32 [[SWITCH_TRUNCATEDINT_SHIFT]], 291
 ; CHECK-NEXT:    ret i32 [[SWITCH_LOAD]]
 ;
 entry:
@@ -2246,8 +2255,13 @@ return:
 define i16 @truncatedint_shift_not_nsw(i32 %c) {
 ; CHECK-LABEL: @truncatedint_shift_not_nsw(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i16], ptr @switch.table.truncatedint_shift_not_nsw, i32 0, i32 [[C:%.*]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i16, ptr [[SWITCH_GEP]], align 2
+; CHECK-NEXT:    [[SWITCH_CAST:%.*]] = trunc i32 [[C:%.*]] to i20
+; CHECK-NEXT:    [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i20 [[SWITCH_CAST]], 4
+; CHECK-NEXT:    [[SWITCH_DOWNSHIFT:%.*]] = lshr i20 -424142, [[SWITCH_SHIFTAMT]]
+; CHECK-NEXT:    [[SWITCH_MASKED:%.*]] = trunc i20 [[SWITCH_DOWNSHIFT]] to i4
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i4 [[SWITCH_MASKED]] to i16
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_SHIFT:%.*]] = shl nuw i16 [[SWITCH_TRUNCATEDINT_CAST]], 12
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = or i16 [[SWITCH_TRUNCATEDINT_SHIFT]], 291
 ; CHECK-NEXT:    ret i16 [[SWITCH_LOAD]]
 ;
 entry:
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table_big.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table_big.ll
index e5e7d916cfdd9b..aebd66245d8bd4 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table_big.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table_big.ll
@@ -5,13 +5,13 @@ target triple = "i386-pc-linux-gnu"
 
 ; A dense switch with a reachable default case should be optimized into a lookup table with a bounds check
 ;.
-; CHECK: @switch.table.reachable_default_dense_0to31 = private unnamed_addr constant [32 x i32] [i32 0, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1], align 4
-; CHECK: @switch.table.unreachable_default_dense_0to31 = private unnamed_addr constant [32 x i32] [i32 0, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1], align 4
-; CHECK: @switch.table.reachable_default_holes_0to31 = private unnamed_addr constant [32 x i32] [i32 0, i32 7, i32 6, i32 0, i32 4, i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 0, i32 2, i32 1, i32 0, i32 7, i32 0, i32 5, i32 4, i32 3, i32 2, i32 0, i32 0, i32 7, i32 6, i32 5, i32 0, i32 3, i32 2, i32 1], align 4
-; CHECK: @switch.table.unreachable_default_holes_0to31 = private unnamed_addr constant [32 x i32] [i32 0, i32 7, i32 6, i32 0, i32 4, i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 0, i32 2, i32 1, i32 0, i32 7, i32 0, i32 5, i32 4, i32 3, i32 2, i32 0, i32 0, i32 7, i32 6, i32 5, i32 0, i32 3, i32 2, i32 1], align 4
-; CHECK: @switch.table.reachable_default_dense_0to32 = private unnamed_addr constant [33 x i32] [i32 0, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0], align 4
-; CHECK: @switch.table.unreachable_default_dense_0to32 = private unnamed_addr constant [33 x i32] [i32 0, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0], align 4
-; CHECK: @switch.table.unreachable_default_holes_0to32 = private unnamed_addr constant [33 x i32] [i32 0, i32 7, i32 6, i32 0, i32 4, i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 0, i32 2, i32 1, i32 0, i32 7, i32 0, i32 5, i32 4, i32 3, i32 2, i32 0, i32 0, i32 7, i32 6, i32 5, i32 0, i32 3, i32 2, i32 1, i32 0], align 4
+; CHECK: @switch.table.switch.truncated.reachable_default_dense_0to31 = private unnamed_addr constant [32 x i4] [i4 0, i4 7, i4 6, i4 5, i4 4, i4 3, i4 2, i4 1, i4 0, i4 7, i4 6, i4 5, i4 4, i4 3, i4 2, i4 1, i4 0, i4 7, i4 6, i4 5, i4 4, i4 3, i4 2, i4 1, i4 0, i4 7, i4 6, i4 5, i4 4, i4 3, i4 2, i4 1], align 1
+; CHECK: @switch.table.switch.truncated.unreachable_default_dense_0to31 = private unnamed_addr constant [32 x i4] [i4 0, i4 7, i4 6, i4 5, i4 4, i4 3, i4 2, i4 1, i4 0, i4 7, i4 6, i4 5, i4 4, i4 3, i4 2, i4 1, i4 0, i4 7, i4 6, i4 5, i4 4, i4 3, i4 2, i4 1, i4 0, i4 7, i4 6, i4 5, i4 4, i4 3, i4 2, i4 1], align 1
+; CHECK: @switch.table.switch.truncated.reachable_default_holes_0to31 = private unnamed_addr constant [32 x i4] [i4 0, i4 7, i4 6, i4 0, i4 4, i4 3, i4 2, i4 1, i4 0, i4 7, i4 6, i4 5, i4 4, i4 0, i4 2, i4 1, i4 0, i4 7, i4 0, i4 5, i4 4, i4 3, i4 2, i4 0, i4 0, i4 7, i4 6, i4 5, i4 0, i4 3, i4 2, i4 1], align 1
+; CHECK: @switch.table.switch.truncated.unreachable_default_holes_0to31 = private unnamed_addr constant [32 x i4] [i4 0, i4 7, i4 6, i4 0, i4 4, i4 3, i4 2, i4 1, i4 0, i4 7, i4 6, i4 5, i4 4, i4 0, i4 2, i4 1, i4 0, i4 7, i4 0, i4 5, i4 4, i4 3, i4 2, i4 0, i4 0, i4 7, i4 6, i4 5, i4 0, i4 3, i4 2, i4 1], align 1
+; CHECK: @switch.table.switch.truncated.reachable_default_dense_0to32 = private unnamed_addr constant [33 x i4] [i4 0, i4 7, i4 6, i4 5, i4 4, i4 3, i4 2, i4 1, i4 0, i4 7, i4 6, i4 5, i4 4, i4 3, i4 2, i4 1, i4 0, i4 7, i4 6, i4 5, i4 4, i4 3, i4 2, i4 1, i4 0, i4 7, i4 6, i4 5, i4 4, i4 3, i4 2, i4 1, i4 0], align 1
+; CHECK: @switch.table.switch.truncated.unreachable_default_dense_0to32 = private unnamed_addr constant [33 x i4] [i4 0, i4 7, i4 6, i4 5, i4 4, i4 3, i4 2, i4 1, i4 0, i4 7, i4 6, i4 5, i4 4, i4 3, i4 2, i4 1, i4 0, i4 7, i4 6, i4 5, i4 4, i4 3, i4 2, i4 1, i4 0, i4 7, i4 6, i4 5, i4 4, i4 3, i4 2, i4 1, i4 0], align 1
+; CHECK: @switch.table.switch.truncated.unreachable_default_holes_0to32 = private unnamed_addr constant [33 x i4] [i4 0, i4 7, i4 6, i4 0, i4 4, i4 3, i4 2, i4 1, i4 0, i4 7, i4 6, i4 5, i4 4, i4 0, i4 2, i4 1, i4 0, i4 7, i4 0, i4 5, i4 4, i4 3, i4 2, i4 0, i4 0, i4 7, i4 6, i4 5, i4 0, i4 3, i4 2, i4 1, i4 0], align 1
 ;.
 define i32 @reachable_default_dense_0to31(i32 %x, i32 %y) {
 ; CHECK-LABEL: @reachable_default_dense_0to31(
@@ -19,8 +19,9 @@ define i32 @reachable_default_dense_0to31(i32 %x, i32 %y) {
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 32
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
 ; CHECK:       switch.lookup:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [32 x i32], ptr @switch.table.reachable_default_dense_0to31, i32 0, i32 [[X]]
-; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [32 x i4], ptr @switch.table.switch.truncated.reachable_default_dense_0to31, i32 0, i32 [[X]]
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i4, ptr [[SWITCH_GEP]], align 1
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i4 [[SWITCH_LOAD]] to i32
 ; CHECK-NEXT:    br label [[RETURN]]
 ; CHECK:       return:
 ; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ [[SWITCH_TRUNCATEDINT_CAST]], [[SWITCH_LOOKUP]] ], [ [[Y:%.*]], [[ENTRY:%.*]] ]
@@ -82,8 +83,9 @@ return:
 define i32 @unreachable_default_dense_0to31(i32 %x, i32 %y) {
 ; CHECK-LABEL: @unreachable_default_dense_0to31(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [32 x i32], ptr @switch.table.unreachable_default_dense_0to31, i32 0, i32 [[X:%.*]]
-; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [32 x i4], ptr @switch.table.switch.truncated.unreachable_default_dense_0to31, i32 0, i32 [[X:%.*]]
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i4, ptr [[SWITCH_GEP]], align 1
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i4 [[SWITCH_LOAD]] to i32
 ; CHECK-NEXT:    ret i32 [[SWITCH_TRUNCATEDINT_CAST]]
 ;
 entry:
@@ -149,8 +151,9 @@ define i32 @reachable_default_holes_0to31(i32 %x, i32 %y) {
 ; CHECK-NEXT:    [[SWITCH_LOBIT:%.*]] = trunc i32 [[SWITCH_SHIFTED]] to i1
 ; CHECK-NEXT:    br i1 [[SWITCH_LOBIT]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN]]
 ; CHECK:       switch.lookup:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [32 x i32], ptr @switch.table.reachable_default_holes_0to31, i32 0, i32 [[X]]
-; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [32 x i4], ptr @switch.table.switch.truncated.reachable_default_holes_0to31, i32 0, i32 [[X]]
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i4, ptr [[SWITCH_GEP]], align 1
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i4 [[SWITCH_LOAD]] to i32
 ; CHECK-NEXT:    br label [[RETURN]]
 ; CHECK:       return:
 ; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ [[SWITCH_TRUNCATEDINT_CAST]], [[SWITCH_LOOKUP]] ], [ [[Y:%.*]], [[SWITCH_HOLE_CHECK]] ], [ [[Y]], [[ENTRY:%.*]] ]
@@ -206,8 +209,9 @@ return:
 define i32 @unreachable_default_holes_0to31(i32 %x, i32 %y) {
 ; CHECK-LABEL: @unreachable_default_holes_0to31(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [32 x i32], ptr @switch.table.unreachable_default_holes_0to31, i32 0, i32 [[X:%.*]]
-; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [32 x i4], ptr @switch.table.switch.truncated.unreachable_default_holes_0to31, i32 0, i32 [[X:%.*]]
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i4, ptr [[SWITCH_GEP]], align 1
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i4 [[SWITCH_LOAD]] to i32
 ; CHECK-NEXT:    ret i32 [[SWITCH_TRUNCATEDINT_CAST]]
 ;
 entry:
@@ -263,8 +267,9 @@ define i32 @reachable_default_dense_0to32(i32 %x, i32 %y) {
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 33
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
 ; CHECK:       switch.lookup:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [33 x i32], ptr @switch.table.reachable_default_dense_0to32, i32 0, i32 [[X]]
-; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [33 x i4], ptr @switch.table.switch.truncated.reachable_default_dense_0to32, i32 0, i32 [[X]]
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i4, ptr [[SWITCH_GEP]], align 1
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i4 [[SWITCH_LOAD]] to i32
 ; CHECK-NEXT:    br label [[RETURN]]
 ; CHECK:       return:
 ; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ [[SWITCH_TRUNCATEDINT_CAST]], [[SWITCH_LOOKUP]] ], [ [[Y:%.*]], [[ENTRY:%.*]] ]
@@ -327,8 +332,9 @@ return:
 define i32 @unreachable_default_dense_0to32(i32 %x, i32 %y) {
 ; CHECK-LABEL: @unreachable_default_dense_0to32(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [33 x i32], ptr @switch.table.unreachable_default_dense_0to32, i32 0, i32 [[X:%.*]]
-; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [33 x i4], ptr @switch.table.switch.truncated.unreachable_default_dense_0to32, i32 0, i32 [[X:%.*]]
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i4, ptr [[SWITCH_GEP]], align 1
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i4 [[SWITCH_LOAD]] to i32
 ; CHECK-NEXT:    ret i32 [[SWITCH_TRUNCATEDINT_CAST]]
 ;
 entry:
@@ -490,8 +496,9 @@ return:
 define i32 @unreachable_default_holes_0to32(i32 %x, i32 %y) {
 ; CHECK-LABEL: @unreachable_default_holes_0to32(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [33 x i32], ptr @switch.table.unreachable_default_holes_0to32, i32 0, i32 [[X:%.*]]
-; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [33 x i4], ptr @switch.table.switch.truncated.unreachable_default_holes_0to32, i32 0, i32 [[X:%.*]]
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i4, ptr [[SWITCH_GEP]], align 1
+; CHECK-NEXT:    [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext i4 [[SWITCH_LOAD]] to i32
 ; CHECK-NEXT:    ret i32 [[SWITCH_TRUNCATEDINT_CAST]]
 ;
 entry:
diff --git a/llvm/test/Transforms/SimplifyCFG/switch-dead-default-lookup-table.ll b/llvm/test/Transforms/SimplifyCFG/switch-dead-default-lookup-table.ll
index bead0dc4c567a8..0de9b12d47d4fa 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch-dead-default-lookup-table.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch-dead-default-lookup-table.ll
@@ -8,8 +8,11 @@ define i64 @test_1(i64 %0) {
 ; CHECK-SAME: i64 [[TMP0:%.*]]) {
 ; CHECK-NEXT:  switch.lookup:
 ; CHECK-NEXT:    [[TMP1:%.*]] = urem i64 [[TMP0]], 4
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i64], ptr @switch.table.test_1, i32 0, i64 [[TMP1]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i64, ptr [[SWITCH_GEP]], align 8
+; CHECK-NEXT:    [[SWITCH_CAST:%.*]] = trunc i64 [[TMP1]] to i8
+; CHECK-NEXT:    [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i8 [[SWITCH_CAST]], 2
+; CHECK-NEXT:    [[SWITCH_DOWNSHIFT:%.*]] = lshr i8 -108, [[SWITCH_SHIFTAMT]]
+; CHECK-NEXT:    [[SWITCH_MASKED:%.*]] = trunc i8 [[SWITCH_DOWNSHIFT]] to i2
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = zext i2 [[SWITCH_MASKED]] to i64
 ; CHECK-NEXT:    ret i64 [[SWITCH_LOAD]]
 ;
   %2 = urem i64 %0, 4
diff --git a/llvm/test/Transforms/SimplifyCFG/switch_mask.ll b/llvm/test/Transforms/SimplifyCFG/switch_mask.ll
index 51c15774d47628..704d035acfa0d4 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch_mask.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch_mask.ll
@@ -186,8 +186,11 @@ define void @switch_lookup_with_nonconst_range(i32 %x, i1 %cond) {
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[ADD]], 6
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[LOR_END:%.*]]
 ; CHECK:       switch.lookup:
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [6 x i32], ptr @switch.table.switch_lookup_with_nonconst_range, i32 0, i32 [[ADD]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    [[SWITCH_CAST:%.*]] = trunc i32 [[ADD]] to i6
+; CHECK-NEXT:    [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i6 [[SWITCH_CAST]], 1
+; CHECK-NEXT:    [[SWITCH_DOWNSHIFT:%.*]] = lshr i6 28, [[SWITCH_SHIFTAMT]]
+; CHECK-NEXT:    [[SWITCH_MASKED:%.*]] = trunc i6 [[SWITCH_DOWNSHIFT]] to i1
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = zext i1 [[SWITCH_MASKED]] to i32
 ; CHECK-NEXT:    br label [[LOR_END]]
 ; CHECK:       lor.end:
 ; CHECK-NEXT:    [[RETVAL_0_I_I:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 1, [[FOR_END]] ]



More information about the llvm-commits mailing list