]> granicus.if.org Git - clang/commitdiff
[OpenCL] AMDGCN: Fix size_t type
authorYaxun Liu <Yaxun.Liu@amd.com>
Thu, 18 Aug 2016 19:34:04 +0000 (19:34 +0000)
committerYaxun Liu <Yaxun.Liu@amd.com>
Thu, 18 Aug 2016 19:34:04 +0000 (19:34 +0000)
Pointers of certain GPUs in AMDGCN target in private address space is 32 bit but pointers in other address spaces are 64 bit. size_t type should be defined as 64 bit for these GPUs so that it could hold pointers in all address spaces. Also fixed issues in pointer arithmetic codegen by using pointer specific intptr type.

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

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

include/clang/Basic/TargetInfo.h
lib/Basic/TargetInfo.cpp
lib/Basic/Targets.cpp
lib/CodeGen/CGExprScalar.cpp
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenTypeCache.h
test/CodeGenOpenCL/size_t.cl [new file with mode: 0644]

index a9378f83afd365ea5f26bd2a5df44b1937e15636..de94cdacd2cb723f33d1135d8d505fed8da75f8f 100644 (file)
@@ -294,6 +294,11 @@ public:
     return AddrSpace == 0 ? PointerAlign : getPointerAlignV(AddrSpace);
   }
 
+  /// \brief Return the maximum width of pointers on this target.
+  virtual uint64_t getMaxPointerWidth() const {
+    return PointerWidth;
+  }
+
   /// \brief Return the size of '_Bool' and C++ 'bool' for this target, in bits.
   unsigned getBoolWidth() const { return BoolWidth; }
 
index dec8b7cda4ecab0dac87e98b1221138b124a142a..592b877fadd64860a6294308441b444e9b28f47b 100644 (file)
@@ -306,8 +306,9 @@ void TargetInfo::adjust(const LangOptions &Opts) {
     }
     LongDoubleWidth = LongDoubleAlign = 128;
 
-    assert(PointerWidth == 32 || PointerWidth == 64);
-    bool Is32BitArch = PointerWidth == 32;
+    unsigned MaxPointerWidth = getMaxPointerWidth();
+    assert(MaxPointerWidth == 32 || MaxPointerWidth == 64);
+    bool Is32BitArch = MaxPointerWidth == 32;
     SizeType = Is32BitArch ? UnsignedInt : UnsignedLong;
     PtrDiffType = Is32BitArch ? SignedInt : SignedLong;
     IntPtrType = Is32BitArch ? SignedInt : SignedLong;
index 793b25e928798473948ed961e2f6070253a1e03d..36e6d4594fa0e4ff465458a719e70666e2ad6c59 100644 (file)
@@ -2004,6 +2004,10 @@ public:
     }
   }
 
+  uint64_t getMaxPointerWidth() const override {
+    return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32;
+  }
+
   const char * getClobbers() const override {
     return "";
   }
index ba7f49b750b2091533246d37f5cfabd593cc7686..0af4c418165fe112c44f7e9338a2e00df8dee8c3 100644 (file)
@@ -787,7 +787,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
   // Handle pointer conversions next: pointers can only be converted to/from
   // other pointers and integers. Check for pointer types in terms of LLVM, as
   // some native types (like Obj-C id) may map to a pointer type.
-  if (isa<llvm::PointerType>(DstTy)) {
+  if (auto DstPT = dyn_cast<llvm::PointerType>(DstTy)) {
     // The source value may be an integer, or a pointer.
     if (isa<llvm::PointerType>(SrcTy))
       return Builder.CreateBitCast(Src, DstTy, "conv");
@@ -795,7 +795,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
     assert(SrcType->isIntegerType() && "Not ptr->ptr or int->ptr conversion?");
     // First, convert to the correct width so that we control the kind of
     // extension.
-    llvm::Type *MiddleTy = CGF.IntPtrTy;
+    llvm::Type *MiddleTy = CGF.CGM.getDataLayout().getIntPtrType(DstPT);
     bool InputSigned = SrcType->isSignedIntegerOrEnumerationType();
     llvm::Value* IntResult =
         Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv");
@@ -1510,12 +1510,13 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
 
     // First, convert to the correct width so that we control the kind of
     // extension.
-    llvm::Type *MiddleTy = CGF.IntPtrTy;
+    auto DestLLVMTy = ConvertType(DestTy);
+    llvm::Type *MiddleTy = CGF.CGM.getDataLayout().getIntPtrType(DestLLVMTy);
     bool InputSigned = E->getType()->isSignedIntegerOrEnumerationType();
     llvm::Value* IntResult =
       Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv");
 
-    return Builder.CreateIntToPtr(IntResult, ConvertType(DestTy));
+    return Builder.CreateIntToPtr(IntResult, DestLLVMTy);
   }
   case CK_PointerToIntegral:
     assert(!DestTy->isBooleanType() && "bool should use PointerToBool");
@@ -2426,6 +2427,7 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
 
   Value *pointer = op.LHS;
   Expr *pointerOperand = expr->getLHS();
+  auto PtrTy = cast<llvm::PointerType>(pointer->getType());
   Value *index = op.RHS;
   Expr *indexOperand = expr->getRHS();
 
@@ -2436,11 +2438,12 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
   }
 
   unsigned width = cast<llvm::IntegerType>(index->getType())->getBitWidth();
-  if (width != CGF.PointerWidthInBits) {
+  auto &DL = CGF.CGM.getDataLayout();
+  if (width != DL.getTypeSizeInBits(PtrTy)) {
     // Zero-extend or sign-extend the pointer value according to
     // whether the index is signed or not.
     bool isSigned = indexOperand->getType()->isSignedIntegerOrEnumerationType();
-    index = CGF.Builder.CreateIntCast(index, CGF.PtrDiffTy, isSigned,
+    index = CGF.Builder.CreateIntCast(index, DL.getIntPtrType(PtrTy), isSigned,
                                       "idx.ext");
   }
 
index 2dcccf4c6c82939f47a9b2eb909d68b4d44b5972..1d74e4cd83831e6d3fb4aa94089dab1e2d53916f 100644 (file)
@@ -101,10 +101,13 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
   PointerWidthInBits = C.getTargetInfo().getPointerWidth(0);
   PointerAlignInBytes =
     C.toCharUnitsFromBits(C.getTargetInfo().getPointerAlign(0)).getQuantity();
+  SizeSizeInBytes =
+    C.toCharUnitsFromBits(C.getTargetInfo().getMaxPointerWidth()).getQuantity();
   IntAlignInBytes =
     C.toCharUnitsFromBits(C.getTargetInfo().getIntAlign()).getQuantity();
   IntTy = llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getIntWidth());
-  IntPtrTy = llvm::IntegerType::get(LLVMContext, PointerWidthInBits);
+  IntPtrTy = llvm::IntegerType::get(LLVMContext,
+    C.getTargetInfo().getMaxPointerWidth());
   Int8PtrTy = Int8Ty->getPointerTo(0);
   Int8PtrPtrTy = Int8PtrTy->getPointerTo(0);
 
index c32b66d129da10f49439aa7bea4dc30d94944bed..47e26bcaa1b68655faf5df9446cebfa9964076d9 100644 (file)
@@ -80,9 +80,14 @@ struct CodeGenTypeCache {
   union {
     unsigned char PointerAlignInBytes;
     unsigned char PointerSizeInBytes;
+  };
+
+  /// The size and alignment of size_t.
+  union {
     unsigned char SizeSizeInBytes; // sizeof(size_t)
     unsigned char SizeAlignInBytes;
   };
+
   CharUnits getSizeSize() const {
     return CharUnits::fromQuantity(SizeSizeInBytes);
   }
diff --git a/test/CodeGenOpenCL/size_t.cl b/test/CodeGenOpenCL/size_t.cl
new file mode 100644 (file)
index 0000000..ed941e0
--- /dev/null
@@ -0,0 +1,110 @@
+// 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
+
+//SZ32: define{{.*}} i32 @test_ptrtoint_private(i8* %x)
+//SZ32: ptrtoint i8* %{{.*}} to i32
+//SZ64: define{{.*}} i64 @test_ptrtoint_private(i8* %x)
+//SZ64: ptrtoint i8* %{{.*}} to i64
+size_t test_ptrtoint_private(private char* x) {
+  return (size_t)x;
+}
+
+//SZ32: define{{.*}} i32 @test_ptrtoint_global(i8 addrspace(1)* %x)
+//SZ32: ptrtoint i8 addrspace(1)* %{{.*}} to i32
+//SZ64: define{{.*}} i64 @test_ptrtoint_global(i8 addrspace(1)* %x)
+//SZ64: ptrtoint i8 addrspace(1)* %{{.*}} to i64
+intptr_t test_ptrtoint_global(global char* x) {
+  return (intptr_t)x;
+}
+
+//SZ32: define{{.*}} i32 @test_ptrtoint_constant(i8 addrspace(2)* %x)
+//SZ32: ptrtoint i8 addrspace(2)* %{{.*}} to i32
+//SZ64: define{{.*}} i64 @test_ptrtoint_constant(i8 addrspace(2)* %x)
+//SZ64: ptrtoint i8 addrspace(2)* %{{.*}} to i64
+uintptr_t test_ptrtoint_constant(constant char* x) {
+  return (uintptr_t)x;
+}
+
+//SZ32: define{{.*}} i32 @test_ptrtoint_local(i8 addrspace(3)* %x)
+//SZ32: ptrtoint i8 addrspace(3)* %{{.*}} to i32
+//SZ64: define{{.*}} i64 @test_ptrtoint_local(i8 addrspace(3)* %x)
+//SZ64: ptrtoint i8 addrspace(3)* %{{.*}} to i64
+size_t test_ptrtoint_local(local char* x) {
+  return (size_t)x;
+}
+
+//SZ32: define{{.*}} i32 @test_ptrtoint_generic(i8 addrspace(4)* %x)
+//SZ32: ptrtoint i8 addrspace(4)* %{{.*}} to i32
+//SZ64: define{{.*}} i64 @test_ptrtoint_generic(i8 addrspace(4)* %x)
+//SZ64: ptrtoint i8 addrspace(4)* %{{.*}} to i64
+size_t test_ptrtoint_generic(generic char* x) {
+  return (size_t)x;
+}
+
+//SZ32: define{{.*}} i8* @test_inttoptr_private(i32 %x)
+//SZ32: inttoptr i32 %{{.*}} to i8*
+//SZ64: define{{.*}} i8* @test_inttoptr_private(i64 %x)
+//AMDONLY: trunc i64 %{{.*}} to i32
+//AMDONLY: inttoptr i32 %{{.*}} to i8*
+//SZ64ONLY: inttoptr i64 %{{.*}} to i8*
+private char* test_inttoptr_private(size_t x) {
+  return (private char*)x;
+}
+
+//SZ32: define{{.*}} i8 addrspace(1)* @test_inttoptr_global(i32 %x)
+//SZ32: inttoptr i32 %{{.*}} to i8 addrspace(1)*
+//SZ64: define{{.*}} i8 addrspace(1)* @test_inttoptr_global(i64 %x)
+//SZ64: inttoptr i64 %{{.*}} to i8 addrspace(1)*
+global char* test_inttoptr_global(size_t x) {
+  return (global char*)x;
+}
+
+//SZ32: define{{.*}} i8 addrspace(3)* @test_add_local(i8 addrspace(3)* %x, i32 %y)
+//SZ32: getelementptr inbounds i8, i8 addrspace(3)* %{{.*}}, i32
+//SZ64: define{{.*}} i8 addrspace(3)* @test_add_local(i8 addrspace(3)* %x, i64 %y)
+//AMDONLY: trunc i64 %{{.*}} to i32
+//AMDONLY: getelementptr inbounds i8, i8 addrspace(3)* %{{.*}}, i32
+//SZ64ONLY: getelementptr inbounds i8, i8 addrspace(3)* %{{.*}}, i64
+local char* test_add_local(local char* x, ptrdiff_t y) {
+  return x + y;
+}
+
+//SZ32: define{{.*}} i8 addrspace(1)* @test_add_global(i8 addrspace(1)* %x, i32 %y)
+//SZ32: getelementptr inbounds i8, i8 addrspace(1)* %{{.*}}, i32
+//SZ64: define{{.*}} i8 addrspace(1)* @test_add_global(i8 addrspace(1)* %x, i64 %y)
+//SZ64: getelementptr inbounds i8, i8 addrspace(1)* %{{.*}}, i64
+global char* test_add_global(global char* x, ptrdiff_t y) {
+  return x + y;
+}
+
+//SZ32: define{{.*}} i32 @test_sub_local(i8 addrspace(3)* %x, i8 addrspace(3)* %y)
+//SZ32: ptrtoint i8 addrspace(3)* %{{.*}} to i32
+//SZ32: ptrtoint i8 addrspace(3)* %{{.*}} to i32
+//SZ64: define{{.*}} i64 @test_sub_local(i8 addrspace(3)* %x, i8 addrspace(3)* %y)
+//SZ64: ptrtoint i8 addrspace(3)* %{{.*}} to i64
+//SZ64: ptrtoint i8 addrspace(3)* %{{.*}} to i64
+ptrdiff_t test_sub_local(local char* x, local char *y) {
+  return x - y;
+}
+
+//SZ32: define{{.*}} i32 @test_sub_private(i8* %x, i8* %y)
+//SZ32: ptrtoint i8* %{{.*}} to i32
+//SZ32: ptrtoint i8* %{{.*}} to i32
+//SZ64: define{{.*}} i64 @test_sub_private(i8* %x, i8* %y)
+//SZ64: ptrtoint i8* %{{.*}} to i64
+//SZ64: ptrtoint i8* %{{.*}} to i64
+ptrdiff_t test_sub_private(private char* x, private char *y) {
+  return x - y;
+}
+
+//SZ32: define{{.*}} i32 @test_sub_mix(i8* %x, i8 addrspace(4)* %y)
+//SZ32: ptrtoint i8* %{{.*}} to i32
+//SZ32: ptrtoint i8 addrspace(4)* %{{.*}} to i32
+//SZ64: define{{.*}} i64 @test_sub_mix(i8* %x, i8 addrspace(4)* %y)
+//SZ64: ptrtoint i8* %{{.*}} to i64
+//SZ64: ptrtoint i8 addrspace(4)* %{{.*}} to i64
+ptrdiff_t test_sub_mix(private char* x, generic char *y) {
+  return x - y;
+}
+