Skip to content

[IR][SDAG] Remove lifetime size handling from SDAG #150944

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 1 commit into from
Jul 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26653,9 +26653,10 @@ object's lifetime.
Arguments:
""""""""""

The first argument is a constant integer representing the size of the
object, or -1 if it is variable sized. The second argument is a pointer
to an ``alloca`` instruction.
The first argument is a constant integer, which is ignored and will be removed
in the future.

The second argument is a pointer to an ``alloca`` instruction.

Semantics:
""""""""""
Expand Down Expand Up @@ -26693,9 +26694,10 @@ The '``llvm.lifetime.end``' intrinsic specifies the end of a
Arguments:
""""""""""

The first argument is a constant integer representing the size of the
object, or -1 if it is variable sized. The second argument is a pointer
to an ``alloca`` instruction.
The first argument is a constant integer, which is ignored and will be removed
in the future.

The second argument is a pointer to an ``alloca`` instruction.

Semantics:
""""""""""
Expand Down
5 changes: 2 additions & 3 deletions llvm/include/llvm/CodeGen/SelectionDAG.h
Original file line number Diff line number Diff line change
Expand Up @@ -1428,10 +1428,9 @@ class SelectionDAG {
EVT MemVT, MachineMemOperand *MMO);

/// Creates a LifetimeSDNode that starts (`IsStart==true`) or ends
/// (`IsStart==false`) the lifetime of the portion of `FrameIndex` between
/// offsets `0` and `Size`.
/// (`IsStart==false`) the lifetime of the `FrameIndex`.
LLVM_ABI SDValue getLifetimeNode(bool IsStart, const SDLoc &dl, SDValue Chain,
int FrameIndex, int64_t Size);
int FrameIndex);

/// Creates a PseudoProbeSDNode with function GUID `Guid` and
/// the index of the block `Index` it is probing, as well as the attributes
Expand Down
10 changes: 3 additions & 7 deletions llvm/include/llvm/CodeGen/SelectionDAGNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1999,23 +1999,19 @@ class FrameIndexSDNode : public SDNode {
}
};

/// This SDNode is used for LIFETIME_START/LIFETIME_END values, which indicate
/// the offet and size that are started/ended in the underlying FrameIndex.
/// This SDNode is used for LIFETIME_START/LIFETIME_END values.
class LifetimeSDNode : public SDNode {
friend class SelectionDAG;
int64_t Size;

LifetimeSDNode(unsigned Opcode, unsigned Order, const DebugLoc &dl,
SDVTList VTs, int64_t Size)
: SDNode(Opcode, Order, dl, VTs), Size(Size) {}
SDVTList VTs)
: SDNode(Opcode, Order, dl, VTs) {}

public:
int64_t getFrameIndex() const {
return cast<FrameIndexSDNode>(getOperand(1))->getIndex();
}

int64_t getSize() const { return Size; }

// Methods to support isa and dyn_cast
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::LIFETIME_START ||
Expand Down
15 changes: 10 additions & 5 deletions llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "llvm/CodeGen/ByteProvider.h"
#include "llvm/CodeGen/DAGCombine.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/SDPatternMatch.h"
Expand Down Expand Up @@ -22778,8 +22779,10 @@ SDValue DAGCombiner::visitLIFETIME_END(SDNode *N) {
const BaseIndexOffset StoreBase = BaseIndexOffset::match(ST, DAG);
// If we store purely within object bounds just before its lifetime ends,
// we can remove the store.
if (LifetimeEndBase.contains(DAG, LifetimeEnd->getSize() * 8, StoreBase,
StoreSize.getFixedValue() * 8)) {
MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
if (LifetimeEndBase.contains(
DAG, MFI.getObjectSize(LifetimeEnd->getFrameIndex()) * 8,
StoreBase, StoreSize.getFixedValue() * 8)) {
LLVM_DEBUG(dbgs() << "\nRemoving store:"; StoreBase.dump();
dbgs() << "\nwithin LIFETIME_END of : ";
LifetimeEndBase.dump(); dbgs() << "\n");
Expand Down Expand Up @@ -29415,7 +29418,7 @@ bool DAGCombiner::mayAlias(SDNode *Op0, SDNode *Op1) const {
MachineMemOperand *MMO;
};

auto getCharacteristics = [](SDNode *N) -> MemUseCharacteristics {
auto getCharacteristics = [this](SDNode *N) -> MemUseCharacteristics {
if (const auto *LSN = dyn_cast<LSBaseSDNode>(N)) {
int64_t Offset = 0;
if (auto *C = dyn_cast<ConstantSDNode>(LSN->getOffset()))
Expand All @@ -29428,13 +29431,15 @@ bool DAGCombiner::mayAlias(SDNode *Op0, SDNode *Op1) const {
LSN->getBasePtr(), Offset /*base offset*/,
LocationSize::precise(Size), LSN->getMemOperand()};
}
if (const auto *LN = cast<LifetimeSDNode>(N))
if (const auto *LN = cast<LifetimeSDNode>(N)) {
MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
return {false /*isVolatile*/,
/*isAtomic*/ false,
LN->getOperand(1),
0,
LocationSize::precise(LN->getSize()),
LocationSize::precise(MFI.getObjectSize(LN->getFrameIndex())),
(MachineMemOperand *)nullptr};
}
// Default.
return {false /*isvolatile*/,
/*isAtomic*/ false,
Expand Down
12 changes: 3 additions & 9 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -784,10 +784,6 @@ static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) {
case ISD::TargetFrameIndex:
ID.AddInteger(cast<FrameIndexSDNode>(N)->getIndex());
break;
case ISD::LIFETIME_START:
case ISD::LIFETIME_END:
ID.AddInteger(cast<LifetimeSDNode>(N)->getSize());
break;
case ISD::PSEUDO_PROBE:
ID.AddInteger(cast<PseudoProbeSDNode>(N)->getGuid());
ID.AddInteger(cast<PseudoProbeSDNode>(N)->getIndex());
Expand Down Expand Up @@ -9360,8 +9356,7 @@ SDValue SelectionDAG::getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl,
}

SDValue SelectionDAG::getLifetimeNode(bool IsStart, const SDLoc &dl,
SDValue Chain, int FrameIndex,
int64_t Size) {
SDValue Chain, int FrameIndex) {
const unsigned Opcode = IsStart ? ISD::LIFETIME_START : ISD::LIFETIME_END;
const auto VTs = getVTList(MVT::Other);
SDValue Ops[2] = {
Expand All @@ -9373,13 +9368,12 @@ SDValue SelectionDAG::getLifetimeNode(bool IsStart, const SDLoc &dl,
FoldingSetNodeID ID;
AddNodeIDNode(ID, Opcode, VTs, Ops);
ID.AddInteger(FrameIndex);
ID.AddInteger(Size);
void *IP = nullptr;
if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP))
return SDValue(E, 0);

LifetimeSDNode *N = newSDNode<LifetimeSDNode>(Opcode, dl.getIROrder(),
dl.getDebugLoc(), VTs, Size);
LifetimeSDNode *N =
newSDNode<LifetimeSDNode>(Opcode, dl.getIROrder(), dl.getDebugLoc(), VTs);
createOperands(N, Ops);
CSEMap.InsertNode(N, IP);
InsertNode(N);
Expand Down
4 changes: 1 addition & 3 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7594,8 +7594,6 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
if (TM.getOptLevel() == CodeGenOptLevel::None)
return;

const int64_t ObjectSize =
cast<ConstantInt>(I.getArgOperand(0))->getSExtValue();
const AllocaInst *LifetimeObject = cast<AllocaInst>(I.getArgOperand(1));

// First check that the Alloca is static, otherwise it won't have a
Expand All @@ -7605,7 +7603,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
return;

const int FrameIndex = SI->second;
Res = DAG.getLifetimeNode(IsStart, sdl, getRoot(), FrameIndex, ObjectSize);
Res = DAG.getLifetimeNode(IsStart, sdl, getRoot(), FrameIndex);
DAG.setRoot(Res);
return;
}
Expand Down
2 changes: 0 additions & 2 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -946,8 +946,6 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
<< " -> "
<< ASC->getDestAddressSpace()
<< ']';
} else if (const LifetimeSDNode *LN = dyn_cast<LifetimeSDNode>(this)) {
OS << "<0 to " << LN->getSize() << ">";
} else if (const auto *AA = dyn_cast<AssertAlignSDNode>(this)) {
OS << '<' << AA->getAlign().value() << '>';
}
Expand Down
15 changes: 4 additions & 11 deletions llvm/test/CodeGen/X86/swap.ll
Original file line number Diff line number Diff line change
Expand Up @@ -113,21 +113,17 @@ define dso_local void @onealloc_readback_1(ptr nocapture %a, ptr nocapture %b) l
;
; AA-LABEL: onealloc_readback_1:
; AA: # %bb.0: # %entry
; AA-NEXT: vmovups (%rdi), %xmm0
; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp)
; AA-NEXT: vmovups (%rsi), %xmm0
; AA-NEXT: vmovups %xmm0, (%rdi)
; AA-NEXT: retq
entry:
%alloc = alloca [16 x i8], i8 2, align 1
%part1 = getelementptr inbounds [16 x i8], ptr %alloc, i64 1, i64 0
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %part1)
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %alloc)
call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %alloc)
call void @llvm.memcpy.p0.p0.i64(ptr nonnull align 1 %part1, ptr align 1 %a, i64 16, i1 false)
call void @llvm.memcpy.p0.p0.i64(ptr nonnull align 1 %alloc, ptr align 1 %b, i64 16, i1 false)
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %part1)
tail call void @llvm.memcpy.p0.p0.i64(ptr nonnull align 1 %a, ptr align 1 %alloc, i64 16, i1 false)
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %alloc)
call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %alloc)
ret void
}

Expand All @@ -144,19 +140,16 @@ define dso_local void @onealloc_readback_2(ptr nocapture %a, ptr nocapture %b) l
; AA-LABEL: onealloc_readback_2:
; AA: # %bb.0: # %entry
; AA-NEXT: vmovups (%rsi), %xmm0
; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp)
; AA-NEXT: vmovups %xmm0, (%rdi)
; AA-NEXT: retq
entry:
%alloc = alloca [16 x i8], i8 2, align 1
%part2 = getelementptr inbounds [16 x i8], ptr %alloc, i64 1, i64 0
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %alloc)
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %part2)
call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %alloc)
call void @llvm.memcpy.p0.p0.i64(ptr nonnull align 1 %alloc, ptr align 1 %a, i64 16, i1 false)
call void @llvm.memcpy.p0.p0.i64(ptr nonnull align 1 %part2, ptr align 1 %b, i64 16, i1 false)
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %alloc)
tail call void @llvm.memcpy.p0.p0.i64(ptr nonnull align 1 %a, ptr align 1 %part2, i64 16, i1 false)
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %part2)
call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %alloc)
ret void
}

Expand Down
Loading