diff --git a/docs/GetElementPtr.html b/docs/GetElementPtr.html index 4e3c7611189..13df3f46f2b 100644 --- a/docs/GetElementPtr.html +++ b/docs/GetElementPtr.html @@ -296,332 +296,6 @@ - -
- -The following is a real discussion from the - #llvm IRC channel about the GEP - instruction. You may find this instructive as it was the basis for this - document.
-User | Comment |
---|---|
Yorion | If x & y must alias, are [ getelementptr x,0,0,1,2 ] and [ getelementptr x,1,2 ] aliased? (they obviously have different types, but they should alias...) |
Yorion | oops, for the second one I meant [ getelementptr y,1,2 ] |
Reid | I don't see how that could be, Yorion but I'm not the authority on this |
Yorion | hmm.. |
Reid | the two geps, by definition, are going to produce different pointers which are not aliased |
Yorion | would [ GEP x,1,0 ] and [ GEP y,1 ] be aliased? |
Reid | if the second gep was [gep y,0,0,1,2] then they should be aliased as well |
Reid | no, I wouldn't expect that to work either :) |
Reid | you can't just arbitrarily drop leading or trailing indices :) |
Reid | (.. leading or trailing 0 indices, I mean) |
Reid | this instruction walks through a data structure and generates a pointer to the resulting thing |
Reid | if the number of indices are different, you're ending up at a different place and by definition they'll have different addresses |
Yorion | oh, I see, because of different types, [ GEP x,0,1 ] - & [ GEP x,1 ] actually might refer to different fields, but might also refer to the same ones... |
Reid | or, at least, that's my crude understanding of it :) |
Reid | no, they'll definitely refer to different fields |
nicholas | GEP x,0,1 ==> &((*(x+0))+1)? vs. GEP x,1 ==> &(*(x+1))? |
Reid | lemme grok that for a sec |
Reid | that might be true in some limited definition of x, but it wouldn't be generally |
nicholas | oh. fields of different sizes in a structure. |
Reid | yup |
Yorion | is perhaps the type unification the reason why [ GEP x,0,1 ] and [ GEP x,1 ] cannot alias? |
Reid | no |
Reid | they may or may not have the same type, but they are definitely different pointers |
Reid | lets use a concrete example for "x" |
Reid | suppose x is "struct {int a, float b} *" |
Reid | GEP X,0,1 is going to return the address of b |
Reid | GEP X,1 is going to return the address of the *second* "a" (after the first b) |
Yorion | ah, I see... |
Yorion | trailing zeros are still a bit confusing... |
Reid | same thing .. you're just selecting the 0th member of an array or structure |
Yorion | you don't move away from the pointer, only the type is changed |
Reid | no, you still move away from the pointer .. the type might change, or not |
Reid | the pointer definitely changes |
Reid | lets look at an example for trailing zero |
Reid | suppose x is "int x[10][10][10][10]" (in C) |
Reid | GEP X,0,0 will yield you a 3 dimensional array |
Reid | GEP X,0,0,0,0,0 will yield you an "int" |
Reid | make sense? |
Yorion | yes |
Reid | so, I think there's a law here: if the number of indices in two GEP instructions are not equivalent, there is no way the resulting pointers can alias |
Reid | (assuming the x and y alias) |
Yorion | I was confused with some code in BasicAliasAnalysis that says that two pointers are equal if they differ only in trailing zeros |
Yorion | BasicAliasAnalysis.cpp:504-518 |
Reid | lemme look |
nicholas | if y1 = GEP X, 0, 0 and y2 = GEP X, 0, 0, 0, 0, 0 (from Reid's example) |
nicholas | then doesn't *y1 and *y2 both refer to the same "int"? |
Reid | they shouldn't |
Reid | hmm .. actually, maybe you're right :) |
Reid | they definitely have different *types* |
Yorion | true |
nicholas | different types just doesn't cut it. :) |
Reid | .. thinking on this :) |
nicholas | similarly, i could create a yucky with a struct that has a char *, then have you GEP right through the pointer into the pointed-to data. That could mean that the resulting point might alias anything. |
Yorion | my theory (after reading BAA) is that all zeros can be omitted, and that the pointers alias if they have the same sequence of indices |
Yorion | however, this screws the typing, so that's why zeros are for |
Yorion | nicholas, does that match your hunch? |
nicholas | I have to admit, I've had much grief with GEPIs already. I wish the semantics were plainly documented as part of their own language, instead of just relying on C aliasing rules and C semantics... |
nicholas | Yorion: leading zeroes can't be omitted. |
Reid | okay, if you have two GEPs and their leading indices are an exact match, if the one with more indices only has trailing 0s then they should alias |
nicholas | must alias, i think. |
Reid | yes, must alias, sorry |
Yorion | okay |
Yorion | I'm glad we cleared this up |
Reid | so, if y1 = GEP X, 1,2,0 and if y2 = GEP X, 1,2,0,0,0 then y1 "must alias" y2 :) |
Reid | but that doesn't work for leading 0s :) |
Yorion | yes, true... I was wrong |
Reid | I too have been having fun with GEP recently :) |
Yorion | but, there're cases like [a = GEP x,1,0; b = GEP a,1,0; c = GEP b,1,0], and that should be equivalent to GEP x,1,0,1,0,1 |
Reid | not quite |
nicholas | I'm sure another rule can be written for GEPIs, but they would only apply to type-safe code. |
nicholas | another *tautology |
Yorion | Reid: why not, only the type should be different... |
Reid | its should be equivalent to GEP x,1,0,1,0,1,0 |
Yorion | and that must alias GEP x,1,0,1,0,1 |
Reid | hmm, by the previous rule, I guess you're right :) |
Yorion | I'm a bit scared that even you're a bit confused about GEP |
Reid | I'm glad I'm not the only one that gets a little confused wrapping my head around this stuff :) |
Reid | GEP has always confused me .. partly because I think its wrong :) |
Reid | well, actually, not so much that GEP is wrong, but that gvars being pointers without storage |
Reid | i.e. when you say "%x = global int" in LLVM, the type of X is int* |
Reid | yet, there is no storage for that pointer |
Reid | its magically deduced |
nicholas | well, it makes no sense to have globals be SSA... |
Reid | heh |
Reid | yeah, well .. practicalities :) |
Yorion | true |
Yorion | sabre gave me a reference on how globals are handled in SSA |
Reid | anyway, gotta run |
Yorion | the paper was crappy, but I do understand now why is it implemented that way in LLVM |
Yorion | thx for the interesting discussion Reid |
Reid | heh .. its one that Chris and I keep having .. he just tells me that C has rotted my brain :) |
nicholas | lol |
Yorion | hehehe |
Reid | he might be right :) |
Yorion | sabre: have you seen the discussion on GEP? |
sabre | no |
sabre | I'll read the backlog, j/s |
sabre | ok, there's a lot |
sabre | what's the executive summary? |
sabre | do you have a q? |
Yorion | is it possible that GEP x,0,0,1 and GEP x,1 alias? |
sabre | no |
Yorion | and b) GEP x,1,0,0 and GEP x,1 should alias, right? |
sabre | I assume you mean for size = 1 ? |
sabre | b) yes |
Yorion | although they have different types |
sabre | right |
Yorion | okay |
Yorion | I'm still not 100% convinced that: a=GEP x,1,0; b=GEP a,1,0; c=GEP b,1,0 cannot alias Z=GEP x,1,1,1 |
Yorion | (that c and z cannot alias) |
sabre | that's becuse they do alias |
sabre | mustalias in fact |
Yorion | but then: GEP x,1,0,1,0,1,0 = GEP x,1,1,1 |
sabre | Yorion: no |
sabre | c != GEP x,1,0,1,0,1,0 |
sabre | the first index doesn't work like that |
Yorion | how does then the first index work? c and z must alias, but GEP x,1,0,1,0 != GEP x,1,1 ?? |
sabre | *sigh* |
Reid | :) |
Reid | we need an FAQ on this |
sabre | Yorion: how did you get |
sabre | "GEP x,1,0,1,0"? |
Yorion | look |
sabre | you can't just concatenate subscripts |
Yorion | why? |
sabre | because... it doesn't work that way? |
sabre | consider C |
Yorion | how does it work? |
sabre | if I have blah* P |
sabre | P[0][1][2][3][4] |
sabre | this is *not* the same as: |
sabre | t = &P[0][1][2] ... t[3][4] |
sabre | Yorion: Consider: struct *P |
sabre | P->X == P[0].X |
sabre | You're losing the 0. |
sabre | P->X->Y == P[0].X[0].Y |
sabre | Not P.X.Y |
sabre | actually that's a bad analogy |
sabre | because C dereferences in this case |
sabre | Try: (&(P->X))->Y |
Yorion | so, a=GEP x,1,0; b=GEP a,1,0; c=GEP b,1,0, can you construct the definition of c in terms of x? |
sabre | yes, but you're going out of bounds :) |
sabre | consider this: |
sabre | { float, { double , { int } } } *P |
sabre | int *X = gep P, 0, 1, 1, 0 |
sabre | do you understand the leading zero? |
sabre | alternatively: |
sabre | t = gep P, 0, 1 |
sabre | t2 = gep t, 0, 1 |
sabre | X = gep t, 0, 0 |
Yorion | what's t2 for? |
sabre | oh |
sabre | sorry :) |
sabre | X = gep t2, 0, 0 |
Yorion | give me a minute please |
sabre | ok |
Yorion | sabre: shouldn't the type be: { float, { double, { int }* } }* P ? |
sabre | nope |
sabre | why the extra * ? |
sabre | if it helps, the type of t is { double, {int}}* and t2 is {int}* and X is int* |
Yorion | wait... 0 represents dereference, natural number i - represents &A[i] ? |
sabre | gep does no dereferences, ever |
sabre | gep P, 0, 1 is equivalent to &P[0].X |
sabre | aka &P->X |
sabre | gep P, 1 == &P[1] aka P+1 |
sabre | so gep P, 0, 1 can't alias gep P, 1 just like - &P->Y can't alias P+1 |
sabre | assuming P is a pointer to struct {X, Y } |
Yorion | sabre: is it possible to come up with a general rule for "arithmetic of GEP indices"? |
sabre | Yorion: of course, it's very simple |
sabre | just not what you're expecting :) |
sabre | See langref.html |
Yorion | for example, a=GEP x,0,0,1 b=GEP a,0,0,1, c=GEP b,0,0,1, that should be equal to GEP x,0,1,1,0, right? |
Yorion | I did |
Yorion | oops, equal to GEP x,0,1,1,1,0 |
sabre | that would be: |
sabre | GEP X, 0, 0, 1, 0, 1, 0, 1 |
Yorion | you're killing me |
sabre | The basic rule when turning: A = GEP B, C D = GEP A, 0, E |
sabre | is that you drop the 0, turning it into |
sabre | GEP B, C, E |
Yorion | okay, that's good. any other rules? |
nicholas | what if it isn't a 0? |
sabre | more generally: A = GEP Ptr, B, C, ... D = GEP A, 0, E, F, ... |
sabre | D = GEP Ptr, B, C, ... E, F, ... |
sabre | if it's not zero, you generally cannot concatenate them |
sabre | unless the first gep has one subscript |
sabre | in which case you drop the zero |
sabre | if you look in InstCombiner::visitGetElementPtrInst, it should have this logic |
Yorion | what if there is no zero? how can I compute the offset from the base pointer in that case? |
Yorion | like A=GEP B,C and D=GEP A,E,F |
sabre | you don't have to combine them to compute an offset |
sabre | are you *just* trying to get a byte offset from the pointer? |
Yorion | I'm trying to get offset of D from B |
sabre | why didn't you say so? :) |
sabre | with all constant subscripts, it's trivial |
sabre | look at SelectionDAGLowering::visitGetElementPtr |
sabre | in CodeGen/SelectionDAG/SelectionDAGISel.cpp |
sabre | basically the rule is that you multiply the index by the size of the thing indexed |
sabre | there is also a Support/GetElementPtrIterator or something |
sabre | that makes it trivial to see what type is indexed by which subscript |
sabre | for each subscript it gives you a type |
sabre | For an array subscript you multiply the index by the indexed type |
sabre | for a struct subscript, you add the field offset |
sabre | s/array/sequentialtype/ if you're in a pedantic mood |
Yorion | let's focus on structs: in that case, the above given example would be: D = GEP B,C,E,F? |
sabre | no |
sabre | you drop the E if it's zero |
sabre | if it's not you can't concat |
sabre | are you trying to trick me into saying "yes, just append the indices"? :) |
Yorion | okay, let's assume E is not zero, how do I compute offset from B for D for a struct? |
sabre | Why are you framing this in terms of concatenation? |
Yorion | no, I'm trying to understand it |
sabre | computing an offset and concatenating are entirely different |
sabre | Lets consider a specific example |
Yorion | because I want to express certain properties in the terms of base pointers either globals or parameters |
Yorion | I want to eliminate locals from my analysis |
sabre | you realize that parmeters can point into the middle of structs? |
Yorion | yes |
sabre | you realize invalid access paths can be constructed with geps/ |
sabre | ? |
Yorion | what do you mean by invalid access paths? |
Yorion | like offseting out of the struct which is passed to the function? |
sabre | The case where the subscript isn't zero is invalid code |
sabre | from a type-safety perspective |
DannyB | he means untypesafe things that seem valid :) |
DannyB | IE they point somewhere in the struct, but not to any particular field |
DannyB | (or whatever) |
sabre | right |
Yorion | okay |
sabre | or they might point in some other struct :) |
sabre | It's the equivalent to saying: |
sabre | struct Foo { int A, int B; } |
sabre | Foo* P = |
sabre | T = &P->B; |
sabre | S = T+1 |
sabre | that is: |
sabre | T = gep 0, 1 |
sabre | S = gep T, 1 |
sabre | you can't concat those and get a type-safe access path |
sabre | remember T = &P->B === T = &P[0].B |
sabre | understand? |
Yorion | let me think for a minute |
sabre | Consider what the C case does, it will be most clear if you're used to C |
sabre | :) |
sabre | Consider the byte offset and why it doesn't point into P-> anything |
sabre | it points into P[1] not P[0] |
Yorion | it's perfectly fine if GEP offsets out of the type. I'd still need to express GEP in the terms of base pointers. Take the example above: T=GEP P,0,1; S=GEP T,1 |
Yorion | type safety is not crucial in my case |
sabre | That specific example is GEP P, 1, 0 |
sabre | however, you can form geps that are NOT equivalent to anything else |
sabre | for example, consider: |
sabre | struct X { int, char} |
Yorion | that is fine. they're equivalent to something in the calling context |
sabre | the same sequence points into padding |
sabre | and there is no gep that can do that |
Yorion | the bottom line is: if the program is valid, interprocedural analysis will match that offset with something in one of the functions on the call stack |
Yorion | and that's all I care about |
Yorion | can you give me a formula for structs for computing - offsets that takes into account the case GEP T,<:non_zeros> and the size of the structs/fields? |
sabre | yes, I did above |
sabre | Two things: |
sabre | GEP Ptr, A, X, Y, Z |
sabre | The result is Ptr + A * sizeof(struct) + fieldoffs(X) + fieldoffs(Y) + fieldoffs(Z) |
sabre | simple enough? |
sabre | you see why "A" is special? |
Yorion | give me a min, I'm constructing an example |
Reid | sabre: I think I finally understand |
Reid | your comment that GEP *never* dereferences makes a lot of sense |
Reid | it is only doing address calculation, so the first one is taking the address of the var |
sabre | If C didn't conflate lvalues and rvalues, GEP would be much easier to understand for people |
Reid | yeah |
Yorion | so, for example: M=GEP A,B,C; N=GEP M,D,E; N = [ A + B*sizeof(struct) + fieldoffs(C) ]:(of type T) + D*sizeof(T) + fieldoffs(E) |
Reid | I just remember learning a hard lesson about the difference between char* A and char A[] .. long time ago when I was learning C |
sabre | of type T* |
sabre | otherwise fine |
Yorion | okay, I think I finally understand it |
sabre | without the T* your D sizeof will be wrong |
Yorion | a suggestion: the formula you gave above explains it all |
Yorion | I'd suggest explaining it that way in documentation |
sabre | That's not right though |
sabre | it doesn't include arrays or packed types |
sabre | so it is, at best, a half truth |
Yorion | tell me, how to compute the fieldoffs for an index? |
sabre | arrays can be in structs :) |
Yorion | in bytes |
sabre | idx * sizeof(arrayelt) |
sabre | just like for pointers (the first index) |
sabre | There are two cases: structs and sequentials |
sabre | for sequentials you use idx*sizeof(sequenced type) |
sabre | for structs you add their offset |
sabre | it's really very simple :) |
sabre | the first index of a gep is always over the pointer |
Yorion | no I meant in LLVM, how do I convert the field offset into bytes? |
sabre | which is why it's strange |
sabre | if you only think about structs |
sabre | TargetData::getFieldOffset |
sabre | or something |
sabre | look in SelectionDAGISel.cpp (visitGEP) as I suggested. |
Yorion | do you still have the energy to go over sequential types? :-) |
Yorion | what is the offset formula for sequential types? |
Reid | we just went over that: idx * sizeof(elementType) |
Yorion | so, if there's an array hidden somewhere in the struct, essentially I need to compute idx*sizeof() instead of fieldoffs() and that's it? |
sabre | yes |
Reid | yes |
Yorion | excellent. |
sabre | There are two cases: structs and sequentials |
sabre | [9:17pm] sabre: for sequentials you use idx*sizeof(sequenced type) |
sabre | [9:17pm] sabre: for structs you add their offset |
sabre | [9:17pm] sabre: it's really very simple :) |
Yorion | now when I understand it, it is simple... |
Yorion | thx |