[llvm-branch-commits] [llvm] release/23.x: [PGO] Fix PGO instrumentation for selects with poison condition (#229002) (PR #230041)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Oct 8 02:34:34 PDT 2026


https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/230041

Backport 48102564a14886db6ba759325446907e2e1cfe71

Requested by: @nikic

>From ab4cd6da4e1b0803eb50c4c4caf694a704b08668 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Thu, 8 Oct 2026 10:05:47 +0200
Subject: [PATCH] [PGO] Fix PGO instrumentation for selects with poison
 condition (#229002)

PGO instrumentation for selects currently emits an
instrprof.increment.step, where the step is a zext of the select
condition (0 if false, 1 if true). However, if the condition is poison,
then the zext is poison and ends up taking an arbitray, possibly very
large, value, which then gets detected as a corrupted profile.

To avoid this, freeze the condition before extending. A poison select
condition can then add 0 or 1 to the counter, but no other value. I
believe that is the best we can do for poison conditions.

Fixes https://github.com/llvm/llvm-project/issues/228895.

(cherry picked from commit 48102564a14886db6ba759325446907e2e1cfe71)
---
 .../Transforms/Instrumentation/PGOInstrumentation.cpp    | 8 +++++++-
 llvm/test/Analysis/CtxProfAnalysis/handle-select.ll      | 5 +++--
 llvm/test/Transforms/PGOProfile/select1.ll               | 9 +++++++++
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
index f6fcb41636000..86479f23f995a 100644
--- a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
+++ b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
@@ -66,6 +66,7 @@
 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
 #include "llvm/Analysis/ProfileSummaryInfo.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/ValueTracking.h"
 #include "llvm/IR/Attributes.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/CFG.h"
@@ -1824,7 +1825,12 @@ void SelectInstVisitor::instrumentOneSelectInst(SelectInst &SI) {
   Module *M = F.getParent();
   IRBuilder<> Builder(&SI);
   Type *Int64Ty = Builder.getInt64Ty();
-  auto *Step = Builder.CreateZExt(SI.getCondition(), Int64Ty);
+  Value *Cond = SI.getCondition();
+  // Freeze the condition so that a poison condition can only increment by
+  // 0 or 1, but not some other value.
+  if (!isGuaranteedNotToBePoison(Cond))
+    Cond = Builder.CreateFreeze(Cond);
+  auto *Step = Builder.CreateZExt(Cond, Int64Ty);
   auto *NormalizedFuncNameVarPtr =
       ConstantExpr::getPointerBitCastOrAddrSpaceCast(
           FuncNameVar, PointerType::get(M->getContext(), 0));
diff --git a/llvm/test/Analysis/CtxProfAnalysis/handle-select.ll b/llvm/test/Analysis/CtxProfAnalysis/handle-select.ll
index 1880672580eb8..53f8aee99f9a0 100644
--- a/llvm/test/Analysis/CtxProfAnalysis/handle-select.ll
+++ b/llvm/test/Analysis/CtxProfAnalysis/handle-select.ll
@@ -21,8 +21,9 @@
 ; INSTR-NEXT:   call void @llvm.instrprof.increment(ptr @bar, i64 [[#]], i32 2, i32 0)
 ; INSTR-NEXT:   %inc =
 ; INSTR:        %test = icmp eq i32 %t, 0
-; INSTR-NEXT:   %1  = zext i1 %test to i64
-; INSTR-NEXT:   call void @llvm.instrprof.increment.step(ptr @bar, i64 [[#]], i32 2, i32 1, i64 %1)
+; INSTR-NEXT:   [[FREEZE:%.*]] = freeze i1 %test
+; INSTR-NEXT:   [[ZEXT:%.*]] = zext i1 [[FREEZE]] to i64
+; INSTR-NEXT:   call void @llvm.instrprof.increment.step(ptr @bar, i64 [[#]], i32 2, i32 1, i64 [[ZEXT]])
 ; INSTR-NEXT:   %res = select
 
 ; POST-INL-LABEL: yes:
diff --git a/llvm/test/Transforms/PGOProfile/select1.ll b/llvm/test/Transforms/PGOProfile/select1.ll
index 51626e6391218..decd58cddbef0 100644
--- a/llvm/test/Transforms/PGOProfile/select1.ll
+++ b/llvm/test/Transforms/PGOProfile/select1.ll
@@ -29,3 +29,12 @@ if.end:
   %retv = phi i32 [ %add, %if.then ], [ %sub, %if.else ]
   ret i32 %retv
 }
+
+define i32 @test_select_maybe_poison(i1 %cmp) {
+; GEN: %[[FREEZE:[0-9]+]] = freeze i1 %cmp
+; GEN: %[[STEP:[0-9]+]] = zext i1 %[[FREEZE]] to i64
+; GEN: call void @llvm.instrprof.increment.step({{.*}} i32 2, i32 1, i64 %[[STEP]])
+; NOSELECT-NOT: call void @llvm.instrprof.increment.step
+  %s = select i1 %cmp, i32 1, i32 2
+  ret i32 %s
+}



More information about the llvm-branch-commits mailing list