[llvm] [IndirectBrExpand] Preserve profile weights (PR #227784)
Aiden Grossman via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 30 09:49:17 PDT 2026
https://github.com/boomanaiden154 updated https://github.com/llvm/llvm-project/pull/227784
>From a282b7299293ea66a0b8787cb9f7b4d7cfcdb6ef Mon Sep 17 00:00:00 2001
From: Aiden Grossman <aidengrossman at google.com>
Date: Wed, 30 Sep 2026 14:11:25 +0000
Subject: [PATCH] [IndirectBrExpand] Preserve profile weights
We can derive the weights for the created select instruction from the
weights of the indirectbr instructions that are used to compose it.
This is a no-op most of the time outside of some contexts, but
production users that utilize PGO do enable this (e.g., the kernel).
---
llvm/lib/CodeGen/IndirectBrExpandPass.cpp | 105 +++++++++++--
llvm/test/CodeGen/X86/O0-pipeline.ll | 6 +-
llvm/test/CodeGen/X86/opt-pipeline.ll | 5 +-
llvm/test/Transforms/IndirectBrExpand/pgo.ll | 148 +++++++++++++++++++
llvm/utils/profcheck-xfail.txt | 1 -
5 files changed, 249 insertions(+), 16 deletions(-)
create mode 100644 llvm/test/Transforms/IndirectBrExpand/pgo.ll
diff --git a/llvm/lib/CodeGen/IndirectBrExpandPass.cpp b/llvm/lib/CodeGen/IndirectBrExpandPass.cpp
index e7a22656f17c2..d04c964be8788 100644
--- a/llvm/lib/CodeGen/IndirectBrExpandPass.cpp
+++ b/llvm/lib/CodeGen/IndirectBrExpandPass.cpp
@@ -25,9 +25,12 @@
///
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/DomTreeUpdater.h"
+#include "llvm/Analysis/LazyBlockFrequencyInfo.h"
#include "llvm/CodeGen/IndirectBrExpand.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
@@ -36,6 +39,7 @@
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/ProfDataUtils.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/ErrorHandling.h"
@@ -46,6 +50,10 @@ using namespace llvm;
#define DEBUG_TYPE "indirectbr-expand"
+namespace llvm {
+extern cl::opt<bool> ProfcheckDisableMetadataFixes;
+} // namespace llvm
+
namespace {
class IndirectBrExpandLegacyPass : public FunctionPass {
@@ -55,6 +63,7 @@ class IndirectBrExpandLegacyPass : public FunctionPass {
IndirectBrExpandLegacyPass() : FunctionPass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
+ LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
AU.addPreserved<DominatorTreeWrapperPass>();
}
@@ -63,8 +72,8 @@ class IndirectBrExpandLegacyPass : public FunctionPass {
} // end anonymous namespace
-static bool runImpl(Function &F, const TargetLowering *TLI,
- DomTreeUpdater *DTU);
+static bool runImpl(Function &F, const TargetLowering *TLI, DomTreeUpdater *DTU,
+ function_ref<BlockFrequencyInfo *()> GetBFI);
PreservedAnalyses IndirectBrExpandPass::run(Function &F,
FunctionAnalysisManager &FAM) {
@@ -76,7 +85,9 @@ PreservedAnalyses IndirectBrExpandPass::run(Function &F,
auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(F);
DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
- bool Changed = runImpl(F, TLI, DT ? &DTU : nullptr);
+ bool Changed = runImpl(F, TLI, DT ? &DTU : nullptr, [&]() {
+ return &FAM.getResult<BlockFrequencyAnalysis>(F);
+ });
if (!Changed)
return PreservedAnalyses::all();
PreservedAnalyses PA;
@@ -96,13 +107,19 @@ FunctionPass *llvm::createIndirectBrExpandPass() {
return new IndirectBrExpandLegacyPass();
}
-bool runImpl(Function &F, const TargetLowering *TLI, DomTreeUpdater *DTU) {
+bool runImpl(Function &F, const TargetLowering *TLI, DomTreeUpdater *DTU,
+ function_ref<BlockFrequencyInfo *()> GetBFI) {
auto &DL = F.getDataLayout();
SmallVector<IndirectBrInst *, 1> IndirectBrs;
+ SmallVector<uint64_t, 1> IndirectBrsBlockFrequencies;
+ SmallVector<uint64_t, 1> IndirectBrsBranchWeightSums;
+ bool SkipProfileUpdates = false;
+ BlockFrequencyInfo *BFI = nullptr;
// Set of all potential successors for indirectbr instructions.
- SmallPtrSet<BasicBlock *, 4> IndirectBrSuccs;
+ DenseMap<const BasicBlock *, SmallVector<std::pair<size_t, uint64_t>>>
+ IndirectBrSuccToIndirectBr;
// Build a list of indirectbrs that we want to rewrite.
for (BasicBlock &BB : F)
@@ -116,7 +133,31 @@ bool runImpl(Function &F, const TargetLowering *TLI, DomTreeUpdater *DTU) {
}
IndirectBrs.push_back(IBr);
- IndirectBrSuccs.insert_range(IBr->successors());
+ for (const BasicBlock *SuccessorBB : IBr->successors())
+ IndirectBrSuccToIndirectBr.insert({SuccessorBB, {}});
+
+ if (SkipProfileUpdates)
+ continue;
+ if (!BFI)
+ BFI = GetBFI();
+ std::optional<uint64_t> BlockFrequency = BFI->getBlockProfileCount(&BB);
+ if (!BlockFrequency.has_value()) {
+ SkipProfileUpdates = true;
+ continue;
+ }
+ IndirectBrsBlockFrequencies.push_back(*BlockFrequency);
+ SmallVector<uint32_t> IndirectBrBranchWeights;
+ bool HasBranchWeights =
+ extractBranchWeights(*IBr, IndirectBrBranchWeights);
+ if (!HasBranchWeights) {
+ SkipProfileUpdates = true;
+ continue;
+ }
+ for (const auto [SuccessorBB, SuccessorBranchWeight] :
+ zip_equal(IBr->successors(), IndirectBrBranchWeights))
+ IndirectBrSuccToIndirectBr[SuccessorBB].push_back(
+ {IndirectBrs.size() - 1, SuccessorBranchWeight});
+ IndirectBrsBranchWeightSums.push_back(sum_of(IndirectBrBranchWeights));
}
if (IndirectBrs.empty())
@@ -127,11 +168,13 @@ bool runImpl(Function &F, const TargetLowering *TLI, DomTreeUpdater *DTU) {
// whose address escapes. We do that here and rewrite all the blockaddress
// constants to just be those integer constants cast to a pointer type.
SmallVector<BasicBlock *, 4> BBs;
+ SmallVector<ScaledNumber<uint64_t>, 4> BBWeights;
for (BasicBlock &BB : F) {
// Skip blocks that aren't successors to an indirectbr we're going to
// rewrite.
- if (!IndirectBrSuccs.count(&BB))
+ auto IndirectBrSuccToIndirectBrIt = IndirectBrSuccToIndirectBr.find(&BB);
+ if (IndirectBrSuccToIndirectBrIt == IndirectBrSuccToIndirectBr.end())
continue;
auto *BA = BlockAddress::lookup(&BB);
@@ -154,6 +197,23 @@ bool runImpl(Function &F, const TargetLowering *TLI, DomTreeUpdater *DTU) {
// expressions, for instance, where they are used to pass labels to
// asm-goto. This part of the pass needs a rework.
BA->replaceAllUsesWith(ConstantExpr::getIntToPtr(BBIndexC, BA->getType()));
+
+ if (SkipProfileUpdates)
+ continue;
+ ScaledNumber<uint64_t> BranchWeightSumsProduct(1, 0);
+ for (uint64_t BranchWeightSum : IndirectBrsBranchWeightSums)
+ BranchWeightSumsProduct *= ScaledNumber<uint64_t>(BranchWeightSum, 0);
+ ScaledNumber<uint64_t> BlockWeight(0, 0);
+ for (const auto &[IndirectBrIndex, BlockBranchProbability] :
+ IndirectBrSuccToIndirectBrIt->second) {
+ BlockWeight += ScaledNumber<uint64_t>(
+ IndirectBrsBlockFrequencies[IndirectBrIndex], 0) *
+ ScaledNumber<uint64_t>(BlockBranchProbability, 0) *
+ (BranchWeightSumsProduct /
+ ScaledNumber<uint64_t>(
+ IndirectBrsBranchWeightSums[IndirectBrIndex], 0));
+ }
+ BBWeights.push_back(BlockWeight);
}
if (BBs.empty()) {
@@ -161,7 +221,7 @@ bool runImpl(Function &F, const TargetLowering *TLI, DomTreeUpdater *DTU) {
// cannot get a valid input and we can replace all of them with unreachable.
SmallVector<DominatorTree::UpdateType, 8> Updates;
if (DTU)
- Updates.reserve(IndirectBrSuccs.size());
+ Updates.reserve(IndirectBrSuccToIndirectBr.size());
for (auto *IBr : IndirectBrs) {
if (DTU) {
for (BasicBlock *SuccBB : IBr->successors())
@@ -171,7 +231,7 @@ bool runImpl(Function &F, const TargetLowering *TLI, DomTreeUpdater *DTU) {
IBr->eraseFromParent();
}
if (DTU) {
- assert(Updates.size() == IndirectBrSuccs.size() &&
+ assert(Updates.size() == IndirectBrSuccToIndirectBr.size() &&
"Got unexpected update count.");
DTU->applyUpdates(Updates);
}
@@ -206,10 +266,10 @@ bool runImpl(Function &F, const TargetLowering *TLI, DomTreeUpdater *DTU) {
SwitchBB = IBr->getParent();
SwitchValue = GetSwitchValue(IBr);
if (DTU) {
- Updates.reserve(IndirectBrSuccs.size());
+ Updates.reserve(IndirectBrSuccToIndirectBr.size());
for (BasicBlock *SuccBB : IBr->successors())
Updates.push_back({DominatorTree::Delete, IBr->getParent(), SuccBB});
- assert(Updates.size() == IndirectBrSuccs.size() &&
+ assert(Updates.size() == IndirectBrSuccToIndirectBr.size() &&
"Got unexpected update count.");
}
IBr->eraseFromParent();
@@ -225,7 +285,8 @@ bool runImpl(Function &F, const TargetLowering *TLI, DomTreeUpdater *DTU) {
// Now replace the indirectbr instructions with direct branches to the
// switch block and fill out the PHI operands.
if (DTU)
- Updates.reserve(IndirectBrs.size() + 2 * IndirectBrSuccs.size());
+ Updates.reserve(IndirectBrs.size() +
+ 2 * IndirectBrSuccToIndirectBr.size());
for (auto *IBr : IndirectBrs) {
SwitchPN->addIncoming(GetSwitchValue(IBr), IBr->getParent());
UncondBrInst::Create(SwitchBB, IBr->getIterator());
@@ -258,6 +319,22 @@ bool runImpl(Function &F, const TargetLowering *TLI, DomTreeUpdater *DTU) {
DTU->applyUpdates(Updates);
}
+ if (SkipProfileUpdates || ProfcheckDisableMetadataFixes) {
+ setExplicitlyUnknownBranchWeightsIfProfiled(*SI, DEBUG_TYPE);
+ return true;
+ }
+
+ int16_t MaxScale = 0;
+ for (const ScaledNumber<uint64_t> &BBWeight : BBWeights)
+ MaxScale = std::max(MaxScale, BBWeight.getScale());
+ SmallVector<uint64_t, 4> ExtractedBBWeights;
+ ExtractedBBWeights.reserve(BBWeights.size());
+ for (ScaledNumber<uint64_t> &BBWeight : BBWeights) {
+ int16_t Shift = MaxScale - BBWeight.getScale();
+ ExtractedBBWeights.push_back(BBWeight.getDigits() >> Shift);
+ }
+ setFittedBranchWeights(*SI, ExtractedBBWeights, false);
+
return true;
}
@@ -276,5 +353,7 @@ bool IndirectBrExpandLegacyPass::runOnFunction(Function &F) {
if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
DTU.emplace(DTWP->getDomTree(), DomTreeUpdater::UpdateStrategy::Lazy);
- return runImpl(F, TLI, DTU ? &*DTU : nullptr);
+ return runImpl(F, TLI, DTU ? &*DTU : nullptr, [&]() {
+ return &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
+ });
}
diff --git a/llvm/test/CodeGen/X86/O0-pipeline.ll b/llvm/test/CodeGen/X86/O0-pipeline.ll
index e8a3084563573..a139af7720e3d 100644
--- a/llvm/test/CodeGen/X86/O0-pipeline.ll
+++ b/llvm/test/CodeGen/X86/O0-pipeline.ll
@@ -30,7 +30,11 @@
; CHECK-NEXT: Instrument function entry/exit with calls to e.g. mcount() (post inlining)
; CHECK-NEXT: Scalarize Masked Memory Intrinsics
; CHECK-NEXT: Expand reduction intrinsics
-; CHECK-NEXT: Expand indirectbr instructions
+; CHECK-NEXT: Dominator Tree Construction
+; CHECK-NEXT: Cycle Info Analysis
+; CHECK-NEXT: Lazy Branch Probability Analysis
+; CHECK-NEXT: Lazy Block Frequency Analysis
+; CHECK-NEXT: Expand indirectbr instructions
; CHECK-NEXT: Exception handling preparation
; CHECK-NEXT: Prepare inline asm insts
; CHECK-NEXT: Safe Stack instrumentation pass
diff --git a/llvm/test/CodeGen/X86/opt-pipeline.ll b/llvm/test/CodeGen/X86/opt-pipeline.ll
index 47d97871274ae..58fb03b8f94a5 100644
--- a/llvm/test/CodeGen/X86/opt-pipeline.ll
+++ b/llvm/test/CodeGen/X86/opt-pipeline.ll
@@ -66,7 +66,10 @@
; CHECK-NEXT: Expand reduction intrinsics
; CHECK-NEXT: Interleaved Access Pass
; CHECK-NEXT: X86 Partial Reduction
-; CHECK-NEXT: Expand indirectbr instructions
+; CHECK-NEXT: Cycle Info Analysis
+; CHECK-NEXT: Lazy Branch Probability Analysis
+; CHECK-NEXT: Lazy Block Frequency Analysis
+; CHECK-NEXT: Expand indirectbr instructions
; CHECK-NEXT: Natural Loop Information
; CHECK-NEXT: Cycle Info Analysis
; CHECK-NEXT: Post-Dominator Tree Construction
diff --git a/llvm/test/Transforms/IndirectBrExpand/pgo.ll b/llvm/test/Transforms/IndirectBrExpand/pgo.ll
new file mode 100644
index 0000000000000..82f9ca445660f
--- /dev/null
+++ b/llvm/test/Transforms/IndirectBrExpand/pgo.ll
@@ -0,0 +1,148 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 6
+; RUN: opt < %s -passes=indirectbr-expand -S | FileCheck %s
+;
+; REQUIRES: x86-registered-target
+
+target triple = "x86_64-unknown-linux-gnu"
+
+ at test1.targets = constant [4 x ptr] [ptr blockaddress(@test1, %bb0),
+ ptr blockaddress(@test1, %bb1),
+ ptr blockaddress(@test1, %bb2),
+ ptr blockaddress(@test1, %bb3)]
+
+;.
+; CHECK: @test1.targets = constant [4 x ptr] [ptr inttoptr (i64 1 to ptr), ptr inttoptr (i64 2 to ptr), ptr inttoptr (i64 3 to ptr), ptr blockaddress(@test1, %bb3)]
+; CHECK: @missing_branch_weights.targets = constant [2 x ptr] [ptr inttoptr (i64 1 to ptr), ptr inttoptr (i64 2 to ptr)]
+;.
+define void @test1(ptr readonly %p, ptr %sink) #0 !prof !0 {
+; CHECK-LABEL: define void @test1(
+; CHECK-SAME: ptr readonly [[P:%.*]], ptr [[SINK:%.*]]) #[[ATTR0:[0-9]+]] !prof [[PROF0:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[BR_SELECT_I:%.*]] = load i64, ptr [[P]], align 8
+; CHECK-NEXT: [[BR_SELECT_CMP:%.*]] = icmp eq i64 [[BR_SELECT_I]], 64
+; CHECK-NEXT: br i1 [[BR_SELECT_CMP]], label %[[BR1:.*]], label %[[BR2:.*]], !prof [[PROF1:![0-9]+]]
+; CHECK: [[BR1]]:
+; CHECK-NEXT: [[I0:%.*]] = load i64, ptr [[P]], align 8
+; CHECK-NEXT: [[TARGET_I0:%.*]] = getelementptr [4 x ptr], ptr @test1.targets, i64 0, i64 [[I0]]
+; CHECK-NEXT: [[TARGET0:%.*]] = load ptr, ptr [[TARGET_I0]], align 8
+; CHECK-NEXT: [[TARGET0_SWITCH_CAST:%.*]] = ptrtoint ptr [[TARGET0]] to i64
+; CHECK-NEXT: br label %[[SWITCH_BB:.*]]
+; CHECK: [[BR2]]:
+; CHECK-NEXT: [[I_NEXT:%.*]] = load i64, ptr [[P]], align 8
+; CHECK-NEXT: [[TARGET_I_NEXT:%.*]] = getelementptr [4 x ptr], ptr @test1.targets, i64 0, i64 [[I_NEXT]]
+; CHECK-NEXT: [[TARGET_NEXT:%.*]] = load ptr, ptr [[TARGET_I_NEXT]], align 8
+; CHECK-NEXT: [[TARGET_NEXT_SWITCH_CAST:%.*]] = ptrtoint ptr [[TARGET_NEXT]] to i64
+; CHECK-NEXT: br label %[[SWITCH_BB]]
+; CHECK: [[BB0:.*]]:
+; CHECK-NEXT: store volatile i64 0, ptr [[SINK]], align 8
+; CHECK-NEXT: br label %[[EXIT:.*]]
+; CHECK: [[BB1:.*]]:
+; CHECK-NEXT: store volatile i64 1, ptr [[SINK]], align 8
+; CHECK-NEXT: br label %[[EXIT]]
+; CHECK: [[BB2:.*]]:
+; CHECK-NEXT: store volatile i64 2, ptr [[SINK]], align 8
+; CHECK-NEXT: br label %[[EXIT]]
+; CHECK: [[BB3:.*:]]
+; CHECK-NEXT: store volatile i64 3, ptr [[SINK]], align 8
+; CHECK-NEXT: br label %[[EXIT]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: ret void
+; CHECK: [[SWITCH_BB]]:
+; CHECK-NEXT: [[SWITCH_VALUE_PHI:%.*]] = phi i64 [ [[TARGET0_SWITCH_CAST]], %[[BR1]] ], [ [[TARGET_NEXT_SWITCH_CAST]], %[[BR2]] ]
+; CHECK-NEXT: switch i64 [[SWITCH_VALUE_PHI]], label %[[BB0]] [
+; CHECK-NEXT: i64 2, label %[[BB1]]
+; CHECK-NEXT: i64 3, label %[[BB2]]
+; CHECK-NEXT: ], !prof [[PROF2:![0-9]+]]
+;
+entry:
+ %br.select.i = load i64, ptr %p
+ %br.select.cmp = icmp eq i64 %br.select.i, 64
+ br i1 %br.select.cmp, label %br1, label %br2, !prof !1
+
+br1:
+ %i0 = load i64, ptr %p
+ %target.i0 = getelementptr [4 x ptr], ptr @test1.targets, i64 0, i64 %i0
+ %target0 = load ptr, ptr %target.i0
+ ; Only a subset of blocks are viable successors here.
+ indirectbr ptr %target0, [label %bb0, label %bb1], !prof !2
+
+br2:
+ %i.next = load i64, ptr %p
+ %target.i.next = getelementptr [4 x ptr], ptr @test1.targets, i64 0, i64 %i.next
+ %target.next = load ptr, ptr %target.i.next
+ ; A different subset of blocks are viable successors here.
+ indirectbr ptr %target.next, [label %bb1, label %bb2], !prof !3
+
+bb0:
+ store volatile i64 0, ptr %sink
+ br label %exit
+
+bb1:
+ store volatile i64 1, ptr %sink
+ br label %exit
+
+bb2:
+ store volatile i64 2, ptr %sink
+ br label %exit
+
+bb3:
+ store volatile i64 3, ptr %sink
+ br label %exit
+
+exit:
+ ret void
+}
+
+ at missing_branch_weights.targets = constant [2 x ptr] [ptr blockaddress(@missing_branch_weights, %bb0),
+ ptr blockaddress(@missing_branch_weights, %bb1)]
+
+define void @missing_branch_weights(ptr readonly %p, ptr %sink) #0 !prof !0 {
+; CHECK-LABEL: define void @missing_branch_weights(
+; CHECK-SAME: ptr readonly [[P:%.*]], ptr [[SINK:%.*]]) #[[ATTR0]] !prof [[PROF0]] {
+; CHECK-NEXT: [[I0:%.*]] = load i64, ptr [[P]], align 8
+; CHECK-NEXT: [[TARGET_I0:%.*]] = getelementptr [4 x ptr], ptr @missing_branch_weights.targets, i64 0, i64 [[I0]]
+; CHECK-NEXT: [[TARGET0:%.*]] = load ptr, ptr [[TARGET_I0]], align 8
+; CHECK-NEXT: [[TARGET0_SWITCH_CAST:%.*]] = ptrtoint ptr [[TARGET0]] to i64
+; CHECK-NEXT: switch i64 [[TARGET0_SWITCH_CAST]], label %[[BB0:.*]] [
+; CHECK-NEXT: i64 2, label %[[BB1:.*]]
+; CHECK-NEXT: ], !prof [[PROF3:![0-9]+]]
+; CHECK: [[BB0]]:
+; CHECK-NEXT: store volatile i64 0, ptr [[SINK]], align 8
+; CHECK-NEXT: br label %[[EXIT:.*]]
+; CHECK: [[BB1]]:
+; CHECK-NEXT: store volatile i64 1, ptr [[SINK]], align 8
+; CHECK-NEXT: br label %[[EXIT]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: ret void
+;
+ %i0 = load i64, ptr %p
+ %target.i0 = getelementptr [4 x ptr], ptr @missing_branch_weights.targets, i64 0, i64 %i0
+ %target0 = load ptr, ptr %target.i0
+ indirectbr ptr %target0, [label %bb0, label %bb1]
+
+bb0:
+ store volatile i64 0, ptr %sink
+ br label %exit
+
+bb1:
+ store volatile i64 1, ptr %sink
+ br label %exit
+
+exit:
+ ret void
+}
+
+attributes #0 = { "target-features"="+retpoline" }
+
+!0 = !{!"function_entry_count", i32 10}
+!1 = !{!"branch_weights", i32 1, i32 2}
+!2 = !{!"branch_weights", i32 3, i32 5}
+!3 = !{!"branch_weights", i32 7, i32 11}
+;.
+; CHECK: attributes #[[ATTR0]] = { "target-features"="+retpoline" }
+;.
+; CHECK: [[PROF0]] = !{!"function_entry_count", i32 10}
+; CHECK: [[PROF1]] = !{!"branch_weights", i32 1, i32 2}
+; CHECK: [[PROF2]] = !{!"branch_weights", i32 162, i32 662, i32 616}
+; CHECK: [[PROF3]] = !{!"unknown", !"indirectbr-expand"}
+;.
diff --git a/llvm/utils/profcheck-xfail.txt b/llvm/utils/profcheck-xfail.txt
index c2b5009a63c80..a12670679eb24 100644
--- a/llvm/utils/profcheck-xfail.txt
+++ b/llvm/utils/profcheck-xfail.txt
@@ -26,7 +26,6 @@ Transforms/IndVarSimplify/debugloc-rem-subst.ll
Transforms/IndVarSimplify/eliminate-rem.ll
Transforms/IndVarSimplify/pr45835.ll
Transforms/IndVarSimplify/preserving-debugloc-rem-div.ll
-Transforms/IndirectBrExpand/basic.ll
Transforms/InstCombine/canonicalize-clamp-like-pattern-between-negative-and-positive-thresholds.ll
Transforms/InstCombine/canonicalize-clamp-like-pattern-between-zero-and-positive-threshold.ll
Transforms/InstCombine/cast-mul-select.ll
More information about the llvm-commits
mailing list