B == LangAS::opencl_global_host)) ||
// Consider pointer size address spaces to be equivalent to default.
((isPtrSizeAddressSpace(A) || A == LangAS::Default) &&
- (isPtrSizeAddressSpace(B) || B == LangAS::Default));
+ (isPtrSizeAddressSpace(B) || B == LangAS::Default)) ||
+ // Default is a superset of SYCL address spaces.
+ (A == LangAS::Default &&
+ (B == LangAS::sycl_private || B == LangAS::sycl_local ||
+ B == LangAS::sycl_global));
}
/// Returns true if the address space in these qualifiers is equal to or
cuda_constant,
cuda_shared,
+ // SYCL specific address spaces.
+ sycl_global,
+ sycl_local,
+ sycl_private,
+
// Pointer size and extension address spaces.
ptr32_sptr,
ptr32_uptr,
/// a Spelling enumeration, the value UINT_MAX is returned.
unsigned getSemanticSpelling() const;
- /// If this is an OpenCL addr space attribute returns its representation
- /// in LangAS, otherwise returns default addr space.
+ /// If this is an OpenCL address space attribute returns its representation
+ /// in LangAS, otherwise returns default address space.
LangAS asOpenCLLangAS() const {
switch (getParsedKind()) {
case ParsedAttr::AT_OpenCLConstantAddressSpace:
}
}
+ /// If this is an OpenCL address space attribute returns its SYCL
+ /// representation in LangAS, otherwise returns default address space.
+ LangAS asSYCLLangAS() const {
+ switch (getKind()) {
+ case ParsedAttr::AT_OpenCLGlobalAddressSpace:
+ return LangAS::sycl_global;
+ case ParsedAttr::AT_OpenCLLocalAddressSpace:
+ return LangAS::sycl_local;
+ case ParsedAttr::AT_OpenCLPrivateAddressSpace:
+ return LangAS::sycl_private;
+ case ParsedAttr::AT_OpenCLGenericAddressSpace:
+ default:
+ return LangAS::Default;
+ }
+ }
+
AttributeCommonInfo::Kind getKind() const {
return AttributeCommonInfo::Kind(Info.AttrKind);
}
7, // cuda_device
8, // cuda_constant
9, // cuda_shared
+ 1, // sycl_global
+ 3, // sycl_local
+ 0, // sycl_private
10, // ptr32_sptr
11, // ptr32_uptr
12 // ptr64
if (Context.getASTContext().addressSpaceMapManglingFor(AS)) {
// <target-addrspace> ::= "AS" <address-space-number>
unsigned TargetAS = Context.getASTContext().getTargetAddressSpace(AS);
- if (TargetAS != 0)
+ if (TargetAS != 0 ||
+ Context.getASTContext().getTargetAddressSpace(LangAS::Default) != 0)
ASString = "AS" + llvm::utostr(TargetAS);
} else {
switch (AS) {
case LangAS::opencl_generic:
ASString = "CLgeneric";
break;
+ // <SYCL-addrspace> ::= "SY" [ "global" | "local" | "private" ]
+ case LangAS::sycl_global:
+ ASString = "SYglobal";
+ break;
+ case LangAS::sycl_local:
+ ASString = "SYlocal";
+ break;
+ case LangAS::sycl_private:
+ ASString = "SYprivate";
+ break;
// <CUDA-addrspace> ::= "CU" [ "device" | "constant" | "shared" ]
case LangAS::cuda_device:
ASString = "CUdevice";
case LangAS::Default:
return "";
case LangAS::opencl_global:
+ case LangAS::sycl_global:
return "__global";
case LangAS::opencl_local:
+ case LangAS::sycl_local:
return "__local";
case LangAS::opencl_private:
+ case LangAS::sycl_private:
return "__private";
case LangAS::opencl_constant:
return "__constant";
Global, // cuda_device
Constant, // cuda_constant
Local, // cuda_shared
+ Global, // sycl_global
+ Local, // sycl_local
+ Private, // sycl_private
Generic, // ptr32_sptr
Generic, // ptr32_uptr
Generic // ptr64
Global, // cuda_device
Constant, // cuda_constant
Local, // cuda_shared
+ // SYCL address space values for this map are dummy
+ Generic, // sycl_global
+ Generic, // sycl_local
+ Generic, // sycl_private
Generic, // ptr32_sptr
Generic, // ptr32_uptr
Generic // ptr64
1, // cuda_device
4, // cuda_constant
3, // cuda_shared
+ 1, // sycl_global
+ 3, // sycl_local
+ 0, // sycl_private
0, // ptr32_sptr
0, // ptr32_uptr
0 // ptr64
namespace clang {
namespace targets {
-static const unsigned SPIRAddrSpaceMap[] = {
+static const unsigned SPIRDefIsPrivMap[] = {
0, // Default
1, // opencl_global
3, // opencl_local
0, // cuda_device
0, // cuda_constant
0, // cuda_shared
+ // SYCL address space values for this map are dummy
+ 0, // sycl_global
+ 0, // sycl_local
+ 0, // sycl_private
+ 0, // ptr32_sptr
+ 0, // ptr32_uptr
+ 0 // ptr64
+};
+
+static const unsigned SPIRDefIsGenMap[] = {
+ 4, // Default
+ // OpenCL address space values for this map are dummy and they can't be used
+ 0, // opencl_global
+ 0, // opencl_local
+ 0, // opencl_constant
+ 0, // opencl_private
+ 0, // opencl_generic
+ 0, // opencl_global_device
+ 0, // opencl_global_host
+ 0, // cuda_device
+ 0, // cuda_constant
+ 0, // cuda_shared
+ 1, // sycl_global
+ 3, // sycl_local
+ 0, // sycl_private
0, // ptr32_sptr
0, // ptr32_uptr
0 // ptr64
TLSSupported = false;
VLASupported = false;
LongWidth = LongAlign = 64;
- AddrSpaceMap = &SPIRAddrSpaceMap;
+ AddrSpaceMap = &SPIRDefIsPrivMap;
UseAddrSpaceMapMangling = true;
HasLegalHalfType = true;
HasFloat16 = true;
return CC_SpirFunction;
}
+ void setAddressSpaceMap(bool DefaultIsGeneric) {
+ AddrSpaceMap = DefaultIsGeneric ? &SPIRDefIsGenMap : &SPIRDefIsPrivMap;
+ }
+
+ void adjust(LangOptions &Opts) override {
+ TargetInfo::adjust(Opts);
+ // FIXME: SYCL specification considers unannotated pointers and references
+ // to be pointing to the generic address space. See section 5.9.3 of
+ // SYCL 2020 specification.
+ // Currently, there is no way of representing SYCL's default address space
+ // language semantic along with the semantics of embedded C's default
+ // address space in the same address space map. Hence the map needs to be
+ // reset to allow mapping to the desired value of 'Default' entry for SYCL.
+ setAddressSpaceMap(/*DefaultIsGeneric=*/Opts.SYCLIsDevice);
+ }
+
void setSupportedOpenCLOpts() override {
// Assume all OpenCL extensions and optional core features are supported
// for SPIR since it is a generic target.
bool hasInt128Type() const override { return false; }
};
+
class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo {
public:
SPIR32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
0, // cuda_device
0, // cuda_constant
0, // cuda_shared
+ 3, // sycl_global
+ 4, // sycl_local
+ 0, // sycl_private
0, // ptr32_sptr
0, // ptr32_uptr
0, // ptr64
0, // cuda_device
0, // cuda_constant
0, // cuda_shared
+ 0, // sycl_global
+ 0, // sycl_local
+ 0, // sycl_private
270, // ptr32_sptr
271, // ptr32_uptr
272 // ptr64
bool isConstant = true;
llvm::GlobalVariable *InsertBefore = nullptr;
unsigned AS =
- getContext().getTargetAddressSpace(getStringLiteralAddressSpace());
+ getContext().getTargetAddressSpace(GetGlobalConstantAddressSpace());
std::string Name;
if (D.hasGlobalStorage())
Name = getMangledName(&D).str() + ".const";
(Ty->isArrayType() || Ty->isRecordType()) &&
CGF.CGM.isTypeConstant(Ty, true))
if (auto Init = ConstantEmitter(CGF).tryEmitAbstract(Inner, Ty)) {
- if (auto AddrSpace = CGF.getTarget().getConstantAddressSpace()) {
- auto AS = AddrSpace.getValue();
- auto *GV = new llvm::GlobalVariable(
- CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
- llvm::GlobalValue::PrivateLinkage, Init, ".ref.tmp", nullptr,
- llvm::GlobalValue::NotThreadLocal,
- CGF.getContext().getTargetAddressSpace(AS));
- CharUnits alignment = CGF.getContext().getTypeAlignInChars(Ty);
- GV->setAlignment(alignment.getAsAlign());
- llvm::Constant *C = GV;
- if (AS != LangAS::Default)
- C = TCG.performAddrSpaceCast(
- CGF.CGM, GV, AS, LangAS::Default,
- GV->getValueType()->getPointerTo(
- CGF.getContext().getTargetAddressSpace(LangAS::Default)));
- // FIXME: Should we put the new global into a COMDAT?
- return Address(C, alignment);
- }
+ auto AS = CGF.CGM.GetGlobalConstantAddressSpace();
+ auto *GV = new llvm::GlobalVariable(
+ CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
+ llvm::GlobalValue::PrivateLinkage, Init, ".ref.tmp", nullptr,
+ llvm::GlobalValue::NotThreadLocal,
+ CGF.getContext().getTargetAddressSpace(AS));
+ CharUnits alignment = CGF.getContext().getTypeAlignInChars(Ty);
+ GV->setAlignment(alignment.getAsAlign());
+ llvm::Constant *C = GV;
+ if (AS != LangAS::Default)
+ C = TCG.performAddrSpaceCast(
+ CGF.CGM, GV, AS, LangAS::Default,
+ GV->getValueType()->getPointerTo(
+ CGF.getContext().getTargetAddressSpace(LangAS::Default)));
+ // FIXME: Should we put the new global into a COMDAT?
+ return Address(C, alignment);
}
return CGF.CreateMemTemp(Ty, "ref.tmp", Alloca);
}
return AddrSpace;
}
+ if (LangOpts.SYCLIsDevice &&
+ (!D || D->getType().getAddressSpace() == LangAS::Default))
+ return LangAS::sycl_global;
+
if (LangOpts.CUDA && LangOpts.CUDAIsDevice) {
if (D && D->hasAttr<CUDAConstantAttr>())
return LangAS::cuda_constant;
return getTargetCodeGenInfo().getGlobalVarAddressSpace(*this, D);
}
-LangAS CodeGenModule::getStringLiteralAddressSpace() const {
+LangAS CodeGenModule::GetGlobalConstantAddressSpace() const {
// OpenCL v1.2 s6.5.3: a string literal is in the constant address space.
if (LangOpts.OpenCL)
return LangAS::opencl_constant;
+ if (LangOpts.SYCLIsDevice)
+ return LangAS::sycl_global;
if (auto AS = getTarget().getConstantAddressSpace())
return AS.getValue();
return LangAS::Default;
llvm::GlobalVariable *GV) {
llvm::Constant *Cast = GV;
if (!CGM.getLangOpts().OpenCL) {
- if (auto AS = CGM.getTarget().getConstantAddressSpace()) {
- if (AS != LangAS::Default)
- Cast = CGM.getTargetCodeGenInfo().performAddrSpaceCast(
- CGM, GV, AS.getValue(), LangAS::Default,
- GV->getValueType()->getPointerTo(
- CGM.getContext().getTargetAddressSpace(LangAS::Default)));
- }
+ auto AS = CGM.GetGlobalConstantAddressSpace();
+ if (AS != LangAS::Default)
+ Cast = CGM.getTargetCodeGenInfo().performAddrSpaceCast(
+ CGM, GV, AS, LangAS::Default,
+ GV->getValueType()->getPointerTo(
+ CGM.getContext().getTargetAddressSpace(LangAS::Default)));
}
return Cast;
}
CodeGenModule &CGM, StringRef GlobalName,
CharUnits Alignment) {
unsigned AddrSpace = CGM.getContext().getTargetAddressSpace(
- CGM.getStringLiteralAddressSpace());
+ CGM.GetGlobalConstantAddressSpace());
llvm::Module &M = CGM.getModule();
// Create a global variable for this string
/// space, target-specific global or constant address space may be returned.
LangAS GetGlobalVarAddressSpace(const VarDecl *D);
+ /// Return the AST address space of constant literal, which is used to emit
+ /// the constant literal as global variable in LLVM IR.
+ /// Note: This is not necessarily the address space of the constant literal
+ /// in AST. For address space agnostic language, e.g. C++, constant literal
+ /// in AST is always in default address space.
+ LangAS GetGlobalConstantAddressSpace() const;
+
/// Return the llvm::Constant for the address of the given global variable.
/// If Ty is non-null and if the global doesn't exist, then it will be created
/// with the specified type instead of whatever the normal requested type
ForDefinition_t IsForDefinition
= NotForDefinition);
- /// Return the AST address space of string literal, which is used to emit
- /// the string literal as global variable in LLVM IR.
- /// Note: This is not necessarily the address space of the string literal
- /// in AST. For address space agnostic language, e.g. C++, string literal
- /// in AST is always in default address space.
- LangAS getStringLiteralAddressSpace() const;
-
/// Return the address of the given function. If Ty is non-null, then this
/// function will use the specified type if it has to create it.
llvm::Constant *GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty = nullptr,
public:
SPIRTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
: TargetCodeGenInfo(std::make_unique<SPIRABIInfo>(CGT)) {}
+
+ LangAS getASTAllocaAddressSpace() const override {
+ return getLangASFromTargetAS(
+ getABIInfo().getDataLayout().getAllocaAddrSpace());
+ }
+
unsigned getOpenCLKernelCallingConv() const override;
};
llvm::APSInt max(addrSpace.getBitWidth());
max =
Qualifiers::MaxAddressSpace - (unsigned)LangAS::FirstTargetAddressSpace;
+
if (addrSpace > max) {
S.Diag(AttrLoc, diag::err_attribute_address_space_too_high)
<< (unsigned)max.getZExtValue() << AddrSpace->getSourceRange();
Attr.setInvalid();
} else {
// The keyword-based type attributes imply which address space to use.
- ASIdx = Attr.asOpenCLLangAS();
+ ASIdx = S.getLangOpts().SYCLIsDevice ? Attr.asSYCLLangAS()
+ : Attr.asOpenCLLangAS();
+
if (ASIdx == LangAS::Default)
llvm_unreachable("Invalid address space");
--- /dev/null
+// RUN: %clang_cc1 -triple spir64 -fsycl-is-device -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
+void bar(int &Data) {}
+// CHECK-DAG: define{{.*}} spir_func void @[[RAW_REF:[a-zA-Z0-9_]+]](i32 addrspace(4)* align 4 dereferenceable(4) %
+void bar2(int &Data) {}
+// CHECK-DAG: define{{.*}} spir_func void @[[RAW_REF2:[a-zA-Z0-9_]+]](i32 addrspace(4)* align 4 dereferenceable(4) %
+void bar(__attribute__((opencl_local)) int &Data) {}
+// CHECK-DAG: define{{.*}} spir_func void [[LOC_REF:@[a-zA-Z0-9_]+]](i32 addrspace(3)* align 4 dereferenceable(4) %
+void foo(int *Data) {}
+// CHECK-DAG: define{{.*}} spir_func void @[[RAW_PTR:[a-zA-Z0-9_]+]](i32 addrspace(4)* %
+void foo2(int *Data) {}
+// CHECK-DAG: define{{.*}} spir_func void @[[RAW_PTR2:[a-zA-Z0-9_]+]](i32 addrspace(4)* %
+void foo(__attribute__((opencl_local)) int *Data) {}
+// CHECK-DAG: define{{.*}} spir_func void [[LOC_PTR:@[a-zA-Z0-9_]+]](i32 addrspace(3)* %
+
+template <typename T>
+void tmpl(T t) {}
+// See Check Lines below.
+
+void usages() {
+ // CHECK-DAG: [[GLOB:%[a-zA-Z0-9]+]] = alloca i32 addrspace(1)*
+ // CHECK-DAG: [[GLOB]].ascast = addrspacecast i32 addrspace(1)** [[GLOB]] to i32 addrspace(1)* addrspace(4)*
+ __attribute__((opencl_global)) int *GLOB;
+ // CHECK-DAG: [[LOC:%[a-zA-Z0-9]+]] = alloca i32 addrspace(3)*
+ // CHECK-DAG: [[LOC]].ascast = addrspacecast i32 addrspace(3)** [[LOC]] to i32 addrspace(3)* addrspace(4)*
+ __attribute__((opencl_local)) int *LOC;
+ // CHECK-DAG: [[NoAS:%[a-zA-Z0-9]+]] = alloca i32 addrspace(4)*
+ // CHECK-DAG: [[NoAS]].ascast = addrspacecast i32 addrspace(4)** [[NoAS]] to i32 addrspace(4)* addrspace(4)*
+ int *NoAS;
+ // CHECK-DAG: [[PRIV:%[a-zA-Z0-9]+]] = alloca i32*
+ // CHECK-DAG: [[PRIV]].ascast = addrspacecast i32** [[PRIV]] to i32* addrspace(4)*
+ __attribute__((opencl_private)) int *PRIV;
+
+ // Explicit conversions
+ // From names address spaces to default address space
+ // CHECK-DAG: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(4)* [[GLOB]].ascast
+ // CHECK-DAG: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast i32 addrspace(1)* [[GLOB_LOAD]] to i32 addrspace(4)*
+ // CHECK-DAG: store i32 addrspace(4)* [[GLOB_CAST]], i32 addrspace(4)* addrspace(4)* [[NoAS]].ascast
+ NoAS = (int *)GLOB;
+ // CHECK-DAG: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load i32 addrspace(3)*, i32 addrspace(3)* addrspace(4)* [[LOC]].ascast
+ // CHECK-DAG: [[LOC_CAST:%[a-zA-Z0-9]+]] = addrspacecast i32 addrspace(3)* [[LOC_LOAD]] to i32 addrspace(4)*
+ // CHECK-DAG: store i32 addrspace(4)* [[LOC_CAST]], i32 addrspace(4)* addrspace(4)* [[NoAS]].ascast
+ NoAS = (int *)LOC;
+ // CHECK-DAG: [[PRIV_LOAD:%[a-zA-Z0-9]+]] = load i32*, i32* addrspace(4)* [[PRIV]].ascast
+ // CHECK-DAG: [[PRIV_CAST:%[a-zA-Z0-9]+]] = addrspacecast i32* [[PRIV_LOAD]] to i32 addrspace(4)*
+ // CHECK-DAG: store i32 addrspace(4)* [[PRIV_CAST]], i32 addrspace(4)* addrspace(4)* [[NoAS]].ascast
+ NoAS = (int *)PRIV;
+ // From default address space to named address space
+ // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load i32 addrspace(4)*, i32 addrspace(4)* addrspace(4)* [[NoAS]].ascast
+ // CHECK-DAG: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast i32 addrspace(4)* [[NoAS_LOAD]] to i32 addrspace(1)*
+ // CHECK-DAG: store i32 addrspace(1)* [[NoAS_CAST]], i32 addrspace(1)* addrspace(4)* [[GLOB]].ascast
+ GLOB = (__attribute__((opencl_global)) int *)NoAS;
+ // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load i32 addrspace(4)*, i32 addrspace(4)* addrspace(4)* [[NoAS]].ascast
+ // CHECK-DAG: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast i32 addrspace(4)* [[NoAS_LOAD]] to i32 addrspace(3)*
+ // CHECK-DAG: store i32 addrspace(3)* [[NoAS_CAST]], i32 addrspace(3)* addrspace(4)* [[LOC]].ascast
+ LOC = (__attribute__((opencl_local)) int *)NoAS;
+ // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load i32 addrspace(4)*, i32 addrspace(4)* addrspace(4)* [[NoAS]].ascast
+ // CHECK-DAG: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast i32 addrspace(4)* [[NoAS_LOAD]] to i32*
+ // CHECK-DAG: store i32* [[NoAS_CAST]], i32* addrspace(4)* [[PRIV]].ascast
+ PRIV = (__attribute__((opencl_private)) int *)NoAS;
+
+ bar(*GLOB);
+ // CHECK-DAG: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(4)* [[GLOB]].ascast
+ // CHECK-DAG: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast i32 addrspace(1)* [[GLOB_LOAD]] to i32 addrspace(4)*
+ // CHECK-DAG: call spir_func void @[[RAW_REF]](i32 addrspace(4)* align 4 dereferenceable(4) [[GLOB_CAST]])
+ bar2(*GLOB);
+ // CHECK-DAG: [[GLOB_LOAD2:%[a-zA-Z0-9]+]] = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(4)* [[GLOB]].ascast
+ // CHECK-DAG: [[GLOB_CAST2:%[a-zA-Z0-9]+]] = addrspacecast i32 addrspace(1)* [[GLOB_LOAD2]] to i32 addrspace(4)*
+ // CHECK-DAG: call spir_func void @[[RAW_REF2]](i32 addrspace(4)* align 4 dereferenceable(4) [[GLOB_CAST2]])
+
+ bar(*LOC);
+ // CHECK-DAG: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load i32 addrspace(3)*, i32 addrspace(3)* addrspace(4)* [[LOC]].ascast
+ // CHECK-DAG: call spir_func void [[LOC_REF]](i32 addrspace(3)* align 4 dereferenceable(4) [[LOC_LOAD]])
+ bar2(*LOC);
+ // CHECK-DAG: [[LOC_LOAD2:%[a-zA-Z0-9]+]] = load i32 addrspace(3)*, i32 addrspace(3)* addrspace(4)* [[LOC]].ascast
+ // CHECK-DAG: [[LOC_CAST2:%[a-zA-Z0-9]+]] = addrspacecast i32 addrspace(3)* [[LOC_LOAD2]] to i32 addrspace(4)*
+ // CHECK-DAG: call spir_func void @[[RAW_REF2]](i32 addrspace(4)* align 4 dereferenceable(4) [[LOC_CAST2]])
+
+ bar(*NoAS);
+ // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load i32 addrspace(4)*, i32 addrspace(4)* addrspace(4)* [[NoAS]].ascast
+ // CHECK-DAG: call spir_func void @[[RAW_REF]](i32 addrspace(4)* align 4 dereferenceable(4) [[NoAS_LOAD]])
+ bar2(*NoAS);
+ // CHECK-DAG: [[NoAS_LOAD2:%[a-zA-Z0-9]+]] = load i32 addrspace(4)*, i32 addrspace(4)* addrspace(4)* [[NoAS]].ascast
+ // CHECK-DAG: call spir_func void @[[RAW_REF2]](i32 addrspace(4)* align 4 dereferenceable(4) [[NoAS_LOAD2]])
+
+ foo(GLOB);
+ // CHECK-DAG: [[GLOB_LOAD3:%[a-zA-Z0-9]+]] = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(4)* [[GLOB]].ascast
+ // CHECK-DAG: [[GLOB_CAST3:%[a-zA-Z0-9]+]] = addrspacecast i32 addrspace(1)* [[GLOB_LOAD3]] to i32 addrspace(4)*
+ // CHECK-DAG: call spir_func void @[[RAW_PTR]](i32 addrspace(4)* [[GLOB_CAST3]])
+ foo2(GLOB);
+ // CHECK-DAG: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(4)* [[GLOB]].ascast
+ // CHECK-DAG: [[GLOB_CAST4:%[a-zA-Z0-9]+]] = addrspacecast i32 addrspace(1)* [[GLOB_LOAD4]] to i32 addrspace(4)*
+ // CHECK-DAG: call spir_func void @[[RAW_PTR2]](i32 addrspace(4)* [[GLOB_CAST4]])
+ foo(LOC);
+ // CHECK-DAG: [[LOC_LOAD3:%[a-zA-Z0-9]+]] = load i32 addrspace(3)*, i32 addrspace(3)* addrspace(4)* [[LOC]].ascast
+ // CHECK-DAG: call spir_func void [[LOC_PTR]](i32 addrspace(3)* [[LOC_LOAD3]])
+ foo2(LOC);
+ // CHECK-DAG: [[LOC_LOAD4:%[a-zA-Z0-9]+]] = load i32 addrspace(3)*, i32 addrspace(3)* addrspace(4)* [[LOC]].ascast
+ // CHECK-DAG: [[LOC_CAST4:%[a-zA-Z0-9]+]] = addrspacecast i32 addrspace(3)* [[LOC_LOAD4]] to i32 addrspace(4)*
+ // CHECK-DAG: call spir_func void @[[RAW_PTR2]](i32 addrspace(4)* [[LOC_CAST4]])
+ foo(NoAS);
+ // CHECK-DAG: [[NoAS_LOAD3:%[a-zA-Z0-9]+]] = load i32 addrspace(4)*, i32 addrspace(4)* addrspace(4)* [[NoAS]].ascast
+ // CHECK-DAG: call spir_func void @[[RAW_PTR]](i32 addrspace(4)* [[NoAS_LOAD3]])
+ foo2(NoAS);
+ // CHECK-DAG: [[NoAS_LOAD4:%[a-zA-Z0-9]+]] = load i32 addrspace(4)*, i32 addrspace(4)* addrspace(4)* [[NoAS]].ascast
+ // CHECK-DAG: call spir_func void @[[RAW_PTR2]](i32 addrspace(4)* [[NoAS_LOAD4]])
+
+ // Ensure that we still get 3 different template instantiations.
+ tmpl(GLOB);
+ // CHECK-DAG: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(4)* [[GLOB]].ascast
+ // CHECK-DAG: call spir_func void @_Z4tmplIPU3AS1iEvT_(i32 addrspace(1)* [[GLOB_LOAD4]])
+ tmpl(LOC);
+ // CHECK-DAG: [[LOC_LOAD5:%[a-zA-Z0-9]+]] = load i32 addrspace(3)*, i32 addrspace(3)* addrspace(4)* [[LOC]].ascast
+ // CHECK-DAG: call spir_func void @_Z4tmplIPU3AS3iEvT_(i32 addrspace(3)* [[LOC_LOAD5]])
+ tmpl(PRIV);
+ // CHECK-DAG: [[PRIV_LOAD5:%[a-zA-Z0-9]+]] = load i32*, i32* addrspace(4)* [[PRIV]].ascast
+ // CHECK-DAG: call spir_func void @_Z4tmplIPU3AS0iEvT_(i32* [[PRIV_LOAD5]])
+ tmpl(NoAS);
+ // CHECK-DAG: [[NoAS_LOAD5:%[a-zA-Z0-9]+]] = load i32 addrspace(4)*, i32 addrspace(4)* addrspace(4)* [[NoAS]].ascast
+ // CHECK-DAG: call spir_func void @_Z4tmplIPiEvT_(i32 addrspace(4)* [[NoAS_LOAD5]])
+}
+
+// CHECK-DAG: define linkonce_odr spir_func void @_Z4tmplIPU3AS1iEvT_(i32 addrspace(1)* %
+// CHECK-DAG: define linkonce_odr spir_func void @_Z4tmplIPU3AS3iEvT_(i32 addrspace(3)* %
+// CHECK-DAG: define linkonce_odr spir_func void @_Z4tmplIPU3AS0iEvT_(i32* %
+// CHECK-DAG: define linkonce_odr spir_func void @_Z4tmplIPiEvT_(i32 addrspace(4)* %
--- /dev/null
+// RUN: %clang_cc1 -triple spir64 -fsycl-is-device -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: @_ZZ4testvE3foo = internal addrspace(1) constant i32 66, align 4
+// CHECK: @[[STR:[.a-zA-Z0-9_]+]] = private unnamed_addr addrspace(1) constant [14 x i8] c"Hello, world!\00", align 1
+
+// CHECK-LABEL: @_Z4testv
+void test() {
+ static const int foo = 0x42;
+
+ // CHECK: %i.ascast = addrspacecast i32* %i to i32 addrspace(4)*
+ // CHECK: %[[ARR:[a-zA-Z0-9]+]] = alloca [42 x i32]
+ // CHECK: %[[ARR]].ascast = addrspacecast [42 x i32]* %[[ARR]] to [42 x i32] addrspace(4)*
+
+ int i = 0;
+ int *pptr = &i;
+ // CHECK: store i32 addrspace(4)* %i.ascast, i32 addrspace(4)* addrspace(4)* %pptr.ascast
+ bool is_i_ptr = (pptr == &i);
+ // CHECK: %[[VALPPTR:[0-9]+]] = load i32 addrspace(4)*, i32 addrspace(4)* addrspace(4)* %pptr.ascast
+ // CHECK: %cmp{{[0-9]*}} = icmp eq i32 addrspace(4)* %[[VALPPTR]], %i.ascast
+ *pptr = foo;
+
+ int var23 = 23;
+ char *cp = (char *)&var23;
+ *cp = 41;
+ // CHECK: store i32 23, i32 addrspace(4)* %[[VAR:[a-zA-Z0-9.]+]]
+ // CHECK: [[VARCAST:%.*]] = bitcast i32 addrspace(4)* %[[VAR]] to i8 addrspace(4)*
+ // CHECK: store i8 addrspace(4)* [[VARCAST]], i8 addrspace(4)* addrspace(4)* %{{.*}}
+
+ int arr[42];
+ char *cpp = (char *)arr;
+ *cpp = 43;
+ // CHECK: [[ARRDECAY:%.*]] = getelementptr inbounds [42 x i32], [42 x i32] addrspace(4)* %[[ARR]].ascast, i64 0, i64 0
+ // CHECK: [[ARRCAST:%.*]] = bitcast i32 addrspace(4)* [[ARRDECAY]] to i8 addrspace(4)*
+ // CHECK: store i8 addrspace(4)* [[ARRCAST]], i8 addrspace(4)* addrspace(4)* %{{.*}}
+
+ int *aptr = arr + 10;
+ if (aptr < arr + sizeof(arr))
+ *aptr = 44;
+ // CHECK: %[[VALAPTR:.*]] = load i32 addrspace(4)*, i32 addrspace(4)* addrspace(4)* %aptr.ascast
+ // CHECK: %[[ARRDCY2:.*]] = getelementptr inbounds [42 x i32], [42 x i32] addrspace(4)* %[[ARR]].ascast, i64 0, i64 0
+ // CHECK: %[[ADDPTR:.*]] = getelementptr inbounds i32, i32 addrspace(4)* %[[ARRDCY2]], i64 168
+ // CHECK: %cmp{{[0-9]+}} = icmp ult i32 addrspace(4)* %[[VALAPTR]], %[[ADDPTR]]
+
+ const char *str = "Hello, world!";
+ // CHECK: store i8 addrspace(4)* getelementptr inbounds ([14 x i8], [14 x i8] addrspace(4)* addrspacecast ([14 x i8] addrspace(1)* @[[STR]] to [14 x i8] addrspace(4)*), i64 0, i64 0), i8 addrspace(4)* addrspace(4)* %[[STRVAL:[a-zA-Z0-9]+]].ascast, align 8
+
+ i = str[0];
+
+ const char *phi_str = i > 2 ? str : "Another hello world!";
+ (void)phi_str;
+ // CHECK: %[[COND:[a-zA-Z0-9]+]] = icmp sgt i32 %{{.*}}, 2
+ // CHECK: br i1 %[[COND]], label %[[CONDTRUE:[.a-zA-Z0-9]+]], label %[[CONDFALSE:[.a-zA-Z0-9]+]]
+
+ // CHECK: [[CONDTRUE]]:
+ // CHECK-NEXT: %[[VALTRUE:[a-zA-Z0-9]+]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %str.ascast
+ // CHECK-NEXT: br label %[[CONDEND:[.a-zA-Z0-9]+]]
+
+ // CHECK: [[CONDFALSE]]:
+
+ // CHECK: [[CONDEND]]:
+ // CHECK-NEXT: phi i8 addrspace(4)* [ %[[VALTRUE]], %[[CONDTRUE]] ], [ getelementptr inbounds ([21 x i8], [21 x i8] addrspace(4)* addrspacecast ([21 x i8] addrspace(1)* @{{.*}} to [21 x i8] addrspace(4)*), i64 0, i64 0), %[[CONDFALSE]] ]
+
+ const char *select_null = i > 2 ? "Yet another Hello world" : nullptr;
+ (void)select_null;
+ // CHECK: select i1 %{{.*}}, i8 addrspace(4)* getelementptr inbounds ([24 x i8], [24 x i8] addrspace(4)* addrspacecast ([24 x i8] addrspace(1)* @{{.*}} to [24 x i8] addrspace(4)*), i64 0, i64 0)
+
+ const char *select_str_trivial1 = true ? str : "Another hello world!";
+ (void)select_str_trivial1;
+ // CHECK: %[[TRIVIALTRUE:[a-zA-Z0-9]+]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %[[STRVAL]]
+ // CHECK: store i8 addrspace(4)* %[[TRIVIALTRUE]], i8 addrspace(4)* addrspace(4)* %{{.*}}, align 8
+
+ const char *select_str_trivial2 = false ? str : "Another hello world!";
+ (void)select_str_trivial2;
+}
--- /dev/null
+// RUN: %clang_cc1 -triple spir64 -fsycl-is-device -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s --check-prefix=SPIR
+// RUN: %clang_cc1 -triple x86_64 -fsycl-is-device -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s --check-prefix=X86
+
+// REQUIRES: x86-registered-target
+
+void foo(__attribute__((opencl_global)) int *);
+void foo(__attribute__((opencl_local)) int *);
+void foo(__attribute__((opencl_private)) int *);
+void foo(int *);
+
+// SPIR: declare spir_func void @_Z3fooPU3AS1i(i32 addrspace(1)*) #1
+// SPIR: declare spir_func void @_Z3fooPU3AS3i(i32 addrspace(3)*) #1
+// SPIR: declare spir_func void @_Z3fooPU3AS0i(i32*) #1
+// SPIR: declare spir_func void @_Z3fooPi(i32 addrspace(4)*) #1
+
+// X86: declare void @_Z3fooPU8SYglobali(i32*) #1
+// X86: declare void @_Z3fooPU7SYlocali(i32*) #1
+// X86: declare void @_Z3fooPU9SYprivatei(i32*) #1
+// X86: declare void @_Z3fooPi(i32*) #1
+
+void test() {
+ __attribute__((opencl_global)) int *glob;
+ __attribute__((opencl_local)) int *loc;
+ __attribute__((opencl_private)) int *priv;
+ int *def;
+ foo(glob);
+ foo(loc);
+ foo(priv);
+ foo(def);
+}
--- /dev/null
+// RUN: %clang_cc1 -fsycl-is-device -verify -fsyntax-only %s
+
+void bar(int &Data) {}
+void bar2(int &Data) {}
+void bar(__attribute__((opencl_private)) int &Data) {}
+void foo(int *Data) {}
+void foo2(int *Data) {}
+void foo(__attribute__((opencl_private)) int *Data) {}
+void baz(__attribute__((opencl_private)) int *Data) {} // expected-note {{candidate function not viable: cannot pass pointer to generic address space as a pointer to address space '__private' in 1st argument}}
+
+template <typename T>
+void tmpl(T *t) {}
+
+void usages() {
+ __attribute__((opencl_global)) int *GLOB;
+ __attribute__((opencl_private)) int *PRIV;
+ __attribute__((opencl_local)) int *LOC;
+ int *NoAS;
+
+ GLOB = PRIV; // expected-error {{assigning '__private int *' to '__global int *' changes address space of pointer}}
+ GLOB = LOC; // expected-error {{assigning '__local int *' to '__global int *' changes address space of pointer}}
+ PRIV = static_cast<__attribute__((opencl_private)) int *>(GLOB); // expected-error {{static_cast from '__global int *' to '__private int *' is not allowed}}
+ PRIV = static_cast<__attribute__((opencl_private)) int *>(LOC); // expected-error {{static_cast from '__local int *' to '__private int *' is not allowed}}
+ NoAS = GLOB + PRIV; // expected-error {{invalid operands to binary expression ('__global int *' and '__private int *')}}
+ NoAS = GLOB + LOC; // expected-error {{invalid operands to binary expression ('__global int *' and '__local int *')}}
+ NoAS += GLOB; // expected-error {{invalid operands to binary expression ('int *' and '__global int *')}}
+
+ bar(*GLOB);
+ bar2(*GLOB);
+
+ bar(*PRIV);
+ bar2(*PRIV);
+
+ bar(*NoAS);
+ bar2(*NoAS);
+
+ bar(*LOC);
+ bar2(*LOC);
+
+ foo(GLOB);
+ foo2(GLOB);
+ foo(PRIV);
+ foo2(PRIV);
+ foo(NoAS);
+ foo2(NoAS);
+ foo(LOC);
+ foo2(LOC);
+
+ tmpl(GLOB);
+ tmpl(PRIV);
+ tmpl(NoAS);
+ tmpl(LOC);
+
+ // Implicit casts to named address space are disallowed
+ baz(NoAS); // expected-error {{no matching function for call to 'baz'}}
+ __attribute__((opencl_local)) int *l = NoAS; // expected-error {{cannot initialize a variable of type '__local int *' with an lvalue of type 'int *'}}
+
+ (void)static_cast<int *>(GLOB);
+ (void)static_cast<void *>(GLOB);
+ int *i = GLOB;
+ void *v = GLOB;
+ (void)i;
+ (void)v;
+}
template <long int I>
void tooBig() {
- __attribute__((address_space(I))) int *bounds; // expected-error {{address space is larger than the maximum supported (8388593)}}
+ __attribute__((address_space(I))) int *bounds; // expected-error {{address space is larger than the maximum supported (8388590)}}
}
template <long int I>
car<1, 2, 3>(); // expected-note {{in instantiation of function template specialization 'car<1, 2, 3>' requested here}}
HasASTemplateFields<1> HASTF;
neg<-1>(); // expected-note {{in instantiation of function template specialization 'neg<-1>' requested here}}
- correct<0x7FFFF1>();
+ correct<0x7FFFED>();
tooBig<8388650>(); // expected-note {{in instantiation of function template specialization 'tooBig<8388650>' requested here}}
__attribute__((address_space(1))) char *x;