<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Hello Daniel,</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
LLVM and GCC's optimisation levels are not really equivalent. <span style="color: rgb(0, 0, 0); font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;">In Clang, -Os makes a performance and code-size trade off. In GCC, -Os is minimising code-size,
 which is equivalent to -Oz with Clang. I have't looked into details yet, but changing -Os to -Oz in the godbolt link gives the codegen you're looking for?</span></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Cheers,</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Sjoerd.</div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> llvm-dev <llvm-dev-bounces@lists.llvm.org> on behalf of Daniel Way via llvm-dev <llvm-dev@lists.llvm.org><br>
<b>Sent:</b> 20 July 2020 06:54<br>
<b>To:</b> llvm-dev@lists.llvm.org <llvm-dev@lists.llvm.org><br>
<b>Subject:</b> [llvm-dev] [ARM] Should Use Load and Store with Register Offset</font>
<div> </div>
</div>
<div>
<div dir="ltr">
<div class="x_gmail_default" style="font-family:arial,helvetica,sans-serif">Hello LLVM Community (specifically anyone working with ARM Cortex-M),</div>
<div class="x_gmail_default" style="font-family:arial,helvetica,sans-serif"><br>
</div>
<div class="x_gmail_default" style="font-family:arial,helvetica,sans-serif">While trying to compile the Newlib C library I found that Clang10 was generating slightly larger binaries than the libc from the prebuilt gcc-arm-none-eabi toolchain. I looked at a
 few specific functions (memcpy, strcpy, etc.) and noticed that LLVM does not tend to generate load/store instructions with a register offset (e.g. ldr Rd, [Rn, Rm] form) and instead prefers the immediate offset form.</div>
<div class="x_gmail_default" style="font-family:arial,helvetica,sans-serif"><br>
</div>
<div class="x_gmail_default" style="font-family:arial,helvetica,sans-serif">When copying a contiguous sequence of bytes, this results in additional instructions to modify the base address. <a href="https://godbolt.org/z/T1xhae">https://godbolt.org/z/T1xhae</a></div>
<div class="x_gmail_default" style="font-family:arial,helvetica,sans-serif"><br>
</div>
<div class="x_gmail_default" style="font-family:arial,helvetica,sans-serif">
<div style="color:rgb(0,0,0); background-color:rgb(255,255,254); font-family:"Consolas, "">
<div><span style="color:rgb(0,0,255)">void</span>* memcpy_alt1(<span style="color:rgb(0,0,255)">void</span>* dst, <span style="color:rgb(0,0,255)">const</span> <span style="color:rgb(0,0,255)">void</span>* src, size_t len) {</div>
<div>    <span style="color:rgb(0,0,255)">char</span>* save = (<span style="color:rgb(0,0,255)">char</span>*)dst;</div>
<div>    <span style="color:rgb(0,0,255)">for</span> (size_t i = <span style="color:rgb(9,134,88)">0</span>; i < len; ++i)</div>
<div>        *((<span style="color:rgb(0,0,255)">char</span>*)(dst + i)) = *((<span style="color:rgb(0,0,255)">char</span>*)(src + i));</div>
<div>    <span style="color:rgb(0,0,255)">return</span> save;</div>
<div>}</div>
<div><br>
</div>
<div>clang --target=armv6m-none-eabi -Os -fomit-frame-pointer</div>
<div>
<div>
<div><span style="color:rgb(0,128,128)">memcpy_alt1:</span></div>
<div>        <span style="color:rgb(0,0,255)">push</span>    {<span style="color:rgb(72,100,170)">r4</span>, <span style="color:rgb(72,100,170)">lr</span>}</div>
<div>        <span style="color:rgb(0,0,255)">cmp</span>     <span style="color:rgb(72,100,170)">r2</span>, <span style="color:rgb(9,134,88)">#0</span></div>
<div>        <span style="color:rgb(0,0,255)">beq</span>     <span style="color:rgb(0,128,128)">.LBB0_3</span></div>
<div>        <span style="color:rgb(0,0,255)">mov</span>     <span style="color:rgb(72,100,170)">r3</span>, <span style="color:rgb(72,100,170)">r0</span></div>
<div><span style="color:rgb(0,128,128)">.LBB0_2:</span></div>
<div>        <span style="color:rgb(0,0,255)">ldrb</span>    <span style="color:rgb(72,100,170)">r4</span>, [<span style="color:rgb(72,100,170)">r1</span>]</div>
<div>        <span style="color:rgb(0,0,255)">strb</span>    <span style="color:rgb(72,100,170)">r4</span>, [<span style="color:rgb(72,100,170)">r3</span>]</div>
<div>        <span style="color:rgb(0,0,255)">adds</span>    <span style="color:rgb(72,100,170)">r1</span>, <span style="color:rgb(72,100,170)">r1</span>, <span style="color:rgb(9,134,88)">#1</span></div>
<div>        <span style="color:rgb(0,0,255)">adds</span>    <span style="color:rgb(72,100,170)">r3</span>, <span style="color:rgb(72,100,170)">r3</span>, <span style="color:rgb(9,134,88)">#1</span></div>
<div>        <span style="color:rgb(0,0,255)">subs</span>    <span style="color:rgb(72,100,170)">r2</span>, <span style="color:rgb(72,100,170)">r2</span>, <span style="color:rgb(9,134,88)">#1</span></div>
<div>        <span style="color:rgb(0,0,255)">bne</span>     <span style="color:rgb(0,128,128)">.LBB0_2</span></div>
<div><span style="color:rgb(0,128,128)">.LBB0_3:</span></div>
<div>        <span style="color:rgb(0,0,255)">pop</span>     {<span style="color:rgb(72,100,170)">r4</span>, <span style="color:rgb(0,128,128)">pc</span>}</div>
</div>
</div>
<div><br>
</div>
<div>arm-none-eabi-gcc -march=armv6-m -Os</div>
<div>
<div>
<div><span style="color:rgb(0,128,128)">memcpy_alt1:</span></div>
<div>        <span style="color:rgb(0,0,255)">movs</span>    <span style="color:rgb(72,100,170)">r3</span>, <span style="color:rgb(9,134,88)">#0</span></div>
<div>        <span style="color:rgb(0,0,255)">push</span>    {<span style="color:rgb(72,100,170)">r4</span>, <span style="color:rgb(72,100,170)">lr</span>}</div>
<div><span style="color:rgb(0,128,128)">.L2:</span></div>
<div>        <span style="color:rgb(0,0,255)">cmp</span>     <span style="color:rgb(72,100,170)">r3</span>, <span style="color:rgb(72,100,170)">r2</span></div>
<div>        <span style="color:rgb(0,0,255)">bne</span>     <span style="color:rgb(0,128,128)">.L3</span></div>
<div>        <span style="color:rgb(0,0,255)">pop</span>     {<span style="color:rgb(72,100,170)">r4</span>, <span style="color:rgb(0,128,128)">pc</span>}</div>
<div><span style="color:rgb(0,128,128)">.L3:</span></div>
<div>        <span style="color:rgb(0,0,255)">ldrb</span>    <span style="color:rgb(72,100,170)">r4</span>, [<span style="color:rgb(72,100,170)">r1</span>, <span style="color:rgb(72,100,170)">r3</span>]</div>
<div>        <span style="color:rgb(0,0,255)">strb</span>    <span style="color:rgb(72,100,170)">r4</span>, [<span style="color:rgb(72,100,170)">r0</span>, <span style="color:rgb(72,100,170)">r3</span>]</div>
<div>        <span style="color:rgb(0,0,255)">adds</span>    <span style="color:rgb(72,100,170)">r3</span>, <span style="color:rgb(72,100,170)">r3</span>, <span style="color:rgb(9,134,88)">#1</span></div>
<div>        <span style="color:rgb(0,0,255)">b</span>       <span style="color:rgb(0,128,128)">.L2</span></div>
</div>
</div>
</div>
</div>
<div class="x_gmail_default" style="font-family:arial,helvetica,sans-serif"><br>
</div>
<div class="x_gmail_default" style="font-family:arial,helvetica,sans-serif">Because this code appears in a loop that could be copying hundreds of bytes, I want to add an optimization that will prioritize load/store instructions with register offsets when the
 offset is used multiple times. I have not worked on LLVM before, so I'd like advice about where to start.</div>
<div class="x_gmail_default" style="">
<ul style="font-family:arial,helvetica,sans-serif">
<li>The generated code is correct, just sub-optimal so is it appropriate to submit a bug report?</li><li>Is anyone already tackling this change or is there someone with more experience interested in collaborating?</li><li>Is this optimization better performed early during instruction selection or late using c++ (i.e. ARMLoadStoreOptimizer.cpp)</li><li>What is the potential to cause harm to other parts of the code gen, specifically for other arm targets. I'm working with armv6m, but armv7m offers base register updating in a single instruction. I don't want to break other useful optimizations.</li></ul>
<div style="font-family:arial,helvetica,sans-serif">So far, I am reading through the LLVM documentation to see where a change could be applied. I have also:</div>
<div style="">
<ul style="">
<li style="font-family:arial,helvetica,sans-serif">Compiled with -S -emit-llvm (see Godbolt link)<br>
There is an identifiable pattern where a getelementptr function is followed by a load or store. When multiple getelementptr functions appear with the same virtual register offset, maybe this should match a tLDRr or tSTRr.</li><li style=""><font face="arial, helvetica, sans-serif">Ran LLC with  </font>--print-machineinstrs <br>
It appears that tLDRBi and tSTRBi are selected very early and never replaced by the equivalent t<LDRB|STRB>r instructions.</li></ul>
<div>Thank you,</div>
</div>
</div>
<div class="x_gmail_default" style="font-family:arial,helvetica,sans-serif"><br>
</div>
<div>
<div dir="ltr" class="x_gmail_signature">
<div dir="ltr">
<div>Daniel Way</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>