]> granicus.if.org Git - clang/commitdiff
CodeGen: Cast alloca to expected address space
authorYaxun Liu <Yaxun.Liu@amd.com>
Thu, 18 May 2017 18:51:09 +0000 (18:51 +0000)
committerYaxun Liu <Yaxun.Liu@amd.com>
Thu, 18 May 2017 18:51:09 +0000 (18:51 +0000)
Alloca always returns a pointer in alloca address space, which may
be different from the type defined by the language. For example,
in C++ the auto variables are in the default address space. Therefore
cast alloca to the expected address space when necessary.

Differential Revision: https://reviews.llvm.org/D32248

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@303370 91177308-0d34-0410-b5e6-96231b3b80d8

28 files changed:
include/clang/AST/ASTContext.h
include/clang/AST/Type.h
include/clang/Basic/AddressSpaces.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/ASTContext.cpp
lib/AST/TypePrinter.cpp
lib/Basic/Targets.cpp
lib/CodeGen/CGDecl.cpp
lib/CodeGen/CGExprScalar.cpp
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenTypeCache.h
lib/CodeGen/TargetInfo.cpp
lib/CodeGen/TargetInfo.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaType.cpp
test/CodeGen/address-space.c
test/CodeGenCXX/amdgcn-automatic-variable.cpp [new file with mode: 0644]
test/CodeGenOpenCL/amdgcn-automatic-variable.cl [new file with mode: 0644]
test/CodeGenOpenCL/amdgpu-alignment.cl
test/CodeGenOpenCL/amdgpu-debug-info-pointer-address-space.cl
test/CodeGenOpenCL/amdgpu-debug-info-variable-expression.cl
test/CodeGenOpenCL/amdgpu-nullptr.cl
test/CodeGenOpenCL/builtins-amdgcn.cl
test/CodeGenOpenCL/byval.cl
test/CodeGenOpenCL/size_t.cl
test/Sema/sizeof-struct-non-zero-as-member.cl
test/SemaOpenCL/storageclass-cl20.cl
test/SemaOpenCL/storageclass.cl

index 2221d6f9fc1e00f766d5ed2c30f27882d5d8c938..4c379620ab2d5134073fb06b4b8a6a601aa55f1c 100644 (file)
@@ -2324,8 +2324,7 @@ public:
   uint64_t getTargetNullPointerValue(QualType QT) const;
 
   bool addressSpaceMapManglingFor(unsigned AS) const {
-    return AddrSpaceMapMangling || 
-           AS >= LangAS::Count;
+    return AddrSpaceMapMangling || AS >= LangAS::FirstTargetAddressSpace;
   }
 
 private:
index b1c2503c32e3d239b70ff5bdabbf0b8c2e6e8678..ce1ce54d1560bdb767afeea160772c6f7c791183 100644 (file)
@@ -333,15 +333,18 @@ public:
 
   bool hasAddressSpace() const { return Mask & AddressSpaceMask; }
   unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; }
+  bool hasTargetSpecificAddressSpace() const {
+    return getAddressSpace() >= LangAS::FirstTargetAddressSpace;
+  }
   /// Get the address space attribute value to be printed by diagnostics.
   unsigned getAddressSpaceAttributePrintValue() const {
     auto Addr = getAddressSpace();
     // This function is not supposed to be used with language specific
     // address spaces. If that happens, the diagnostic message should consider
     // printing the QualType instead of the address space value.
-    assert(Addr == 0 || Addr >= LangAS::Count);
+    assert(Addr == 0 || hasTargetSpecificAddressSpace());
     if (Addr)
-      return Addr - LangAS::Count;
+      return Addr - LangAS::FirstTargetAddressSpace;
     // TODO: The diagnostic messages where Addr may be 0 should be fixed
     // since it cannot differentiate the situation where 0 denotes the default
     // address space or user specified __attribute__((address_space(0))).
index 0ec5aafd64b696121496f1891ce86fd4400ec64f..95b9b9c7d0b3185d61b108570a39140f6bb8b803 100644 (file)
@@ -45,13 +45,12 @@ enum ID {
   // This denotes the count of language-specific address spaces and also
   // the offset added to the target-specific address spaces, which are usually
   // specified by address space attributes __attribute__(address_space(n))).
-  Count
+  FirstTargetAddressSpace
 };
 
 /// The type of a lookup table which maps from language-specific address spaces
 /// to target-specific ones.
-typedef unsigned Map[Count];
-
+typedef unsigned Map[FirstTargetAddressSpace];
 }
 
 }
index 1db6704f6d1fb67e0a2d213f4494d6654fddd9d3..463d057d8fd0db89d81584bcea4187726b5bd08a 100644 (file)
@@ -2490,7 +2490,7 @@ def err_attribute_address_multiple_qualifiers : Error<
 def err_attribute_address_function_type : Error<
   "function type may not be qualified with an address space">;
 def err_as_qualified_auto_decl : Error<
-  "automatic variable qualified with an address space">;
+  "automatic variable qualified with an%select{| invalid}0 address space">;
 def err_arg_with_address_space : Error<
   "parameter may not be qualified with an address space">;
 def err_field_with_address_space : Error<
index 3b526a23edd9523d42cdfd9d8783ccdd7d7dfc7a..29d970e66d7122c7da1accbf87b897145ebeafc5 100644 (file)
@@ -8730,8 +8730,8 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
       char *End;
       unsigned AddrSpace = strtoul(Str, &End, 10);
       if (End != Str && AddrSpace != 0) {
-        Type = Context.getAddrSpaceQualType(Type, AddrSpace +
-            LangAS::Count);
+        Type = Context.getAddrSpaceQualType(
+            Type, AddrSpace + LangAS::FirstTargetAddressSpace);
         Str = End;
       }
       if (c == '*')
@@ -9546,13 +9546,8 @@ uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const {
 }
 
 unsigned ASTContext::getTargetAddressSpace(unsigned AS) const {
-  // For OpenCL, only function local variables are not explicitly marked with
-  // an address space in the AST, and these need to be the address space of
-  // alloca.
-  if (!AS && LangOpts.OpenCL)
-    return getTargetInfo().getDataLayout().getAllocaAddrSpace();
-  if (AS >= LangAS::Count)
-    return AS - LangAS::Count;
+  if (AS >= LangAS::FirstTargetAddressSpace)
+    return AS - LangAS::FirstTargetAddressSpace;
   else
     return (*AddrSpaceMap)[AS];
 }
index 2be14ab621230b7b58178ef40bf367388d9dcf33..0551340c37a17a6dc8c23904d6c7a750e03cf4fc 100644 (file)
@@ -1668,9 +1668,9 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
         OS << "__shared";
         break;
       default:
-        assert(addrspace >= LangAS::Count);
+        assert(addrspace >= LangAS::FirstTargetAddressSpace);
         OS << "__attribute__((address_space(";
-        OS << addrspace - LangAS::Count;
+        OS << addrspace - LangAS::FirstTargetAddressSpace;
         OS << ")))";
     }
   }
index 92c561aa941343a56f3044b8325ca5a8693496ad..1b9fbed17731bc0d2c93cf06c782212dcec51361 100644 (file)
@@ -2034,25 +2034,45 @@ ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const {
   return llvm::makeArrayRef(GCCRegNames);
 }
 
-static const LangAS::Map AMDGPUPrivateIsZeroMap = {
-    4,  // Default
-    1,  // opencl_global
-    3,  // opencl_local
-    2,  // opencl_constant
-    4,  // opencl_generic
-    1,  // cuda_device
-    2,  // cuda_constant
-    3   // cuda_shared
+static const LangAS::Map AMDGPUNonOpenCLPrivateIsZeroMap = {
+    4, // Default
+    1, // opencl_global
+    3, // opencl_local
+    2, // opencl_constant
+    4, // opencl_generic
+    1, // cuda_device
+    2, // cuda_constant
+    3  // cuda_shared
+};
+static const LangAS::Map AMDGPUNonOpenCLGenericIsZeroMap = {
+    0, // Default
+    1, // opencl_global
+    3, // opencl_local
+    2, // opencl_constant
+    0, // opencl_generic
+    1, // cuda_device
+    2, // cuda_constant
+    3  // cuda_shared
 };
-static const LangAS::Map AMDGPUGenericIsZeroMap = {
-    0,  // Default
-    1,  // opencl_global
-    3,  // opencl_local
-    2,  // opencl_constant
-    0,  // opencl_generic
-    1,  // cuda_device
-    2,  // cuda_constant
-    3   // cuda_shared
+static const LangAS::Map AMDGPUOpenCLPrivateIsZeroMap = {
+    0, // Default
+    1, // opencl_global
+    3, // opencl_local
+    2, // opencl_constant
+    4, // opencl_generic
+    1, // cuda_device
+    2, // cuda_constant
+    3  // cuda_shared
+};
+static const LangAS::Map AMDGPUOpenCLGenericIsZeroMap = {
+    5, // Default
+    1, // opencl_global
+    3, // opencl_local
+    2, // opencl_constant
+    0, // opencl_generic
+    1, // cuda_device
+    2, // cuda_constant
+    3  // cuda_shared
 };
 
 // If you edit the description strings, make sure you update
@@ -2149,8 +2169,12 @@ public:
                     : DataLayoutStringR600);
     assert(DataLayout->getAllocaAddrSpace() == AS.Private);
 
-    AddrSpaceMap = IsGenericZero ? &AMDGPUGenericIsZeroMap :
-        &AMDGPUPrivateIsZeroMap;
+    AddrSpaceMap =
+        llvm::StringSwitch<const LangAS::Map *>(Triple.getEnvironmentName())
+            .Case("opencl", &AMDGPUOpenCLPrivateIsZeroMap)
+            .Case("amdgiz", &AMDGPUNonOpenCLGenericIsZeroMap)
+            .Case("amdgizcl", &AMDGPUOpenCLGenericIsZeroMap)
+            .Default(&AMDGPUNonOpenCLPrivateIsZeroMap);
     UseAddrSpaceMapMangling = true;
   }
 
index 0fa8eeb1c3e13fd7b34cd1266f7ad337572c382b..d6abfa15e541a77bf0c0706ac601ac0d2ef7c3a7 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
-#include "CodeGenFunction.h"
 #include "CGBlocks.h"
 #include "CGCXXABI.h"
 #include "CGCleanup.h"
 #include "CGDebugInfo.h"
 #include "CGOpenCLRuntime.h"
 #include "CGOpenMPRuntime.h"
+#include "CodeGenFunction.h"
 #include "CodeGenModule.h"
+#include "TargetInfo.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/Decl.h"
@@ -1105,6 +1106,21 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
     address = Address(vla, alignment);
   }
 
+  // Alloca always returns a pointer in alloca address space, which may
+  // be different from the type defined by the language. For example,
+  // in C++ the auto variables are in the default address space. Therefore
+  // cast alloca to the expected address space when necessary.
+  auto T = D.getType();
+  assert(T.getAddressSpace() == LangAS::Default);
+  if (getASTAllocaAddressSpace() != LangAS::Default) {
+    auto *Addr = getTargetHooks().performAddrSpaceCast(
+        *this, address.getPointer(), getASTAllocaAddressSpace(),
+        T.getAddressSpace(),
+        address.getElementType()->getPointerTo(
+            getContext().getTargetAddressSpace(T.getAddressSpace())),
+        /*non-null*/ true);
+    address = Address(Addr, address.getAlignment());
+  }
   setAddrOfLocalVar(&D, address);
   emission.Addr = address;
 
index b8d830ee9f3f0044c6d85573f746c99f00d480d2..048b50d8261d750df24e80ae3681d4e0b034fe7c 100644 (file)
@@ -1579,10 +1579,9 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
     }
     // Since target may map different address spaces in AST to the same address
     // space, an address space conversion may end up as a bitcast.
-    auto *Src = Visit(E);
-    return CGF.CGM.getTargetCodeGenInfo().performAddrSpaceCast(CGF, Src,
-                                                               E->getType(),
-                                                               DestTy);
+    return CGF.CGM.getTargetCodeGenInfo().performAddrSpaceCast(
+        CGF, Visit(E), E->getType()->getPointeeType().getAddressSpace(),
+        DestTy->getPointeeType().getAddressSpace(), ConvertType(DestTy));
   }
   case CK_AtomicToNonAtomic:
   case CK_NonAtomicToAtomic:
index a0254797ea43037f12cc29379f66f2785696d583..dee4351a51e3097bb10f20a70b60b9c91dd45771 100644 (file)
@@ -113,6 +113,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
   Int8PtrPtrTy = Int8PtrTy->getPointerTo(0);
   AllocaInt8PtrTy = Int8Ty->getPointerTo(
       M.getDataLayout().getAllocaAddrSpace());
+  ASTAllocaAddressSpace = getTargetCodeGenInfo().getASTAllocaAddressSpace();
 
   RuntimeCC = getTargetCodeGenInfo().getABIInfo().getRuntimeCC();
   BuiltinCC = getTargetCodeGenInfo().getABIInfo().getBuiltinCC();
index 8ce9860cc638f16abe5977bb2c981f975bcfe18e..450eab48a3b41e0755d0e7c0048ca8617c3fb9af 100644 (file)
@@ -94,6 +94,8 @@ struct CodeGenTypeCache {
     unsigned char SizeAlignInBytes;
   };
 
+  unsigned ASTAllocaAddressSpace;
+
   CharUnits getSizeSize() const {
     return CharUnits::fromQuantity(SizeSizeInBytes);
   }
@@ -111,6 +113,8 @@ struct CodeGenTypeCache {
   llvm::CallingConv::ID getRuntimeCC() const { return RuntimeCC; }
   llvm::CallingConv::ID BuiltinCC;
   llvm::CallingConv::ID getBuiltinCC() const { return BuiltinCC; }
+
+  unsigned getASTAllocaAddressSpace() const { return ASTAllocaAddressSpace; }
 };
 
 }  // end namespace CodeGen
index 18367d1602ba4da0617cd18b51e2a5e020a74cc3..e47b48072457e31aa5faf73ec14c4e5d84ec6139 100644 (file)
@@ -407,12 +407,11 @@ llvm::Constant *TargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &
 }
 
 llvm::Value *TargetCodeGenInfo::performAddrSpaceCast(
-    CodeGen::CodeGenFunction &CGF, llvm::Value *Src, QualType SrcTy,
-    QualType DestTy) const {
+    CodeGen::CodeGenFunction &CGF, llvm::Value *Src, unsigned SrcAddr,
+    unsigned DestAddr, llvm::Type *DestTy, bool isNonNull) const {
   // Since target may map different address spaces in AST to the same address
   // space, an address space conversion may end up as a bitcast.
-  return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Src,
-             CGF.ConvertType(DestTy));
+  return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Src, DestTy);
 }
 
 static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays);
@@ -7292,6 +7291,11 @@ public:
 
   llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM,
       llvm::PointerType *T, QualType QT) const override;
+
+  unsigned getASTAllocaAddressSpace() const override {
+    return LangAS::FirstTargetAddressSpace +
+           getABIInfo().getDataLayout().getAllocaAddrSpace();
+  }
 };
 }
 
index 223d6d047af713bb09c43dbb8ebfe96dffc775a3..247d01dcb0861d2b658065b29036be085376d9ee 100644 (file)
@@ -229,13 +229,20 @@ public:
   virtual llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM,
       llvm::PointerType *T, QualType QT) const;
 
+  /// Get the AST address space for alloca.
+  virtual unsigned getASTAllocaAddressSpace() const { return LangAS::Default; }
+
   /// Perform address space cast of an expression of pointer type.
   /// \param V is the LLVM value to be casted to another address space.
-  /// \param SrcTy is the QualType of \p V.
-  /// \param DestTy is the destination QualType.
+  /// \param SrcAddr is the language address space of \p V.
+  /// \param DestAddr is the targeted language address space.
+  /// \param DestTy is the destination LLVM pointer type.
+  /// \param IsNonNull is the flag indicating \p V is known to be non null.
   virtual llvm::Value *performAddrSpaceCast(CodeGen::CodeGenFunction &CGF,
-      llvm::Value *V, QualType SrcTy, QualType DestTy) const;
-
+                                            llvm::Value *V, unsigned SrcAddr,
+                                            unsigned DestAddr,
+                                            llvm::Type *DestTy,
+                                            bool IsNonNull = false) const;
 };
 
 } // namespace CodeGen
index 48091728ee32d5db51c29b87e2109ab10ee718bc..ba1e97b33d6fb00e58ee9bda6168294f92ad45a7 100644 (file)
@@ -7191,7 +7191,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
   // ISO/IEC TR 18037 S5.1.2
   if (!getLangOpts().OpenCL
       && NewVD->hasLocalStorage() && T.getAddressSpace() != 0) {
-    Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl);
+    Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 0;
     NewVD->setInvalidDecl();
     return;
   }
@@ -7271,6 +7271,11 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
           NewVD->setInvalidDecl();
           return;
         }
+      } else if (T.getAddressSpace() != LangAS::Default) {
+        // Do not allow other address spaces on automatic variable.
+        Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 1;
+        NewVD->setInvalidDecl();
+        return;
       }
     }
   }
index 3992179fabae352883de9607c55f3d2ea0f13f25..1433607e9c719ac8ab2f5c0bfa45d77e5807c22f 100644 (file)
@@ -5531,14 +5531,15 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
       addrSpace.setIsSigned(false);
     }
     llvm::APSInt max(addrSpace.getBitWidth());
-    max = Qualifiers::MaxAddressSpace - LangAS::Count;
+    max = Qualifiers::MaxAddressSpace - LangAS::FirstTargetAddressSpace;
     if (addrSpace > max) {
       S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
         << (unsigned)max.getZExtValue() << ASArgExpr->getSourceRange();
       Attr.setInvalid();
       return;
     }
-    ASIdx = static_cast<unsigned>(addrSpace.getZExtValue()) + LangAS::Count;
+    ASIdx = static_cast<unsigned>(addrSpace.getZExtValue()) +
+            LangAS::FirstTargetAddressSpace;
   } else {
     // The keyword-based type attributes imply which address space to use.
     switch (Attr.getKind()) {
index 5d57d5b6ebe5ee6df4129cc23b43e06203f7eb84..35e3dbdcfa737b91d8accf93c6e9d3c29ea9c054 100644 (file)
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck -check-prefixes=CHECK,GIZ %s
 // RUN: %clang_cc1 -triple amdgcn -emit-llvm < %s | FileCheck -check-prefixes=CHECK,PIZ %s
-// RUN: %clang_cc1 -triple amdgcn---amdgiz -emit-llvm < %s | FileCheck -check-prefixes=CHeCK,GIZ %s
+// RUN: %clang_cc1 -triple amdgcn---amdgiz -emit-llvm < %s | FileCheck -check-prefixes=CHECK,GIZ %s
 
 // CHECK: @foo = common addrspace(1) global
 int foo __attribute__((address_space(1)));
@@ -40,8 +40,10 @@ typedef struct {
 } MyStruct;
 
 // CHECK-LABEL: define void @test4(
-// CHECK: call void @llvm.memcpy.p0i8.p2i8
-// CHECK: call void @llvm.memcpy.p2i8.p0i8
+// GIZ: call void @llvm.memcpy.p0i8.p2i8
+// GIZ: call void @llvm.memcpy.p2i8.p0i8
+// PIZ: call void @llvm.memcpy.p4i8.p2i8
+// PIZ: call void @llvm.memcpy.p2i8.p4i8
 void test4(MyStruct __attribute__((address_space(2))) *pPtr) {
   MyStruct s = pPtr[0];
   pPtr[0] = s;
diff --git a/test/CodeGenCXX/amdgcn-automatic-variable.cpp b/test/CodeGenCXX/amdgcn-automatic-variable.cpp
new file mode 100644 (file)
index 0000000..aab7207
--- /dev/null
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 -O0 -triple amdgcn---amdgiz -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: define void @_Z5func1Pi(i32* %x)
+void func1(int *x) {
+  // CHECK: %[[x_addr:.*]] = alloca i32*{{.*}}addrspace(5)
+  // CHECK: store i32* %x, i32* addrspace(5)* %[[x_addr]]
+  // CHECK: %[[r0:.*]] = load i32*, i32* addrspace(5)* %[[x_addr]]
+  // CHECK: store i32 1, i32* %[[r0]]
+  *x = 1;
+}
+
+// CHECK-LABEL: define void @_Z5func2v()
+void func2(void) {
+  // CHECK: %lv1 = alloca i32, align 4, addrspace(5)
+  // CHECK: %lv2 = alloca i32, align 4, addrspace(5)
+  // CHECK: %la = alloca [100 x i32], align 4, addrspace(5)
+  // CHECK: %lp1 = alloca i32*, align 4, addrspace(5)
+  // CHECK: %lp2 = alloca i32*, align 4, addrspace(5)
+  // CHECK: %lvc = alloca i32, align 4, addrspace(5)
+
+  // CHECK: %[[r0:.*]] = addrspacecast i32 addrspace(5)* %lv1 to i32*
+  // CHECK: store i32 1, i32* %[[r0]]
+  int lv1;
+  lv1 = 1;
+  // CHECK: %[[r1:.*]] = addrspacecast i32 addrspace(5)* %lv2 to i32*
+  // CHECK: store i32 2, i32* %[[r1]]
+  int lv2 = 2;
+
+  // CHECK: %[[r2:.*]] = addrspacecast [100 x i32] addrspace(5)* %la to [100 x i32]*
+  // CHECK: %[[arrayidx:.*]] = getelementptr inbounds [100 x i32], [100 x i32]* %[[r2]], i64 0, i64 0
+  // CHECK: store i32 3, i32* %[[arrayidx]], align 4
+  int la[100];
+  la[0] = 3;
+
+  // CHECK: %[[r3:.*]] = addrspacecast i32* addrspace(5)* %lp1 to i32**
+  // CHECK: store i32* %[[r0]], i32** %[[r3]], align 4
+  int *lp1 = &lv1;
+
+  // CHECK: %[[r4:.*]] = addrspacecast i32* addrspace(5)* %lp2 to i32**
+  // CHECK: %[[arraydecay:.*]] = getelementptr inbounds [100 x i32], [100 x i32]* %[[r2]], i32 0, i32 0
+  // CHECK: store i32* %[[arraydecay]], i32** %[[r4]], align 4
+  int *lp2 = la;
+
+  // CHECK: call void @_Z5func1Pi(i32* %[[r0]])
+  func1(&lv1);
+
+  // CHECK: %[[r5:.*]] = addrspacecast i32 addrspace(5)* %lvc to i32*
+  // CHECK: store i32 4, i32* %[[r5]]
+  // CHECK: store i32 4, i32* %[[r0]]
+  const int lvc = 4;
+  lv1 = lvc;
+}
+
+void destroy(int x);
+
+class A {
+int x;
+public:
+  A():x(0) {}
+  ~A() {
+   destroy(x);
+  }
+};
+
+// CHECK-LABEL: define void @_Z5func3v
+void func3() {
+  // CHECK: %[[a:.*]] = alloca %class.A, align 4, addrspace(5)
+  // CHECK: %[[r0:.*]] = addrspacecast %class.A addrspace(5)* %[[a]] to %class.A*
+  // CHECK: call void @_ZN1AC1Ev(%class.A* %[[r0]])
+  // CHECK: call void @_ZN1AD1Ev(%class.A* %[[r0]])
+  A a;
+}
diff --git a/test/CodeGenOpenCL/amdgcn-automatic-variable.cl b/test/CodeGenOpenCL/amdgcn-automatic-variable.cl
new file mode 100644 (file)
index 0000000..2930956
--- /dev/null
@@ -0,0 +1,60 @@
+// RUN: %clang_cc1 -O0 -cl-std=CL1.2 -triple amdgcn---amdgizcl -emit-llvm %s -o - | FileCheck -check-prefixes=CHECK,CL12 %s
+// RUN: %clang_cc1 -O0 -cl-std=CL2.0 -triple amdgcn---amdgizcl -emit-llvm %s -o - | FileCheck -check-prefixes=CHECK,CL20 %s
+
+// CL12-LABEL: define void @func1(i32 addrspace(5)* %x)
+// CL20-LABEL: define void @func1(i32* %x)
+void func1(int *x) {
+  // CL12: %[[x_addr:.*]] = alloca i32 addrspace(5)*{{.*}}addrspace(5)
+  // CL12: store i32 addrspace(5)* %x, i32 addrspace(5)* addrspace(5)* %[[x_addr]]
+  // CL12: %[[r0:.*]] = load i32 addrspace(5)*, i32 addrspace(5)* addrspace(5)* %[[x_addr]]
+  // CL12: store i32 1, i32 addrspace(5)* %[[r0]]
+  // CL20: %[[x_addr:.*]] = alloca i32*{{.*}}addrspace(5)
+  // CL20: store i32* %x, i32* addrspace(5)* %[[x_addr]]
+  // CL20: %[[r0:.*]] = load i32*, i32* addrspace(5)* %[[x_addr]]
+  // CL20: store i32 1, i32* %[[r0]]
+  *x = 1;
+}
+
+// CHECK-LABEL: define void @func2()
+void func2(void) {
+  // CHECK: %lv1 = alloca i32, align 4, addrspace(5)
+  // CHECK: %lv2 = alloca i32, align 4, addrspace(5)
+  // CHECK: %la = alloca [100 x i32], align 4, addrspace(5)
+  // CL12: %lp1 = alloca i32 addrspace(5)*, align 4, addrspace(5)
+  // CL12: %lp2 = alloca i32 addrspace(5)*, align 4, addrspace(5)
+  // CL20: %lp1 = alloca i32*, align 4, addrspace(5)
+  // CL20: %lp2 = alloca i32*, align 4, addrspace(5)
+  // CHECK: %lvc = alloca i32, align 4, addrspace(5)
+
+  // CHECK: store i32 1, i32 addrspace(5)* %lv1
+  int lv1;
+  lv1 = 1;
+  // CHECK: store i32 2, i32 addrspace(5)* %lv2
+  int lv2 = 2;
+
+  // CHECK: %[[arrayidx:.*]] = getelementptr inbounds [100 x i32], [100 x i32] addrspace(5)* %la, i64 0, i64 0
+  // CHECK: store i32 3, i32 addrspace(5)* %[[arrayidx]], align 4
+  int la[100];
+  la[0] = 3;
+
+  // CL12: store i32 addrspace(5)* %lv1, i32 addrspace(5)* addrspace(5)* %lp1, align 4
+  // CL20: %[[r0:.*]] = addrspacecast i32 addrspace(5)* %lv1 to i32*
+  // CL20: store i32* %[[r0]], i32* addrspace(5)* %lp1, align 4
+  int *lp1 = &lv1;
+
+  // CHECK: %[[arraydecay:.*]] = getelementptr inbounds [100 x i32], [100 x i32] addrspace(5)* %la, i32 0, i32 0
+  // CL12: store i32 addrspace(5)* %[[arraydecay]], i32 addrspace(5)* addrspace(5)* %lp2, align 4
+  // CL20: %[[r1:.*]] = addrspacecast i32 addrspace(5)* %[[arraydecay]] to i32*
+  // CL20: store i32* %[[r1]], i32* addrspace(5)* %lp2, align 4
+  int *lp2 = la;
+
+  // CL12: call void @func1(i32 addrspace(5)* %lv1)
+  // CL20: %[[r2:.*]] = addrspacecast i32 addrspace(5)* %lv1 to i32*
+  // CL20: call void @func1(i32* %[[r2]])
+  func1(&lv1);
+
+  // CHECK: store i32 4, i32 addrspace(5)* %lvc
+  // CHECK: store i32 4, i32 addrspace(5)* %lv1
+  const int lvc = 4;
+  lv1 = lvc;
+}
index 35a8342eec0156b7d801eeb10e5ebf7cccd3983a..714e7240f53925089cc024e0025f2d990824fc78 100644 (file)
@@ -1,5 +1,5 @@
 // REQUIRES: amdgpu-registered-target
-// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -S -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple amdgcn-unknown-unknown-opencl -S -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s
 
 #pragma OPENCL EXTENSION cl_khr_fp64 : enable
 #pragma OPENCL EXTENSION cl_khr_fp16 : enable
index 7baee5eee39182019de8e2a69d33829b1525d00b..061ce2cca2fca6cad759308a6887d543e9c71963 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang -cl-std=CL2.0 -emit-llvm -g -O0 -S -target amdgcn-amd-amdhsa -mcpu=fiji -o - %s | FileCheck %s
+// RUN: %clang -cl-std=CL2.0 -emit-llvm -g -O0 -S -target amdgcn-amd-amdhsa-opencl -mcpu=fiji -o - %s | FileCheck %s
 
 // CHECK-DAG: ![[DWARF_ADDRESS_SPACE_NONE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{{[0-9]+}}, size: {{[0-9]+}})
 // CHECK-DAG: ![[DWARF_ADDRESS_SPACE_LOCAL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{{[0-9]+}}, size: {{[0-9]+}}, dwarfAddressSpace: 2)
index c0a4c21ce760bc9e1c0eb1ec6717d62ba9b7a17c..8cf086bf8dcc240bb19e850bb2c3535ba646a91e 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang -cl-std=CL2.0 -emit-llvm -g -O0 -S -target amdgcn-amd-amdhsa -mcpu=fiji -o - %s | FileCheck %s
+// RUN: %clang -cl-std=CL2.0 -emit-llvm -g -O0 -S -target amdgcn-amd-amdhsa-opencl -mcpu=fiji -o - %s | FileCheck %s
 
 // CHECK-DAG: ![[LOCAL:[0-9]+]] = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef)
 // CHECK-DAG: ![[PRIVATE:[0-9]+]] = !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)
index 37c7469aa180a8d963c77137429af09fb34f87b2..3e54cd5c34a0d9d039c70aa6948cc4338e11daeb 100644 (file)
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 %s -cl-std=CL2.0 -include opencl-c.h -triple amdgcn -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 %s -O0 -cl-std=CL2.0 -include opencl-c.h -triple amdgcn -emit-llvm -o - | FileCheck --check-prefix=NOOPT %s
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -include opencl-c.h -triple amdgcn---opencl -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -O0 -cl-std=CL2.0 -include opencl-c.h -triple amdgcn---opencl -emit-llvm -o - | FileCheck --check-prefix=NOOPT %s
 
 typedef struct {
   private char *p1;
index a19ce2f1ed597d9bb48cd9d0b4be94a6104450e8..fdbae9b531c1e42627d7c99b42446fc30225af26 100644 (file)
@@ -1,5 +1,5 @@
 // REQUIRES: amdgpu-registered-target
-// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -S -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple amdgcn-unknown-unknown-opencl -S -emit-llvm -o - %s | FileCheck %s
 
 #pragma OPENCL EXTENSION cl_khr_fp64 : enable
 
index 1a8105c5207f9223418de474f2135da61395a994..a7c5adfb79d6c2b6d7377555ce1a656a35bca962 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn---opencl %s | FileCheck %s
 // RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn---amdgizcl %s | FileCheck %s -check-prefix=AMDGIZ
 
 struct A {
index ed941e01852d285273d6104bfc19ea50bee6bba7..20f29fe1cd41ce6d3ff9985c06efd7ac621c9314 100644 (file)
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple spir-unknown-unknown -o - | FileCheck --check-prefix=SZ32 %s
 // RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple spir64-unknown-unknown -o - | FileCheck --check-prefix=SZ64 --check-prefix=SZ64ONLY %s
-// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple amdgcn-- -o - | FileCheck --check-prefix=SZ64 --check-prefix=AMDONLY %s
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple amdgcn---opencl -o - | FileCheck --check-prefix=SZ64 --check-prefix=AMDONLY %s
 
 //SZ32: define{{.*}} i32 @test_ptrtoint_private(i8* %x)
 //SZ32: ptrtoint i8* %{{.*}} to i32
index 0e13c61503aaa2f44941ad8f117760d180b524b7..cd959735fe81c9eee70117cbb86ca931779f565e 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fsyntax-only -triple amdgcn -target-cpu verde -S -emit-llvm -o - %s
+// RUN: %clang_cc1 -verify -fsyntax-only -triple amdgcn--opencl -target-cpu verde -S -emit-llvm -o - %s
 // expected-no-diagnostics
 
 // Record lowering was crashing on SI and newer targets, because it
index 1eba64b44c8a08879fbad092db61df4e7ef93dee..b12676fe743771f862a474f75be4f59316ec2ace 100644 (file)
@@ -12,7 +12,9 @@ void kernel foo() {
 
   constant int L1 = 0;
   local int L2;
-  global int L3; // expected-error{{function scope variable cannot be declared in global address space}}
+  global int L3;                              // expected-error{{function scope variable cannot be declared in global address space}}
+  generic int L4;                             // expected-error{{automatic variable qualified with an invalid address space}}
+  __attribute__((address_space(100))) int L5; // expected-error{{automatic variable qualified with an invalid address space}}
 
   extern global int G5;
   extern int G6; // expected-error{{extern variable must reside in global or constant address space}}
index f457cfd1d3f609107c90d242106eb3fa167393b7..e611313b4a70b6700ed1fe3bc82a94ea225444cf 100644 (file)
@@ -13,29 +13,37 @@ void kernel foo(int x) {
   constant int L1 = 0;
   local int L2;
 
-  auto int L3 = 7; // expected-error{{OpenCL version 1.2 does not support the 'auto' storage class specifier}}
-  global int L4;   // expected-error{{function scope variable cannot be declared in global address space}}
-
-  constant int L5 = x; // expected-error {{initializer element is not a compile-time constant}}
-  global int *constant L6 = &G4;
-  private int *constant L7 = &x; // expected-error {{initializer element is not a compile-time constant}}
-  constant int *constant L8 = &L1;
-  local int *constant L9 = &L2; // expected-error {{initializer element is not a compile-time constant}}
+  auto int L3 = 7;                            // expected-error{{OpenCL version 1.2 does not support the 'auto' storage class specifier}}
+  global int L4;                              // expected-error{{function scope variable cannot be declared in global address space}}
+  __attribute__((address_space(100))) int L5; // expected-error{{automatic variable qualified with an invalid address space}}
+
+  constant int L6 = x;                        // expected-error {{initializer element is not a compile-time constant}}
+  global int *constant L7 = &G4;
+  private int *constant L8 = &x;              // expected-error {{initializer element is not a compile-time constant}}
+  constant int *constant L9 = &L1;
+  local int *constant L10 = &L2;              // expected-error {{initializer element is not a compile-time constant}}
 }
 
 static void kernel bar() { // expected-error{{kernel functions cannot be declared static}}
 }
 
 void f() {
-  constant int L1 = 0; // expected-error{{non-kernel function variable cannot be declared in constant address space}}
-  local int L2;        // expected-error{{non-kernel function variable cannot be declared in local address space}}
+  constant int L1 = 0;                        // expected-error{{non-kernel function variable cannot be declared in constant address space}}
+  local int L2;                               // expected-error{{non-kernel function variable cannot be declared in local address space}}
+  global int L3;                              // expected-error{{function scope variable cannot be declared in global address space}}
+  __attribute__((address_space(100))) int L4; // expected-error{{automatic variable qualified with an invalid address space}}
+
   {
-    constant int L1 = 0; // expected-error{{non-kernel function variable cannot be declared in constant address space}}
-    local int L2;        // expected-error{{non-kernel function variable cannot be declared in local address space}}
+    constant int L1 = 0;                        // expected-error{{non-kernel function variable cannot be declared in constant address space}}
+    local int L2;                               // expected-error{{non-kernel function variable cannot be declared in local address space}}
+    global int L3;                              // expected-error{{function scope variable cannot be declared in global address space}}
+    __attribute__((address_space(100))) int L4; // expected-error{{automatic variable qualified with an invalid address space}}
   }
-  global int L3; // expected-error{{function scope variable cannot be declared in global address space}}
-  extern constant float L4;
-  extern local float L5; // expected-error{{extern variable must reside in constant address space}}
-  static int L6 = 0;     // expected-error{{variables in function scope cannot be declared static}}
-  static int L7;         // expected-error{{variables in function scope cannot be declared static}}
+
+
+  extern constant float L5;
+  extern local float L6; // expected-error{{extern variable must reside in constant address space}}
+
+  static int L7 = 0;     // expected-error{{variables in function scope cannot be declared static}}
+  static int L8;         // expected-error{{variables in function scope cannot be declared static}}
 }