<div dir="ltr">Hi James, Arnaud, Sebastian,<div><br></div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">I think one idea to improve the situation is to consider the cost vector of adjacent nodes during RN. Let's say you decided to do a RN for node A and want to compute the costs for choosing register %Ri. The current implementation does this by computing min(row/column i of edge A <--> B) but you can do better by adding B's cost vector to the row/column before computing the minimum. This way you also consider B's affinitiy for %R0.</blockquote></div><div><br></div><div>The current solver does not use an "RN" rule as such (certainly nothing comparable to what was discussed in the 2002 Scholz/Eckstein paper). We have a heuristic rule for selecting nodes for reduction, but we do not propagate costs from heuristically reduced nodes until backpropagation.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span style="color:rgb(33,33,33);font-family:'helvetica neue',helvetica,arial,sans-serif;font-size:12.800000190734863px">In fact, it seems even worse than this; if RN is used, then all neighbors are disconnected. So during backpropagation, unless I'm missing something, it seems we will only ever consider the node cost, never adding in any edge cost.</span></blockquote><div><span style="color:rgb(33,33,33);font-family:'helvetica neue',helvetica,arial,sans-serif;font-size:12.800000190734863px"><br></span></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px">I think you're right, but just to be precise: In the current solver any heuristically reduced node is colored during backpropagation taking into account the costs for nodes further up the stack (i.e. ones that have been colored earlier during backpropagation) only. Nodes further down in the stack are not considered.</span></font></div><div><span style="color:rgb(33,33,33);font-family:'helvetica neue',helvetica,arial,sans-serif;font-size:12.800000190734863px"><br></span></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px">The metric we use for spill cost being what it is (i.e. not targeted for PBQP, but that’s a different subject)...</span></font></blockquote><div><br></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px">Yes - this is also a very interesting subject.</span></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px"><br></span></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px">So: There are four things that we can tweak that I know of:</span></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px"><br></span></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px">(1) Spill cost metrics.</span></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px">(2) Heuristic node <i>selection</i>. (Currently "provably colorable nodes first (in no particular order as far as I remember), possibly uncolorable nodes last in order of spill cost")</span></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px">(3) Speculative assignment during heuristic reduction - propagate costs onto neighbors of the RN node based on a localized guess at the best solution.</span></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px">(4) Look-ahead during backpropagation.</span></font></div><div><br></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px">All of these are worth looking at, but I'd be inclined to look at (2) (maybe we should reduce nodes with many affinity edges later, so that they're colored earlier?) and (4) (a user-configurable lookahead would let clients trade compile-time for allocation quality smoothly).</span></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px"><br></span></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px">James - how can I reproduce your test case? I tried with r271685 using 'llc -O3 -regalloc=pbqp zia.ll', but I got:</span></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px"><br></span></font></div><div><font color="#212121"><span style="font-size:12.800000190734863px"><div><div><font face="monospace, monospace">bar:</font></div><div><font face="monospace, monospace">        .fnstart</font></div><div><font face="monospace, monospace">@ BB#0:</font></div><div><font face="monospace, monospace">        .save   {r0, r1, r2, r3, r4, lr}</font></div><div><font face="monospace, monospace">        push    {r0, r1, r2, r3, r4, lr}</font></div><div><font face="monospace, monospace">        ldr     r0, .LCPI0_0</font></div><div><font face="monospace, monospace">        ldm.w   r0, {r1, r2, r3, r12, lr}</font></div><div><font face="monospace, monospace">        ldrd    r4, r0, [r0, #20]</font></div><div><font face="monospace, monospace">        strd    lr, r4, [sp]</font></div><div><font face="monospace, monospace">        str     r0, [sp, #8]</font></div><div><font face="monospace, monospace">        mov     r0, r1</font></div><div><font face="monospace, monospace">        mov     r1, r2</font></div><div><font face="monospace, monospace">        mov     r2, r3</font></div><div><font face="monospace, monospace">        mov     r3, r12</font></div><div><font face="monospace, monospace">        bl      baz</font></div><div><font face="monospace, monospace">        pop     {r0, r1, r2, r3, r4, pc}</font></div><div><font face="monospace, monospace">        .p2align        2</font></div></div><div style="font-family:'helvetica neue',helvetica,arial,sans-serif"><br></div></span></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px">which has even more registers used.</span></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px"><br></span></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px">Cheers,</span></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px">Lang.</span></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><span style="font-size:12.800000190734863px"><br></span></font></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jun 3, 2016 at 11:09 AM, James Molloy <span dir="ltr"><<a href="mailto:james@jamesmolloy.co.uk" target="_blank">james@jamesmolloy.co.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi,<span class=""><div><br></div><div>> <span style="color:rgb(33,33,33);font-family:'helvetica neue',helvetica,arial,sans-serif;line-height:1.5">> I think one idea to improve the situation is to consider the cost vector of adjacent nodes during RN. Let's say you decided to do a RN for node A and want to compute the costs for choosing register %Ri. The current implementation does this by computing min(row/column i of edge A <--> B) but you can do better by adding B's cost vector to the row/column before computing the minimum. This way you also consider B's affinitiy for %R0.</span></div><div><span style="color:rgb(33,33,33);font-family:'helvetica neue',helvetica,arial,sans-serif;line-height:1.5"><br></span></div></span><div><span style="color:rgb(33,33,33);font-family:'helvetica neue',helvetica,arial,sans-serif;line-height:1.5">In fact, it seems even worse than this; if RN is used, then all neighbors are disconnected. So during backpropagation, unless I'm missing something, it seems we will only ever consider the node cost, never adding in any edge cost.</span></div></div><div class="HOEnZb"><div class="h5"><br><div class="gmail_quote"><div dir="ltr">On Fri, 3 Jun 2016 at 19:04 James Molloy <<a href="mailto:james@jamesmolloy.co.uk" target="_blank">james@jamesmolloy.co.uk</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Sebastien,</div><div dir="ltr"><div><br></div><div><span style="color:rgb(33,33,33);font-family:'helvetica neue',helvetica,arial,sans-serif">> I think one idea to improve the situation is to consider the cost vector of adjacent nodes during RN. Let's say you decided to do a RN for node A and want to compute the costs for choosing register %Ri. The current implementation does this by computing min(row/column i of edge A <--> B) but you can do better by adding B's cost vector to the row/column before computing the minimum. This way you also consider B's affinitiy for %R0.</span><br></div><div><span style="color:rgb(33,33,33);font-family:'helvetica neue',helvetica,arial,sans-serif"><br></span></div></div><div dir="ltr"><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif">Am I right in thinking that this extra calculation would take place during the backpropagation phase?</font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><br></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif">I'm also interested as to whether such a calculation would be sufficient when more copies are inserted (a chain of copies):</font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><br></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif">      COPY           COPY</font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif">A <--------> B <---------> C</font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><br></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif">If we reduce B last, and we only account for neighboring affinities at the backpropagation phase, we will not get an optimal allocation. However if we could somehow propagate neighboring affinities at the *reduction* stage, perhaps we might get a transitivity property emerging that could solve the above case optimally?</font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><br></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif">I'm very much a newbie in this area so be gentle on me :)</font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><br></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif">Cheers,</font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif"><br></font></div><div><font color="#212121" face="helvetica neue, helvetica, arial, sans-serif">James</font></div></div><br><div class="gmail_quote"><div dir="ltr">On Fri, 3 Jun 2016 at 15:33 Arnaud De Grandmaison <<a href="mailto:Arnaud.DeGrandmaison@arm.com" target="_blank">Arnaud.DeGrandmaison@arm.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">





<div bgcolor="white" lang="FR" link="blue" vlink="purple">
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Hi James,<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">I’ve tried to play in the past with the allocation order, which can definitely be tweaked and improved. The metric we use for spill cost being
 what it is (i.e. not targeted for PBQP, but that’s a different subject), I found it made real sense to use some other heuristics to sort nodes (on top of the spill cost) when there was a tie between them.  Of course, that’s a heuristic and it can sometimes
 be wrong. Another option I tried was to ensure the nodes’ allocation order gets updated when some costs are propagated.<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">I have also tried to implement something along the lines of what Sebastian suggested (i.e. considering the cost of adjacent nodes). This made the
 allocation better, but allocation time went very high --- but I had no time to try to improve the heuristic.<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">I did not know about Sebastian et al paper, so thanks for pointing to it !
<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Cheers,<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Arnaud<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></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><span lang="EN-US" style="font-size:10.0pt;font-family:"Tahoma","sans-serif";color:windowtext">From:</span></b><span lang="EN-US" style="font-size:10.0pt;font-family:"Tahoma","sans-serif";color:windowtext"> Sebastian Buchwald [mailto:<a href="mailto:Sebastian.Buchwald@kit.edu" target="_blank">Sebastian.Buchwald@kit.edu</a>]
<br>
<b>Sent:</b> 02 June 2016 20:57<br>
<b>To:</b> <a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>; <a href="mailto:james@jamesmolloy.co.uk" target="_blank">james@jamesmolloy.co.uk</a>; <a href="mailto:lhames@gmail.com" target="_blank">lhames@gmail.com</a>; Arnaud De Grandmaison<br>
<b>Subject:</b> Re: [llvm-dev] PBQP register allocation and copy propagation<u></u><u></u></span></p>
</div>
</div></div></div></div><div bgcolor="white" lang="FR" link="blue" vlink="purple"><div><div style="border:none;border-left:solid blue 1.5pt;padding:0cm 0cm 0cm 4.0pt">
<p class="MsoNormal"><u></u> <u></u></p>
<div>
<p class="MsoNormal">On 06/02/2016 07:22 PM, James Molloy via llvm-dev wrote:<u></u><u></u></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<div>
<p class="MsoNormal">Hi Lang and Arnaud,<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">I've been testing out the PBQP allocator for Thumb-2 and have ran into a problem I'd love to get your input on.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">The problem is exemplfied in the codegen for the function @bar in the attached IR file:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">bar:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">        push    {r4, lr}<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">        sub     sp, #12<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> (1)    movw    r2, :lower16:.L_MergedGlobals<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> (1)    movt    r2, :upper16:.L_MergedGlobals<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">        ldm.w   r2, {r0, r1, r3, r12, lr}<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">        ldrd    r4, r2, [r2, #20]<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">        strd    lr, r4, [sp]<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">        str     r2, [sp, #8]<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> (2)    mov     r2, r3         ****<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">        mov     r3, r12        ****<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">        bl      baz<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">        add     sp, #12<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">        pop     {r4, pc}<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">The two moves marked with **** are unnecessary. Especially the first, which could be removed simply by swapping r2 and r3. This becomes even more pronounced when I teach PBQP about how best to use registers to allow LDM/STM formation; the
 codegen is perfect apart from those two moves that just won't go.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">I've discovered that the underlying problem is that line (1) is reduced after line (2). During the backpropagation phase (1) is allocated r2 which means (2) cannot, as they interfere.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Interestingly they're both reduced by rule RN and as the spill cost is the same between them (and they're both conservatively allocatable), it's pure luck which gets allocated first. I have a patch to account for the opportunity cost of
 allocating r2 to (1) instead of (2) by assigning a cost to r2 in (1)'s affinity matrix; this seems to work. However I don't really know what's the right approach here - dealing with this problem purely by propagating opportunity costs through affinity matrices
 or doing something better with the reduction order.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">This ties in with another problem I'm seeing with a prototype live-range splitter for PBQP. Obviously when pre-splitting around every instruction, many copies are inserted. But the above problem rears its head again! Consider this:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">%vregB = COPY %R0<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">%vregA = COPY %vregB<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">      COPY<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">  A <------> B<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Node B has an affinity for register R0. The affinity edge between A and B is a simple coalescing affinity (identity matrix). If B is assigned first, it will get R0 and then A will also select R0. However if A is selected first then it doesn't
 know anything about node B's affinities and could thus get any register, causing a MOV.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">The above trivial example would be reduced by rule R1, so would actually work optimally (because the reduction would account for B's costs in A). However it is trivial to add two or more interfering defs that cause the reduction rule to
 change to RN:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">%vregC = def...<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">%vregD = def...<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">%vregB = COPY %R0<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">%vregA = COPY %vregB<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">       = use %vregC, %vregD<u></u><u></u></p>
</div>
</div>
</blockquote>
<p class="MsoNormal">I think one idea to improve the situation is to consider the cost vector of adjacent nodes during RN. Let's say you decided to do a RN for node A and want to compute the costs for choosing register %Ri. The current implementation does this
 by computing min(row/column i of edge A <--> B) but you can do better by adding B's cost vector to the row/column before computing the minimum. This way you also consider B's affinitiy for %R0.<br>
<br>
<br>
<u></u><u></u></p>
<div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Now the reduction order is arbitrary and local costs aren't propagated unlike R1 and R2. In fact, there is a rule "RM" proposed by Buchwald [1] that seeks to fix a very similar case to this.<u></u><u></u></p>
</div>
</div>
<p class="MsoNormal">Porting RM to that situation would basically say "always fulfill this affinity" (beween A and B). Of course that's the wrong choice, if you really need the copy.<br>
<br>
Best regards,<br>
Sebastian<br>
<br>
<br>
<u></u><u></u></p>
<div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">What do you think?<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Cheers,<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">James<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">[1] SSA-based Register Allocation with PBQP, Buchwald et al,
<a href="https://pp.info.uni-karlsruhe.de/uploads/publikationen/buchwald11cc.pdf" target="_blank">
https://pp.info.uni-karlsruhe.de/uploads/publikationen/buchwald11cc.pdf</a><u></u><u></u></p>
</div>
</div>
<p class="MsoNormal"><br>
<br>
<br>
<u></u><u></u></p>
<pre>_______________________________________________<u></u><u></u></pre>
<pre>LLVM Developers mailing list<u></u><u></u></pre>
<pre><a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><u></u><u></u></pre>
<pre><a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><u></u><u></u></pre>
<p class="MsoNormal"><u></u> <u></u></p>
</div></div></div><div bgcolor="white" lang="FR" link="blue" vlink="purple"><div><div style="border:none;border-left:solid blue 1.5pt;padding:0cm 0cm 0cm 4.0pt"></div>
</div>
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose,
 or store or copy the information in any medium. Thank you.
</div>

</blockquote></div></blockquote></div>
</div></div></blockquote></div><br></div>