MaskRay updated this revision to Diff 446277.
MaskRay added a comment.

Add blank lines
remove trailing whitespace


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129009/new/

https://reviews.llvm.org/D129009

Files:
  llvm/include/llvm/IR/GlobalIFunc.h
  llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
  llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
  llvm/lib/IR/Globals.cpp
  llvm/lib/Transforms/IPO/FunctionImport.cpp
  llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
  llvm/test/ThinLTO/X86/alias-ifunc.ll

Index: llvm/test/ThinLTO/X86/alias-ifunc.ll
===================================================================
--- /dev/null
+++ llvm/test/ThinLTO/X86/alias-ifunc.ll
@@ -0,0 +1,57 @@
+; RUN: opt -module-summary -o %t.bc %s
+; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-BAR
+; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-BAZ
+; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-QUX
+; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-RESOLVER
+; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-QUUX
+; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-CORGE
+; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-GRAULT
+; RUN: llvm-lto2 run %t.bc -r %t.bc,foo,px -r %t.bc,bar,px -r %t.bc,baz,px -r %t.bc,qux,px -r %t.bc,grault,px -o %t2
+; RUN: llvm-nm %t2.1 | FileCheck %s --check-prefix=CHECK-SYMBOL
+
+; CHECK-SYMBOL: i bar
+; CHECK-SYMBOL: i baz
+; CHECK-SYMBOL: i foo
+; CHECK-SYMBOL: t foo_resolver
+; CHECK-SYMBOL: i grault
+; CHECK-SYMBOL: i quuz
+; CHECK-SYMBOL: i qux
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+@foo = ifunc i32 (i32), ptr @foo_resolver
+; CHECK-RESOLVER:      (name: "foo_resolver"
+; CHECK-RESOLVER-SAME: live: 1
+define internal i32 (i32)* @foo_resolver() {
+entry:
+  ret i32 (i32)* null
+}
+; CHECK-BAR:      (name: "bar"
+; CHECK-BAR-NOT:  summaries: (
+; CHECK-BAR-SAME: ; guid = {{[0-9]+}}
+@bar = alias i32 (i32), ptr @foo
+
+; CHECK-BAZ:      (name: "baz"
+; CHECK-BAZ-NOT:  summaries: (
+; CHECK-BAZ-SAME: ; guid = {{[0-9]+}}
+@baz = weak alias i32 (i32), ptr @foo
+
+; CHECK-QUX:      (name: "qux"
+; CHECK-QUX-NOT:  summaries: (
+; CHECK-QUX-SAME: ; guid = {{[0-9]+}}
+@qux = alias i32 (i32), ptr @bar
+
+; CHECK-QUUX:      (name: "quux"
+; CHECK-QUUX-SAME: live: 1
+@quux = internal alias i32 (i32)* (), ptr @foo_resolver
+@quuz = internal ifunc i32 (i32), ptr @quux
+
+; CHECK-CORGE:      (name: "corge"
+; CHECK-CORGE-NOT:  summaries: (
+; CHECK-CORGE-SAME: ; guid = {{[0-9]+}}
+@corge = internal alias i32 (i32), ptr @quuz
+
+; CHECK-GRAULT:      (name: "grault"
+; CHECK-GRAULT-NOT:  summaries: (
+; CHECK-GRAULT-SAME: ; guid = {{[0-9]+}}
+@grault = alias i32 (i32), ptr @corge
Index: llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
===================================================================
--- llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
+++ llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
@@ -35,6 +35,13 @@
 bool FunctionImportGlobalProcessing::shouldPromoteLocalToGlobal(
     const GlobalValue *SGV, ValueInfo VI) {
   assert(SGV->hasLocalLinkage());
+
+  // Ifuncs and ifunc alias does not have summary.
+  if (isa<GlobalIFunc>(SGV) ||
+      (isa<GlobalAlias>(SGV) &&
+       isa<GlobalIFunc>(cast<GlobalAlias>(SGV)->getAliaseeObject())))
+    return false;
+
   // Both the imported references and the original local variable must
   // be promoted.
   if (!isPerformingImport() && !isModuleExporting())
Index: llvm/lib/Transforms/IPO/FunctionImport.cpp
===================================================================
--- llvm/lib/Transforms/IPO/FunctionImport.cpp
+++ llvm/lib/Transforms/IPO/FunctionImport.cpp
@@ -1147,6 +1147,14 @@
   // Declare a callback for the internalize pass that will ask for every
   // candidate GlobalValue if it can be internalized or not.
   auto MustPreserveGV = [&](const GlobalValue &GV) -> bool {
+    // It may be the case that GV is on a chain of an ifunc, its alias and
+    // subsequent aliases. In this case, the summary for the value is not
+    // available.
+    if (isa<GlobalIFunc>(&GV) ||
+        (isa<GlobalAlias>(&GV) &&
+         isa<GlobalIFunc>(cast<GlobalAlias>(&GV)->getAliaseeObject())))
+      return true;
+
     // Lookup the linkage recorded in the summaries during global analysis.
     auto GS = DefinedGlobals.find(GV.getGUID());
     if (GS == DefinedGlobals.end()) {
@@ -1277,7 +1285,7 @@
       }
     }
     for (GlobalAlias &GA : SrcModule->aliases()) {
-      if (!GA.hasName())
+      if (!GA.hasName() || isa<GlobalIFunc>(GA.getAliaseeObject()))
         continue;
       auto GUID = GA.getGUID();
       auto Import = ImportGUIDs.count(GUID);
Index: llvm/lib/IR/Globals.cpp
===================================================================
--- llvm/lib/IR/Globals.cpp
+++ llvm/lib/IR/Globals.cpp
@@ -316,32 +316,38 @@
   return true;
 }
 
+template <typename Operation>
 static const GlobalObject *
-findBaseObject(const Constant *C, DenseSet<const GlobalAlias *> &Aliases) {
-  if (auto *GO = dyn_cast<GlobalObject>(C))
+findBaseObject(const Constant *C, DenseSet<const GlobalAlias *> &Aliases,
+               const Operation &Op) {
+  if (auto *GO = dyn_cast<GlobalObject>(C)) {
+    Op(*GO);
     return GO;
-  if (auto *GA = dyn_cast<GlobalAlias>(C))
+  }
+  if (auto *GA = dyn_cast<GlobalAlias>(C)) {
+    Op(*GA);
     if (Aliases.insert(GA).second)
-      return findBaseObject(GA->getOperand(0), Aliases);
+      return findBaseObject(GA->getOperand(0), Aliases, Op);
+  }
   if (auto *CE = dyn_cast<ConstantExpr>(C)) {
     switch (CE->getOpcode()) {
     case Instruction::Add: {
-      auto *LHS = findBaseObject(CE->getOperand(0), Aliases);
-      auto *RHS = findBaseObject(CE->getOperand(1), Aliases);
+      auto *LHS = findBaseObject(CE->getOperand(0), Aliases, Op);
+      auto *RHS = findBaseObject(CE->getOperand(1), Aliases, Op);
       if (LHS && RHS)
         return nullptr;
       return LHS ? LHS : RHS;
     }
     case Instruction::Sub: {
-      if (findBaseObject(CE->getOperand(1), Aliases))
+      if (findBaseObject(CE->getOperand(1), Aliases, Op))
         return nullptr;
-      return findBaseObject(CE->getOperand(0), Aliases);
+      return findBaseObject(CE->getOperand(0), Aliases, Op);
     }
     case Instruction::IntToPtr:
     case Instruction::PtrToInt:
     case Instruction::BitCast:
     case Instruction::GetElementPtr:
-      return findBaseObject(CE->getOperand(0), Aliases);
+      return findBaseObject(CE->getOperand(0), Aliases, Op);
     default:
       break;
     }
@@ -351,7 +357,7 @@
 
 const GlobalObject *GlobalValue::getAliaseeObject() const {
   DenseSet<const GlobalAlias *> Aliases;
-  return findBaseObject(this, Aliases);
+  return findBaseObject(this, Aliases, [](const GlobalValue &) {});
 }
 
 bool GlobalValue::isAbsoluteSymbolRef() const {
@@ -544,7 +550,7 @@
 
 const GlobalObject *GlobalAlias::getAliaseeObject() const {
   DenseSet<const GlobalAlias *> Aliases;
-  return findBaseObject(getOperand(0), Aliases);
+  return findBaseObject(getOperand(0), Aliases, [](const GlobalValue &) {});
 }
 
 //===----------------------------------------------------------------------===//
@@ -577,5 +583,12 @@
 
 const Function *GlobalIFunc::getResolverFunction() const {
   DenseSet<const GlobalAlias *> Aliases;
-  return dyn_cast<Function>(findBaseObject(getResolver(), Aliases));
+  return dyn_cast<Function>(
+      findBaseObject(getResolver(), Aliases, [](const GlobalValue &) {}));
+}
+
+void GlobalIFunc::applyAlongResolverPath(
+    function_ref<void(const GlobalValue &)> Op) const {
+  DenseSet<const GlobalAlias *> Aliases;
+  findBaseObject(getResolver(), Aliases, Op);
 }
Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
===================================================================
--- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -4104,8 +4104,9 @@
 
   for (const GlobalAlias &A : M.aliases()) {
     auto *Aliasee = A.getAliaseeObject();
-    if (!Aliasee->hasName())
-      // Nameless function don't have an entry in the summary, skip it.
+    // Skip ifunc and nameless functions which don't have an entry in the
+    // summary.
+    if (!Aliasee->hasName() || isa<GlobalIFunc>(Aliasee))
       continue;
     auto AliasId = VE.getValueID(&A);
     auto AliaseeId = VE.getValueID(Aliasee);
Index: llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
===================================================================
--- llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
+++ llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
@@ -646,15 +646,18 @@
   Index.addGlobalValueSummary(V, std::move(GVarSummary));
 }
 
-static void
-computeAliasSummary(ModuleSummaryIndex &Index, const GlobalAlias &A,
-                    DenseSet<GlobalValue::GUID> &CantBePromoted) {
+static void computeAliasSummary(ModuleSummaryIndex &Index, const GlobalAlias &A,
+                                DenseSet<GlobalValue::GUID> &CantBePromoted) {
+  // Skip summary for indirect function aliases as summary for aliasee will not
+  // be emitted.
+  const GlobalObject *Aliasee = A.getAliaseeObject();
+  if (isa<GlobalIFunc>(Aliasee))
+    return;
   bool NonRenamableLocal = isNonRenamableLocal(A);
   GlobalValueSummary::GVFlags Flags(
       A.getLinkage(), A.getVisibility(), NonRenamableLocal,
       /* Live = */ false, A.isDSOLocal(), A.canBeOmittedFromSymbolTable());
   auto AS = std::make_unique<AliasSummary>(Flags);
-  auto *Aliasee = A.getAliaseeObject();
   auto AliaseeVI = Index.getValueInfo(Aliasee->getGUID());
   assert(AliaseeVI && "Alias expects aliasee summary to be available");
   assert(AliaseeVI.getSummaryList().size() == 1 &&
@@ -811,6 +814,13 @@
   for (const GlobalAlias &A : M.aliases())
     computeAliasSummary(Index, A, CantBePromoted);
 
+  // Iterate through ifuncs, set their resolvers all alive.
+  for (const GlobalIFunc &I : M.ifuncs()) {
+    I.applyAlongResolverPath([&Index](const GlobalValue &GV) {
+      Index.getGlobalValueSummary(GV)->setLive(true);
+    });
+  }
+
   for (auto *V : LocalsUsed) {
     auto *Summary = Index.getGlobalValueSummary(*V);
     assert(Summary && "Missing summary for global value");
Index: llvm/include/llvm/IR/GlobalIFunc.h
===================================================================
--- llvm/include/llvm/IR/GlobalIFunc.h
+++ llvm/include/llvm/IR/GlobalIFunc.h
@@ -93,6 +93,13 @@
   static bool classof(const Value *V) {
     return V->getValueID() == Value::GlobalIFuncVal;
   }
+
+  /// Apply specific operation to all resolver-related values.
+  /// If resolver target is already a global object, then apply the operation to
+  /// it directly. If target is a GlobalExpr or a GlobalAlias, evaluate it to
+  /// its base object and apply the operation for the base object and all
+  /// aliases along the path.
+  void applyAlongResolverPath(function_ref<void(const GlobalValue &)> Op) const;
 };
 
 template <>
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to