Skip to content

Commit 14c98bc

Browse files
[CHR] Fix crash when marking merged condition unknown (#173902)
CHR builds the merged hot-path predicate with IRBuilder::CreateLogicalAnd. That helper is implemented as a select and can constant-fold to a non- Instruction (e.g. i1 true). The pass then attempted to mark the merged condition as having explicitly unknown branch weights when profile data is present, but it unconditionally did cast<Instruction>(MergedCondition), which can crash in release builds. Guard the metadata update with dyn_cast<Instruction> and pass the containing Function explicitly to avoid calling Instruction::getFunction when the value is not attached yet. Add a regression test that exercises the constant-folding case. Crashing stack: ``` 2. Running pass "chr" on function "repro_crash" #0 0x0000000003be00a4 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (bin/opt+0x3be00a4) #1 0x0000000003bdd9e8 llvm::sys::RunSignalHandlers() (bin/opt+0x3bdd9e8) #2 0x0000000003be1300 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0 intel#3 0x0000ffffa8e1d840 (linux-vdso.so.1+0x840) intel#4 0x0000000003c815e0 llvm::Instruction::getFunction() const (bin/opt+0x3c815e0) intel#5 0x0000000003dcd35c llvm::setExplicitlyUnknownBranchWeightsIfProfiled(llvm::Instruction&, llvm::StringRef, llvm::Function const*) (bin/opt+0x3dcd35c) intel#6 0x0000000004fb3670 (anonymous namespace)::CHR::addToMergedCondition(bool, llvm::Value*, llvm::Instruction*, (anonymous namespace)::CHRScope*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::Value*&) ControlHeightReduction.cpp:0:0 intel#7 0x0000000004fa7d88 (anonymous namespace)::CHR::run() ControlHeightReduction.cpp:0:0 intel#8 0x0000000004fa3618 llvm::ControlHeightReductionPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (bin/opt+0x4fa3618) ``` Tests: opt < llvm/test/Transforms/PGOProfile/chr-unknown-profdata-crash.ll -passes='require<profile-summary>,function(chr)' -force-chr -chr-merge-threshold=1 -disable-output
1 parent db9549c commit 14c98bc

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,8 +1992,8 @@ void CHR::addToMergedCondition(bool IsTrueBiased, Value *Cond,
19921992

19931993
// Use logical and to avoid propagating poison from later conditions.
19941994
MergedCondition = IRB.CreateLogicalAnd(MergedCondition, Cond);
1995-
setExplicitlyUnknownBranchWeightsIfProfiled(
1996-
*cast<Instruction>(MergedCondition), DEBUG_TYPE);
1995+
if (auto *MergedInst = dyn_cast<Instruction>(MergedCondition))
1996+
setExplicitlyUnknownBranchWeightsIfProfiled(*MergedInst, DEBUG_TYPE, &F);
19971997
}
19981998

19991999
void CHR::transformScopes(SmallVectorImpl<CHRScope *> &CHRScopes) {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; RUN: opt < %s -passes='require<profile-summary>,function(chr)' -force-chr -chr-merge-threshold=1 -disable-output
2+
3+
; Regression test for a crash in CHR when setting unknown profdata on the
4+
; merged condition. IRBuilder::CreateLogicalAnd is implemented as a select and
5+
; can constant-fold to a non-Instruction value (e.g. `i1 true`). The buggy code
6+
; assumed it always produced an Instruction and did `cast<Instruction>(V)`,
7+
; which can segfault in release builds.
8+
define void @repro_crash() {
9+
entry:
10+
br i1 true, label %then, label %exit, !prof !15
11+
12+
then:
13+
br label %exit
14+
15+
exit:
16+
ret void
17+
}
18+
19+
!llvm.module.flags = !{!0}
20+
!0 = !{i32 1, !"ProfileSummary", !1}
21+
!1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
22+
!2 = !{!"ProfileFormat", !"InstrProf"}
23+
!3 = !{!"TotalCount", i64 10000}
24+
!4 = !{!"MaxCount", i64 10}
25+
!5 = !{!"MaxInternalCount", i64 1}
26+
!6 = !{!"MaxFunctionCount", i64 1000}
27+
!7 = !{!"NumCounts", i64 1}
28+
!8 = !{!"NumFunctions", i64 1}
29+
!9 = !{!"DetailedSummary", !10}
30+
!10 = !{!11}
31+
!11 = !{i32 999999, i64 1, i32 1}
32+
33+
!15 = !{!"branch_weights", i32 100, i32 1}

0 commit comments

Comments
 (0)