This is an archive of the discontinued LLVM Phabricator instance.

[AArch64] [GlobalISel] Fix clobbered callee saved registers with win64 varargs
ClosedPublic

Authored by mstorsjo on Aug 18 2023, 5:52 AM.

Details

Summary

This fixes a regression since 1c10d5b175992a9d056a2d763a932e5652386fc1
/ https://reviews.llvm.org/D130903 by applying the same fix from
SelectionDAG from 8cb3667541a94c4fa11b06e19020f753414c1d03 /
https://reviews.llvm.org/D35720.

This could possibly have been detected if the existing testcases
in win64_vararg.ll had been tested with GlobalISel too, but all
the IR snippets there fail to be translated with GlobalISel.

This adds a separate testcase based on real world LLVM IR (instead of
hand-reduced IR), which GlobalISel does translate happily - tested
with both SelectionDAG and GlobalISel.

Before this change, the stack object locations (visible in MIR
with "llc -print-after-all") didn't match with what the prologue
emitted by AArch64FrameLowering actually looked like, which caused
clobbered callee saved registers when function local stack objects
aliased the actual location of the callee saved registers.

This fixes https://github.com/llvm/llvm-project/issues/64740.

Diff Detail

Event Timeline

mstorsjo created this revision.Aug 18 2023, 5:52 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 18 2023, 5:52 AM
mstorsjo requested review of this revision.Aug 18 2023, 5:52 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 18 2023, 5:52 AM
arsenm added a subscriber: arsenm.Aug 18 2023, 6:08 AM
arsenm added inline comments.
llvm/test/CodeGen/AArch64/win64_vararg2.ll
73–74

Use named values

tschuett added inline comments.
llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
567

Is this:
if (GPRSaveSize & 15 > 0) or
if (GPRSaveSize & 15 == 15) ?

mstorsjo added inline comments.Aug 18 2023, 7:29 AM
llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
567

It's if ((GPRSaveSize & 15) > 0) - or practically if ((GPRSaveSize & 15) == 8) as GPRSaveSize is in increments of 8. It's essentially checking whether GPRArgRegs.size() - FirstVariadicGPR is even or odd.

This is kept very similar to https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp#L6699-L6706.

llvm/test/CodeGen/AArch64/win64_vararg2.ll
73–74

Ok, I can change it that way.

FWIW, this was just the pretty much unreduced output from Clang. We've got a bunch of preexisting similar hand-reduced IR cases in win64_vararg.ll, but all of those make globalisel bail out, so I wanted to have a case that globalisel actually does accept.

mstorsjo updated this revision to Diff 551645.Aug 18 2023, 2:41 PM

Simplified the testcase a little, rewrote the test IR to use named values.

dzhidzhoev added inline comments.Aug 18 2023, 3:07 PM
llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
570

nit: static_cast?

mstorsjo updated this revision to Diff 551660.Aug 18 2023, 3:22 PM

Use static_cast

Looks good to me

Looks good to me

Thanks! Would you care to set the formal approval flag as well? (I'd like to get this landed so I can flag it for backporting soon - this can cause subtle breakage for any vararg function on windows/aarch64, if compiled without optimizations.)

For context; D130903 ported a bunch of logic from SelectionDAG to GlobalISel, but skipped these lines as they were believed to not be necessary - but they turned out to be needed after all. This patch readds the few lines that were skipped. (They have been in place in the SelectionDAG implementation since 2017.)

dzhidzhoev accepted this revision.Aug 21 2023, 4:07 AM
This revision is now accepted and ready to land.Aug 21 2023, 4:07 AM
This revision was landed with ongoing or failed builds.Aug 21 2023, 4:17 AM
This revision was automatically updated to reflect the committed changes.