<html 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" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=ProgId content=Word.Document><meta name=Generator content="Microsoft Word 14"><meta name=Originator content="Microsoft Word 14"><link rel=File-List href="cid:filelist.xml@01D0BA30.DE157890"><!--[if gte mso 9]><xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
<o:DoNotRelyOnCSS/>
</o:OfficeDocumentSettings>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:WordDocument>
<w:SpellingState>Clean</w:SpellingState>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:EnvelopeVis/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>EN-US</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:DoNotExpandShiftReturn/>
<w:BreakWrappedTables/>
<w:SplitPgBreakAndParaMark/>
<w:EnableOpenTypeKerning/>
</w:Compatibility>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true" DefSemiHidden="true" DefQFormat="false" DefPriority="99" LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false" UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><style><!--
/* Font Definitions */
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;
mso-font-alt:"Arial Rounded MT Bold";
mso-font-charset:0;
mso-generic-font-family:swiss;
mso-font-pitch:variable;
mso-font-signature:-536870145 1073786111 1 0 415 0;}
@font-face
{font-family:Tahoma;
panose-1:2 11 6 4 3 5 4 4 2 4;
mso-font-alt:Tahoma;
mso-font-charset:0;
mso-generic-font-family:swiss;
mso-font-pitch:variable;
mso-font-signature:-520081665 -1073717157 41 0 66047 0;}
@font-face
{font-family:Menlo;
panose-1:0 0 0 0 0 0 0 0 0 0;
mso-font-alt:"Times New Roman";
mso-font-charset:0;
mso-generic-font-family:roman;
mso-font-format:other;
mso-font-pitch:auto;
mso-font-signature:0 0 0 0 0 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-unhide:no;
mso-style-qformat:yes;
mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:"Times New Roman","serif";
mso-fareast-font-family:Calibri;}
a:link, span.MsoHyperlink
{mso-style-noshow:yes;
mso-style-priority:99;
color:blue;
text-decoration:underline;
text-underline:single;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-noshow:yes;
mso-style-priority:99;
color:purple;
text-decoration:underline;
text-underline:single;}
span.EmailStyle17
{mso-style-type:personal-reply;
mso-style-noshow:yes;
mso-style-unhide:no;
mso-ansi-font-size:11.0pt;
mso-bidi-font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-fareast-font-family:Calibri;
mso-hansi-font-family:Calibri;
mso-bidi-font-family:"Times New Roman";
color:#1F497D;}
span.SpellE
{mso-style-name:"";
mso-spl-e:yes;}
.MsoChpDefault
{mso-style-type:export-only;
mso-default-props:yes;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-fareast-font-family:Calibri;
mso-hansi-font-family:Calibri;
mso-bidi-font-family:"Times New Roman";}
@page WordSection1
{size:612.0pt 792.0pt;
margin:72.0pt 72.0pt 72.0pt 72.0pt;
mso-header-margin:36.0pt;
mso-footer-margin:36.0pt;
mso-paper-source:0;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 10]><style>/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-hansi-font-family:Calibri;}
</style><![endif]--><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=EN-US link=blue vlink=purple style='tab-interval:36.0pt'><div class=WordSection1><p class=MsoNormal><font size=2 color="#1f497d" face=Calibri><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";mso-bidi-font-family:"Times New Roman";color:#1F497D'>Thanks for letting me know! I’m currently working on a fix for this.<o:p></o:p></span></font></p><p class=MsoNormal><font size=2 color="#1f497d" face=Calibri><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";mso-bidi-font-family:"Times New Roman";color:#1F497D'>Indeed, <span class=SpellE>DepCands</span> looks like the suspect here(<span class=SpellE>std</span>::set + what leaders<o:p></o:p></span></font></p><p class=MsoNormal><font size=2 color="#1f497d" face=Calibri><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";mso-bidi-font-family:"Times New Roman";color:#1F497D'>are assigned to each equivalence class could change that order).<o:p></o:p></span></font></p><p class=MsoNormal><font size=2 color="#1f497d" face=Calibri><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";mso-bidi-font-family:"Times New Roman";color:#1F497D'><o:p> </o:p></span></font></p><p class=MsoNormal><font size=2 color="#1f497d" face=Calibri><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";mso-bidi-font-family:"Times New Roman";color:#1F497D'>I initially thought that this should be deterministic..<o:p></o:p></span></font></p><p class=MsoNormal><font size=2 color="#1f497d" face=Calibri><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";mso-bidi-font-family:"Times New Roman";color:#1F497D'><o:p> </o:p></span></font></p><p class=MsoNormal><font size=2 color="#1f497d" face=Calibri><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";mso-bidi-font-family:"Times New Roman";color:#1F497D'>Using the order from Pointers instead should fix this.<o:p></o:p></span></font></p><p class=MsoNormal><font size=2 color="#1f497d" face=Calibri><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";mso-bidi-font-family:"Times New Roman";color:#1F497D'><o:p> </o:p></span></font></p><p class=MsoNormal><font size=2 color="#1f497d" face=Calibri><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";mso-bidi-font-family:"Times New Roman";color:#1F497D'>Thanks,<o:p></o:p></span></font></p><p class=MsoNormal><font size=2 color="#1f497d" face=Calibri><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";mso-bidi-font-family:"Times New Roman";color:#1F497D'>Silviu<o:p></o:p></span></font></p><p class=MsoNormal><font size=2 color="#1f497d" face=Calibri><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";mso-bidi-font-family:"Times New Roman";color:#1F497D'><o:p> </o:p></span></font></p><p class=MsoNormal><font size=2 color="#1f497d" face=Calibri><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";mso-bidi-font-family:"Times New Roman";color:#1F497D'><o:p> </o:p></span></font></p><div style='border:none;border-left:solid blue 1.5pt;padding:0cm 0cm 0cm 4.0pt'><div><div style='border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0cm 0cm 0cm'><p class=MsoNormal><b><font size=2 face=Tahoma><span style='font-size:10.0pt;font-family:"Tahoma","sans-serif";mso-fareast-font-family:"Times New Roman";font-weight:bold'>From:</span></font></b><font size=2 face=Tahoma><span style='font-size:10.0pt;font-family:"Tahoma","sans-serif";mso-fareast-font-family:"Times New Roman"'> NAKAMURA Takumi [mailto:geek4civic@gmail.com] <br><b><span style='font-weight:bold'>Sent:</span></b> 09 July 2015 02:33<br><b><span style='font-weight:bold'>To:</span></b> Reid Kleckner; Silviu Baranga<br><b><span style='font-weight:bold'>Cc:</span></b> llvm-commits<br><b><span style='font-weight:bold'>Subject:</span></b> Re: [llvm] r241673 - [LAA] Merge memchecks for accesses separated by a constant offset<o:p></o:p></span></font></p></div></div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'><o:p> </o:p></span></font></p><div><p class=MsoNormal><font size=1 color=black face=Menlo><span style='font-size:8.5pt;font-family:"Menlo","serif";color:black;background:#AAFFAA'>DepCandidates (std::set) is dubious.</span></font><o:p></o:p></p></div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'><o:p> </o:p></span></font></p><div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'>On Thu, Jul 9, 2015 at 10:06 AM NAKAMURA Takumi <<a href="mailto:geek4civic@gmail.com">geek4civic@gmail.com</a>> wrote:<o:p></o:p></span></font></p></div><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;mso-border-left-alt:solid #CCCCCC .75pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-right:0cm'><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'>Seems causes different emissions between stage2 and stage3.<br><br> <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__bb.pgr.jp_builders_clang-2D3stage-2Di686-2Dlinux_builds_2726&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=ghg4sCtLo34lR_Dtk8EBQfMUk03a8aPiDGALESCgldY&s=al9AK_ym3pYIp8An0tCXVMkxm6okkkOPuCI__HHiwDA&e=" target="_blank">http://bb.pgr.jp/builders/clang-3stage-i686-linux/builds/2726</a><o:p></o:p></span></font></p><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'><o:p> </o:p></span></font></p></div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'>Stage2 is built by clang built by g++, +Asserts.<o:p></o:p></span></font></p></div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'>Stage3 is built by clang built by stage2-clang, -Asserts.<o:p></o:p></span></font></p></div></div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'><o:p> </o:p></span></font></p><div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'>On Thu, Jul 9, 2015 at 6:25 AM Reid Kleckner <<a href="mailto:rnk@google.com" target="_blank">rnk@google.com</a>> wrote:<o:p></o:p></span></font></p></div><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;mso-border-left-alt:solid #CCCCCC .75pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-right:0cm'><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'>The number-memchecks.ll test fails for me on Windows because the output ordering is different. The two check groups are printed in opposite order:<o:p></o:p></span></font></p><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'><o:p> </o:p></span></font></p></div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'><o:p> </o:p></span></font></p></div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'>"""<o:p></o:p></span></font></p></div><div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'>Printing analysis 'Loop Access Analysis' for function 'testg':<o:p></o:p></span></font></p></div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> for.body:<o:p></o:p></span></font></p></div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> Report: unsafe dependent memory operations in loop<o:p></o:p></span></font></p></div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> Interesting Dependences:<o:p></o:p></span></font></p></div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> Unknown:<o:p></o:p></span></font></p></div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> store i16 %mul1, i16* %arrayidxC, align 2 -><o:p></o:p></span></font></p></div></div></div><div><div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> store i16 %mul, i16* %arrayidxC1, align 2<o:p></o:p></span></font></p></div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'><o:p> </o:p></span></font></p></div></div></div><div><div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> Run-time memory checks:<o:p></o:p></span></font></p></div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> Check 0:<o:p></o:p></span></font></p></div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> Comparing group 0:<o:p></o:p></span></font></p></div></div></div><div><div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %ind<o:p></o:p></span></font></p></div></div></div><div><div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> Against group 2:<o:p></o:p></span></font></p></div></div></div><div><div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc<o:p></o:p></span></font></p></div></div></div><div><div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind<o:p></o:p></span></font></p></div></div></div><div><div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> Check 1:<o:p></o:p></span></font></p></div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> Comparing group 1:<o:p></o:p></span></font></p></div></div></div><div><div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> %arrayidxA1 = getelementptr inbounds i16, i16* %a, i64 %add<o:p></o:p></span></font></p></div></div></div><div><div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %ind<o:p></o:p></span></font></p></div></div></div><div><div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> Against group 2:<o:p></o:p></span></font></p></div></div></div><div><div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc<o:p></o:p></span></font></p></div></div></div><div><div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'> %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind<o:p></o:p></span></font></p></div></div></div><div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'>"""<o:p></o:p></span></font></p></div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'><o:p> </o:p></span></font></p></div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'>Can you fix the code to be deterministic, i.e. not rely on hashtable ordering?<o:p></o:p></span></font></p></div></div><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'><o:p> </o:p></span></font></p><div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'>On Wed, Jul 8, 2015 at 2:16 AM, Silviu Baranga <<a href="mailto:silviu.baranga@arm.com" target="_blank">silviu.baranga@arm.com</a>> wrote:<o:p></o:p></span></font></p><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'>Author: sbaranga<br>Date: Wed Jul 8 04:16:33 2015<br>New Revision: 241673<br><br>URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject-3Frev-3D241673-26view-3Drev&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=uFcf0gLR_MIrQFYhuAb8gVsoNdftcSB1mZMezpDReAU&s=Dxo7K237VlAGYajD5SNgUt5XddeKt_mFDUjKmbGQiqw&e=" target="_blank">http://llvm.org/viewvc/llvm-project?rev=241673&view=rev</a><br>Log:<br>[LAA] Merge memchecks for accesses separated by a constant offset<br><br>Summary:<br>Often filter-like loops will do memory accesses that are<br>separated by constant offsets. In these cases it is<br>common that we will exceed the threshold for the<br>allowable number of checks.<br><br>However, it should be possible to merge such checks,<br>sice a check of any interval againt two other intervals separated<br>by a constant offset (a,b), (a+c, b+c) will be equivalent with<br>a check againt (a, b+c), as long as (a,b) and (a+c, b+c) overlap.<br>Assuming the loop will be executed for a sufficient number of<br>iterations, this will be true. If not true, checking against<br>(a, b+c) is still safe (although not equivalent).<br><br>As long as there are no dependencies between two accesses,<br>we can merge their checks into a single one. We use this<br>technique to construct groups of accesses, and then check<br>the intervals associated with the groups instead of<br>checking the accesses directly.<br><br>Reviewers: anemet<br><br>Subscribers: llvm-commits<br><br>Differential Revision: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__reviews.llvm.org_D10386&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=uFcf0gLR_MIrQFYhuAb8gVsoNdftcSB1mZMezpDReAU&s=WZTW9zyjMHaRKXUhKETIcSFkjBukReMt6Zx5q0F5GLo&e=" target="_blank">http://reviews.llvm.org/D10386</a><br><br>Modified:<br> llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h<br> llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp<br> llvm/trunk/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll<br> llvm/trunk/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll<br> llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll<br> llvm/trunk/test/Transforms/LoopDistribute/basic-with-memchecks.ll<br><br>Modified: llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h<br>URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_include_llvm_Analysis_LoopAccessAnalysis.h-3Frev-3D241673-26r1-3D241672-26r2-3D241673-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=uFcf0gLR_MIrQFYhuAb8gVsoNdftcSB1mZMezpDReAU&s=ee7qyjv9D3q1usyor7Ut8EOQ4lfsGoBXXa40MufUDrQ&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h?rev=241673&r1=241672&r2=241673&view=diff</a><br>==============================================================================<br>--- llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h (original)<br>+++ llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h Wed Jul 8 04:16:33 2015<br>@@ -311,7 +311,7 @@ public:<br> /// This struct holds information about the memory runtime legality check that<br> /// a group of pointers do not overlap.<br> struct RuntimePointerCheck {<br>- RuntimePointerCheck() : Need(false) {}<br>+ RuntimePointerCheck(ScalarEvolution *SE) : Need(false), SE(SE) {}<br><br> /// Reset the state of the pointer runtime information.<br> void reset() {<br>@@ -322,16 +322,55 @@ public:<br> IsWritePtr.clear();<br> DependencySetId.clear();<br> AliasSetId.clear();<br>+ Exprs.clear();<br> }<br><br> /// Insert a pointer and calculate the start and end SCEVs.<br>- void insert(ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr,<br>- unsigned DepSetId, unsigned ASId,<br>- const ValueToValueMap &Strides);<br>+ void insert(Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId,<br>+ unsigned ASId, const ValueToValueMap &Strides);<br><br> /// \brief No run-time memory checking is necessary.<br> bool empty() const { return Pointers.empty(); }<br><br>+ /// A grouping of pointers. A single memcheck is required between<br>+ /// two groups.<br>+ struct CheckingPtrGroup {<br>+ /// \brief Create a new pointer checking group containing a single<br>+ /// pointer, with index \p Index in RtCheck.<br>+ CheckingPtrGroup(unsigned Index, RuntimePointerCheck &RtCheck)<br>+ : RtCheck(RtCheck), High(RtCheck.Ends[Index]),<br>+ Low(RtCheck.Starts[Index]) {<br>+ Members.push_back(Index);<br>+ }<br>+<br>+ /// \brief Tries to add the pointer recorded in RtCheck at index<br>+ /// \p Index to this pointer checking group. We can only add a pointer<br>+ /// to a checking group if we will still be able to get<br>+ /// the upper and lower bounds of the check. Returns true in case<br>+ /// of success, false otherwise.<br>+ bool addPointer(unsigned Index);<br>+<br>+ /// Constitutes the context of this pointer checking group. For each<br>+ /// pointer that is a member of this group we will retain the index<br>+ /// at which it appears in RtCheck.<br>+ RuntimePointerCheck &RtCheck;<br>+ /// The SCEV expression which represents the upper bound of all the<br>+ /// pointers in this group.<br>+ const SCEV *High;<br>+ /// The SCEV expression which represents the lower bound of all the<br>+ /// pointers in this group.<br>+ const SCEV *Low;<br>+ /// Indices of all the pointers that constitute this grouping.<br>+ SmallVector<unsigned, 2> Members;<br>+ };<br>+<br>+ /// \brief Groups pointers such that a single memcheck is required<br>+ /// between two different groups. This will clear the CheckingGroups vector<br>+ /// and re-compute it. We will only group dependecies if \p UseDependencies<br>+ /// is true, otherwise we will create a separate group for each pointer.<br>+ void groupChecks(MemoryDepChecker::DepCandidates &DepCands,<br>+ bool UseDependencies);<br>+<br> /// \brief Decide whether we need to issue a run-time check for pointer at<br> /// index \p I and \p J to prove their independence.<br> ///<br>@@ -341,6 +380,12 @@ public:<br> bool needsChecking(unsigned I, unsigned J,<br> const SmallVectorImpl<int> *PtrPartition) const;<br><br>+ /// \brief Decide if we need to add a check between two groups of pointers,<br>+ /// according to needsChecking.<br>+ bool needsChecking(const CheckingPtrGroup &M,<br>+ const CheckingPtrGroup &N,<br>+ const SmallVectorImpl<int> *PtrPartition) const;<br>+<br> /// \brief Return true if any pointer requires run-time checking according<br> /// to needsChecking.<br> bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const;<br>@@ -372,6 +417,12 @@ public:<br> SmallVector<unsigned, 2> DependencySetId;<br> /// Holds the id of the disjoint alias set to which this pointer belongs.<br> SmallVector<unsigned, 2> AliasSetId;<br>+ /// Holds at position i the SCEV for the access i<br>+ SmallVector<const SCEV *, 2> Exprs;<br>+ /// Holds a partitioning of pointers into "check groups".<br>+ SmallVector<CheckingPtrGroup, 2> CheckingGroups;<br>+ /// Holds a pointer to the ScalarEvolution analysis.<br>+ ScalarEvolution *SE;<br> };<br><br> LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout &DL,<br><br>Modified: llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp<br>URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Analysis_LoopAccessAnalysis.cpp-3Frev-3D241673-26r1-3D241672-26r2-3D241673-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=uFcf0gLR_MIrQFYhuAb8gVsoNdftcSB1mZMezpDReAU&s=jgDoUSmGrEpNcijw3f5mG6psVDXWQp5Rz1pJjlCtKRQ&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp?rev=241673&r1=241672&r2=241673&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp (original)<br>+++ llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp Wed Jul 8 04:16:33 2015<br>@@ -48,6 +48,13 @@ static cl::opt<unsigned, true> RuntimeMe<br> cl::location(VectorizerParams::RuntimeMemoryCheckThreshold), cl::init(8));<br> unsigned VectorizerParams::RuntimeMemoryCheckThreshold;<br><br>+/// \brief The maximum iterations used to merge memory checks<br>+static cl::opt<unsigned> MemoryCheckMergeThreshold(<br>+ "memory-check-merge-threshold", cl::Hidden,<br>+ cl::desc("Maximum number of comparisons done when trying to merge "<br>+ "runtime memory checks. (default = 100)"),<br>+ cl::init(100));<br>+<br> /// Maximum SIMD width.<br> const unsigned VectorizerParams::MaxVectorWidth = 64;<br><br>@@ -113,8 +120,8 @@ const SCEV *llvm::replaceSymbolicStrideS<br> }<br><br> void LoopAccessInfo::RuntimePointerCheck::insert(<br>- ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId,<br>- unsigned ASId, const ValueToValueMap &Strides) {<br>+ Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId, unsigned ASId,<br>+ const ValueToValueMap &Strides) {<br> // Get the stride replaced scev.<br> const SCEV *Sc = replaceSymbolicStrideSCEV(SE, Strides, Ptr);<br> const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Sc);<br>@@ -127,6 +134,136 @@ void LoopAccessInfo::RuntimePointerCheck<br> IsWritePtr.push_back(WritePtr);<br> DependencySetId.push_back(DepSetId);<br> AliasSetId.push_back(ASId);<br>+ Exprs.push_back(Sc);<br>+}<br>+<br>+bool LoopAccessInfo::RuntimePointerCheck::needsChecking(<br>+ const CheckingPtrGroup &M, const CheckingPtrGroup &N,<br>+ const SmallVectorImpl<int> *PtrPartition) const {<br>+ for (unsigned I = 0, EI = M.Members.size(); EI != I; ++I)<br>+ for (unsigned J = 0, EJ = N.Members.size(); EJ != J; ++J)<br>+ if (needsChecking(M.Members[I], N.Members[J], PtrPartition))<br>+ return true;<br>+ return false;<br>+}<br>+<br>+/// Compare \p I and \p J and return the minimum.<br>+/// Return nullptr in case we couldn't find an answer.<br>+static const SCEV *getMinFromExprs(const SCEV *I, const SCEV *J,<br>+ ScalarEvolution *SE) {<br>+ const SCEV *Diff = SE->getMinusSCEV(J, I);<br>+ const SCEVConstant *C = dyn_cast<const SCEVConstant>(Diff);<br>+<br>+ if (!C)<br>+ return nullptr;<br>+ if (C->getValue()->isNegative())<br>+ return J;<br>+ return I;<br>+}<br>+<br>+bool LoopAccessInfo::RuntimePointerCheck::CheckingPtrGroup::addPointer(<br>+ unsigned Index) {<br>+ // Compare the starts and ends with the known minimum and maximum<br>+ // of this set. We need to know how we compare against the min/max<br>+ // of the set in order to be able to emit memchecks.<br>+ const SCEV *Min0 = getMinFromExprs(RtCheck.Starts[Index], Low, RtCheck.SE);<br>+ if (!Min0)<br>+ return false;<br>+<br>+ const SCEV *Min1 = getMinFromExprs(RtCheck.Ends[Index], High, RtCheck.SE);<br>+ if (!Min1)<br>+ return false;<br>+<br>+ // Update the low bound expression if we've found a new min value.<br>+ if (Min0 == RtCheck.Starts[Index])<br>+ Low = RtCheck.Starts[Index];<br>+<br>+ // Update the high bound expression if we've found a new max value.<br>+ if (Min1 != RtCheck.Ends[Index])<br>+ High = RtCheck.Ends[Index];<br>+<br>+ Members.push_back(Index);<br>+ return true;<br>+}<br>+<br>+void LoopAccessInfo::RuntimePointerCheck::groupChecks(<br>+ MemoryDepChecker::DepCandidates &DepCands,<br>+ bool UseDependencies) {<br>+ // We build the groups from dependency candidates equivalence classes<br>+ // because:<br>+ // - We know that pointers in the same equivalence class share<br>+ // the same underlying object and therefore there is a chance<br>+ // that we can compare pointers<br>+ // - We wouldn't be able to merge two pointers for which we need<br>+ // to emit a memcheck. The classes in DepCands are already<br>+ // conveniently built such that no two pointers in the same<br>+ // class need checking against each other.<br>+<br>+ // We use the following (greedy) algorithm to construct the groups<br>+ // For every pointer in the equivalence class:<br>+ // For each existing group:<br>+ // - if the difference between this pointer and the min/max bounds<br>+ // of the group is a constant, then make the pointer part of the<br>+ // group and update the min/max bounds of that group as required.<br>+<br>+ CheckingGroups.clear();<br>+<br>+ // If we don't have the dependency partitions, construct a new<br>+ // checking pointer group for each pointer.<br>+ if (!UseDependencies) {<br>+ for (unsigned I = 0; I < Pointers.size(); ++I)<br>+ CheckingGroups.push_back(CheckingPtrGroup(I, *this));<br>+ return;<br>+ }<br>+<br>+ unsigned TotalComparisons = 0;<br>+<br>+ DenseMap<Value *, unsigned> PositionMap;<br>+ for (unsigned Pointer = 0; Pointer < Pointers.size(); ++Pointer)<br>+ PositionMap[Pointers[Pointer]] = Pointer;<br>+<br>+ // Go through all equivalence classes, get the the "pointer check groups"<br>+ // and add them to the overall solution.<br>+ for (auto DI = DepCands.begin(), DE = DepCands.end(); DI != DE; ++DI) {<br>+ if (!DI->isLeader())<br>+ continue;<br>+<br>+ SmallVector<CheckingPtrGroup, 2> Groups;<br>+<br>+ for (auto MI = DepCands.member_begin(DI), ME = DepCands.member_end();<br>+ MI != ME; ++MI) {<br>+ unsigned Pointer = PositionMap[MI->getPointer()];<br>+ bool Merged = false;<br>+<br>+ // Go through all the existing sets and see if we can find one<br>+ // which can include this pointer.<br>+ for (CheckingPtrGroup &Group : Groups) {<br>+ // Don't perform more than a certain amount of comparisons.<br>+ // This should limit the cost of grouping the pointers to something<br>+ // reasonable. If we do end up hitting this threshold, the algorithm<br>+ // will create separate groups for all remaining pointers.<br>+ if (TotalComparisons > MemoryCheckMergeThreshold)<br>+ break;<br>+<br>+ TotalComparisons++;<br>+<br>+ if (Group.addPointer(Pointer)) {<br>+ Merged = true;<br>+ break;<br>+ }<br>+ }<br>+<br>+ if (!Merged)<br>+ // We couldn't add this pointer to any existing set or the threshold<br>+ // for the number of comparisons has been reached. Create a new group<br>+ // to hold the current pointer.<br>+ Groups.push_back(CheckingPtrGroup(Pointer, *this));<br>+ }<br>+<br>+ // We've computed the grouped checks for this partition.<br>+ // Save the results and continue with the next one.<br>+ std::copy(Groups.begin(), Groups.end(), std::back_inserter(CheckingGroups));<br>+ }<br> }<br><br> bool LoopAccessInfo::RuntimePointerCheck::needsChecking(<br>@@ -156,42 +293,71 @@ bool LoopAccessInfo::RuntimePointerCheck<br> void LoopAccessInfo::RuntimePointerCheck::print(<br> raw_ostream &OS, unsigned Depth,<br> const SmallVectorImpl<int> *PtrPartition) const {<br>- unsigned NumPointers = Pointers.size();<br>- if (NumPointers == 0)<br>- return;<br><br> OS.indent(Depth) << "Run-time memory checks:\n";<br>+<br> unsigned N = 0;<br>- for (unsigned I = 0; I < NumPointers; ++I)<br>- for (unsigned J = I + 1; J < NumPointers; ++J)<br>- if (needsChecking(I, J, PtrPartition)) {<br>- OS.indent(Depth) << N++ << ":\n";<br>- OS.indent(Depth + 2) << *Pointers[I];<br>- if (PtrPartition)<br>- OS << " (Partition: " << (*PtrPartition)[I] << ")";<br>- OS << "\n";<br>- OS.indent(Depth + 2) << *Pointers[J];<br>- if (PtrPartition)<br>- OS << " (Partition: " << (*PtrPartition)[J] << ")";<br>- OS << "\n";<br>+ for (unsigned I = 0; I < CheckingGroups.size(); ++I)<br>+ for (unsigned J = I + 1; J < CheckingGroups.size(); ++J)<br>+ if (needsChecking(CheckingGroups[I], CheckingGroups[J], PtrPartition)) {<br>+ OS.indent(Depth) << "Check " << N++ << ":\n";<br>+ OS.indent(Depth + 2) << "Comparing group " << I << ":\n";<br>+<br>+ for (unsigned K = 0; K < CheckingGroups[I].Members.size(); ++K) {<br>+ OS.indent(Depth + 2) << *Pointers[CheckingGroups[I].Members[K]]<br>+ << "\n";<br>+ if (PtrPartition)<br>+ OS << " (Partition: "<br>+ << (*PtrPartition)[CheckingGroups[I].Members[K]] << ")"<br>+ << "\n";<br>+ }<br>+<br>+ OS.indent(Depth + 2) << "Against group " << J << ":\n";<br>+<br>+ for (unsigned K = 0; K < CheckingGroups[J].Members.size(); ++K) {<br>+ OS.indent(Depth + 2) << *Pointers[CheckingGroups[J].Members[K]]<br>+ << "\n";<br>+ if (PtrPartition)<br>+ OS << " (Partition: "<br>+ << (*PtrPartition)[CheckingGroups[J].Members[K]] << ")"<br>+ << "\n";<br>+ }<br> }<br>+<br>+ OS.indent(Depth) << "Grouped accesses:\n";<br>+ for (unsigned I = 0; I < CheckingGroups.size(); ++I) {<br>+ OS.indent(Depth + 2) << "Group " << I << ":\n";<br>+ OS.indent(Depth + 4) << "(Low: " << *CheckingGroups[I].Low<br>+ << " High: " << *CheckingGroups[I].High << ")\n";<br>+ for (unsigned J = 0; J < CheckingGroups[I].Members.size(); ++J) {<br>+ OS.indent(Depth + 6) << "Member: " << *Exprs[CheckingGroups[I].Members[J]]<br>+ << "\n";<br>+ }<br>+ }<br> }<br><br> unsigned LoopAccessInfo::RuntimePointerCheck::getNumberOfChecks(<br> const SmallVectorImpl<int> *PtrPartition) const {<br>- unsigned NumPointers = Pointers.size();<br>+<br>+ unsigned NumPartitions = CheckingGroups.size();<br> unsigned CheckCount = 0;<br><br>- for (unsigned I = 0; I < NumPointers; ++I)<br>- for (unsigned J = I + 1; J < NumPointers; ++J)<br>- if (needsChecking(I, J, PtrPartition))<br>+ for (unsigned I = 0; I < NumPartitions; ++I)<br>+ for (unsigned J = I + 1; J < NumPartitions; ++J)<br>+ if (needsChecking(CheckingGroups[I], CheckingGroups[J], PtrPartition))<br> CheckCount++;<br> return CheckCount;<br> }<br><br> bool LoopAccessInfo::RuntimePointerCheck::needsAnyChecking(<br> const SmallVectorImpl<int> *PtrPartition) const {<br>- return getNumberOfChecks(PtrPartition) != 0;<br>+ unsigned NumPointers = Pointers.size();<br>+<br>+ for (unsigned I = 0; I < NumPointers; ++I)<br>+ for (unsigned J = I + 1; J < NumPointers; ++J)<br>+ if (needsChecking(I, J, PtrPartition))<br>+ return true;<br>+ return false;<br> }<br><br> namespace {<br>@@ -341,7 +507,7 @@ bool AccessAnalysis::canCheckPtrAtRT(<br> // Each access has its own dependence set.<br> DepId = RunningDepId++;<br><br>- RtCheck.insert(SE, TheLoop, Ptr, IsWrite, DepId, ASId, StridesMap);<br>+ RtCheck.insert(TheLoop, Ptr, IsWrite, DepId, ASId, StridesMap);<br><br> DEBUG(dbgs() << "LAA: Found a runtime check ptr:" << *Ptr << '\n');<br> } else {<br>@@ -387,6 +553,9 @@ bool AccessAnalysis::canCheckPtrAtRT(<br> }<br> }<br><br>+ if (NeedRTCheck && CanDoRT)<br>+ RtCheck.groupChecks(DepCands, IsDepCheckNeeded);<br>+<br> return CanDoRT;<br> }<br><br>@@ -1360,32 +1529,35 @@ std::pair<Instruction *, Instruction *><br> if (!PtrRtCheck.Need)<br> return std::make_pair(nullptr, nullptr);<br><br>- unsigned NumPointers = PtrRtCheck.Pointers.size();<br>- SmallVector<TrackingVH<Value> , 2> Starts;<br>- SmallVector<TrackingVH<Value> , 2> Ends;<br>+ SmallVector<TrackingVH<Value>, 2> Starts;<br>+ SmallVector<TrackingVH<Value>, 2> Ends;<br><br> LLVMContext &Ctx = Loc->getContext();<br> SCEVExpander Exp(*SE, DL, "induction");<br> Instruction *FirstInst = nullptr;<br><br>- for (unsigned i = 0; i < NumPointers; ++i) {<br>- Value *Ptr = PtrRtCheck.Pointers[i];<br>+ for (unsigned i = 0; i < PtrRtCheck.CheckingGroups.size(); ++i) {<br>+ const RuntimePointerCheck::CheckingPtrGroup &CG =<br>+ PtrRtCheck.CheckingGroups[i];<br>+ Value *Ptr = PtrRtCheck.Pointers[CG.Members[0]];<br> const SCEV *Sc = SE->getSCEV(Ptr);<br><br> if (SE->isLoopInvariant(Sc, TheLoop)) {<br>- DEBUG(dbgs() << "LAA: Adding RT check for a loop invariant ptr:" <<<br>- *Ptr <<"\n");<br>+ DEBUG(dbgs() << "LAA: Adding RT check for a loop invariant ptr:" << *Ptr<br>+ << "\n");<br> Starts.push_back(Ptr);<br> Ends.push_back(Ptr);<br> } else {<br>- DEBUG(dbgs() << "LAA: Adding RT check for range:" << *Ptr << '\n');<br> unsigned AS = Ptr->getType()->getPointerAddressSpace();<br><br> // Use this type for pointer arithmetic.<br> Type *PtrArithTy = Type::getInt8PtrTy(Ctx, AS);<br>+ Value *Start = nullptr, *End = nullptr;<br><br>- Value *Start = Exp.expandCodeFor(PtrRtCheck.Starts[i], PtrArithTy, Loc);<br>- Value *End = Exp.expandCodeFor(PtrRtCheck.Ends[i], PtrArithTy, Loc);<br>+ DEBUG(dbgs() << "LAA: Adding RT check for range:\n");<br>+ Start = Exp.expandCodeFor(CG.Low, PtrArithTy, Loc);<br>+ End = Exp.expandCodeFor(CG.High, PtrArithTy, Loc);<br>+ DEBUG(dbgs() << "Start: " << *CG.Low << " End: " << *CG.High << "\n");<br> Starts.push_back(Start);<br> Ends.push_back(End);<br> }<br>@@ -1394,9 +1566,14 @@ std::pair<Instruction *, Instruction *><br> IRBuilder<> ChkBuilder(Loc);<br> // Our instructions might fold to a constant.<br> Value *MemoryRuntimeCheck = nullptr;<br>- for (unsigned i = 0; i < NumPointers; ++i) {<br>- for (unsigned j = i+1; j
< NumPointers; ++j) {<br>- if (!PtrRtCheck.needsChecking(i, j, PtrPartition))<br>+ for (unsigned i = 0; i < PtrRtCheck.CheckingGroups.size(); ++i) {<br>+ for (unsigned j = i + 1; j < PtrRtCheck.CheckingGroups.size(); ++j) {<br>+ const RuntimePointerCheck::CheckingPtrGroup &CGI =<br>+ PtrRtCheck.CheckingGroups[i];<br>+ const RuntimePointerCheck::CheckingPtrGroup &CGJ =<br>+ PtrRtCheck.CheckingGroups[j];<br>+<br>+ if (!PtrRtCheck.needsChecking(CGI, CGJ, PtrPartition))<br> continue;<br><br> unsigned AS0 = Starts[i]->getType()->getPointerAddressSpace();<br>@@ -1447,8 +1624,8 @@ LoopAccessInfo::LoopAccessInfo(Loop *L,<br> const TargetLibraryInfo *TLI, AliasAnalysis *AA,<br> DominatorTree *DT, LoopInfo *LI,<br> const ValueToValueMap &Strides)<br>- : DepChecker(SE, L), TheLoop(L), SE(SE), DL(DL),<br>- TLI(TLI), AA(AA), DT(DT), LI(LI), NumLoads(0), NumStores(0),<br>+ : PtrRtCheck(SE), DepChecker(SE, L), TheLoop(L), SE(SE), DL(DL), TLI(TLI),<br>+ AA(AA), DT(DT), LI(LI), NumLoads(0), NumStores(0),<br> MaxSafeDepDistBytes(-1U), CanVecMem(false),<br> StoreToLoopInvariantAddress(false) {<br> if (canAnalyzeLoop())<br><br>Modified: llvm/trunk/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll<br>URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_Analysis_LoopAccessAnalysis_number-2Dof-2Dmemchecks.ll-3Frev-3D241673-26r1-3D241672-26r2-3D241673-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=uFcf0gLR_MIrQFYhuAb8gVsoNdftcSB1mZMezpDReAU&s=Y-v3S_4R47_3pPyXhbHdLm4ACVBkEjbE-9GgFMygShY&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll?rev=241673&r1=241672&r2=241673&view=diff</a><br>==============================================================================<br>--- llvm/trunk/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll (original)<br>+++ llvm/trunk/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll Wed Jul 8 04:16:33 2015<br>@@ -1,19 +1,20 @@<br> ; RUN: opt -loop-accesses -analyze < %s | FileCheck %s<br><br>-; 3 reads and 3 writes should need 12 memchecks<br>-<br> target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"<br> target triple = "aarch64--linux-gnueabi"<br><br>+; 3 reads and 3 writes should need 12 memchecks<br>+; CHECK: function 'testf':<br> ; CHECK: Memory dependences are safe with run-time checks<br>-; Memory dependecies have labels starting from 0, so in<br>+<br>+; Memory dependencies have labels starting from 0, so in<br> ; order to verify that we have n checks, we look for<br> ; (n-1): and not n:.<br><br> ; CHECK: Run-time memory checks:<br>-; CHECK-NEXT: 0:<br>-; CHECK: 11:<br>-; CHECK-NOT: 12:<br>+; CHECK-NEXT: Check 0:<br>+; CHECK: Check 11:<br>+; CHECK-NOT: Check 12:<br><br> define void @testf(i16* %a,<br> i16* %b,<br>@@ -52,6 +53,165 @@ for.body:<br><br> %exitcond = icmp eq i64 %add, 20<br> br i1 %exitcond, label %for.end, label %for.body<br>+<br>+for.end: ; preds = %for.body<br>+ ret void<br>+}<br>+<br>+; The following (testg and testh) check that we can group<br>+; memory checks of accesses which differ by a constant value.<br>+; Both tests are based on the following C code:<br>+;<br>+; void testh(short *a, short *b, short *c) {<br>+; unsigned long ind = 0;<br>+; for (unsigned long ind = 0; ind < 20; ++ind) {<br>+; c[2 * ind] = a[ind] * a[ind + 1];<br>+; c[2 * ind + 1] = a[ind] * a[ind + 1] * b[ind];<br>+; }<br>+; }<br>+;<br>+; It is sufficient to check the intervals<br>+; [a, a + 21], [b, b + 20] against [c, c + 41].<br>+<br>+; 3 reads and 2 writes - two of the reads can be merged,<br>+; and the writes can be merged as well. This gives us a<br>+; total of 2 memory checks.<br>+<br>+; CHECK: function 'testg':<br>+<br>+; CHECK: Run-time memory checks:<br>+; CHECK-NEXT: Check 0:<br>+; CHECK-NEXT: Comparing group 0:<br>+; CHECK-NEXT: %arrayidxA1 = getelementptr inbounds i16, i16* %a, i64 %add<br>+; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %ind<br>+; CHECK-NEXT: Against group 2:<br>+; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc<br>+; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind<br>+; CHECK-NEXT: Check 1:<br>+; CHECK-NEXT: Comparing group 1:<br>+; CHECK-NEXT: %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %ind<br>+; CHECK-NEXT: Against group 2:<br>+; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc<br>+; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind<br>+; CHECK-NEXT: Grouped accesses:<br>+; CHECK-NEXT: Group 0:<br>+; CHECK-NEXT: (Low: %a High: (40 + %a))<br>+; CHECK-NEXT: Member: {(2 + %a),+,2}<br>+; CHECK-NEXT: Member: {%a,+,2}<br>+; CHECK-NEXT: Group 1:<br>+; CHECK-NEXT: (Low: %b High: (38 + %b))<br>+; CHECK-NEXT: Member: {%b,+,2}<br>+; CHECK-NEXT: Group 2:<br>+; CHECK-NEXT: (Low: %c High: (78 + %c))<br>+; CHECK-NEXT: Member: {(2 + %c),+,4}<br>+; CHECK-NEXT: Member: {%c,+,4}<br>+<br>+define void @testg(i16* %a,<br>+ i16* %b,<br>+ i16* %c) {<br>+entry:<br>+ br label %for.body<br>+<br>+for.body: ; preds = %for.body, %entry<br>+ %ind = phi i64 [ 0, %entry ], [ %add, %for.body ]<br>+ %store_ind = phi i64 [ 0, %entry ], [ %store_ind_next, %for.body ]<br>+<br>+ %add = add nuw nsw i64 %ind, 1<br>+ %store_ind_inc = add nuw nsw i64 %store_ind, 1<br>+ %store_ind_next = add nuw nsw i64 %store_ind_inc, 1<br>+<br>+ %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %ind<br>+ %loadA = load i16, i16* %arrayidxA, align 2<br>+<br>+ %arrayidxA1 = getelementptr inbounds i16, i16* %a, i64 %add<br>+ %loadA1 = load i16, i16* %arrayidxA1, align 2<br>+<br>+ %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %ind<br>+ %loadB = load i16, i16* %arrayidxB, align 2<br>+<br>+ %mul = mul i16 %loadA, %loadA1<br>+ %mul1 = mul i16 %mul, %loadB<br>+<br>+ %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind<br>+ store i16 %mul1, i16* %arrayidxC, align 2<br>+<br>+ %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc<br>+ store i16 %mul, i16* %arrayidxC1, align 2<br>+<br>+ %exitcond = icmp eq i64 %add, 20<br>+ br i1 %exitcond, label %for.end, label %for.body<br>+<br>+for.end: ; preds = %for.body<br>+ ret void<br>+}<br>+<br>+; 3 reads and 2 writes - the writes can be merged into a single<br>+; group, but the GEPs used for the reads are not marked as inbounds.<br>+; We can still merge them because we are using a unit stride for<br>+; accesses, so we cannot overflow the GEPs.<br>+<br>+; CHECK: function 'testh':<br>+; CHECK: Run-time memory checks:<br>+; CHECK-NEXT: Check 0:<br>+; CHECK-NEXT: Comparing group 0:<br>+; CHECK-NEXT: %arrayidxA1 = getelementptr i16, i16* %a, i64 %add<br>+; CHECK-NEXT: %arrayidxA = getelementptr i16, i16* %a, i64 %ind<br>+; CHECK-NEXT: Against group 2:<br>+; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc<br>+; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind<br>+; CHECK-NEXT: Check 1:<br>+; CHECK-NEXT: Comparing group 1:<br>+; CHECK-NEXT: %arrayidxB = getelementptr i16, i16* %b, i64 %ind<br>+; CHECK-NEXT: Against group 2:<br>+; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc<br>+; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind<br>+; CHECK-NEXT: Grouped accesses:<br>+; CHECK-NEXT: Group 0:<br>+; CHECK-NEXT: (Low: %a High: (40 + %a))<br>+; CHECK-NEXT: Member: {(2 + %a),+,2}<br>+; CHECK-NEXT: Member: {%a,+,2}<br>+; CHECK-NEXT: Group 1:<br>+; CHECK-NEXT: (Low: %b High: (38 + %b))<br>+; CHECK-NEXT: Member: {%b,+,2}<br>+; CHECK-NEXT: Group 2:<br>+; CHECK-NEXT: (Low: %c High: (78 + %c))<br>+; CHECK-NEXT: Member: {(2 + %c),+,4}<br>+; CHECK-NEXT: Member: {%c,+,4}<br>+<br>+define void @testh(i16* %a,<br>+ i16* %b,<br>+ i16* %c) {<br>+entry:<br>+ br label %for.body<br>+<br>+for.body: ; preds = %for.body, %entry<br>+ %ind = phi i64 [ 0, %entry ], [ %add, %for.body ]<br>+ %store_ind = phi i64 [ 0, %entry ], [ %store_ind_next, %for.body ]<br>+<br>+ %add = add nuw nsw i64 %ind, 1<br>+ %store_ind_inc = add nuw nsw i64 %store_ind, 1<br>+ %store_ind_next = add nuw nsw i64 %store_ind_inc, 1<br>+<br>+ %arrayidxA = getelementptr i16, i16* %a, i64 %ind<br>+ %loadA = load i16, i16* %arrayidxA, align 2<br>+<br>+ %arrayidxA1 = getelementptr i16, i16* %a, i64 %add<br>+ %loadA1 = load i16, i16* %arrayidxA1, align 2<br>+<br>+ %arrayidxB = getelementptr i16, i16* %b, i64 %ind<br>+ %loadB = load i16, i16* %arrayidxB, align 2<br>+<br>+ %mul = mul i16 %loadA, %loadA1<br>+ %mul1 = mul i16 %mul, %loadB<br>+<br>+ %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind<br>+ store i16 %mul1, i16* %arrayidxC, align 2<br>+<br>+ %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc<br>+ store i16 %mul, i16* %arrayidxC1, align 2<br>+<br>+ %exitcond = icmp eq i64 %add, 20<br>+ br i1 %exitcond, label %for.end, label %for.body<br><br> for.end: ; preds = %for.body<br> ret void<br><br>Modified: llvm/trunk/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll<br>URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_Analysis_LoopAccessAnalysis_resort-2Dto-2Dmemchecks-2Donly.ll-3Frev-3D241673-26r1-3D241672-26r2-3D241673-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=uFcf0gLR_MIrQFYhuAb8gVsoNdftcSB1mZMezpDReAU&s=JOc5_PXhNth6VnQN3CEEvSTM90SHTXct7enPAEmHz7I&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll?rev=241673&r1=241672&r2=241673&view=diff</a><br>==============================================================================<br>--- llvm/trunk/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll (original)<br>+++ llvm/trunk/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll Wed Jul 8 04:16:33 2015<br>@@ -15,7 +15,9 @@ target triple = "x86_64-apple-macosx10.1<br> ; CHECK-NEXT: Interesting Dependences:<br> ; CHECK-NEXT: Run-time memory checks:<br> ; CHECK-NEXT: 0:<br>+; CHECK-NEXT: Comparing group<br> ; CHECK-NEXT: %arrayidxA2 = getelementptr inbounds i16, i16* %a, i64 %idx<br>+; CHECK-NEXT: Against group<br> ; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %indvar<br><br> @B = common global i16* null, align 8<br><br>Modified: llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll<br>URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_Analysis_LoopAccessAnalysis_unsafe-2Dand-2Drt-2Dchecks.ll-3Frev-3D241673-26r1-3D241672-26r2-3D241673-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=uFcf0gLR_MIrQFYhuAb8gVsoNdftcSB1mZMezpDReAU&s=YLQkgpXK7eq7uHA9rBwftq4p-U7welp1znOtw8VfhGI&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll?rev=241673&r1=241672&r2=241673&view=diff</a><br>==============================================================================<br>--- llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll (original)<br>+++ llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll Wed Jul 8 04:16:33 2015<br>@@ -14,10 +14,16 @@ target triple = "x86_64-apple-macosx10.1<br> ; CHECK-NEXT: store i16 %mul1, i16* %arrayidxA_plus_2, align 2<br> ; CHECK: Run-time memory checks:<br> ; CHECK-NEXT: 0:<br>+; CHECK-NEXT: Comparing group<br>+; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %storemerge3<br> ; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16, i16* %a, i64 %add<br>+; CHECK-NEXT: Against group<br> ; CHECK-NEXT: %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %storemerge3<br> ; CHECK-NEXT: 1:<br>+; CHECK-NEXT: Comparing group<br>+; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %storemerge3<br> ; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16, i16* %a, i64 %add<br>+; CHECK-NEXT: Against group<br> ; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %storemerge3<br><br> @B = common global i16* null, align 8<br><br>Modified: llvm/trunk/test/Transforms/LoopDistribute/basic-with-memchecks.ll<br>URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_Transforms_LoopDistribute_basic-2Dwith-2Dmemchecks.ll-3Frev-3D241673-26r1-3D241672-26r2-3D241673-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=uFcf0gLR_MIrQFYhuAb8gVsoNdftcSB1mZMezpDReAU&s=e-P3DrwxY7CSNu_j9MVwxJ2dBrtPl4pmQ_epAx9j5BY&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopDistribute/basic-with-memchecks.ll?rev=241673&r1=241672&r2=241673&view=diff</a><br>==============================================================================<br>--- llvm/trunk/test/Transforms/LoopDistribute/basic-with-memchecks.ll (original)<br>+++ llvm/trunk/test/Transforms/LoopDistribute/basic-with-memchecks.ll Wed Jul 8 04:16:33 2015<br>@@ -32,16 +32,14 @@ entry:<br> %e = load i32*, i32** @E, align 8<br> br label %for.body<br><br>-; We have two compares for each array overlap check which is a total of 10<br>-; compares.<br>+; We have two compares for each array overlap check.<br>+; Since the checks to A and A + 4 get merged, this will give us a<br>+; total of 8 compares.<br> ;<br> ; CHECK: for.body.lver.memcheck:<br> ; CHECK: = icmp<br> ; CHECK: = icmp<br><br>-; CHECK: = icmp<br>-; CHECK: = icmp<br>-<br> ; CHECK: = icmp<br> ; CHECK: = icmp<br><br><br><br>_______________________________________________<br>llvm-commits mailing list<br><a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><o:p></o:p></span></font></p></div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'><o:p> </o:p></span></font></p></div><p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size:12.0pt'>_______________________________________________<br>llvm-commits mailing list<br><a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><o:p></o:p></span></font></p></blockquote></div></blockquote></div></div></div></body></html>