[clang] 57a0416 - [clang][CodeGen] Handle template parameter objects with explicit address spaces (#69266)

via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 28 16:15:23 PST 2023


Author: Alex Voicu
Date: 2023-11-29T00:15:18Z
New Revision: 57a0416e0e8ccd522d4242dbe5d0d7893864a10a

URL: https://github.com/llvm/llvm-project/commit/57a0416e0e8ccd522d4242dbe5d0d7893864a10a
DIFF: https://github.com/llvm/llvm-project/commit/57a0416e0e8ccd522d4242dbe5d0d7893864a10a.diff

LOG: [clang][CodeGen] Handle template parameter objects with explicit address spaces (#69266)

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.

Added: 
    clang/test/CodeGenCXX/template-param-objects-address-space.cpp

Modified: 
    clang/lib/CodeGen/CGExpr.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index a75f630e1a4c767..9fe8f1d7da780c8 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -3038,9 +3038,20 @@ 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)


        


More information about the cfe-commits mailing list