[IR] Allow available_externally GlobalAlias

GlobalVariable and Function can be available_externally. GlobalAlias is used
similarly. Allowing available_externally is a natural extension and helps
ThinLTO discard GlobalAlias in a non-prevailing COMDAT (see D135427).

For now, available_externally GlobalAlias must point to an
available_externally GlobalValue (not ConstantExpr).

Differential Revision: https://reviews.llvm.org/D137441
This commit is contained in:
Fangrui Song 2022-11-07 09:03:23 -08:00
parent ec224e3b68
commit 90ad3e3c02
4 changed files with 34 additions and 10 deletions

View File

@ -886,8 +886,9 @@ Syntax::
[, partition "name"]
The linkage must be one of ``private``, ``internal``, ``linkonce``, ``weak``,
``linkonce_odr``, ``weak_odr``, ``external``. Note that some system linkers
might not correctly handle dropping a weak symbol that is aliased.
``linkonce_odr``, ``weak_odr``, ``external``, ``available_externally``. Note
that some system linkers might not correctly handle dropping a weak symbol that
is aliased.
Aliases that are not ``unnamed_addr`` are guaranteed to have the same address as
the aliasee expression. ``unnamed_addr`` ones are only guaranteed to point
@ -906,8 +907,10 @@ some can only be checked when producing an object file:
intermediate alias being overridden cannot be represented in an
object file.
* No global value in the expression can be a declaration, since that
would require a relocation, which is not possible.
* If the alias has the ``available_externally`` linkage, the aliasee must be an
``available_externally`` global value; otherwise the aliasee can be an
expression but no global value in the expression can be a declaration, since
that would require a relocation, which is not possible.
* If either the alias or the aliasee may be replaced by a symbol outside the
module at link time or runtime, any optimization cannot replace the alias with

View File

@ -93,8 +93,8 @@ public:
}
static bool isValidLinkage(LinkageTypes L) {
return isExternalLinkage(L) || isLocalLinkage(L) ||
isWeakLinkage(L) || isLinkOnceLinkage(L);
return isExternalLinkage(L) || isLocalLinkage(L) || isWeakLinkage(L) ||
isLinkOnceLinkage(L) || isAvailableExternallyLinkage(L);
}
// Methods for support type inquiry through isa, cast, and dyn_cast:

View File

@ -817,9 +817,18 @@ void Verifier::visitAliaseeSubExpr(const GlobalAlias &GA, const Constant &C) {
void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias*> &Visited,
const GlobalAlias &GA, const Constant &C) {
if (const auto *GV = dyn_cast<GlobalValue>(&C)) {
Check(!GV->isDeclarationForLinker(), "Alias must point to a definition",
if (GA.hasAvailableExternallyLinkage()) {
Check(isa<GlobalValue>(C) &&
cast<GlobalValue>(C).hasAvailableExternallyLinkage(),
"available_externally alias must point to available_externally "
"global value",
&GA);
}
if (const auto *GV = dyn_cast<GlobalValue>(&C)) {
if (!GA.hasAvailableExternallyLinkage()) {
Check(!GV->isDeclarationForLinker(), "Alias must point to a definition",
&GA);
}
if (const auto *GA2 = dyn_cast<GlobalAlias>(GV)) {
Check(Visited.insert(GA2).second, "Aliases cannot form a cycle", &GA);
@ -848,7 +857,7 @@ void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias*> &Visited,
void Verifier::visitGlobalAlias(const GlobalAlias &GA) {
Check(GlobalAlias::isValidLinkage(GA.getLinkage()),
"Alias should have private, internal, linkonce, weak, linkonce_odr, "
"weak_odr, or external linkage!",
"weak_odr, external, or available_externally linkage!",
&GA);
const Constant *Aliasee = GA.getAliasee();
Check(Aliasee, "Aliasee cannot be NULL!", &GA);

View File

@ -1,4 +1,4 @@
; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s --implicit-check-not=alias --implicit-check-not=Alias
declare void @f()
@ -31,3 +31,15 @@ define available_externally void @f2() {
@test3_c = alias i32, i32* @test3_b
; CHECK: Alias cannot point to an interposable alias
; CHECK-NEXT: i32* @test3_c
@test4_a = available_externally global i32 42
@test4_b = available_externally alias i32, i32* @test4_a
@test4_c = available_externally alias void(), void()* @f2
@test4_d = available_externally alias i32, i32* @test4_b
@test4_e = available_externally alias i32, i32* @test3_a
@test4_f = available_externally alias i32, inttoptr (i64 sub (i64 ptrtoint (i32* @test4_a to i64), i64 ptrtoint (i32* @test4_a to i64)) to i32*)
; CHECK: available_externally alias must point to available_externally global value
; CHECK-NEXT: i32* @test4_e
; CHECK: available_externally alias must point to available_externally global value
; CHECK-NEXT: i32* @test4_f