<html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br><div><div>On Mar 24, 2014, at 10:00 AM, Nadav Rotem <<a href="mailto:nrotem@apple.com">nrotem@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class="Apple-interchange-newline">On Mar 24, 2014, at 9:51 AM, Quentin Colombet <<a href="mailto:qcolombet@apple.com">qcolombet@apple.com</a>> wrote:</div><br class="Apple-interchange-newline" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Thanks Nadav.<div><br><div><div>On Mar 23, 2014, at 2:40 PM, Nadav Rotem <<a href="mailto:nrotem@apple.com">nrotem@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class="Apple-interchange-newline">On Mar 21, 2014, at 3:55 PM, Quentin Colombet <<a href="mailto:qcolombet@apple.com">qcolombet@apple.com</a>> wrote:</div><br class="Apple-interchange-newline" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Hi Nadav,<div><br></div><div>Here is a new patch that provides the fallback patterns.</div><div><br></div><div>That said, the new patterns creates less efficient code that my initial proposal.</div><div><br></div><div>I.e., fallback patterns:</div><div><div style="margin: 0px; font-size: 11px; font-family: Menlo;"><span class="Apple-tab-span" style="white-space: pre;">   </span>movb<span class="Apple-tab-span" style="white-space: pre;">      </span>(%rdi), %al</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;"><span class="Apple-tab-span" style="white-space: pre;">    </span>vmovd<span class="Apple-tab-span" style="white-space: pre;">     </span>%eax, %xmm1</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;"><span class="Apple-tab-span" style="white-space: pre;">    </span>vpbroadcastb<span class="Apple-tab-span" style="white-space: pre;">      </span>%xmm1, %xmm1</div></div><div style="margin: 0px;">Orignial patch:</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;"><div style="margin: 0px;"><span class="Apple-tab-span" style="white-space: pre;">        </span>vpbroadcastb<span class="Apple-tab-span" style="white-space: pre;">      </span>(%rdi), %xmm1</div></div><div><br></div><div>You told me that a later pass is supposed to catch the new opportunities of load folding. Looks like it does not know how to do that across copies.</div><div>We would have to fix that at some point.</div><div><br></div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">foldMemoryOperandImpl in X86InstrInfo.cpp folds memory operands into instructions. It wonít work for integers because unlike floats you first need to move the scalar value into the vector register.</div></blockquote><div>Agreed, thatís why I said it does not know how to do that across copies :).</div><br><blockquote type="cite"><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br></div><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div>Anyhow, I think both patches are orthogonal, having fallback patterns looks like a good idea but selection directly the instructions that match what X86ISelLowering thought it was lowering seems a good approach too :).</div><div><br></div><div>What do you think?</div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">I think that vbroadcast instructions are special because of they way that they are used. In many cases the loaded value could be hoisted outside the loop but selecting the vbroadcast MI prevents the hoisting of the load.</div></blockquote><div>I see. Though the broadcast could be hoisted outside of the loop too, isnít it?</div></div></div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Oh, right, my mistake. Yes, it can also be hoisted out. </div><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br><blockquote type="cite"><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">One example is constants that are materialized to constant pool loads. Ideally we would like to save the scalar constant in memory and load it outside of the loop. However, by selecting the vbroadcast we prevent the hoisting of the load. Currently we save the pre-broadcasted constant in memory, which is wasteful. Loading from memory and splatting a value across a vector register is not an expensive operation and vbroadcast is not a huge win for the typical case. vbroadcast *is* beneficial for tiled matrix multiplications because you need to multiply a scalar by a vector, but matmul are usually hand-optimized. The typical case where vbroadcast is selected is where a constant is multiplied by a vector. Maybe you could benchmark the llvm test suite and see if it really matters. Last time I checked I found that in-register broadcasts, what were introduced in AVX2 are useful, but the AVX1 broadcasts from memory were not. </div></blockquote><div>If the patch with the fallback patterns looks good to you, Iíd like to commit it to fix the instruction selection crash.</div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Yes, please. LGTM. </div></blockquote><div>Thanks, this is r<span style="font-family: Menlo; font-size: 11px;">204631.</span></div><div><br></div>-Quentin<br><blockquote type="cite"><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div><div><br></div><div>In parallel, I will benchmark the llvm test suite to see if the other patch would help performances.</div><br><blockquote type="cite"><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br></div><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div><br></div><div>As a side question, do you happen to have a test case for the existing fallback patterns?</div><div>The original commit  r<span style="font-family: Menlo; font-size: 11px;">155437<span class="Apple-converted-space"> </span></span>do not have any test case and I was wondering how a load could have new users added to it (some constant load?). Thus, I wanted to check we were not already working around the problem I mentioned.</div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">I donít remember exactly but I can think of a case that can cause this problem.  Letís say that in two places in the program we use the vector value [1.0,1.0,1.0,1.0].  When we lower the first use we turn it into a broadcast of the loaded scalar 1.0. When we lower the second value we do the same thing, except that this time we have to uses to the ď1.0Ē scalar. Also, scalar loads to constant values are introduced in many places in ISel lowering. </div></blockquote>Makes sense.</div><div><br></div><div>Thanks,</div><div>-Quentin<br><blockquote type="cite"><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div><br></div><div>Thanks,<br><div apple-content-edited="true"><div style="font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">-Quentin</div></div><div></div></div></div><span><broadcast_fallback.patch></span><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div></div><br><div><div>On Mar 21, 2014, at 1:25 PM, Quentin Colombet <<a href="mailto:qcolombet@apple.com">qcolombet@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Talked with Nadav off-line.<div><br></div><div>In fact X86 backend has fallback patterns for such cases. We may just miss a few of them. Looking into it.</div><div><br></div><div>Thanks,<br><div apple-content-edited="true"><div style="font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">-Quentin</div></div><br><div><div>On Mar 21, 2014, at 12:49 PM, Quentin Colombet <<a href="mailto:qcolombet@apple.com">qcolombet@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Hi Nadav and Owen,<div><br></div><div>Here is a patch that fixes a cannot select failure for broadcast instruction in the X86 backend <<a href="rdar://problem/16074331">rdar://problem/16074331</a>>.</div><div>Although the fix is in the x86 backend (Nadavís domain), the root cause of the problem is in SelectionDAGISel (Owenís domain).</div><div><br></div><div>Thanks for your review and feedbacks.</div><div><br></div><div><br></div><div>** Symptom **</div><div><br></div><div>Compiling the test case in the patch with x86_64 and avx2 would produce:</div><div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">--</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">LLVM ERROR: Cannot select: 0x7f9d02059128: v8i16 = X86ISD::VBROADCAST 0x7f9d02037178 [ORD=9] [ID=13]</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">  0x7f9d02037178: i16,ch = load 0x7f9d0205ab18, 0x7f9d02059230, 0x7f9d02036b48<LD2[%cV_R.addr](align=4)> [ORD=7] [ID=11]</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">    0x7f9d02059230: i64,ch = CopyFromReg 0x7f9d01512a30, 0x7f9d02036a40 [ORD=1] [ID=8]</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">      0x7f9d02036a40: i64 = Register %vreg0 [ID=1]</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">    0x7f9d02036b48: i64 = undef [ID=3]</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">In function: isel_crash_broadcast</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">FileCheck error: '-' is empty.</div><div style="margin: 0px; font-size: 11px; font-family: Menlo; min-height: 13px;"><br></div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">--</div></div><div><br></div><div><br></div><div>** Problem **</div><div><br></div><div>The instruction supposed to match is a broadcast of a value coming from the memory, i.e., a load folded into a broadcast.</div><div>The load is used only once and the broadcast does not have any other input dependencies. Thus, the folding is possible modulo a proper scheduling of the broadcast node.</div><div><br></div><div>The problem here is that during the select phase of the  isel process, SelectionDAGISel performs a check to see if the load is foldable into the broadcast (HandleMergeInputChains). This test is overly conservative and fails to detect that the folding is okay.</div><div><br></div><div><br></div><div>** Cause **</div><div><br></div><div>HandleMergeInputChains is not actually checking that a cycle will be created if something is folded into something else.</div><div>In particular, it is not checking for reachability but instead relies on heuristics to give a quick answer. This answer is conservatively correct:</div><div>- No: no cycle will be created.</div><div>- Yes: a cycle *may* be created. </div><div><br></div><div>In this example we have something like this:</div><div><div>a = ld @a</div><div>|   \</div><div>|    st b, @b</div><div>C = vbroadcast a</div><div><br></div><div>Here, we are trying to fold a into C and there is a chain between the load of a and the store of b.</div><div>Since this chain is not part of the pattern it assumes it will create a cycle:</div><div> st b, @b</div><div>   ^</div><div>    |</div><div>    v  </div><div>C = vbroadcast ld @b</div><div><br></div><div>This is wrong, because the chain is in one direction C -> st b, i.e., we can schedule C before st b.</div><div>I beleive this limitation is intended for three reasons:</div><div>1. to avoid costly reachability checks.</div><div>2. to handle only the rewriting of token factor from the not-yet-matched nodes to the matched node.</div></div><div>3. everything that has been matched is ready to schedule.</div><div><br></div><div>Interestingly, inverting the selection order of the st and vbroadcast nodes in this dag, solves the issue, because now the store is considered as scheduled and therefore cannot create a cycle (condition #3).</div><div><br></div><div><br></div><div><span style="orphans: 2; text-align: -webkit-auto; widows: 2;">** Proposed Solution **</span></div><div><span style="orphans: 2; text-align: -webkit-auto; widows: 2;"><br></span></div><div><span style="orphans: 2; text-align: -webkit-auto; widows: 2;">Fixing the root cause of the problem requires to change a lot of assumption in SelectionDAGISel, in particular #3. Moreover, #1 may be very harmful for the compile time.</span></div><div><span style="orphans: 2; text-align: -webkit-auto; widows: 2;">Therefore, the proposed fix works around the problem by forcing a valid schedule for the broadcast instruction to please the select phase. In parallel, I will file a PR for the general issue.</span></div><div><span style="orphans: 2; text-align: -webkit-auto; widows: 2;"><br></span></div><div style="orphans: 2; widows: 2;">Other ideas are welcome!</div><div style="orphans: 2; widows: 2;"><br></div><div style="orphans: 2; widows: 2;">For the details, the patch is transforming this:</div><div style="orphans: 2; widows: 2;"><div>load -- chain --> someNode  -- more deps -></div><div>      \</div><div>        +-- use --> broadcast -- more deps -></div><div><br></div><div>Into this:</div><div>load                          +-- chain  --> someNode  -- more deps -></div><div>      \                       /</div><div>        +-- use --> broadcast -- more deps -></div><div><br></div><div>Thus, the broadcast will be schedule in place of the load. By construction, this is valid, because load has only one use and broadcast only one input dependency (the load).</div></div><div><span style="orphans: 2; text-align: -webkit-auto; widows: 2;"><br></span></div><div><span style="orphans: 2; text-align: -webkit-auto; widows: 2;">Thanks,</span></div><div><span style="orphans: 2; text-align: -webkit-auto; widows: 2;">-Quentin</span></div><div></div></div><span><broadcast.patch></span><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div></div></div>_______________________________________________<br>llvm-commits mailing list<br><a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br></blockquote></div><br></div></div>_______________________________________________<br>llvm-commits mailing list<br><a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a></blockquote></div></div></blockquote></blockquote></div></div></blockquote></blockquote></div><br></body></html>