This is an archive of the discontinued LLVM Phabricator instance.

Weaken MFI Max Call Frame Size Assertion
ClosedPublic

Authored by oskarwirga on May 23 2023, 6:27 PM.

Details

Summary

A year ago when I was not invested at all into compilers, I found an assertion error when building an AArch64 debug build with LTO + CFI, among other combinations.

It was posted as a github issue here: https://github.com/llvm/llvm-project/issues/54088

I took it upon myself to revisit the issue now that I have spent some more time working on LLVM.

Diff Detail

Event Timeline

oskarwirga created this revision.May 23 2023, 6:27 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 23 2023, 6:27 PM
oskarwirga requested review of this revision.May 23 2023, 6:27 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 23 2023, 6:27 PM
barannikov88 added inline comments.
llvm/test/CodeGen/AArch64/compute-call-frame-size-unreachable-pass.ll
2

The test without -mtriple will run for the default target (LLVM_DEFAULT_TARGET_TRIPLE). Does it trigger on any backend?
If so, can it be moved to llvm/test/CodeGen/Generic?

barannikov88 added inline comments.May 23 2023, 6:58 PM
llvm/test/CodeGen/AArch64/compute-call-frame-size-unreachable-pass.ll
2

Ah, never mind, it contains the triple string.
It is a bit of unusual though, llc test don't usually have neither triple nor datalayout.

oskarwirga added inline comments.May 23 2023, 7:37 PM
llvm/test/CodeGen/AArch64/compute-call-frame-size-unreachable-pass.ll
2

I don't know what is usual when it comes to this stuff, happy to change things to make it proper :)

I'm not sure this is the correct fix. The assertion specifically checks that MaxCallFrameSize and AdjustsStack computed here are the same as computed by MachineFrameInfo::computeMaxCallFrameSize.
Have you been able to figure out why the results of the calculations are different?

llvm/test/CodeGen/AArch64/compute-call-frame-size-unreachable-pass.ll
2

llc tests usually have -mtriple argument instead of specifying 'target triple' in the source and usually don't have 'target datalayout' (it is inferred from the triple).
This allows you to write multiple RUN lines with different -mtriple's, i.e. makes tests more flexible.

I'm not sure this is the correct fix. The assertion specifically checks that MaxCallFrameSize and AdjustsStack computed here are the same as computed by MachineFrameInfo::computeMaxCallFrameSize.
Have you been able to figure out why the results of the calculations are different?

Yes, bcl5980 commented on the github issue:

In the AArch64TargetLowering::finalizeLowering it call MFI.computeMaxCallFrameSize(MF) to get MaxCallFrameSize
MaxCallFrameSize is 8 because a ADJCALLSTACKDOWN/ADJCALLSTACKUP in bb.2
And in the pass unreachable-mbb-elimination, bb.2 will be removed
Then the assert will be triggered in the pass prologepilog
Not sure how to fix the assert

I was able to fix this assertion by appending to UnreachableMachineBlockElim::runOnMachineFunction

MachineFrameInfo &MFI = F.getFrameInfo();
MFI.computeMaxCallFrameSize(F);

but was advised to weaken this assertion by @MatzeB with his reasoning being that the assertion was mostly to catch cases where the value grew later, rather than shrank.

barannikov88 added a comment.EditedMay 23 2023, 9:28 PM

I'm not sure this is the correct fix. The assertion specifically checks that MaxCallFrameSize and AdjustsStack computed here are the same as computed by MachineFrameInfo::computeMaxCallFrameSize.
Have you been able to figure out why the results of the calculations are different?

Yes, bcl5980 commented on the github issue:

In the AArch64TargetLowering::finalizeLowering it call MFI.computeMaxCallFrameSize(MF) to get MaxCallFrameSize
MaxCallFrameSize is 8 because a ADJCALLSTACKDOWN/ADJCALLSTACKUP in bb.2
And in the pass unreachable-mbb-elimination, bb.2 will be removed
Then the assert will be triggered in the pass prologepilog
Not sure how to fix the assert

I was able to fix this assertion by appending to UnreachableMachineBlockElim::runOnMachineFunction

MachineFrameInfo &MFI = F.getFrameInfo();
MFI.computeMaxCallFrameSize(F);

but was advised to weaken this assertion by @MatzeB with his reasoning being that the assertion was mostly to catch cases where the value grew later, rather than shrank.

In this case AdjustsStack on line 352 should be initialized to false and MFI.adjustsStack() == AdjustsStack should also be removed making this assertion kind of useless.
If @MatzeB is happy with this, I'm too.

Fix the test to be more normal

oskarwirga marked 3 inline comments as done.May 24 2023, 6:37 PM
MatzeB added a comment.EditedMay 30 2023, 11:05 AM

In this case AdjustsStack on line 352 should be initialized to false and MFI.adjustsStack() == AdjustsStack should also be removed making this assertion kind of useless.
If @MatzeB is happy with this, I'm too.

Maybe we can handle this in a similar manner. AdjustsStack==true should be the more conservative answer and we should be fine going from an initial true to false after optimizations. So we can weaken this check as well to only assert that we are not going from false to true...

MatzeB added inline comments.May 31 2023, 11:24 AM
llvm/test/CodeGen/AArch64/compute-call-frame-size-unreachable-pass.ll
2

A simple -mtriple aarch64-- may work too.

11–27

can you simplify (in the sense of less lines in the .ll file) this test more by dropping the !type annotations and the data for them, the #0 attribute function attributes, internal and fastcc, the !nosanitize metadata?

Make sure we don't go from false to true.

barannikov88 added inline comments.May 31 2023, 12:04 PM
llvm/lib/CodeGen/PrologEpilogInserter.cpp
352

This should be initialized to false.
There is no difference in practice, but it will be clearer that the flag is recalculated.

oskarwirga marked an inline comment as done.

Make the target generic aarch64

oskarwirga marked an inline comment as done.May 31 2023, 12:48 PM
oskarwirga marked an inline comment as not done.May 31 2023, 8:24 PM
oskarwirga added inline comments.
llvm/lib/CodeGen/PrologEpilogInserter.cpp
352

Interestingly setting this to false causes CodeGen/X86/asan-check-memaccess-add.ll to crash :D

oskarwirga marked an inline comment as not done.May 31 2023, 8:25 PM

Is there any reason why this would be emitting less instructions for just asan-check-memaccess-add.ll?

barannikov88 added inline comments.Jun 1 2023, 12:44 AM
llvm/lib/CodeGen/PrologEpilogInserter.cpp
352

Probably it changed from true to false, which could never happen before.
I didn't expect a change in behavior, so feel free to revert this part

oskarwirga updated this revision to Diff 527468.Jun 1 2023, 9:54 AM

Lets go back to what makes the least changes

MatzeB accepted this revision.Jul 5 2023, 1:30 PM

Let's see how this goes. LGTM

This revision is now accepted and ready to land.Jul 5 2023, 1:30 PM
This revision was automatically updated to reflect the committed changes.