Skip to content

Commit a768399

Browse files
committed
[SYCL] Implement SYCL address space attributes handling
Default address space (applies when no explicit address space was specified) maps to generic (4) address space. Added SYCLDevice env to triple. Static variables without address space now reside in global address space, unless they have an explicit address space qualifier in source code. Although OpenCL specification explicitly states that a string literal should reside in constant address space, it does not work for SYCL with "generic by default" address space rules. For example: const char *getLiteral() { return "A"; } void func(bool AorB) { char B[] = {'B', '\0'}; const char* C = AorB ? A : B; } If `A' reside in constant address space, it cannot be returned from a function `getLiteral', because it returns a generic const char*. 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. Pointers with the same address space in AST may end up in different address spaces in IR. We cannot CodeGen a conditional operator (ternary 'if') whose operands have different address spaces, so we have to addrspacecast them to generic. When a static variable is lowered from AST to LLVM IR, it can change an address space depending on its storage class. For example, a static variable declared in function scope may be assigned to global address space if language rules allow. When this happens, original address space of a variable (retuned by D.getType()) is no longer can be used as target address space. Correct address space for a global can be obtained from CodeGenModule::GetGlobalVarAddressSpace function, but in this case we just copy it from the existing global (OldGV). Pointers with the same address space in AST may end up in different address spaces in IR. We cannot CodeGen a binary compare operator (<, >, ==, etc.) whose operands have different address spaces, so we have to addrspacecast them to generic. Emit address space cast if return type and return value have different address spaces. Invalid bitcast with different address spaces was emitted as arument of llvm.invariant.start intrinsic for work group scope constants. This problem caused assertion fail. Make sure that all operands of phi instruction that is generated while lowering conditional operator have the same type. This fixes compiler assertion. Signed-off-by: Alexey Bader <[email protected]>
1 parent 04329db commit a768399

29 files changed

+750
-34
lines changed

clang/include/clang/AST/Type.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,13 @@ class Qualifiers {
486486
/// Returns true if the address space in these qualifiers is equal to or
487487
/// a superset of the address space in the argument qualifiers.
488488
bool isAddressSpaceSupersetOf(Qualifiers other) const {
489-
return isAddressSpaceSupersetOf(getAddressSpace(), other.getAddressSpace());
489+
return isAddressSpaceSupersetOf(getAddressSpace(),
490+
other.getAddressSpace()) ||
491+
(!hasAddressSpace() &&
492+
(other.getAddressSpace() == LangAS::sycl_private ||
493+
other.getAddressSpace() == LangAS::sycl_local ||
494+
other.getAddressSpace() == LangAS::sycl_global ||
495+
other.getAddressSpace() == LangAS::sycl_constant));
490496
}
491497

492498
/// Determines if these qualifiers compatibly include another set.

clang/include/clang/Basic/AddressSpaces.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ enum class LangAS : unsigned {
4242
cuda_constant,
4343
cuda_shared,
4444

45+
// SYCL specific address spaces.
46+
sycl_global,
47+
sycl_local,
48+
sycl_constant,
49+
sycl_private,
50+
4551
// Pointer size and extension address spaces.
4652
ptr32_sptr,
4753
ptr32_uptr,

clang/include/clang/Sema/ParsedAttr.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,24 @@ class ParsedAttr final
534534
}
535535
}
536536

537+
/// If this is an OpenCL addr space attribute returns its SYCL representation
538+
/// in LangAS, otherwise returns default addr space.
539+
LangAS asSYCLLangAS() const {
540+
switch (getKind()) {
541+
case ParsedAttr::AT_OpenCLConstantAddressSpace:
542+
return LangAS::sycl_constant;
543+
case ParsedAttr::AT_OpenCLGlobalAddressSpace:
544+
return LangAS::sycl_global;
545+
case ParsedAttr::AT_OpenCLLocalAddressSpace:
546+
return LangAS::sycl_local;
547+
case ParsedAttr::AT_OpenCLPrivateAddressSpace:
548+
return LangAS::sycl_private;
549+
case ParsedAttr::AT_OpenCLGenericAddressSpace:
550+
default:
551+
return LangAS::Default;
552+
}
553+
}
554+
537555
AttributeCommonInfo::Kind getKind() const { return getParsedKind(); }
538556
};
539557

clang/lib/AST/ASTContext.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,10 @@ static const LangASMap *getAddressSpaceMap(const TargetInfo &T,
836836
5, // cuda_device
837837
6, // cuda_constant
838838
7, // cuda_shared
839+
1, // sycl_global
840+
3, // sycl_local
841+
2, // sycl_constant
842+
0, // sycl_private
839843
8, // ptr32_sptr
840844
9, // ptr32_uptr
841845
10 // ptr64

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2285,7 +2285,7 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals, const DependentAddressSp
22852285
if (Context.getASTContext().addressSpaceMapManglingFor(AS)) {
22862286
// <target-addrspace> ::= "AS" <address-space-number>
22872287
unsigned TargetAS = Context.getASTContext().getTargetAddressSpace(AS);
2288-
if (TargetAS != 0)
2288+
if (TargetAS != 0 || (Context.getASTContext().getLangOpts().SYCLIsDevice))
22892289
ASString = "AS" + llvm::utostr(TargetAS);
22902290
} else {
22912291
switch (AS) {

clang/lib/AST/TypePrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1777,12 +1777,16 @@ std::string Qualifiers::getAddrSpaceAsString(LangAS AS) {
17771777
case LangAS::Default:
17781778
return "";
17791779
case LangAS::opencl_global:
1780+
case LangAS::sycl_global:
17801781
return "__global";
17811782
case LangAS::opencl_local:
1783+
case LangAS::sycl_local:
17821784
return "__local";
17831785
case LangAS::opencl_private:
1786+
case LangAS::sycl_private:
17841787
return "";
17851788
case LangAS::opencl_constant:
1789+
case LangAS::sycl_constant:
17861790
return "__constant";
17871791
case LangAS::opencl_generic:
17881792
return "__generic";

clang/lib/Basic/Targets.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -562,17 +562,29 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple,
562562
}
563563

564564
case llvm::Triple::spir: {
565-
if (Triple.getOS() != llvm::Triple::UnknownOS ||
566-
Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
567-
return nullptr;
565+
if (Triple.getEnvironment() == llvm::Triple::SYCLDevice) {
566+
switch (os) {
567+
case llvm::Triple::Linux:
568+
return new LinuxTargetInfo<SPIR32SYCLDeviceTargetInfo>(Triple, Opts);
569+
default:
570+
return new SPIR32SYCLDeviceTargetInfo(Triple, Opts);
571+
}
572+
}
568573
return new SPIR32TargetInfo(Triple, Opts);
569574
}
575+
570576
case llvm::Triple::spir64: {
571-
if (Triple.getOS() != llvm::Triple::UnknownOS ||
572-
Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
573-
return nullptr;
577+
if (Triple.getEnvironment() == llvm::Triple::SYCLDevice) {
578+
switch (os) {
579+
case llvm::Triple::Linux:
580+
return new LinuxTargetInfo<SPIR64SYCLDeviceTargetInfo>(Triple, Opts);
581+
default:
582+
return new SPIR64SYCLDeviceTargetInfo(Triple, Opts);
583+
}
584+
}
574585
return new SPIR64TargetInfo(Triple, Opts);
575586
}
587+
576588
case llvm::Triple::wasm32:
577589
if (Triple.getSubArch() != llvm::Triple::NoSubArch ||
578590
Triple.getVendor() != llvm::Triple::UnknownVendor ||

clang/lib/Basic/Targets/AMDGPU.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsGenMap = {
4848
Global, // cuda_device
4949
Constant, // cuda_constant
5050
Local, // cuda_shared
51+
Global, // sycl_global
52+
Local, // sycl_local
53+
Constant, // sycl_constant
54+
Private, // sycl_private
5155
Generic, // ptr32_sptr
5256
Generic, // ptr32_uptr
5357
Generic // ptr64
@@ -63,6 +67,10 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = {
6367
Global, // cuda_device
6468
Constant, // cuda_constant
6569
Local, // cuda_shared
70+
Global, // sycl_global
71+
Local, // sycl_local
72+
Constant, // sycl_constant
73+
Private, // sycl_private
6674
Generic, // ptr32_sptr
6775
Generic, // ptr32_uptr
6876
Generic // ptr64

clang/lib/Basic/Targets/NVPTX.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ static const unsigned NVPTXAddrSpaceMap[] = {
3333
1, // cuda_device
3434
4, // cuda_constant
3535
3, // cuda_shared
36+
1, // sycl_global
37+
3, // sycl_local
38+
4, // sycl_constant
39+
0, // sycl_private
3640
0, // ptr32_sptr
3741
0, // ptr32_uptr
3842
0 // ptr64

clang/lib/Basic/Targets/SPIR.h

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,29 @@ static const unsigned SPIRAddrSpaceMap[] = {
3131
0, // cuda_device
3232
0, // cuda_constant
3333
0, // cuda_shared
34+
1, // sycl_global
35+
3, // sycl_local
36+
2, // sycl_constant
37+
0, // sycl_private
38+
0, // ptr32_sptr
39+
0, // ptr32_uptr
40+
0 // ptr64
41+
};
42+
43+
static const unsigned SYCLAddrSpaceMap[] = {
44+
4, // Default
45+
1, // opencl_global
46+
3, // opencl_local
47+
2, // opencl_constant
48+
0, // opencl_private
49+
4, // opencl_generic
50+
0, // cuda_device
51+
0, // cuda_constant
52+
0, // cuda_shared
53+
1, // sycl_global
54+
3, // sycl_local
55+
2, // sycl_constant
56+
0, // sycl_private
3457
0, // ptr32_sptr
3558
0, // ptr32_uptr
3659
0 // ptr64
@@ -40,14 +63,14 @@ class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public TargetInfo {
4063
public:
4164
SPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
4265
: TargetInfo(Triple) {
43-
assert(getTriple().getOS() == llvm::Triple::UnknownOS &&
44-
"SPIR target must use unknown OS");
45-
assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
46-
"SPIR target must use unknown environment type");
4766
TLSSupported = false;
4867
VLASupported = false;
4968
LongWidth = LongAlign = 64;
50-
AddrSpaceMap = &SPIRAddrSpaceMap;
69+
if (Triple.getEnvironment() == llvm::Triple::SYCLDevice) {
70+
AddrSpaceMap = &SYCLAddrSpaceMap;
71+
} else {
72+
AddrSpaceMap = &SPIRAddrSpaceMap;
73+
}
5174
UseAddrSpaceMapMangling = true;
5275
HasLegalHalfType = true;
5376
HasFloat16 = true;
@@ -130,6 +153,35 @@ class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public SPIRTargetInfo {
130153
void getTargetDefines(const LangOptions &Opts,
131154
MacroBuilder &Builder) const override;
132155
};
156+
157+
class LLVM_LIBRARY_VISIBILITY SPIR32SYCLDeviceTargetInfo
158+
: public SPIR32TargetInfo {
159+
public:
160+
SPIR32SYCLDeviceTargetInfo(const llvm::Triple &Triple,
161+
const TargetOptions &Opts)
162+
: SPIR32TargetInfo(Triple, Opts) {
163+
// This is workaround for exception_ptr class.
164+
// Exceptions is not allowed in sycl device code but we should be able
165+
// to parse host code. So we allow compilation of exception_ptr but
166+
// if exceptions are used in device code we should emit a diagnostic.
167+
MaxAtomicInlineWidth = 32;
168+
}
169+
};
170+
171+
class LLVM_LIBRARY_VISIBILITY SPIR64SYCLDeviceTargetInfo
172+
: public SPIR64TargetInfo {
173+
public:
174+
SPIR64SYCLDeviceTargetInfo(const llvm::Triple &Triple,
175+
const TargetOptions &Opts)
176+
: SPIR64TargetInfo(Triple, Opts) {
177+
// This is workaround for exception_ptr class.
178+
// Exceptions is not allowed in sycl device code but we should be able
179+
// to parse host code. So we allow compilation of exception_ptr but
180+
// if exceptions are used in device code we should emit a diagnostic.
181+
MaxAtomicInlineWidth = 64;
182+
}
183+
};
184+
133185
} // namespace targets
134186
} // namespace clang
135187
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H

clang/lib/Basic/Targets/TCE.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ static const unsigned TCEOpenCLAddrSpaceMap[] = {
4040
0, // cuda_device
4141
0, // cuda_constant
4242
0, // cuda_shared
43+
3, // sycl_global
44+
4, // sycl_local
45+
5, // sycl_constant
46+
0, // sycl_private
4347
0, // ptr32_sptr
4448
0, // ptr32_uptr
4549
0, // ptr64

clang/lib/Basic/Targets/X86.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ static const unsigned X86AddrSpaceMap[] = {
3232
0, // cuda_device
3333
0, // cuda_constant
3434
0, // cuda_shared
35+
0, // sycl_global
36+
0, // sycl_local
37+
0, // sycl_constant
38+
0, // sycl_private
3539
270, // ptr32_sptr
3640
271, // ptr32_uptr
3741
272 // ptr64

clang/lib/CodeGen/CGCall.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4100,6 +4100,17 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
41004100
V->getType()->isIntegerTy())
41014101
V = Builder.CreateZExt(V, ArgInfo.getCoerceToType());
41024102

4103+
if (FirstIRArg < IRFuncTy->getNumParams()) {
4104+
const auto *LHSPtrTy =
4105+
dyn_cast_or_null<llvm::PointerType>(V->getType());
4106+
const auto *RHSPtrTy = dyn_cast_or_null<llvm::PointerType>(
4107+
IRFuncTy->getParamType(FirstIRArg));
4108+
if (LHSPtrTy && RHSPtrTy &&
4109+
LHSPtrTy->getAddressSpace() != RHSPtrTy->getAddressSpace())
4110+
V = Builder.CreateAddrSpaceCast(V,
4111+
IRFuncTy->getParamType(FirstIRArg));
4112+
}
4113+
41034114
// If the argument doesn't match, perform a bitcast to coerce it. This
41044115
// can happen due to trivial type mismatches.
41054116
if (FirstIRArg < IRFuncTy->getNumParams() &&
@@ -4309,6 +4320,20 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
43094320
if (!CallArgs.getCleanupsToDeactivate().empty())
43104321
deactivateArgCleanupsBeforeCall(*this, CallArgs);
43114322

4323+
// Addrspace cast to generic if necessary
4324+
for (unsigned i = 0; i < IRFuncTy->getNumParams(); ++i) {
4325+
if (auto *PtrTy = dyn_cast<llvm::PointerType>(IRCallArgs[i]->getType())) {
4326+
auto *ExpectedPtrType =
4327+
cast<llvm::PointerType>(IRFuncTy->getParamType(i));
4328+
unsigned ValueAS = PtrTy->getAddressSpace();
4329+
unsigned ExpectedAS = ExpectedPtrType->getAddressSpace();
4330+
if (ValueAS != ExpectedAS) {
4331+
IRCallArgs[i] = Builder.CreatePointerBitCastOrAddrSpaceCast(
4332+
IRCallArgs[i], ExpectedPtrType);
4333+
}
4334+
}
4335+
}
4336+
43124337
// Assert that the arguments we computed match up. The IR verifier
43134338
// will catch this, but this is a common enough source of problems
43144339
// during IRGen changes that it's way better for debugging to catch

clang/lib/CodeGen/CGClass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ Address CodeGenFunction::GetAddressOfBaseClass(
319319
EmitTypeCheck(TCK_Upcast, Loc, Value.getPointer(),
320320
DerivedTy, DerivedAlign, SkippedChecks);
321321
}
322-
return Builder.CreateBitCast(Value, BasePtrTy);
322+
return Builder.CreatePointerBitCastOrAddrSpaceCast(Value, BasePtrTy);
323323
}
324324

325325
llvm::BasicBlock *origBB = nullptr;

clang/lib/CodeGen/CGDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
344344
OldGV->getLinkage(), Init, "",
345345
/*InsertBefore*/ OldGV,
346346
OldGV->getThreadLocalMode(),
347-
CGM.getContext().getTargetAddressSpace(D.getType()));
347+
OldGV->getType()->getPointerAddressSpace());
348348
GV->setVisibility(OldGV->getVisibility());
349349
GV->setDSOLocal(OldGV->isDSOLocal());
350350
GV->setComdat(OldGV->getComdat());

clang/lib/CodeGen/CGDeclCXX.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,15 @@ void CodeGenFunction::EmitInvariantStart(llvm::Constant *Addr, CharUnits Size) {
161161
// Grab the llvm.invariant.start intrinsic.
162162
llvm::Intrinsic::ID InvStartID = llvm::Intrinsic::invariant_start;
163163
// Overloaded address space type.
164-
llvm::Type *ObjectPtr[1] = {Int8PtrTy};
164+
llvm::Type *ResTy = llvm::PointerType::getInt8PtrTy(
165+
CGM.getLLVMContext(), Addr->getType()->getPointerAddressSpace());
166+
llvm::Type *ObjectPtr[1] = {ResTy};
165167
llvm::Function *InvariantStart = CGM.getIntrinsic(InvStartID, ObjectPtr);
166168

167169
// Emit a call with the size in bytes of the object.
168170
uint64_t Width = Size.getQuantity();
169-
llvm::Value *Args[2] = { llvm::ConstantInt::getSigned(Int64Ty, Width),
170-
llvm::ConstantExpr::getBitCast(Addr, Int8PtrTy)};
171+
llvm::Value *Args[2] = {llvm::ConstantInt::getSigned(Int64Ty, Width),
172+
llvm::ConstantExpr::getBitCast(Addr, ResTy)};
171173
Builder.CreateCall(InvariantStart, Args);
172174
}
173175

0 commit comments

Comments
 (0)