aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
diff options
context:
space:
mode:
authorJessica Del <50999226+OutOfCache@users.noreply.github.com>2025-09-09 16:24:52 +0200
committerGitHub <noreply@github.com>2025-09-09 16:24:52 +0200
commit89d86b626cb29fbd7b476ea6f082256691444ad5 (patch)
treef12ca06dacad3f94f758f050b028c488e85dda36 /llvm/lib/Transforms/Utils/SimplifyCFG.cpp
parent4aa59f550a95803e876001e9f416af207d7936a8 (diff)
downloadllvm-89d86b626cb29fbd7b476ea6f082256691444ad5.zip
llvm-89d86b626cb29fbd7b476ea6f082256691444ad5.tar.gz
llvm-89d86b626cb29fbd7b476ea6f082256691444ad5.tar.bz2
SimplifyCFG: Enable switch replacements in more cases (#156477)
In some cases, we can replace a switch with simpler instructions or a lookup table. For instance, if every case results in the same value, we can simply replace the switch with that single value. However, lookup tables are not always supported. Targets, function attributes and compiler options can deactivate lookup table creation. Currently, even simpler switch replacements like the single value optimization do not get applied, because we only enable these transformations if lookup tables are enabled. This PR enables the other kinds of replacements, even if lookup tables are not supported. First, it checks if the potential replacements are lookup tables. If they are, then check if lookup tables are supported and whether to continue. If they are not, then we can apply the other transformations. Originally, lookup table creation was delayed until late stages of the compilation pipeline, because it can result in difficult-to-analyze code and prevent other optimizations. As a side effect of this change, we can also enable the simpler optimizations much earlier in the compilation process.
Diffstat (limited to 'llvm/lib/Transforms/Utils/SimplifyCFG.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyCFG.cpp30
1 files changed, 22 insertions, 8 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 39edc4d..970f853 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -6458,6 +6458,9 @@ public:
/// Return the default value of the switch.
Constant *getDefaultValue();
+ /// Return true if the replacement is a lookup table.
+ bool isLookupTable();
+
private:
// Depending on the switch, there are different alternatives.
enum {
@@ -6605,7 +6608,6 @@ SwitchReplacement::SwitchReplacement(
(void)M.smul_ov(APInt(M.getBitWidth(), TableSize - 1), MayWrap);
LinearMapValWrapped = NonMonotonic || MayWrap;
Kind = LinearMapKind;
- ++NumLinearMaps;
return;
}
}
@@ -6625,7 +6627,6 @@ SwitchReplacement::SwitchReplacement(
BitMap = ConstantInt::get(M.getContext(), TableInt);
BitMapElementTy = IT;
Kind = BitMapKind;
- ++NumBitMaps;
return;
}
@@ -6642,6 +6643,7 @@ Value *SwitchReplacement::replaceSwitch(Value *Index, IRBuilder<> &Builder,
case SingleValueKind:
return SingleValue;
case LinearMapKind: {
+ ++NumLinearMaps;
// Derive the result value from the input value.
Value *Result = Builder.CreateIntCast(Index, LinearMultiplier->getType(),
false, "switch.idx.cast");
@@ -6657,6 +6659,7 @@ Value *SwitchReplacement::replaceSwitch(Value *Index, IRBuilder<> &Builder,
return Result;
}
case BitMapKind: {
+ ++NumBitMaps;
// Type of the bitmap (e.g. i59).
IntegerType *MapTy = BitMap->getIntegerType();
@@ -6679,6 +6682,7 @@ Value *SwitchReplacement::replaceSwitch(Value *Index, IRBuilder<> &Builder,
return Builder.CreateTrunc(DownShifted, BitMapElementTy, "switch.masked");
}
case LookupTableKind: {
+ ++NumLookupTables;
auto *Table =
new GlobalVariable(*Func->getParent(), Initializer->getType(),
/*isConstant=*/true, GlobalVariable::PrivateLinkage,
@@ -6745,6 +6749,8 @@ static bool isTypeLegalForLookupTable(Type *Ty, const TargetTransformInfo &TTI,
Constant *SwitchReplacement::getDefaultValue() { return DefaultValue; }
+bool SwitchReplacement::isLookupTable() { return Kind == LookupTableKind; }
+
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
@@ -6915,11 +6921,6 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
BasicBlock *BB = SI->getParent();
Function *Fn = BB->getParent();
- // Only build lookup table when we have a target that supports it or the
- // attribute is not set.
- if (!TTI.shouldBuildLookupTables() ||
- (Fn->getFnAttribute("no-jump-tables").getValueAsBool()))
- return false;
// FIXME: If the switch is too sparse for a lookup table, perhaps we could
// split off a dense part and build a lookup table for that.
@@ -7078,6 +7079,20 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
PhiToReplacementMap.insert({PHI, Replacement});
}
+ bool AnyLookupTables = any_of(
+ PhiToReplacementMap, [](auto &KV) { return KV.second.isLookupTable(); });
+
+ // A few conditions prevent the generation of lookup tables:
+ // 1. The target does not support lookup tables.
+ // 2. The "no-jump-tables" function attribute is set.
+ // However, these objections do not apply to other switch replacements, like
+ // the bitmap, so we only stop here if any of these conditions are met and we
+ // want to create a LUT. Otherwise, continue with the switch replacement.
+ if (AnyLookupTables &&
+ (!TTI.shouldBuildLookupTables() ||
+ Fn->getFnAttribute("no-jump-tables").getValueAsBool()))
+ return false;
+
Builder.SetInsertPoint(SI);
// TableIndex is the switch condition - TableIndexOffset if we don't
// use the condition directly
@@ -7219,7 +7234,6 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
if (DTU)
DTU->applyUpdates(Updates);
- ++NumLookupTables;
if (NeedMask)
++NumLookupTablesHoles;
return true;