[llvm] [GlobalMergeFunctions] Skip No Params (PR #116548)

Kyungwoo Lee via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 17 12:47:32 PST 2024


https://github.com/kyulee-com updated https://github.com/llvm/llvm-project/pull/116548

>From 0515e2106654c4f0ed393ba21e47786735730153 Mon Sep 17 00:00:00 2001
From: Kyungwoo Lee <kyulee at meta.com>
Date: Sun, 17 Nov 2024 08:47:46 -0800
Subject: [PATCH] [GlobalMergeFunctions] Skip No Params

---
 llvm/lib/CGData/StableFunctionMap.cpp         | 50 ++++++++++++-------
 llvm/lib/CodeGen/GlobalMergeFunctions.cpp     | 11 ++--
 .../Generic}/cgdata-merge-local.ll            |  2 +-
 .../CodeGen/Generic/cgdata-merge-no-params.ll | 45 +++++++++++++++++
 4 files changed, 85 insertions(+), 23 deletions(-)
 rename llvm/test/{ThinLTO/AArch64 => CodeGen/Generic}/cgdata-merge-local.ll (98%)
 create mode 100644 llvm/test/CodeGen/Generic/cgdata-merge-no-params.ll

diff --git a/llvm/lib/CGData/StableFunctionMap.cpp b/llvm/lib/CGData/StableFunctionMap.cpp
index fe7be0c0b6e7b8..b3f5ad9752a2e8 100644
--- a/llvm/lib/CGData/StableFunctionMap.cpp
+++ b/llvm/lib/CGData/StableFunctionMap.cpp
@@ -14,6 +14,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CGData/StableFunctionMap.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 
@@ -35,21 +36,30 @@ static cl::opt<unsigned> GlobalMergingMaxParams(
     cl::desc(
         "The maximum number of parameters allowed when merging functions."),
     cl::init(std::numeric_limits<unsigned>::max()), cl::Hidden);
-static cl::opt<unsigned> GlobalMergingParamOverhead(
+static cl::opt<bool> GlobalMergingSkipNoParams(
+    "global-merging-skip-no-params",
+    cl::desc("Skip merging functions with no parameters."), cl::init(false),
+    cl::Hidden);
+static cl::opt<double> GlobalMergingInstOverhead(
+    "global-merging-inst-overhead",
+    cl::desc("The overhead cost associated with each instruction when lowering "
+             "to machine instruction."),
+    cl::init(1.0), cl::Hidden);
+static cl::opt<double> GlobalMergingParamOverhead(
     "global-merging-param-overhead",
     cl::desc("The overhead cost associated with each parameter when merging "
              "functions."),
-    cl::init(2), cl::Hidden);
-static cl::opt<unsigned>
+    cl::init(2.0), cl::Hidden);
+static cl::opt<double>
     GlobalMergingCallOverhead("global-merging-call-overhead",
                               cl::desc("The overhead cost associated with each "
                                        "function call when merging functions."),
-                              cl::init(1), cl::Hidden);
-static cl::opt<unsigned> GlobalMergingExtraThreshold(
+                              cl::init(1.0), cl::Hidden);
+static cl::opt<double> GlobalMergingExtraThreshold(
     "global-merging-extra-threshold",
     cl::desc("An additional cost threshold that must be exceeded for merging "
              "to be considered beneficial."),
-    cl::init(0), cl::Hidden);
+    cl::init(0.0), cl::Hidden);
 
 unsigned StableFunctionMap::getIdOrCreateForName(StringRef Name) {
   auto It = NameToId.find(Name);
@@ -159,22 +169,28 @@ static bool isProfitable(
   unsigned InstCount = SFS[0]->InstCount;
   if (InstCount < GlobalMergingMinInstrs)
     return false;
-
-  unsigned ParamCount = SFS[0]->IndexOperandHashMap->size();
-  if (ParamCount > GlobalMergingMaxParams)
-    return false;
-
-  unsigned Benefit = InstCount * (StableFunctionCount - 1);
-  unsigned Cost =
-      (GlobalMergingParamOverhead * ParamCount + GlobalMergingCallOverhead) *
-          StableFunctionCount +
-      GlobalMergingExtraThreshold;
+  double Benefit =
+      InstCount * (StableFunctionCount - 1) * GlobalMergingInstOverhead;
+
+  double Cost = 0.0;
+  SmallSet<stable_hash, 8> UniqueHashVals;
+  for (auto &SF : SFS) {
+    UniqueHashVals.clear();
+    for (auto &[IndexPair, Hash] : *SF->IndexOperandHashMap)
+      UniqueHashVals.insert(Hash);
+    unsigned ParamCount = UniqueHashVals.size();
+    if (ParamCount > GlobalMergingMaxParams)
+      return false;
+    if (GlobalMergingSkipNoParams && ParamCount == 0)
+      return false;
+    Cost += ParamCount * GlobalMergingParamOverhead + GlobalMergingCallOverhead;
+  }
+  Cost += GlobalMergingExtraThreshold;
 
   bool Result = Benefit > Cost;
   LLVM_DEBUG(dbgs() << "isProfitable: Hash = " << SFS[0]->Hash << ", "
                     << "StableFunctionCount = " << StableFunctionCount
                     << ", InstCount = " << InstCount
-                    << ", ParamCount = " << ParamCount
                     << ", Benefit = " << Benefit << ", Cost = " << Cost
                     << ", Result = " << (Result ? "true" : "false") << "\n");
   return Result;
diff --git a/llvm/lib/CodeGen/GlobalMergeFunctions.cpp b/llvm/lib/CodeGen/GlobalMergeFunctions.cpp
index c8f1b98c9a18e9..470582885fab0c 100644
--- a/llvm/lib/CodeGen/GlobalMergeFunctions.cpp
+++ b/llvm/lib/CodeGen/GlobalMergeFunctions.cpp
@@ -405,12 +405,13 @@ static ParamLocsVecTy computeParamInfo(
   }
 
   ParamLocsVecTy ParamLocsVec;
-  for (auto &[HashSeq, Locs] : HashSeqToLocs) {
+  for (auto &[HashSeq, Locs] : HashSeqToLocs)
     ParamLocsVec.push_back(std::move(Locs));
-    llvm::sort(ParamLocsVec, [&](const ParamLocs &L, const ParamLocs &R) {
-      return L[0] < R[0];
-    });
-  }
+
+  llvm::sort(ParamLocsVec, [&](const ParamLocs &L, const ParamLocs &R) {
+    return L[0] < R[0];
+  });
+
   return ParamLocsVec;
 }
 
diff --git a/llvm/test/ThinLTO/AArch64/cgdata-merge-local.ll b/llvm/test/CodeGen/Generic/cgdata-merge-local.ll
similarity index 98%
rename from llvm/test/ThinLTO/AArch64/cgdata-merge-local.ll
rename to llvm/test/CodeGen/Generic/cgdata-merge-local.ll
index 660ffe6109948f..3517fbd3ae8a26 100644
--- a/llvm/test/ThinLTO/AArch64/cgdata-merge-local.ll
+++ b/llvm/test/CodeGen/Generic/cgdata-merge-local.ll
@@ -2,7 +2,7 @@
 ; while parameterizing a difference in their global variables, g1 and g2.
 ; To achieve this, we create two instances of the global merging function, f1.Tgm and f2.Tgm,
 ; which are tail-called from thunks f1 and f2 respectively.
-; These identical functions, f1.Tgm and f2.Tgm, will be folded by the linker via Identical Code Folding (IFC).
+; These identical functions, f1.Tgm and f2.Tgm, will be folded by the linker via Identical Code Folding (ICF).
 
 ; RUN: opt -S --passes=global-merge-func %s | FileCheck %s
 
diff --git a/llvm/test/CodeGen/Generic/cgdata-merge-no-params.ll b/llvm/test/CodeGen/Generic/cgdata-merge-no-params.ll
new file mode 100644
index 00000000000000..bf892add25e592
--- /dev/null
+++ b/llvm/test/CodeGen/Generic/cgdata-merge-no-params.ll
@@ -0,0 +1,45 @@
+; This test verifies whether two identical functions, f1 and f2, can be merged
+; locally using the global merge function.
+; The functions, f1.Tgm and f2.Tgm, will be folded by the linker through
+; Identical Code Folding (ICF).
+; While identical functions can already be folded by the linker, creating this
+; canonical form can be beneficial in downstream passes. This merging process
+; can be controlled by the -global-merging-skip-no-params option.
+
+; RUN: llc -enable-global-merge-func=true -global-merging-skip-no-params=false < %s | FileCheck %s --check-prefix=MERGE
+; RUN: llc -enable-global-merge-func=true -global-merging-skip-no-params=true < %s | FileCheck %s --check-prefix=NOMERGE
+
+; MERGE: _f1.Tgm
+; MERGE: _f2.Tgm
+
+; NOMERGE-NOT: _f1.Tgm
+; NOMERGE-NOT: _f2.Tgm
+
+target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+target triple = "arm64-unknown-ios12.0.0"
+
+ at g = external local_unnamed_addr global [0 x i32], align 4
+ at g1 = external global i32, align 4
+ at g2 = external global i32, align 4
+
+define i32 @f1(i32 %a) {
+entry:
+  %idxprom = sext i32 %a to i64
+  %arrayidx = getelementptr inbounds [0 x i32], [0 x i32]* @g, i64 0, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %1 = load volatile i32, i32* @g1, align 4
+  %mul = mul nsw i32 %1, %0
+  %add = add nsw i32 %mul, 1
+  ret i32 %add
+}
+
+define i32 @f2(i32 %a) {
+entry:
+  %idxprom = sext i32 %a to i64
+  %arrayidx = getelementptr inbounds [0 x i32], [0 x i32]* @g, i64 0, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %1 = load volatile i32, i32* @g1, align 4
+  %mul = mul nsw i32 %1, %0
+  %add = add nsw i32 %mul, 1
+  ret i32 %add
+}



More information about the llvm-commits mailing list