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

Ryan Taylor via llvm-dev llvm-dev at lists.llvm.org
Fri Feb 19 07:35:03 PST 2021


Juneyoung,

  I don't think it's a valid argument to say we shouldn't propagate the
restrict qualifier because then we can't do transformations
  because the reverse argument can easily be made: if we don't propagate
the restrict qualifier then we can't do transformations.
  By definition, I think that transformation should be invalid if either i
or j are restrict qualified. The restrict qualifier should
  probably be thought of as a contract between the programmer and the
compiler. I think the programmer should expect the
  compiler to adhere to the restrict qualifier in best effort. The compiler
should also not try to outthink the programmer, in that
  if the programmer accesses memory on, or based on, a restrict qualified
pointer with another pointer, the behavior is undefined.

Jeron,

  I appreciate it.  I have added myself to the next AA call and added
int2ptr capturing as an agenda I hope we can briefly discuss.

Thanks,

Ryan

On Fri, Feb 19, 2021 at 3:49 AM Jeroen Dobbelaere <
Jeroen.Dobbelaere at synopsys.com> wrote:

> 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> 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>
> 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> 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> 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>
> *Sent:* Thursday, February 18, 2021 19:11
> *To:* Jeroen Dobbelaere <dobbel at synopsys.com>
> *Cc:* Johannes Doerfert <johannesdoerfert at gmail.com>; llvm-dev <
> llvm-dev at lists.llvm.org>; Juneyoung Lee <juneyoung.lee at sf.snu.ac.kr>;
> Philip Reames <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> 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>
> *Sent:* Thursday, February 18, 2021 18:51
> *To:* Jeroen Dobbelaere <dobbel at synopsys.com>
> *Cc:* Johannes Doerfert <johannesdoerfert at gmail.com>; llvm-dev <
> llvm-dev at lists.llvm.org>; Juneyoung Lee <juneyoung.lee at sf.snu.ac.kr>;
> Philip Reames <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> 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>
> *Sent:* Thursday, February 18, 2021 18:31
> *To:* Johannes Doerfert <johannesdoerfert at gmail.com>
> *Cc:* llvm-dev <llvm-dev at lists.llvm.org>; Jeroen Dobbelaere <
> dobbel at synopsys.com>; Juneyoung Lee <juneyoung.lee at sf.snu.ac.kr>; Philip
> Reames <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> 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
> > 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/a58a83b0/attachment.html>


More information about the llvm-dev mailing list