diff --git a/llvm-preserve-symbols-used.patch b/llvm-preserve-symbols-used.patch new file mode 100644 index 0000000..cb4195b --- /dev/null +++ b/llvm-preserve-symbols-used.patch @@ -0,0 +1,123 @@ +From 2cdf8f7c0bdc4d36f236e4cbb45bd9f996f15d14 Mon Sep 17 00:00:00 2001 +From: Amanieu d'Antras +Date: Thu, 16 Jun 2022 21:31:33 +0100 +Subject: [PATCH 1/8] [MergeFunctions] Preserve symbols used + llvm.used/llvm.compiler.used + +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. + +Differential Revision: https://reviews.llvm.org/D127751 + +(cherry picked from commit caa2a829cdf905a5e8664d96a464d414b2adb42e) +--- + llvm/lib/Transforms/IPO/MergeFunctions.cpp | 15 ++++++++- + llvm/test/Transforms/MergeFunc/merge-used.ll | 35 ++++++++++++++++++++ + 2 files changed, 49 insertions(+), 1 deletion(-) + create mode 100644 llvm/test/Transforms/MergeFunc/merge-used.ll + +diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp +index 97ef872c5499..b51e0a5d4dce 100644 +--- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp ++++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp +@@ -123,6 +123,7 @@ + #include "llvm/Transforms/IPO.h" + #include "llvm/Transforms/IPO/MergeFunctions.h" + #include "llvm/Transforms/Utils/FunctionComparator.h" ++#include "llvm/Transforms/Utils/ModuleUtils.h" + #include + #include + #include +@@ -228,6 +229,9 @@ private: + /// analyzed again. + std::vector Deferred; + ++ /// Set of values marked as used in llvm.used and llvm.compiler.used. ++ SmallPtrSet Used; ++ + #ifndef NDEBUG + /// Checks the rules of order relation introduced among functions set. + /// Returns true, if sanity check has been passed, and false if failed. +@@ -410,6 +414,11 @@ static bool isEligibleForMerging(Function &F) { + bool MergeFunctions::runOnModule(Module &M) { + bool Changed = false; + ++ SmallVector 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> +@@ -456,6 +465,7 @@ bool MergeFunctions::runOnModule(Module &M) { + FnTree.clear(); + FNodesInTree.clear(); + GlobalNumbers.clear(); ++ Used.clear(); + + return Changed; + } +@@ -828,7 +838,10 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) { + // For better debugability, under MergeFunctionsPDI, we do not modify G's + // call sites to point to F even when within the same translation unit. + if (!G->isInterposable() && !MergeFunctionsPDI) { +- if (G->hasGlobalUnnamedAddr()) { ++ // 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. ++ if (G->hasGlobalUnnamedAddr() && !Used.contains(G)) { + // G might have been a key in our GlobalNumberState, and it's illegal + // to replace a key in ValueMap with a non-global. + GlobalNumbers.erase(G); +diff --git a/llvm/test/Transforms/MergeFunc/merge-used.ll b/llvm/test/Transforms/MergeFunc/merge-used.ll +new file mode 100644 +index 000000000000..a86e66eee3f9 +--- /dev/null ++++ b/llvm/test/Transforms/MergeFunc/merge-used.ll +@@ -0,0 +1,35 @@ ++; RUN: opt -S -mergefunc < %s | FileCheck %s ++ ++@llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (i32 (i32)* @a to i8*)], section "llvm.metadata" ++ ++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 ++} ++ ++define i32 @c(i32 %a) unnamed_addr { ++ %b = tail call i32 @a(i32 %a) ++ ret i32 %b ++} ++ ++; CHECK-LABEL: @llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (i32 (i32)* @a to i8*)], section "llvm.metadata" ++ ++; CHECK-LABEL: define i32 @b(i32 %a) unnamed_addr ++; CHECK-NEXT: xor ++; CHECK-NEXT: xor ++; CHECK-NEXT: ret ++ ++; CHECK-LABEL: define i32 @c(i32 %a) unnamed_addr ++; CHECK-NEXT: tail call i32 @b(i32 %a) ++; CHECK-NEXT: ret ++ ++; CHECK-LABEL: define internal i32 @a(i32 %0) unnamed_addr ++; CHECK-NEXT: tail call i32 @b(i32 %0) ++; CHECK-NEXT: ret +-- +2.37.0 (Apple Git-136) + diff --git a/llvm14.changes b/llvm14.changes index be91f20..0ff1f73 100644 --- a/llvm14.changes +++ b/llvm14.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Tue Sep 27 03:23:10 UTC 2022 - William Brown + +- Add llvm-preserve-symbols-used.patch to resolve some symbols preserving + with asm in Rust. + ------------------------------------------------------------------- Wed Sep 21 21:21:19 UTC 2022 - Aaron Puchert diff --git a/llvm14.spec b/llvm14.spec index e105188..349fed7 100644 --- a/llvm14.spec +++ b/llvm14.spec @@ -377,6 +377,8 @@ Patch34: clang-repl-private-deps.patch Patch35: llvm-glibc-2-36.patch # Let test match for linux instead of -linux-. Patch36: clang-test-xfail-gnuless-triple.patch +# Cherry pick from rust llvm project (https://reviews.llvm.org/D127751) +Patch37: llvm-preserve-symbols-used.patch BuildRequires: binutils-devel >= 2.21.90 BuildRequires: cmake >= 3.13.4 BuildRequires: fdupes @@ -806,6 +808,7 @@ This package contains the development files for Polly. %patch25 -p2 %patch27 -p2 %patch33 -p2 +%patch37 -p2 pushd clang-%{_version}.src %patch2 -p1