[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