Skip to content

[IR] Add utilities for manipulating length of MemIntrinsic [nfc] #153856

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
Aug 20, 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
11 changes: 11 additions & 0 deletions llvm/include/llvm/IR/IntrinsicInst.h
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,13 @@ template <typename Derived> class MemIntrinsicBase : public IntrinsicInst {
const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); }
Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); }

std::optional<APInt> getLengthInBytes() const {
ConstantInt *C = dyn_cast<ConstantInt>(getLength());
if (!C)
return std::nullopt;
return C->getValue();
}

/// This is just like getRawDest, but it strips off any cast
/// instructions (including addrspacecast) that feed it, giving the
/// original input. The returned value is guaranteed to be a pointer.
Expand Down Expand Up @@ -1022,6 +1029,10 @@ template <typename Derived> class MemIntrinsicBase : public IntrinsicInst {
"setLength called with value of wrong type!");
setArgOperand(ARG_LENGTH, L);
}

void setLength(uint64_t L) {
setLength(ConstantInt::get(getLength()->getType(), L));
}
};

/// Common base class for all memory transfer intrinsics. Simply provides
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/SafeStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ bool SafeStack::IsMemIntrinsicSafe(const MemIntrinsic *MI, const Use &U,
return true;
}

const auto *Len = dyn_cast<ConstantInt>(MI->getLength());
auto Len = MI->getLengthInBytes();
// Non-constant size => unsafe. FIXME: try SCEV getRange.
if (!Len) return false;
return IsAccessSafe(U, Len->getZExtValue(), AllocaPtr, AllocaSize);
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Transforms/IPO/AttributorAttributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2008,9 +2008,8 @@ struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
// destination) and second (=source) arguments as we know how they are
// accessed.
if (auto *MI = dyn_cast_or_null<MemIntrinsic>(getCtxI())) {
ConstantInt *Length = dyn_cast<ConstantInt>(MI->getLength());
int64_t LengthVal = AA::RangeTy::Unknown;
if (Length)
if (auto Length = MI->getLengthInBytes())
LengthVal = Length->getSExtValue();
unsigned ArgNo = getIRPosition().getCallSiteArgNo();
ChangeStatus Changed = ChangeStatus::UNCHANGED;
Expand Down
16 changes: 8 additions & 8 deletions llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,15 @@ Instruction *InstCombinerImpl::SimplifyAnyMemTransfer(AnyMemTransferInst *MI) {
// wouldn't be constant), and this must be a noop.
if (!isModSet(AA->getModRefInfoMask(MI->getDest()))) {
// Set the size of the copy to 0, it will be deleted on the next iteration.
MI->setLength(Constant::getNullValue(MI->getLength()->getType()));
MI->setLength((uint64_t)0);
return MI;
}

// If the source is provably undef, the memcpy/memmove doesn't do anything
// (unless the transfer is volatile).
if (hasUndefSource(MI) && !MI->isVolatile()) {
// Set the size of the copy to 0, it will be deleted on the next iteration.
MI->setLength(Constant::getNullValue(MI->getLength()->getType()));
MI->setLength((uint64_t)0);
return MI;
}

Expand Down Expand Up @@ -211,7 +211,7 @@ Instruction *InstCombinerImpl::SimplifyAnyMemTransfer(AnyMemTransferInst *MI) {
}

// Set the size of the copy to 0, it will be deleted on the next iteration.
MI->setLength(Constant::getNullValue(MemOpLength->getType()));
MI->setLength((uint64_t)0);
return MI;
}

Expand All @@ -229,7 +229,7 @@ Instruction *InstCombinerImpl::SimplifyAnyMemSet(AnyMemSetInst *MI) {
// wouldn't be constant), and this must be a noop.
if (!isModSet(AA->getModRefInfoMask(MI->getDest()))) {
// Set the size of the copy to 0, it will be deleted on the next iteration.
MI->setLength(Constant::getNullValue(MI->getLength()->getType()));
MI->setLength((uint64_t)0);
return MI;
}

Expand All @@ -238,7 +238,7 @@ Instruction *InstCombinerImpl::SimplifyAnyMemSet(AnyMemSetInst *MI) {
// value. Change to PoisonValue once #52930 is resolved.
if (isa<UndefValue>(MI->getValue())) {
// Set the size of the copy to 0, it will be deleted on the next iteration.
MI->setLength(Constant::getNullValue(MI->getLength()->getType()));
MI->setLength((uint64_t)0);
return MI;
}

Expand Down Expand Up @@ -279,7 +279,7 @@ Instruction *InstCombinerImpl::SimplifyAnyMemSet(AnyMemSetInst *MI) {
S->setOrdering(AtomicOrdering::Unordered);

// Set the size of the copy to 0, it will be deleted on the next iteration.
MI->setLength(Constant::getNullValue(LenC->getType()));
MI->setLength((uint64_t)0);
return MI;
}

Expand Down Expand Up @@ -1753,9 +1753,9 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
// Intrinsics cannot occur in an invoke or a callbr, so handle them here
// instead of in visitCallBase.
if (auto *MI = dyn_cast<AnyMemIntrinsic>(II)) {
if (ConstantInt *NumBytes = dyn_cast<ConstantInt>(MI->getLength())) {
if (auto NumBytes = MI->getLengthInBytes()) {
// memmove/cpy/set of zero bytes is a noop.
if (NumBytes->isNullValue())
if (NumBytes->isZero())
return eraseInstFromFunction(CI);

// For atomic unordered mem intrinsics if len is not a positive or
Expand Down
6 changes: 2 additions & 4 deletions llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -685,15 +685,13 @@ static bool tryToShorten(Instruction *DeadI, int64_t &DeadStart,
<< "\n KILLER [" << ToRemoveStart << ", "
<< int64_t(ToRemoveStart + ToRemoveSize) << ")\n");

Value *DeadWriteLength = DeadIntrinsic->getLength();
Value *TrimmedLength = ConstantInt::get(DeadWriteLength->getType(), NewSize);
DeadIntrinsic->setLength(TrimmedLength);
DeadIntrinsic->setLength(NewSize);
DeadIntrinsic->setDestAlignment(PrefAlign);

Value *OrigDest = DeadIntrinsic->getRawDest();
if (!IsOverwriteEnd) {
Value *Indices[1] = {
ConstantInt::get(DeadWriteLength->getType(), ToRemoveSize)};
ConstantInt::get(DeadIntrinsic->getLength()->getType(), ToRemoveSize)};
Instruction *NewDestGEP = GetElementPtrInst::CreateInBounds(
Type::getInt8Ty(DeadIntrinsic->getContext()), OrigDest, Indices, "",
DeadI->getIterator());
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Transforms/Scalar/SROA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3425,8 +3425,7 @@ class AllocaSliceRewriter : public InstVisitor<AllocaSliceRewriter, bool> {

// Rewrite the size as needed.
if (NewEndOffset != EndOffset)
II.setLength(ConstantInt::get(II.getLength()->getType(),
NewEndOffset - NewBeginOffset));
II.setLength(NewEndOffset - NewBeginOffset);
return false;
}
// Record this instruction for deletion.
Expand Down