<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="Generator" content="Microsoft Word 15 (filtered medium)">
<!--[if !mso]><style>v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style><![endif]--><style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p.msonormal0, li.msonormal0, div.msonormal0
        {mso-style-name:msonormal;
        mso-margin-top-alt:auto;
        margin-right:0in;
        mso-margin-bottom-alt:auto;
        margin-left:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
span.EmailStyle18
        {mso-style-type:personal;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
span.EmailStyle19
        {mso-style-type:personal-compose;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri",sans-serif;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
/* List Definitions */
@list l0
        {mso-list-id:1093747166;
        mso-list-template-ids:1121507020;}
@list l0:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level2
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level5
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level8
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
ol
        {margin-bottom:0in;}
ul
        {margin-bottom:0in;}
--></style><!--[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">
<div class="WordSection1">
<p class="MsoNormal">Hi Bandhav,<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">When an optimization pass modifies load/stores in a way that the provenance is lost (like the vectorizer sometimes does), the 'noalias function arguments' might indeed<o:p></o:p></p>
<p class="MsoNormal">provide a fallback.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I checked that when vectorization is disabled, the ptr_provenance information remains available.<o:p></o:p></p>
<p class="MsoNormal">(using:  -fno-slp-vectorize -fno-vectorize -fno-tree-vectorize  )<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">When the ptr_provenance information is available, the scheduler will make use of it. You can use following diff to ensure that the info is also printed at MIR level.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">diff --git a/llvm/lib/CodeGen/MachineOperand.cpp b/llvm/lib/CodeGen/MachineOperand.cpp<o:p></o:p></p>
<p class="MsoNormal">index 5e4d5edb9ce6..fc871e756e03 100644<o:p></o:p></p>
<p class="MsoNormal">--- a/llvm/lib/CodeGen/MachineOperand.cpp<o:p></o:p></p>
<p class="MsoNormal">+++ b/llvm/lib/CodeGen/MachineOperand.cpp<o:p></o:p></p>
<p class="MsoNormal">@@ -1166,6 +1166,10 @@ void MachineMemOperand::print(raw_ostream &OS, ModuleSlotTracker &MST,<o:p></o:p></p>
<p class="MsoNormal">     OS << ", !noalias ";<o:p></o:p></p>
<p class="MsoNormal">     AAInfo.NoAlias->printAsOperand(OS, MST);<o:p></o:p></p>
<p class="MsoNormal">   }<o:p></o:p></p>
<p class="MsoNormal">+  if (AAInfo.NoAliasProvenance) {<o:p></o:p></p>
<p class="MsoNormal">+    OS << ", !ptr_provenance ";<o:p></o:p></p>
<p class="MsoNormal">+    AAInfo.NoAliasProvenance->printAsOperand(OS, true, MST);<o:p></o:p></p>
<p class="MsoNormal">+  }<o:p></o:p></p>
<p class="MsoNormal">   if (getRanges()) {<o:p></o:p></p>
<p class="MsoNormal">     OS << ", !range ";<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Greetings,<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Jeroen Dobbelaere<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div style="border:none;border-left:solid blue 1.5pt;padding:0in 0in 0in 4.0pt">
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b>From:</b> Bandhav Veluri <bandhav.veluri00@gmail.com> <br>
<b>Sent:</b> Wednesday, June 24, 2020 22:19<br>
<b>To:</b> Jeroen Dobbelaere <dobbel@synopsys.com><br>
<b>Cc:</b> Neil Henning <neil.henning@unity3d.com>; llvm-dev@lists.llvm.org; Kruse, Michael <michael.kruse@anl.gov><br>
<b>Subject:</b> Re: FW: [llvm-dev] Restrict qualifier on class members<o:p></o:p></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div>
<p class="MsoNormal"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">Hi Jeroen,<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:12.0pt;font-family:"Arial",sans-serif"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">Does that mean in this case, even though the frontend correctly interprets </span><span style="font-size:12.0pt;font-family:"Courier New"">__restrict</span><span style="font-size:12.0pt;font-family:"Arial",sans-serif">
 on struct fields, the backend is only considering </span><span style="font-size:12.0pt;font-family:"Courier New"">nolias</span><span style="font-size:12.0pt;font-family:"Arial",sans-serif"> metadata on function arguments?</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:12.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">Thanks,</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">Bandhav</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div>
<p class="MsoNormal">On Wed, Jun 24, 2020 at 1:32 AM Jeroen Dobbelaere <<a href="mailto:Jeroen.Dobbelaere@synopsys.com">Jeroen.Dobbelaere@synopsys.com</a>> wrote:<o:p></o:p></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Hi Bandhav,<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">I did notice in the previous example, that the vectorizer used the noalias information, but that it also got stripped during the vectorization.<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">That is certainly one of the places where the noalias handling can be improved.<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">It would be interesting to see if the necessary information gets through to the MIR level when vectorization is disabled.<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">That should be visible with the 'ptr_provenance' field.<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Greetings,<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Jeroen Dobbelaere<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<div style="border:none;border-left:solid blue 1.5pt;padding:0in 0in 0in 4.0pt">
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b>From:</b> Bandhav Veluri <<a href="mailto:bandhav.veluri00@gmail.com" target="_blank">bandhav.veluri00@gmail.com</a>>
<br>
<b>Sent:</b> Wednesday, June 24, 2020 10:12<br>
<b>To:</b> Jeroen Dobbelaere <<a href="mailto:dobbel@synopsys.com" target="_blank">dobbel@synopsys.com</a>><br>
<b>Cc:</b> Neil Henning <<a href="mailto:neil.henning@unity3d.com" target="_blank">neil.henning@unity3d.com</a>>;
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>; Kruse, Michael <<a href="mailto:michael.kruse@anl.gov" target="_blank">michael.kruse@anl.gov</a>><br>
<b>Subject:</b> Re: FW: [llvm-dev] Restrict qualifier on class members<o:p></o:p></p>
</div>
</div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">Hi Jeroen,</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">Sorry, I missed that. I tried the patch, and this program:</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt"><br>
</span><span style="font-size:12.0pt;font-family:"Courier New"">#include <stdint.h><br>
<br>
#define __remote __attribute__((address_space(1)))<br>
<br>
__remote int* A;<br>
__remote int* B;<br>
<br>
void vec_add(__remote int* __restrict a,<br>
             __remote int* __restrict b,<br>
             int n) {<br>
  #pragma unroll 4<br>
  for(int i=0; i<n; ++i) {<br>
    a[i] += b[i];<br>
  }<br>
}<br>
<br>
int main(int argc, char** argv) {<br>
  __remote int* __restrict a = A;<br>
  __remote int* __restrict b = B;<br>
<br>
  #pragma unroll 4<br>
  for(int i=0; i<4; ++i) {<br>
    a[i] += b[i];<br>
  }<br>
<br>
  return 0;<br>
}</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Courier New"">vec_add</span><span style="font-size:12.0pt"> give following schedule:</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Courier New"">*** Final schedule for %bb.8 ***<br>
SU(0):   %33:gpr = LW %56:gpr, -8 :: (load 4 from %ir.scevgep8, !tbaa !14, !noalias !13, addrspace 1)<br>
SU(1):   %34:gpr = LW %55:gpr, -8 :: (load 4 from %ir.scevgep14, !tbaa !14, !noalias !13, addrspace 1)<br>
SU(4):   %36:gpr = LW %56:gpr, -4 :: (load 4 from %ir.scevgep10, !tbaa !14, !noalias !13, addrspace 1)<br>
SU(5):   %37:gpr = LW %55:gpr, -4 :: (load 4 from %ir.scevgep16, !tbaa !14, !noalias !13, addrspace 1)<br>
SU(8):   %39:gpr = LW %56:gpr, 0 :: (load 4 from %ir.lsr.iv6, !tbaa !14, !noalias !13, addrspace 1)<br>
SU(9):   %40:gpr = LW %55:gpr, 0 :: (load 4 from %ir.lsr.iv12, !tbaa !14, !noalias !13, addrspace 1)<br>
SU(12):   %42:gpr = LW %56:gpr, 4 :: (load 4 from %ir.scevgep9, !tbaa !14, !noalias !13, addrspace 1)<br>
SU(13):   %43:gpr = LW %55:gpr, 4 :: (load 4 from %ir.scevgep15, !tbaa !14, !noalias !13, addrspace 1)<br>
SU(2):   %35:gpr = nsw ADD %34:gpr, %33:gpr<br>
SU(3):   SW %35:gpr, %55:gpr, -8 :: (store 4 into %ir.scevgep14, !tbaa !14, !noalias !13, addrspace 1)<br>
SU(6):   %38:gpr = nsw ADD %37:gpr, %36:gpr<br>
SU(7):   SW %38:gpr, %55:gpr, -4 :: (store 4 into %ir.scevgep16, !tbaa !14, !noalias !13, addrspace 1)<br>
SU(10):   %41:gpr = nsw ADD %40:gpr, %39:gpr<br>
SU(11):   SW %41:gpr, %55:gpr, 0 :: (store 4 into %ir.lsr.iv12, !tbaa !14, !noalias !13, addrspace 1)<br>
SU(14):   %44:gpr = nsw ADD %43:gpr, %42:gpr<br>
SU(15):   SW %44:gpr, %55:gpr, 4 :: (store 4 into %ir.scevgep15, !tbaa !14, !noalias !13, addrspace 1)<br>
SU(16):   %57:gpr = nuw nsw ADDI %57:gpr, 4<br>
SU(17):   %56:gpr = ADDI %56:gpr, 16<br>
SU(18):   %55:gpr = ADDI %55:gpr, 16</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">And
</span><span style="font-size:12.0pt;font-family:"Courier New"">main </span><span style="font-size:12.0pt;font-family:"Arial",sans-serif">gives following schedule:</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Courier New""> *** Final schedule for %bb.0 ***<br>
 SU(0):   %2:gpr = LUI target-flags(riscv-hi) @A<br>
 SU(2):   %4:gpr = LUI target-flags(riscv-hi) @B<br>
 SU(3):   %5:gpr = LW %4:gpr, target-flags(riscv-lo) @B :: (dereferenceable load 4 from @B, !tbaa !9, !noalias !22)<br>
 SU(1):   %3:gpr = LW %2:gpr, target-flags(riscv-lo) @A :: (dereferenceable load 4 from @A, !tbaa !9, !noalias !22)<br>
 SU(4):   %6:gpr = LW %5:gpr, 0 :: (load 4 from %ir.3, !tbaa !14, !noalias !22, addrspace 1)<br>
 SU(5):   %7:gpr = LW %3:gpr, 0 :: (load 4 from %ir.1, !tbaa !14, !noalias !22, addrspace 1)<br>
 SU(6):   %8:gpr = nsw ADD %7:gpr, %6:gpr<br>
 SU(7):   SW %8:gpr, %3:gpr, 0 :: (store 4 into %ir.1, !tbaa !14, !noalias !22, addrspace 1)<br>
 SU(8):   %9:gpr = LW %5:gpr, 4 :: (load 4 from %ir.arrayidx.1, !tbaa !14, !noalias !22, addrspace 1)<br>
 SU(9):   %10:gpr = LW %3:gpr, 4 :: (load 4 from %ir.arrayidx1.1, !tbaa !14, !noalias !22, addrspace 1)<br>
 SU(10):   %11:gpr = nsw ADD %10:gpr, %9:gpr<br>
 SU(11):   SW %11:gpr, %3:gpr, 4 :: (store 4 into %ir.arrayidx1.1, !tbaa !14, !noalias !22, addrspace 1)<br>
 SU(12):   %12:gpr = LW %5:gpr, 8 :: (load 4 from %ir.arrayidx.2, !tbaa !14, !noalias !22, addrspace 1)<br>
 SU(13):   %13:gpr = LW %3:gpr, 8 :: (load 4 from %ir.arrayidx1.2, !tbaa !14, !noalias !22, addrspace 1)<br>
 SU(14):   %14:gpr = nsw ADD %13:gpr, %12:gpr<br>
 SU(15):   SW %14:gpr, %3:gpr, 8 :: (store 4 into %ir.arrayidx1.2, !tbaa !14, !noalias !22, addrspace 1)<br>
 SU(16):   %15:gpr = LW %5:gpr, 12 :: (load 4 from %ir.arrayidx.3, !tbaa !14, !noalias !22, addrspace 1)<br>
 SU(17):   %16:gpr = LW %3:gpr, 12 :: (load 4 from %ir.arrayidx1.3, !tbaa !14, !noalias !22, addrspace 1)<br>
 SU(18):   %17:gpr = nsw ADD %16:gpr, %15:gpr<br>
 SU(20):   $x10 = COPY $x0<br>
 SU(19):   SW %17:gpr, %3:gpr, 12 :: (store 4 into %ir.arrayidx1.3, !tbaa !14, !noalias !22, addrspace 1)</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">This is great! Memory accesses are marked
</span><span style="font-size:12.0pt;font-family:"Courier New"">noalias. </span><span style="font-size:12.0pt;font-family:"Arial",sans-serif">I wanted memory accesses to be annotated as noalias to basically remove loop-carried dependencies so that I can reorder
 them for efficient scheduling. But when I look at Schedule DAG,</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">For
</span><span style="font-size:12.0pt;font-family:"Courier New"">vec_add</span><span style="font-size:12.0pt;font-family:"Arial",sans-serif"> I see something like this (note
</span><span style="font-size:12.0pt;font-family:"Courier New"">BotQ.A</span><span style="font-size:12.0pt;font-family:"Arial",sans-serif">, scheduler can choose any of those => no loop carried dependence):</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Courier New"">  - Latency limited.<br>
** ScheduleDAGMILive::schedule picking next node<br>
Queue BotQ.P:<br>
Queue BotQ.A: 16 15 11 7 3<br>
  Cand SU(16) ORDER<br>
Pick Bot ORDER</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">For
</span><span style="font-size:12.0pt;font-family:"Courier New"">main</span><span style="font-size:12.0pt;font-family:"Arial",sans-serif">, at best I see something like this:</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Courier New"">** ScheduleDAGMILive::schedule picking next node<br>
Cycle: 45 BotQ.A<br>
Queue BotQ.P:<br>
Queue BotQ.A: 12 13<br>
  Cand SU(12) ORDER<br>
  Cand SU(13) ORDER</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">In theory, schedules for vec_add and main should be the same right? Is there anything else I should do to make the
</span><span style="font-size:12.0pt;font-family:"Courier New"">__restrict</span><span style="font-size:12.0pt;font-family:"Arial",sans-serif"> remove loop-carried dependence in
</span><span style="font-size:12.0pt;font-family:"Courier New"">main</span><span style="font-size:12.0pt;font-family:"Arial",sans-serif">?</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">Attaching IR and scheduler log for reference...</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif"> </span><o:p></o:p></p>
</div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">On Mon, Jun 22, 2020 at 3:03 PM Jeroen Dobbelaere <<a href="mailto:Jeroen.Dobbelaere@synopsys.com" target="_blank">Jeroen.Dobbelaere@synopsys.com</a>> wrote:<o:p></o:p></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0in;margin-bottom:5.0pt">
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Hi Bandhav,<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">as mentioned in the summary of
<a href="https://urldefense.com/v3/__https:/reviews.llvm.org/D69542__;!!A4F2R9G_pg!OmBKB80qBacnrqnvVVCAWFkwISI7m6FZ1z4B8XOkDZKUndeom24G2GmH_KktbhCAqzAnX4K4$" target="_blank">
https://reviews.llvm.org/D69542</a>  :<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">   The base version is
<a href="https://urldefense.com/v3/__https:/reviews.llvm.org/rGb2a37cfe2bda0bc8c4d2e981922b5ac59c429bdc__;!!A4F2R9G_pg!OmBKB80qBacnrqnvVVCAWFkwISI7m6FZ1z4B8XOkDZKUndeom24G2GmH_KktbhCAq3tq-EY3$" target="_blank">
b2a37cfe2bda0bc8c4d2e981922b5ac59c429bdc</a> (June 12, 2020)<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Greetings,<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Jeroen Dobbelaere<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b>From:</b> llvm-dev <<a href="mailto:llvm-dev-bounces@lists.llvm.org" target="_blank">llvm-dev-bounces@lists.llvm.org</a>>
<b>On Behalf Of </b>Bandhav Veluri via llvm-dev<br>
<b>Sent:</b> Monday, June 22, 2020 18:32<br>
<b>To:</b> Neil Henning <<a href="mailto:neil.henning@unity3d.com" target="_blank">neil.henning@unity3d.com</a>><br>
<b>Cc:</b> llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>>; Kruse, Michael <<a href="mailto:michael.kruse@anl.gov" target="_blank">michael.kruse@anl.gov</a>><br>
<b>Subject:</b> Re: [llvm-dev] Restrict qualifier on class members<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">Hi Jeroen,</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">That's great! I was trying to use the patch, what's the latest version of the project we could apply it on?</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">Hi Neil,</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">That seems like what I can do as well! Do you happen to have some examples lying around? Maybe a pointer to the planned
 presentation, if that's okay?</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">Thank you,</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Arial",sans-serif">Bandhav</span><o:p></o:p></p>
</div>
</div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">On Mon, Jun 22, 2020 at 1:55 AM Neil Henning <<a href="mailto:neil.henning@unity3d.com" target="_blank">neil.henning@unity3d.com</a>> wrote:<o:p></o:p></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0in;margin-bottom:5.0pt">
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">I was originally going to cover this in my now defunct EuroLLVM talk but... we had this exact same problem on Unity's HPC# Burst compiler - how to track no-aliasing on structs.
 We were constrained in that we had to make it work with LLVM versions all the way back to shipped LLVM 6, so what we did was:<o:p></o:p></p>
</div>
<div>
<ul type="disc">
<li class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;mso-list:l0 level1 lfo1">
Add module-level metadata that tracked whether a given struct member field was no-alias.<o:p></o:p></li><li class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;mso-list:l0 level1 lfo1">
Added our own alias analysis using createExternalAAWrapperPass to register it in the pass pipeline.<o:p></o:p></li></ul>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">This allowed us to have zero modifications to LLVM and do something useful with aliasing. The one 'issue' with it is if you have a stack-allocated struct that is SROA'ed you will
 lose the info that it was a struct, or if you are in a private/internal linkage function that has the struct as an argument, the opt passes can modify the function signature to lose the struct too. We had to do some mitigations here to get perfect aliasing
 on our usecases.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Hope this helps,<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">-Neil.<o:p></o:p></p>
</div>
</div>
</div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">On Mon, Jun 22, 2020 at 5:44 AM Michael Kruse via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<o:p></o:p></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0in;margin-bottom:5.0pt">
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Unfortunately
<a href="https://urldefense.com/v3/__https:/llvm.org/docs/LangRef.html*llvm-loop-parallel-accesses-metadata__;Iw!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLJxlIVzl$" target="_blank">
https://llvm.org/docs/LangRef.html#llvm-loop-parallel-accesses-metadata</a><br>
is not a solution here. A loop-parallel access does not imply<br>
non-aliasing. The obvious case is when only reading from a location,<br>
but even when a location is written to I'd be careful to deduce that<br>
they do not alias since it might be a "benign data race" or the value<br>
never used. Additionally, LLVM's loop unroller is known to now handle<br>
noalias metadata correctly as it just copies it.<br>
<br>
There has been a discussion here:<br>
<a href="https://urldefense.com/v3/__http:/lists.llvm.org/pipermail/llvm-dev/2020-May/141587.html__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLAvIBb7x$" target="_blank">http://lists.llvm.org/pipermail/llvm-dev/2020-May/141587.html</a><br>
<br>
Michael<br>
<br>
<br>
Am So., 21. Juni 2020 um 12:24 Uhr schrieb Johannes Doerfert via<br>
llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>>:<br>
><br>
> Hi Bandhav,<br>
><br>
><br>
> Jeroen Dobbelaere (CC'ed) is currently working on support for restrict qualified local variables and struct members.<br>
><br>
> The patches exist but are not merged yet. If you want to give it a try apply <a href="https://urldefense.com/v3/__https:/reviews.llvm.org/D69542__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLLzXOdAP$" target="_blank">
https://reviews.llvm.org/D69542</a>.<br>
><br>
><br>
> Initially I could only think of this solution for your problem: <a href="https://urldefense.com/v3/__https:/godbolt.org/z/6WtPXJ__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLEju0wQ6$" target="_blank">
https://godbolt.org/z/6WtPXJ</a><br>
><br>
> Michael (CC'ed) might now another annotation to get `llvm.access` metadata for the loop, which should do what you intend.<br>
><br>
><br>
> Cheers,<br>
><br>
>   Johannes<br>
><br>
><br>
> On 6/21/20 11:56 AM, Bandhav Veluri via llvm-dev wrote:<br>
><br>
> Hi,<br>
><br>
> I'm trying to abstract some special pointers with a class, like in the<br>
> example program below:<br>
><br>
>   1 #define __remote __attribute__((address_space(1)))<br>
>   2 #include <stdint.h><br>
>   3<br>
>   4 __remote int* A;<br>
>   5 __remote int* B;<br>
>   6<br>
>   7 class RemotePtr {<br>
>   8   private:<br>
>   9     __remote int* __restrict a;<br>
>  10<br>
>  11   public:<br>
>  12     RemotePtr(__remote int* a) : a(a) {}<br>
>  13<br>
>  14     __remote int& at(int n) {<br>
>  15       return a[n];<br>
>  16     }<br>
>  17 };<br>
>  18<br>
>  19 int main(int argc, char** argv) {<br>
>  20   RemotePtr a(A);<br>
>  21   RemotePtr b(B);<br>
>  22<br>
>  23   #pragma unroll 4<br>
>  24   for(int i=0; i<4; ++i) {<br>
>  25     <a href="https://urldefense.com/v3/__http:/a.at__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLOY-9qOq$" target="_blank">a.at</a>(i) +=
<a href="https://urldefense.com/v3/__http:/b.at__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLBIWnTL5$" target="_blank">
b.at</a>(i);<br>
>  26   }<br>
>  27<br>
>  28   return 0;<br>
>  29 }<br>
><br>
> It's given that pointer a, in each object of the class RemotePtr, is the<br>
> only pointer that can access the array pointed by it. So, I tried __remote<br>
> int* __restrict a; (line 9) construct to tell Clang the same. This doesn't<br>
> seem to work and I see no noliass in the generated IR. Specifically, I want<br>
> lines 23-26 optimized assuming no aliasing between A and B. Any reason why<br>
> Clang shouldn't annotate memory accesses in lines 23-26 with noaliass<br>
> taking line 9 into account?<br>
><br>
> The higher level problem is this: is there a way to compile lines 23-26<br>
> assuming no aliasing between A and B, by just doing something in the<br>
> RemotePtr class (so that main is clear of ugly code)? If that's not<br>
> possible, is there a way to tell Clang that lines 23-26 should assume no<br>
> aliasing at all, by some pragma?<br>
><br>
> Thank you,<br>
> Bandhav<br>
><br>
><br>
> _______________________________________________<br>
> LLVM Developers mailing list<br>
> <a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
> <a href="https://urldefense.com/v3/__https:/lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLD9-lkj8$" target="_blank">
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
><br>
> _______________________________________________<br>
> LLVM Developers mailing list<br>
> <a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
> <a href="https://urldefense.com/v3/__https:/lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLD9-lkj8$" target="_blank">
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://urldefense.com/v3/__https:/lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLD9-lkj8$" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><o:p></o:p></p>
</blockquote>
</div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><br clear="all">
<br>
-- <o:p></o:p></p>
<div>
<div>
<table class="MsoNormalTable" border="0" cellspacing="0" cellpadding="0" width="100%" style="width:100.0%;border-collapse:collapse;border-spacing:0px">
<tbody>
<tr>
<td valign="top" style="padding:0in 0in 15.0pt 0in">
<table class="MsoNormalTable" border="0" cellspacing="0" cellpadding="0" align="left" style="border-collapse:collapse;border-spacing:0px">
<tbody>
<tr>
<td width="64" valign="top" style="width:48.0pt;padding:0in 0in 0in 0in">
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;line-height:18.0pt">
<span style="font-size:12.5pt;border:solid windowtext 1.0pt;padding:0in"><img border="0" width="64" height="64" style="width:.6666in;height:.6666in" id="gmail-m_1939310555962317815m_-4201325131281898321m_-197615054483451320m_-6512711895812077998gmail-m_962587869508049584_x005f_x0000_i1025" src="cid:image001.jpg@01D64AE0.946DC580" alt="Image removed by sender."></span><o:p></o:p></p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td valign="top" style="padding:0in 0in 0in 0in">
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;line-height:11.25pt">
<b><span style="font-size:10.5pt;font-family:"Arial",sans-serif;color:black">Neil Henning</span></b><o:p></o:p></p>
</div>
</td>
</tr>
<tr>
<td valign="top" style="padding:0in 0in 0in 0in">
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;line-height:11.25pt">
<span style="font-size:10.5pt;font-family:"Arial",sans-serif;color:black">Senior Software Engineer Compiler</span><o:p></o:p></p>
</div>
</td>
</tr>
<tr>
<td valign="top" style="padding:0in 0in 0in 0in">
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;line-height:11.25pt">
<span style="font-size:9.0pt;font-family:"Arial",sans-serif;color:black"><a href="https://urldefense.com/v3/__http:/unity.com__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLJhMkp2Z$" target="_blank">unity.com</a></span><o:p></o:p></p>
</div>
</td>
</tr>
</tbody>
</table>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</body>
</html>