From d1fa777082da1eabf8d3515b2adcf01e90123387 Mon Sep 17 00:00:00 2001 From: XChy Date: Fri, 10 Oct 2025 18:20:00 +0800 Subject: [PATCH 1/2] [DFAJumpThreading] Precompute value - successor mapping --- .../Transforms/Scalar/DFAJumpThreading.cpp | 62 ++++++++++++------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp index e5935f4748c7f..683e64ec4b608 100644 --- a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp @@ -386,22 +386,6 @@ inline raw_ostream &operator<<(raw_ostream &OS, const PathType &Path) { return OS; } -/// Helper to get the successor corresponding to a particular case value for -/// a switch statement. -static BasicBlock *getNextCaseSuccessor(SwitchInst *Switch, - const APInt &NextState) { - BasicBlock *NextCase = nullptr; - for (auto Case : Switch->cases()) { - if (Case.getCaseValue()->getValue() == NextState) { - NextCase = Case.getCaseSuccessor(); - break; - } - } - if (!NextCase) - NextCase = Switch->getDefaultDest(); - return NextCase; -} - namespace { /// ThreadingPath is a path in the control flow of a loop that can be threaded /// by cloning necessary basic blocks and replacing conditional branches with @@ -835,19 +819,32 @@ struct AllSwitchPaths { TPaths = std::move(TempList); } + /// Fast helper to get the successor corresponding to a particular case value for + /// a switch statement. + BasicBlock *getNextCaseSuccessor(const APInt &NextState) { + // Precompute the value => successor mapping + if (CaseValToDest.empty()) { + for (auto Case : Switch->cases()) { + APInt CaseVal = Case.getCaseValue()->getValue(); + CaseValToDest[CaseVal] = Case.getCaseSuccessor(); + } + } + + auto SuccIt = CaseValToDest.find(NextState); + return SuccIt == CaseValToDest.end() ? Switch->getDefaultDest() + : SuccIt->second; + } + // Two states are equivalent if they have the same switch destination. // Unify the states in different threading path if the states are equivalent. void unifyTPaths() { - llvm::SmallDenseMap DestToState; + SmallDenseMap DestToState; for (ThreadingPath &Path : TPaths) { APInt NextState = Path.getExitValue(); - BasicBlock *Dest = getNextCaseSuccessor(Switch, NextState); - auto StateIt = DestToState.find(Dest); - if (StateIt == DestToState.end()) { - DestToState.insert({Dest, NextState}); + BasicBlock *Dest = getNextCaseSuccessor(NextState); + auto [StateIt, Inserted] = DestToState.try_emplace(Dest, NextState); + if (Inserted) continue; - } - if (NextState != StateIt->second) { LLVM_DEBUG(dbgs() << "Next state in " << Path << " is equivalent to " << StateIt->second << "\n"); @@ -861,6 +858,7 @@ struct AllSwitchPaths { BasicBlock *SwitchBlock; OptimizationRemarkEmitter *ORE; std::vector TPaths; + DenseMap CaseValToDest; LoopInfo *LI; Loop *SwitchOuterLoop; }; @@ -1162,6 +1160,24 @@ struct TransformDFA { SSAUpdate.RewriteAllUses(&DTU->getDomTree()); } + /// Helper to get the successor corresponding to a particular case value for + /// a switch statement. + /// TODO: Unify it with SwitchPaths->getNextCaseSuccessor(SwitchInst *Switch) + /// by updating cached value => successor mapping during threading. + static BasicBlock *getNextCaseSuccessor(SwitchInst *Switch, + const APInt &NextState) { + BasicBlock *NextCase = nullptr; + for (auto Case : Switch->cases()) { + if (Case.getCaseValue()->getValue() == NextState) { + NextCase = Case.getCaseSuccessor(); + break; + } + } + if (!NextCase) + NextCase = Switch->getDefaultDest(); + return NextCase; + } + /// Clones a basic block, and adds it to the CFG. /// /// This function also includes updating phi nodes in the successors of the From c8063ccff1afa00b744fcfb40433ca5d01533c28 Mon Sep 17 00:00:00 2001 From: XChy Date: Fri, 10 Oct 2025 18:44:47 +0800 Subject: [PATCH 2/2] format --- llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp index 683e64ec4b608..ff5f390d6fe18 100644 --- a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp @@ -819,8 +819,8 @@ struct AllSwitchPaths { TPaths = std::move(TempList); } - /// Fast helper to get the successor corresponding to a particular case value for - /// a switch statement. + /// Fast helper to get the successor corresponding to a particular case value + /// for a switch statement. BasicBlock *getNextCaseSuccessor(const APInt &NextState) { // Precompute the value => successor mapping if (CaseValToDest.empty()) {