This is an archive of the discontinued LLVM Phabricator instance.

[OpenCL] Add LangAS::opencl_private to represent private address space in AST
ClosedPublic

Authored by yaxunl on Jul 6 2017, 12:42 PM.

Details

Summary

Currently Clang uses default address space (0) to represent private address space for OpenCL
in AST. There are two issues with this:

  1. Multiple address spaces including private address space cannot be diagnosed.
  1. There is no mangling for default address space. For example, if private int* is emitted as

i32 addrspace(5)* in IR. It is supposed to be mangled as PUAS5i but it is mangled as
Pi instead.

This patch attempts to represent OpenCL private address space explicitly in AST. It adds
a new enum LangAS::opencl_private and adds it to the variable types which are implicitly
private:

automatic variables without address space qualifier

function parameter

pointee type without address space qualifier (OpenCL 1.2 and below)

For printing and semantic check of implicit addr space, there is another patch https://reviews.llvm.org/D38857

Diff Detail

Repository
rL LLVM

Event Timeline

yaxunl created this revision.Jul 6 2017, 12:42 PM
yaxunl updated this revision to Diff 105733.Jul 7 2017, 10:41 PM
yaxunl edited the summary of this revision. (Show Details)

Add private address space qualifier to automatic variable and function parameter. Update sema tests.

ToDo: drop address space when converting l-value to r-value.

yaxunl updated this revision to Diff 105774.Jul 9 2017, 7:25 AM
yaxunl retitled this revision from [WIP][OpenCL] Add LangAS::opencl_private to represent private address space in AST to [OpenCL] Add LangAS::opencl_private to represent private address space in AST.
yaxunl edited the summary of this revision. (Show Details)

Update lit tests.

It is essentially done. Clang already drops all qualifiers when converting l-value to r-value.

The only missing part is to let Clang treat (void*)0 as a generic null pointer for OpenCL 1.2 and below since now it is a pointer to private address space.

yaxunl updated this revision to Diff 105785.Jul 9 2017, 10:48 AM

Treat (void*)0 as null pointer for OpenCL 1.2. Rebase to ToT.

bader accepted this revision.Jul 11 2017, 3:41 AM

LGTM, thanks.

This revision is now accepted and ready to land.Jul 11 2017, 3:41 AM
Anastasia added inline comments.Jul 12 2017, 11:16 AM
lib/AST/Expr.cpp
3235 ↗(On Diff #105785)

Would we still be accepting the following:

global int * ptr = (global void*)0;
lib/Sema/SemaDecl.cpp
7964 ↗(On Diff #105785)

Could we use LangAS::Default instead?

11846 ↗(On Diff #105785)

Could we use LangAS::Default here too?

11851 ↗(On Diff #105785)

Would it be better to lift this into if condition of line 11846?

lib/Sema/SemaType.cpp
6969 ↗(On Diff #105785)

Would it be nicer to not append any address space at all neither here nor down at the end of this function and keep it default instead until the Codegen? If it's doable I would very much prefer that. It seems like it would make the implementation potentially a bit cleaner to understand and easier to improve semantical analysis. See one example of improving original type printing in my comment to the test below.

Also there are at least these 3 related bugs open currently:
https://bugs.llvm.org//show_bug.cgi?id=33418
https://bugs.llvm.org//show_bug.cgi?id=33419
https://bugs.llvm.org//show_bug.cgi?id=33420

Does your change address any of those?

test/SemaOpenCL/access-qualifier.cl
23 ↗(On Diff #105785)

Ok, I think that here it would be less confusing not to add any address space since it's missing in the original source.

yaxunl marked 6 inline comments as done.Jul 13 2017, 11:59 AM
yaxunl added inline comments.
lib/AST/Expr.cpp
3235 ↗(On Diff #105785)

Yes. There is a test SemaOpenCL/null_literal.cl

lib/Sema/SemaDecl.cpp
7964 ↗(On Diff #105785)

done

11846 ↗(On Diff #105785)

done

11851 ↗(On Diff #105785)

will do.

lib/Sema/SemaType.cpp
6969 ↗(On Diff #105785)

On the contrary, I think using default address space for automatic variable and function parameter will cause ambiguity and inconsistency in AST, making it more difficult to understand and process, and making some bug (e.g. https://bugs.llvm.org//show_bug.cgi?id=33419) unfixable. For example, private int f(void) and int f(void) will be identical in AST, therefore we cannot diagnose private int f(void).

With current representation I am able to fix the 3 bugs. I will update the diff.

test/SemaOpenCL/access-qualifier.cl
23 ↗(On Diff #105785)

Although it looks strange at first sight, __private __read_write image1d_t is the true type of the argument. The function argument is allocated from stack and is an l-value. If we take its address, we get a private pointer.

yaxunl updated this revision to Diff 106486.Jul 13 2017, 12:07 PM
yaxunl marked 6 inline comments as done.

Revised by Anastasia's comments.

Anastasia added inline comments.Jul 19 2017, 8:41 AM
lib/Sema/SemaDecl.cpp
11846 ↗(On Diff #105785)

Sorry, I wasn't clear. I think we could have:

if (T.getAddressSpace() != LangAS::Default && T.getAddressSpace() != LangAS::opencl_private)

and then original condition. It is a bit clearer I think.

lib/Sema/SemaType.cpp
6969 ↗(On Diff #105785)

I don't see why?

private int f(void) -> will have an address space attribute in AST as it is provided explicitly.

int f(void) -> will have no address space attribute because it's not provided explicitly and not attached implicitly either.

All I was asking is not to deduce the address space here if it's not specified explicitly until later step when we need to put it in the IR.

test/SemaOpenCL/access-qualifier.cl
23 ↗(On Diff #105785)

Yes, it is a true type in the Clang internal representation indeed, but not in the original source though. Here we are giving the feedback about the source code so it's nicer to keep it as close to the original as possible. But we are doing similar "magic" for blocks, images and other places, so it's not that critical at the end. Just if it can be avoided it would be better.

yaxunl marked 6 inline comments as done.Jul 19 2017, 12:36 PM
yaxunl added inline comments.
lib/Sema/SemaDecl.cpp
11846 ↗(On Diff #105785)

No. For OpenCL, the condition is on line 11847 and 11848. An array type in other address spaces is allowed.

lib/Sema/SemaType.cpp
6969 ↗(On Diff #105785)

Clang already deduce global and generic address spaces and use them in the diagnostic messages. I don't see why we can use deduced global and generic address space in diagnostics whereas cannot use deduced private address space in diagnostics. Why users can accept deduced global and generic address spaces but cannot accept deduced private address space?

Automatic variables and function parameters have private address space. This is the reality and as true as a global variable has global or constant address spaces. Not using private address space in diagnostics gives user illusion that automatic variables and function parameters do not have address space, which is not true.

Besides, allowing default address space to represent private address space in AST causes ambiguity in AST. Instead of just check if a type has private address space, now we need to check if a type has private or default address spaces. Also if an expression has default address space, it is not clear if it is an l-value or r-value. This will complicate semantic checking unnecessarily. Also I am not sure if it is acceptable to modify AST between Sema and CodeGen since it seems to change the paradigm of how clang does Sema/CodeGen now.

Anastasia added inline comments.Jul 20 2017, 8:00 AM
lib/Sema/SemaDecl.cpp
11846 ↗(On Diff #105785)

I think the initial condition was T.getAddressSpace() != 0 i.e. if not private address space.

So now since we added private this should be T.getAddressSpace() !=LangAS::opencl_private but we can have the default case as well hence 'T.getAddressSpace() !=LangAS::opencl_private || T.getAddressSpace() !=LangAS::Default'.

This entire case seems to be for OpenCL anyways. So you could also move out the OpenCL check if you prefer. I am just trying to see if we can make this easier to understand.

lib/Sema/SemaType.cpp
6969 ↗(On Diff #105785)

Clang already deduce global and generic address spaces and use them in the diagnostic messages. I don't see why we can use deduced global and generic address space in diagnostics whereas cannot use deduced private address space in diagnostics. Why users can accept deduced global and generic address spaces but cannot accept deduced private address space?

Yes, we did this initially as a workaround because there was no way to distinguish the private and default address space. So now since we are adding the private AS explicitly, it would be nice to remove the workaround if that's possible. It's just a messy code which is hard to understand and we had places in which we need to know if the address space was specified explicitly or now. NULL pointer is one of them. There were also bugs associated to this because it wasn't expected that the address space is 'magically' attached during parsing. Even though most of the things are solved now... I would prefer not to deduce any attributes at this place not just private but global and default as well...

Besides, allowing default address space to represent private address space in AST causes ambiguity in AST. Instead of just check if a type has private address space, now we need to check if a type has private or default address spaces.

I don't see any ambiguity, this is a difference in OpenCL wrt C that we have implicit address space which we have to handle in the compiler too. The question is what's the best place to loose the information about default address space... so we first went for removing it early in parsing but there were a number of issues for example NULL couldn't be handled properly and some other bugs. The original source couldn't be printed back the same way. I personally find the current solution a bit hacky because this function was just supposed to simply parse the attribute and not to add bits that don't exist in the original source code. Therefore, the code is overcomplicated because we are trying to get some extra information about Declarator properties which this function shouldn't really touch.

Once again I have never said it is wrong to add private address space to those objects, just it will be cleaner in my view if we don't do it at this stage. If it's too difficult to do it differently (e.g too big of the change) I am OK to accept this solution. But if it's possible to do it later, I would prefer to keep default address space with no address space attribute until the last point where we generate the IR.

Also if an expression has default address space, it is not clear if it is an l-value or r-value. This will complicate semantic checking unnecessarily. Also I am not sure if it is acceptable to modify AST between Sema and CodeGen since it seems to change the paradigm of how clang does Sema/CodeGen now.

Could you please elaborate what is the difficulty here?

yaxunl marked 2 inline comments as done.Aug 17 2017, 8:53 AM
yaxunl added inline comments.
lib/Sema/SemaType.cpp
6969 ↗(On Diff #105785)

Address space is a type qualifier applies to all expressions, not just variables. Using default address space in AST means that the real address space of any expression will depend on the context and needs to be evaluated whenever it is needed for semantic checking, which may result in lots of changes in Sema.

Since most semantic checking uses the real address space, it is more efficient to use real address space in AST.

The only semantic checking that requires to know the original default address space seems to be (void*)0 for OpenCL 1.2 since by OpenCL spec it should be a private pointer but by convention it is treated as null pointer. It does not make sense to use default address space in AST just for this one special case. I think we should be able to handle it through some other approach.

John, do you have any comments? Thanks.

rjmccall edited edge metadata.Aug 17 2017, 12:01 PM

The meaning we've agreed on for LangAS::Default is to be the address space of local declarations, which corresponds quite well to __private in OpenCL. I think your concern about diagnostics is better addressed by changing the pretty-printer than by changing Sema to give all local declarations qualified type.

The meaning we've agreed on for LangAS::Default is to be the address space of local declarations, which corresponds quite well to __private in OpenCL. I think your concern about diagnostics is better addressed by changing the pretty-printer than by changing Sema to give all local declarations qualified type.

How about adding a ImplicitAddrSpace bit to Qualifier to indicate address space is implicit, then does not print the address space qualifier in AST printer if the bit is set.

Well, we don't currently have a concept of a non-canonical qualifier, but I think it probably wouldn't be difficult to support; you would just need ASTContext::getQualifiedType to be aware of it.

yaxunl updated this revision to Diff 112288.Aug 22 2017, 8:03 PM
yaxunl edited the summary of this revision. (Show Details)

Add a flag to indicate whether address space qualifier is implicit and only print explicit address space in diagnostics.

yaxunl marked 6 inline comments as done.Aug 22 2017, 8:20 PM
yaxunl added inline comments.
lib/Sema/SemaDecl.cpp
11846 ↗(On Diff #105785)

This is not just for OpenCL.

The condition expresses the following logic:

For non-OpenCL languages, only default addr space is allowed on function argument.

For OpenCL, for array type argument, any addr space is allowed; for non-array type argument, only private addr space is allowed.

rjmccall added inline comments.Aug 22 2017, 8:44 PM
lib/Sema/SemaDecl.cpp
11846 ↗(On Diff #105785)

Parameters declared with type 'foo T[]' will be canonicalized to 'foo T*' when forming the function type, so that's not actually a different rule in the end.

yaxunl marked an inline comment as done.Sep 5 2017, 5:35 PM

ping

Anastasia added inline comments.Sep 7 2017, 7:50 AM
include/clang/AST/Type.h
332 ↗(On Diff #112288)

Could we add a bit of comment somewhere explaining why we added implicit AS flag please.

lib/AST/Expr.cpp
3254 ↗(On Diff #112288)

Is this comment right wrt to named address spaces. So is (private void*)0 not a nullptr?

3257 ↗(On Diff #112288)

Can we now simplify this by checking implicit AS bit instead?

lib/Sema/SemaType.cpp
6974 ↗(On Diff #112288)

I am not very convinced we need to do all this check really... I think since we have to live with this code further and maintain it let's try to simplify it a bit. This can also help us avoid redundant checks. Perhaps we could even move it out in a separate function?

How about some sort of hierarchical check structure like:

CL version?
<2.0>=2.0
privateType?
pointernon-pointer
genericScope?
programfunction
globalQualifiers?
nonestatic/extern
privateglobal
6994 ↗(On Diff #112288)

The generic address space -> The default address space

yaxunl marked 6 inline comments as done.Sep 8 2017, 3:34 AM
yaxunl added inline comments.
include/clang/AST/Type.h
332 ↗(On Diff #112288)

Will do.

lib/AST/Expr.cpp
3254 ↗(On Diff #112288)

Yes this will be true.

Neither (private void*)0 nor (__generic void*)0 should be treated nullptr since they cannot be assigned to a constant pointer.

This need some change below to check implicity of the address space. I will do that. Also add more tests about this.

lib/Sema/SemaType.cpp
6994 ↗(On Diff #112288)

'The generic address space name for arguments' is literally from the OpenCL 1.2 spec. Note it refers 'generic address space name', which is not the 'generic address space' defined by OpenCL 2.0 spec.

yaxunl updated this revision to Diff 114337.Sep 8 2017, 3:44 AM
yaxunl marked 3 inline comments as done.
yaxunl edited the summary of this revision. (Show Details)

Add comments for getImplicitAddressSpaceFlag and fix checking of null pointer.

Anastasia added inline comments.Sep 8 2017, 8:20 AM
lib/Sema/SemaType.cpp
6994 ↗(On Diff #112288)

True, but this spec was written before v2.0 was released. And I feel now it makes things confusing considering that we have v2.0 implementation too.

yaxunl marked 2 inline comments as done.Sep 8 2017, 8:25 AM
yaxunl added inline comments.
lib/Sema/SemaType.cpp
6994 ↗(On Diff #112288)

I can make the change. I just feel a little bit uneasy since this looks like a citation but actually is rephrased.

Anastasia added inline comments.Sep 8 2017, 9:49 AM
lib/Sema/SemaType.cpp
6994 ↗(On Diff #112288)

Cool! Thanks!

yaxunl updated this revision to Diff 116704.Sep 26 2017, 1:38 PM
yaxunl marked 5 inline comments as done.

Rebase to ToT and clean up logic.

yaxunl marked an inline comment as done.Sep 26 2017, 1:41 PM
yaxunl added inline comments.
lib/Sema/SemaType.cpp
6974 ↗(On Diff #112288)

fixed.

Anastasia added inline comments.Sep 27 2017, 9:28 AM
lib/Sema/SemaType.cpp
6808 ↗(On Diff #116704)

Great! This looks so clear now!

6810 ↗(On Diff #116704)

I think this could be checked before calling the function.

6863 ↗(On Diff #116704)

Do we cover extern too?

6872 ↗(On Diff #116704)

I think we can't have this case for CL1.2 see s6.8. But I think it could happen for extern though.

yaxunl marked 5 inline comments as done.Sep 28 2017, 9:05 AM
yaxunl added inline comments.
lib/Sema/SemaType.cpp
6810 ↗(On Diff #116704)

will do.

6863 ↗(On Diff #116704)

will add.

6872 ↗(On Diff #116704)

Right. I will remove setting implicit addr space for static var for CL1.2.

For extern var, for CL2.0 I will set implicit addr space to global.

However, for CL1.2 since only constant addr space is supported for file-scope var, I can only set the implicit addr space of an extern var to be constant. However I feel this may cause more confusion than convenience, therefore I will not set implicit addr space for extern var for CL1.2. If user does not use constant addr space with extern var explicitly, they will see diagnostics that extern var must have constant addr space. This is also the current behavior before my change.

yaxunl updated this revision to Diff 117020.Sep 28 2017, 10:49 AM
yaxunl marked 3 inline comments as done.

Revised by Anastasia's comments.

Why is most of this patch necessary under the design of adding a non-canonical __private address space?

include/clang/AST/Type.h
336 ↗(On Diff #117020)

isAddressSpaceImplicit()

337 ↗(On Diff #117020)

setAddressSpaceImplicit

lib/AST/ItaniumMangle.cpp
2232 ↗(On Diff #117020)

In what situation is this mangled? I thought we agree this was non-canonical.

Anastasia added inline comments.Oct 4 2017, 9:57 AM
lib/Sema/SemaType.cpp
6872 ↗(On Diff #116704)

Makes sense!

test/SemaOpenCL/storageclass.cl
63 ↗(On Diff #117020)

Does it make sense to put different address spaces here since this code is rejected earlier anyway?

yaxunl updated this revision to Diff 117770.Oct 4 2017, 6:23 PM
yaxunl marked 9 inline comments as done.

Revised by John's comments.

yaxunl added a comment.Oct 4 2017, 6:30 PM

Why is most of this patch necessary under the design of adding a non-canonical __private address space?

There are two reasons that we need a flag to indicate an address space is simplicit:

  1. We need a consistent way to print the address space qualifier depending on whether it is implicit or not.

We only print address space qualifier when it is explicit. This is not just for private address space. It is for all
address spaces.

  1. In some rare situations we need to know whether an address space is implicit when doing the semantic

checking.

Since the implicit property is per address space qualifier, we need this flag to be on the qualifier.

include/clang/AST/Type.h
336 ↗(On Diff #117020)

Will change.

337 ↗(On Diff #117020)

Will change.

lib/AST/ItaniumMangle.cpp
2232 ↗(On Diff #117020)

OpenCL has overloaded builtin functions, e.g. __attribute__((overloadable)) void f(private int*) and __attribute__((overloadable)) void f(global int*). These functions need to be mangled so that the mangled names are different.

test/SemaOpenCL/storageclass.cl
63 ↗(On Diff #117020)

In Sema I saw code handling different address spaces in various places. I want to make sure that all address spaces are handled correctly.

Are you sure it's a good idea to not print the address space when it's implicit? Won't that often lead to really confusing diagnostics?

Also, we do already have a way of expressing that an extended qualifier was explicit: AttributedType. We have very similar sorts of superficial well-formedness checks to what I think you're trying to do in ObjC ARC.

yaxunl added a comment.Oct 5 2017, 8:15 AM

Are you sure it's a good idea to not print the address space when it's implicit? Won't that often lead to really confusing diagnostics?

Also, we do already have a way of expressing that an extended qualifier was explicit: AttributedType. We have very similar sorts of superficial well-formedness checks to what I think you're trying to do in ObjC ARC.

Based on my observation, in most cases it is OK not to print the implicit address space, and printing implicit address space could cause quite annoying cluttering. In some cases printing implicit address space may be desired. I can improve the printing in some future patch, e.g. only hide the implicit address space in situations which causes cluttering but not providing much useful information.

I think AttributedType sounds an interesting idea and worth exploring.

I just felt this review dragged too long (~ 3 months) already. We have an important backend change depending on this feature. Since the current solution achieves its goals already, can we leave re-implementing it by AttributedType for the future? Thanks.

You have an important backend change relying on being able to preserve type sugar better in diagnostics? The only apparent semantic change in this patch is that you're changing the mangling, which frankly seems incorrect.

yaxunl added a comment.Oct 5 2017, 8:25 PM

You have an important backend change relying on being able to preserve type sugar better in diagnostics? The only apparent semantic change in this patch is that you're changing the mangling, which frankly seems incorrect.

Can you elaborate on why the mangling is incorrect?

Non-canonical information is not supposed to be mangled.

It's not clear to me what the language rule you're really trying to implement is. Maybe you really do need a canonical __private address space, in which case you are going to have to change a lot of code in Sema to add the address space qualifier to every local and temporary allocation. But that's not obvious to me yet, because you haven't really explained why it needs to be explicit in the representation.

If you just want pointers to private to be mangled with an address-space qualifier — meaning I guess that the mangling e.g. Pi will be completely unused — that should be easy enough to handle in the mangler. But if you need to distinguish between private-qualified types and unqualified types, and that distinction isn't purely to implement some syntactic restriction about not writing e.g. private global, then that's not good enough and you do need a canonical __private.

Telling me that you're in a hurry isn't helpful; preserving a reasonable representation and not allowing corner cases to become maintenance problems is far more important to the project than landing patches in trunk on some particular schedule.

Non-canonical information is not supposed to be mangled.

It's not clear to me what the language rule you're really trying to implement is. Maybe you really do need a canonical __private address space, in which case you are going to have to change a lot of code in Sema to add the address space qualifier to every local and temporary allocation. But that's not obvious to me yet, because you haven't really explained why it needs to be explicit in the representation.

In OpenCL all memory is in certain address space, therefore every l-value and pointee in a pointer should have an address space. Private address space has equal status as global or local address space. There are language rules about pointers to what address space can be assigned to pointers to what address space. Therefore all address space needs to be canonical. This patch already puts every local variable and function parameter in private address space, as is done in deduceOpenCLImplicitAddrSpace(). We need private address space to be explicit because we need to display explicit private address space and implicit address space differently, also because in certain semantic checks we need to know if a private address space is explicit or not.

If you just want pointers to private to be mangled with an address-space qualifier — meaning I guess that the mangling e.g. Pi will be completely unused — that should be easy enough to handle in the mangler. But if you need to distinguish between private-qualified types and unqualified types, and that distinction isn't purely to implement some syntactic restriction about not writing e.g. private global, then that's not good enough and you do need a canonical __private.

The mangler does not mangle an empty type qualifier, therefore if private address space is represented as the default address space (i.e., no address space), it will not be mangled at all. This is also related to the substitution and cannot be easily changed without breaking lots of stuff in the mangler.

Telling me that you're in a hurry isn't helpful; preserving a reasonable representation and not allowing corner cases to become maintenance problems is far more important to the project than landing patches in trunk on some particular schedule.

The introduction of explicit private address space and the implicit address space flag in AST is precisely for handling those corner cases in the OpenCL language rules so that they won't become maintenance problems.

Okay. I think I see your point about why it would be better to have a canonical __private address space that is different from the implicit address space 0. I assume this means that there should basically never be pointers, references, or l-values in address space 0 in OpenCL. You will lose a significant amount of representational efficiency by doing this, but it's probably not overwhelming.

I know you aren't implementing OpenCL C++ yet, so most of the cases where temporaries are introduced aren't meaningful to you, but you will at least need to consider compound literals. I suspect the right rule is that file-scope literals should be inferred as being in global or constant memory, depending on whether they're const, and local-scope literals should be inferred as __private.

I'll try to review your patch tomorrow.

Anastasia edited edge metadata.Oct 6 2017, 5:06 AM

Okay. I think I see your point about why it would be better to have a canonical __private address space that is different from the implicit address space 0. I assume this means that there should basically never be pointers, references, or l-values in address space 0 in OpenCL.

If you mean 0 is private address space then no. There can be private AS pointers. But if you mean 0 is no address space then this doesn't exist in OpenCL. I think the right design in the first place would have been to keep address spaces in AST just as they are in the source code and add explicit address spaces to all types in IR instead. In this case absence of any address spaces in AST would signal implicit AS to be used. This would make some Sema checks a bit more complicated though, but the design would become a lot cleaner. Unfortunately I think it would not be worth doing this big change now.

You will lose a significant amount of representational efficiency by doing this, but it's probably not overwhelming.

I know you aren't implementing OpenCL C++ yet, so most of the cases where temporaries are introduced aren't meaningful to you, but you will at least need to consider compound literals. I suspect the right rule is that file-scope literals should be inferred as being in global or constant memory, depending on whether they're const, and local-scope literals should be inferred as __private.

I'll try to review your patch tomorrow.

Okay. I think I see your point about why it would be better to have a canonical __private address space that is different from the implicit address space 0. I assume this means that there should basically never be pointers, references, or l-values in address space 0 in OpenCL.

If you mean 0 is private address space then no. There can be private AS pointers. But if you mean 0 is no address space then this doesn't exist in OpenCL. I think the right design in the first place would have been to keep address spaces in AST just as they are in the source code and add explicit address spaces to all types in IR instead. In this case absence of any address spaces in AST would signal implicit AS to be used. This would make some Sema checks a bit more complicated though, but the design would become a lot cleaner. Unfortunately I think it would not be worth doing this big change now.

My understanding is that that is exactly what the majority of this patch is trying to achieve: making private its own address space, separate from address space 0. The patch is certainly introducing a new address-space enumerator for private; if that's meant to be treated as canonically equal to address space 0, well, (1) this patch doesn't seem to add any of the APIs that I'd expect would be required to make that work, like a way to canonicalize an address space or ask if two address spaces are canonically the same, and (2) that would be a major new complexity in the representation that we wouldn't welcome anyway.

The patch is also tracking explicitness of address spaces in the non-canonical type system, but the majority of the patch is spent dealing with the consequences of splitting __private away from address space 0.

Yaxun has convinced me that it's important to represent a private-qualified type differently from an unqualified type.(*) It seems that you agree, but you're concerned about how that will affect your schedule. I can't speak to your schedule; it seems to me that you and Yaxun need to figure that out privately. If you decide not to separate them yet, then the majority of this patch needs to be put on hold. If you do decide to separate them, it seems to me that we should probably split the change to private out from the introduction of implicit address spaces. Just let me know what you want to do.

(*) I know that you aren't considering OpenCL C++ yet, but often these representation/model questions are easier to answer when thinking about C++ instead of C because type differences are so much more directly important in C++. In OpenCL C++, I assume it will be important to distinguish between <int> and <private int> as template arguments. That tells us straight up that private needs to be represented differently from a lack of qualifier. Note that the result, where certain type representations (e.g. an unqualified int*) become basically meaningless and should never be constructed by Sema, is already precedented in Clang: ObjC ARC does the same thing to unqualified ObjC pointer types, like id*.

(*) I know that you aren't considering OpenCL C++ yet, but often these representation/model questions are easier to answer when thinking about C++ instead of C because type differences are so much more directly important in C++. In OpenCL C++, I assume it will be important to distinguish between <int> and <private int> as template arguments. That tells us straight up that private needs to be represented differently from a lack of qualifier. Note that the result, where certain type representations (e.g. an unqualified int*) become basically meaningless and should never be constructed by Sema, is already precedented in Clang: ObjC ARC does the same thing to unqualified ObjC pointer types, like id*.

It's pretty complicated in OpenCL as int and private int won't be different, but int* and private int* would be different only in OpenCL2.0. The rules are pretty convoluted and I have summarized them in the table earlier: https://reviews.llvm.org/D35082#inline-327303. The issue is that there is not anything like this in other languages and therefore we have this issue trying to fit this concept with something similar but not exactly the same. I thought you and Sam decided to use implicit AS flag to make printing messages consistent with the original source code. I am fine with this approach, however, I would prefer to just keep no AS qualifier in the default AS mode instead of deducing it during parcing in processTypeAttrs, and only to add the AS to the IR at the end of the CodeGen phase. I think it would be a lot easier to understand. However, as Sam has pointed out a lot of code in Sema has been written assuming the deduction of AS and is using AS qualifiers explicitly and therefore it seems like it would be a bigger change to go for. At the same type we have refactored the deduction of default AS now in the parcing phase and it looks a lot better than I thought it would be. So I don't mind if we continue this way.

If there is no other issues. May I commit this patch now? Thanks.

It sounds like there's agreement about the basic technical direction of introducing LangAS::opencl_private. Please introduce isAddressSpaceImplicit() in a different patch and make this patch just about the introduction of LangAS::opencl_private. You can have the pretty-printer just ignore __private for now, which should avoid gratuitous diagnostic changes.

I would like you to investigate using AttributedType for the pretty-printing and address-space semantic checks before adding isAddressSpaceImplicit().

include/clang/AST/Type.h
562 ↗(On Diff #117770)

"I" is not an appropriate abbreviation for "AddressSpaceImplicit".

include/clang/Basic/AddressSpaces.h
34 ↗(On Diff #117770)

I think you need a real comment about the design of OpenCL address spaces here. Specifically, it is important to note that OpenCL no longer uses LangAS::Default for anything except r-values.

yaxunl marked 2 inline comments as done.Oct 11 2017, 3:07 PM

It sounds like there's agreement about the basic technical direction of introducing LangAS::opencl_private. Please introduce isAddressSpaceImplicit() in a different patch and make this patch just about the introduction of LangAS::opencl_private. You can have the pretty-printer just ignore __private for now, which should avoid gratuitous diagnostic changes.

I would like you to investigate using AttributedType for the pretty-printing and address-space semantic checks before adding isAddressSpaceImplicit().

Thanks. I will separate the implicit addr space flag to another patch.

include/clang/AST/Type.h
562 ↗(On Diff #117770)

Will change it to ImplictAddrSpace.

include/clang/Basic/AddressSpaces.h
34 ↗(On Diff #117770)

Will do.

Thanks. I will separate the implicit addr space flag to another patch.

Thanks, appreciated.

include/clang/AST/Type.h
562 ↗(On Diff #117770)

Sounds good.

yaxunl updated this revision to Diff 118813.Oct 12 2017, 11:30 AM
yaxunl marked 7 inline comments as done.
yaxunl edited the summary of this revision. (Show Details)

Separate implicit addr space flag to another patch as John suggested.

This patch only introduces the private addr space but does not print it.

yaxunl edited the summary of this revision. (Show Details)Oct 12 2017, 11:44 AM

A few minor comments; feel free to commit after addressing them.

include/clang/Basic/AddressSpaces.h
34 ↗(On Diff #117770)

Thanks, WFM.

lib/AST/TypePrinter.cpp
1703 ↗(On Diff #118813)

Please add the case here, even if it's unreachable for now.

lib/Sema/SemaType.cpp
5754 ↗(On Diff #118813)

Please just make this a case, and then the default can be llvm_unreachable.

This revision was automatically updated to reflect the committed changes.
cfe/trunk/test/SemaOpenCL/cl20-device-side-enqueue.cl