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

Juneyoung Lee via llvm-dev llvm-dev at lists.llvm.org
Thu Feb 18 22:24:30 PST 2021


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
>>
>> 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/deaa5687/attachment.html>


More information about the llvm-dev mailing list