[llvm] [NFC] SimplifyCFG: Detect switch replacement earlier in `switchToLookup` (PR #155602)
    Jessica Del via llvm-commits 
    llvm-commits at lists.llvm.org
       
    Mon Sep  1 04:44:25 PDT 2025
    
    
  
https://github.com/OutOfCache updated https://github.com/llvm/llvm-project/pull/155602
>From 6cf88f97cf43259939ce9a221fdbcd087fc09edb Mon Sep 17 00:00:00 2001
From: Jessica Del <Jessica.Del at amd.com>
Date: Tue, 26 Aug 2025 16:03:11 +0200
Subject: [PATCH 01/11] SimplifyCFG: Move ResultType and NumResults calculation
Move the insertion into ResultTypes further up and the NumResults
further down.
---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index ef110a6922f05..49426db175f4d 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -6955,7 +6955,8 @@ static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
                         Results, DL, TTI))
       return false;
 
-    // Append the result from this case to the list for each phi.
+    // Append the result  and result types from this case to the list for each
+    // phi.
     for (const auto &I : Results) {
       PHINode *PHI = I.first;
       Constant *Value = I.second;
@@ -6963,23 +6964,16 @@ static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
       if (Inserted)
         PHIs.push_back(PHI);
       It->second.push_back(std::make_pair(CaseVal, Value));
+      ResultTypes[PHI] = ResultLists[PHI][0].second->getType();
     }
   }
 
-  // Keep track of the result types.
-  for (PHINode *PHI : PHIs) {
-    ResultTypes[PHI] = ResultLists[PHI][0].second->getType();
-  }
-
-  uint64_t NumResults = ResultLists[PHIs[0]].size();
-
   // If the table has holes, we need a constant result for the default case
   // or a bitmask that fits in a register.
   SmallVector<std::pair<PHINode *, Constant *>, 4> DefaultResultsList;
   bool HasDefaultResults =
       getCaseResults(SI, nullptr, SI->getDefaultDest(), &CommonDest,
                      DefaultResultsList, DL, TTI);
-
   for (const auto &I : DefaultResultsList) {
     PHINode *PHI = I.first;
     Constant *Result = I.second;
@@ -6998,6 +6992,7 @@ static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
   // If the default destination is unreachable, or if the lookup table covers
   // all values of the conditional variable, branch directly to the lookup table
   // BB. Otherwise, check that the condition is within the case range.
+  uint64_t NumResults = ResultLists[PHIs[0]].size();
   bool DefaultIsReachable = !SI->defaultDestUnreachable();
 
   bool TableHasHoles = (NumResults < TableSize);
>From ee5a80d2882e3bfc82f35fd3687a25ea0c749a1f Mon Sep 17 00:00:00 2001
From: Jessica Del <Jessica.Del at amd.com>
Date: Tue, 26 Aug 2025 16:06:14 +0200
Subject: [PATCH 02/11] SimplifyCFG: Calculate TableIndexOffset earlier
---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 49426db175f4d..1ec292b2257b1 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -6983,12 +6983,17 @@ static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
   bool UseSwitchConditionAsTableIndex = shouldUseSwitchConditionAsTableIndex(
       *MinCaseVal, *MaxCaseVal, HasDefaultResults, ResultTypes, DL, TTI);
   uint64_t TableSize;
-  if (UseSwitchConditionAsTableIndex)
+  ConstantInt *TableIndexOffset;
+  if (UseSwitchConditionAsTableIndex) {
     TableSize = MaxCaseVal->getLimitedValue() + 1;
-  else
+    TableIndexOffset = ConstantInt::get(MaxCaseVal->getIntegerType(), 0);
+  } else {
     TableSize =
         (MaxCaseVal->getValue() - MinCaseVal->getValue()).getLimitedValue() + 1;
 
+    TableIndexOffset = MinCaseVal;
+  }
+
   // If the default destination is unreachable, or if the lookup table covers
   // all values of the conditional variable, branch directly to the lookup table
   // BB. Otherwise, check that the condition is within the case range.
@@ -7038,12 +7043,9 @@ static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
   // Compute the table index value.
   Builder.SetInsertPoint(SI);
   Value *TableIndex;
-  ConstantInt *TableIndexOffset;
   if (UseSwitchConditionAsTableIndex) {
-    TableIndexOffset = ConstantInt::get(MaxCaseVal->getIntegerType(), 0);
     TableIndex = SI->getCondition();
   } else {
-    TableIndexOffset = MinCaseVal;
     // If the default is unreachable, all case values are s>= MinCaseVal. Then
     // we can try to attach nsw.
     bool MayWrap = true;
>From b25f19765e48698e2f2a63bd46e6a74a4ad10865 Mon Sep 17 00:00:00 2001
From: Jessica Del <Jessica.Del at amd.com>
Date: Tue, 26 Aug 2025 16:25:31 +0200
Subject: [PATCH 03/11] SimplifyCFG: Move TableIndex further up to calculate
 TableSize earlier
If we use the switch condition as table index, the default results
can influence the TableSize.
The TableSize is used for the decision whether we want to create a table
in the first place, so it makes sense to set TableIndex and the final
TableSize before the check in `shouldBuildLookupTable`.
However, if we do not use the switch condition as the table index,
we move the setting *after* the decision to build it.
Since we need to create a sub instruction in that case, only do that
once we are sure. Additionally, that case does not influence the
TableSize, so there is no harm in setting it later.
---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 89 ++++++++++++-----------
 1 file changed, 47 insertions(+), 42 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 1ec292b2257b1..82902ce503ba2 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -7022,9 +7022,55 @@ static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
       return false;
   }
 
+  // Compute the table index value.
+  Value *TableIndex;
+  if (UseSwitchConditionAsTableIndex) {
+    TableIndex = SI->getCondition();
+    if (HasDefaultResults) {
+      // Grow the table to cover all possible index values to avoid the range
+      // check. It will use the default result to fill in the table hole later,
+      // so make sure it exist.
+      ConstantRange CR =
+          computeConstantRange(TableIndex, /* ForSigned */ false);
+      // Grow the table shouldn't have any size impact by checking
+      // wouldFitInRegister.
+      // TODO: Consider growing the table also when it doesn't fit in a register
+      // if no optsize is specified.
+      const uint64_t UpperBound = CR.getUpper().getLimitedValue();
+      if (!CR.isUpperWrapped() && all_of(ResultTypes, [&](const auto &KV) {
+            return SwitchLookupTable::wouldFitInRegister(
+                DL, UpperBound, KV.second /* ResultType */);
+          })) {
+        // There may be some case index larger than the UpperBound (unreachable
+        // case), so make sure the table size does not get smaller.
+        TableSize = std::max(UpperBound, TableSize);
+        // The default branch is unreachable after we enlarge the lookup table.
+        // Adjust DefaultIsReachable to reuse code path.
+        DefaultIsReachable = false;
+      }
+    }
+  }
+
   if (!shouldBuildLookupTable(SI, TableSize, TTI, DL, ResultTypes))
     return false;
 
+  Builder.SetInsertPoint(SI);
+  // TableIndex is the switch condition - TableIndexOffset if we don't
+  // use the condition directly
+  if (!UseSwitchConditionAsTableIndex) {
+    // If the default is unreachable, all case values are s>= MinCaseVal. Then
+    // we can try to attach nsw.
+    bool MayWrap = true;
+    if (!DefaultIsReachable) {
+      APInt Res =
+          MaxCaseVal->getValue().ssub_ov(MinCaseVal->getValue(), MayWrap);
+      (void)Res;
+    }
+    TableIndex = Builder.CreateSub(SI->getCondition(), TableIndexOffset,
+                                   "switch.tableidx", /*HasNUW =*/false,
+                                   /*HasNSW =*/!MayWrap);
+  }
+
   std::vector<DominatorTree::UpdateType> Updates;
 
   // Compute the maximum table size representable by the integer type we are
@@ -7040,50 +7086,9 @@ static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
   BasicBlock *LookupBB = BasicBlock::Create(
       Mod.getContext(), "switch.lookup", CommonDest->getParent(), CommonDest);
 
-  // Compute the table index value.
-  Builder.SetInsertPoint(SI);
-  Value *TableIndex;
-  if (UseSwitchConditionAsTableIndex) {
-    TableIndex = SI->getCondition();
-  } else {
-    // If the default is unreachable, all case values are s>= MinCaseVal. Then
-    // we can try to attach nsw.
-    bool MayWrap = true;
-    if (!DefaultIsReachable) {
-      APInt Res = MaxCaseVal->getValue().ssub_ov(MinCaseVal->getValue(), MayWrap);
-      (void)Res;
-    }
-
-    TableIndex = Builder.CreateSub(SI->getCondition(), TableIndexOffset,
-                                   "switch.tableidx", /*HasNUW =*/false,
-                                   /*HasNSW =*/!MayWrap);
-  }
-
   BranchInst *RangeCheckBranch = nullptr;
 
-  // Grow the table to cover all possible index values to avoid the range check.
-  // It will use the default result to fill in the table hole later, so make
-  // sure it exist.
-  if (UseSwitchConditionAsTableIndex && HasDefaultResults) {
-    ConstantRange CR = computeConstantRange(TableIndex, /* ForSigned */ false);
-    // Grow the table shouldn't have any size impact by checking
-    // wouldFitInRegister.
-    // TODO: Consider growing the table also when it doesn't fit in a register
-    // if no optsize is specified.
-    const uint64_t UpperBound = CR.getUpper().getLimitedValue();
-    if (!CR.isUpperWrapped() && all_of(ResultTypes, [&](const auto &KV) {
-          return SwitchLookupTable::wouldFitInRegister(
-              DL, UpperBound, KV.second /* ResultType */);
-        })) {
-      // There may be some case index larger than the UpperBound (unreachable
-      // case), so make sure the table size does not get smaller.
-      TableSize = std::max(UpperBound, TableSize);
-      // The default branch is unreachable after we enlarge the lookup table.
-      // Adjust DefaultIsReachable to reuse code path.
-      DefaultIsReachable = false;
-    }
-  }
-
+  Builder.SetInsertPoint(SI);
   const bool GeneratingCoveredLookupTable = (MaxTableSize == TableSize);
   if (!DefaultIsReachable || GeneratingCoveredLookupTable) {
     Builder.CreateBr(LookupBB);
>From efa2d5c7e77e55662c47915ed383c0fe4724c7a3 Mon Sep 17 00:00:00 2001
From: Jessica Del <Jessica.Del at amd.com>
Date: Tue, 26 Aug 2025 16:41:24 +0200
Subject: [PATCH 04/11] SimplifyCFG: Create the SwitchLookupTable earlier
The table decides what kind of lookup table is created. To become more
flexible in a future change, we want to know the type before we check if
we want to create it.
---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 38 +++++++++++++++--------
 1 file changed, 25 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 82902ce503ba2..6e7eb69543b3e 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -7071,6 +7071,27 @@ static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
                                    /*HasNSW =*/!MayWrap);
   }
 
+  // Keep track of the tables we create for each phi node
+  struct TableInfo {
+    SwitchLookupTable Table;
+    Constant *DefaultValue;
+  };
+  // Find out what kind of table to create by creating a SwitchLookupTable
+  SmallDenseMap<PHINode *, TableInfo> PhiToTableMap;
+  for (PHINode *PHI : PHIs) {
+    const auto &ResultList = ResultLists[PHI];
+
+    Type *ResultType = ResultList.begin()->second->getType();
+    // Use any value to fill the lookup table holes.
+    Constant *DV =
+        AllHolesArePoison ? PoisonValue::get(ResultType) : DefaultResults[PHI];
+    StringRef FuncName = Fn->getName();
+    SwitchLookupTable Table(*Fn->getParent(), TableSize, TableIndexOffset,
+                            ResultList, DV, DL, FuncName);
+    TableInfo TI = {Table, DV};
+    PhiToTableMap.insert({PHI, TI});
+  }
+
   std::vector<DominatorTree::UpdateType> Updates;
 
   // Compute the maximum table size representable by the integer type we are
@@ -7159,25 +7180,16 @@ static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
 
   for (PHINode *PHI : PHIs) {
     const ResultListTy &ResultList = ResultLists[PHI];
-
-    Type *ResultType = ResultList.begin()->second->getType();
-
-    // Use any value to fill the lookup table holes.
-    Constant *DV =
-        AllHolesArePoison ? PoisonValue::get(ResultType) : DefaultResults[PHI];
-    StringRef FuncName = Fn->getName();
-    SwitchLookupTable Table(Mod, TableSize, TableIndexOffset, ResultList, DV,
-                            DL, FuncName);
-
-    Value *Result = Table.buildLookup(TableIndex, Builder, DL);
-
+    auto TableInfo = PhiToTableMap.at(PHI);
+    auto *Result = TableInfo.Table.buildLookup(TableIndex, Builder, DL);
     // Do a small peephole optimization: re-use the switch table compare if
     // possible.
     if (!TableHasHoles && HasDefaultResults && RangeCheckBranch) {
       BasicBlock *PhiBlock = PHI->getParent();
       // Search for compare instructions which use the phi.
       for (auto *User : PHI->users()) {
-        reuseTableCompare(User, PhiBlock, RangeCheckBranch, DV, ResultList);
+        reuseTableCompare(User, PhiBlock, RangeCheckBranch,
+                          TableInfo.DefaultValue, ResultList);
       }
     }
 
>From 86419f7dda90388ef6057a3765d1b73cfddce519 Mon Sep 17 00:00:00 2001
From: Jessica Del <Jessica.Del at amd.com>
Date: Tue, 26 Aug 2025 15:21:04 +0200
Subject: [PATCH 05/11] SimplifyCFG: Delay lookup table creation
Previously, the global LUT was created in the constructor of
SwitchLookupTable.
Since we want to call the constructor way earlier to decide what kind of
LUT to create (and if we want to create any), this can create the LUT
unnecessarily if we later on decide not to use one.
Only create it once we are certain we want to create a LUT.
---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 36 ++++++++++++++---------
 1 file changed, 22 insertions(+), 14 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 6e7eb69543b3e..0dfbf4784ffc2 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -6449,7 +6449,8 @@ class SwitchLookupTable {
 
   /// Build instructions with Builder to retrieve the value at
   /// the position given by Index in the lookup table.
-  Value *buildLookup(Value *Index, IRBuilder<> &Builder, const DataLayout &DL);
+  Value *buildLookup(Value *Index, IRBuilder<> &Builder, const DataLayout &DL,
+                     Function *Func);
 
   /// Return true if a table with TableSize elements of
   /// type ElementType would fit in a target-legal register.
@@ -6479,6 +6480,9 @@ class SwitchLookupTable {
     ArrayKind
   } Kind;
 
+  // The type of the output values.
+  Type *ValueType;
+
   // For SingleValueKind, this is the single value.
   Constant *SingleValue = nullptr;
 
@@ -6493,6 +6497,8 @@ class SwitchLookupTable {
 
   // For ArrayKind, this is the array.
   GlobalVariable *Array = nullptr;
+  ArrayType *ArrayTy = nullptr;
+  Constant *Initializer = nullptr;
 };
 
 } // end anonymous namespace
@@ -6507,7 +6513,7 @@ SwitchLookupTable::SwitchLookupTable(
   // If all values in the table are equal, this is that value.
   SingleValue = Values.begin()->second;
 
-  Type *ValueType = Values.begin()->second->getType();
+  ValueType = Values.begin()->second->getType();
 
   // Build up the table contents.
   SmallVector<Constant *, 64> TableContents(TableSize);
@@ -6622,21 +6628,14 @@ SwitchLookupTable::SwitchLookupTable(
   }
 
   // Store the table in an array.
-  ArrayType *ArrayTy = ArrayType::get(ValueType, TableSize);
-  Constant *Initializer = ConstantArray::get(ArrayTy, TableContents);
-
-  Array = new GlobalVariable(M, ArrayTy, /*isConstant=*/true,
-                             GlobalVariable::PrivateLinkage, Initializer,
-                             "switch.table." + FuncName);
-  Array->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
-  // Set the alignment to that of an array items. We will be only loading one
-  // value out of it.
-  Array->setAlignment(DL.getPrefTypeAlign(ValueType));
+  ArrayTy = ArrayType::get(ValueType, TableSize);
+  Initializer = ConstantArray::get(ArrayTy, TableContents);
+
   Kind = ArrayKind;
 }
 
 Value *SwitchLookupTable::buildLookup(Value *Index, IRBuilder<> &Builder,
-                                      const DataLayout &DL) {
+                                      const DataLayout &DL, Function *Func) {
   switch (Kind) {
   case SingleValueKind:
     return SingleValue;
@@ -6678,6 +6677,15 @@ Value *SwitchLookupTable::buildLookup(Value *Index, IRBuilder<> &Builder,
     return Builder.CreateTrunc(DownShifted, BitMapElementTy, "switch.masked");
   }
   case ArrayKind: {
+    // Only build lookup table when we have a target that supports it or the
+    // attribute is not set.
+    Array = new GlobalVariable(*Func->getParent(), ArrayTy, /*isConstant=*/true,
+                               GlobalVariable::PrivateLinkage, Initializer,
+                               "switch.table." + Func->getName());
+    Array->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
+    // Set the alignment to that of an array items. We will be only loading one
+    // value out of it.
+    Array->setAlignment(DL.getPrefTypeAlign(ValueType));
     Type *IndexTy = DL.getIndexType(Array->getType());
     auto *ArrayTy = cast<ArrayType>(Array->getValueType());
 
@@ -7181,7 +7189,7 @@ static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
   for (PHINode *PHI : PHIs) {
     const ResultListTy &ResultList = ResultLists[PHI];
     auto TableInfo = PhiToTableMap.at(PHI);
-    auto *Result = TableInfo.Table.buildLookup(TableIndex, Builder, DL);
+    auto *Result = TableInfo.Table.buildLookup(TableIndex, Builder, DL, Fn);
     // Do a small peephole optimization: re-use the switch table compare if
     // possible.
     if (!TableHasHoles && HasDefaultResults && RangeCheckBranch) {
>From a2b2cff942a81825c2a81a9dbed9a58b886c497d Mon Sep 17 00:00:00 2001
From: Jessica Del <Jessica.Del at amd.com>
Date: Tue, 26 Aug 2025 16:57:25 +0200
Subject: [PATCH 06/11] SimplifyCFG: Renaming
SwitchLookupTable -> SwitchReplacement
This class contains more than just a typical lookup table.
It helps to optimize the switch away, either by lookup table, or with a
linear function, a bitmap, or a single value replacement.
ArrayKind -> LookupTableKind
ArrayKind is the "true" LUT kind.
buildLookup -> replaceSwitch
---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 108 +++++++++++-----------
 1 file changed, 55 insertions(+), 53 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 0dfbf4784ffc2..ebb51260f5be9 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -6437,20 +6437,22 @@ static bool trySwitchToSelect(SwitchInst *SI, IRBuilder<> &Builder,
 
 namespace {
 
-/// This class represents a lookup table that can be used to replace a switch.
-class SwitchLookupTable {
+/// This class finds alternatives for switches to ultimately
+/// replace the switch.
+class SwitchReplacement {
 public:
-  /// Create a lookup table to use as a switch replacement with the contents
-  /// of Values, using DefaultValue to fill any holes in the table.
-  SwitchLookupTable(
+  /// Create a helper for optimizations to use as a switch replacement.
+  /// Find a better representation for the content of Values,
+  /// using DefaultValue to fill any holes in the table.
+  SwitchReplacement(
       Module &M, uint64_t TableSize, ConstantInt *Offset,
       const SmallVectorImpl<std::pair<ConstantInt *, Constant *>> &Values,
       Constant *DefaultValue, const DataLayout &DL, const StringRef &FuncName);
 
-  /// Build instructions with Builder to retrieve the value at
-  /// the position given by Index in the lookup table.
-  Value *buildLookup(Value *Index, IRBuilder<> &Builder, const DataLayout &DL,
-                     Function *Func);
+  /// Build instructions with Builder to retrieve values using Index
+  /// and replace the switch.
+  Value *replaceSwitch(Value *Index, IRBuilder<> &Builder, const DataLayout &DL,
+                       Function *Func);
 
   /// Return true if a table with TableSize elements of
   /// type ElementType would fit in a target-legal register.
@@ -6458,14 +6460,13 @@ class SwitchLookupTable {
                                  Type *ElementType);
 
 private:
-  // Depending on the contents of the table, it can be represented in
-  // different ways.
+  // Depending on the switch, there are different alternatives.
   enum {
-    // For tables where each element contains the same value, we just have to
+    // For switches where each case contains the same value, we just have to
     // store that single value and return it for each lookup.
     SingleValueKind,
 
-    // For tables where there is a linear relationship between table index
+    // For switches where there is a linear relationship between table index
     // and values. We calculate the result with a simple multiplication
     // and addition instead of a table lookup.
     LinearMapKind,
@@ -6477,7 +6478,7 @@ class SwitchLookupTable {
 
     // The table is stored as an array of values. Values are retrieved by load
     // instructions from the table.
-    ArrayKind
+    LookupTableKind
   } Kind;
 
   // The type of the output values.
@@ -6495,15 +6496,15 @@ class SwitchLookupTable {
   ConstantInt *LinearMultiplier = nullptr;
   bool LinearMapValWrapped = false;
 
-  // For ArrayKind, this is the array.
-  GlobalVariable *Array = nullptr;
-  ArrayType *ArrayTy = nullptr;
+  // For LookupTableKind, this is the table.
+  GlobalVariable *Table = nullptr;
+  ArrayType *TableTy = nullptr;
   Constant *Initializer = nullptr;
 };
 
 } // end anonymous namespace
 
-SwitchLookupTable::SwitchLookupTable(
+SwitchReplacement::SwitchReplacement(
     Module &M, uint64_t TableSize, ConstantInt *Offset,
     const SmallVectorImpl<std::pair<ConstantInt *, Constant *>> &Values,
     Constant *DefaultValue, const DataLayout &DL, const StringRef &FuncName) {
@@ -6628,14 +6629,14 @@ SwitchLookupTable::SwitchLookupTable(
   }
 
   // Store the table in an array.
-  ArrayTy = ArrayType::get(ValueType, TableSize);
-  Initializer = ConstantArray::get(ArrayTy, TableContents);
+  TableTy = ArrayType::get(ValueType, TableSize);
+  Initializer = ConstantArray::get(TableTy, TableContents);
 
-  Kind = ArrayKind;
+  Kind = LookupTableKind;
 }
 
-Value *SwitchLookupTable::buildLookup(Value *Index, IRBuilder<> &Builder,
-                                      const DataLayout &DL, Function *Func) {
+Value *SwitchReplacement::replaceSwitch(Value *Index, IRBuilder<> &Builder,
+                                        const DataLayout &DL, Function *Func) {
   switch (Kind) {
   case SingleValueKind:
     return SingleValue;
@@ -6676,18 +6677,18 @@ Value *SwitchLookupTable::buildLookup(Value *Index, IRBuilder<> &Builder,
     // Mask off.
     return Builder.CreateTrunc(DownShifted, BitMapElementTy, "switch.masked");
   }
-  case ArrayKind: {
+  case LookupTableKind: {
     // Only build lookup table when we have a target that supports it or the
-    // attribute is not set.
-    Array = new GlobalVariable(*Func->getParent(), ArrayTy, /*isConstant=*/true,
+    // attribute is notable.
+    Table = new GlobalVariable(*Func->getParent(), TableTy, /*isConstant=*/true,
                                GlobalVariable::PrivateLinkage, Initializer,
                                "switch.table." + Func->getName());
-    Array->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
+    Table->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
     // Set the alignment to that of an array items. We will be only loading one
     // value out of it.
-    Array->setAlignment(DL.getPrefTypeAlign(ValueType));
-    Type *IndexTy = DL.getIndexType(Array->getType());
-    auto *ArrayTy = cast<ArrayType>(Array->getValueType());
+    Table->setAlignment(DL.getPrefTypeAlign(ValueType));
+    Type *IndexTy = DL.getIndexType(Table->getType());
+    auto *ArrayTy = cast<ArrayType>(Table->getValueType());
 
     if (Index->getType() != IndexTy) {
       unsigned OldBitWidth = Index->getType()->getIntegerBitWidth();
@@ -6699,14 +6700,14 @@ Value *SwitchLookupTable::buildLookup(Value *Index, IRBuilder<> &Builder,
 
     Value *GEPIndices[] = {ConstantInt::get(IndexTy, 0), Index};
     Value *GEP =
-        Builder.CreateInBoundsGEP(ArrayTy, Array, GEPIndices, "switch.gep");
+        Builder.CreateInBoundsGEP(ArrayTy, Table, GEPIndices, "switch.gep");
     return Builder.CreateLoad(ArrayTy->getElementType(), GEP, "switch.load");
   }
   }
-  llvm_unreachable("Unknown lookup table kind!");
+  llvm_unreachable("Unknown helper kind!");
 }
 
-bool SwitchLookupTable::wouldFitInRegister(const DataLayout &DL,
+bool SwitchReplacement::wouldFitInRegister(const DataLayout &DL,
                                            uint64_t TableSize,
                                            Type *ElementType) {
   auto *IT = dyn_cast<IntegerType>(ElementType);
@@ -6786,7 +6787,7 @@ shouldBuildLookupTable(SwitchInst *SI, uint64_t TableSize,
     // Saturate this flag to false.
     AllTablesFitInRegister =
         AllTablesFitInRegister &&
-        SwitchLookupTable::wouldFitInRegister(DL, TableSize, Ty);
+        SwitchReplacement::wouldFitInRegister(DL, TableSize, Ty);
 
     // If both flags saturate, we're done. NOTE: This *only* works with
     // saturating flags, and all flags have to saturate first due to the
@@ -6817,7 +6818,7 @@ static bool shouldUseSwitchConditionAsTableIndex(
       !HasDefaultResults)
     return false;
   return all_of(ResultTypes, [&](const auto &KV) {
-    return SwitchLookupTable::wouldFitInRegister(
+    return SwitchReplacement::wouldFitInRegister(
         DL, MaxCaseVal.getLimitedValue() + 1 /* TableSize */,
         KV.second /* ResultType */);
   });
@@ -6908,9 +6909,9 @@ static void reuseTableCompare(
 /// If the switch is only used to initialize one or more phi nodes in a common
 /// successor block with different constant values, replace the switch with
 /// lookup tables.
-static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
-                                DomTreeUpdater *DTU, const DataLayout &DL,
-                                const TargetTransformInfo &TTI) {
+static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
+                                 DomTreeUpdater *DTU, const DataLayout &DL,
+                                 const TargetTransformInfo &TTI) {
   assert(SI->getNumCases() > 1 && "Degenerate switch?");
 
   BasicBlock *BB = SI->getParent();
@@ -7046,7 +7047,7 @@ static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
       // if no optsize is specified.
       const uint64_t UpperBound = CR.getUpper().getLimitedValue();
       if (!CR.isUpperWrapped() && all_of(ResultTypes, [&](const auto &KV) {
-            return SwitchLookupTable::wouldFitInRegister(
+            return SwitchReplacement::wouldFitInRegister(
                 DL, UpperBound, KV.second /* ResultType */);
           })) {
         // There may be some case index larger than the UpperBound (unreachable
@@ -7080,24 +7081,24 @@ static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
   }
 
   // Keep track of the tables we create for each phi node
-  struct TableInfo {
-    SwitchLookupTable Table;
-    Constant *DefaultValue;
+  struct ReplacementParams {
+    SwitchReplacement Replacer;
+    Constant *DefaultVal;
   };
-  // Find out what kind of table to create by creating a SwitchLookupTable
-  SmallDenseMap<PHINode *, TableInfo> PhiToTableMap;
+  // Keep track of the switch replacement for each phi
+  SmallDenseMap<PHINode *, ReplacementParams> PhiToReplacementMap;
   for (PHINode *PHI : PHIs) {
     const auto &ResultList = ResultLists[PHI];
 
     Type *ResultType = ResultList.begin()->second->getType();
     // Use any value to fill the lookup table holes.
-    Constant *DV =
+    Constant *DefaultVal =
         AllHolesArePoison ? PoisonValue::get(ResultType) : DefaultResults[PHI];
     StringRef FuncName = Fn->getName();
-    SwitchLookupTable Table(*Fn->getParent(), TableSize, TableIndexOffset,
-                            ResultList, DV, DL, FuncName);
-    TableInfo TI = {Table, DV};
-    PhiToTableMap.insert({PHI, TI});
+    SwitchReplacement Replacement(*Fn->getParent(), TableSize, TableIndexOffset,
+                                  ResultList, DefaultVal, DL, FuncName);
+    ReplacementParams Parameters = {Replacement, DefaultVal};
+    PhiToReplacementMap.insert({PHI, Parameters});
   }
 
   std::vector<DominatorTree::UpdateType> Updates;
@@ -7188,8 +7189,9 @@ static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
 
   for (PHINode *PHI : PHIs) {
     const ResultListTy &ResultList = ResultLists[PHI];
-    auto TableInfo = PhiToTableMap.at(PHI);
-    auto *Result = TableInfo.Table.buildLookup(TableIndex, Builder, DL, Fn);
+    auto TableInfo = PhiToReplacementMap.at(PHI);
+    auto *Result =
+        TableInfo.Replacer.replaceSwitch(TableIndex, Builder, DL, Fn);
     // Do a small peephole optimization: re-use the switch table compare if
     // possible.
     if (!TableHasHoles && HasDefaultResults && RangeCheckBranch) {
@@ -7197,7 +7199,7 @@ static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
       // Search for compare instructions which use the phi.
       for (auto *User : PHI->users()) {
         reuseTableCompare(User, PhiBlock, RangeCheckBranch,
-                          TableInfo.DefaultValue, ResultList);
+                          TableInfo.DefaultVal, ResultList);
       }
     }
 
@@ -7730,7 +7732,7 @@ bool SimplifyCFGOpt::simplifySwitch(SwitchInst *SI, IRBuilder<> &Builder) {
   // CVP. Therefore, only apply this transformation during late stages of the
   // optimisation pipeline.
   if (Options.ConvertSwitchToLookupTable &&
-      switchToLookupTable(SI, Builder, DTU, DL, TTI))
+      simplifySwitchLookup(SI, Builder, DTU, DL, TTI))
     return requestResimplify();
 
   if (simplifySwitchOfPowersOfTwo(SI, Builder, DL, TTI))
>From 7f26c6b4e6d2fe7378bf74d63c2649abbea4b778 Mon Sep 17 00:00:00 2001
From: Jessica Del <Jessica.Del at amd.com>
Date: Mon, 1 Sep 2025 11:49:45 +0200
Subject: [PATCH 07/11] fixup! SimplifyCFG: Renaming
---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index ebb51260f5be9..a9696b55cc3b2 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -6497,8 +6497,6 @@ class SwitchReplacement {
   bool LinearMapValWrapped = false;
 
   // For LookupTableKind, this is the table.
-  GlobalVariable *Table = nullptr;
-  ArrayType *TableTy = nullptr;
   Constant *Initializer = nullptr;
 };
 
@@ -6629,7 +6627,7 @@ SwitchReplacement::SwitchReplacement(
   }
 
   // Store the table in an array.
-  TableTy = ArrayType::get(ValueType, TableSize);
+  auto *TableTy = ArrayType::get(ValueType, TableSize);
   Initializer = ConstantArray::get(TableTy, TableContents);
 
   Kind = LookupTableKind;
@@ -6678,11 +6676,10 @@ Value *SwitchReplacement::replaceSwitch(Value *Index, IRBuilder<> &Builder,
     return Builder.CreateTrunc(DownShifted, BitMapElementTy, "switch.masked");
   }
   case LookupTableKind: {
-    // Only build lookup table when we have a target that supports it or the
-    // attribute is notable.
-    Table = new GlobalVariable(*Func->getParent(), TableTy, /*isConstant=*/true,
-                               GlobalVariable::PrivateLinkage, Initializer,
-                               "switch.table." + Func->getName());
+    auto *Table =
+        new GlobalVariable(*Func->getParent(), Initializer->getType(),
+                           /*isConstant=*/true, GlobalVariable::PrivateLinkage,
+                           Initializer, "switch.table." + Func->getName());
     Table->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
     // Set the alignment to that of an array items. We will be only loading one
     // value out of it.
>From f3ee6373d8292ad39512380bfc5563aae18d90bc Mon Sep 17 00:00:00 2001
From: Jessica Del <Jessica.Del at amd.com>
Date: Mon, 1 Sep 2025 11:49:45 +0200
Subject: [PATCH 08/11] fixup! SimplifyCFG: Move ResultType and NumResults
 calculation
---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index a9696b55cc3b2..88dfe8c45e387 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -6961,7 +6961,7 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
                         Results, DL, TTI))
       return false;
 
-    // Append the result  and result types from this case to the list for each
+    // Append the result and result types from this case to the list for each
     // phi.
     for (const auto &I : Results) {
       PHINode *PHI = I.first;
>From fea2badfb5f89bf878a1e7f0249a78e0adde56cc Mon Sep 17 00:00:00 2001
From: Jessica Del <Jessica.Del at amd.com>
Date: Mon, 1 Sep 2025 11:52:06 +0200
Subject: [PATCH 09/11] SimplifyCFG: Add DefaultValue to SwitchReplacement
Track the default switch value in the SwitchReplacement.
---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 54 ++++++++++++-----------
 1 file changed, 28 insertions(+), 26 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 88dfe8c45e387..97523f5b90968 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -6459,6 +6459,9 @@ class SwitchReplacement {
   static bool wouldFitInRegister(const DataLayout &DL, uint64_t TableSize,
                                  Type *ElementType);
 
+  /// Return the default value of the switch.
+  Constant *getDefaultValue();
+
 private:
   // Depending on the switch, there are different alternatives.
   enum {
@@ -6481,6 +6484,9 @@ class SwitchReplacement {
     LookupTableKind
   } Kind;
 
+  // The default value of the switch.
+  Constant *DefaultValue;
+
   // The type of the output values.
   Type *ValueType;
 
@@ -6505,7 +6511,8 @@ class SwitchReplacement {
 SwitchReplacement::SwitchReplacement(
     Module &M, uint64_t TableSize, ConstantInt *Offset,
     const SmallVectorImpl<std::pair<ConstantInt *, Constant *>> &Values,
-    Constant *DefaultValue, const DataLayout &DL, const StringRef &FuncName) {
+    Constant *DefaultValue, const DataLayout &DL, const StringRef &FuncName)
+    : DefaultValue(DefaultValue) {
   assert(Values.size() && "Can't build lookup table without values!");
   assert(TableSize >= Values.size() && "Can't fit values in table!");
 
@@ -6740,6 +6747,8 @@ static bool isTypeLegalForLookupTable(Type *Ty, const TargetTransformInfo &TTI,
          DL.fitsInLegalInteger(IT->getBitWidth());
 }
 
+Constant *SwitchReplacement::getDefaultValue() { return DefaultValue; }
+
 static bool isSwitchDense(uint64_t NumCases, uint64_t CaseRange) {
   // 40% is the default density for building a jump table in optsize/minsize
   // mode. See also TargetLoweringBase::isSuitableForJumpTable(), which this
@@ -7060,6 +7069,21 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
   if (!shouldBuildLookupTable(SI, TableSize, TTI, DL, ResultTypes))
     return false;
 
+  // Keep track of the switch replacement for each phi
+  SmallDenseMap<PHINode *, SwitchReplacement> PhiToReplacementMap;
+  for (PHINode *PHI : PHIs) {
+    const auto &ResultList = ResultLists[PHI];
+
+    Type *ResultType = ResultList.begin()->second->getType();
+    // Use any value to fill the lookup table holes.
+    Constant *DefaultVal =
+        AllHolesArePoison ? PoisonValue::get(ResultType) : DefaultResults[PHI];
+    StringRef FuncName = Fn->getName();
+    SwitchReplacement Replacement(*Fn->getParent(), TableSize, TableIndexOffset,
+                                  ResultList, DefaultVal, DL, FuncName);
+    PhiToReplacementMap.insert({PHI, Replacement});
+  }
+
   Builder.SetInsertPoint(SI);
   // TableIndex is the switch condition - TableIndexOffset if we don't
   // use the condition directly
@@ -7077,27 +7101,6 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
                                    /*HasNSW =*/!MayWrap);
   }
 
-  // Keep track of the tables we create for each phi node
-  struct ReplacementParams {
-    SwitchReplacement Replacer;
-    Constant *DefaultVal;
-  };
-  // Keep track of the switch replacement for each phi
-  SmallDenseMap<PHINode *, ReplacementParams> PhiToReplacementMap;
-  for (PHINode *PHI : PHIs) {
-    const auto &ResultList = ResultLists[PHI];
-
-    Type *ResultType = ResultList.begin()->second->getType();
-    // Use any value to fill the lookup table holes.
-    Constant *DefaultVal =
-        AllHolesArePoison ? PoisonValue::get(ResultType) : DefaultResults[PHI];
-    StringRef FuncName = Fn->getName();
-    SwitchReplacement Replacement(*Fn->getParent(), TableSize, TableIndexOffset,
-                                  ResultList, DefaultVal, DL, FuncName);
-    ReplacementParams Parameters = {Replacement, DefaultVal};
-    PhiToReplacementMap.insert({PHI, Parameters});
-  }
-
   std::vector<DominatorTree::UpdateType> Updates;
 
   // Compute the maximum table size representable by the integer type we are
@@ -7186,9 +7189,8 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
 
   for (PHINode *PHI : PHIs) {
     const ResultListTy &ResultList = ResultLists[PHI];
-    auto TableInfo = PhiToReplacementMap.at(PHI);
-    auto *Result =
-        TableInfo.Replacer.replaceSwitch(TableIndex, Builder, DL, Fn);
+    auto Replacement = PhiToReplacementMap.at(PHI);
+    auto *Result = Replacement.replaceSwitch(TableIndex, Builder, DL, Fn);
     // Do a small peephole optimization: re-use the switch table compare if
     // possible.
     if (!TableHasHoles && HasDefaultResults && RangeCheckBranch) {
@@ -7196,7 +7198,7 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
       // Search for compare instructions which use the phi.
       for (auto *User : PHI->users()) {
         reuseTableCompare(User, PhiBlock, RangeCheckBranch,
-                          TableInfo.DefaultVal, ResultList);
+                          Replacement.getDefaultValue(), ResultList);
       }
     }
 
>From 2689cd45bd3d2d6f82b56da83d4143fba0a78468 Mon Sep 17 00:00:00 2001
From: Jessica Del <Jessica.Del at amd.com>
Date: Mon, 1 Sep 2025 12:01:21 +0200
Subject: [PATCH 10/11] SimplifyCFG: Track ResultTypes as Vector
ResultTypes was a map of PHINodes to a Type, but the PHINode
key was never used.
Track the types in a SmallVector instead.
---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 30 +++++++++++------------
 1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 97523f5b90968..81dcc65f3b957 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -6775,18 +6775,16 @@ static bool isSwitchDense(ArrayRef<int64_t> Values) {
 // TODO: We could support larger than legal types by limiting based on the
 // number of loads required and/or table size. If the constants are small we
 // could use smaller table entries and extend after the load.
-static bool
-shouldBuildLookupTable(SwitchInst *SI, uint64_t TableSize,
-                       const TargetTransformInfo &TTI, const DataLayout &DL,
-                       const SmallDenseMap<PHINode *, Type *> &ResultTypes) {
+static bool shouldBuildLookupTable(SwitchInst *SI, uint64_t TableSize,
+                                   const TargetTransformInfo &TTI,
+                                   const DataLayout &DL,
+                                   const SmallVector<Type *> &ResultTypes) {
   if (SI->getNumCases() > TableSize)
     return false; // TableSize overflowed.
 
   bool AllTablesFitInRegister = true;
   bool HasIllegalType = false;
-  for (const auto &I : ResultTypes) {
-    Type *Ty = I.second;
-
+  for (const auto &Ty : ResultTypes) {
     // Saturate this flag to true.
     HasIllegalType = HasIllegalType || !isTypeLegalForLookupTable(Ty, TTI, DL);
 
@@ -6815,7 +6813,7 @@ shouldBuildLookupTable(SwitchInst *SI, uint64_t TableSize,
 
 static bool shouldUseSwitchConditionAsTableIndex(
     ConstantInt &MinCaseVal, const ConstantInt &MaxCaseVal,
-    bool HasDefaultResults, const SmallDenseMap<PHINode *, Type *> &ResultTypes,
+    bool HasDefaultResults, const SmallVector<Type *> &ResultTypes,
     const DataLayout &DL, const TargetTransformInfo &TTI) {
   if (MinCaseVal.isNullValue())
     return true;
@@ -6823,10 +6821,9 @@ static bool shouldUseSwitchConditionAsTableIndex(
       MaxCaseVal.getLimitedValue() == std::numeric_limits<uint64_t>::max() ||
       !HasDefaultResults)
     return false;
-  return all_of(ResultTypes, [&](const auto &KV) {
+  return all_of(ResultTypes, [&](const auto &ResultType) {
     return SwitchReplacement::wouldFitInRegister(
-        DL, MaxCaseVal.getLimitedValue() + 1 /* TableSize */,
-        KV.second /* ResultType */);
+        DL, MaxCaseVal.getLimitedValue() + 1 /* TableSize */, ResultType);
   });
 }
 
@@ -6953,7 +6950,7 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
   SmallDenseMap<PHINode *, ResultListTy> ResultLists;
 
   SmallDenseMap<PHINode *, Constant *> DefaultResults;
-  SmallDenseMap<PHINode *, Type *> ResultTypes;
+  SmallVector<Type *> ResultTypes;
   SmallVector<PHINode *, 4> PHIs;
 
   for (SwitchInst::CaseIt E = SI->case_end(); CI != E; ++CI) {
@@ -6979,7 +6976,7 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
       if (Inserted)
         PHIs.push_back(PHI);
       It->second.push_back(std::make_pair(CaseVal, Value));
-      ResultTypes[PHI] = ResultLists[PHI][0].second->getType();
+      ResultTypes.push_back(PHI->getType());
     }
   }
 
@@ -7052,9 +7049,10 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
       // TODO: Consider growing the table also when it doesn't fit in a register
       // if no optsize is specified.
       const uint64_t UpperBound = CR.getUpper().getLimitedValue();
-      if (!CR.isUpperWrapped() && all_of(ResultTypes, [&](const auto &KV) {
-            return SwitchReplacement::wouldFitInRegister(
-                DL, UpperBound, KV.second /* ResultType */);
+      if (!CR.isUpperWrapped() &&
+          all_of(ResultTypes, [&](const auto &ResultType) {
+            return SwitchReplacement::wouldFitInRegister(DL, UpperBound,
+                                                         ResultType);
           })) {
         // There may be some case index larger than the UpperBound (unreachable
         // case), so make sure the table size does not get smaller.
>From d85752bb6ca95c0e7da2fdabe3f765fef99d2671 Mon Sep 17 00:00:00 2001
From: Jessica Del <Jessica.Del at amd.com>
Date: Mon, 1 Sep 2025 13:43:26 +0200
Subject: [PATCH 11/11] fixup! SimplifyCFG: Move TableIndex further up to
 calculate TableSize earlier
---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 81dcc65f3b957..355cfd9df2032 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -7034,6 +7034,9 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
       return false;
   }
 
+  if (!shouldBuildLookupTable(SI, TableSize, TTI, DL, ResultTypes))
+    return false;
+
   // Compute the table index value.
   Value *TableIndex;
   if (UseSwitchConditionAsTableIndex) {
@@ -7064,9 +7067,6 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
     }
   }
 
-  if (!shouldBuildLookupTable(SI, TableSize, TTI, DL, ResultTypes))
-    return false;
-
   // Keep track of the switch replacement for each phi
   SmallDenseMap<PHINode *, SwitchReplacement> PhiToReplacementMap;
   for (PHINode *PHI : PHIs) {
    
    
More information about the llvm-commits
mailing list