Skip to content

[MachineFrameInfo] Refactoring with computeMaxcallFrameSize() (NFC) #78001

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 18, 2024

Conversation

JonPsson1
Copy link
Contributor

  • Use computeMaxCallFrameSize() in PEI::calculateCallFrameInfo() instead of duplicating the code.
  • Set AdjustsStack for a stackaligning inline-asm early in SelectionDAGISel where they are already checked for, instead of in computeMaxCallFrameSize().

This refactoring looks like an improvement to me, but I have one open question and that is regarding global isel as it would also need to set AdjustsStack..?

@llvmbot llvmbot added the llvm:SelectionDAG SelectionDAGISel as well label Jan 13, 2024
@llvmbot
Copy link
Member

llvmbot commented Jan 13, 2024

@llvm/pr-subscribers-backend-systemz
@llvm/pr-subscribers-backend-powerpc
@llvm/pr-subscribers-debuginfo
@llvm/pr-subscribers-backend-aarch64
@llvm/pr-subscribers-backend-amdgpu
@llvm/pr-subscribers-backend-x86
@llvm/pr-subscribers-llvm-globalisel

@llvm/pr-subscribers-llvm-selectiondag

Author: Jonas Paulsson (JonPsson1)

Changes
  • Use computeMaxCallFrameSize() in PEI::calculateCallFrameInfo() instead of duplicating the code.
  • Set AdjustsStack for a stackaligning inline-asm early in SelectionDAGISel where they are already checked for, instead of in computeMaxCallFrameSize().

This refactoring looks like an improvement to me, but I have one open question and that is regarding global isel as it would also need to set AdjustsStack..?


Full diff: https://github.com/llvm/llvm-project/pull/78001.diff

4 Files Affected:

  • (modified) llvm/include/llvm/CodeGen/MachineFrameInfo.h (+6-2)
  • (modified) llvm/lib/CodeGen/MachineFrameInfo.cpp (+6-8)
  • (modified) llvm/lib/CodeGen/PrologEpilogInserter.cpp (+11-28)
  • (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (+3-3)
diff --git a/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/llvm/include/llvm/CodeGen/MachineFrameInfo.h
index 7d11d63d4066f4..0fe73fec7ee67f 100644
--- a/llvm/include/llvm/CodeGen/MachineFrameInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineFrameInfo.h
@@ -638,13 +638,17 @@ class MachineFrameInfo {
   bool hasTailCall() const { return HasTailCall; }
   void setHasTailCall(bool V = true) { HasTailCall = V; }
 
-  /// Computes the maximum size of a callframe and the AdjustsStack property.
+  /// Computes the maximum size of a callframe.
   /// This only works for targets defining
   /// TargetInstrInfo::getCallFrameSetupOpcode(), getCallFrameDestroyOpcode(),
   /// and getFrameSize().
   /// This is usually computed by the prologue epilogue inserter but some
   /// targets may call this to compute it earlier.
-  void computeMaxCallFrameSize(const MachineFunction &MF);
+  /// If FrameSDOps is passed, the frame instructions in the MF will be
+  /// inserted into it.
+  void computeMaxCallFrameSize(
+      MachineFunction &MF,
+      std::vector<MachineBasicBlock::iterator> *FrameSDOps = nullptr);
 
   /// Return the maximum size of a call frame that must be
   /// allocated for an outgoing function call.  This is only available if
diff --git a/llvm/lib/CodeGen/MachineFrameInfo.cpp b/llvm/lib/CodeGen/MachineFrameInfo.cpp
index 280d3a6a41edc9..a151e61a2f60de 100644
--- a/llvm/lib/CodeGen/MachineFrameInfo.cpp
+++ b/llvm/lib/CodeGen/MachineFrameInfo.cpp
@@ -184,7 +184,8 @@ uint64_t MachineFrameInfo::estimateStackSize(const MachineFunction &MF) const {
   return alignTo(Offset, StackAlign);
 }
 
-void MachineFrameInfo::computeMaxCallFrameSize(const MachineFunction &MF) {
+void MachineFrameInfo::computeMaxCallFrameSize(
+    MachineFunction &MF, std::vector<MachineBasicBlock::iterator> *FrameSDOps) {
   const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
   unsigned FrameSetupOpcode = TII.getCallFrameSetupOpcode();
   unsigned FrameDestroyOpcode = TII.getCallFrameDestroyOpcode();
@@ -192,18 +193,15 @@ void MachineFrameInfo::computeMaxCallFrameSize(const MachineFunction &MF) {
          "Can only compute MaxCallFrameSize if Setup/Destroy opcode are known");
 
   MaxCallFrameSize = 0;
-  for (const MachineBasicBlock &MBB : MF) {
-    for (const MachineInstr &MI : MBB) {
+  for (MachineBasicBlock &MBB : MF) {
+    for (MachineInstr &MI : MBB) {
       unsigned Opcode = MI.getOpcode();
       if (Opcode == FrameSetupOpcode || Opcode == FrameDestroyOpcode) {
         unsigned Size = TII.getFrameSize(MI);
         MaxCallFrameSize = std::max(MaxCallFrameSize, Size);
         AdjustsStack = true;
-      } else if (MI.isInlineAsm()) {
-        // Some inline asm's need a stack frame, as indicated by operand 1.
-        unsigned ExtraInfo = MI.getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
-        if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
-          AdjustsStack = true;
+        if (FrameSDOps != nullptr)
+          FrameSDOps->push_back(&MI);
       }
     }
   }
diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
index 8af17e63e25c75..b0f2753c86230f 100644
--- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
@@ -228,9 +228,8 @@ bool PEI::runOnMachineFunction(MachineFunction &MF) {
   FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(MF);
   ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE();
 
-  // Calculate the MaxCallFrameSize and AdjustsStack variables for the
-  // function's frame information. Also eliminates call frame pseudo
-  // instructions.
+  // Calculate the MaxCallFrameSize value for the function's frame
+  // information. Also eliminates call frame pseudo instructions.
   calculateCallFrameInfo(MF);
 
   // Determine placement of CSR spill/restore code and prolog/epilog code:
@@ -350,17 +349,13 @@ bool PEI::runOnMachineFunction(MachineFunction &MF) {
   return true;
 }
 
-/// Calculate the MaxCallFrameSize and AdjustsStack
-/// variables for the function's frame information and eliminate call frame
-/// pseudo instructions.
+/// Calculate the MaxCallFrameSize variables for the function's frame
+/// information and eliminate call frame pseudo instructions.
 void PEI::calculateCallFrameInfo(MachineFunction &MF) {
   const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
   const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
   MachineFrameInfo &MFI = MF.getFrameInfo();
 
-  unsigned MaxCallFrameSize = 0;
-  bool AdjustsStack = MFI.adjustsStack();
-
   // Get the function call frame set-up and tear-down instruction opcode
   unsigned FrameSetupOpcode = TII.getCallFrameSetupOpcode();
   unsigned FrameDestroyOpcode = TII.getCallFrameDestroyOpcode();
@@ -370,26 +365,14 @@ void PEI::calculateCallFrameInfo(MachineFunction &MF) {
   if (FrameSetupOpcode == ~0u && FrameDestroyOpcode == ~0u)
     return;
 
+  // (Re-)Compute the MaxCallFrameSize with some sanity checks.
+  bool WasComputed = MFI.isMaxCallFrameSizeComputed();
+  unsigned MaxCFSIn = MFI.getMaxCallFrameSize();
+  bool AdjStackIn = MFI.adjustsStack();
   std::vector<MachineBasicBlock::iterator> FrameSDOps;
-  for (MachineBasicBlock &BB : MF)
-    for (MachineBasicBlock::iterator I = BB.begin(); I != BB.end(); ++I)
-      if (TII.isFrameInstr(*I)) {
-        unsigned Size = TII.getFrameSize(*I);
-        if (Size > MaxCallFrameSize) MaxCallFrameSize = Size;
-        AdjustsStack = true;
-        FrameSDOps.push_back(I);
-      } else if (I->isInlineAsm()) {
-        // Some inline asm's need a stack frame, as indicated by operand 1.
-        unsigned ExtraInfo = I->getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
-        if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
-          AdjustsStack = true;
-      }
-
-  assert(!MFI.isMaxCallFrameSizeComputed() ||
-         (MFI.getMaxCallFrameSize() >= MaxCallFrameSize &&
-          !(AdjustsStack && !MFI.adjustsStack())));
-  MFI.setAdjustsStack(AdjustsStack);
-  MFI.setMaxCallFrameSize(MaxCallFrameSize);
+  MFI.computeMaxCallFrameSize(MF, &FrameSDOps);
+  assert(!WasComputed || (MaxCFSIn >= MFI.getMaxCallFrameSize() &&
+                          !(!AdjStackIn && MFI.adjustsStack())));
 
   if (TFI->canSimplifyCallFramePseudos(MF)) {
     // If call frames are not being included as part of the stack frame, and
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 9acfc76d7d5eac..d0609434b8b7ee 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -670,12 +670,12 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {
 
     for (const auto &MI : MBB) {
       const MCInstrDesc &MCID = TII->get(MI.getOpcode());
-      if ((MCID.isCall() && !MCID.isReturn()) ||
-          MI.isStackAligningInlineAsm()) {
+      if ((MCID.isCall() && !MCID.isReturn()) || MI.isStackAligningInlineAsm())
         MFI.setHasCalls(true);
-      }
       if (MI.isInlineAsm()) {
         MF->setHasInlineAsm(true);
+        if (MI.isStackAligningInlineAsm())
+          MFI.setAdjustsStack(true);
       }
     }
   }

@rovka
Copy link
Collaborator

rovka commented Jan 16, 2024

This refactoring looks like an improvement to me, but I have one open question and that is regarding global isel as it would also need to set AdjustsStack..?

You could probably set it in lowerInlineAsm, where the ExtraFlags are computed.

How is this change going to affect code that doesn't pass through isel? For instance if someone writes a MIR test and doesn't specify adjustsStack in the frameInfo?

@arsenm
Copy link
Contributor

arsenm commented Jan 16, 2024

This refactoring looks like an improvement to me, but I have one open question and that is regarding global isel as it would also need to set AdjustsStack..?

You could probably set it in lowerInlineAsm, where the ExtraFlags are computed.

How is this change going to affect code that doesn't pass through isel? For instance if someone writes a MIR test and doesn't specify adjustsStack in the frameInfo?

We should teach the verifier to make sure the adjustsStack is consistent with the SP defs in the instruction stream

@JonPsson1
Copy link
Contributor Author

You could probably set it in lowerInlineAsm, where the ExtraFlags are computed.

Thanks - patch updated.

How is this change going to affect code that doesn't pass through isel? For instance if someone writes a MIR test and doesn't specify adjustsStack in the frameInfo?

Yeah - for MIR tests using inline-asms with alignstack, they would either have to be created with -stop-before= (to get the frameInfo correct), or adjustsStack would have to be specified manually.

@JonPsson1
Copy link
Contributor Author

We should teach the verifier to make sure the adjustsStack is consistent with the SP defs in the instruction stream

Should I add a TODO in MachineVerifier, or you think this is needed as part of this?

Given this comment, I guess the verifier should check this after PEI. By then the frame instructions will have been removed, so it can only check for any def of SP. The rule would be "if the SP is defined anywhere in the function (or it has an inline-asm with alignstack), adjustsStack should be 'true'?


  /// Return true if this function adjusts the stack -- e.g.,
  /// when calling another function. This is only valid during and after
  /// prolog/epilog code insertion.
  bool adjustsStack() const { return AdjustsStack; }
  void setAdjustsStack(bool V) { AdjustsStack = V; }

@arsenm
Copy link
Contributor

arsenm commented Jan 17, 2024

Should I add a TODO in MachineVerifier, or you think this is needed as part of this?

Should be a separate patch

The rule would be "if the SP is defined anywhere in the function (or it has an inline-asm with alignstack), adjustsStack should be 'true'?

Yes, something like that

for (const MachineBasicBlock &MBB : MF) {
for (const MachineInstr &MI : MBB) {
for (MachineBasicBlock &MBB : MF) {
for (MachineInstr &MI : MBB) {
unsigned Opcode = MI.getOpcode();
if (Opcode == FrameSetupOpcode || Opcode == FrameDestroyOpcode) {
unsigned Size = TII.getFrameSize(MI);
MaxCallFrameSize = std::max(MaxCallFrameSize, Size);
AdjustsStack = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems weird that we're still computing AdjustsStack for calls, but not asm here. I'd expect both or neither

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be best in that case to do the calls also during isel, given that not all targets actually need the frame pseudos. On SystemZ we would like to eliminate them early (see #77812) as they serve no use around calls (call frame allocated once for all calls in prolog), and we just realized that we are even suppose keep the StackFrameSize accuarate when splitting blocks in FinalizeISel, which we currently do not do.

I am a little uncertain on exactly what AdjustsStack means. Does it mean that the function redefines SP, or could it also mean that it makes any call (which do not necessarily change SP on all targets, I think)?

It seems that given the current MachineFrameInfo scan for frame instructions, AdjustsStack could be set always in SelectionDAG::getCALLSEQ_START() (and similar for GlobalISel)? (and the current definition of AdjustsStack is then "any call", so maybe the comment could be clarified).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The call frame pseudos are also used to implement dynamic allocas. I kind of assumed it meant that kind of case, so I'm a little surprised it's set for calls (given we already have a separate hasCalls property)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been a confusion for me also - I actually tried setting the AdjustsStack for any call, but that gave test failures on some target.

Yes, as callseq pseudos seem to be used for other things and not just calls, any refactoring needs to preserve this mapping from them to the AdjustsStack flag, I think.

@@ -602,6 +603,9 @@ bool InlineAsmLowering::lowerInlineAsm(
}
}

if (ExtraInfo.get() & InlineAsm::Extra_IsAlignStack)
MF.getFrameInfo().setAdjustsStack(true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also related #46222? Should probably split this to a separate change

@JonPsson1
Copy link
Contributor Author

@arsenm I guess you are right that it makes most sense to compute the AdjustsStack flag for both calls and inlineasms in the same place. I think it should probably be done during isel, since it is not affected by anything else computed later on. However, I started with that thinking that all that would be needed would be to do it once in getCALLSEQ_START(). That turned out to be far from true: There is GlobalISel, FastISel, X86 emits it during EmitCustomInserter, ... Global ISel even emits it by first creating it and then only after creating other instructions adding the final immediate values to it.

I am not sure if it would actually be better to do it in isel, as there are so many different places this would have to be remembered. It is simplifying during isel to not have to set AdjustsStack, but of course it could be done.

I kept that part out of the patch for now, so now this only avoids the code duplication of computeMaxCallFrameSize().

@JonPsson1
Copy link
Contributor Author

Actually, I got the idea of how to handle this for all instruction selectors and targets by simply doing this in finalize isel. This is very simple and seems ok per the comment in top of FinalizeISel.cpp. Patch updated.

@JonPsson1
Copy link
Contributor Author

It needs to be done with an extra loop as targets may insert new call frame setup instructions during pseudo expansion. If this extra loop is not acceptable, maybe then give up here on setting AdjustsStack during/after isel.

@@ -69,6 +72,15 @@ bool FinalizeISel::runOnMachineFunction(MachineFunction &MF) {
}
}

for (auto &MBB : MF)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really think it's worth adding an extra loop for it. It doesn't seem like it would be too bad to require custom inserters to set this. It's more OK if we could catch this with the verifier

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK - patch updated. I now actually found out there were cases of emitting calls even after finalize isel (PPCTLSDynamicCall.cpp), which made it obvious that this should be verified as late as possible. Seems there is no real need to employ the verifier - a single assert in PEI does the job, I think.

@JonPsson1
Copy link
Contributor Author

PING

@JonPsson1
Copy link
Contributor Author

ping!

I was hoping to commit this before continuing with "[SystemZ] Eliminate call sequence instructions early", so it would be nice to make some progress here...

@JonPsson1
Copy link
Contributor Author

ping!

Comment on lines +375 to +376
assert((FrameSDOps.empty() || MF.getFrameInfo().adjustsStack()) &&
"AdjustsStack not set in presence of a frame pseudo instruction.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably should go in the verifier. It's really unfortunate when MIR asserts and you have to debug just to realize it was supposed to be invalid MIR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, will do a follow-up patch for that.

Only do the code-duplication fix.
Set AdjustsStack in finalize isel.
Add assert in PEI and fix backends/mir-tests.
@JonPsson1
Copy link
Contributor Author

Thanks for review. Some more .mir tests were fixed after review approval by adding 'adjustsStack: true' as needed:


 llvm/test/CodeGen/AArch64/stack-probing-no-scratch-reg.mir | 1 +
 llvm/test/CodeGen/AArch64/stack-probing-shrink-wrap.mir    | 1 +
 llvm/test/DebugInfo/MIR/X86/debug-loc-0.mir                | 2 +-
 llvm/test/DebugInfo/MIR/X86/prolog-epilog-indirection.mir  | 1 +
 llvm/test/DebugInfo/X86/live-debug-vars-dse.mir            | 2 +-
 llvm/test/DebugInfo/X86/prolog-params.mir                  | 2 ++

@JonPsson1 JonPsson1 merged commit 09bc6ab into llvm:main Mar 18, 2024
@nathanchance
Copy link
Member

I bisect a crash that I see while building the Linux kernel to this change. A trivial reproducer from cvise that crashes at this change but not the parent.

void input_report_abs(int);
void touchscreen_report_pos(_Bool multitouch) {
  input_report_abs(multitouch ? 5 : 0);
  input_report_abs(multitouch ? 6 : 1);
}
$ clang --target=s390x-linux-gnu -O2 -c -o /dev/null touchscreen.i
clang: /home/nathan/tmp/cvise.IoySpFokBb/src/llvm/lib/CodeGen/PrologEpilogInserter.cpp:376: void (anonymous namespace)::PEI::calculateCallFrameInfo(MachineFunction &): Assertion `(FrameSDOps.empty() || MF.getFrameInfo().adjustsStack()) && "AdjustsStack not set in presence of a frame pseudo instruction."' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: clang --target=s390x-linux-gnu -O2 -c -o /dev/null touchscreen.i
1.	<eof> parser at end of file
2.	Code generation
3.	Running pass 'Function Pass Manager' on module 'touchscreen.i'.
4.	Running pass 'Prologue/Epilogue Insertion & Frame Finalization' on function '@touchscreen_report_pos'
 #0 0x00000000026f1704 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x26f1704)
 #1 0x00000000026ef64c llvm::sys::RunSignalHandlers() (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x26ef64c)
 #2 0x0000000002674bec CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x0000ffffa16677f0 (linux-vdso.so.1+0x7f0)
 #4 0x0000ffffa1027c40 __pthread_kill_implementation (/lib64/libc.so.6+0x97c40)
 #5 0x0000ffffa0fd5940 gsignal (/lib64/libc.so.6+0x45940)
 #6 0x0000ffffa0fc0288 abort (/lib64/libc.so.6+0x30288)
 #7 0x0000ffffa0fce340 __assert_fail_base (/lib64/libc.so.6+0x3e340)
 #8 0x0000ffffa0fce3b4 (/lib64/libc.so.6+0x3e3b4)
 #9 0x0000000001fad41c (anonymous namespace)::PEI::runOnMachineFunction(llvm::MachineFunction&) PrologEpilogInserter.cpp:0:0
#10 0x0000000001cda07c llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x1cda07c)
#11 0x0000000002260c18 llvm::FPPassManager::runOnFunction(llvm::Function&) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x2260c18)
#12 0x000000000226863c llvm::FPPassManager::runOnModule(llvm::Module&) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x226863c)
#13 0x0000000002261510 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x2261510)
#14 0x0000000002e2fdf0 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x2e2fdf0)
#15 0x0000000002e4fc1c clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x2e4fc1c)
#16 0x0000000003f31994 clang::ParseAST(clang::Sema&, bool, bool) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x3f31994)
#17 0x00000000031fa970 clang::FrontendAction::Execute() (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x31fa970)
#18 0x0000000003182590 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x3182590)
#19 0x00000000032c52f8 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x32c52f8)
#20 0x0000000001905cdc cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x1905cdc)
#21 0x0000000001902cd0 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#22 0x0000000003031140 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::$_0>(long) Job.cpp:0:0
#23 0x0000000002674954 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x2674954)
#24 0x00000000030308f0 clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x30308f0)
#25 0x0000000002ff8474 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x2ff8474)
#26 0x0000000002ff86c0 clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x2ff86c0)
#27 0x00000000030117b0 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x30117b0)
#28 0x00000000019020a4 clang_main(int, char**, llvm::ToolContext const&) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x19020a4)
#29 0x000000000191007c main (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x191007c)
#30 0x0000ffffa0fc0adc __libc_start_call_main (/lib64/libc.so.6+0x30adc)
#31 0x0000ffffa0fc0bbc __libc_start_main@GLIBC_2.17 (/lib64/libc.so.6+0x30bbc)
#32 0x00000000019008f0 _start (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x19008f0)
clang: error: clang frontend command failed with exit code 134 (use -v to see invocation)
ClangBuiltLinux clang version 19.0.0git (https://github.com/llvm/llvm-project.git 09bc6abba6e226ad5e9d18d4365690d6f04de21a)
Target: s390x-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin
clang: note: diagnostic msg: Error generating preprocessed source(s) - no preprocessable inputs.
# bad: [6872a646523c1e85a98dfa20b2f4dd7774e10ba4] [ValueTracking] Handle vector range metadata in isKnownNonZero()
# good: [192be3c9c13363847d176f2c4bba2bd4be5e822f] fix: constexpr bit_cast with empty base classes (#82383)
git bisect start '6872a646523c1e85a98dfa20b2f4dd7774e10ba4' '192be3c9c13363847d176f2c4bba2bd4be5e822f'
# bad: [20f5bcfb1a3b58c430a5df6dd837b30c22a2b788] [OpenMP] Add OpenMP extension API to dump mapping tables (#85381)
git bisect bad 20f5bcfb1a3b58c430a5df6dd837b30c22a2b788
# good: [4c5bc7667728d5383c41eb8a20dd5e49257904d2] [libcxx][test] Create feature host-can-create-symlinks (#82204)
git bisect good 4c5bc7667728d5383c41eb8a20dd5e49257904d2
# bad: [487f356b20860a3eeb29b836483c639735f9393c] [RemoveDIs][AsmWriter] Add empty-metadata operands to the SlotTracker (#85636)
git bisect bad 487f356b20860a3eeb29b836483c639735f9393c
# good: [1d9fb2ee612f0ccf588d40dc4b5445cffd36e8af] [clang][Interp] Disable CFStringMakeConstantString test on AIX
git bisect good 1d9fb2ee612f0ccf588d40dc4b5445cffd36e8af
# good: [cb84f130b724f64f88f780c1731a4c6e9cba99cd] [AMDGPU] Remove unneeded addr mode predicates on FLAT Real instructions (#85641)
git bisect good cb84f130b724f64f88f780c1731a4c6e9cba99cd
# good: [e2e3624fae669f85de1445bf7037ff29feb30905] [clang][test] Try to fix constexpr-void-cast test
git bisect good e2e3624fae669f85de1445bf7037ff29feb30905
# bad: [09bc6abba6e226ad5e9d18d4365690d6f04de21a] [MachineFrameInfo] Refactoring around computeMaxcallFrameSize() (NFC) (#78001)
git bisect bad 09bc6abba6e226ad5e9d18d4365690d6f04de21a
# good: [9253950ec1690e786ba1cdaaf3234fb30b633eab] [libclc] Convert tabs to spaces in CMake (#85634)
git bisect good 9253950ec1690e786ba1cdaaf3234fb30b633eab
# first bad commit: [09bc6abba6e226ad5e9d18d4365690d6f04de21a] [MachineFrameInfo] Refactoring around computeMaxcallFrameSize() (NFC) (#78001)

@JonPsson1
Copy link
Contributor Author

JonPsson1 commented Mar 20, 2024

@nathanchance

I bisect a crash that I see while building the Linux kernel to this change. A trivial reproducer from cvise that crashes at this change but not the parent.

void input_report_abs(int);
void touchscreen_report_pos(_Bool multitouch) {
  input_report_abs(multitouch ? 5 : 0);
  input_report_abs(multitouch ? 6 : 1);
}
$ clang --target=s390x-linux-gnu -O2 -c -o /dev/null touchscreen.i
clang: /home/nathan/tmp/cvise.IoySpFokBb/src/llvm/lib/CodeGen/PrologEpilogInserter.cpp:376: void (anonymous namespace)::PEI::calculateCallFrameInfo(MachineFunction &): Assertion `(FrameSDOps.empty() || MF.getFrameInfo().adjustsStack()) && "AdjustsStack not set in presence of a frame pseudo instruction."' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: clang --target=s390x-linux-gnu -O2 -c -o /dev/null touchscreen.i
1.	<eof> parser at end of file
2.	Code generation
3.	Running pass 'Function Pass Manager' on module 'touchscreen.i'.
4.	Running pass 'Prologue/Epilogue Insertion & Frame Finalization' on function '@touchscreen_report_pos'
 #0 0x00000000026f1704 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x26f1704)
 #1 0x00000000026ef64c llvm::sys::RunSignalHandlers() (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x26ef64c)
 #2 0x0000000002674bec CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x0000ffffa16677f0 (linux-vdso.so.1+0x7f0)
 #4 0x0000ffffa1027c40 __pthread_kill_implementation (/lib64/libc.so.6+0x97c40)
 #5 0x0000ffffa0fd5940 gsignal (/lib64/libc.so.6+0x45940)
 #6 0x0000ffffa0fc0288 abort (/lib64/libc.so.6+0x30288)
 #7 0x0000ffffa0fce340 __assert_fail_base (/lib64/libc.so.6+0x3e340)
 #8 0x0000ffffa0fce3b4 (/lib64/libc.so.6+0x3e3b4)
 #9 0x0000000001fad41c (anonymous namespace)::PEI::runOnMachineFunction(llvm::MachineFunction&) PrologEpilogInserter.cpp:0:0
#10 0x0000000001cda07c llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x1cda07c)
#11 0x0000000002260c18 llvm::FPPassManager::runOnFunction(llvm::Function&) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x2260c18)
#12 0x000000000226863c llvm::FPPassManager::runOnModule(llvm::Module&) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x226863c)
#13 0x0000000002261510 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x2261510)
#14 0x0000000002e2fdf0 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x2e2fdf0)
#15 0x0000000002e4fc1c clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x2e4fc1c)
#16 0x0000000003f31994 clang::ParseAST(clang::Sema&, bool, bool) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x3f31994)
#17 0x00000000031fa970 clang::FrontendAction::Execute() (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x31fa970)
#18 0x0000000003182590 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x3182590)
#19 0x00000000032c52f8 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x32c52f8)
#20 0x0000000001905cdc cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x1905cdc)
#21 0x0000000001902cd0 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#22 0x0000000003031140 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::$_0>(long) Job.cpp:0:0
#23 0x0000000002674954 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x2674954)
#24 0x00000000030308f0 clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x30308f0)
#25 0x0000000002ff8474 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x2ff8474)
#26 0x0000000002ff86c0 clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x2ff86c0)
#27 0x00000000030117b0 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x30117b0)
#28 0x00000000019020a4 clang_main(int, char**, llvm::ToolContext const&) (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x19020a4)
#29 0x000000000191007c main (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x191007c)
#30 0x0000ffffa0fc0adc __libc_start_call_main (/lib64/libc.so.6+0x30adc)
#31 0x0000ffffa0fc0bbc __libc_start_main@GLIBC_2.17 (/lib64/libc.so.6+0x30bbc)
#32 0x00000000019008f0 _start (/home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin/clang-19+0x19008f0)
clang: error: clang frontend command failed with exit code 134 (use -v to see invocation)
ClangBuiltLinux clang version 19.0.0git (https://github.com/llvm/llvm-project.git 09bc6abba6e226ad5e9d18d4365690d6f04de21a)
Target: s390x-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/nathan/tmp/cvise.IoySpFokBb/install/llvm-bad/bin
clang: note: diagnostic msg: Error generating preprocessed source(s) - no preprocessable inputs.
# bad: [6872a646523c1e85a98dfa20b2f4dd7774e10ba4] [ValueTracking] Handle vector range metadata in isKnownNonZero()
# good: [192be3c9c13363847d176f2c4bba2bd4be5e822f] fix: constexpr bit_cast with empty base classes (#82383)
git bisect start '6872a646523c1e85a98dfa20b2f4dd7774e10ba4' '192be3c9c13363847d176f2c4bba2bd4be5e822f'
# bad: [20f5bcfb1a3b58c430a5df6dd837b30c22a2b788] [OpenMP] Add OpenMP extension API to dump mapping tables (#85381)
git bisect bad 20f5bcfb1a3b58c430a5df6dd837b30c22a2b788
# good: [4c5bc7667728d5383c41eb8a20dd5e49257904d2] [libcxx][test] Create feature host-can-create-symlinks (#82204)
git bisect good 4c5bc7667728d5383c41eb8a20dd5e49257904d2
# bad: [487f356b20860a3eeb29b836483c639735f9393c] [RemoveDIs][AsmWriter] Add empty-metadata operands to the SlotTracker (#85636)
git bisect bad 487f356b20860a3eeb29b836483c639735f9393c
# good: [1d9fb2ee612f0ccf588d40dc4b5445cffd36e8af] [clang][Interp] Disable CFStringMakeConstantString test on AIX
git bisect good 1d9fb2ee612f0ccf588d40dc4b5445cffd36e8af
# good: [cb84f130b724f64f88f780c1731a4c6e9cba99cd] [AMDGPU] Remove unneeded addr mode predicates on FLAT Real instructions (#85641)
git bisect good cb84f130b724f64f88f780c1731a4c6e9cba99cd
# good: [e2e3624fae669f85de1445bf7037ff29feb30905] [clang][test] Try to fix constexpr-void-cast test
git bisect good e2e3624fae669f85de1445bf7037ff29feb30905
# bad: [09bc6abba6e226ad5e9d18d4365690d6f04de21a] [MachineFrameInfo] Refactoring around computeMaxcallFrameSize() (NFC) (#78001)
git bisect bad 09bc6abba6e226ad5e9d18d4365690d6f04de21a
# good: [9253950ec1690e786ba1cdaaf3234fb30b633eab] [libclc] Convert tabs to spaces in CMake (#85634)
git bisect good 9253950ec1690e786ba1cdaaf3234fb30b633eab
# first bad commit: [09bc6abba6e226ad5e9d18d4365690d6f04de21a] [MachineFrameInfo] Refactoring around computeMaxcallFrameSize() (NFC) (#78001)

Sorry for the trouble - thanks for the bugreport! Fix proposed at #85945

JonPsson1 added a commit that referenced this pull request Mar 21, 2024
Check for all frame instructions in finalize isel, not just for the
frame setup opcode. This was proven necessary, see #78001 
for discussion.
chencha3 pushed a commit to chencha3/llvm-project that referenced this pull request Mar 23, 2024
…llvm#78001)

- Use computeMaxCallFrameSize() in PEI::calculateCallFrameInfo() instead of duplicating the code.

- Set AdjustsStack in FinalizeISel instead of in computeMaxCallFrameSize().
chencha3 pushed a commit to chencha3/llvm-project that referenced this pull request Mar 23, 2024
Check for all frame instructions in finalize isel, not just for the
frame setup opcode. This was proven necessary, see llvm#78001 
for discussion.
@JonPsson1 JonPsson1 deleted the MaxCFSRefac branch March 26, 2024 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants