[X86][ABI] Don't preserve return regs for preserve_all/preserve_most CCs
authorAnton Bikineev <bikineev@chromium.org>
Wed, 4 Jan 2023 23:51:21 +0000 (00:51 +0100)
committerAnton Bikineev <bikineev@chromium.org>
Mon, 23 Jan 2023 12:32:17 +0000 (13:32 +0100)
commit0276fa89d7a4dbe73105c9148f947716b3d8f17f
tree0c307cbeb77d47d6d436fbe10e27751fc42af3fb
parent291a7fcf70db4d45c24b559fc867d3499b2e1e04
[X86][ABI] Don't preserve return regs for preserve_all/preserve_most CCs

Currently both calling conventions preserve registers that are used to
store a return value. This causes the returned value to be lost:

  define i32 @bar() {
    %1 = call preserve_mostcc i32 @foo()
    ret i32 %1
  }

  define preserve_mostcc i32 @foo() {
    ret i32 2
    ; preserve_mostcc will restore %rax,
    ; whatever it was before the call.
  }

This contradicts the current documentation (preserve_allcc "behaves
identical to the `C` calling conventions on how arguments and return
values are passed") and also breaks [[clang::preserve_most]].

This change makes CSRs be preserved iff they are not used to store a
return value (e.g. %rax for scalars, {%rax:%rdx} for __int128, %xmm0
for double). For void functions no additional registers are
preserved, i.e. the behaviour is backward compatible with existing
code.

Differential Revision: https://reviews.llvm.org/D141020
llvm/docs/LangRef.rst
llvm/lib/Target/X86/X86CallingConv.td
llvm/lib/Target/X86/X86ISelLowering.cpp
llvm/test/CodeGen/X86/preserve_allcc64-ret-double.ll [new file with mode: 0644]
llvm/test/CodeGen/X86/preserve_allcc64.ll
llvm/test/CodeGen/X86/preserve_mostcc64-ret-double.ll [new file with mode: 0644]
llvm/test/CodeGen/X86/preserve_mostcc64.ll