[llvm-dev] Issue with shrink wrapping

Francis Visoiu Mistrih via llvm-dev llvm-dev at lists.llvm.org
Tue Apr 10 03:39:41 PDT 2018


Hello Momchil,

(CC’ing more people that could correct me if I’m wrong)

Thanks for looking into this. More answers below:

> On 9 Apr 2018, at 17:57, Momchil Velikov via llvm-dev <llvm-dev at lists.llvm.org> wrote:
> 
> Hello,
> 
> So, I have this testcase:
> 
>     void f(int n, int x[]) {
>       if (n < 0)
>         return;
> 
>       int a[n];
> 
>       for (int i = 0; i < n; i++)
>         a[i] = x[n - i - 1];
> 
>       for (int i = 0; i < n; i++)
>         x[i] = a[i] + 1;
>     }
> 
> that, compiled with -O1/-Os for AArch64 and X86, generates machine code, which
> fails to properly restore the stack pointer upon function return.
> 
> The testcase allocates a VLA, thus clang generates calls to `llvm.stacksave` and
> `llvm.stackrestore`. The latter call is lowered to `mov sp, x2`, however this
> move does not affect decisions made by the shrink wrapping pass, as the
> instruction does not use or define a callee-saved register.

I was afraid that this would happen at some point, but never came across a miscompile due to this. I guess the assumption here was that all the code using the stack pointer is generated after/during PEI, so tracking FrameIndex operands would be sufficient.

> 
> The end effect is that placement of register save/restore code is such that
> along a certain path, the callee-saved registers and the stack pointer are
> restored, but then the stack pointer is overwritten with an incorrect value.
> 
> I've "fixed" this by modifying `ShrinkWrap::useOrDefCSROrFI` to explicitly check
> for the stack pointer register (using
> `TLI.getStackPointerRegisterToSaveRestore`)

This part sounds ok to me. Can you put up a patch please?

> and also to ignore tall call
> instructions (`isCall() && isReturn()`), since they implictly use SP (for
> AArch{32,64} at least).

Calls are handled through the regmask check, and return blocks should be handled by the common-dominator call. Did you run into any issues with this? Marking blocks containing `isReturn` instructions as used will basically make shrink-wrapping to fail all the time.

> 
> Does this look correct? Are there alternatives?

Another thing we could do is to add SP (through TLI.getStackPointerRegisterToSaveRestore) to the CurrentCSRs set (and probably rename the set).

> 
> Shouldn't `ShrinkWrap::useOrDefCSROrFI` also check whether or not
> `MachineInstr::Frame{Setup,Destroy}` flags are set?

It’s not perfectly clear what the flag is used for and whether all targets use it for the same purpose. There has been some discussion here: http://lists.llvm.org/pipermail/llvm-dev/2017-February/110281.html <http://lists.llvm.org/pipermail/llvm-dev/2017-February/110281.html>, but I wouldn’t rely on that flag, especially if we want to be able to do some more advanced shrink-wrapping, we are better knowing why the instruction is considered as a “FrameSetup/Destroy” instruction.

> 
> In that case, I suppose an alternative slution would be to ensure that
> `llvm.{stacksave,stackrestore} are ultimately lowered to `MachineInstr`s, which
> have these flags set, perhaps by custom lowering of
> ISD::{STACKSAVE,STACKRESTORE} to pseudo-instructions? That'd involve changes to
> each backend, where shrink wrapping is enabled, although it looks least hackish.

I think the SP approach is correct, but yes, this would work as well.

Thanks,

— 
Francis

> 
> Comments?
> 
> Thanks and best regards,
> Momchil Velikov
> 
> 
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180410/5105503d/attachment.html>


More information about the llvm-dev mailing list