[llvm] [GlobalOpt] Don't resolve aliased ifuncs with declared resolvees. (PR #96220)
Alexandros Lamprineas via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 20 11:16:42 PDT 2024
https://github.com/labrinea created https://github.com/llvm/llvm-project/pull/96220
Fixes https://github.com/llvm/llvm-project/issues/96197.
A global alias should always point to a definition. Ifuncs are definitions, so far so good. However an ifunc may be statically resolved to a function that is declared but not defined in the translation unit.
With this patch we perform static resolution if:
* the resolvee is defined
* otherwise none of the ifunc users is a global alias
>From f480a0db0ad1f4036be44348c851a951b13e129b Mon Sep 17 00:00:00 2001
From: Alexandros Lamprineas <alexandros.lamprineas at arm.com>
Date: Thu, 20 Jun 2024 19:00:06 +0100
Subject: [PATCH] [GlobalOpt] Don't resolve aliased ifuncs with declared
resolvees.
Fixes https://github.com/llvm/llvm-project/issues/96197.
A global alias should always point to a definition. Ifuncs are
definitions, so far so good. However an ifunc may be statically
resolved to a function that is declared but not defined in the
translation unit.
With this patch we perform static resolution if:
* the resolvee is defined
* otherwise none of the ifunc users is a global alias
---
llvm/lib/Transforms/IPO/GlobalOpt.cpp | 4 +++-
.../GlobalOpt/resolve-static-ifunc.ll | 22 +++++++++++++++++++
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
index b7c6d25657bc0..411a8454bf18b 100644
--- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
@@ -2458,7 +2458,9 @@ static bool OptimizeStaticIFuncs(Module &M) {
bool Changed = false;
for (GlobalIFunc &IF : M.ifuncs())
if (Function *Callee = hasSideeffectFreeStaticResolution(IF))
- if (!IF.use_empty()) {
+ if (!IF.use_empty() &&
+ (!Callee->isDeclaration() ||
+ none_of(IF.users(), [](User *U) { return isa<GlobalAlias>(U); }))) {
IF.replaceAllUsesWith(Callee);
NumIFuncsResolved++;
Changed = true;
diff --git a/llvm/test/Transforms/GlobalOpt/resolve-static-ifunc.ll b/llvm/test/Transforms/GlobalOpt/resolve-static-ifunc.ll
index 2a1717304fb4c..de087343208c7 100644
--- a/llvm/test/Transforms/GlobalOpt/resolve-static-ifunc.ll
+++ b/llvm/test/Transforms/GlobalOpt/resolve-static-ifunc.ll
@@ -7,11 +7,15 @@ target triple = "aarch64-unknown-linux-gnu"
@trivial.ifunc = internal ifunc void (), ptr @trivial.resolver
;.
; CHECK: @unknown_condition = external local_unnamed_addr global i1
+; CHECK: @alias_decl = weak_odr alias void (), ptr @aliased_decl.ifunc
+; CHECK: @alias_def = weak_odr alias void (), ptr @aliased_def._Msimd
; CHECK: @external_ifunc.ifunc = dso_local ifunc void (), ptr @external_ifunc.resolver
; CHECK: @complex.ifunc = internal ifunc void (), ptr @complex.resolver
; CHECK: @sideeffects.ifunc = internal ifunc void (), ptr @sideeffects.resolver
; CHECK: @interposable_ifunc.ifunc = internal ifunc void (), ptr @interposable_ifunc.resolver
; CHECK: @interposable_resolver.ifunc = weak ifunc void (), ptr @interposable_resolver.resolver
+; CHECK: @aliased_decl.ifunc = weak_odr ifunc void (), ptr @aliased_decl.resolver
+; CHECK: @aliased_def.ifunc = weak_odr ifunc void (), ptr @aliased_def.resolver
;.
define ptr @trivial.resolver() {
ret ptr @trivial._Msimd
@@ -89,6 +93,20 @@ define void @interposable_resolver.default() {
ret void
}
+ at alias_decl = weak_odr alias void (), ptr @aliased_decl.ifunc
+ at aliased_decl.ifunc = weak_odr ifunc void (), ptr @aliased_decl.resolver
+declare void @aliased_decl._Msimd()
+define ptr @aliased_decl.resolver() {
+ ret ptr @aliased_decl._Msimd
+}
+
+ at alias_def = weak_odr alias void (), ptr @aliased_def.ifunc
+ at aliased_def.ifunc = weak_odr ifunc void (), ptr @aliased_def.resolver
+define void @aliased_def._Msimd() { ret void }
+define ptr @aliased_def.resolver() {
+ ret ptr @aliased_def._Msimd
+}
+
define void @caller() {
; CHECK-LABEL: define void @caller() local_unnamed_addr {
; CHECK-NEXT: call void @trivial._Msimd()
@@ -97,6 +115,8 @@ define void @caller() {
; CHECK-NEXT: call void @sideeffects.ifunc()
; CHECK-NEXT: call void @interposable_ifunc.ifunc()
; CHECK-NEXT: call void @interposable_resolver.ifunc()
+; CHECK-NEXT: call void @aliased_decl.ifunc()
+; CHECK-NEXT: call void @aliased_def._Msimd()
; CHECK-NEXT: ret void
;
call void @trivial.ifunc()
@@ -105,5 +125,7 @@ define void @caller() {
call void @sideeffects.ifunc()
call void @interposable_ifunc.ifunc()
call void @interposable_resolver.ifunc()
+ call void @aliased_decl.ifunc()
+ call void @aliased_def.ifunc()
ret void
}
More information about the llvm-commits
mailing list