<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>