[RISC-V][LoongArch] Revert Musttail Fixes#191508
Conversation
This reverts: - 2b839f6 (llvm#168506) - 6a81656 (llvm#170547) - ab17b54 (llvm#188006) - e65dd1f (llvm#191093) The changes in llvm#168506 and llvm#170547 both have a lifetime issue where an SDValue is kept for the duration of a function, despite being valid only when processing the same basic block. Reverting both on LoongArch and RISC-V as the implementations are identical and one of the fix commits touches both targets, rather than doing only a RISC-V revert. I also think this more cleanly shows what is being undone when starting again with the changes.
|
@llvm/pr-subscribers-backend-risc-v @llvm/pr-subscribers-backend-loongarch Author: Sam Elliott (lenary) ChangesThis reverts: The changes in #168506 and #170547 both have a lifetime issue where an SDValue is kept for the duration of a function, despite being valid only when processing the same basic block. Reverting both on LoongArch and RISC-V as the implementations are identical and one of the fix commits touches both targets, rather than doing only a RISC-V revert. I also think this more cleanly shows what is being undone when starting again with the changes. Patch is 74.12 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/191508.diff 11 Files Affected:
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index bf98f23fae581..2e4eb1da55ac7 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -8360,7 +8360,6 @@ SDValue LoongArchTargetLowering::LowerFormalArguments(
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
MachineFunction &MF = DAG.getMachineFunction();
- auto *LoongArchFI = MF.getInfo<LoongArchMachineFunctionInfo>();
switch (CallConv) {
default:
@@ -8425,8 +8424,6 @@ SDValue LoongArchTargetLowering::LowerFormalArguments(
continue;
}
InVals.push_back(ArgValue);
- if (Ins[InsIdx].Flags.isByVal())
- LoongArchFI->addIncomingByValArgs(ArgValue);
}
if (IsVarArg) {
@@ -8435,6 +8432,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
@@ -8484,8 +8482,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()) {
@@ -8542,11 +8538,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.
@@ -8558,19 +8552,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();
@@ -8580,14 +8568,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;
}
@@ -8615,7 +8595,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;
@@ -8641,7 +8620,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;
@@ -8649,39 +8628,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;
@@ -8776,44 +8738,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/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index fed7faa309579..c2a81b4101061 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -24310,7 +24310,6 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
MachineFunction &MF = DAG.getMachineFunction();
- RISCVMachineFunctionInfo *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
switch (CallConv) {
default:
@@ -24438,9 +24437,6 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
continue;
}
InVals.push_back(ArgValue);
-
- if (Ins[InsIdx].Flags.isByVal())
- RVFI->addIncomingByValArgs(ArgValue);
}
if (any_of(ArgLocs,
@@ -24453,6 +24449,7 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
const TargetRegisterClass *RC = &RISCV::GPRRegClass;
MachineFrameInfo &MFI = MF.getFrameInfo();
MachineRegisterInfo &RegInfo = MF.getRegInfo();
+ RISCVMachineFunctionInfo *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
// Size of the vararg save area. For now, the varargs save area is either
// zero or large enough to hold a0-a7.
@@ -24470,7 +24467,7 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
// If saving an odd number of registers then create an extra stack slot to
// ensure that the frame pointer is 2*XLEN-aligned, which in turn ensures
- // offsets to even-numbered registers remain 2*XLEN-aligned.
+ // offsets to even-numbered registered remain 2*XLEN-aligned.
if (Idx % 2) {
MFI.CreateFixedObject(
XLenInBytes, VaArgOffset - static_cast<int>(XLenInBytes), true);
@@ -24500,12 +24497,9 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
RVFI->setVarArgsSaveSize(VarArgsSaveSize);
}
- RVFI->setArgumentStackSize(CCInfo.getStackSize());
-
// All stores are grouped in one node to allow the matching between
- // the size of Ins and InVals.
+ // the size of Ins and InVals. This only happens for vararg functions.
if (!OutChains.empty()) {
- assert(IsVarArg && "Only variadic functions should have OutChains");
OutChains.push_back(Chain);
Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
}
@@ -24524,7 +24518,6 @@ bool RISCVTargetLowering::isEligibleForTailCallOptimization(
auto &Outs = CLI.Outs;
auto &Caller = MF.getFunction();
auto CallerCC = Caller.getCallingConv();
- auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
// Exception-handling functions need a special set of instructions to
// indicate a return to the hardware. Tail-calling another function would
@@ -24534,29 +24527,29 @@ bool RISCVTargetLowering::isEligibleForTailCallOptimization(
if (Caller.hasFnAttribute("interrupt"))
return false;
- // 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() > RVFI->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.
+ // Since long doubles (fp128) and i128 are larger than 2*XLEN, they are
+ // passed indirectly. So the address of the value will be passed in a
+ // register, or if not available, then the address is put on the stack. In
+ // order to pass indirectly, space on the stack often needs to be allocated
+ // in order to store the value. In this case the CCInfo.getNextStackOffset()
+ // != 0 check is not enough and we need to check if any CCValAssign ArgsLocs
+ // are passed CCValAssign::Indirect.
+ for (auto &VA : ArgLocs)
+ if (VA.getLocInfo() == CCValAssign::Indirect)
+ return false;
+
// Do not tail call opt if either caller or callee uses struct return
// 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, e = Outs.size(); i != e; ++i) {
- if (!Outs[i].Flags.isByVal())
- continue;
- if (j >= RVFI->getIncomingByValArgsSize())
- return false;
- if (RVFI->getIncomingByValArgs(j).getValueType() != Outs[i].ArgVT)
- return false;
- ++j;
- }
-
// The callee has to preserve all registers the caller needs to preserve.
const RISCVRegisterInfo *TRI = Subtarget.getRegisterInfo();
const uint32_t *CallerPreserved = TRI->getCallPreservedMask(MF, CallerCC);
@@ -24566,12 +24559,12 @@ bool RISCVTargetLowering::isEligibleForTailCallOptimization(
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;
+ // Byval parameters hand the function a pointer directly into the stack area
+ // we want to reuse during a tail call. Working around this *is* possible
+ // but less efficient and uglier in LowerCall.
+ for (auto &Arg : Outs)
+ if (Arg.Flags.isByVal())
+ return false;
return true;
}
@@ -24600,7 +24593,6 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
const CallBase *CB = CLI.CB;
MachineFunction &MF = DAG.getMachineFunction();
- RISCVMachineFunctionInfo *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
MachineFunction::CallSiteInfo CSInfo;
// Set type id for call site info.
@@ -24634,7 +24626,7 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
// Create local copies for byval args
SmallVector<SDValue, 8> 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;
@@ -24643,39 +24635,21 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
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, XLenVT);
- SDValue Dst;
- if (IsTailCall) {
- SDValue CallerArg = RVFI->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, IsTailCall,
+ 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>, 8> RegsToPass;
SmallVector<SDValue, 8> MemOpChains;
@@ -24777,12 +24751,8 @@ SDValue RISCVTargetLowering::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.
@@ -24793,32 +24763,20 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
CSInfo.ArgRegPairs.emplace_back(VA.getLocReg(), i);
} 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, RISCV::X2, PtrVT);
-
- if (IsTailCall) {
- unsigned OpSize = divideCeil(VA.getValVT().getSizeInBits(), 8);
- int FI = MF.getFrameInfo().CreateFixedObject(OpSize, Offset, true);
- DstAddr = DAG.getFrameIndex(FI, PtrVT);
- DstInfo = MachinePointerI...
[truncated]
|
|
/cc @heiher @folkertdev for info |
|
The issue seems like it should be fairly easy to fix: we already copy the address into a virtual register, it's just a matter of digging up the correct virtual register. But it does indicate the testing was extremely limited. |
|
On RISC-V, the lifetime problem was one of two issues, the other was causing miscompiles. Because the risc-v implementation was being worked on actively (and there are fixes for one of the issues), I thought it less intrusive to revert than to fix-forward. |
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.
…, r=chenyukang explicit-tail-calls: disable two tests on LoongArch A [recent LLVM change](llvm/llvm-project#191508) broke these on LLVM 23. I suspect these will eventually be fixed, so maybe it'd be okay/better to just leave this pending so it applies to our CI without merging it? I'm open to opinions.
Rollup merge of #155259 - durin42:llvm-23-loongarch-tailcall, r=chenyukang explicit-tail-calls: disable two tests on LoongArch A [recent LLVM change](llvm/llvm-project#191508) broke these on LLVM 23. I suspect these will eventually be fixed, so maybe it'd be okay/better to just leave this pending so it applies to our CI without merging it? I'm open to opinions.
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.
Apply the RISCV parts of the upstream revert 501417b (llvm#191508). The reverted code stored SDValues in MachineFunctionInfo across basic blocks, which is unsound because the SelectionDAG is cleared between BBs. This removes ArgumentStackSize, IncomingByValArgs, the byval matching loop in isEligibleForTailCallOptimization, parametersInCSRMatch, and the byval forwarding in LowerCall. The indirect arg rejection and sret check revert to the conservative pre-byval behavior. The IncomingIndirectArgs map (for musttail forwarding) is kept; its SDValue lifetime issue will be fixed in the next commit. The LoongArch part of the revert is not included because the branch base has diverged too far. Assisted-by: Claude (Anthropic) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous commit in this series made musttail take an early return true from isEligibleForTailCallOptimization so indirect-arg forwarding could kick in. That bypassed the pre-existing byval check as well, and byval tail-call support was reverted in 501417b (llvm#191508) pending a virtual-register-based re-implementation. The result was a silent miscompile: for musttail with a byval arg the caller allocates a local copy, writes a pointer into it, restores sp, and then tail calls with a dangling pointer. Move the byval rejection before the musttail bypass so it applies to both regular and must-tail calls. A musttail site with a byval arg will now hit reportFatalInternalError in LowerCall, matching the behavior on main before the indirect-arg fix landed, until byval tail-call support is reinstated on top of the new vreg-based forwarding path. Assisted-by: Claude (Anthropic) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This reverts:
musttailsupport #170547)The changes in #168506 and #170547 both have a lifetime issue where an SDValue is kept for the duration of a function, despite being valid only when processing the same basic block.
Reverting both on LoongArch and RISC-V as the implementations are identical and one of the fix commits touches both targets, rather than doing only a RISC-V revert. I also think this more cleanly shows what is being undone when starting again with the changes.