Skip to content

Commit 5a2fe9c

Browse files
authored
[SYCL] Emit an aliased function only if it is used (#2430)
Signed-off-by: Premanand M Rao <premanand.m.rao@intel.com>
1 parent e53aa20 commit 5a2fe9c

File tree

3 files changed

+107
-8
lines changed

3 files changed

+107
-8
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2264,6 +2264,30 @@ void CodeGenModule::EmitDeferred() {
22642264
CurDeclsToEmit.swap(DeferredDeclsToEmit);
22652265

22662266
for (GlobalDecl &D : CurDeclsToEmit) {
2267+
const ValueDecl *VD = cast<ValueDecl>(D.getDecl());
2268+
// If emitting for SYCL device, emit the deferred alias
2269+
// as well as what it aliases.
2270+
if (LangOpts.SYCLIsDevice) {
2271+
if (AliasAttr *Attr = VD->getAttr<AliasAttr>()) {
2272+
StringRef AliaseeName = Attr->getAliasee();
2273+
auto DDI = DeferredDecls.find(AliaseeName);
2274+
// Emit what is aliased first.
2275+
if (DDI != DeferredDecls.end()) {
2276+
llvm::GlobalValue *AliaseeGV = dyn_cast<llvm::GlobalValue>(
2277+
GetAddrOfGlobal(DDI->second, ForDefinition));
2278+
if (!AliaseeGV)
2279+
AliaseeGV = GetGlobalValue(getMangledName(DDI->second));
2280+
assert(AliaseeGV);
2281+
EmitGlobalDefinition(DDI->second, AliaseeGV);
2282+
// Remove the entry just added to the DeferredDeclsToEmit
2283+
// since we have emitted it.
2284+
DeferredDeclsToEmit.pop_back();
2285+
}
2286+
// Now emit the alias itself.
2287+
EmitAliasDefinition(D);
2288+
continue;
2289+
}
2290+
}
22672291
// We should call GetAddrOfGlobal with IsForDefinition set to true in order
22682292
// to get GlobalValue with exactly the type we need, not something that
22692293
// might had been created for another decl with the same mangled name but
@@ -2296,6 +2320,20 @@ void CodeGenModule::EmitDeferred() {
22962320
// Otherwise, emit the definition and move on to the next one.
22972321
EmitGlobalDefinition(D, GV);
22982322

2323+
if (LangOpts.SYCLIsDevice) {
2324+
// If there are any aliases deferred for this, emit those now.
2325+
for (auto It = DeferredAliases.begin(); It != DeferredAliases.end();
2326+
/*no increment*/) {
2327+
const ValueDecl *Global = cast<ValueDecl>(It->second.getDecl());
2328+
if (It->first == getMangledName(D)) {
2329+
EmitAliasDefinition(Global);
2330+
It = DeferredAliases.erase(It);
2331+
} else {
2332+
++It;
2333+
}
2334+
}
2335+
}
2336+
22992337
// If we found out that we need to emit more decls, do that recursively.
23002338
// This has the advantage that the decls are emitted in a DFS and related
23012339
// ones are close together, which is convenient for testing.
@@ -2619,9 +2657,19 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
26192657
return;
26202658

26212659
// If this is an alias definition (which otherwise looks like a declaration)
2622-
// emit it now.
2623-
if (Global->hasAttr<AliasAttr>())
2624-
return EmitAliasDefinition(GD);
2660+
// handle it now.
2661+
if (AliasAttr *Attr = Global->getAttr<AliasAttr>()) {
2662+
// Emit the alias here if it is not SYCL device compilation.
2663+
if (!LangOpts.SYCLIsDevice)
2664+
return EmitAliasDefinition(GD);
2665+
// Defer for SYCL devices, until either the alias or what it aliases
2666+
// is used.
2667+
StringRef MangledName = getMangledName(GD);
2668+
DeferredDecls[MangledName] = GD;
2669+
StringRef AliaseeName = Attr->getAliasee();
2670+
DeferredAliases[AliaseeName] = GD;
2671+
return;
2672+
}
26252673

26262674
// IFunc like an alias whose value is resolved at runtime by calling resolver.
26272675
if (Global->hasAttr<IFuncAttr>())
@@ -4836,20 +4884,21 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
48364884
// if a deferred decl.
48374885
llvm::Constant *Aliasee;
48384886
llvm::GlobalValue::LinkageTypes LT;
4887+
unsigned AS;
48394888
if (isa<llvm::FunctionType>(DeclTy)) {
48404889
Aliasee = GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, GD,
48414890
/*ForVTable=*/false);
48424891
LT = getFunctionLinkage(GD);
4892+
AS = Aliasee->getType()->getPointerAddressSpace();
48434893
} else {
4844-
Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(),
4845-
llvm::PointerType::getUnqual(DeclTy),
4894+
AS = ArgInfoAddressSpace(GetGlobalVarAddressSpace(/*D=*/nullptr));
4895+
Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(), DeclTy->getPointerTo(AS),
48464896
/*D=*/nullptr);
48474897
LT = getLLVMLinkageVarDefinition(cast<VarDecl>(GD.getDecl()),
48484898
D->getType().isConstQualified());
48494899
}
48504900

48514901
// Create the new alias itself, but don't set a name yet.
4852-
unsigned AS = Aliasee->getType()->getPointerAddressSpace();
48534902
auto *GA =
48544903
llvm::GlobalAlias::create(DeclTy, AS, LT, "", Aliasee, &getModule());
48554904

@@ -4870,8 +4919,8 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
48704919
// Remove it and replace uses of it with the alias.
48714920
GA->takeName(Entry);
48724921

4873-
Entry->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GA,
4874-
Entry->getType()));
4922+
Entry->replaceAllUsesWith(
4923+
llvm::ConstantExpr::getBitCast(GA, Entry->getType()));
48754924
Entry->eraseFromParent();
48764925
} else {
48774926
GA->setName(MangledName);

clang/lib/CodeGen/CodeGenModule.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,11 @@ class CodeGenModule : public CodeGenTypeCache {
345345
/// yet.
346346
std::map<StringRef, GlobalDecl> DeferredDecls;
347347

348+
/// This contains all the aliases that are deferred for emission until
349+
/// they or what they alias are actually used. Note that the StringRef
350+
/// associated in this map is that of the aliasee.
351+
std::map<StringRef, GlobalDecl> DeferredAliases;
352+
348353
/// This is a list of deferred decls which we have seen that *are* actually
349354
/// referenced. These get code generated when the module is done.
350355
std::vector<GlobalDecl> DeferredDeclsToEmit;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %clang_cc1 -fsycl -fsycl-is-device -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
2+
// Test that aliasing does not force an unused entity to be emitted
3+
4+
// CHECK-NOT: define spir_func void @unused_func()
5+
extern "C" void unused_func() {}
6+
// CHECK-NOT: @unused_aliaser
7+
extern "C" void unused_aliaser() __attribute__((alias("unused_func")));
8+
// CHECK-NOT: @unused_int
9+
int unused_int = 3;
10+
// CHECK-NOT: @alias_unused_int
11+
extern int alias_unused_int __attribute__((alias("unused_int")));
12+
13+
// CHECK-DAG: define spir_func void @used_func()
14+
extern "C" void used_func() {}
15+
// CHECK-DAG: @aliaser = alias void (), void ()* @used_func
16+
extern "C" void aliaser() __attribute__((alias("used_func")));
17+
18+
// CHECK-DAG: define spir_func void @func()
19+
extern "C" void func() {}
20+
// CHECK-DAG: @used_aliaser = alias void (), void ()* @func
21+
extern "C" void used_aliaser() __attribute__((alias("func")));
22+
23+
// CHECK-DAG: @used_int = addrspace(1) constant i32 5, align 4
24+
extern "C" const int used_int = 5;
25+
// CHECK-DAG: @alias_used_int = alias i32, i32 addrspace(1)* @used_int
26+
extern "C" const int alias_used_int __attribute__((alias("used_int")));
27+
// CHECK-DAG: @vint = addrspace(1) constant i32 7, align 4
28+
extern "C" const int vint = 7;
29+
// CHECK-DAG: @used_alias_used_int = alias i32, i32 addrspace(1)* @vint
30+
extern "C" const int used_alias_used_int __attribute__((alias("vint")));
31+
32+
// CHECK-DAG: define spir_func void @{{.*}}bar{{.*}}
33+
void bar(const int &i) {}
34+
35+
// CHECK-DAG: define spir_func void @{{.*}}foo{{.*}}
36+
void __attribute__((sycl_device)) foo() {
37+
// CHECK-DAG: call spir_func void @{{.*}}bar{{.*}}@used_int
38+
bar(used_int);
39+
// CHECK-DAG: call spir_func void @{{.*}}bar{{.*}}@used_alias_used_int
40+
bar(used_alias_used_int);
41+
// CHECK-DAG: call spir_func void @used_func()
42+
used_func();
43+
// CHECK-DAG: call spir_func void @used_aliaser()
44+
used_aliaser();
45+
}

0 commit comments

Comments
 (0)