[llvm-dev] inttoptr->add->ptrtoint capturing pointer?

Jeroen Dobbelaere via llvm-dev llvm-dev at lists.llvm.org
Fri Feb 19 00:49:36 PST 2021


For what its worth:
- for the full restrict implementation, I tried to follow the specification as close as possible.
  Given that, refinements and tuning to the llvm-ir level behavior can be done/discussed.
- my interpretation of the standard is that 'an integer computation' (ak  ptr2int) loses the 'based on' property. A 'int2ptr' will not bring it back (*).
- If you have code like:

   int * restrict p;
   int q=(int)p); // losses restrict based on
   p[1]=42;
   *(int*)(q+4) = 43;  // accesses same object as p[1], but _not_ based on 'p' -> undefined behavior
  return p[1];

the final access using 'q' will result in undefined behavior.

- (*) I made one exception to this:  as llvm is (was?) sometimes introducing ptr2int /int2ptr conversions itself, I ensured that we look through these
  in order to track the 'based on' relationship.

> Optimization can transform use(int2ptr(i)) inside the branch into use(int2ptr(j)) because i == j holds.

[0] is a good read for these cases. This is a situation that the full restrict patches is not trying to fix.
But, the 'ptr_provenance' infrastructure it introduces is something that can be useful to tackle it.
As was discussed during last LLVM AA Technical call[1], this infrastructure is the next step forward to introduce
into the main llvm, as it will help solving these kind of issues.

Greetings,

Jeroen Dobbelaere

[0] pointer provenance  proposal  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2577.pdf
[1] LLVM AA Technical Call https://docs.google.com/document/d/1ybwEKDVtIbhIhK50qYtwKsL50K-NvB6LfuBsfepBZ9Y/edit

From: Juneyoung Lee <juneyoung.lee at sf.snu.ac.kr>
Sent: Friday, February 19, 2021 07:25
To: Ryan Taylor <ryta1203 at gmail.com>
Cc: Jeroen Dobbelaere <dobbel at synopsys.com>; Johannes Doerfert <johannesdoerfert at gmail.com>; llvm-dev <llvm-dev at lists.llvm.org>; Philip Reames <listmail at philipreames.com>
Subject: Re: [llvm-dev] inttoptr->add->ptrtoint capturing pointer?

I think inttoptr should drop noalias-ness of the input pointer because it may collide with existing optimizations.

int i = ptr2int(p) + ofs
int j = ptr2int(p') + ofs'
if (i == j) use(int2ptr(i));

Optimization can transform use(int2ptr(i)) inside the branch into use(int2ptr(j)) because i == j holds.
If int2ptr preserves noalias-ness of the input pointer, this transformation becomes invalid.
For example, if p was a normal pointer and p' was a noalias pointer, the replacement makes the program more undefined.
In general, it is hard to detect whether an integer variable is derived from a pointer or not; imagine that i and j were complex expressions.

In terms of correctness, it is okay for LLVM to define the inttoptr cast drop the noalias information because it makes the program more defined.
noalias (and restrict as well) guarantees disjointness of memory accesses by defining its violation as undefined behavior. Removing noalias is thus okay.



On Fri, Feb 19, 2021 at 12:54 PM Ryan Taylor <ryta1203 at gmail.com<mailto:ryta1203 at gmail.com>> wrote:
Juneyoung,

  It seems from the spec the intention (in best practice) is to allow restrict to follow through to any pointers based on the original restrict pointer providing
  that the new pointer is based on the original restrict pointer and only the original restrict pointer (ie, no other pointers), so on and so forth (ie propagated).
  So in the example, the original pointer's restrict qualifier, in this case, should follow through the ptr2int->add->int2ptr to the new pointer.

  Yes, currently (and with the new patches) this doesn't work, as int2ptr assumes capture, which prevents noalias, but should that be correct? It doesn't seem
  like it from the spec.

Thanks.

On Thu, Feb 18, 2021 at 10:37 PM Juneyoung Lee <juneyoung.lee at sf.snu.ac.kr<mailto:juneyoung.lee at sf.snu.ac.kr>> wrote:
Hi,

I think what Jeroen says is about the behavior of C programs.
In C, an expression can be restrict-qualified, which isn't the case in LLVM IR; there is no 'i8* restrict' type or something like that.
I guess noalias intrinsics are inserted to preserve the information when translating restrict pointers in C to IR.

To summarize, the return value of inttoptr (which is an IR instruction) itself won't work as a restrict-qualified pointer because there is no restrict qualifier in IR.
If it is somehow used by the noalias intrinsics, it should be able to gain the power to work as a restrict pointer.


>    x = (const float *)((int)x+off2))
>
> I'm not sure why this should be capturing the pointer?

The reason is that (int)x + off2 may accidentally point into a different object.
A possible workaround is to use (const float*)((const char*)x+off2), which is guaranteed to preserve the provenance.
clang-tidy has an option to detect integer-to-pointer casts to warn about possible performance degradation: https://clang.llvm.org/extra/clang-tidy/checks/performance-no-int-to-ptr.html<https://urldefense.com/v3/__https:/clang.llvm.org/extra/clang-tidy/checks/performance-no-int-to-ptr.html__;!!A4F2R9G_pg!LKtxvZ6he7rfjJmBI-AAgN3kjUM8cqpoOQdydkds11U_1grfRzh1G03sxvK-fhYV55PmNrEq$>

Juneyoung

On Fri, Feb 19, 2021 at 4:00 AM Ryan Taylor <ryta1203 at gmail.com<mailto:ryta1203 at gmail.com>> wrote:
Yes, so if you have an int2ptr->add+(non-pointer)->ptr2int that should retain restrict qualifier, but you are saying it doesn't, or that the new patches won't support that, correct?

Thanks.

On Thu, Feb 18, 2021 at 1:22 PM Jeroen Dobbelaere <Jeroen.Dobbelaere at synopsys.com<mailto:Jeroen.Dobbelaere at synopsys.com>> wrote:
> Seems like as long as the pointer is based on the restrict pointer (and no other pointer)and follows the constraints, it to is restrict qualified?

as long as the pointer expression is based on a restrict pointer... its accesses are associated to that restrict pointer (and assumed to not alias with other restrict pointers in the same scope).

Greetings,

Jeroen Dobbelaere




From: Ryan Taylor <ryta1203 at gmail.com<mailto:ryta1203 at gmail.com>>
Sent: Thursday, February 18, 2021 19:11
To: Jeroen Dobbelaere <dobbel at synopsys.com<mailto:dobbel at synopsys.com>>
Cc: Johannes Doerfert <johannesdoerfert at gmail.com<mailto:johannesdoerfert at gmail.com>>; llvm-dev <llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org>>; Juneyoung Lee <juneyoung.lee at sf.snu.ac.kr<mailto:juneyoung.lee at sf.snu.ac.kr>>; Philip Reames <listmail at philipreames.com<mailto:listmail at philipreames.com>>
Subject: Re: [llvm-dev] inttoptr->add->ptrtoint capturing pointer?

Ok, just clarifying.

Am I interrupting 6.7.3.1.4 incorrectly?

Seems like as long as the pointer is based on the restrict pointer (and no other pointer)and follows the constraints, it to is restrict qualified?

  During each execution of B, let L be any lvalue that has &L based on P. If L is used to access the value of the object X that it designates, and X is also modified (by any means), then the following requirements apply: T shall not be const-qualified. Every other lvalue used to access the value of X shall also have its address based on P. Every access that modifies X shall be considered also to modify P, for the purposes of this subclause.

Thanks.



On Thu, Feb 18, 2021 at 12:59 PM Jeroen Dobbelaere <Jeroen.Dobbelaere at synopsys.com<mailto:Jeroen.Dobbelaere at synopsys.com>> wrote:
> So if some restrict pointer 'x' is casted to int, adds 1, then casted back to pointer, it nullifies the restrict qualifier, despite the results having no other uses?
yes.

int * restrict x = ...;

bad usage:
    *(int*)((int)x + 1) = 42;

valid usage:
    x = (int*)((int)x + 1);
   *x = 42;

Greetings,

Jeroen Dobbelaere

From: Ryan Taylor <ryta1203 at gmail.com<mailto:ryta1203 at gmail.com>>
Sent: Thursday, February 18, 2021 18:51
To: Jeroen Dobbelaere <dobbel at synopsys.com<mailto:dobbel at synopsys.com>>
Cc: Johannes Doerfert <johannesdoerfert at gmail.com<mailto:johannesdoerfert at gmail.com>>; llvm-dev <llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org>>; Juneyoung Lee <juneyoung.lee at sf.snu.ac.kr<mailto:juneyoung.lee at sf.snu.ac.kr>>; Philip Reames <listmail at philipreames.com<mailto:listmail at philipreames.com>>
Subject: Re: [llvm-dev] inttoptr->add->ptrtoint capturing pointer?

So if some restrict pointer 'x' is casted to int, adds 1, then casted back to pointer, it nullifies the restrict qualifier, despite the results having no other uses?

Thanks.

On Thu, Feb 18, 2021 at 12:41 PM Jeroen Dobbelaere <Jeroen.Dobbelaere at synopsys.com<mailto:Jeroen.Dobbelaere at synopsys.com>> wrote:
> How will inttoptr work with the new restrict patches?  Certainly the int2ptr capturing shouldn't nullify the restrict qualifier.

The full restrict patches see through 'inttoptr(ptrtoint( x ) )', Besides that, the analysis stops at 'ptr2int(x)' and 'anything can happen'.
Because of this, all other 'inttoptr' usages will never introduce a restrict provenance.

(aka, a restrict pointer converted to an int + some computations and then converted back to a pointer will normally not retain the 'restrictness' and that can trigger undefined behavior)

Greetings,

Jeroen Dobbelaere

From: Ryan Taylor <ryta1203 at gmail.com<mailto:ryta1203 at gmail.com>>
Sent: Thursday, February 18, 2021 18:31
To: Johannes Doerfert <johannesdoerfert at gmail.com<mailto:johannesdoerfert at gmail.com>>
Cc: llvm-dev <llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org>>; Jeroen Dobbelaere <dobbel at synopsys.com<mailto:dobbel at synopsys.com>>; Juneyoung Lee <juneyoung.lee at sf.snu.ac.kr<mailto:juneyoung.lee at sf.snu.ac.kr>>; Philip Reames <listmail at philipreames.com<mailto:listmail at philipreames.com>>
Subject: Re: [llvm-dev] inttoptr->add->ptrtoint capturing pointer?

Juneyoung said he hadn't started working on it yet, so I'm going to take a look at it also.

How will inttoptr work with the new restrict patches?  Certainly the int2ptr capturing shouldn't nullify the restrict qualifier.

Thanks.





On Thu, Feb 18, 2021 at 12:04 PM Johannes Doerfert <johannesdoerfert at gmail.com<mailto:johannesdoerfert at gmail.com>> wrote:
I think you are working with a custom llvm here but I will
make a few general statements that might help:

- The noalias intrinsic as you've shown it captures, unfortunately.
   We don't have the `nocapture_maybe_returned` attribute in IR yet that
the Attributor uses for these situations,
   IIRC, Juneyoung is working on making it an LLVM-IR enum attribute
already.

- int2ptr is assumed to capture in basically every analysis I've seen.
It doesn't intrinsically but it is really
   hard to get it right. That said, we could allow *very* special
patterns but I would argue those should be recognized
   in instcombine and replaced there.

- Philip and I are working to define capture better for the lang ref, we
might want to include some examples and
   rational around int2ptr when we have a coherent model.

I've CC'ed people that might correct me or augment my answer, hope this
helps :)

~ Johannes


On 2/18/21 9:17 AM, Ryan Taylor via llvm-dev wrote:
> I have an example:
>
> foo(float * restrict y, int off1, int off2) {
>    float * restrict x;
>    for (..) {
>      for (..) {
>        x = y+off1;
>      }
>      x = (const float *)((int)x+off2))
>
> I'm not sure why this should be capturing the pointer?
>
> For instance, looking at scoped noalias dbg info:
>
> SNA: Capture check for B/CSB UO:   %54 = inttoptr i32 %add83 to float*,
> !dbg !101
> SNA: Pointer   %1 = call float* @llvm.noalias.p0_float(float* %0, metadata
> !38), !dbg !41 might be captured!
>
> Is this implying that the noalias intrinsic might be capturing the pointer?
> It doesn't look like "noalias" intrinsic has NoCapture property on the
> pointer:
>
> def int_noalias       : Intrinsic<[llvm_anyptr_ty],
>                                    [LLVMMatchType<0>, llvm_metadata_ty],
>                                    [IntrArgMemOnly, Returned<0>]>;
>
> It should though right? From the definition of capture it is returning the
> pointer; however, we know nothing is happening here.
>
> I'm on llvm 10 with Hal's restrict patches.
>
> Thanks.
>
>
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org>
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev<https://urldefense.com/v3/__https:/lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev__;!!A4F2R9G_pg!Pm5BQtdh_gU6pe-WvhApIs2FOjI1V7vJDj6H93m0sNUItsa5T6CbzW5JL1cixruSF_kY7ywW$>


--

Juneyoung Lee
Software Foundation Lab, Seoul National University


--

Juneyoung Lee
Software Foundation Lab, Seoul National University
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20210219/ebde9c77/attachment-0001.html>


More information about the llvm-dev mailing list