[llvm] [MergeFunctions] Add support to run the pass over a set of function pointers (PR #111045)

Stephen Tozer via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 15 06:45:53 PST 2024


================
@@ -409,24 +428,36 @@ static bool isEligibleForMerging(Function &F) {
          !hasDistinctMetadataIntrinsic(F);
 }
 
-bool MergeFunctions::runOnModule(Module &M) {
+template <typename FuncContainer>
+bool MergeFunctions::runOnModule(FuncContainer &M) {
   bool Changed = false;
 
-  SmallVector<GlobalValue *, 4> UsedV;
-  collectUsedGlobalVariables(M, UsedV, /*CompilerUsed=*/false);
-  collectUsedGlobalVariables(M, UsedV, /*CompilerUsed=*/true);
-  Used.insert(UsedV.begin(), UsedV.end());
+  if constexpr (std::is_same<FuncContainer, Module>::value) {
+    SmallVector<GlobalValue *, 4> UsedV;
+    collectUsedGlobalVariables(M, UsedV, /*CompilerUsed=*/false);
+    collectUsedGlobalVariables(M, UsedV, /*CompilerUsed=*/true);
+    Used.insert(UsedV.begin(), UsedV.end());
+  }
 
   // All functions in the module, ordered by hash. Functions with a unique
   // hash value are easily eliminated.
   std::vector<std::pair<stable_hash, Function *>> HashedFuncs;
-  for (Function &Func : M) {
-    if (isEligibleForMerging(Func)) {
-      HashedFuncs.push_back({StructuralHash(Func), &Func});
+  if constexpr (std::is_same<FuncContainer, std::set<Function *>>::value) {
+    for (Function *Func : M) {
+      if (isEligibleForMerging(*Func)) {
+        HashedFuncs.push_back({StructuralHash(*Func), Func});
+      }
+    }
+  }
+  if constexpr (std::is_same<FuncContainer, Module>::value) {
+    for (Function &Func : M) {
+      if (isEligibleForMerging(Func)) {
+        HashedFuncs.push_back({StructuralHash(Func), &Func});
+      }
----------------
SLTozer wrote:

Small suggestion, but this could be further simplified (and made less dependent on the exact types passed into it) by using one loop with an `auto` type and extracting a `Function*` from that. In particular, right now if the user changed the variable type being passed in from `std::set` to `llvm::DenseSet` or some similar change, this function would successfully compile but neither of these blocks would be entered. I think the simplest way would be to create a pair of functions above this one:
```
  inline Function *asPtr(Function *Fn) { return Fn; }
  inline Function *asPtr(Function &Fn) { return &Fn; }
...
  for (auto Func : M) {
    Function *FuncPtr = asPtr(Func);
```
Or, you could do it inline with `if constexpr`:
```
  Function *FuncPtr;
  if constexpr (std::is_reference_type_v<decltype(Func)>)
    FuncPtr = &Func;
  else
    FuncPtr = Func;
```

https://github.com/llvm/llvm-project/pull/111045


More information about the llvm-commits mailing list