Index: clang/lib/Basic/Targets/AMDGPU.h =================================================================== --- clang/lib/Basic/Targets/AMDGPU.h +++ clang/lib/Basic/Targets/AMDGPU.h @@ -355,7 +355,9 @@ // address space has value 0 but in private and local address space has // value ~0. uint64_t getNullPointerValue(LangAS AS) const override { - return AS == LangAS::opencl_local ? ~0 : 0; + // FIXME: Also should handle region. + return (AS == LangAS::opencl_local || AS == LangAS::opencl_private) + ? ~0 : 0; } void setAuxTarget(const TargetInfo *Aux) override; Index: clang/test/CodeGenOpenCL/amdgpu-nullptr.cl =================================================================== --- clang/test/CodeGenOpenCL/amdgpu-nullptr.cl +++ clang/test/CodeGenOpenCL/amdgpu-nullptr.cl @@ -19,7 +19,7 @@ // Test 0 as initializer. -// CHECK: @private_p = local_unnamed_addr addrspace(1) global i8 addrspace(5)* null, align 4 +// CHECK: @private_p = local_unnamed_addr addrspace(1) global i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), align 4 private char *private_p = 0; // CHECK: @local_p = local_unnamed_addr addrspace(1) global i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), align 4 @@ -36,7 +36,7 @@ // Test NULL as initializer. -// CHECK: @private_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(5)* null, align 4 +// CHECK: @private_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), align 4 private char *private_p_NULL = NULL; // CHECK: @local_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), align 4 @@ -57,25 +57,28 @@ // CHECK: @fold_generic = local_unnamed_addr addrspace(1) global i32* null, align 8 generic int *fold_generic = (global int*)(generic float*)(private char*)0; -// CHECK: @fold_priv = local_unnamed_addr addrspace(1) global i16 addrspace(5)* null, align 4 +// CHECK: @fold_priv = local_unnamed_addr addrspace(1) global i16 addrspace(5)* addrspacecast (i16* null to i16 addrspace(5)*), align 4 private short *fold_priv = (private short*)(generic int*)(global void*)0; -// CHECK: @fold_priv_arith = local_unnamed_addr addrspace(1) global i8 addrspace(5)* inttoptr (i32 10 to i8 addrspace(5)*), align 4 +// CHECK: @fold_priv_arith = local_unnamed_addr addrspace(1) global i8 addrspace(5)* inttoptr (i32 9 to i8 addrspace(5)*), align 4 private char *fold_priv_arith = (private char*)0 + 10; -// CHECK: @fold_int = local_unnamed_addr addrspace(1) global i32 14, align 4 +// CHECK: @fold_local_arith = local_unnamed_addr addrspace(1) global i8 addrspace(3)* inttoptr (i32 9 to i8 addrspace(3)*), align 4 +local char *fold_local_arith = (local char*)0 + 10; + +// CHECK: @fold_int = local_unnamed_addr addrspace(1) global i32 13, align 4 int fold_int = (int)(private void*)(generic char*)(global int*)0 + 14; -// CHECK: @fold_int2 = local_unnamed_addr addrspace(1) global i32 13, align 4 +// CHECK: @fold_int2 = local_unnamed_addr addrspace(1) global i32 12, align 4 int fold_int2 = (int) ((private void*)0 + 13); -// CHECK: @fold_int3 = local_unnamed_addr addrspace(1) global i32 0, align 4 +// CHECK: @fold_int3 = local_unnamed_addr addrspace(1) global i32 -1, align 4 int fold_int3 = (int) ((private int*)0); -// CHECK: @fold_int4 = local_unnamed_addr addrspace(1) global i32 8, align 4 +// CHECK: @fold_int4 = local_unnamed_addr addrspace(1) global i32 7, align 4 int fold_int4 = (int) &((private int*)0)[2]; -// CHECK: @fold_int5 = local_unnamed_addr addrspace(1) global i32 4, align 4 +// CHECK: @fold_int5 = local_unnamed_addr addrspace(1) global i32 3, align 4 int fold_int5 = (int) &((private StructTy1*)0)->p2; @@ -97,12 +100,12 @@ // Test static variable initialization. -// NOOPT: @test_static_var_private.sp1 = internal addrspace(1) global i8 addrspace(5)* null, align 4 -// NOOPT: @test_static_var_private.sp2 = internal addrspace(1) global i8 addrspace(5)* null, align 4 -// NOOPT: @test_static_var_private.sp3 = internal addrspace(1) global i8 addrspace(5)* null, align 4 +// NOOPT: @test_static_var_private.sp1 = internal addrspace(1) global i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), align 4 +// NOOPT: @test_static_var_private.sp2 = internal addrspace(1) global i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), align 4 +// NOOPT: @test_static_var_private.sp3 = internal addrspace(1) global i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), align 4 // NOOPT: @test_static_var_private.sp4 = internal addrspace(1) global i8 addrspace(5)* null, align 4 // NOOPT: @test_static_var_private.sp5 = internal addrspace(1) global i8 addrspace(5)* null, align 4 -// NOOPT: @test_static_var_private.SS1 = internal addrspace(1) global %struct.StructTy1 { i8 addrspace(5)* null, i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }, align 8 +// NOOPT: @test_static_var_private.SS1 = internal addrspace(1) global %struct.StructTy1 { i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }, align 8 // NOOPT: @test_static_var_private.SS2 = internal addrspace(1) global %struct.StructTy2 zeroinitializer, align 8 void test_static_var_private(void) { @@ -121,7 +124,7 @@ // NOOPT: @test_static_var_local.sp3 = internal addrspace(1) global i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), align 4 // NOOPT: @test_static_var_local.sp4 = internal addrspace(1) global i8 addrspace(3)* null, align 4 // NOOPT: @test_static_var_local.sp5 = internal addrspace(1) global i8 addrspace(3)* null, align 4 -// NOOPT: @test_static_var_local.SS1 = internal addrspace(1) global %struct.StructTy1 { i8 addrspace(5)* null, i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }, align 8 +// NOOPT: @test_static_var_local.SS1 = internal addrspace(1) global %struct.StructTy1 { i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }, align 8 // NOOPT: @test_static_var_local.SS2 = internal addrspace(1) global %struct.StructTy2 zeroinitializer, align 8 void test_static_var_local(void) { static local char *sp1 = 0; @@ -136,8 +139,8 @@ // Test function-scope variable initialization. // NOOPT-LABEL: @test_func_scope_var_private( -// NOOPT: store i8 addrspace(5)* null, i8 addrspace(5)* addrspace(5)* %sp1, align 4 -// NOOPT: store i8 addrspace(5)* null, i8 addrspace(5)* addrspace(5)* %sp2, align 4 +// NOOPT: store i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(5)* addrspace(5)* %sp1, align 4 +// NOOPT: store i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(5)* addrspace(5)* %sp2, align 4 // NOOPT: store i8 addrspace(5)* null, i8 addrspace(5)* addrspace(5)* %sp3, align 4 // NOOPT: store i8 addrspace(5)* null, i8 addrspace(5)* addrspace(5)* %sp4, align 4 // NOOPT: %[[SS1:.*]] = bitcast %struct.StructTy1 addrspace(5)* %SS1 to i8 addrspace(5)* @@ -181,8 +184,8 @@ // cannot have common linkage since common linkage requires zero initialization // and does not have explicit section. -// CHECK: @p1 = local_unnamed_addr addrspace(1) global i8 addrspace(5)* null, align 4 -// COMMON: @p1 = common local_unnamed_addr addrspace(1) global i8 addrspace(5)* null, align 4 +// CHECK: @p1 = local_unnamed_addr addrspace(1) global i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), align 4 +// COMMON: @p1 = weak local_unnamed_addr addrspace(1) global i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), align 4 private char *p1; // CHECK: @p2 = local_unnamed_addr addrspace(1) global i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), align 4 @@ -203,14 +206,14 @@ // Test default initialization of structure. -// CHECK: @S1 = local_unnamed_addr addrspace(1) global %struct.StructTy1 { i8 addrspace(5)* null, i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }, align 8 +// CHECK: @S1 = local_unnamed_addr addrspace(1) global %struct.StructTy1 { i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }, align 8 StructTy1 S1; // CHECK: @S2 = local_unnamed_addr addrspace(1) global %struct.StructTy2 zeroinitializer, align 8 StructTy2 S2; // Test default initialization of array. -// CHECK: @A1 = local_unnamed_addr addrspace(1) global [2 x %struct.StructTy1] [%struct.StructTy1 { i8 addrspace(5)* null, i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }, %struct.StructTy1 { i8 addrspace(5)* null, i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }], align 8 +// CHECK: @A1 = local_unnamed_addr addrspace(1) global [2 x %struct.StructTy1] [%struct.StructTy1 { i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }, %struct.StructTy1 { i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }], align 8 StructTy1 A1[2]; // CHECK: @A2 = local_unnamed_addr addrspace(1) global [2 x %struct.StructTy2] zeroinitializer, align 8 @@ -219,7 +222,7 @@ // Test comparison with 0. // CHECK-LABEL: cmp_private -// CHECK: icmp eq i8 addrspace(5)* %p, null +// CHECK: icmp eq i8 addrspace(5)* %p, addrspacecast (i8* null to i8 addrspace(5)*) void cmp_private(private char* p) { if (p != 0) *p = 0; @@ -258,7 +261,7 @@ // Test comparison with NULL. // CHECK-LABEL: cmp_NULL_private -// CHECK: icmp eq i8 addrspace(5)* %p, null +// CHECK: icmp eq i8 addrspace(5)* %p, addrspacecast (i8* null to i8 addrspace(5)*) void cmp_NULL_private(private char* p) { if (p != NULL) *p = 0; @@ -296,7 +299,7 @@ // Test storage 0 as null pointer. // CHECK-LABEL: test_storage_null_pointer -// CHECK: store i8 addrspace(5)* null, i8 addrspace(5)** %arg_private +// CHECK: store i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(5)** %arg_private // CHECK: store i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(3)** %arg_local // CHECK: store i8 addrspace(1)* null, i8 addrspace(1)** %arg_global // CHECK: store i8 addrspace(4)* null, i8 addrspace(4)** %arg_constant @@ -315,7 +318,7 @@ // Test storage NULL as null pointer. // CHECK-LABEL: test_storage_null_pointer_NULL -// CHECK: store i8 addrspace(5)* null, i8 addrspace(5)** %arg_private +// CHECK: store i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(5)** %arg_private // CHECK: store i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(3)** %arg_local // CHECK: store i8 addrspace(1)* null, i8 addrspace(1)** %arg_global // CHECK: store i8 addrspace(4)* null, i8 addrspace(4)** %arg_constant @@ -340,8 +343,8 @@ generic char* arg_generic); // CHECK-LABEL: test_pass_null_pointer_arg -// CHECK: call void @test_pass_null_pointer_arg_calee(i8 addrspace(5)* null, i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(1)* null, i8 addrspace(4)* null, i8* null) -// CHECK: call void @test_pass_null_pointer_arg_calee(i8 addrspace(5)* null, i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(1)* null, i8 addrspace(4)* null, i8* null) +// CHECK: call void @test_pass_null_pointer_arg_calee(i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(1)* null, i8 addrspace(4)* null, i8* null) +// CHECK: call void @test_pass_null_pointer_arg_calee(i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(1)* null, i8 addrspace(4)* null, i8* null) void test_pass_null_pointer_arg(void) { test_pass_null_pointer_arg_calee(0, 0, 0, 0, 0); test_pass_null_pointer_arg_calee(NULL, NULL, NULL, NULL, NULL); @@ -355,8 +358,8 @@ size_t arg_generic); // CHECK-LABEL: test_cast_null_pointer_to_sizet -// CHECK: call void @test_cast_null_pointer_to_sizet_calee(i64 0, i64 ptrtoint (i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*) to i64), i64 0, i64 0, i64 0) -// CHECK: call void @test_cast_null_pointer_to_sizet_calee(i64 0, i64 ptrtoint (i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*) to i64), i64 0, i64 0, i64 0) +// CHECK: call void @test_cast_null_pointer_to_sizet_calee(i64 ptrtoint (i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*) to i64), i64 ptrtoint (i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*) to i64), i64 0, i64 0, i64 0) #7 +// CHECK: call void @test_cast_null_pointer_to_sizet_calee(i64 ptrtoint (i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*) to i64), i64 ptrtoint (i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*) to i64), i64 0, i64 0, i64 0) #7 void test_cast_null_pointer_to_sizet(void) { test_cast_null_pointer_to_sizet_calee((size_t)((private char*)0), (size_t)((local char*)0), @@ -468,7 +471,7 @@ // Test cast to bool. // CHECK-LABEL: cast_bool_private -// CHECK: icmp eq i8 addrspace(5)* %p, null +// CHECK: icmp eq i8 addrspace(5)* %p, addrspacecast (i8* null to i8 addrspace(5)*) void cast_bool_private(private char* p) { if (p) *p = 0; @@ -513,7 +516,12 @@ } StructTy3; // CHECK-LABEL: test_memset_private -// CHECK: call void @llvm.memset.p5i8.i64(i8 addrspace(5)* align 8 {{.*}}, i8 0, i64 40, i1 false) +// CHECK: call void @llvm.memset.p5i8.i64(i8 addrspace(5)* align 8 {{.*}}, i8 0, i64 32, i1 false) +// CHECK: [[GEP:%.*]] = getelementptr inbounds %struct.StructTy3, %struct.StructTy3 addrspace(5)* %ptr, i32 0, i32 4 +// CHECK: store i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(5)* addrspace(5)* [[GEP]] +// CHECK: [[GEP1:%.*]] = getelementptr inbounds i8, i8 addrspace(5)* {{.*}}, i32 36 +// CHECK: [[GEP1_CAST:%.*]] = bitcast i8 addrspace(5)* [[GEP1]] to i32 addrspace(5)* +// CHECK: store i32 0, i32 addrspace(5)* [[GEP1_CAST]], align 4 void test_memset_private(private StructTy3 *ptr) { StructTy3 S3 = {0, 0, 0, 0, 0}; *ptr = S3; @@ -529,7 +537,7 @@ } // CHECK-LABEL: test_cast_0_to_private_ptr -// CHECK: ret i32 addrspace(5)* null +// CHECK: ret i32 addrspace(5)* addrspacecast (i32* null to i32 addrspace(5)*) private int* test_cast_0_to_private_ptr(void) { return (private int*)0; } @@ -571,7 +579,7 @@ } // CHECK-LABEL: test_not_private_ptr -// CHECK: %[[lnot:.*]] = icmp eq i8 addrspace(5)* %p, null +// CHECK: %[[lnot:.*]] = icmp eq i8 addrspace(5)* %p, addrspacecast (i8* null to i8 addrspace(5)*) // CHECK: %[[lnot_ext:.*]] = zext i1 %[[lnot]] to i32 // CHECK: ret i32 %[[lnot_ext]] int test_not_private_ptr(private char* p) { @@ -588,7 +596,7 @@ // CHECK-LABEL: test_and_ptr -// CHECK: %[[tobool:.*]] = icmp ne i8 addrspace(5)* %p1, null +// CHECK: %[[tobool:.*]] = icmp ne i8 addrspace(5)* %p1, addrspacecast (i8* null to i8 addrspace(5)*) // CHECK: %[[tobool1:.*]] = icmp ne i8 addrspace(3)* %p2, addrspacecast (i8* null to i8 addrspace(3)*) // CHECK: %[[res:.*]] = and i1 %[[tobool]], %[[tobool1]] // CHECK: %[[land_ext:.*]] = zext i1 %[[res]] to i32 @@ -603,7 +611,7 @@ // NOOPT: store i32 addrspace(1)* null, i32 addrspace(1)* addrspace(5)* %glob, align 8 // NOOPT: %{{.*}} = sub i64 %{{.*}}, 0 // NOOPT: call void @test_fold_callee -// NOOPT: %{{.*}} = add nsw i64 %{{.*}}, 0 +// NOOPT: %{{.*}} = add nsw i64 %1, sext (i32 ptrtoint (i32 addrspace(5)* addrspacecast (i32* null to i32 addrspace(5)*) to i32) to i64) // NOOPT: %{{.*}} = sub nsw i64 %{{.*}}, 1 void test_fold_callee(void); void test_fold_private(void) {