Skip to content

Commit

Permalink
[OpenCL] AMDGCN: Fix size_t type
Browse files Browse the repository at this point in the history
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

llvm-svn: 279121
  • Loading branch information
yxsamliu committed Aug 18, 2016
1 parent 9e60a2a commit 6305f8a
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 9 deletions.
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/TargetInfo.h
Expand Up @@ -294,6 +294,11 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
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; }

Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Basic/TargetInfo.cpp
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets.cpp
Expand Up @@ -2004,6 +2004,10 @@ class AMDGPUTargetInfo final : public TargetInfo {
}
}

uint64_t getMaxPointerWidth() const override {
return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32;
}

const char * getClobbers() const override {
return "";
}
Expand Down
15 changes: 9 additions & 6 deletions clang/lib/CodeGen/CGExprScalar.cpp
Expand Up @@ -787,15 +787,15 @@ 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");

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");
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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();

Expand All @@ -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");
}

Expand Down
5 changes: 4 additions & 1 deletion clang/lib/CodeGen/CodeGenModule.cpp
Expand Up @@ -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);

Expand Down
5 changes: 5 additions & 0 deletions clang/lib/CodeGen/CodeGenTypeCache.h
Expand Up @@ -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);
}
Expand Down
110 changes: 110 additions & 0 deletions clang/test/CodeGenOpenCL/size_t.cl
@@ -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;
}

0 comments on commit 6305f8a

Please sign in to comment.