[PATCH] D127751: [MergeFunctions] Preserve symbols used llvm.used/llvm.compiler.used

Amanieu d'Antras via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 14 08:14:00 PDT 2022


Amanieu created this revision.
Amanieu added a reviewer: nikic.
Herald added subscribers: ormris, hiraditya.
Herald added a project: All.
Amanieu requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

llvm.used and llvm.compiler.used are often used with inline assembly that refers to a specific symbol so that the symbol is kept through to the linker even though there are no references to it from LLVM IR. This fixes the MergeFunctions pass to preserve references to these symbols in llvm.used/llvm.compiler.used so they are not deleted from the IR. This doesn't prevent these functions from being merged, but guarantees that an alias or thunk with the expected symbol name is kept in the IR.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D127751

Files:
  llvm/lib/Transforms/IPO/MergeFunctions.cpp
  llvm/test/Transforms/MergeFunc/merge-used.ll


Index: llvm/test/Transforms/MergeFunc/merge-used.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/MergeFunc/merge-used.ll
@@ -0,0 +1,18 @@
+; RUN: opt -S -mergefunc < %s | FileCheck %s
+
+ at llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (i32 (i32)* @a to i8*)], section "llvm.metadata"
+
+; CHECK: @a
+; CHECK: @b
+
+define internal i32 @a(i32 %a) unnamed_addr {
+  %b = xor i32 %a, 0
+  %c = xor i32 %b, 0
+  ret i32 %c
+}
+
+define i32 @b(i32 %a) unnamed_addr {
+  %b = xor i32 %a, 0
+  %c = xor i32 %b, 0
+  ret i32 %c
+}
Index: llvm/lib/Transforms/IPO/MergeFunctions.cpp
===================================================================
--- llvm/lib/Transforms/IPO/MergeFunctions.cpp
+++ llvm/lib/Transforms/IPO/MergeFunctions.cpp
@@ -120,6 +120,7 @@
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/IPO.h"
 #include "llvm/Transforms/Utils/FunctionComparator.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
 #include <algorithm>
 #include <cassert>
 #include <iterator>
@@ -225,6 +226,10 @@
   /// analyzed again.
   std::vector<WeakTrackingVH> Deferred;
 
+  /// Set of values marked as used in llvm.used and llvm.compiler.used.
+  SmallPtrSet<GlobalValue *, 4> Used;
+  SmallPtrSet<GlobalValue *, 4> CompilerUsed;
+
 #ifndef NDEBUG
   /// Checks the rules of order relation introduced among functions set.
   /// Returns true, if check has been passed, and false if failed.
@@ -407,6 +412,14 @@
 bool MergeFunctions::runOnModule(Module &M) {
   bool Changed = false;
 
+  // Keep track of functions referred to by llvm.used/llvm.compiler.used.
+  SmallVector<GlobalValue *, 4> UsedV;
+  collectUsedGlobalVariables(M, UsedV, /*CompilerUsed=*/false);
+  Used.insert(UsedV.begin(), UsedV.end());
+  SmallVector<GlobalValue *, 4> CompilerUsedV;
+  collectUsedGlobalVariables(M, CompilerUsedV, /*CompilerUsed=*/true);
+  CompilerUsed.insert(CompilerUsedV.begin(), CompilerUsedV.end());
+
   // All functions in the module, ordered by hash. Functions with a unique
   // hash value are easily eliminated.
   std::vector<std::pair<FunctionComparator::FunctionHash, Function *>>
@@ -453,6 +466,8 @@
   FnTree.clear();
   FNodesInTree.clear();
   GlobalNumbers.clear();
+  Used.clear();
+  CompilerUsed.clear();
 
   return Changed;
 }
@@ -833,6 +848,18 @@
         Constant *BitcastF = ConstantExpr::getBitCast(F, G->getType());
         removeUsers(G);
         G->replaceAllUsesWith(BitcastF);
+
+        // Functions referred to by llvm.used/llvm.compiler.used are special:
+        // there are uses of the symbol name that are not visible to LLVM,
+        // usually from inline asm. We need to handle these by keeping the old
+        // symbol in the used list as an alias or thunk.
+        //
+        // RAUW will have removed references to G from the existing list, make
+        // sure to add it back.
+        if (Used.contains(G))
+          appendToUsed(*G->getParent(), {G});
+        if (CompilerUsed.contains(G))
+          appendToCompilerUsed(*G->getParent(), {G});
       } else {
         // Redirect direct callers of G to F. (See note on MergeFunctionsPDI
         // above).


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D127751.436790.patch
Type: text/x-patch
Size: 3196 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220614/8fe7510b/attachment.bin>


More information about the llvm-commits mailing list