Skip to content

Commit 05442e2

Browse files
Andrew Savonichevbader
authored andcommitted
[SYCL] Insert implicit addrspacecast when casting between different AS
When default address space values in C++ are CodeGen'ed into different address spaces in LLVM IR, we must ensure that an addrspacecast is emitted before a bitcast. Signed-off-by: Andrew Savonichev <andrew.savonichev@intel.com>
1 parent f82eaab commit 05442e2

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1987,10 +1987,24 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
19871987
Value *Src = Visit(const_cast<Expr*>(E));
19881988
llvm::Type *SrcTy = Src->getType();
19891989
llvm::Type *DstTy = ConvertType(DestTy);
1990+
bool NeedAddrspaceCast = false;
19901991
if (SrcTy->isPtrOrPtrVectorTy() && DstTy->isPtrOrPtrVectorTy() &&
19911992
SrcTy->getPointerAddressSpace() != DstTy->getPointerAddressSpace()) {
1992-
llvm_unreachable("wrong cast for pointers in different address spaces"
1993-
"(must be an address space cast)!");
1993+
// If we have the same address space in AST, which is then codegen'ed to
1994+
// different address spaces in IR, then an address space cast should be
1995+
// valid.
1996+
//
1997+
// This is the case for SYCL, where both types have Default address space
1998+
// in AST, but in IR one of them may be in opencl_private, and another in
1999+
// opencl_generic address space:
2000+
//
2001+
// int arr[5]; // automatic variable, default AS in AST, private AS in
2002+
// IR char* p = arr; // default AS in AST, generic AS in IR
2003+
//
2004+
if (E->getType().getAddressSpace() != DestTy.getAddressSpace())
2005+
llvm_unreachable("wrong cast for pointers in different address spaces"
2006+
"(must be an address space cast)!");
2007+
NeedAddrspaceCast = true;
19942008
}
19952009

19962010
if (CGF.SanOpts.has(SanitizerKind::CFIUnrelatedCast)) {
@@ -2025,6 +2039,13 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
20252039
CGF.getDebugInfo()->
20262040
addHeapAllocSiteMetadata(CI, CE->getType(), CE->getExprLoc());
20272041

2042+
if (NeedAddrspaceCast) {
2043+
llvm::Type *SrcPointeeTy = Src->getType()->getPointerElementType();
2044+
llvm::Type *SrcNewAS = llvm::PointerType::get(
2045+
SrcPointeeTy, cast<llvm::PointerType>(DstTy)->getAddressSpace());
2046+
2047+
Src = Builder.CreateAddrSpaceCast(Src, SrcNewAS);
2048+
}
20282049
return Builder.CreateBitCast(Src, DstTy);
20292050
}
20302051
case CK_AddressSpaceConversion: {

clang/test/CodeGenSYCL/address-space-new.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,36 @@ void test() {
77
// CHECK-NEW: @_ZZ4testvE3foo = internal addrspace(1) constant i32 66, align 4
88

99
// CHECK: @[[STR:[.a-zA-Z0-9_]+]] = private unnamed_addr constant [14 x i8] c"Hello, world!\00", align 1
10+
11+
// CHECK: %[[ARR:[a-zA-Z0-9]+]] = alloca [42 x i32]
12+
1013
int i = 0;
1114
int *pptr = &i;
1215
// CHECK-LEGACY: store i32* %i, i32** %pptr
1316
// CHECK-NEW: %[[GEN:[0-9]+]] = addrspacecast i32* %i to i32 addrspace(4)*
1417
// CHECK-NEW: store i32 addrspace(4)* %[[GEN]], i32 addrspace(4)** %pptr
1518
*pptr = foo;
1619

20+
int var23 = 23;
21+
char *cp = (char *)&var23;
22+
*cp = 41;
23+
// CHECK: store i32 23, i32* %[[VAR:[a-zA-Z0-9]+]]
24+
// CHECK-OLD: [[VARCAST:[a-zA-Z0-9]+]] = bitcast i32* %[[VAR]] to i8*
25+
// CHECK-OLD: store i8* %[[VARCAST]], i8** %{{.*}}
26+
// CHECK-NEW: [[VARAS:[a-zA-Z0-9]+]] = addrspacecast i32* %[[VAR]] to i32 addrspace(4)*
27+
// CHECK-NEW: [[VARCAST:[a-zA-Z0-9]+]] = bitcast i32 addrspace(4)* %[[VARAS]] to i8 addrspace(4)*
28+
// CHECK-NEW: store i8 addrspace(4)* %[[VARCAST]], i8 addrspace(4)** %{{.*}}
29+
30+
int arr[42];
31+
char *cpp = (char *)arr;
32+
*cpp = 43;
33+
// CHECK: %[[ARRDECAY:[a-zA-Z0-9]+]] = getelementptr inbounds [42 x i32], [42 x i32]* %[[ARR]], i64 0, i64 0
34+
// CHECK-OLD: [[ARRCAST:[a-zA-Z0-9]+]] = bitcast i32* %[[ARRDECAY]] to i8*
35+
// CHECK-OLD: store i8* %[[ARRCAST]], i8** %{{.*}}
36+
// CHECK-NEW: %[[ARRAS:[a-zA-Z0-9]+]] = addrspacecast i32* %[[ARRDECAY]] to i32 addrspace(4)*
37+
// CHECK-NEW: %[[ARRCAST:[a-zA-Z0-9]+]] = bitcast i32 addrspace(4)* %[[ARRAS]] to i8 addrspace(4)*
38+
// CHECK-NEW: store i8 addrspace(4)* %[[ARRCAST]], i8 addrspace(4)** %{{.*}}
39+
1740
const char *str = "Hello, world!";
1841
// CHECK-LEGACY: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @[[STR]], i64 0, i64 0), i8** %{{.*}}, align 8
1942
// CHECK-NEW: store i8 addrspace(4)* addrspacecast (i8* getelementptr inbounds ([14 x i8], [14 x i8]* @[[STR]], i64 0, i64 0) to i8 addrspace(4)*), i8 addrspace(4)** %{{.*}}, align 8

0 commit comments

Comments
 (0)