[profcheck][InstCombine] Preserve weights for xor statements (#175678)

When simplifying an xor statement with logical boolean operands, we may
be able to preserve branch weight data if the simplified instruction's
conditional was the first operand of one of the two logical boolean
inputs.

Tracking issue: #147390
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index b496110..9450b28 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -5478,15 +5478,20 @@
       match(&I, m_c_Xor(m_OneUse(m_LogicalAnd(m_Value(A), m_Value(B))),
                         m_OneUse(m_LogicalOr(m_Value(C), m_Value(D)))))) {
     bool NeedFreeze = isa<SelectInst>(Op0) && isa<SelectInst>(Op1) && B == D;
-    if (B == C || B == D)
+    Instruction *MDFrom = cast<Instruction>(Op0);
+    if (B == C || B == D) {
       std::swap(A, B);
+      MDFrom = B == C ? cast<Instruction>(Op1) : nullptr;
+    }
     if (A == C)
       std::swap(C, D);
     if (A == D) {
       if (NeedFreeze)
         A = Builder.CreateFreeze(A);
       Value *NotB = Builder.CreateNot(B);
-      return SelectInst::Create(A, NotB, C);
+      return MDFrom == nullptr || ProfcheckDisableMetadataFixes
+                 ? createSelectInstWithUnknownProfile(A, NotB, C)
+                 : SelectInst::Create(A, NotB, C, "", nullptr, MDFrom);
     }
   }
 
diff --git a/llvm/test/Transforms/InstCombine/xor-and-or.ll b/llvm/test/Transforms/InstCombine/xor-and-or.ll
index c380e27..2e0a209 100644
--- a/llvm/test/Transforms/InstCombine/xor-and-or.ll
+++ b/llvm/test/Transforms/InstCombine/xor-and-or.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
 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
 
 define i1 @xor_logic_and_logic_or1(i1 %c, i1 %x, i1 %y) {
@@ -13,39 +13,39 @@
   ret i1 %r
 }
 
-define i1 @xor_logic_and_logic_or2(i1 %c, i1 %x, i1 %y) {
+define i1 @xor_logic_and_logic_or2(i1 %c, i1 %x, i1 %y) !prof !0 {
 ; CHECK-LABEL: @xor_logic_and_logic_or2(
 ; CHECK-NEXT:    [[TMP1:%.*]] = xor i1 [[X:%.*]], true
-; CHECK-NEXT:    [[R:%.*]] = select i1 [[C:%.*]], i1 [[TMP1]], i1 [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[C:%.*]], i1 [[TMP1]], i1 [[Y:%.*]], !prof [[PROF1:![0-9]+]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
-  %o = select i1 %y, i1 true, i1 %c
-  %a = select i1 %c, i1 %x, i1 false
+  %o = select i1 %y, i1 true, i1 %c, !prof !1
+  %a = select i1 %c, i1 %x, i1 false, !prof !2
   %r = xor i1 %a, %o
   ret i1 %r
 }
 
-define i1 @xor_logic_and_logic_or2_commuted(i1 %c, i1 %x, i1 %y) {
+define i1 @xor_logic_and_logic_or2_commuted(i1 %c, i1 %x, i1 %y) !prof !0 {
 ; CHECK-LABEL: @xor_logic_and_logic_or2_commuted(
 ; CHECK-NEXT:    [[TMP1:%.*]] = xor i1 [[X:%.*]], true
-; CHECK-NEXT:    [[R:%.*]] = select i1 [[C:%.*]], i1 [[TMP1]], i1 [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[C:%.*]], i1 [[TMP1]], i1 [[Y:%.*]], !prof [[PROF2:![0-9]+]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
-  %o = select i1 %y, i1 true, i1 %c
-  %a = select i1 %c, i1 %x, i1 false
+  %o = select i1 %y, i1 true, i1 %c, !prof !1
+  %a = select i1 %c, i1 %x, i1 false, !prof !2
   %r = xor i1 %o, %a
   ret i1 %r
 }
 
-define i1 @xor_logic_and_logic_or3(i1 %c, i1 %x, i1 %y) {
+define i1 @xor_logic_and_logic_or3(i1 %c, i1 %x, i1 %y) !prof !0 {
 ; CHECK-LABEL: @xor_logic_and_logic_or3(
 ; CHECK-NEXT:    [[TMP1:%.*]] = freeze i1 [[C:%.*]]
 ; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[X:%.*]], true
-; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i1 [[TMP2]], i1 [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i1 [[TMP2]], i1 [[Y:%.*]], !prof [[PROF3:![0-9]+]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
-  %o = select i1 %y, i1 true, i1 %c
-  %a = select i1 %x, i1 %c, i1 false
+  %o = select i1 %y, i1 true, i1 %c, !prof !1
+  %a = select i1 %x, i1 %c, i1 false, !prof !2
   %r = xor i1 %a, %o
   ret i1 %r
 }
@@ -254,3 +254,13 @@
 }
 
 declare void @use(i1)
+
+!0 = !{!"function_entry_count", i64 1000}
+!1 = !{!"branch_weights", i32 2, i32 3}
+!2 = !{!"branch_weights", i32 5, i32 7}
+;.
+; CHECK: [[META0:![0-9]+]] = !{!"function_entry_count", i64 1000}
+; CHECK: [[PROF1]] = !{!"branch_weights", i32 5, i32 7}
+; CHECK: [[PROF2]] = !{!"branch_weights", i32 2, i32 3}
+; CHECK: [[PROF3]] = !{!"unknown", !"instcombine"}
+;.