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 <[email protected]> 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} +;. _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
