[llvm-branch-commits] [llvm] [InstCombine][profcheck] Propogate profile metadata when transforming br (X && !Y) to br (!X || Y) (PR #175939)
Snehasish Kumar via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Jan 14 10:46:07 PST 2026
https://github.com/snehasish updated https://github.com/llvm/llvm-project/pull/175939
>From c5bed226dcb6a4000c852fbce5e259f78138ee93 Mon Sep 17 00:00:00 2001
From: Snehasish Kumar <snehasishk at google.com>
Date: Wed, 14 Jan 2026 12:12:06 +0000
Subject: [PATCH] [InstCombine][profcheck] Propogate profile metadata when
transforming br (X && !Y) to br (!X || Y)
Updated visitBranchInst to propagate and swap !prof metadata when transforming br (X && !Y) to br (!X || Y).
---
.../InstCombine/InstructionCombining.cpp | 12 +++++
llvm/test/Transforms/InstCombine/branch.ll | 54 +++++++++++--------
2 files changed, 43 insertions(+), 23 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 13eef3ccbfc43..5af33acacb69f 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -4234,6 +4234,18 @@ Instruction *InstCombinerImpl::visitBranchInst(BranchInst &BI) {
Value *NotX = Builder.CreateNot(X, "not." + X->getName());
Value *Or = Builder.CreateLogicalOr(NotX, Y);
BI.swapSuccessors();
+ // Swap branch weights since we've swapped successors.
+ if (!ProfcheckDisableMetadataFixes) {
+ if (auto *OrInst = dyn_cast<Instruction>(Or)) {
+ if (auto *CondInst = dyn_cast<Instruction>(Cond)) {
+ SmallVector<uint32_t> Weights;
+ if (extractBranchWeights(*CondInst, Weights) && Weights.size() == 2) {
+ std::swap(Weights[0], Weights[1]);
+ setBranchWeights(*OrInst, Weights, /*IsExpected=*/false);
+ }
+ }
+ }
+ }
if (BPI)
BPI->swapSuccEdgesProbabilities(BI.getParent());
return replaceOperand(BI, 0, Or);
diff --git a/llvm/test/Transforms/InstCombine/branch.ll b/llvm/test/Transforms/InstCombine/branch.ll
index 1d5ff72eef9ce..40b2c56a243be 100644
--- a/llvm/test/Transforms/InstCombine/branch.ll
+++ b/llvm/test/Transforms/InstCombine/branch.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals smart
; RUN: opt -passes=instcombine -S < %s | FileCheck %s
declare void @use(i1)
@@ -8,7 +8,7 @@ declare void @use(i1)
define i32 @test(i32 %x) {
; CHECK-LABEL: @test(
; CHECK-NEXT: entry:
-; CHECK-NEXT: br i1 false, label [[MERGE:%.*]], label [[MERGE]]
+; CHECK-NEXT: br i1 false, label [[MERGE:%.*]], label [[MERGE]], !prof [[PROF1:![0-9]+]]
; CHECK: merge:
; CHECK-NEXT: ret i32 [[X:%.*]]
;
@@ -23,7 +23,7 @@ merge:
define i32 @pat(i32 %x) {
; CHECK-LABEL: @pat(
-; CHECK-NEXT: br i1 false, label [[PATATINO:%.*]], label [[PATATINO]]
+; CHECK-NEXT: br i1 false, label [[PATATINO:%.*]], label [[PATATINO]], !prof [[PROF1]]
; CHECK: patatino:
; CHECK-NEXT: ret i32 [[X:%.*]]
;
@@ -36,13 +36,13 @@ patatino:
define i1 @test01(i1 %cond) {
; CHECK-LABEL: @test01(
; CHECK-NEXT: entry:
-; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_TRUE_1:%.*]], label [[IF_FALSE_1:%.*]]
+; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_TRUE_1:%.*]], label [[IF_FALSE_1:%.*]], !prof [[PROF1]]
; CHECK: if.true.1:
; CHECK-NEXT: br label [[MERGE_1:%.*]]
; CHECK: if.false.1:
; CHECK-NEXT: br label [[MERGE_1]]
; CHECK: merge.1:
-; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE_2:%.*]], label [[IF_FALSE_2:%.*]]
+; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE_2:%.*]], label [[IF_FALSE_2:%.*]], !prof [[PROF1]]
; CHECK: if.true.2:
; CHECK-NEXT: br label [[MERGE_2:%.*]]
; CHECK: if.false.2:
@@ -77,13 +77,13 @@ merge.2:
define i1 @test02(i1 %cond) {
; CHECK-LABEL: @test02(
; CHECK-NEXT: entry:
-; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_TRUE_1:%.*]], label [[IF_FALSE_1:%.*]]
+; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_TRUE_1:%.*]], label [[IF_FALSE_1:%.*]], !prof [[PROF1]]
; CHECK: if.true.1:
; CHECK-NEXT: br label [[MERGE_1:%.*]]
; CHECK: if.false.1:
; CHECK-NEXT: br label [[MERGE_1]]
; CHECK: merge.1:
-; CHECK-NEXT: br i1 [[COND]], label [[IF_FALSE_2:%.*]], label [[IF_TRUE_2:%.*]]
+; CHECK-NEXT: br i1 [[COND]], label [[IF_FALSE_2:%.*]], label [[IF_TRUE_2:%.*]], !prof [[PROF1]]
; CHECK: if.true.2:
; CHECK-NEXT: br label [[MERGE_2:%.*]]
; CHECK: if.false.2:
@@ -121,8 +121,8 @@ define i32 @logical_and_not(i1 %x, i1 %y) {
; CHECK-LABEL: @logical_and_not(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[NOT_X:%.*]] = xor i1 [[X:%.*]], true
-; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[NOT_X]], i1 true, i1 [[Y:%.*]]
-; CHECK-NEXT: br i1 [[TMP0]], label [[F:%.*]], label [[T:%.*]]
+; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[NOT_X]], i1 true, i1 [[Y:%.*]], !prof [[PROF2:![0-9]+]]
+; CHECK-NEXT: br i1 [[TMP0]], label [[F:%.*]], label [[T:%.*]], !prof [[PROF1]]
; CHECK: t:
; CHECK-NEXT: ret i32 42
; CHECK: f:
@@ -130,7 +130,7 @@ define i32 @logical_and_not(i1 %x, i1 %y) {
;
entry:
%noty = xor i1 %y, true
- %and = select i1 %x, i1 %noty, i1 false
+ %and = select i1 %x, i1 %noty, i1 false, !prof !0
br i1 %and, label %t, label %f
t:
@@ -140,14 +140,16 @@ f:
ret i32 3
}
+!0 = !{!"branch_weights", i32 10, i32 20}
+
; if (x && y || !x) ret 3; ret 42 --> if (!x || y) ret 3; ret 42
define i32 @logical_and_or(i1 %x, i1 %y) {
; CHECK-LABEL: @logical_and_or(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[NOT_X:%.*]] = xor i1 [[X:%.*]], true
-; CHECK-NEXT: [[AND:%.*]] = select i1 [[NOT_X]], i1 true, i1 [[Y:%.*]]
-; CHECK-NEXT: br i1 [[AND]], label [[F:%.*]], label [[T:%.*]]
+; CHECK-NEXT: [[AND:%.*]] = select i1 [[NOT_X]], i1 true, i1 [[Y:%.*]], !prof [[PROF3:![0-9]+]]
+; CHECK-NEXT: br i1 [[AND]], label [[F:%.*]], label [[T:%.*]], !prof [[PROF1]]
; CHECK: t:
; CHECK-NEXT: ret i32 42
; CHECK: f:
@@ -170,8 +172,8 @@ define i32 @logical_or_not(i1 %x, i1 %y) {
; CHECK-LABEL: @logical_or_not(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
-; CHECK-NEXT: [[AND:%.*]] = select i1 [[NOTX]], i1 true, i1 [[Y:%.*]]
-; CHECK-NEXT: br i1 [[AND]], label [[F:%.*]], label [[T:%.*]]
+; CHECK-NEXT: [[AND:%.*]] = select i1 [[NOTX]], i1 true, i1 [[Y:%.*]], !prof [[PROF4:![0-9]+]]
+; CHECK-NEXT: br i1 [[AND]], label [[F:%.*]], label [[T:%.*]], !prof [[PROF1]]
; CHECK: t:
; CHECK-NEXT: ret i32 42
; CHECK: f:
@@ -196,8 +198,8 @@ define i32 @logical_and_not_use1(i1 %x, i1 %y) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
; CHECK-NEXT: call void @use(i1 [[NOTY]])
-; CHECK-NEXT: [[AND:%.*]] = select i1 [[X:%.*]], i1 [[NOTY]], i1 false
-; CHECK-NEXT: br i1 [[AND]], label [[T:%.*]], label [[F:%.*]]
+; CHECK-NEXT: [[AND:%.*]] = select i1 [[X:%.*]], i1 [[NOTY]], i1 false, !prof [[PROF4]]
+; CHECK-NEXT: br i1 [[AND]], label [[T:%.*]], label [[F:%.*]], !prof [[PROF1]]
; CHECK: t:
; CHECK-NEXT: ret i32 42
; CHECK: f:
@@ -222,9 +224,9 @@ define i32 @logical_and_not_use2(i1 %x, i1 %y) {
; CHECK-LABEL: @logical_and_not_use2(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
-; CHECK-NEXT: [[AND:%.*]] = select i1 [[X:%.*]], i1 [[NOTY]], i1 false
+; CHECK-NEXT: [[AND:%.*]] = select i1 [[X:%.*]], i1 [[NOTY]], i1 false, !prof [[PROF4]]
; CHECK-NEXT: call void @use(i1 [[AND]])
-; CHECK-NEXT: br i1 [[AND]], label [[T:%.*]], label [[F:%.*]]
+; CHECK-NEXT: br i1 [[AND]], label [[T:%.*]], label [[F:%.*]], !prof [[PROF1]]
; CHECK: t:
; CHECK-NEXT: ret i32 42
; CHECK: f:
@@ -245,7 +247,7 @@ f:
define i32 @dom_true(i1 %cmp) {
; CHECK-LABEL: @dom_true(
-; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]], !prof [[PROF1]]
; CHECK: if.then:
; CHECK-NEXT: ret i32 1
; CHECK: if.else:
@@ -263,7 +265,7 @@ if.else:
define i32 @dom_false(i1 %cmp) {
; CHECK-LABEL: @dom_false(
-; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
+; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]], !prof [[PROF1]]
; CHECK: if.then:
; CHECK-NEXT: ret i32 0
; CHECK: if.else:
@@ -281,7 +283,7 @@ if.else:
define i32 @dom_true_phi(i1 %cmp) {
; CHECK-LABEL: @dom_true_phi(
-; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]], !prof [[PROF1]]
; CHECK: if.then:
; CHECK-NEXT: br label [[IF_END:%.*]]
; CHECK: if.else:
@@ -308,7 +310,7 @@ if.end:
define i32 @same_dest(i1 %cmp) {
; CHECK-LABEL: @same_dest(
-; CHECK-NEXT: br i1 false, label [[IF_THEN:%.*]], label [[IF_THEN]]
+; CHECK-NEXT: br i1 false, label [[IF_THEN:%.*]], label [[IF_THEN]], !prof [[PROF1]]
; CHECK: if.then:
; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP:%.*]] to i32
; CHECK-NEXT: ret i32 [[ZEXT]]
@@ -322,7 +324,7 @@ if.then:
define i32 @not_dom(i1 %cmp) {
; CHECK-LABEL: @not_dom(
-; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]], !prof [[PROF1]]
; CHECK: if.then:
; CHECK-NEXT: br label [[IF_ELSE]]
; CHECK: if.else:
@@ -338,3 +340,9 @@ if.else:
%zext = zext i1 %cmp to i32
ret i32 %zext
}
+;.
+; CHECK: [[PROF1]] = !{!"branch_weights", i32 1, i32 1}
+; CHECK: [[PROF2]] = !{!"branch_weights", i32 20, i32 10}
+; CHECK: [[PROF3]] = !{!"branch_weights", i32 3, i32 2}
+; CHECK: [[PROF4]] = !{!"branch_weights", i32 2, i32 3}
+;.
More information about the llvm-branch-commits
mailing list