ebevhan added a comment.

In D62574#2183294 <https://reviews.llvm.org/D62574#2183294>, @Anastasia wrote:

> In D62574#2136423 <https://reviews.llvm.org/D62574#2136423>, @ebevhan wrote:
>
>> It seems that D70605 <https://reviews.llvm.org/D70605> attempted to 
>> ameliorate the issues that I observed (pointer-conversion doing too much), 
>> but it didn't manage to solve the problem fully.
>
> Can you explain what's left to be done?

My cache is a bit flushed on this at the moment but I do believe that if the 
issue described in D83325 <https://reviews.llvm.org/D83325> is resolved, this 
patch should work.



================
Comment at: lib/Sema/SemaOverload.cpp:3171
+  // qualification conversion for disjoint address spaces make address space
+  // casts *work*?
   Qualifiers FromQuals = FromType.getQualifiers();
----------------
Anastasia wrote:
> ebevhan wrote:
> > Anastasia wrote:
> > > ebevhan wrote:
> > > > Anastasia wrote:
> > > > > Anastasia wrote:
> > > > > > ebevhan wrote:
> > > > > > > Anastasia wrote:
> > > > > > > > I guess if address spaces don't overlap we don't have a valid 
> > > > > > > > qualification conversion. This seems to align with the logic 
> > > > > > > > for cv. My guess is that none of the other conversions will be 
> > > > > > > > valid for non overlapping address spaces and the error will 
> > > > > > > > occur.
> > > > > > > > 
> > > > > > > > I think at this point we might not need to know if it's 
> > > > > > > > implicit or explicit? I believe we might have a separate check 
> > > > > > > > for this somewhere because it works for OpenCL. I don't know 
> > > > > > > > though if it might simplify the flow if we move this logic 
> > > > > > > > rather here.
> > > > > > > > 
> > > > > > > > The cv checks above seem to use `CStyle` flag. I am wondering 
> > > > > > > > if we could use it to detect implicit or explicit. Because we 
> > > > > > > > can only cast address space with C style cast at the moment.  
> > > > > > > > Although after adding `addrspace_cast` operator that will no 
> > > > > > > > longer be the only way.
> > > > > > > > I guess if address spaces don't overlap we don't have a valid 
> > > > > > > > qualification conversion. This seems to align with the logic 
> > > > > > > > for cv. My guess is that none of the other conversions will be 
> > > > > > > > valid for non overlapping address spaces and the error will 
> > > > > > > > occur.
> > > > > > > 
> > > > > > > Right. So the reasoning is that if the address spaces are 
> > > > > > > disjoint according to the overlap rule, then it cannot be 
> > > > > > > considered a qualification conversion.
> > > > > > > 
> > > > > > > But with the new hooks, it's possible for a target to allow 
> > > > > > > explicit conversion even if address spaces do not overlap 
> > > > > > > according to the rules. So even though there is no overlap, such 
> > > > > > > a conversion could still be a qualification conversion if it was 
> > > > > > > explicit (either via a c-style cast or an `addrspace_cast`). This 
> > > > > > > is in fact the default for all targets (see the patch in 
> > > > > > > TargetInfo.h).
> > > > > > > 
> > > > > > > I think I need a refresher on how the casts were meant to work; 
> > > > > > > were both `static_cast` and `reinterpret_cast` supposed to be 
> > > > > > > capable of implicit conversion (say, private -> generic) but only 
> > > > > > > `addrspace_cast` for the other direction (generic -> private)? Or 
> > > > > > > was `reinterpret_cast` supposed to fail in the first case?
> > > > > > Just as a summary:
> > > > > > 
> > > > > > - All casts should allow safe/implicit AS conversions i.e. 
> > > > > > `__private`/`__local`/`__global` -> `__generic` in OpenCL
> > > > > > - All casts except for C-style and `addrspace_cast` should disallow 
> > > > > > unsafe/explicit conversions i.e. generic -> 
> > > > > > `__private`/`__local`/`__global` in OpenCL
> > > > > > - All casts should disallow forbidden conversions with no address 
> > > > > > space overlap i.e. `__constant` <-> any other in OpenCL
> > > > > > 
> > > > > > In OpenCL overlapping logic is only used for explicit i.e. unsafe 
> > > > > > conversion. So it seems we might only need those conversions here 
> > > > > > then? 
> > > > > Did you have time to look into this?
> > > > I still don't really understand why the code checks for overlap here. 
> > > > Removing this check causes one test case to break, 
> > > > CodeGenCXX/address-space-cast.cpp. Specifically, this:
> > > > 
> > > > ```
> > > > #define __private__ __attribute__((address_space(5)))
> > > > 
> > > > void test_cast(char *gen_char_ptr, void *gen_void_ptr, int 
> > > > *gen_int_ptr) {
> > > >   __private__ void *priv_void_ptr = (__private__ void *)gen_char_ptr;
> > > > }
> > > > ```
> > > > 
> > > > It tries to resolve the C-style cast with TryAddressSpaceCast, but 
> > > > fails as the underlying pointee types (`char` and `void`) are 
> > > > different. Then it tries to do it as a static_cast instead, but fails 
> > > > to produce an `AddressSpaceConversion`; instead, it makes a `BitCast` 
> > > > **as the second conversion step** which causes CodeGen to break since 
> > > > the conversion kind is wrong (the address spaces don't match).
> > > > 
> > > > Is address space conversion supposed to be a pointer conversion or a 
> > > > qualification conversion? If the second conversion step had emitted an 
> > > > AddressSpaceConversion instead of a BitCast, it would have worked. But 
> > > > at the same time, if we have IsQualificationConversion return false 
> > > > whenever we would need to do an address space conversion, other tests 
> > > > break.
> > > > 
> > > > I suppose that a solution might be to remove the special case in 
> > > > IsQualificationConversion for address spaces, and that 
> > > > TryAddressSpaceCast should ignore the underlying type if it's part of a 
> > > > C-style cast. That way we won't try to handle it as a static_cast. But 
> > > > I don't know if that's just a workaround for a larger underlying issue, 
> > > > or if it causes other issues.
> > > > 
> > > > All in all, I have no idea what these code paths are trying to 
> > > > accomplish. It just doesn't make sense to me. :(
> > > > 
> > > > It tries to resolve the C-style cast with TryAddressSpaceCast, but 
> > > > fails as the underlying pointee types (char and void) are different. 
> > > > Then it tries to do it as a static_cast instead, but fails to produce 
> > > > an AddressSpaceConversion; instead, it makes a BitCast as the second 
> > > > conversion step which causes CodeGen to break since the conversion kind 
> > > > is wrong (the address spaces don't match).
> > > 
> > > Strange! `TryStaticCast` should set cast kind to 
> > > `CK_AddressSpaceConversion` if it detects the address spaces are 
> > > different. Do you know why it doesn't happen for this test case?
> > > 
> > > > Is address space conversion supposed to be a pointer conversion or a 
> > > > qualification conversion?
> > > 
> > > It is a qualification conversion.
> > > 
> > > > 
> > > > I suppose that a solution might be to remove the special case in 
> > > > IsQualificationConversion for address spaces, and that 
> > > > TryAddressSpaceCast should ignore the underlying type if it's part of a 
> > > > C-style cast. That way we won't try to handle it as a static_cast. But 
> > > > I don't know if that's just a workaround for a larger underlying issue, 
> > > > or if it causes other issues.
> > > 
> > > I think the idea of separate conversions is for each of them to work as a 
> > > separate step. So address space cast should be working just as const cast 
> > > i.e. it should only check the address space conversion and not the type. 
> > > However the problem here is that `addrspacecast` supersedes `bitcast`. 
> > > Therefore there are extra checks in the casts later to classify the cast 
> > > kind correctly. If this flow fails we can reevaluate but this is the idea 
> > > we were following up to now.
> > > 
> > > 
> > > 
> > > 
> > > 
> > > 
> > > 
> > > 
> > I've determined that something doesn't add up with how conversions are 
> > generated. I'm pretty sure that the issue lies in 
> > `PerformImplicitConversion`.
> > 
> > When we analyze the c-style cast in this:
> > ```
> > char * p;
> > __private__ void * pp = (__private__ void *)gen_char_ptr;
> > ```
> > we determine that this cannot be an addrspace_cast (as the unqualified 
> > pointee types are different). It can be a static_cast, though. The implicit 
> > conversion resulting from this static_cast should occur in two steps: the 
> > second conversion should be a pointer conversion from `char*` to `void*`, 
> > and the third conversion should be a qualification conversion from `void*` 
> > to `__private__ void*`.
> > 
> > Now, this *is* the ICS/SCS that we get. However, when we realize the 
> > conversion sequence in PerformImplicitConversion, it actually completely 
> > ignores the intermediate types in the conversion sequence. Everything it 
> > does is only on the intermediate 'From' type after each conversion step and 
> > the final 'To' type, but we never consider the intermediate 'To' type. This 
> > means that it will try to realize the entire conversion sequence (both the 
> > 'bitcast' conversion and the 'addrspace' conversion) in a single (pointer 
> > conversion) step instead of two, and since CheckPointerConversion has no 
> > provisions for address space casts (because why should it?) we get a 
> > CK_BitCast and codegen fails since it's trying to change the address space 
> > of the type.
> > 
> > This means that each conversion step realization needs to be aware of every 
> > kind of CastKind that could possibly occur in each step, which is bizarre. 
> > We know exactly what type we are converting from and to in each conversion 
> > in the sequence; why do we use the *final* result type to determine what 
> > kind of implicit cast we should use in each step?
> > 
> > I've tried to make PerformImplicitConversion aware of the intermediate 
> > types, but this breaks a bunch of tests, as there are lots of checks and 
> > diagnoses in the function that require the final type. One contributor to 
> > this is that the 'ToType' of the SCS (`ToType[2]`) doesn't actually have to 
> > match the final 'ToType' of the conversion. Something to do with exception 
> > specifications.
> > 
> > It feels like this code is just broken and everyone has just been coding 
> > around the issues. Perhaps this is the root:
> > ```
> >   // Overall FIXME: we are recomputing too many types here and doing far too
> >   // much extra work. What this means is that we need to keep track of more
> >   // information that is computed when we try the implicit conversion 
> > initially,
> >   // so that we don't need to recompute anything here.
> > ```
> > 
> > I don't know what the solution here is, short of redesigning 
> > PerformImplicitConversion.
> Btw the example that you provide here seems to compile in OpenCL now: 
> https://godbolt.org/z/j9E3s4
That's neat. It does seem like the example in D83325 compiles too, but I 
suspect it wouldn't work with this patch.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62574/new/

https://reviews.llvm.org/D62574

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to