Author: Nikita Popov
Date: 2026-07-16T08:59:19+02:00
New Revision: 6f3a1e431f9f8bae9f78244c8ee1a38203dc62b6

URL: 
https://github.com/llvm/llvm-project/commit/6f3a1e431f9f8bae9f78244c8ee1a38203dc62b6
DIFF: 
https://github.com/llvm/llvm-project/commit/6f3a1e431f9f8bae9f78244c8ee1a38203dc62b6.diff

LOG: Revert "[MergeFunctions] Preserve instruction-level profile metadata 
during m…"

This reverts commit 687fbfae778ac2953c35920fb042446ef967c239.

Added: 
    

Modified: 
    llvm/include/llvm/Transforms/IPO/MergeFunctions.h
    llvm/lib/Transforms/IPO/MergeFunctions.cpp
    llvm/unittests/Transforms/IPO/MergeFunctionsTest.cpp

Removed: 
    llvm/test/Transforms/MergeFunc/merge-functions-branch-weights.ll
    
llvm/test/Transforms/MergeFunc/merge-functions-reordered-blocks-branch-weights.ll
    llvm/test/Transforms/MergeFunc/merge-functions-select-weights.ll
    llvm/test/Transforms/MergeFunc/merge-functions-value-profile.ll


################################################################################
diff  --git a/llvm/include/llvm/Transforms/IPO/MergeFunctions.h 
b/llvm/include/llvm/Transforms/IPO/MergeFunctions.h
index d28d6167e5555..75399d3297a05 100644
--- a/llvm/include/llvm/Transforms/IPO/MergeFunctions.h
+++ b/llvm/include/llvm/Transforms/IPO/MergeFunctions.h
@@ -28,9 +28,9 @@ class MergeFunctionsPass : public 
OptionalPassInfoMixin<MergeFunctionsPass> {
 public:
   LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
 
-  LLVM_ABI static bool runOnModule(Module &M, ModuleAnalysisManager &AM);
+  LLVM_ABI static bool runOnModule(Module &M);
   LLVM_ABI static DenseMap<Function *, Function *>
-  runOnFunctions(ArrayRef<Function *> Funcs, ModuleAnalysisManager &AM);
+  runOnFunctions(ArrayRef<Function *> F);
 };
 
 } // end namespace llvm

diff  --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp 
b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
index afe80da5843ca..c4e56855ea2fb 100644
--- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp
+++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
@@ -89,15 +89,9 @@
 
//===----------------------------------------------------------------------===//
 
 #include "llvm/Transforms/IPO/MergeFunctions.h"
-#include "llvm/ADT/APInt.h"
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/PostOrderIterator.h"
-#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Statistic.h"
-#include "llvm/Analysis/BlockFrequencyInfo.h"
-#include "llvm/Analysis/BranchProbabilityInfo.h"
 #include "llvm/IR/Argument.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/DebugInfoMetadata.h"
@@ -110,21 +104,16 @@
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
-#include "llvm/IR/Metadata.h"
 #include "llvm/IR/Module.h"
-#include "llvm/IR/PassManager.h"
-#include "llvm/IR/ProfDataUtils.h"
 #include "llvm/IR/StructuralHash.h"
 #include "llvm/IR/Type.h"
 #include "llvm/IR/Use.h"
 #include "llvm/IR/User.h"
 #include "llvm/IR/Value.h"
 #include "llvm/IR/ValueHandle.h"
-#include "llvm/ProfileData/InstrProf.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/IPO.h"
@@ -132,10 +121,7 @@
 #include "llvm/Transforms/Utils/ModuleUtils.h"
 #include <algorithm>
 #include <cassert>
-#include <cstddef>
-#include <cstdint>
 #include <iterator>
-#include <memory>
 #include <optional>
 #include <set>
 #include <utility>
@@ -208,11 +194,11 @@ class FunctionNode {
 /// bitcast of the other.
 class MergeFunctions {
 public:
-  explicit MergeFunctions(FunctionAnalysisManager &FAM)
-      : FnTree(FunctionNodeCmp(&GlobalNumbers)), FAM(FAM) {}
+  MergeFunctions() : FnTree(FunctionNodeCmp(&GlobalNumbers)) {
+  }
 
   template <typename FuncContainer> bool run(FuncContainer &Functions);
-  DenseMap<Function *, Function *> runOnFunctions(ArrayRef<Function *> Funcs);
+  DenseMap<Function *, Function *> runOnFunctions(ArrayRef<Function *> F);
 
   SmallPtrSet<GlobalValue *, 4> &getUsed();
 
@@ -271,8 +257,6 @@ class MergeFunctions {
   /// again.
   void mergeTwoFunctions(Function *F, Function *G);
 
-  void mergeInstrProfMetadataInto(Function *Dst, Function *Src);
-
   /// Fill PDIUnrelatedWL with instructions from the entry block that are
   /// unrelated to parameter related debug info.
   /// \param PDVRUnrelatedWL The equivalent non-intrinsic debug records.
@@ -303,9 +287,7 @@ class MergeFunctions {
   // If needed, replace G with an alias to F if possible, or a thunk to F if
   // profitable. Returns false if neither is the case. If \p G is not needed
   // (i.e. it is discardable and not used), \p G is removed directly.
-  // \p MergeProfile must be true when G's profile should be preserved, it is
-  // merged into F before G is erased or rewritten.
-  bool writeThunkOrAliasIfNeeded(Function *F, Function *G, bool MergeProfile);
+  bool writeThunkOrAliasIfNeeded(Function *F, Function *G);
 
   /// Replace function F with function G in the function tree.
   void replaceFunctionInTree(const FunctionNode &FN, Function *G);
@@ -323,23 +305,20 @@ class MergeFunctions {
 
   /// Deleted-New functions mapping
   DenseMap<Function *, Function *> DelToNewMap;
-
-  FunctionAnalysisManager &FAM;
 };
 } // end anonymous namespace
 
 PreservedAnalyses MergeFunctionsPass::run(Module &M,
                                           ModuleAnalysisManager &AM) {
-  if (!MergeFunctionsPass::runOnModule(M, AM))
+  if (!MergeFunctionsPass::runOnModule(M))
     return PreservedAnalyses::all();
   return PreservedAnalyses::none();
 }
 
 SmallPtrSet<GlobalValue *, 4> &MergeFunctions::getUsed() { return Used; }
 
-bool MergeFunctionsPass::runOnModule(Module &M, ModuleAnalysisManager &AM) {
-  auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
-  MergeFunctions MF(FAM);
+bool MergeFunctionsPass::runOnModule(Module &M) {
+  MergeFunctions MF;
   SmallVector<GlobalValue *, 4> UsedV;
   collectUsedGlobalVariables(M, UsedV, /*CompilerUsed=*/false);
   collectUsedGlobalVariables(M, UsedV, /*CompilerUsed=*/true);
@@ -348,15 +327,9 @@ bool MergeFunctionsPass::runOnModule(Module &M, 
ModuleAnalysisManager &AM) {
 }
 
 DenseMap<Function *, Function *>
-MergeFunctionsPass::runOnFunctions(ArrayRef<Function *> Funcs,
-                                   ModuleAnalysisManager &AM) {
-  if (Funcs.empty())
-    return DenseMap<Function *, Function *>();
-
-  Module &M = *Funcs.front()->getParent();
-  auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
-  MergeFunctions MF(FAM);
-  return MF.runOnFunctions(Funcs);
+MergeFunctionsPass::runOnFunctions(ArrayRef<Function *> F) {
+  MergeFunctions MF;
+  return MF.runOnFunctions(F);
 }
 
 #ifndef NDEBUG
@@ -520,8 +493,8 @@ template <typename FuncContainer> bool 
MergeFunctions::run(FuncContainer &M) {
 }
 
 DenseMap<Function *, Function *>
-MergeFunctions::runOnFunctions(ArrayRef<Function *> Funcs) {
-  [[maybe_unused]] bool MergeResult = this->run(Funcs);
+MergeFunctions::runOnFunctions(ArrayRef<Function *> F) {
+  [[maybe_unused]] bool MergeResult = this->run(F);
   assert(MergeResult == !DelToNewMap.empty());
   return this->DelToNewMap;
 }
@@ -761,7 +734,7 @@ static void copyMetadataIfPresent(Function *From, Function 
*To,
 // For better debugability, under MergeFunctionsPDI, we do not modify G's
 // call sites to point to F even when within the same translation unit.
 void MergeFunctions::writeThunk(Function *F, Function *G) {
-  std::optional<uint64_t> GEntryCount = G->getEntryCount();
+  std::optional<uint64_t> GEC = G->getEntryCount();
   BasicBlock *GEntryBlock = nullptr;
   std::vector<Instruction *> PDIUnrelatedWL;
   std::vector<DbgVariableRecord *> PDVRUnrelatedWL;
@@ -831,8 +804,8 @@ void MergeFunctions::writeThunk(Function *F, Function *G) {
                << G->getName() << "()\n");
   } else {
     NewG->copyAttributesFrom(G);
-    if (GEntryCount)
-      NewG->setEntryCount(*GEntryCount);
+    if (GEC)
+      NewG->setEntryCount(*GEC);
     NewG->takeName(G);
     // Ensure CFI type metadata is propagated to the new function.
     copyMetadataIfPresent(G, NewG, "type");
@@ -885,36 +858,21 @@ void MergeFunctions::writeAlias(Function *F, Function *G) 
{
 
 // If needed, replace G with an alias to F if possible, or a thunk to F if
 // profitable. Returns false if neither is the case. If \p G is not needed 
(i.e.
-// it is discardable and unused), \p G is removed directly. If \p MergeProfile
-// is set, G's profile metadata is merged into F.
-bool MergeFunctions::writeThunkOrAliasIfNeeded(Function *F, Function *G,
-                                               bool MergeProfile) {
-  bool ShouldErase =
-      G->isDiscardableIfUnused() && G->use_empty() && !MergeFunctionsPDI;
-  bool ShouldAlias = canCreateAliasFor(G);
-  bool ShouldThunk = canCreateThunkFor(F);
-
-  if (!ShouldErase && !ShouldAlias && !ShouldThunk)
-    return false;
-
-  if (MergeProfile)
-    mergeInstrProfMetadataInto(F, G);
-
-  if (ShouldErase) {
+// it is discardable and unused), \p G is removed directly.
+bool MergeFunctions::writeThunkOrAliasIfNeeded(Function *F, Function *G) {
+  if (G->isDiscardableIfUnused() && G->use_empty() && !MergeFunctionsPDI) {
     G->eraseFromParent();
     return true;
   }
-
-  if (ShouldAlias) {
+  if (canCreateAliasFor(G)) {
     writeAlias(F, G);
     return true;
   }
-  if (ShouldThunk) {
+  if (canCreateThunkFor(F)) {
     writeThunk(F, G);
     return true;
   }
-
-  llvm_unreachable("Erase, alias or thunk must apply");
+  return false;
 }
 
 /// Returns true if \p F is either weak_odr or linkonce_odr.
@@ -922,174 +880,6 @@ static bool isODR(const Function *F) {
   return F->hasWeakODRLinkage() || F->hasLinkOnceODRLinkage();
 }
 
-static uint64_t getBlockCountForMerging(const BlockFrequencyInfo &BFI,
-                                        const BasicBlock *BB) {
-  if (auto Count = BFI.getBlockProfileCount(BB, /*AllowSynthetic=*/true))
-    return *Count;
-  return 1;
-}
-
-// The branch weights are relative within a function. Before merging we
-// normalize these to absolute counts.
-// (weight * BlockCount / TotalWeight)
-static uint64_t scaleToBlockCount(uint64_t Weight, uint64_t TotalWeight,
-                                  uint64_t BlockCount) {
-  if (Weight == 0 || TotalWeight == 0 || BlockCount == 0)
-    return 0;
-  APInt Num(128, BlockCount);
-  Num *= APInt(128, Weight);
-  APInt Den(128, TotalWeight);
-  Num = (Num + Den.lshr(1)).udiv(Den);
-  assert(Num.getActiveBits() <= 64 &&
-         "scaleToBlockCount: result exceeds uint64_t; Weight > TotalWeight?");
-  return Num.getLimitedValue();
-}
-
-// Combine the scaled branch_weights of corresponding instructions of F and G.
-static void mergeBranchWeightsOnInstructions(Instruction *DstI,
-                                             const Instruction *SrcI,
-                                             const BlockFrequencyInfo &DstBFI,
-                                             const BlockFrequencyInfo &SrcBFI) 
{
-  SmallVector<uint32_t, 8> DstWeights, SrcWeights;
-  bool HasDst = extractBranchWeights(*DstI, DstWeights);
-  bool HasSrc = extractBranchWeights(*SrcI, SrcWeights);
-  if (!HasDst && !HasSrc)
-    return;
-
-  uint64_t DstBlockCount = getBlockCountForMerging(DstBFI, DstI->getParent());
-  uint64_t SrcBlockCount = getBlockCountForMerging(SrcBFI, SrcI->getParent());
-
-  uint64_t DstTotal = 0, SrcTotal = 0;
-  if (HasDst)
-    extractProfTotalWeight(*DstI, DstTotal);
-  if (HasSrc)
-    extractProfTotalWeight(*SrcI, SrcTotal);
-
-  assert((!HasDst || !HasSrc || DstWeights.size() == SrcWeights.size()) &&
-         "equivalent branch/select instructions must have matching weight "
-         "arity");
-  size_t NumWeights = HasDst ? DstWeights.size() : SrcWeights.size();
-  SmallVector<uint64_t, 8> MergedWeights;
-  MergedWeights.reserve(NumWeights);
-  for (size_t I = 0; I < NumWeights; ++I) {
-    uint64_t DstW = HasDst ? DstWeights[I] : 0;
-    uint64_t SrcW = HasSrc ? SrcWeights[I] : 0;
-    uint64_t DstAbs = scaleToBlockCount(DstW, DstTotal, DstBlockCount);
-    uint64_t SrcAbs = scaleToBlockCount(SrcW, SrcTotal, SrcBlockCount);
-    MergedWeights.push_back(SaturatingAdd(DstAbs, SrcAbs));
-  }
-
-  bool IsExpected =
-      hasBranchWeightOrigin(*DstI) && hasBranchWeightOrigin(*SrcI);
-  setFittedBranchWeights(*DstI, MergedWeights, IsExpected);
-}
-
-// Accumulate value profile counts of Instruction I into Merged. Value profile
-// counts are absolute, not relative branch-style weights.
-static void addValueProfile(const Instruction &I, InstrProfValueKind Kind,
-                            DenseMap<uint64_t, uint64_t> &Merged) {
-  uint64_t Total = 0;
-  SmallVector<InstrProfValueData, 4> VDs =
-      getValueProfDataFromInst(I, Kind, /*MaxNumValueData=*/UINT32_MAX, Total);
-  if (VDs.empty())
-    return;
-  for (const InstrProfValueData &VD : VDs)
-    Merged[VD.Value] = SaturatingAdd(Merged[VD.Value], VD.Count);
-}
-
-// Merge (union) value profiles of Dst and Src.
-static void mergeValueProfileOnInstructions(Instruction *DstI,
-                                            const Instruction *SrcI) {
-  MDNode *DstProf = DstI->getMetadata(LLVMContext::MD_prof);
-  MDNode *SrcProf = SrcI->getMetadata(LLVMContext::MD_prof);
-  bool HasDst = DstProf && isValueProfileMD(DstProf);
-  bool HasSrc = SrcProf && isValueProfileMD(SrcProf);
-  if (!HasDst && !HasSrc)
-    return;
-
-  auto *DstKind =
-      HasDst ? mdconst::dyn_extract<ConstantInt>(DstProf->getOperand(1))
-             : nullptr;
-  auto *SrcKind =
-      HasSrc ? mdconst::dyn_extract<ConstantInt>(SrcProf->getOperand(1))
-             : nullptr;
-  if (HasDst && HasSrc && DstKind && SrcKind &&
-      DstKind->getZExtValue() != SrcKind->getZExtValue()) {
-    DstI->setMetadata(LLVMContext::MD_prof, nullptr);
-    return;
-  }
-
-  const ConstantInt *KindCI = DstKind ? DstKind : SrcKind;
-  if (!KindCI) {
-    DstI->setMetadata(LLVMContext::MD_prof, nullptr);
-    return;
-  }
-
-  InstrProfValueKind Kind =
-      static_cast<InstrProfValueKind>(KindCI->getZExtValue());
-
-  DenseMap<uint64_t, uint64_t> Merged;
-  if (HasDst)
-    addValueProfile(*DstI, Kind, Merged);
-  if (HasSrc)
-    addValueProfile(*SrcI, Kind, Merged);
-
-  if (Merged.empty())
-    return;
-
-  SmallVector<InstrProfValueData, 8> VDs;
-  VDs.reserve(Merged.size());
-  uint64_t Sum = 0;
-  for (auto &[Value, Count] : Merged) {
-    VDs.push_back({Value, Count});
-    Sum = SaturatingAdd(Sum, Count);
-  }
-  llvm::sort(VDs, [](const InstrProfValueData &A, const InstrProfValueData &B) 
{
-    return A.Count > B.Count;
-  });
-  annotateValueSite(*DstI->getFunction()->getParent(), *DstI, VDs, Sum, Kind,
-                    VDs.size());
-}
-
-/// Merge \p Src's instruction-level branch weights and value profile
-/// metadata into the corresponding instructions of \p Dst. \p Dst is the
-/// surviving function; \p Src will be erased or rewritten after this call.
-/// Both functions must be structurally identical.
-void MergeFunctions::mergeInstrProfMetadataInto(Function *Dst, Function *Src) {
-  const BlockFrequencyInfo &DstBFI =
-      FAM.getResult<BlockFrequencyAnalysis>(*Dst);
-  const BlockFrequencyInfo &SrcBFI =
-      FAM.getResult<BlockFrequencyAnalysis>(*Src);
-
-  // FunctionComparator guarantees identical CFG topology and instruction
-  // ordering. Walk the CFGs in RPO rather than function block-list order, as
-  // equivalent functions need not store their basic blocks in the same order.
-  ReversePostOrderTraversal<Function *> DstRPOT(Dst);
-  ReversePostOrderTraversal<Function *> SrcRPOT(Src);
-  for (auto [DstBB, SrcBB] : llvm::zip_equal(DstRPOT, SrcRPOT)) {
-    for (auto [DstI, SrcI] : llvm::zip_equal(*DstBB, *SrcBB)) {
-      MDNode *DstProf = DstI.getMetadata(LLVMContext::MD_prof);
-      MDNode *SrcProf = SrcI.getMetadata(LLVMContext::MD_prof);
-      if ((DstProf && isValueProfileMD(DstProf)) ||
-          (SrcProf && isValueProfileMD(SrcProf)))
-        mergeValueProfileOnInstructions(&DstI, &SrcI);
-
-      // Handle branch weights on SelectInsts here. Terminators are handled
-      // separately below, outside the instruction loop.
-      if (isa<SelectInst>(DstI))
-        mergeBranchWeightsOnInstructions(&DstI, &SrcI, DstBFI, SrcBFI);
-    }
-    Instruction *DstTerm = DstBB->getTerminator();
-    const Instruction *SrcTerm = SrcBB->getTerminator();
-    mergeBranchWeightsOnInstructions(DstTerm, SrcTerm, DstBFI, SrcBFI);
-  }
-
-  PreservedAnalyses PA = PreservedAnalyses::all();
-  PA.abandon<BranchProbabilityAnalysis>();
-  PA.abandon<BlockFrequencyAnalysis>();
-  FAM.invalidate(*Dst, PA);
-}
-
 static void mergeEntryCountsInto(Function *F, std::optional<uint64_t> FC,
                                  std::optional<uint64_t> GC) {
   if (!FC && !GC)
@@ -1101,8 +891,8 @@ static void mergeEntryCountsInto(Function *F, 
std::optional<uint64_t> FC,
 // Merge two equivalent functions. Upon completion, Function G is deleted.
 void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
 
-  std::optional<uint64_t> FEntryCount = F->getEntryCount();
-  std::optional<uint64_t> GEntryCount = G->getEntryCount();
+  std::optional<uint64_t> FEC = F->getEntryCount();
+  std::optional<uint64_t> GEC = G->getEntryCount();
 
   // Create a new thunk that both F and G can call, if F cannot call G 
directly.
   // That is the case if F is either interposable or if G is either weak_odr or
@@ -1145,13 +935,10 @@ void MergeFunctions::mergeTwoFunctions(Function *F, 
Function *G) {
     const MaybeAlign NewFAlign = NewF->getAlign();
     const MaybeAlign GAlign = G->getAlign();
 
-    // Merge !prof, while G still has its body.
-    writeThunkOrAliasIfNeeded(F, G, /*MergeProfile*/ true);
-    if (FEntryCount)
-      NewF->setEntryCount(*FEntryCount);
-    // NewF becomes thunk/alias to the shared body F, it has no profile to be
-    // merged.
-    writeThunkOrAliasIfNeeded(F, NewF, /*MergeProfile*/ false);
+    writeThunkOrAliasIfNeeded(F, G);
+    if (FEC)
+      NewF->setEntryCount(*FEC);
+    writeThunkOrAliasIfNeeded(F, NewF);
 
     if (NewFAlign || GAlign)
       F->setAlignment(std::max(NewFAlign.valueOrOne(), GAlign.valueOrOne()));
@@ -1159,9 +946,8 @@ void MergeFunctions::mergeTwoFunctions(Function *F, 
Function *G) {
       F->setAlignment(std::nullopt);
     F->setLinkage(GlobalValue::PrivateLinkage);
     // The private shared implementation accumulates both symbols' entries
-    // (FEntryCount + GEntryCount), while each ODR thunk retains its own
-    // per-symbol entry count.
-    mergeEntryCountsInto(F, FEntryCount, GEntryCount);
+    // (FEC + GEC), while each ODR thunk retains its own per-symbol entry 
count.
+    mergeEntryCountsInto(F, FEC, GEC);
     ++NumDoubleWeak;
     ++NumFunctionsMerged;
   } else {
@@ -1189,15 +975,14 @@ void MergeFunctions::mergeTwoFunctions(Function *F, 
Function *G) {
     // stop here and delete G. There's no need for a thunk. (See note on
     // MergeFunctionsPDI above).
     if (G->isDiscardableIfUnused() && G->use_empty() && !MergeFunctionsPDI) {
-      mergeInstrProfMetadataInto(F, G);
-      mergeEntryCountsInto(F, FEntryCount, GEntryCount);
+      mergeEntryCountsInto(F, FEC, GEC);
       G->eraseFromParent();
       ++NumFunctionsMerged;
       return;
     }
 
-    if (writeThunkOrAliasIfNeeded(F, G, /*MergeProfile*/ true)) {
-      mergeEntryCountsInto(F, FEntryCount, GEntryCount);
+    if (writeThunkOrAliasIfNeeded(F, G)) {
+      mergeEntryCountsInto(F, FEC, GEC);
       ++NumFunctionsMerged;
     }
   }

diff  --git a/llvm/test/Transforms/MergeFunc/merge-functions-branch-weights.ll 
b/llvm/test/Transforms/MergeFunc/merge-functions-branch-weights.ll
deleted file mode 100644
index 46a80c2916766..0000000000000
--- a/llvm/test/Transforms/MergeFunc/merge-functions-branch-weights.ll
+++ /dev/null
@@ -1,239 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 
UTC_ARGS: --include-generated-funcs --version 6
-; RUN: opt -S -passes=mergefunc < %s | FileCheck %s
-
-; Verify that MergeFunctions correctly combines branch_weights on
-; conditional branches when merging structurally identical functions.
-; Because FunctionComparator only matches functions whose control-flow
-; structure and instruction sequence are identical, MergeFunctions can
-; process both functions side by side and merge any instruction-level
-; metadata, including branch weight information.
-; To compute the merged weights, the pass converts each function's
-; relative branch weights into absolute execution counts using the
-; function's entry count, then adds the corresponding counts together.
-
-; --------------------------------------------------------------------------
-; Both functions provide branch weight metadata.
-; br_both_a: entry count = 100, weights = 10:90
-;            absolute counts: true = 10, false = 90
-; br_both_b: entry count = 200, weights = 30:70
-;            absolute counts: true = 60, false = 140
-; After merging:
-;            true  = 10 + 60  = 70
-;            false = 90 + 140 = 230
-; --------------------------------------------------------------------------
-define internal i32 @br_both_a(i32 %x) !prof !1 {
-entry:
-  %cmp = icmp slt i32 %x, 0
-  br i1 %cmp, label %then, label %else, !prof !2
-
-then:
-  ret i32 1
-
-else:
-  ret i32 0
-}
-
-define internal i32 @br_both_b(i32 %x) !prof !3 {
-entry:
-  %cmp = icmp slt i32 %x, 0
-  br i1 %cmp, label %then, label %else, !prof !4
-
-then:
-  ret i32 1
-
-else:
-  ret i32 0
-}
-
-; --------------------------------------------------------------------------
-; Only one of the functions provides branch weight metadata.
-; br_one_a has an entry count of 40 but does not specify any
-; branch_weights.
-; br_one_b has an entry count of 60 with branch weights of 40:80,
-; which correspond to absolute counts of true = 20 and false = 40.
-; Since only br_one_b contributes branch weight information, the
-; merged branch retains those counts:
-;            true  = 20
-;            false = 40
-; --------------------------------------------------------------------------
-define internal i32 @br_one_a(i32 %x) !prof !5 {
-entry:
-  %cmp = icmp sgt i32 %x, 0
-  br i1 %cmp, label %then, label %else
-
-then:
-  ret i32 7
-
-else:
-  ret i32 8
-}
-
-define internal i32 @br_one_b(i32 %x) !prof !6 {
-entry:
-  %cmp = icmp sgt i32 %x, 0
-  br i1 %cmp, label %then, label %else, !prof !7
-
-then:
-  ret i32 7
-
-else:
-  ret i32 8
-}
-
-; --------------------------------------------------------------------------
-; Thunk case: two dso_local functions are merged through a thunk, and
-; their branch weight metadata is combined as part of the merge.
-; thunk_a has an entry count of 10 with branch weights of 1:9,
-; resulting in absolute counts of true = 1 and false = 9.
-; thunk_b has an entry count of 20 with branch weights of 3:17,
-; resulting in absolute counts of true = 3 and false = 17.
-; After merging the two functions, the corresponding counts are added:
-;            true  = 1 + 3  = 4
-;            false = 9 + 17 = 26
-; --------------------------------------------------------------------------
-define dso_local i32 @thunk_a(i32 %x) unnamed_addr !prof !8 {
-entry:
-  %cmp = icmp ult i32 %x, 3
-  br i1 %cmp, label %then, label %else, !prof !9
-
-then:
-  ret i32 9
-
-else:
-  ret i32 10
-}
-
-define dso_local i32 @thunk_b(i32 %x) unnamed_addr !prof !10 {
-entry:
-  %cmp = icmp ult i32 %x, 3
-  br i1 %cmp, label %then, label %else, !prof !11
-
-then:
-  ret i32 9
-
-else:
-  ret i32 10
-}
-
-; --------------------------------------------------------------------------
-; ODR case: two weak_odr functions are merged into a single shared
-; implementation, and their branch weight metadata is merged as well.
-; odr_a has an entry count of 100 with branch weights of 1:9,
-; corresponding to absolute counts of true = 10 and false = 90.
-; odr_b has an entry count of 200 with branch weights of 3:17,
-; corresponding to absolute counts of true = 30 and false = 170.
-; The merged function combines the counts from both inputs:
-;            true  = 10 + 30  = 40
-;            false = 90 + 170 = 260
-; --------------------------------------------------------------------------
-define weak_odr i32 @odr_a(i32 %x) !prof !12 {
-entry:
-  %cmp = icmp ugt i32 %x, 4
-  br i1 %cmp, label %then, label %else, !prof !13
-
-then:
-  ret i32 11
-
-else:
-  ret i32 12
-}
-
-define weak_odr i32 @odr_b(i32 %x) !prof !14 {
-entry:
-  %cmp = icmp ugt i32 %x, 4
-  br i1 %cmp, label %then, label %else, !prof !15
-
-then:
-  ret i32 11
-
-else:
-  ret i32 12
-}
-
-!1 = !{!"function_entry_count", i64 100}
-!2 = !{!"branch_weights", i32 10, i32 90}
-!3 = !{!"function_entry_count", i64 200}
-!4 = !{!"branch_weights", i32 30, i32 70}
-!5 = !{!"function_entry_count", i64 40}
-!6 = !{!"function_entry_count", i64 60}
-!7 = !{!"branch_weights", i32 40, i32 80}
-!8 = !{!"function_entry_count", i64 10}
-!9 = !{!"branch_weights", i32 1, i32 9}
-!10 = !{!"function_entry_count", i64 20}
-!11 = !{!"branch_weights", i32 3, i32 17}
-!12 = !{!"function_entry_count", i64 100}
-!13 = !{!"branch_weights", i32 1, i32 9}
-!14 = !{!"function_entry_count", i64 200}
-!15 = !{!"branch_weights", i32 3, i32 17}
-; CHECK-LABEL: define internal i32 @br_both_a(
-; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF0:![0-9]+]] {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X]], 0
-; CHECK-NEXT:    br i1 [[CMP]], label %[[THEN:.*]], label %[[ELSE:.*]], !prof 
[[PROF1:![0-9]+]]
-; CHECK:       [[THEN]]:
-; CHECK-NEXT:    ret i32 1
-; CHECK:       [[ELSE]]:
-; CHECK-NEXT:    ret i32 0
-;
-;
-; CHECK-LABEL: define internal i32 @br_one_a(
-; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF2:![0-9]+]] {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X]], 0
-; CHECK-NEXT:    br i1 [[CMP]], label %[[THEN:.*]], label %[[ELSE:.*]], !prof 
[[PROF3:![0-9]+]]
-; CHECK:       [[THEN]]:
-; CHECK-NEXT:    ret i32 7
-; CHECK:       [[ELSE]]:
-; CHECK-NEXT:    ret i32 8
-;
-;
-; CHECK-LABEL: define dso_local i32 @thunk_a(
-; CHECK-SAME: i32 [[X:%.*]]) unnamed_addr !prof [[PROF4:![0-9]+]] {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[X]], 3
-; CHECK-NEXT:    br i1 [[CMP]], label %[[THEN:.*]], label %[[ELSE:.*]], !prof 
[[PROF5:![0-9]+]]
-; CHECK:       [[THEN]]:
-; CHECK-NEXT:    ret i32 9
-; CHECK:       [[ELSE]]:
-; CHECK-NEXT:    ret i32 10
-;
-;
-; CHECK-LABEL: define private i32 @0(
-; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF0]] {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[X]], 4
-; CHECK-NEXT:    br i1 [[CMP]], label %[[THEN:.*]], label %[[ELSE:.*]], !prof 
[[PROF6:![0-9]+]]
-; CHECK:       [[THEN]]:
-; CHECK-NEXT:    ret i32 11
-; CHECK:       [[ELSE]]:
-; CHECK-NEXT:    ret i32 12
-;
-;
-; CHECK-LABEL: define dso_local i32 @thunk_b(
-; CHECK-SAME: i32 [[TMP0:%.*]]) unnamed_addr !prof [[PROF7:![0-9]+]] {
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call i32 @thunk_a(i32 [[TMP0]])
-; CHECK-NEXT:    ret i32 [[TMP2]]
-;
-;
-; CHECK-LABEL: define weak_odr i32 @odr_b(
-; CHECK-SAME: i32 [[TMP0:%.*]]) !prof [[PROF8:![0-9]+]] {
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call i32 @[[GLOB0:[0-9]+]](i32 [[TMP0]])
-; CHECK-NEXT:    ret i32 [[TMP2]]
-;
-;
-; CHECK-LABEL: define weak_odr i32 @odr_a(
-; CHECK-SAME: i32 [[TMP0:%.*]]) !prof [[PROF2]] {
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call i32 @[[GLOB0]](i32 [[TMP0]])
-; CHECK-NEXT:    ret i32 [[TMP2]]
-;
-;.
-; CHECK: [[PROF0]] = !{!"function_entry_count", i64 300}
-; CHECK: [[PROF1]] = !{!"branch_weights", i32 70, i32 230}
-; CHECK: [[PROF2]] = !{!"function_entry_count", i64 100}
-; CHECK: [[PROF3]] = !{!"branch_weights", i32 20, i32 40}
-; CHECK: [[PROF4]] = !{!"function_entry_count", i64 30}
-; CHECK: [[PROF5]] = !{!"branch_weights", i32 4, i32 26}
-; CHECK: [[PROF6]] = !{!"branch_weights", i32 40, i32 260}
-; CHECK: [[PROF7]] = !{!"function_entry_count", i64 20}
-; CHECK: [[PROF8]] = !{!"function_entry_count", i64 200}
-;.

diff  --git 
a/llvm/test/Transforms/MergeFunc/merge-functions-reordered-blocks-branch-weights.ll
 
b/llvm/test/Transforms/MergeFunc/merge-functions-reordered-blocks-branch-weights.ll
deleted file mode 100644
index 6853813849243..0000000000000
--- 
a/llvm/test/Transforms/MergeFunc/merge-functions-reordered-blocks-branch-weights.ll
+++ /dev/null
@@ -1,121 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 
UTC_ARGS: --version 6
-; RUN: opt -S -passes=mergefunc < %s | FileCheck %s
-
-; Verify that MergeFunctions correctly combines branch_weights when equivalent
-; functions store corresponding basic blocks in a 
diff erent textual order.
-; mergeInstrProfMetadataInto must match blocks by CFG traversal, not function
-; block-list order, so the left and right branch metadata is merged with the
-; corresponding block even when @br_reordered_b lists right before left.
-
-; --------------------------------------------------------------------------
-; Both functions have the same CFG and successor order:
-;            entry -> left/right
-;            left  -> ret1/ret2
-;            right -> ret3/ret4
-;
-; br_reordered_a block order: entry, left, right, ret1, ret2, ret3, ret4
-; br_reordered_b block order: entry, right, left, ret1, ret2, ret3, ret4
-;
-; entry is reached with counts 100 and 200, and both functions split it evenly:
-;            true  = 50 + 100 = 150
-;            false = 50 + 100 = 150
-;
-; left is reached with counts 50 and 100.
-; br_reordered_a left weights = 1:4, giving counts 10:40.
-; br_reordered_b left weights = 3:7, giving counts 30:70.
-; After merging left:
-;            true  = 10 + 30 = 40
-;            false = 40 + 70 = 110
-;
-; right is reached with counts 50 and 100.
-; br_reordered_a right weights = 2:3, giving counts 20:30.
-; br_reordered_b right weights = 4:6, giving counts 40:60.
-; After merging right:
-;            true  = 20 + 40 = 60
-;            false = 30 + 60 = 90
-; --------------------------------------------------------------------------
-define internal i32 @br_reordered_a(i32 %x, i32 %y) !prof !0 {
-; CHECK-LABEL: define internal i32 @br_reordered_a(
-; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) !prof [[PROF0:![0-9]+]] {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[ENTRY_CMP:%.*]] = icmp slt i32 [[X]], 0
-; CHECK-NEXT:    br i1 [[ENTRY_CMP]], label %[[LEFT:.*]], label %[[RIGHT:.*]], 
!prof [[PROF1:![0-9]+]]
-; CHECK:       [[LEFT]]:
-; CHECK-NEXT:    [[LEFT_CMP:%.*]] = icmp slt i32 [[Y]], 10
-; CHECK-NEXT:    br i1 [[LEFT_CMP]], label %[[RET1:.*]], label %[[RET2:.*]], 
!prof [[PROF2:![0-9]+]]
-; CHECK:       [[RIGHT]]:
-; CHECK-NEXT:    [[RIGHT_CMP:%.*]] = icmp slt i32 [[Y]], 20
-; CHECK-NEXT:    br i1 [[RIGHT_CMP]], label %[[RET3:.*]], label %[[RET4:.*]], 
!prof [[PROF3:![0-9]+]]
-; CHECK:       [[RET1]]:
-; CHECK-NEXT:    ret i32 1
-; CHECK:       [[RET2]]:
-; CHECK-NEXT:    ret i32 2
-; CHECK:       [[RET3]]:
-; CHECK-NEXT:    ret i32 3
-; CHECK:       [[RET4]]:
-; CHECK-NEXT:    ret i32 4
-;
-entry:
-  %entry.cmp = icmp slt i32 %x, 0
-  br i1 %entry.cmp, label %left, label %right, !prof !1
-
-left:                                             ; preds = %entry
-  %left.cmp = icmp slt i32 %y, 10
-  br i1 %left.cmp, label %ret1, label %ret2, !prof !2
-
-right:                                            ; preds = %entry
-  %right.cmp = icmp slt i32 %y, 20
-  br i1 %right.cmp, label %ret3, label %ret4, !prof !3
-
-ret1:                                             ; preds = %left
-  ret i32 1
-
-ret2:                                             ; preds = %left
-  ret i32 2
-
-ret3:                                             ; preds = %right
-  ret i32 3
-
-ret4:                                             ; preds = %right
-  ret i32 4
-}
-
-define internal i32 @br_reordered_b(i32 %x, i32 %y) !prof !4 {
-entry:
-  %entry.cmp = icmp slt i32 %x, 0
-  br i1 %entry.cmp, label %left, label %right, !prof !1
-
-right:                                            ; preds = %entry
-  %right.cmp = icmp slt i32 %y, 20
-  br i1 %right.cmp, label %ret3, label %ret4, !prof !5
-
-left:                                             ; preds = %entry
-  %left.cmp = icmp slt i32 %y, 10
-  br i1 %left.cmp, label %ret1, label %ret2, !prof !6
-
-ret1:                                             ; preds = %left
-  ret i32 1
-
-ret2:                                             ; preds = %left
-  ret i32 2
-
-ret3:                                             ; preds = %right
-  ret i32 3
-
-ret4:                                             ; preds = %right
-  ret i32 4
-}
-
-!0 = !{!"function_entry_count", i64 100}
-!1 = !{!"branch_weights", i32 1, i32 1}
-!2 = !{!"branch_weights", i32 1, i32 4}
-!3 = !{!"branch_weights", i32 2, i32 3}
-!4 = !{!"function_entry_count", i64 200}
-!5 = !{!"branch_weights", i32 4, i32 6}
-!6 = !{!"branch_weights", i32 3, i32 7}
-;.
-; CHECK: [[PROF0]] = !{!"function_entry_count", i64 300}
-; CHECK: [[PROF1]] = !{!"branch_weights", i32 150, i32 150}
-; CHECK: [[PROF2]] = !{!"branch_weights", i32 40, i32 110}
-; CHECK: [[PROF3]] = !{!"branch_weights", i32 60, i32 90}
-;.

diff  --git a/llvm/test/Transforms/MergeFunc/merge-functions-select-weights.ll 
b/llvm/test/Transforms/MergeFunc/merge-functions-select-weights.ll
deleted file mode 100644
index c052cabba6288..0000000000000
--- a/llvm/test/Transforms/MergeFunc/merge-functions-select-weights.ll
+++ /dev/null
@@ -1,50 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 
UTC_ARGS: --version 6
-; RUN: opt -S -passes=mergefunc < %s | FileCheck %s
-;
-
-; Verify that MergeFunctions correctly combines select-instruction
-; branch_weights when merging two structurally identical functions.
-; Since FunctionComparator only considers functions equal when their
-; control-flow graphs and instruction order match exactly, MergeFunctions
-; can safely walk both functions in parallel and merge any instruction-level
-; metadata it encounters.
-;
-; The functions sel_a and sel_b 
diff er only in their entry counts and
-; select branch_weights. When merged, the pass first converts each
-; function's relative branch weights into absolute execution counts using
-; its entry count, and then adds the counts together to produce the
-; final merged weights.
-;
-; sel_a: entry 50,  weights 10:90  -> true=5,   false=45
-; sel_b: entry 150, weights 30:70  -> true=45,  false=105
-; Merged:                         true=5+45=50,  false=45+105=150
-
-define internal i32 @sel_a(i32 %x) !prof !1 {
-; CHECK-LABEL: define internal i32 @sel_a(
-; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF0:![0-9]+]] {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X]], 0
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 1, i32 0, !prof 
[[PROF1:![0-9]+]]
-; CHECK-NEXT:    ret i32 [[SEL]]
-;
-entry:
-  %cmp = icmp slt i32 %x, 0
-  %sel = select i1 %cmp, i32 1, i32 0, !prof !2
-  ret i32 %sel
-}
-
-define internal i32 @sel_b(i32 %x) !prof !3 {
-entry:
-  %cmp = icmp slt i32 %x, 0
-  %sel = select i1 %cmp, i32 1, i32 0, !prof !4
-  ret i32 %sel
-}
-
-!1 = !{!"function_entry_count", i64 50}
-!2 = !{!"branch_weights", i32 10, i32 90}
-!3 = !{!"function_entry_count", i64 150}
-!4 = !{!"branch_weights", i32 30, i32 70}
-;.
-; CHECK: [[PROF0]] = !{!"function_entry_count", i64 200}
-; CHECK: [[PROF1]] = !{!"branch_weights", i32 50, i32 150}
-;.

diff  --git a/llvm/test/Transforms/MergeFunc/merge-functions-value-profile.ll 
b/llvm/test/Transforms/MergeFunc/merge-functions-value-profile.ll
deleted file mode 100644
index c5e9488b90480..0000000000000
--- a/llvm/test/Transforms/MergeFunc/merge-functions-value-profile.ll
+++ /dev/null
@@ -1,142 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 
UTC_ARGS: --version 6
-; RUN: opt -S -passes=mergefunc < %s | FileCheck %s
-;
-
-; Verify that MergeFunctions correctly merges value profile (VP) metadata
-; on indirect calls when combining structurally identical functions.
-; Because FunctionComparator only considers functions equivalent when
-; their control-flow structure and instruction ordering match exactly,
-; MergeFunctions can walk the two functions in parallel and safely merge
-; instruction-level metadata.
-;
-; Value profile counts are already absolute. The pass combines profiles by
-; adding counts for targets that appear in both functions and preserving
-; targets that appear in only one.
-
-; --------------------------------------------------------------------------
-; Both functions provide value profile metadata for the indirect call.
-;
-; vp_both_a has an entry count of 100 and a profile of:
-;            {111:60, 222:40}
-;
-; vp_both_b has an entry count of 200 and a profile of:
-;            {111:120, 333:80}
-;
-; After merging, counts for shared targets are summed while unique
-; targets are carried over:
-;
-;            entry count = 300
-;            VP {111:180, 333:80, 222:40}
-; --------------------------------------------------------------------------
-define internal i32 @vp_both_a(ptr %fn) !prof !1 {
-; CHECK-LABEL: define internal i32 @vp_both_a(
-; CHECK-SAME: ptr [[FN:%.*]]) !prof [[PROF0:![0-9]+]] {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[FN_VAL:%.*]] = load ptr, ptr [[FN]], align 8
-; CHECK-NEXT:    [[R:%.*]] = call i32 [[FN_VAL]](), !prof [[PROF1:![0-9]+]]
-; CHECK-NEXT:    ret i32 [[R]]
-;
-entry:
-  %fn_val = load ptr, ptr %fn
-  %r = call i32 %fn_val(), !prof !2
-  ret i32 %r
-}
-
-define internal i32 @vp_both_b(ptr %fn) !prof !3 {
-entry:
-  %fn_val = load ptr, ptr %fn
-  %r = call i32 %fn_val(), !prof !4
-  ret i32 %r
-}
-
-; --------------------------------------------------------------------------
-; Only one of the functions provides value profile metadata for the
-; indirect call.
-;
-; vp_one_a has an entry count of 30 but does not contain any VP data
-; on the call site.
-;
-; vp_one_b has an entry count of 70 and records the target profile:
-;            {888:50}
-;
-; Since only vp_one_b contributes value profile information, the merged
-; function carries that profile forward unchanged while combining the
-; overall entry counts.
-;
-;            entry count = 100
-;            VP {888:50}
-; --------------------------------------------------------------------------
-define internal i32 @vp_one_a(ptr %fn) !prof !5 {
-; CHECK-LABEL: define internal i32 @vp_one_a(
-; CHECK-SAME: ptr [[FN:%.*]]) !prof [[PROF2:![0-9]+]] {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[FN_VAL:%.*]] = load ptr, ptr [[FN]], align 8
-; CHECK-NEXT:    [[R:%.*]] = call i32 [[FN_VAL]](), !prof [[PROF3:![0-9]+]]
-; CHECK-NEXT:    [[ADJ:%.*]] = add i32 [[R]], 3
-; CHECK-NEXT:    ret i32 [[ADJ]]
-;
-entry:
-  %fn_val = load ptr, ptr %fn
-  %r = call i32 %fn_val()
-  %adj = add i32 %r, 3
-  ret i32 %adj
-}
-
-define internal i32 @vp_one_b(ptr %fn) !prof !6 {
-entry:
-  %fn_val = load ptr, ptr %fn
-  %r = call i32 %fn_val(), !prof !7
-  %adj = add i32 %r, 3
-  ret i32 %adj
-}
-
-; --------------------------------------------------------------------------
-; Both functions attach value profile metadata to the indirect call, but
-; they use 
diff erent VP kinds.
-;
-; Because the profiles are not compatible, MergeFunctions cannot safely
-; merge them into a single representation. Rather than producing
-; potentially misleading profile data, the pass drops the call-site
-; !prof metadata during the merge.
-; --------------------------------------------------------------------------
-define internal i32 @vp_kind_a(ptr %fn) !prof !8 {
-; CHECK-LABEL: define internal i32 @vp_kind_a(
-; CHECK-SAME: ptr [[FN:%.*]]) !prof [[PROF2]] {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[FN_VAL:%.*]] = load ptr, ptr [[FN]], align 8
-; CHECK-NEXT:    [[R:%.*]] = call i32 [[FN_VAL]]()
-; CHECK-NEXT:    [[ADJ:%.*]] = add i32 [[R]], 2
-; CHECK-NEXT:    ret i32 [[ADJ]]
-;
-entry:
-  %fn_val = load ptr, ptr %fn
-  %r = call i32 %fn_val(), !prof !9
-  %adj = add i32 %r, 2
-  ret i32 %adj
-}
-
-define internal i32 @vp_kind_b(ptr %fn) !prof !10 {
-entry:
-  %fn_val = load ptr, ptr %fn
-  %r = call i32 %fn_val(), !prof !11
-  %adj = add i32 %r, 2
-  ret i32 %adj
-}
-
-!1 = !{!"function_entry_count", i64 100}
-!2 = !{!"VP", i32 0, i64 100, i64 111, i64 60, i64 222, i64 40}
-!3 = !{!"function_entry_count", i64 200}
-!4 = !{!"VP", i32 0, i64 200, i64 111, i64 120, i64 333, i64 80}
-!5 = !{!"function_entry_count", i64 30}
-!6 = !{!"function_entry_count", i64 70}
-!7 = !{!"VP", i32 0, i64 70, i64 888, i64 50}
-!8 = !{!"function_entry_count", i64 30}
-!9 = !{!"VP", i32 0, i64 30, i64 666, i64 20}
-!10 = !{!"function_entry_count", i64 70}
-!11 = !{!"VP", i32 1, i64 70, i64 777, i64 50}
-;.
-; CHECK: [[PROF0]] = !{!"function_entry_count", i64 300}
-; CHECK: [[PROF1]] = !{!"VP", i32 0, i64 300, i64 111, i64 180, i64 333, i64 
80, i64 222, i64 40}
-; CHECK: [[PROF2]] = !{!"function_entry_count", i64 100}
-; CHECK: [[PROF3]] = !{!"VP", i32 0, i64 50, i64 888, i64 50}
-;.

diff  --git a/llvm/unittests/Transforms/IPO/MergeFunctionsTest.cpp 
b/llvm/unittests/Transforms/IPO/MergeFunctionsTest.cpp
index 879b48e6457a3..5be92b5ae3188 100644
--- a/llvm/unittests/Transforms/IPO/MergeFunctionsTest.cpp
+++ b/llvm/unittests/Transforms/IPO/MergeFunctionsTest.cpp
@@ -9,15 +9,9 @@
 #include "llvm/Transforms/IPO/MergeFunctions.h"
 
 #include "llvm/ADT/SetVector.h"
-#include "llvm/Analysis/BlockFrequencyInfo.h"
-#include "llvm/Analysis/BranchProbabilityInfo.h"
-#include "llvm/Analysis/LoopInfo.h"
-#include "llvm/Analysis/PostDominators.h"
-#include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/AsmParser/Parser.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
-#include "llvm/IR/PassInstrumentation.h"
 #include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
 #include <memory>
@@ -26,35 +20,10 @@ using namespace llvm;
 
 namespace {
 
-class MergeFunctionsTest : public testing::Test {
-protected:
+TEST(MergeFunctions, TrueOutputModuleTest) {
   LLVMContext Ctx;
-  ModuleAnalysisManager MAM;
-  FunctionAnalysisManager FAM;
-
-  MergeFunctionsTest() {
-    FAM.registerPass([&] { return TargetLibraryAnalysis(); });
-    FAM.registerPass([&] { return DominatorTreeAnalysis(); });
-    FAM.registerPass([&] { return PostDominatorTreeAnalysis(); });
-    FAM.registerPass([&] { return LoopAnalysis(); });
-    FAM.registerPass([&] { return BranchProbabilityAnalysis(); });
-    FAM.registerPass([&] { return BlockFrequencyAnalysis(); });
-    FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
-    FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
-    MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
-    MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
-  }
-
-  std::unique_ptr<Module> parseModule(StringRef IR) {
-    SMDiagnostic Err;
-    std::unique_ptr<Module> M = parseAssemblyString(IR, Err, Ctx);
-    EXPECT_TRUE(M);
-    return M;
-  }
-};
-
-TEST_F(MergeFunctionsTest, TrueOutputModuleTest) {
-  std::unique_ptr<Module> M = parseModule(R"invalid(
+  SMDiagnostic Err;
+  std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
         @.str = private unnamed_addr constant [10 x i8] c"On f: %d\0A\00", 
align 1
         @.str.1 = private unnamed_addr constant [13 x i8] c"On main: 
%d\0A\00", align 1
 
@@ -95,14 +64,17 @@ TEST_F(MergeFunctionsTest, TrueOutputModuleTest) {
                 %4 = add nsw i32 %3, 2
                 ret i32 %4
         }
-    )invalid");
+    )invalid",
+                                                Err, Ctx));
 
   // Expects true after merging _slice_add10 and _slice_add10_alt
-  EXPECT_TRUE(MergeFunctionsPass::runOnModule(*M, MAM));
+  EXPECT_TRUE(MergeFunctionsPass::runOnModule(*M));
 }
 
-TEST_F(MergeFunctionsTest, TrueOutputFunctionsTest) {
-  std::unique_ptr<Module> M = parseModule(R"invalid(
+TEST(MergeFunctions, TrueOutputFunctionsTest) {
+  LLVMContext Ctx;
+  SMDiagnostic Err;
+  std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
         @.str = private unnamed_addr constant [10 x i8] c"On f: %d\0A\00", 
align 1
         @.str.1 = private unnamed_addr constant [13 x i8] c"On main: 
%d\0A\00", align 1
 
@@ -143,14 +115,15 @@ TEST_F(MergeFunctionsTest, TrueOutputFunctionsTest) {
                 %4 = add nsw i32 %3, 2
                 ret i32 %4
         }
-    )invalid");
+    )invalid",
+                                                Err, Ctx));
 
   SetVector<Function *> FunctionsSet;
   for (Function &F : *M)
     FunctionsSet.insert(&F);
 
   DenseMap<Function *, Function *> MergeResult =
-      MergeFunctionsPass::runOnFunctions(FunctionsSet.getArrayRef(), MAM);
+      MergeFunctionsPass::runOnFunctions(FunctionsSet.getArrayRef());
 
   // Expects that both functions (_slice_add10 and _slice_add10_alt)
   // be mapped to the same new function
@@ -161,8 +134,10 @@ TEST_F(MergeFunctionsTest, TrueOutputFunctionsTest) {
       EXPECT_EQ(P.second, NewFunction);
 }
 
-TEST_F(MergeFunctionsTest, FalseOutputModuleTest) {
-  std::unique_ptr<Module> M = parseModule(R"invalid(
+TEST(MergeFunctions, FalseOutputModuleTest) {
+  LLVMContext Ctx;
+  SMDiagnostic Err;
+  std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
         @.str = private unnamed_addr constant [10 x i8] c"On f: %d\0A\00", 
align 1
         @.str.1 = private unnamed_addr constant [13 x i8] c"On main: 
%d\0A\00", align 1
 
@@ -203,14 +178,17 @@ TEST_F(MergeFunctionsTest, FalseOutputModuleTest) {
                 %4 = add nsw i32 %3, 2
                 ret i32 %0
         }
-    )invalid");
+    )invalid",
+                                                Err, Ctx));
 
   // Expects false after trying to merge _slice_add10 and _slice_add10_alt
-  EXPECT_FALSE(MergeFunctionsPass::runOnModule(*M, MAM));
+  EXPECT_FALSE(MergeFunctionsPass::runOnModule(*M));
 }
 
-TEST_F(MergeFunctionsTest, FalseOutputFunctionsTest) {
-  std::unique_ptr<Module> M = parseModule(R"invalid(
+TEST(MergeFunctions, FalseOutputFunctionsTest) {
+  LLVMContext Ctx;
+  SMDiagnostic Err;
+  std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
         @.str = private unnamed_addr constant [10 x i8] c"On f: %d\0A\00", 
align 1
         @.str.1 = private unnamed_addr constant [13 x i8] c"On main: 
%d\0A\00", align 1
 
@@ -251,14 +229,15 @@ TEST_F(MergeFunctionsTest, FalseOutputFunctionsTest) {
                 %4 = add nsw i32 %3, 2
                 ret i32 %0
         }
-    )invalid");
+    )invalid",
+                                                Err, Ctx));
 
   SetVector<Function *> FunctionsSet;
   for (Function &F : *M)
     FunctionsSet.insert(&F);
 
   DenseMap<Function *, Function *> MergeResult =
-      MergeFunctionsPass::runOnFunctions(FunctionsSet.getArrayRef(), MAM);
+      MergeFunctionsPass::runOnFunctions(FunctionsSet.getArrayRef());
 
   // Expects empty map
   EXPECT_EQ(MergeResult.size(), 0u);


        
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to