Skip to content

[22.x][LoongArch] Revert musttail/byval/sret Changes#191525

Merged
c-rhodes merged 1 commit intollvm:release/22.xfrom
lenary:pr/22.x/revert-loongarch-musttail
Apr 17, 2026
Merged

[22.x][LoongArch] Revert musttail/byval/sret Changes#191525
c-rhodes merged 1 commit intollvm:release/22.xfrom
lenary:pr/22.x/revert-loongarch-musttail

Conversation

@lenary
Copy link
Copy Markdown
Member

@lenary lenary commented Apr 10, 2026

This reverts:

There's a lifetime issue in the implementation, where an SDValue is saved and may be used outside the current basic block.

The corresponding revert on main is
501417b (#191508) - in this case only the LoongArch changes made it to the 22.x branches, so this commit only affects that architecture.

@llvmbot
Copy link
Copy Markdown
Member

llvmbot commented Apr 10, 2026

@llvm/pr-subscribers-backend-loongarch

Author: Sam Elliott (lenary)

Changes

This reverts:

There's a lifetime issue in the implementation, where an SDValue is saved and may be used outside the current basic block.

The corresponding revert on main is
501417b (#191508) - in this case only the LoongArch changes made it to the 22.x branches, so this commit only affects that architecture.


Patch is 35.10 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/191525.diff

5 Files Affected:

  • (modified) llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp (+25-80)
  • (modified) llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h (-14)
  • (removed) llvm/test/CodeGen/LoongArch/issue187832.ll (-48)
  • (removed) llvm/test/CodeGen/LoongArch/musttail.ll (-567)
  • (modified) llvm/test/CodeGen/LoongArch/tail-calls.ll (+9-4)
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 7cb61bafb5ad3..2cfe3b2bc1a99 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -8157,7 +8157,6 @@ SDValue LoongArchTargetLowering::LowerFormalArguments(
     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
 
   MachineFunction &MF = DAG.getMachineFunction();
-  auto *LoongArchFI = MF.getInfo<LoongArchMachineFunctionInfo>();
 
   switch (CallConv) {
   default:
@@ -8221,8 +8220,6 @@ SDValue LoongArchTargetLowering::LowerFormalArguments(
       continue;
     }
     InVals.push_back(ArgValue);
-    if (Ins[InsIdx].Flags.isByVal())
-      LoongArchFI->addIncomingByValArgs(ArgValue);
   }
 
   if (IsVarArg) {
@@ -8231,6 +8228,7 @@ SDValue LoongArchTargetLowering::LowerFormalArguments(
     const TargetRegisterClass *RC = &LoongArch::GPRRegClass;
     MachineFrameInfo &MFI = MF.getFrameInfo();
     MachineRegisterInfo &RegInfo = MF.getRegInfo();
+    auto *LoongArchFI = MF.getInfo<LoongArchMachineFunctionInfo>();
 
     // Offset of the first variable argument from stack pointer, and size of
     // the vararg save area. For now, the varargs save area is either zero or
@@ -8280,8 +8278,6 @@ SDValue LoongArchTargetLowering::LowerFormalArguments(
     LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
   }
 
-  LoongArchFI->setArgumentStackSize(CCInfo.getStackSize());
-
   // All stores are grouped in one node to allow the matching between
   // the size of Ins and InVals. This only happens for vararg functions.
   if (!OutChains.empty()) {
@@ -8338,11 +8334,9 @@ bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
   auto &Outs = CLI.Outs;
   auto &Caller = MF.getFunction();
   auto CallerCC = Caller.getCallingConv();
-  auto *LoongArchFI = MF.getInfo<LoongArchMachineFunctionInfo>();
 
-  // If the stack arguments for this call do not fit into our own save area then
-  // the call cannot be made tail.
-  if (CCInfo.getStackSize() > LoongArchFI->getArgumentStackSize())
+  // Do not tail call opt if the stack is used to pass parameters.
+  if (CCInfo.getStackSize() != 0)
     return false;
 
   // Do not tail call opt if any parameters need to be passed indirectly.
@@ -8354,19 +8348,13 @@ bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
   // semantics.
   auto IsCallerStructRet = Caller.hasStructRetAttr();
   auto IsCalleeStructRet = Outs.empty() ? false : Outs[0].Flags.isSRet();
-  if (IsCallerStructRet != IsCalleeStructRet)
+  if (IsCallerStructRet || IsCalleeStructRet)
     return false;
 
-  // Do not tail call opt if caller's and callee's byval arguments do not match.
-  for (unsigned i = 0, j = 0; i < Outs.size(); ++i) {
-    if (!Outs[i].Flags.isByVal())
-      continue;
-    if (j >= LoongArchFI->getIncomingByValArgsSize())
-      return false;
-    if (LoongArchFI->getIncomingByValArgs(j).getValueType() != Outs[i].ArgVT)
+  // Do not tail call opt if either the callee or caller has a byval argument.
+  for (auto &Arg : Outs)
+    if (Arg.Flags.isByVal())
       return false;
-    ++j;
-  }
 
   // The callee has to preserve all registers the caller needs to preserve.
   const LoongArchRegisterInfo *TRI = Subtarget.getRegisterInfo();
@@ -8376,14 +8364,6 @@ bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
     if (!TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
       return false;
   }
-
-  // If the callee takes no arguments then go on to check the results of the
-  // call.
-  const MachineRegisterInfo &MRI = MF.getRegInfo();
-  const SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
-  if (!parametersInCSRMatch(MRI, CallerPreserved, ArgLocs, OutVals))
-    return false;
-
   return true;
 }
 
@@ -8411,7 +8391,6 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
   bool &IsTailCall = CLI.IsTailCall;
 
   MachineFunction &MF = DAG.getMachineFunction();
-  auto *LoongArchFI = MF.getInfo<LoongArchMachineFunctionInfo>();
 
   // Analyze the operands of the call, assigning locations to each operand.
   SmallVector<CCValAssign> ArgLocs;
@@ -8437,7 +8416,7 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
 
   // Create local copies for byval args.
   SmallVector<SDValue> ByValArgs;
-  for (unsigned i = 0, j = 0, e = Outs.size(); i != e; ++i) {
+  for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
     ISD::ArgFlagsTy Flags = Outs[i].Flags;
     if (!Flags.isByVal())
       continue;
@@ -8445,39 +8424,22 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
     SDValue Arg = OutVals[i];
     unsigned Size = Flags.getByValSize();
     Align Alignment = Flags.getNonZeroByValAlign();
+
+    int FI =
+        MF.getFrameInfo().CreateStackObject(Size, Alignment, /*isSS=*/false);
+    SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
     SDValue SizeNode = DAG.getConstant(Size, DL, GRLenVT);
-    SDValue Dst;
 
-    if (IsTailCall) {
-      SDValue CallerArg = LoongArchFI->getIncomingByValArgs(j++);
-      if (isa<GlobalAddressSDNode>(Arg) || isa<ExternalSymbolSDNode>(Arg) ||
-          isa<FrameIndexSDNode>(Arg))
-        Dst = CallerArg;
-    } else {
-      int FI =
-          MF.getFrameInfo().CreateStackObject(Size, Alignment, /*isSS=*/false);
-      Dst = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
-    }
-    if (Dst) {
-      Chain =
-          DAG.getMemcpy(Chain, DL, Dst, Arg, SizeNode, Alignment,
-                        /*IsVolatile=*/false,
-                        /*AlwaysInline=*/false, /*CI=*/nullptr, std::nullopt,
-                        MachinePointerInfo(), MachinePointerInfo());
-      ByValArgs.push_back(Dst);
-    }
+    Chain = DAG.getMemcpy(Chain, DL, FIPtr, Arg, SizeNode, Alignment,
+                          /*IsVolatile=*/false,
+                          /*AlwaysInline=*/false, /*CI=*/nullptr, std::nullopt,
+                          MachinePointerInfo(), MachinePointerInfo());
+    ByValArgs.push_back(FIPtr);
   }
 
   if (!IsTailCall)
     Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL);
 
-  // During a tail call, stores to the argument area must happen after all of
-  // the function's incoming arguments have been loaded because they may alias.
-  // This is done by folding in a TokenFactor from LowerFormalArguments, but
-  // there's no point in doing so repeatedly so this tracks whether that's
-  // happened yet.
-  bool AfterFormalArgLoads = false;
-
   // Copy argument values to their designated locations.
   SmallVector<std::pair<Register, SDValue>> RegsToPass;
   SmallVector<SDValue> MemOpChains;
@@ -8572,44 +8534,27 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
     }
 
     // Use local copy if it is a byval arg.
-    if (Flags.isByVal()) {
-      if (!IsTailCall || (isa<GlobalAddressSDNode>(ArgValue) ||
-                          isa<ExternalSymbolSDNode>(ArgValue) ||
-                          isa<FrameIndexSDNode>(ArgValue)))
-        ArgValue = ByValArgs[j++];
-    }
+    if (Flags.isByVal())
+      ArgValue = ByValArgs[j++];
 
     if (VA.isRegLoc()) {
       // Queue up the argument copies and emit them at the end.
       RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue));
     } else {
       assert(VA.isMemLoc() && "Argument not register or memory");
-      SDValue DstAddr;
-      MachinePointerInfo DstInfo;
-      int32_t Offset = VA.getLocMemOffset();
+      assert(!IsTailCall && "Tail call not allowed if stack is used "
+                            "for passing parameters");
 
       // Work out the address of the stack slot.
       if (!StackPtr.getNode())
         StackPtr = DAG.getCopyFromReg(Chain, DL, LoongArch::R3, PtrVT);
-
-      if (IsTailCall) {
-        unsigned OpSize = divideCeil(VA.getValVT().getSizeInBits(), 8);
-        int FI = MF.getFrameInfo().CreateFixedObject(OpSize, Offset, true);
-        DstAddr = DAG.getFrameIndex(FI, PtrVT);
-        DstInfo = MachinePointerInfo::getFixedStack(MF, FI);
-        if (!AfterFormalArgLoads) {
-          Chain = DAG.getStackArgumentTokenFactor(Chain);
-          AfterFormalArgLoads = true;
-        }
-      } else {
-        SDValue PtrOff = DAG.getIntPtrConstant(Offset, DL);
-        DstAddr = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, PtrOff);
-        DstInfo = MachinePointerInfo::getStack(MF, Offset);
-      }
+      SDValue Address =
+          DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr,
+                      DAG.getIntPtrConstant(VA.getLocMemOffset(), DL));
 
       // Emit the store.
       MemOpChains.push_back(
-          DAG.getStore(Chain, DL, ArgValue, DstAddr, DstInfo));
+          DAG.getStore(Chain, DL, ArgValue, Address, MachinePointerInfo()));
     }
   }
 
diff --git a/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h b/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h
index 4159b97bcf598..904985c189dba 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h
+++ b/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h
@@ -32,17 +32,10 @@ class LoongArchMachineFunctionInfo : public MachineFunctionInfo {
   /// Size of stack frame to save callee saved registers
   unsigned CalleeSavedStackSize = 0;
 
-  /// Amount of bytes on stack consumed by the arguments being passed on
-  /// the stack
-  unsigned ArgumentStackSize = 0;
-
   /// FrameIndex of the spill slot when there is no scavenged register in
   /// insertIndirectBranch.
   int BranchRelaxationSpillFrameIndex = -1;
 
-  /// Incoming ByVal arguments
-  SmallVector<SDValue, 8> IncomingByValArgs;
-
   /// Registers that have been sign extended from i32.
   SmallVector<Register, 8> SExt32Registers;
 
@@ -70,9 +63,6 @@ class LoongArchMachineFunctionInfo : public MachineFunctionInfo {
   unsigned getCalleeSavedStackSize() const { return CalleeSavedStackSize; }
   void setCalleeSavedStackSize(unsigned Size) { CalleeSavedStackSize = Size; }
 
-  unsigned getArgumentStackSize() const { return ArgumentStackSize; }
-  void setArgumentStackSize(unsigned size) { ArgumentStackSize = size; }
-
   int getBranchRelaxationSpillFrameIndex() {
     return BranchRelaxationSpillFrameIndex;
   }
@@ -80,10 +70,6 @@ class LoongArchMachineFunctionInfo : public MachineFunctionInfo {
     BranchRelaxationSpillFrameIndex = Index;
   }
 
-  void addIncomingByValArgs(SDValue Val) { IncomingByValArgs.push_back(Val); }
-  SDValue getIncomingByValArgs(int Idx) { return IncomingByValArgs[Idx]; }
-  unsigned getIncomingByValArgsSize() const { return IncomingByValArgs.size(); }
-
   void addSExt32Register(Register Reg) { SExt32Registers.push_back(Reg); }
 
   bool isSExt32Register(Register Reg) const {
diff --git a/llvm/test/CodeGen/LoongArch/issue187832.ll b/llvm/test/CodeGen/LoongArch/issue187832.ll
deleted file mode 100644
index b483a7640e171..0000000000000
--- a/llvm/test/CodeGen/LoongArch/issue187832.ll
+++ /dev/null
@@ -1,48 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
-; RUN: llc -mtriple=loongarch32 %s -o - | FileCheck %s --check-prefix=LA32
-; RUN: llc -mtriple=loongarch64 %s -o - | FileCheck %s --check-prefix=LA64
-
-%Box = type { i32, i32, i32, i8, [3 x i8], i32, i8, [1 x i8], i16, i16, i8, [5 x i8], { i64, ptr }, { i64, ptr }, { i64, ptr } }
-
-define void @test(ptr byval(%Box) %0) nounwind {
-; LA32-LABEL: test:
-; LA32:       # %bb.0:
-; LA32-NEXT:    addi.w $sp, $sp, -112
-; LA32-NEXT:    st.w $ra, $sp, 108 # 4-byte Folded Spill
-; LA32-NEXT:    st.w $fp, $sp, 104 # 4-byte Folded Spill
-; LA32-NEXT:    addi.w $fp, $sp, 24
-; LA32-NEXT:    ori $a2, $zero, 80
-; LA32-NEXT:    move $a0, $fp
-; LA32-NEXT:    move $a1, $zero
-; LA32-NEXT:    bl memcpy
-; LA32-NEXT:    st.w $zero, $sp, 8
-; LA32-NEXT:    st.w $zero, $sp, 4
-; LA32-NEXT:    st.w $zero, $sp, 0
-; LA32-NEXT:    move $a0, $zero
-; LA32-NEXT:    move $a1, $zero
-; LA32-NEXT:    move $a2, $zero
-; LA32-NEXT:    move $a3, $fp
-; LA32-NEXT:    move $a4, $zero
-; LA32-NEXT:    move $a5, $zero
-; LA32-NEXT:    move $a6, $zero
-; LA32-NEXT:    move $a7, $zero
-; LA32-NEXT:    jirl $ra, $zero, 0
-; LA32-NEXT:    ld.w $fp, $sp, 104 # 4-byte Folded Reload
-; LA32-NEXT:    ld.w $ra, $sp, 108 # 4-byte Folded Reload
-; LA32-NEXT:    addi.w $sp, $sp, 112
-; LA32-NEXT:    ret
-;
-; LA64-LABEL: test:
-; LA64:       # %bb.0:
-; LA64-NEXT:    movgr2fr.d $fa0, $zero
-; LA64-NEXT:    move $a0, $zero
-; LA64-NEXT:    move $a1, $zero
-; LA64-NEXT:    move $a2, $zero
-; LA64-NEXT:    move $a3, $zero
-; LA64-NEXT:    move $a4, $zero
-; LA64-NEXT:    move $a5, $zero
-; LA64-NEXT:    move $a6, $zero
-; LA64-NEXT:    jr $a0
-  tail call void null(ptr null, double 0.000000e+00, ptr byval(%Box) null, { i64, ptr } zeroinitializer, i32 0, i64 0, i1 false)
-  ret void
-}
diff --git a/llvm/test/CodeGen/LoongArch/musttail.ll b/llvm/test/CodeGen/LoongArch/musttail.ll
deleted file mode 100644
index 23369ddd81fca..0000000000000
--- a/llvm/test/CodeGen/LoongArch/musttail.ll
+++ /dev/null
@@ -1,567 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
-; RUN: llc -mtriple=loongarch32 %s -o - | FileCheck %s --check-prefix=LA32
-; RUN: llc -mtriple=loongarch64 %s -o - | FileCheck %s --check-prefix=LA64
-
-declare i32 @many_args_callee(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, i32 %8, i32 %9)
-
-define i32 @many_args_tail(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, i32 %8, i32 %9) {
-; LA32-LABEL: many_args_tail:
-; LA32:       # %bb.0:
-; LA32-NEXT:    ori $a0, $zero, 8
-; LA32-NEXT:    st.w $a0, $sp, 0
-; LA32-NEXT:    ori $a0, $zero, 9
-; LA32-NEXT:    ori $a1, $zero, 1
-; LA32-NEXT:    ori $a2, $zero, 2
-; LA32-NEXT:    ori $a3, $zero, 3
-; LA32-NEXT:    ori $a4, $zero, 4
-; LA32-NEXT:    ori $a5, $zero, 5
-; LA32-NEXT:    ori $a6, $zero, 6
-; LA32-NEXT:    ori $a7, $zero, 7
-; LA32-NEXT:    st.w $a0, $sp, 4
-; LA32-NEXT:    move $a0, $zero
-; LA32-NEXT:    b many_args_callee
-;
-; LA64-LABEL: many_args_tail:
-; LA64:       # %bb.0:
-; LA64-NEXT:    ori $a0, $zero, 8
-; LA64-NEXT:    st.d $a0, $sp, 0
-; LA64-NEXT:    ori $a0, $zero, 9
-; LA64-NEXT:    ori $a1, $zero, 1
-; LA64-NEXT:    ori $a2, $zero, 2
-; LA64-NEXT:    ori $a3, $zero, 3
-; LA64-NEXT:    ori $a4, $zero, 4
-; LA64-NEXT:    ori $a5, $zero, 5
-; LA64-NEXT:    ori $a6, $zero, 6
-; LA64-NEXT:    ori $a7, $zero, 7
-; LA64-NEXT:    st.d $a0, $sp, 8
-; LA64-NEXT:    move $a0, $zero
-; LA64-NEXT:    pcaddu18i $t8, %call36(many_args_callee)
-; LA64-NEXT:    jr $t8
-  %ret = tail call i32 @many_args_callee(i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9)
-  ret i32 %ret
-}
-
-define i32 @many_args_musttail(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, i32 %8, i32 %9) {
-; LA32-LABEL: many_args_musttail:
-; LA32:       # %bb.0:
-; LA32-NEXT:    ori $a0, $zero, 8
-; LA32-NEXT:    st.w $a0, $sp, 0
-; LA32-NEXT:    ori $a0, $zero, 9
-; LA32-NEXT:    ori $a1, $zero, 1
-; LA32-NEXT:    ori $a2, $zero, 2
-; LA32-NEXT:    ori $a3, $zero, 3
-; LA32-NEXT:    ori $a4, $zero, 4
-; LA32-NEXT:    ori $a5, $zero, 5
-; LA32-NEXT:    ori $a6, $zero, 6
-; LA32-NEXT:    ori $a7, $zero, 7
-; LA32-NEXT:    st.w $a0, $sp, 4
-; LA32-NEXT:    move $a0, $zero
-; LA32-NEXT:    b many_args_callee
-;
-; LA64-LABEL: many_args_musttail:
-; LA64:       # %bb.0:
-; LA64-NEXT:    ori $a0, $zero, 8
-; LA64-NEXT:    st.d $a0, $sp, 0
-; LA64-NEXT:    ori $a0, $zero, 9
-; LA64-NEXT:    ori $a1, $zero, 1
-; LA64-NEXT:    ori $a2, $zero, 2
-; LA64-NEXT:    ori $a3, $zero, 3
-; LA64-NEXT:    ori $a4, $zero, 4
-; LA64-NEXT:    ori $a5, $zero, 5
-; LA64-NEXT:    ori $a6, $zero, 6
-; LA64-NEXT:    ori $a7, $zero, 7
-; LA64-NEXT:    st.d $a0, $sp, 8
-; LA64-NEXT:    move $a0, $zero
-; LA64-NEXT:    pcaddu18i $t8, %call36(many_args_callee)
-; LA64-NEXT:    jr $t8
-  %ret = musttail call i32 @many_args_callee(i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9)
-  ret i32 %ret
-}
-
-; This function has more arguments than it's tail-callee. This isn't valid for
-; the musttail attribute, but can still be tail-called as a non-guaranteed
-; optimisation, because the outgoing arguments to @many_args_callee fit in the
-; stack space allocated by the caller of @more_args_tail.
-define i32 @more_args_tail(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, i32 %8, i32 %9) {
-; LA32-LABEL: more_args_tail:
-; LA32:       # %bb.0:
-; LA32-NEXT:    ori $a0, $zero, 8
-; LA32-NEXT:    st.w $a0, $sp, 0
-; LA32-NEXT:    ori $a0, $zero, 9
-; LA32-NEXT:    ori $a1, $zero, 1
-; LA32-NEXT:    ori $a2, $zero, 2
-; LA32-NEXT:    ori $a3, $zero, 3
-; LA32-NEXT:    ori $a4, $zero, 4
-; LA32-NEXT:    ori $a5, $zero, 5
-; LA32-NEXT:    ori $a6, $zero, 6
-; LA32-NEXT:    ori $a7, $zero, 7
-; LA32-NEXT:    st.w $a0, $sp, 4
-; LA32-NEXT:    move $a0, $zero
-; LA32-NEXT:    b many_args_callee
-;
-; LA64-LABEL: more_args_tail:
-; LA64:       # %bb.0:
-; LA64-NEXT:    ori $a0, $zero, 8
-; LA64-NEXT:    st.d $a0, $sp, 0
-; LA64-NEXT:    ori $a0, $zero, 9
-; LA64-NEXT:    ori $a1, $zero, 1
-; LA64-NEXT:    ori $a2, $zero, 2
-; LA64-NEXT:    ori $a3, $zero, 3
-; LA64-NEXT:    ori $a4, $zero, 4
-; LA64-NEXT:    ori $a5, $zero, 5
-; LA64-NEXT:    ori $a6, $zero, 6
-; LA64-NEXT:    ori $a7, $zero, 7
-; LA64-NEXT:    st.d $a0, $sp, 8
-; LA64-NEXT:    move $a0, $zero
-; LA64-NEXT:    pcaddu18i $t8, %call36(many_args_callee)
-; LA64-NEXT:    jr $t8
-  %ret = tail call i32 @many_args_callee(i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9)
-  ret i32 %ret
-}
-
-; Again, this isn't valid for musttail, but can be tail-called in practice
-; because the stack size if the same.
-define i32 @different_args_tail_32bit(i64 %0, i64 %1, i64 %2, i64 %3, i64 %4) nounwind {
-; LA32-LABEL: different_args_tail_32bit:
-; LA32:       # %bb.0:
-; LA32-NEXT:    ori $a0, $zero, 8
-; LA32-NEXT:    st.w $a0, $sp, 0
-; LA32-NEXT:    ori $a0, $zero, 9
-; LA32-NEXT:    ori $a1, $zero, 1
-; LA32-NEXT:    ori $a2, $zero, 2
-; LA32-NEXT:    ori $a3, $zero, 3
-; LA32-NEXT:    ori $a4, $zero, 4
-; LA32-NEXT:    ori $a5, $zero, 5
-; LA32-NEXT:    ori $a6, $zero, 6
-; LA32-NEXT:    ori $a7, $zero, 7
-; LA32-NEXT:    st.w $a0, $sp, 4
-; LA32-NEXT:    move $a0, $zero
-; LA32-NEXT:    b many_args_callee
-;
-; LA64-LABEL: different_args_tail_32bit:
-; LA64:       # %bb.0:
-; LA64-NEXT:    addi.d $sp, $sp, -32
-; LA64-NEXT:    st.d $ra, $sp, 24 # 8-byte Folded Spill
-; LA64-NEXT:    ori $a0, $zero, 9
-; LA64-NEXT:    st.d $a0, $sp, 8
-; LA64-NEXT:    ori $a0, $zero, 8
-; LA64-NEXT:    ori $a1, $zero, 1
-; LA64-NEXT:    ori $a2, $zero, 2
-; LA64-NEXT:    ori $a3, $zero, 3
-; LA64-NEXT:    ori $a4, $zero, 4
-; LA64-NEXT:    ori $a5, $zero, 5
-; LA64-NEXT:    ori $a6, $zero, 6
-; LA64-NEXT:    ori $a7, $zero, 7
-; LA64-NEXT:    st.d $a0, $sp, 0
-; LA64-NEXT:    move $a0, $zero
-; LA64-NEXT:    pcaddu18i $ra, %call36(many_args_callee)
-; LA64-NEXT:    jirl $ra, $ra, 0
-; LA64-NEXT:    ld.d $ra, $sp, 24 # 8-byte Folded Reload
-; LA64-NEXT:    addi.d $sp, $sp, 32
-; LA64-NEXT:    ret
-  %ret = tail call i32 @many_args_callee(i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9)
-  ret i32 %ret
-}
-
-define i32 @different_args_tail_64bit(i128 %0, i128 %1, i128 %2, i128 %3, i128 %4) nounwind {
-; LA32-LABEL: different_args_tail_64bit:
-; LA32:       # %bb.0:
-; LA32-NEXT:    addi.w $sp, $sp, -16
-; LA32-NEXT:    st.w $ra, $sp, 12 # 4-byte Folded Spill
-; LA32-NEXT:    ori $a0, $zero, 9
-; LA32-NEXT:    st.w $a0, $sp, 4
-; LA32-NEXT:    ori $a0, $zero, 8
-; LA32-NEXT:    ori $a1, $zero, 1
-; LA32-NEXT:    ori $a2, $zero, 2
-; LA32-NEXT:    ori $a3, $zero, 3
-; LA32-NEXT:    ori $a4, $zero, 4
-; LA32-NEXT:    ori $a5, $zero, 5
-; LA32-NEXT:    ori $a6, $zero, 6
-; LA32-NEXT:    ori $a7, $zero, 7
-; LA32-NEXT:    st.w $a0, $sp, 0
-; LA32-NEXT:    move $a0, $zero
-; LA32-NEXT:    bl many_args_callee
-; LA32-NEXT:    ld.w $ra, $sp, 12 # 4-byte Folded Reload
-; LA32-NEXT:    addi.w $sp, $sp, 16
-; LA32-NEXT:    ret
-;
-; LA64-LABEL: different_args_tail_64bit:
-; LA64:       # %bb.0:
-; LA64-NEXT:    ori $a0, $zero, 8
-; LA64-NEXT:    st.d $a0, $sp, 0
-; LA64-NEXT:    ori $a0, $zero, 9
-; LA64-NEXT:    ori $a1, $zero, 1
-; LA64-NEXT:    ori $a2, $zero, 2
-; LA64-NEXT:    ori $a3, $zero, 3
-; LA64-NEXT:    ori $a4, $zero, 4
-; LA64-NEXT:    or...
[truncated]

Copy link
Copy Markdown
Member

@heiher heiher left a comment

Choose a reason for hiding this comment

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

Okay, lets start again.

@github-project-automation github-project-automation Bot moved this from Needs Triage to Needs Merge in LLVM Release Status Apr 11, 2026
This reverts:
- 2b839f6 (llvm#168506)
- d40e607 (llvm#188006)

There's a lifetime issue in the implementation, where an SDValue is
saved and may be used outside the current basic block.

The corresponding revert on `main` is
501417b (llvm#191508) - in this case only
the LoongArch changes made it to the 22.x branches, so this commit only
affects that architecture.
@c-rhodes c-rhodes force-pushed the pr/22.x/revert-loongarch-musttail branch from 76a2447 to fa56327 Compare April 17, 2026 09:45
@c-rhodes c-rhodes merged commit fa56327 into llvm:release/22.x Apr 17, 2026
1 check was pending
@github-project-automation github-project-automation Bot moved this from Needs Merge to Done in LLVM Release Status Apr 17, 2026
@lenary lenary deleted the pr/22.x/revert-loongarch-musttail branch April 21, 2026 20:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.

4 participants