[llvm] Reland: Port Swift's merge function pass to llvm: merging functions that differ in constants (PR #71584)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 7 12:33:11 PST 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Manman Ren (manman-ren)
<details>
<summary>Changes</summary>
This patch is based on the initial PR: https://github.com/llvm/llvm-project/pull/68235 and the follow-up PR: https://github.com/llvm/llvm-project/pull/71219.
PR68235 was merged and got reverted because folks think it is not adequately reviewed.
See RFC for details:
https://discourse.llvm.org/t/rfc-for-moving-swift-s-merge-function-pass-to-llvm/73778
This pass has been in Swift repo for a while, it has significant size win on C++ and ObjectiveC as well. As a first step, we are porting it over to llvm. We also have plans on supporting global function merging using Hashes.
On top of #<!-- -->68235 and #<!-- -->71219, this patch also addresses review comments:
-- Remove typed pointer usages from test cases
-- Remove pointer authentication support
-- Drop llvm:: prefixes
---
Patch is 73.97 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/71584.diff
12 Files Affected:
- (added) llvm/include/llvm/Transforms/IPO/MergeFunctionsIgnoringConst.h (+37)
- (modified) llvm/include/llvm/Transforms/Utils/FunctionComparator.h (+1)
- (added) llvm/include/llvm/Transforms/Utils/FunctionComparatorIgnoringConst.h (+58)
- (added) llvm/include/llvm/Transforms/Utils/MergeFunctionsIgnoringConst.h (+29)
- (modified) llvm/lib/Passes/PassBuilder.cpp (+1)
- (modified) llvm/lib/Passes/PassBuilderPipelines.cpp (+11)
- (modified) llvm/lib/Passes/PassRegistry.def (+1)
- (modified) llvm/lib/Transforms/IPO/CMakeLists.txt (+1)
- (added) llvm/lib/Transforms/IPO/MergeFunctionsIgnoringConst.cpp (+1187)
- (modified) llvm/lib/Transforms/Utils/CMakeLists.txt (+1)
- (added) llvm/lib/Transforms/Utils/FunctionComparatorIgnoringConst.cpp (+164)
- (added) llvm/test/Transforms/MergeFuncIgnoringConst/merge_func.ll (+532)
``````````diff
diff --git a/llvm/include/llvm/Transforms/IPO/MergeFunctionsIgnoringConst.h b/llvm/include/llvm/Transforms/IPO/MergeFunctionsIgnoringConst.h
new file mode 100644
index 000000000000000..62cd97db0b84091
--- /dev/null
+++ b/llvm/include/llvm/Transforms/IPO/MergeFunctionsIgnoringConst.h
@@ -0,0 +1,37 @@
+//===- MergeFunctionsIgnoringConst.h - Merge Functions ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass transforms simple global variables that never have their address
+// taken. If obviously true, it marks read/write globals as constant, deletes
+// variables only stored to, etc.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_IPO_MERGEFUNCTIONSIGNORINGCONST_H
+#define LLVM_TRANSFORMS_IPO_MERGEFUNCTIONSIGNORINGCONST_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class Module;
+
+/// Merge functions that differ by constants.
+class MergeFuncIgnoringConstPass
+ : public PassInfoMixin<MergeFuncIgnoringConstPass> {
+ std::string MergeFuncSuffix = ".Tm";
+
+public:
+ MergeFuncIgnoringConstPass() {}
+ MergeFuncIgnoringConstPass(std::string Suffix) : MergeFuncSuffix(Suffix) {}
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_IPO_MERGEFUNCTIONSIGNORINGCONST_H
diff --git a/llvm/include/llvm/Transforms/Utils/FunctionComparator.h b/llvm/include/llvm/Transforms/Utils/FunctionComparator.h
index c28f868039a1f7b..1a314b481c72c61 100644
--- a/llvm/include/llvm/Transforms/Utils/FunctionComparator.h
+++ b/llvm/include/llvm/Transforms/Utils/FunctionComparator.h
@@ -379,6 +379,7 @@ class FunctionComparator {
/// But, we are still not able to compare operands of PHI nodes, since those
/// could be operands from further BBs we didn't scan yet.
/// So it's impossible to use dominance properties in general.
+protected:
mutable DenseMap<const Value*, int> sn_mapL, sn_mapR;
// The global state we will use
diff --git a/llvm/include/llvm/Transforms/Utils/FunctionComparatorIgnoringConst.h b/llvm/include/llvm/Transforms/Utils/FunctionComparatorIgnoringConst.h
new file mode 100644
index 000000000000000..9c7fe3baf2fa0db
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Utils/FunctionComparatorIgnoringConst.h
@@ -0,0 +1,58 @@
+//===- FunctionComparatorIgnoringConst.h - Function Comparator --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the FunctionComparatorIgnoringConst class which is used by
+// the MergeFuncIgnoringConst pass for comparing functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_FUNCTIONCOMPARATORIGNORINGCONST_H
+#define LLVM_TRANSFORMS_UTILS_FUNCTIONCOMPARATORIGNORINGCONST_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Operator.h"
+#include "llvm/IR/ValueMap.h"
+#include "llvm/Support/AtomicOrdering.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Transforms/Utils/FunctionComparator.h"
+#include <set>
+
+namespace llvm {
+
+/// FunctionComparatorIgnoringConst - Compares two functions to determine
+/// whether or not they match when certain constants are ignored.
+class FunctionComparatorIgnoringConst : public FunctionComparator {
+public:
+ FunctionComparatorIgnoringConst(const Function *F1, const Function *F2,
+ GlobalNumberState *GN)
+ : FunctionComparator(F1, F2, GN) {}
+
+ int cmpOperandsIgnoringConsts(const Instruction *L, const Instruction *R,
+ unsigned opIdx);
+
+ int cmpBasicBlocksIgnoringConsts(
+ const BasicBlock *BBL, const BasicBlock *BBR,
+ const std::set<std::pair<int, int>> *InstOpndIndex = nullptr);
+
+ int compareIgnoringConsts(
+ const std::set<std::pair<int, int>> *InstOpndIndex = nullptr);
+
+ int compareConstants(const Constant *L, const Constant *R) const {
+ return cmpConstants(L, R);
+ }
+
+private:
+ /// Scratch index for instruction in order during cmpOperandsIgnoringConsts.
+ int Index = 0;
+};
+
+} // end namespace llvm
+#endif // LLVM_TRANSFORMS_UTILS_FUNCTIONCOMPARATORIGNORINGCONST_H
diff --git a/llvm/include/llvm/Transforms/Utils/MergeFunctionsIgnoringConst.h b/llvm/include/llvm/Transforms/Utils/MergeFunctionsIgnoringConst.h
new file mode 100644
index 000000000000000..e63afbb6bbf1718
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Utils/MergeFunctionsIgnoringConst.h
@@ -0,0 +1,29 @@
+//===- MergeFunctionsIgnoringConst.h - Merge Functions ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines helpers used in the MergeFunctionsIgnoringConst.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_MERGEFUNCTIONSIGNORINGCONST_H
+#define LLVM_TRANSFORMS_UTILS_MERGEFUNCTIONSIGNORINGCONST_H
+
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Operator.h"
+
+using namespace llvm;
+
+bool isEligibleInstrunctionForConstantSharing(const Instruction *I);
+
+bool isEligibleOperandForConstantSharing(const Instruction *I, unsigned OpIdx);
+
+bool isEligibleFunction(Function *F);
+
+Value *createCast(IRBuilder<> &Builder, Value *V, Type *DestTy);
+#endif // LLVM_TRANSFORMS_UTILS_MERGEFUNCTIONSIGNORINGCONST_H
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index dd9d799f9d55dcc..f0fb6fe5c67d94a 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -123,6 +123,7 @@
#include "llvm/Transforms/IPO/LowerTypeTests.h"
#include "llvm/Transforms/IPO/MemProfContextDisambiguation.h"
#include "llvm/Transforms/IPO/MergeFunctions.h"
+#include "llvm/Transforms/IPO/MergeFunctionsIgnoringConst.h"
#include "llvm/Transforms/IPO/ModuleInliner.h"
#include "llvm/Transforms/IPO/OpenMPOpt.h"
#include "llvm/Transforms/IPO/PartialInlining.h"
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp
index f4a4802bcb649f3..29ac6213366463b 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -60,6 +60,7 @@
#include "llvm/Transforms/IPO/LowerTypeTests.h"
#include "llvm/Transforms/IPO/MemProfContextDisambiguation.h"
#include "llvm/Transforms/IPO/MergeFunctions.h"
+#include "llvm/Transforms/IPO/MergeFunctionsIgnoringConst.h"
#include "llvm/Transforms/IPO/ModuleInliner.h"
#include "llvm/Transforms/IPO/OpenMPOpt.h"
#include "llvm/Transforms/IPO/PartialInlining.h"
@@ -176,6 +177,10 @@ static cl::opt<bool> EnableMergeFunctions(
"enable-merge-functions", cl::init(false), cl::Hidden,
cl::desc("Enable function merging as part of the optimization pipeline"));
+static cl::opt<bool> EnableMergeFuncIgnoringConst(
+ "enable-merge-func-ignoring-const", cl::init(false), cl::Hidden,
+ cl::desc("Enable function merger that ignores constants"));
+
static cl::opt<bool> EnablePostPGOLoopRotation(
"enable-post-pgo-loop-rotation", cl::init(true), cl::Hidden,
cl::desc("Run the loop rotation transformation after PGO instrumentation"));
@@ -1644,6 +1649,9 @@ ModulePassManager PassBuilder::buildThinLTODefaultPipeline(
MPM.addPass(buildModuleOptimizationPipeline(
Level, ThinOrFullLTOPhase::ThinLTOPostLink));
+ if (EnableMergeFuncIgnoringConst)
+ MPM.addPass(MergeFuncIgnoringConstPass());
+
// Emit annotation remarks.
addAnnotationRemarksPass(MPM);
@@ -1969,6 +1977,9 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
invokeFullLinkTimeOptimizationLastEPCallbacks(MPM, Level);
+ if (EnableMergeFuncIgnoringConst)
+ MPM.addPass(MergeFuncIgnoringConstPass());
+
// Emit annotation remarks.
addAnnotationRemarksPass(MPM);
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 2067fc473b522db..3dae19c0eb66e45 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -87,6 +87,7 @@ MODULE_PASS("lower-ifunc", LowerIFuncPass())
MODULE_PASS("lowertypetests", LowerTypeTestsPass())
MODULE_PASS("metarenamer", MetaRenamerPass())
MODULE_PASS("mergefunc", MergeFunctionsPass())
+MODULE_PASS("mergefunc-ignoring-const", MergeFuncIgnoringConstPass())
MODULE_PASS("name-anon-globals", NameAnonGlobalPass())
MODULE_PASS("no-op-module", NoOpModulePass())
MODULE_PASS("objc-arc-apelim", ObjCARCAPElimPass())
diff --git a/llvm/lib/Transforms/IPO/CMakeLists.txt b/llvm/lib/Transforms/IPO/CMakeLists.txt
index 034f1587ae8df44..4dac04d3369950f 100644
--- a/llvm/lib/Transforms/IPO/CMakeLists.txt
+++ b/llvm/lib/Transforms/IPO/CMakeLists.txt
@@ -30,6 +30,7 @@ add_llvm_component_library(LLVMipo
LowerTypeTests.cpp
MemProfContextDisambiguation.cpp
MergeFunctions.cpp
+ MergeFunctionsIgnoringConst.cpp
ModuleInliner.cpp
OpenMPOpt.cpp
PartialInlining.cpp
diff --git a/llvm/lib/Transforms/IPO/MergeFunctionsIgnoringConst.cpp b/llvm/lib/Transforms/IPO/MergeFunctionsIgnoringConst.cpp
new file mode 100644
index 000000000000000..f5ee17ed0c4fc85
--- /dev/null
+++ b/llvm/lib/Transforms/IPO/MergeFunctionsIgnoringConst.cpp
@@ -0,0 +1,1187 @@
+//===--- MergeFunctionsIgnoringConst.cpp - Merge functions ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass looks for similar functions that are mergeable and folds them.
+// The implementation is similar to LLVM's MergeFunctions pass. Instead of
+// merging identical functions, it merges functions which only differ by a few
+// constants in certain instructions.
+// This is copied from Swift's implementation.
+//
+// This pass should run after LLVM's MergeFunctions pass, because it works best
+// if there are no _identical_ functions in the module.
+// Note: it would also work for identical functions but could produce more
+// code overhead than the LLVM pass.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/IPO/MergeFunctionsIgnoringConst.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StableHashing.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Analysis/ObjCARCUtil.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Operator.h"
+#include "llvm/IR/StructuralHash.h"
+#include "llvm/IR/ValueHandle.h"
+#include "llvm/IR/ValueMap.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/Utils/FunctionComparatorIgnoringConst.h"
+#include "llvm/Transforms/Utils/MergeFunctionsIgnoringConst.h"
+#include <vector>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "mergefunc-ignoring-const"
+
+STATISTIC(NumFunctionsMergedIgnoringConst, "Number of functions merged");
+STATISTIC(NumThunksWrittenIgnoringConst, "Number of thunks generated");
+
+static cl::opt<unsigned> NumFunctionsIgnoringConstForSanityCheck(
+ "mergefunc-ignoringconst-sanity",
+ cl::desc("How many functions in module could be used for "
+ "MergeFunctionsIgnoringConst pass sanity check. "
+ "'0' disables this check. Works only with '-debug' key."),
+ cl::init(0), cl::Hidden);
+
+static cl::opt<unsigned> IgnoringConstMergeThreshold(
+ "mergefunc-ignoringconst-threshold",
+ cl::desc("Functions larger than the threshold are considered for merging."
+ "'0' disables function merging at all."),
+ cl::init(15), cl::Hidden);
+
+cl::opt<bool> UseLinkOnceODRLinkageMerging(
+ "use-linkonceodr-linkage-merging", cl::init(false), cl::Hidden,
+ cl::desc(
+ "Use LinkeOnceODR linkage to deduplicate the identical merged function "
+ "(default = off)"));
+
+cl::opt<bool> NoInlineForMergedFunction(
+ "no-inline-merged-function", cl::init(false), cl::Hidden,
+ cl::desc("set noinline for merged function (default = off)"));
+
+static cl::opt<bool>
+ CastArrayType("merge-cast-array-type", cl::init(false), cl::Hidden,
+ cl::desc("support for casting array type (default = off)"));
+
+static cl::opt<bool> IgnoreMusttailFunction(
+ "ignore-musttail-function", cl::init(false), cl::Hidden,
+ cl::desc(
+ "ignore functions containing callsites with musttail (default = off)"));
+
+static cl::opt<bool> AlwaysCallThunk(
+ "merge-always-call-thunk", cl::init(false), cl::Hidden,
+ cl::desc(
+ "do not replace callsites and always emit a thunk (default = off)"));
+
+static cl::list<std::string> MergeBlockRegexFilters(
+ "merge-block-regex", cl::Optional,
+ cl::desc("Block functions from merging if they match the given "
+ "regular expression"),
+ cl::ZeroOrMore);
+
+static cl::list<std::string> MergeAllowRegexFilters(
+ "merge-allow-regex", cl::Optional,
+ cl::desc("Allow functions from merging if they match the given "
+ "regular expression"),
+ cl::ZeroOrMore);
+
+namespace {
+
+/// MergeFuncIgnoringConst finds functions which only differ by constants in
+/// certain instructions, e.g. resulting from specialized functions of layout
+/// compatible types.
+/// Such functions are merged by replacing the differing constants by a
+/// parameter. The original functions are replaced by thunks which call the
+/// merged function with the specific argument constants.
+///
+class MergeFuncIgnoringConstImpl {
+public:
+ MergeFuncIgnoringConstImpl(std::string Suffix)
+ : FnTree(FunctionNodeCmp(&GlobalNumbers)), MergeFuncSuffix(Suffix) {}
+
+ bool runImpl(Module &M);
+
+private:
+ struct FunctionEntry;
+
+ /// Describes the set of functions which are considered as "equivalent" (i.e.
+ /// only differing by some constants).
+ struct EquivalenceClass {
+ /// The single-linked list of all functions which are a member of this
+ /// equivalence class.
+ FunctionEntry *First;
+
+ /// A very cheap hash, used to early exit if functions do not match.
+ IRHash Hash;
+
+ public:
+ // Note the hash is recalculated potentially multiple times, but it is
+ // cheap.
+ EquivalenceClass(FunctionEntry *First)
+ : First(First), Hash(StructuralHash(*First->F)) {
+ assert(!First->Next);
+ }
+ };
+
+ /// The function comparison operator is provided here so that FunctionNodes do
+ /// not need to become larger with another pointer.
+ class FunctionNodeCmp {
+ GlobalNumberState *GlobalNumbers;
+
+ public:
+ FunctionNodeCmp(GlobalNumberState *GN) : GlobalNumbers(GN) {}
+ bool operator()(const EquivalenceClass &LHS,
+ const EquivalenceClass &RHS) const {
+ // Order first by hashes, then full function comparison.
+ if (LHS.Hash != RHS.Hash)
+ return LHS.Hash < RHS.Hash;
+ FunctionComparatorIgnoringConst FCmp(LHS.First->F, RHS.First->F,
+ GlobalNumbers);
+ return FCmp.compareIgnoringConsts() == -1;
+ }
+ };
+ using FnTreeType = std::set<EquivalenceClass, FunctionNodeCmp>;
+
+ ///
+ struct FunctionEntry {
+ FunctionEntry(Function *F, FnTreeType::iterator I)
+ : F(F), Next(nullptr), NumUnhandledCallees(0), TreeIter(I),
+ IsMerged(false) {}
+
+ /// Back-link to the function.
+ AssertingVH<Function> F;
+
+ /// The next function in its equivalence class.
+ FunctionEntry *Next;
+
+ /// The number of not-yet merged callees. Used to process the merging in
+ /// bottom-up call order.
+ /// This is only valid in the first entry of an equivalence class. The
+ /// counts of all functions in an equivalence class are accumulated in the
+ /// first entry.
+ int NumUnhandledCallees;
+
+ /// The iterator of the function's equivalence class in the FnTree.
+ /// It's FnTree.end() if the function is not in an equivalence class.
+ FnTreeType::iterator TreeIter;
+
+ /// True if this function is already a thunk, calling the merged function.
+ bool IsMerged;
+ };
+
+ /// Describes an operator of a specific instruction.
+ struct OpLocation {
+ Instruction *I;
+ unsigned OpIndex;
+ };
+
+ /// Information for a function. Used during merging.
+ struct FunctionInfo {
+
+ FunctionInfo(Function *F)
+ : F(F), CurrentInst(nullptr), NumParamsNeeded(0) {}
+
+ void init() {
+ CurrentInst = &*F->begin()->begin();
+ NumParamsNeeded = 0;
+ }
+
+ /// Advances the current instruction to the next instruction.
+ void nextInst() {
+ assert(CurrentInst);
+ if (CurrentInst->isTerminator()) {
+ auto BlockIter = std::next(CurrentInst->getParent()->getIterator());
+ if (BlockIter == F->end()) {
+ CurrentInst = nullptr;
+ return;
+ }
+ CurrentInst = &*BlockIter->begin();
+ return;
+ }
+ CurrentInst = &*std::next(CurrentInst->getIterator());
+ }
+
+ Function *F;
+
+ /// The current instruction while iterating over all instructions.
+ Instruction *CurrentInst;
+
+ /// Roughly the number of parameters needed if this function would be
+ /// merged with the first function of the equivalence class.
+ int NumParamsNeeded;
+ };
+
+ using FunctionInfos = SmallVector<FunctionInfo, 8>;
+
+ /// Describes a parameter which we create to parameterize the merged function.
+ struct ParamInfo {
+ /// The value of the parameter for all the functions in the equivalence
+ /// class.
+ SmallVector<Constant *, 8> Values;
+
+ /// All uses of the parameter in the merged function.
+ SmallVector<OpLocation, 16> Uses;
+
+ /// Checks if this parameter can be used to describe an operand in all
+ /// functions of the equivalence class. Returns true if all values match
+ /// the specific instruction operands in all functions.
+ bool matches(const FunctionInfos &FInfos, unsigned OpIdx) const {
+ unsigned NumFuncs = FInfos.size();
+ assert(Values.size() == NumFuncs);
+ for (unsigned Idx = 0; Idx < NumFuncs; ++Idx) {
+ const FunctionInfo &FI = FInfos[Idx];
+ Constant *C = cast<Constant>(FI.CurrentInst->getOperand(OpIdx));
+ if (Values[Idx] != C)
+ return false;
+ }
+ return true;
+ }
+ };
+
+ using ParamInfos = SmallVector<ParamInfo, 16>;
+
+ Module *CurrentModule = nullptr;
+
+ GlobalNumberState GlobalNumbers;
+
+ /// A work queue of functions that may have been modified and should be
+ /// analyzed again.
+ std::vector<WeakTrackingVH> Deferred;
+
+ /// The set of all distinct functions. Use the insert() and remove() methods
+ /// to modify it. The map allows efficient lookup and deferring of Functions.
+ FnTreeType FnTree;
+
+ ValueMap<Function *, FunctionEntry *> FuncEntries;
+
+ std::string MergeFuncSuffix = ".Tm";
+
+ FunctionEntry *getEntry(Function *F) const { return FuncEntries.lookup(F); }
+
+ bool isInEquiva...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/71584
More information about the llvm-commits
mailing list