[PATCH] Handle accesses to sturctures with embedded arrays and different offsets better
Daniel Berlin
dberlin at dberlin.org
Fri Mar 20 12:25:36 PDT 2015
If you want this to work we have serious problems, since the same can be
said for simple structs as well:
struct S00 {
char mC_0;
short mS_1;
int mI_2;
int mI_3;
};
void test_s00b(struct S00* a, struct S00* b)
{
a->mI_2=1;
b->mI_3=2;
// c++11: NoAlias
// llvm: NoAlias
// future: NoAlias
}
You can play the same trick here, and change offset of b so that mi_2 and
mi_3 are in the same place, and both are ints.
(Jeroen produced these results saying they are NoAlias).
On Fri, Mar 20, 2015 at 12:09 PM, Nick Lewycky <nlewycky at google.com> wrote:
> On 20 March 2015 at 11:58, Daniel Berlin <dberlin at dberlin.org> wrote:
>
>>
>>
>> On Fri, Mar 20, 2015 at 11:41 AM, Nick Lewycky <nlewycky at google.com>
>> wrote:
>>
>>> ================
>>> Comment at: lib/Analysis/BasicAliasAnalysis.cpp:979
>>> @@ -978,1 +978,3 @@
>>>
>>> +/// isActualObject - Return true if V represents an actual object
>>> where we can
>>> +/// reason about the offsets directly, like an argument, alloca, or
>>> global
>>> ----------------
>>> I really don't understand this comment, either from "actual" or "reason
>>> about the offsets directly".
>>>
>>> Looking at the uses, I don't see any reason not to use
>>> llvm::isIdentifiedObject. I think what you need to know is that [V,
>>> V+Offset] does not overlap any other object. isIdentifiedObject should be
>>> sufficient for that.
>>>
>>
>> It would be, except isIdentifiedObject does not consider Arguments to be
>> identified unless they are noalias or byval.
>>
>> We don't care.
>> The only case noalias could matter is if they are in a union, and as
>> we've been through on this thread, we don't consider passing addresses of
>> union members to save you.
>>
>>
>>
>>>
>>> ================
>>> Comment at: lib/Analysis/BasicAliasAnalysis.cpp:983
>>> @@ +982,3 @@
>>> +static bool isActualObject(const Value *V) {
>>> + if (isa<GlobalValue>(V) || isa<Argument>(V) || isa<AllocaInst>(V))
>>> + return true;
>>> ----------------
>>> What about GlobalAlias? GlobalAlias isa GlobalValue.
>>>
>> Agreed.
>>
>>
>>>
>>> ================
>>> Comment at: lib/Analysis/BasicAliasAnalysis.cpp:1063
>>> @@ -1054,1 +1062,3 @@
>>> + // If they have the same offsets, and the underlying object is
>>> noalias,
>>> + // they must not alias
>>> if (GEP1BaseOffset == GEP2BaseOffset &&
>>> ----------------
>>> Full stop after "alias".
>>>
>> Fixed
>>
>>
>>>
>>> ================
>>> Comment at: lib/Analysis/BasicAliasAnalysis.cpp:1069
>>> @@ +1068,3 @@
>>> + } else {
>>> + // If these are both arguments, global variable, or alloca,
>>> and the
>>> + // [offset, offset+size] ranges don't overlap, they can't alias
>>> ----------------
>>> Extra space between "both" and "arguments".
>>>
>> Fixed
>>
>>>
>>> ================
>>> Comment at: lib/Analysis/BasicAliasAnalysis.cpp:1069
>>> @@ +1068,3 @@
>>> + } else {
>>> + // If these are both arguments, global variable, or alloca,
>>> and the
>>> + // [offset, offset+size] ranges don't overlap, they can't alias
>>> ----------------
>>> nlewycky wrote:
>>> > Extra space between "both" and "arguments".
>>> Tense agreement between "arguments" and "global variable" and "alloca".
>>>
>>
>>
>>> Fixed
>>>
>>
>>
>>> ================
>>> Comment at: lib/Analysis/BasicAliasAnalysis.cpp:1070
>>> @@ +1069,3 @@
>>> + // If these are both arguments, global variable, or alloca,
>>> and the
>>> + // [offset, offset+size] ranges don't overlap, they can't alias
>>> + if (isActualObject(UnderlyingV1) &&
>>> isActualObject(UnderlyingV2) &&
>>> ----------------
>>> Full stop after "alias".
>>>
>> Fixed.
>>
>>
>>>
>>> ================
>>> Comment at: test/Analysis/BasicAA/gep-alias.ll:235
>>> @@ +234,3 @@
>>> +
>>> +; We should be able to determine the second store and the load do not
>>> conflict,
>>> +; but the first store and the load are must alias
>>> ----------------
>>> But they can, I just need to call @test13 with %a = %b + 13 .
>>
>>
>>
>> I'm not sure i see how this works.
>>
>> Did you mean to check whether arguments are noalias?
>>>
>>> No.
>> The original testcase is:
>> // struct
>> struct S00 {
>> char mC_0;
>> short mS_1;
>> int mI_2;
>> int mI_3;
>> };
>>
>> // array member
>> // ------------
>> struct S03 {
>> short mS_0;
>> struct S00 mS00_1[4];
>> short mS_2;
>> };
>>
>> int test_s03c(struct S03* a, struct S03* b)
>> {
>> a->mS00_1[0].mI_2=1;
>> b->mS00_1[1].mI_2=2;
>> return a->mS00_1[0].mI_2;
>> }
>>
>> I don't see how you an make these conflict, no matter what you pass in,
>> because the [1] prevents it.
>>
>
> All I need to do is arrange that &a->mS00_1[0].mI_2 == &b->mS00_1[1].mI_2.
>
> void test() {
> int mI_2;
> char *a = (char*)&mI_2, *b = (char*)&mI_2;
> a -= offsetof(S03, mS00_1[0].mI_2);
> b -= offsetof(S03, mS00_1[1].mI_2);
> test_s03c((S03*)a, (S03*)b);
> }
>
> Nick
>
> %6 is %b+17 (aka gep %5, i32 0, i32 1, i32 2)
>>> %10 loads %a+5 (aka gep %a, i32 0, i32 1, i32 0, i32 2)
>>>
>>>
>>
>>> [I assume one byte of padding in %struct.S00 after the i16.]
>>>
>>> ================
>>> Comment at: test/Analysis/BasicAA/gep-alias.ll:236
>>> @@ +235,3 @@
>>> +; We should be able to determine the second store and the load do not
>>> conflict,
>>> +; but the first store and the load are must alias
>>> +define i32 @test13(%struct.S03* %a, %struct.S03* %b) {
>>> ----------------
>>> Full stop after "alias".
>>>
>>> http://reviews.llvm.org/D8487
>>>
>>> EMAIL PREFERENCES
>>> http://reviews.llvm.org/settings/panel/emailpreferences/
>>>
>>>
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150320/f9678fc2/attachment.html>
More information about the llvm-commits
mailing list