<HTML xmlns="http://www.w3.org/TR/REC-html40" xmlns:v =
"urn:schemas-microsoft-com:vml" xmlns:o =
"urn:schemas-microsoft-com:office:office" xmlns:w =
"urn:schemas-microsoft-com:office:word" xmlns:m =
"http://schemas.microsoft.com/office/2004/12/omml"><HEAD>
<META content="text/html; charset=us-ascii" http-equiv=Content-Type>
<META name=Generator content="Microsoft Word 15 (filtered medium)">
<STYLE><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:#0563C1;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:#954F72;
text-decoration:underline;}
span.EmailStyle17
{mso-style-type:personal-compose;
font-family:"Calibri",sans-serif;
color:windowtext;}
.MsoChpDefault
{mso-style-type:export-only;
font-family:"Calibri",sans-serif;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></STYLE>
</HEAD>
<BODY lang=EN-US dir=ltr vLink=#954f72 link=#0563c1>
<DIV dir=ltr>
<DIV style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial'; COLOR: #000000">
<DIV>I agree that’s a bit strange.</DIV>
<DIV>I dunno about SROA, but BasicAA certainly knows about structs and
unions. I don’t think right now it has any problem handling those. (and if
there’s some case it doesn’t, shouldn’t be hard to fix)</DIV>
<DIV>Also, BasicAA has special rules for arrays of structs that can conclude
no-alias even if some of the indexes aren’t constants. So you could even turn
those no-alias results into may-alias; instcombine is losing information
here.</DIV>
<DIV> </DIV>
<DIV>I guess you could lookup the history to see why/when that transformation
was introduced if noone remembers.</DIV>
<DIV> </DIV>
<DIV>Nuno</DIV>
<DIV> </DIV>
<DIV> </DIV>
<DIV
style='FONT-SIZE: small; TEXT-DECORATION: none; FONT-FAMILY: "Calibri"; FONT-WEIGHT: normal; COLOR: #000000; FONT-STYLE: normal; DISPLAY: inline'>
<DIV style="FONT: 10pt tahoma">
<DIV> </DIV>
<DIV style="BACKGROUND: #f5f5f5">
<DIV style="font-color: black"><B>From:</B> <A
title=llvm-dev@lists.llvm.org>Nema, Ashutosh via llvm-dev</A> </DIV>
<DIV><B>Sent:</B> Thursday, August 10, 2017 8:22 AM</DIV>
<DIV><B>To:</B> <A title=llvm-dev@lists.llvm.org>llvm-dev</A> </DIV>
<DIV><B>Subject:</B> [llvm-dev] InstCombine GEP</DIV></DIV></DIV>
<DIV> </DIV></DIV>
<DIV
style='FONT-SIZE: small; TEXT-DECORATION: none; FONT-FAMILY: "Calibri"; FONT-WEIGHT: normal; COLOR: #000000; FONT-STYLE: normal; DISPLAY: inline'>
<DIV class=WordSection1>
<P class=MsoNormal>Hi,<o:p></o:p></P>
<P class=MsoNormal><o:p></o:p> </P>
<P class=MsoNormal>I have a doubt with GEP transformation in the
instruction-combiner.<o:p></o:p></P>
<P class=MsoNormal><o:p></o:p> </P>
<P class=MsoNormal>Consider below test-case:<o:p></o:p></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt">struct ABC
{<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> int
A;<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> int
B[100];<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> struct XYZ
{<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> int
X;<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> int
Y[100];<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> }
OBJ;<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt">};<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt">void Setup(struct ABC
*);<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt">int foo(int offset)
{<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> struct ABC *Ptr =
malloc(sizeof(struct ABC));<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt">
Setup(Ptr);<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> return Ptr->OBJ.X +
Ptr->OBJ.Y[33];<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt">}<o:p></o:p></SPAN></P>
<P class=MsoNormal><o:p></o:p> </P>
<P class=MsoNormal>Generated IR for the test-case:<o:p></o:p></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt">define i32 @foo(i32 %offset)
local_unnamed_addr #0 {<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt">entry:<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> %call = tail call i8*
@malloc(i64 808)<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> %0 = bitcast i8* %call
to %struct.ABC*<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> tail call void
@Setup(%struct.ABC* %0) #3<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> %OBJ = getelementptr
inbounds i8, <SPAN style="BACKGROUND: yellow; mso-highlight: yellow">i8* %call,
i64 404</SPAN><o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> %X = bitcast i8* %OBJ to
i32*<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> %1 = load i32, i32* %X,
align 4, !tbaa !2<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> %arrayidx =
getelementptr inbounds i8, <SPAN
style="BACKGROUND: yellow; mso-highlight: yellow">i8* %call, i64
540</SPAN><o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> %2 = bitcast i8*
%arrayidx to i32*<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> %3 = load i32, i32* %2,
align 4, !tbaa !8<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> %add = add nsw i32 %3,
%1<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> ret i32
%add<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt">}<o:p></o:p></SPAN></P>
<P class=MsoNormal><o:p></o:p> </P>
<P class=MsoNormal>Instruction combiner transforms GEPs to i8 type, because of
this the GEP offset looks weird and the actual type information is missing on
GEP.<o:p></o:p></P>
<P class=MsoNormal>I expected the GEPs to use the actual type offsetting for
which the memory is allocated.<o:p></o:p></P>
<P class=MsoNormal><o:p></o:p> </P>
<P class=MsoNormal>Expected IR:<o:p></o:p></P>
<P class=MsoNormal><o:p></o:p> </P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt">; Function Attrs: nounwind
uwtable<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt">define i32 @foo(i32 %offset)
local_unnamed_addr #0 {<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt">entry:<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> %call = tail call i8*
@malloc(i64 808)<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> %0 = bitcast i8* %call
to %struct.ABC*<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> tail call void
@Setup(%struct.ABC* %0) #3<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> %X = getelementptr
inbounds %struct.ABC, %struct.ABC* <SPAN
style="BACKGROUND: teal; mso-highlight: teal">%0, i64 0, i32 2, i32
0</SPAN><o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> %1 = load i32, i32* %X,
align 4, !tbaa !2<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> %arrayidx =
getelementptr inbounds %struct.ABC, %struct.ABC* <SPAN
style="BACKGROUND: teal; mso-highlight: teal">%0, i64 0, i32 2, i32 1, i64
33</SPAN><o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> %2 = load i32, i32*
%arrayidx, align 4, !tbaa !8<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> %add = add nsw i32 %2,
%1<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt"> ret i32
%add<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-SIZE: 10pt">}<o:p></o:p></SPAN></P>
<P class=MsoNormal><o:p></o:p> </P>
<P class=MsoNormal>In the above IR the GEP offsetting looks very explicit for
the type struct.ABC.<o:p></o:p></P>
<P class=MsoNormal><o:p></o:p> </P>
<P class=MsoNormal>Looking at the InstCombiner source found the below code is
responsible for it:<o:p></o:p></P>
<P class=MsoNormal>1914 /// See if we can simplify:<o:p></o:p></P>
<P class=MsoNormal>1915 /// X = bitcast A* to
B*<o:p></o:p></P>
<P class=MsoNormal>1916 /// Y = gep X, <...constant
indices...><o:p></o:p></P>
<P class=MsoNormal>1917 /// into a gep of the original struct.
This is important for SROA and alias<o:p></o:p></P>
<P class=MsoNormal>1918 /// analysis of unions. If "A" is also
a bitcast, wait for A/X to be merged.<o:p></o:p></P>
<P class=MsoNormal>1919 if (BitCastInst *BCI =
dyn_cast<BitCastInst>(PtrOp)) {<o:p></o:p></P>
<P class=MsoNormal>1920 ....<o:p></o:p></P>
<P class=MsoNormal><o:p></o:p> </P>
<P class=MsoNormal>I’m not sure how transforming GEP offset to i8 type will help
alias analysis & SROA for the mentioned test case.<o:p></o:p></P>
<P class=MsoNormal><o:p></o:p> </P>
<P class=MsoNormal>Regards,<o:p></o:p></P>
<P class=MsoNormal>Ashutosh</P></DIV></DIV></DIV></DIV></BODY></HTML>