Skip to content

[clang][CodeGen] Handle template parameter objects with explicit address spaces #69266

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Nov 29, 2023

Conversation

AlexVlx
Copy link
Contributor

@AlexVlx AlexVlx commented Oct 16, 2023

For certain cases (e.g. when their address is observable at run time) it is necessary to provide physical backing for non-type template parameter objects. Said backing comes in the form of a global variable. For certain targets (e.g. AMDGPU), which use a non-default address space for globals, this can lead to an issue when referencing said global in address space agnostic languages (such as HIP), for example when passing them to a function.

This patch addresses this issue by inserting an address space cast iff there is an address space mismatch between the type of a reference expression and the address space of the backing global. A test is also added.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen IR generation bugs: mangling, exceptions, etc. labels Oct 16, 2023
@AlexVlx AlexVlx removed the clang Clang issues not falling into any other category label Oct 16, 2023
@AlexVlx AlexVlx changed the title Handle template parameter objects with explicit address spaces [clang][CodeGen] Handle template parameter objects with explicit address spaces Oct 16, 2023
@llvmbot
Copy link
Member

llvmbot commented Oct 16, 2023

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-codegen

Author: Alex Voicu (AlexVlx)

Changes

For certain cases (e.g. when their address is observable at run time) it is necessary to provide physical backing for non-type template parameter objects. Said backing comes in the form of a global variable. For certain targets (e.g. AMDGPU), which use a non-default address space for globals, this can lead to an issue when referencing said global in address space agnostic languages (such as HIP), for example when passing them to a function.

This patch addresses this issue by inserting an address space cast iff there is an address space mismatch between the type of a reference expression and the address space of the backing global. A test is also added.


Full diff: https://github.com/llvm/llvm-project/pull/69266.diff

2 Files Affected:

  • (modified) clang/lib/CodeGen/CGExpr.cpp (+15-3)
  • (added) clang/test/CodeGenCXX/template-param-objects-address-space.cpp (+32)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 54a1d300a9ac738..784d3f7b03909e3 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -2992,9 +2992,21 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
     return MakeAddrLValue(CGM.GetAddrOfMSGuidDecl(GD), T,
                           AlignmentSource::Decl);
 
-  if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND))
-    return MakeAddrLValue(CGM.GetAddrOfTemplateParamObject(TPO), T,
-                          AlignmentSource::Decl);
+  if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) {
+    auto ATPO = CGM.GetAddrOfTemplateParamObject(TPO);
+    auto AS = getLangASFromTargetAS(ATPO.getAddressSpace());
+
+    if (AS != T.getAddressSpace()) {
+      auto TargetAS = getContext().getTargetAddressSpace(T.getAddressSpace());
+      auto PtrTy = ATPO.getElementType()->getPointerTo(TargetAS);
+      auto ASC = getTargetHooks().performAddrSpaceCast(CGM, ATPO.getPointer(),
+                                                       AS, T.getAddressSpace(),
+                                                       PtrTy);
+      ATPO = ConstantAddress(ASC, ATPO.getElementType(), ATPO.getAlignment());
+    }
+
+    return MakeAddrLValue(ATPO, T, AlignmentSource::Decl);
+  }
 
   llvm_unreachable("Unhandled DeclRefExpr");
 }
diff --git a/clang/test/CodeGenCXX/template-param-objects-address-space.cpp b/clang/test/CodeGenCXX/template-param-objects-address-space.cpp
new file mode 100644
index 000000000000000..b54dcfe77934ee2
--- /dev/null
+++ b/clang/test/CodeGenCXX/template-param-objects-address-space.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -std=c++20 %s -emit-llvm -o - | FileCheck %s
+
+struct S { char buf[32]; };
+template<S s> constexpr const char *begin() { return s.buf; }
+template<S s> constexpr const char *end() { return s.buf + __builtin_strlen(s.buf); }
+template<S s> constexpr const void *retval() { return &s; }
+extern const void *callee(const S*);
+template<S s> constexpr const void* observable_addr() { return callee(&s); }
+
+// CHECK: [[HELLO:@_ZTAXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEE]]
+// CHECK-SAME: = linkonce_odr addrspace(1) constant { <{ [11 x i8], [21 x i8] }> } { <{ [11 x i8], [21 x i8] }> <{ [11 x i8] c"hello world", [21 x i8] zeroinitializer }> }, comdat
+
+// CHECK: @p
+// CHECK-SAME: addrspace(1) global ptr addrspacecast (ptr addrspace(1) [[HELLO]] to ptr)
+const char *p = begin<S{"hello world"}>();
+
+// CHECK: @q
+// CHECK-SAME: addrspace(1) global ptr addrspacecast (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) [[HELLO]], i64 11) to ptr)
+const char *q = end<S{"hello world"}>();
+
+const void *(*r)() = &retval<S{"hello world"}>;
+
+// CHECK: @s
+// CHECK-SAME: addrspace(1) global ptr null
+const void *s = observable_addr<S{"hello world"}>();
+
+// CHECK: define linkonce_odr noundef ptr @_Z6retvalIXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEEEPKvv()
+// CHECK: ret ptr addrspacecast (ptr addrspace(1) [[HELLO]] to ptr)
+
+// CHECK: define linkonce_odr noundef ptr @_Z15observable_addrIXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEEEPKvv()
+// CHECK: %call = call noundef ptr @_Z6calleePK1S(ptr noundef addrspacecast (ptr addrspace(1) [[HELLO]] to ptr))
+// CHECK: declare noundef ptr @_Z6calleePK1S(ptr noundef)

@github-actions
Copy link

github-actions bot commented Oct 16, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

@llvmbot llvmbot added the clang Clang issues not falling into any other category label Oct 17, 2023
@AlexVlx
Copy link
Contributor Author

AlexVlx commented Nov 10, 2023

Gentle ping.

Copy link
Collaborator

@yxsamliu yxsamliu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks.

@AlexVlx AlexVlx merged commit 57a0416 into llvm:main Nov 29, 2023
@AlexVlx AlexVlx deleted the template_parameter_objects_as branch November 29, 2023 00:15
@efriedma-quic
Copy link
Collaborator

The concept makes sense, but I think the code should be inside CodeGenModule::GetAddrOfTemplateParamObject? I think all users of the function want a value in the correct address-space.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen IR generation bugs: mangling, exceptions, etc. clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants