<font size=2 face="sans-serif">Hello all,</font><br><br><font size=2 face="sans-serif">I'm new to the llvm community.  I'm
learning how things work.  I noticed that there has been some interest
in improving how unions are handled.  Bug 21725 is one example.  I
figured it might be a interesting place to start.  I discussed this
with a couple people, and below is a suggestion on how to represent unions.
 I would like some comments on how this fits in with how things are
done in llvm.</font><br><br><font size=2 face="sans-serif">Later,</font><br><font size=2 face="sans-serif">Steven Perron</font><br><br><font size=2 face="sans-serif">Motivation</font><br><font size=2 face="sans-serif">==========</font><br><br><font size=2 face="sans-serif">The main motivation for this is functional
correctness of code using unions.</font><br><font size=2 face="sans-serif">See </font><a href="https://llvm.org/bugs/show_bug.cgi?id=21725"><font size=2 face="sans-serif">https://llvm.org/bugs/show_bug.cgi?id=21725</font></a><font size=2 face="sans-serif">for one example.  The problem is</font><br><font size=2 face="sans-serif">that the basic alias analysis (or any
other alias analysis) will not always have</font><br><font size=2 face="sans-serif">enough information to be able see that
the two references definitely overlap.</font><br><font size=2 face="sans-serif">When this happens, the lack of alias
information for unions could allow</font><br><font size=2 face="sans-serif">undesired optimizations.</font><br><br><br><font size=2 face="sans-serif">Current state</font><br><font size=2 face="sans-serif">=============</font><br><br><font size=2 face="sans-serif">For this RFC, we are interested in how
the type based aliasing is represented</font><br><font size=2 face="sans-serif">for non-scalar data types.  In
C/C++, this will be arrays, structs, classes, and</font><br><font size=2 face="sans-serif">unions.  We will not mention classes
again because for this purpose they are the</font><br><font size=2 face="sans-serif">exact same as structs.</font><br><br><font size=2 face="sans-serif">We will start with structs.  To
help with the aliasing of structs, There is a</font><br><font size=2 face="sans-serif">format for the type based aliasing meta
data known as the struct-path.  Here is</font><br><font size=2 face="sans-serif">example IR:</font><br><br><font size=2 face="sans-serif"> %0 = load i32, i32* getelementptr
inbounds (%struct.S, %struct.S* @s, i32 0, %i32 2), align 4, !tbaa !2</font><br><font size=2 face="sans-serif"> %1 = load i32, i32* getelementptr
inbounds (%struct.S, %struct.S* @s, i32 0, %i32 3), align 4, !tbaa !7</font><br><font size=2 face="sans-serif"> ...</font><br><font size=2 face="sans-serif"> !2 = !{!3, !6, i64 800}</font><br><font size=2 face="sans-serif"> !3 = !{!"S", !4, i64
0, !4, i64 400, !6, i64 800, !6, i64 804}</font><br><font size=2 face="sans-serif"> !4 = !{!"omnipotent char",
!5, i64 0}</font><br><font size=2 face="sans-serif"> !5 = !{!"Simple C/C++ TBAA"}</font><br><font size=2 face="sans-serif"> !6 = !{!"int", !4, i64
0}</font><br><font size=2 face="sans-serif"> !7 = !{!3, !6, i64 804}</font><br><br><font size=2 face="sans-serif">The two loads are loads of different
int members of the same struct.  The type</font><br><font size=2 face="sans-serif">based aliasing gives them different
meta data tags (!2 and !7).  This allows the</font><br><font size=2 face="sans-serif">analysis to determine that they are
different solely from the type based</font><br><font size=2 face="sans-serif">aliasing information.  Looking
at !2, it points to !3 with offset 800.  This</font><br><font size=2 face="sans-serif">offset is used to identify which member
of the struct is being accessed.</font><br><br><font size=2 face="sans-serif">Next we will consider arrays.  When
there is an array access, the type based</font><br><font size=2 face="sans-serif">aliasing views it as an access of the
type of the element.  In general, this is</font><br><font size=2 face="sans-serif">not a problem.  For C/C++, there
is no real difference between an array</font><br><font size=2 face="sans-serif">reference and a dereference of a pointer.
 However, this causes a lose of</font><br><font size=2 face="sans-serif">information when accessing arrays that
are part of a struct or union.</font><br><br><font size=2 face="sans-serif">Here is an example:</font><br><br><font size=2 face="sans-serif">  %arrayidx = getelementptr inbounds
[100 x i32], [100 x i32]* getelementptr %inbounds (%struct.S, %struct.S*
@s, i32 0, i32 0), i64 0, i64 %idxprom</font><br><font size=2 face="sans-serif">  %1 = load i32, i32* %arrayidx,
align 4, !tbaa !1</font><br><font size=2 face="sans-serif">  ...</font><br><font size=2 face="sans-serif">  !1 = !{!2, !2, i64 0}</font><br><font size=2 face="sans-serif">  !2 = !{!"int", !3,
i64 0}</font><br><br><font size=2 face="sans-serif">This is an access to an array of integers
in a struct of type S.  Note that the</font><br><font size=2 face="sans-serif">type on the load is "int".
 The type bases alias information has lost that this</font><br><font size=2 face="sans-serif">is a reference to a member of a struct.</font><br><br><font size=2 face="sans-serif">We finish by considering unions.  Like
arrays, an access to a member of a union</font><br><font size=2 face="sans-serif">is treated as if is it type of the type
of the member being accessed.  Here is</font><br><font size=2 face="sans-serif">an example:</font><br><br><font size=2 face="sans-serif">  %4 = load i32, i32* getelementptr
inbounds (%union.U, %union.U* @u, i32 0, i32 %0), align 4, !tbaa !2</font><br><font size=2 face="sans-serif">  ...</font><br><font size=2 face="sans-serif">  !2 = !{!3, !3, i64 0}</font><br><font size=2 face="sans-serif">  !3 = !{!"int", !4,
i64 0}</font><br><br><font size=2 face="sans-serif">Here we lose the information that the
reference is part of a union, so we cannot</font><br><font size=2 face="sans-serif">tell that this memory may overlap with
something of a different type.  Clang</font><br><font size=2 face="sans-serif">currently relies on other aliasing analysis
like the basic alias analysis to</font><br><font size=2 face="sans-serif">observer that the two references are
aliased.</font><br><br><font size=2 face="sans-serif">Proposed changes for arrays</font><br><font size=2 face="sans-serif">===========================</font><br><br><font size=2 face="sans-serif">To deal with array references, they
should be treated as if all array accesses</font><br><font size=2 face="sans-serif">are accesses to the first member of
the array.  For the purpose of type based</font><br><font size=2 face="sans-serif">aliasing, this should be good enough.
 The offset in the tag would be the</font><br><font size=2 face="sans-serif">offset of the start of the array plus,
if applicable, the offset needed to</font><br><font size=2 face="sans-serif">access the member of the array element
as if the element was a top-level struct</font><br><font size=2 face="sans-serif">member at offset 0.  Note that
the values for the indexing of the array is not</font><br><font size=2 face="sans-serif">included.  Thus, accesses to an
element of the last dimension of a</font><br><font size=2 face="sans-serif">multidimensional array appears the same
as an access to a flattened version of</font><br><font size=2 face="sans-serif">the multidimensional array.  Then,
in the struct path, the array member's offset</font><br><font size=2 face="sans-serif">will be the starting offset of the array,
as it is now.  What will change in the</font><br><font size=2 face="sans-serif">struct path is the type node for the
array.  The type node will become the type</font><br><font size=2 face="sans-serif">of the array element instead of "omnipotent
char", as it is now.</font><br><br><font size=2 face="sans-serif">This change is a must to be able to
get union aliasing correct because we need</font><br><font size=2 face="sans-serif">to know when an array is part of a union
that may overlap with other members.</font><br><br><br><br><font size=2 face="sans-serif">Proposed changes for unions</font><br><font size=2 face="sans-serif">============================</font><br><br><font size=2 face="sans-serif">To properly deal with unions, there
are a few issues that need to be dealt with.</font><br><br><font size=2 face="sans-serif">1) Unions have to somehow be represented
in the TBAA.  As was pointed out above,</font><br><font size=2 face="sans-serif">this information is currently lost.</font><br><br><font size=2 face="sans-serif">2) With the struct path TBAA, it is
assumed that the length of a member extends</font><br><font size=2 face="sans-serif">to the start of the next.  This
will not be true for unions.</font><br><br><font size=2 face="sans-serif">3) With the current struct path TBAA,
you can determine which member is</font><br><font size=2 face="sans-serif">reference by looking at the offset.
 That is not true with unions because every</font><br><font size=2 face="sans-serif">member starts at offset 0.  We
will need another way of doing this for unions.</font><br><br><font size=2 face="sans-serif">Any solution we come up with will have
to get around these three problems.</font><br><br><font size=2 face="sans-serif">To deal with unions, we will use the
change in bug 21725 (see link above).  This</font><br><font size=2 face="sans-serif">will treat a union as if it is a struct.
 However, the important change to make</font><br><font size=2 face="sans-serif">the unions work is that the length of
the memory reference will have to be taken</font><br><font size=2 face="sans-serif">into consideration when looking at the
type based aliasing.  This should be easy</font><br><font size=2 face="sans-serif">enough because TypeBasedAAResult::alias
takes two arguments of type</font><br><font size=2 face="sans-serif">MemoryLocation, and they contain the
size information that is needed.  This</font><br><font size=2 face="sans-serif">should easy take care of the first two
problems.</font><br><br><font size=2 face="sans-serif">In TypeBasedAAResult::alias, we will
also have to deal with the fact that unions</font><br><font size=2 face="sans-serif">have multiple members all at offset
0.  This means that, unlike structs, the</font><br><font size=2 face="sans-serif">compiler will not be able to tell which
member of the union the memory reference</font><br><font size=2 face="sans-serif">actually used.  To deal with this,
TypeBasedAAResult::alias (and the functions</font><br><font size=2 face="sans-serif">it calls) will have to acts as if all
of the unions members could have been</font><br><font size=2 face="sans-serif">accessed.  So the search along
the tree will follow all of the member instead of</font><br><font size=2 face="sans-serif">just one as we currently do with structs.
 Changes to the algorithm can be made</font><br><font size=2 face="sans-serif">to avoid traversing the same TBAA nodes
multiple times.  The section at the end</font><br><font size=2 face="sans-serif">explores the consequences of this decision
and a possible alternative.</font><br><br><font size=2 face="sans-serif">Examples</font><br><font size=2 face="sans-serif">========</font><br><br><font size=2 face="sans-serif">Source code for the example</font><br><font size=2 face="sans-serif">---------------------------</font><br><br><font size=2 face="sans-serif">struct S</font><br><font size=2 face="sans-serif">{</font><br><font size=2 face="sans-serif">  int b;</font><br><font size=2 face="sans-serif">  struct T</font><br><font size=2 face="sans-serif">  {</font><br><font size=2 face="sans-serif">    int a[10];</font><br><font size=2 face="sans-serif">  } t;</font><br><font size=2 face="sans-serif">} s;</font><br><br><font size=2 face="sans-serif">struct C</font><br><font size=2 face="sans-serif">{</font><br><font size=2 face="sans-serif">  int a;</font><br><font size=2 face="sans-serif">  int b;</font><br><font size=2 face="sans-serif">};</font><br><br><font size=2 face="sans-serif">struct R</font><br><font size=2 face="sans-serif">{</font><br><font size=2 face="sans-serif">  union {</font><br><font size=2 face="sans-serif">    struct C a[10];</font><br><font size=2 face="sans-serif">    struct C b[10];</font><br><font size=2 face="sans-serif">  } u;</font><br><font size=2 face="sans-serif">  int c;</font><br><font size=2 face="sans-serif">} r;</font><br><br><font size=2 face="sans-serif">union U</font><br><font size=2 face="sans-serif">{</font><br><font size=2 face="sans-serif">  int i;</font><br><font size=2 face="sans-serif">  float f;</font><br><font size=2 face="sans-serif">} u;</font><br><br><font size=2 face="sans-serif">struct Q</font><br><font size=2 face="sans-serif">{</font><br><font size=2 face="sans-serif">  int a;</font><br><font size=2 face="sans-serif">  union U u;</font><br><font size=2 face="sans-serif">} q;</font><br><br><font size=2 face="sans-serif">int foo()</font><br><font size=2 face="sans-serif">{</font><br><font size=2 face="sans-serif">  return s.t.a[4] + s.b + r.u.b[3].b
+ u.i + u.f + q.u.i + q.u.f + q.a + r.c;</font><br><font size=2 face="sans-serif">}</font><br><br><font size=2 face="sans-serif">----------------------------</font><br><font size=2 face="sans-serif">Current llvm-ir</font><br><font size=2 face="sans-serif">----------------------------</font><br><br><font size=2 face="sans-serif">*** IR Dump Before Module Verifier ***</font><br><font size=2 face="sans-serif">; Function Attrs: nounwind</font><br><font size=2 face="sans-serif">define signext i32 @foo() #0 {</font><br><font size=2 face="sans-serif">entry:</font><br><font size=2 face="sans-serif">  %0 = load i32, i32* getelementptr
inbounds (%struct.S, %struct.S* @s, i32 0, i32 1, i32 0, i64 4), align
4, !tbaa !2</font><br><font size=2 face="sans-serif">  %1 = load i32, i32* getelementptr
inbounds (%struct.S, %struct.S* @s, i32 0, i32 0), align 4, !tbaa !6</font><br><font size=2 face="sans-serif">  %add = add nsw i32 %0, %1</font><br><font size=2 face="sans-serif">  %2 = load i32, i32* getelementptr
inbounds (%struct.R, %struct.R* @r, i32 0, i32 0, i32 0, i64 3, i32 1),
align 4, !tbaa !9</font><br><font size=2 face="sans-serif">  %add1 = add nsw i32 %add, %2</font><br><font size=2 face="sans-serif">  %3 = load i32, i32* getelementptr
inbounds (%union.U, %union.U* @u, i32 0, i32 0), align 4, !tbaa !2</font><br><font size=2 face="sans-serif">  %add2 = add nsw i32 %add1, %3</font><br><font size=2 face="sans-serif">  %conv = sitofp i32 %add2 to float</font><br><font size=2 face="sans-serif">  %4 = load float, float* bitcast
(%union.U* @u to float*), align 4, !tbaa !11</font><br><font size=2 face="sans-serif">  %add3 = fadd float %conv, %4</font><br><font size=2 face="sans-serif">  %5 = load i32, i32* getelementptr
inbounds (%struct.Q, %struct.Q* @q, i32 0, i32 1, i32 0), align 4, !tbaa
!2</font><br><font size=2 face="sans-serif">  %conv4 = sitofp i32 %5 to float</font><br><font size=2 face="sans-serif">  %add5 = fadd float %add3, %conv4</font><br><font size=2 face="sans-serif">  %6 = load float, float* bitcast
(%union.U* getelementptr inbounds (%struct.Q, %struct.Q* @q, i32 0, i32
1) to float*), align 4, !tbaa !11</font><br><font size=2 face="sans-serif">  %add6 = fadd float %add5, %6</font><br><font size=2 face="sans-serif">  %7 = load i32, i32* getelementptr
inbounds (%struct.Q, %struct.Q* @q, i32 0, i32 0), align 4, !tbaa !13</font><br><font size=2 face="sans-serif">  %conv7 = sitofp i32 %7 to float</font><br><font size=2 face="sans-serif">  %add8 = fadd float %add6, %conv7</font><br><font size=2 face="sans-serif">  %8 = load i32, i32* getelementptr
inbounds (%struct.R, %struct.R* @r, i32 0, i32 1), align 4, !tbaa !15</font><br><font size=2 face="sans-serif">  %conv9 = sitofp i32 %8 to float</font><br><font size=2 face="sans-serif">  %add10 = fadd float %add8, %conv9</font><br><font size=2 face="sans-serif">  %conv11 = fptosi float %add10
to i32</font><br><font size=2 face="sans-serif">  ret i32 %conv11</font><br><font size=2 face="sans-serif">}</font><br><br><font size=2 face="sans-serif">!0 = !{i32 1, !"PIC Level",
i32 2}</font><br><font size=2 face="sans-serif">!1 = !{!"clang version 4.0.0 (trunk
290896)"}</font><br><font size=2 face="sans-serif">!2 = !{!3, !3, i64 0}</font><br><font size=2 face="sans-serif">!3 = !{!"int", !4, i64 0}</font><br><font size=2 face="sans-serif">!4 = !{!"omnipotent char",
!5, i64 0}</font><br><font size=2 face="sans-serif">!5 = !{!"Simple C/C++ TBAA"}</font><br><font size=2 face="sans-serif">!6 = !{!7, !3, i64 0}</font><br><font size=2 face="sans-serif">!7 = !{!"S", !3, i64 0, !8,
i64 4}</font><br><font size=2 face="sans-serif">!8 = !{!"T", !4, i64 0}</font><br><font size=2 face="sans-serif">!9 = !{!10, !3, i64 4}</font><br><font size=2 face="sans-serif">!10 = !{!"C", !3, i64 0, !3,
i64 4}</font><br><font size=2 face="sans-serif">!11 = !{!12, !12, i64 0}</font><br><font size=2 face="sans-serif">!12 = !{!"float", !4, i64
0}</font><br><font size=2 face="sans-serif">!13 = !{!14, !3, i64 0}</font><br><font size=2 face="sans-serif">!14 = !{!"Q", !3, i64 0, !4,
i64 4}</font><br><font size=2 face="sans-serif">!15 = !{!16, !3, i64 80}</font><br><font size=2 face="sans-serif">!16 = !{!"R", !4, i64 0, !3,
i64 80}</font><br><br><font size=2 face="sans-serif">----------------------------</font><br><font size=2 face="sans-serif">Suggested new llvm-ir</font><br><font size=2 face="sans-serif">----------------------------</font><br><br><font size=2 face="sans-serif">*** IR Dump Before Module Verifier ***</font><br><font size=2 face="sans-serif">; Function Attrs: nounwind</font><br><font size=2 face="sans-serif">define signext i32 @foo() #0 {</font><br><font size=2 face="sans-serif">entry:</font><br><font size=2 face="sans-serif">  %0 = load i32, i32* getelementptr
inbounds (%struct.S, %struct.S* @s, i32 0, i32 1, i32 0, i64 4), align
4, !tbaa !2</font><br><font size=2 face="sans-serif">  %1 = load i32, i32* getelementptr
inbounds (%struct.S, %struct.S* @s, i32 0, i32 0), align 4, !tbaa !6</font><br><font size=2 face="sans-serif">  %add = add nsw i32 %0, %1</font><br><font size=2 face="sans-serif">  %2 = load i32, i32* getelementptr
inbounds (%struct.R, %struct.R* @r, i32 0, i32 0, i32 0, i64 3, i32 1),
align 4, !tbaa !9</font><br><font size=2 face="sans-serif">  %add1 = add nsw i32 %add, %2</font><br><font size=2 face="sans-serif">  %3 = load i32, i32* getelementptr
inbounds (%union.U, %union.U* @u, i32 0, i32 0), align 4, !tbaa !18  
                     
// Need to change to reference the union "U", not just the scalar.</font><br><font size=2 face="sans-serif">  %add2 = add nsw i32 %add1, %3</font><br><font size=2 face="sans-serif">  %conv = sitofp i32 %add2 to float</font><br><font size=2 face="sans-serif">  %4 = load float, float* bitcast
(%union.U* @u to float*), align 4, !tbaa !11</font><br><font size=2 face="sans-serif">  %add3 = fadd float %conv, %4</font><br><font size=2 face="sans-serif">  %5 = load i32, i32* getelementptr
inbounds (%struct.Q, %struct.Q* @q, i32 0, i32 1, i32 0), align 4, !tbaa
!19                // Need to reference
the top level struct "Q", and not just the scalar.</font><br><font size=2 face="sans-serif">  %conv4 = sitofp i32 %5 to float</font><br><font size=2 face="sans-serif">  %add5 = fadd float %add3, %conv4</font><br><font size=2 face="sans-serif">  %6 = load float, float* bitcast
(%union.U* getelementptr inbounds (%struct.Q, %struct.Q* @q, i32 0, i32
1) to float*), align 4, !tbaa !20     // Need to reference the
struct "Q".</font><br><font size=2 face="sans-serif">  %add6 = fadd float %add5, %6</font><br><font size=2 face="sans-serif">  %7 = load i32, i32* getelementptr
inbounds (%struct.Q, %struct.Q* @q, i32 0, i32 0), align 4, !tbaa !13</font><br><font size=2 face="sans-serif">  %conv7 = sitofp i32 %7 to float</font><br><font size=2 face="sans-serif">  %add8 = fadd float %add6, %conv7</font><br><font size=2 face="sans-serif">  %8 = load i32, i32* getelementptr
inbounds (%struct.R, %struct.R* @r, i32 0, i32 1), align 4, !tbaa !15</font><br><font size=2 face="sans-serif">  %conv9 = sitofp i32 %8 to float</font><br><font size=2 face="sans-serif">  %add10 = fadd float %add8, %conv9</font><br><font size=2 face="sans-serif">  %conv11 = fptosi float %add10
to i32</font><br><font size=2 face="sans-serif">  ret i32 %conv11</font><br><font size=2 face="sans-serif">}</font><br><br><font size=2 face="sans-serif">!0 = !{i32 1, !"PIC Level",
i32 2}</font><br><font size=2 face="sans-serif">!1 = !{!"clang version 4.0.0 (trunk
290896)"}</font><br><font size=2 face="sans-serif">!2 = !{!7, !3, i64 4}    
                     
        // Need to change to point to the struct "S"
with the starting offset of the array.</font><br><font size=2 face="sans-serif">!3 = !{!"int", !4, i64 0}</font><br><font size=2 face="sans-serif">!4 = !{!"omnipotent char",
!5, i64 0}</font><br><font size=2 face="sans-serif">!5 = !{!"Simple C/C++ TBAA"}</font><br><font size=2 face="sans-serif">!6 = !{!7, !3, i64 0}</font><br><font size=2 face="sans-serif">!7 = !{!"S", !3, i64 0, !8,
i64 4}</font><br><font size=2 face="sans-serif">!8 = !{!"T", !3, i64 0}  
                     
        // Use "int" for the type of the
array instead of "omnipotent char.".</font><br><font size=2 face="sans-serif">!9 = !{!16, !3, i64 44}    
                     
      // Point to the outermost struct "R" instead
of "C".  Add the offset of the array in "R" and
the offset of the member in "C".</font><br><font size=2 face="sans-serif">!10 = !{!"C", !3, i64 0, !3,
i64 4}</font><br><font size=2 face="sans-serif">!11 = !{!17, !12, i64 0}    
                     
     // Need to point to the union "U" instead
of using the scalar.</font><br><font size=2 face="sans-serif">!12 = !{!"float", !4, i64
0}</font><br><font size=2 face="sans-serif">!13 = !{!14, !3, i64 0}</font><br><font size=2 face="sans-serif">!14 = !{!"Q", !3, i64 0, !17,
i64 4}                    //
Use the union "U" as the type for the member.</font><br><font size=2 face="sans-serif">!15 = !{!16, !3, i64 80}</font><br><font size=2 face="sans-serif">!16 = !{!"R", !21, i64 0,
!3, i64 80}                  
// Have the first member point to the union "R.u".</font><br><font size=2 face="sans-serif">!17 = !{!"U", !3, i64 0, !12,
i64 0}                    //
Introduce the struct path for the union.</font><br><font size=2 face="sans-serif">!18 = !{!17, !3, i64 0}    
                     
      // Tag for a union reference goes through the union.</font><br><font size=2 face="sans-serif">!19 = !{!14, !3, i64 4}    
                     
      // Tag for a union reference inside a struct points
to the top level struct.</font><br><font size=2 face="sans-serif">!20 = !{!14, !11, i64 4}    
                     
     // Same as !19 except for the float.</font><br><font size=2 face="sans-serif">!21 = !{!"R.u", !10, i64 0,
!10, i64 0}                 //
Add a struct path for the union defined in "R". </font><br><br><br><font size=2 face="sans-serif">Multiple members at the same offset</font><br><font size=2 face="sans-serif">===================================</font><br><br><font size=2 face="sans-serif">Consider the following example:</font><br><br><font size=2 face="sans-serif">union U {</font><br><font size=2 face="sans-serif">  int a;</font><br><font size=2 face="sans-serif">  float b;</font><br><font size=2 face="sans-serif">};</font><br><br><font size=2 face="sans-serif">int foo( U * u, int * i, float * f )</font><br><font size=2 face="sans-serif">{</font><br><font size=2 face="sans-serif">  *i = 0;</font><br><font size=2 face="sans-serif">  *f = 100.0;</font><br><font size=2 face="sans-serif">  return u->a;</font><br><font size=2 face="sans-serif">}</font><br><br><font size=2 face="sans-serif">With the changes I described above,
the reference "u->a" will alias both "*i"</font><br><font size=2 face="sans-serif">and "*f" because, when we
see the struct-path for the union, we will follow path</font><br><font size=2 face="sans-serif">for "a" and "b".
 This may be more conservative than we want.  It might also be</font><br><font size=2 face="sans-serif">exactly what we want.</font><br><br><font size=2 face="sans-serif">The difficulty in being more precise
is that, in general, we cannot know which</font><br><font size=2 face="sans-serif">member of the union was access with
the current information in the llvm-ir.  If</font><br><font size=2 face="sans-serif">we want to fix this we can create a
new scalar to represent the members</font><br><font size=2 face="sans-serif">which will be used as the scalar meta
data in the tag.  Then, when a struct-path</font><br><font size=2 face="sans-serif">node for a union is reached, we will
have to search each possible path to see if</font><br><font size=2 face="sans-serif">it reaches the scalar node on the tag.
 If it does, that is the path we follow.</font><br><br><font size=2 face="sans-serif">With this change, the llvm-ir for the
example would be:</font><br><br><font size=2 face="sans-serif">define signext i32 @foo(%union.U* %u,
i32* %i, float* %f) #0 {</font><br><font size=2 face="sans-serif">entry:</font><br><font size=2 face="sans-serif">  store i32 0, i32* %i, align 4,
!tbaa !2</font><br><font size=2 face="sans-serif">  store float 1.000000e+02, float*
%f, align 4, !tbaa !6</font><br><font size=2 face="sans-serif">  %a = bitcast %union.U* %u to
i32*</font><br><font size=2 face="sans-serif">  %0 = load i32, i32* %a, align
4, !tbaa !11            // Use the new tag</font><br><font size=2 face="sans-serif">  ret i32 %0</font><br><font size=2 face="sans-serif">}</font><br><br><font size=2 face="sans-serif">!0 = !{i32 1, !"PIC Level",
i32 2}</font><br><font size=2 face="sans-serif">!1 = !{!"clang version 4.0.0 (trunk
290896)"}</font><br><font size=2 face="sans-serif">!2 = !{!3, !3, i64 0}</font><br><font size=2 face="sans-serif">!3 = !{!"int", !4, i64 0}</font><br><font size=2 face="sans-serif">!4 = !{!"omnipotent char",
!5, i64 0}</font><br><font size=2 face="sans-serif">!5 = !{!"Simple C/C++ TBAA"}</font><br><font size=2 face="sans-serif">!6 = !{!7, !7, i64 0}</font><br><font size=2 face="sans-serif">!7 = !{!"float", !4, i64 0}</font><br><font size=2 face="sans-serif">!8 = !{!"U", !9, i64 0, !10,
i64 0}     // The struct path for the union with special members.</font><br><font size=2 face="sans-serif">!9 = !{!"U.a", !3, 0}  
                // The member of
the union.</font><br><font size=2 face="sans-serif">!10 = !{!"U.b", !7, 0}  
               // The member of
the union.</font><br><font size=2 face="sans-serif">!11 = !{!8, !9, 0}      
               // The new tag where
the scalar is the union member instead of the generic "int".</font><br><br><br><br><font size=2 face="sans-serif">Read versus write aliasing</font><br><font size=2 face="sans-serif">==========================</font><br><br><font size=2 face="sans-serif">It has come to my attention that there
is a question about whether the read</font><br><font size=2 face="sans-serif">versus write aliasing matters for union
aliasing.  Maybe there is something in</font><br><font size=2 face="sans-serif">the C/C++ specification I am missing,
but I believe we need to handle this as</font><br><font size=2 face="sans-serif">well.  Suppose we take an example
similar to the one in defect 21725:</font><br><br><font size=2 face="sans-serif">#include <stdio.h></font><br><br><font size=2 face="sans-serif">union U {</font><br><font size=2 face="sans-serif">        short s;</font><br><font size=2 face="sans-serif">        int i;</font><br><font size=2 face="sans-serif">} u;</font><br><br><font size=2 face="sans-serif">int v = 987;</font><br><font size=2 face="sans-serif">union U* up = &u;</font><br><br><font size=2 face="sans-serif">int foo()</font><br><font size=2 face="sans-serif">{</font><br><font size=2 face="sans-serif">        int temp
= u.s;</font><br><font size=2 face="sans-serif">        up->i
= 123;     // 123</font><br><font size=2 face="sans-serif">        printf("%d\n",
up->i);</font><br><font size=2 face="sans-serif">        printf("%hd\n",
temp);</font><br><font size=2 face="sans-serif">        return 0;</font><br><font size=2 face="sans-serif">}</font><br><br><font size=2 face="sans-serif">In this case, if the read of "u.s"
is not aliased to the write of "up->i" and</font><br><font size=2 face="sans-serif">they are reordered, then "temp"
could get the wrong value.</font><BR>