<div dir="ltr">Hi Tim,<div><br></div><div>For the following small case,</div><div><br></div><div>{code}</div><div><div>%X = type { i64, i64, i64 }                                                                                            </div>
<div>declare void @f(%X*)</div><div>define void @t() {</div><div>entry:</div><div>  %tmp = alloca %X</div><div>  call void @f(%X* %tmp)</div><div>  call void @f(%X* %tmp)</div><div>  ret void</div><div>}</div></div><div>{code}<br>
<div><br></div><div>We are generating AArch64 code like below </div></div><div><br></div><div>{code}</div><div><div><span class="" style="white-space:pre">    </span>stp<span class="" style="white-space:pre">       </span>x20, x19, [sp, #-32]!<br>
</div><div><span class="" style="white-space:pre">        </span>stp<span class="" style="white-space:pre">       </span>x29, x30, [sp, #16]</div><div><span class="" style="white-space:pre">        </span>add<span class="" style="white-space:pre">       </span>x29, sp, #16            // =16</div>
<div><span class="" style="white-space:pre">    </span>sub<span class="" style="white-space:pre">       </span>sp, sp, #32             // =32</div><div><span class="" style="white-space:pre">       </span>.cfi_offset w20, -32<br></div><div>
<span class="" style="white-space:pre">       </span>add<span class="" style="white-space:pre">       </span>x19, sp, #8             // =8</div><div><span class="" style="white-space:pre">        </span>mov<span class="" style="white-space:pre">       </span> x0, x19</div>
<div><span class="" style="white-space:pre">    </span>bl<span class="" style="white-space:pre">        </span>f</div><div><span class="" style="white-space:pre">  </span>mov<span class="" style="white-space:pre">       </span> x0, x19</div>
<div><span class="" style="white-space:pre">    </span>bl<span class="" style="white-space:pre">        </span>f</div><div><span class="" style="white-space:pre">  </span>sub<span class="" style="white-space:pre">       </span>sp, x29, #16            // =16</div>
<div><span class="" style="white-space:pre">    </span>ldp<span class="" style="white-space:pre">       </span>x29, x30, [sp, #16]</div><div><span class="" style="white-space:pre">        </span>ldp<span class="" style="white-space:pre">       </span>x20, x19, [sp], #32</div>
<div><span class="" style="white-space:pre">    </span>ret</div></div><div>{code}</div><div><br></div><div>x19 is used as a temp register, and accordingly we need to use a stack slot to store/load this callee-saved register. Since this case is very small, it seems to be able to be optimized like below,</div>
<div><br></div><div>{code}</div><div><div><span class="" style="white-space:pre">   </span>stp<span class="" style="white-space:pre">       </span>x29, x30, [sp, #-16]!</div><div><span class="" style="white-space:pre">      </span>mov<span class="" style="white-space:pre">       </span> x29, sp</div>
<div><span class="" style="white-space:pre">    </span>sub<span class="" style="white-space:pre">       </span>sp, sp, #32             // =32</div><div><span class="" style="white-space:pre">       </span>add<span class="" style="white-space:pre">       </span>x0, sp, #8              // =8<br>
</div><div><span class="" style="white-space:pre">        </span>bl<span class="" style="white-space:pre">        </span>f</div><div><span class="" style="white-space:pre">  </span>add<span class="" style="white-space:pre">       </span>x0, sp, #8              // =8</div>
<div><span class="" style="white-space:pre">    </span>bl<span class="" style="white-space:pre">        </span>f</div><div><span class="" style="white-space:pre">  </span>mov<span class="" style="white-space:pre">       </span> sp, x29</div>
<div><span class="" style="white-space:pre">    </span>ldp<span class="" style="white-space:pre">       </span>x29, x30, [sp], #16</div><div><span class="" style="white-space:pre">        </span>ret</div></div><div>{code}</div><div><br></div>
<div>We can do this just because "add x19, sp #8" is very fast like "mov" and can be rematerialized. So the following patch can make it work.</div><div><br></div><div>{code}</div><div><div>diff --git a/lib/Target/AArch64/AArch64InstrFormats.td b/lib/Target/AArch64/AArch64InstrFormats.td</div>
<div>index 446149b..c8122a6 100644</div><div>--- a/lib/Target/AArch64/AArch64InstrFormats.td</div><div>+++ b/lib/Target/AArch64/AArch64InstrFormats.td</div><div>@@ -1613,6 +1613,7 @@ class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,</div>
<div> multiclass AddSub<bit isSub, string mnemonic,</div><div>                   SDPatternOperator OpNode = null_frag> {</div><div>   let hasSideEffects = 0 in {</div><div>+  let isReMaterializable = 1, isAsCheapAsAMove = 1 in {</div>
<div>   // Add/Subtract immediate</div><div>   def Wri  : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,</div><div>                            mnemonic, OpNode> {</div><div>@@ -1622,6 +1623,7 @@ multiclass AddSub<bit isSub, string mnemonic,</div>
<div>                            mnemonic, OpNode> {</div><div>     let Inst{31} = 1;</div><div>   }</div><div>+  }</div><div> </div><div>   // Add/Subtract register - Only used for CodeGen</div><div>   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;</div>
<div>@@ -1680,6 +1682,7 @@ multiclass AddSub<bit isSub, string mnemonic,</div><div> multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp> {</div><div>   let isCompare = 1, Defs = [NZCV] in {</div>
<div>   // Add/Subtract immediate</div><div>+  let isReMaterializable = 1, isAsCheapAsAMove = 1 in {</div><div>   def Wri  : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,</div><div>                            mnemonic, OpNode> {</div>
<div>     let Inst{31} = 0;</div><div>@@ -1688,6 +1691,7 @@ multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp> {</div><div>                            mnemonic, OpNode> {</div><div>     let Inst{31} = 1;</div>
<div>   }</div><div>+  }</div><div> </div><div>   // Add/Subtract register</div><div>   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;</div><div>{code}<br></div></div><div><br></div><div>But ADDWri/ADDXri represents "Add (immediate) : Rd = Rn + shift(imm)" and shift can be either #0 or #12. For add with "lsl #12", it may not be the same cost as mov, so we would have to split Wri/Xri into two separate defs. Since ADDWri/ADDXri are being used around the back-end code, I not sure if this change meet your expectation and it seems not a very clean solution for me as well. Or do you know is there any smarter method in td file to dynamically assign isReMaterializable to 1 based on shift value?</div>
<div><br></div><div>Any idea?</div><div><br></div><div>Thanks,</div><div>-Jiangning</div></div>