[llvm] a987022 - [MemoryBuiltins] Add getBaseObjectSize() (NFCI) (#155911)

Roman Divacky via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 1 09:35:37 PDT 2025


Hi Nikita,

One of the users of getObjectSize() is isObjectSize() thats only ever called on
the same objects computing the size needlessly twice. I think it could be
changed to only compute the size of the object just once and then compare the
sizes, thus saving one getObjectSize() call.

Am I missing something?

Thanks, Roman

On Mon, Sep 01, 2025 at 12:26:01AM -0700, via llvm-commits wrote:
> 
> Author: Nikita Popov
> Date: 2025-09-01T09:25:56+02:00
> New Revision: a987022f33a27610732544b0c5f4475ce818c982
> 
> URL: https://github.com/llvm/llvm-project/commit/a987022f33a27610732544b0c5f4475ce818c982
> DIFF: https://github.com/llvm/llvm-project/commit/a987022f33a27610732544b0c5f4475ce818c982.diff
> 
> LOG: [MemoryBuiltins] Add getBaseObjectSize() (NFCI) (#155911)
> 
> getObjectSize() is based on ObjectSizeOffsetVisitor, which has become
> very expensive over time. The implementation is geared towards computing
> as-good-as-possible results for the objectsize intrinsics and similar.
> However, we also use it in BasicAA, which is very hot, and really only
> cares about the base cases like alloca/malloc/global, not any of the
> analysis for GEPs, phis, or loads.
> 
> Add a new getBaseObjectSize() API for this use case, which only handles
> the non-recursive cases. As a bonus, this API can easily return a
> TypeSize and thus support scalable vectors. For now, I'm explicitly
> discarding the scalable sizes in BasicAA just to avoid unnecessary
> behavior changes during this refactor.
> 
> Added: 
>     
> 
> Modified: 
>     llvm/include/llvm/Analysis/MemoryBuiltins.h
>     llvm/lib/Analysis/BasicAliasAnalysis.cpp
>     llvm/lib/Analysis/MemoryBuiltins.cpp
> 
> Removed: 
>     
> 
> 
> ################################################################################
> diff  --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h
> index 0f0605e4f01b2..1b509fb66ce37 100644
> --- a/llvm/include/llvm/Analysis/MemoryBuiltins.h
> +++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h
> @@ -181,6 +181,14 @@ LLVM_ABI bool getObjectSize(const Value *Ptr, uint64_t &Size,
>                              const DataLayout &DL, const TargetLibraryInfo *TLI,
>                              ObjectSizeOpts Opts = {});
>  
> +/// Like getObjectSize(), but only returns the size of base objects (like
> +/// allocas, global variables and allocator calls) and std::nullopt otherwise.
> +/// Requires ExactSizeFromOffset mode.
> +LLVM_ABI std::optional<TypeSize> getBaseObjectSize(const Value *Ptr,
> +                                                   const DataLayout &DL,
> +                                                   const TargetLibraryInfo *TLI,
> +                                                   ObjectSizeOpts Opts = {});
> +
>  /// Try to turn a call to \@llvm.objectsize into an integer value of the given
>  /// Type. Returns null on failure. If MustSucceed is true, this function will
>  /// not return null, and may return conservative values governed by the second
> 
> diff  --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
> index 61f80103e55b5..de37c391cf254 100644
> --- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
> +++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
> @@ -103,12 +103,15 @@ static std::optional<TypeSize> getObjectSize(const Value *V,
>                                               const TargetLibraryInfo &TLI,
>                                               bool NullIsValidLoc,
>                                               bool RoundToAlign = false) {
> -  uint64_t Size;
>    ObjectSizeOpts Opts;
>    Opts.RoundToAlign = RoundToAlign;
>    Opts.NullIsUnknownSize = NullIsValidLoc;
> -  if (getObjectSize(V, Size, DL, &TLI, Opts))
> -    return TypeSize::getFixed(Size);
> +  if (std::optional<TypeSize> Size = getBaseObjectSize(V, DL, &TLI, Opts)) {
> +    // FIXME: Remove this check, only exists to preserve previous behavior.
> +    if (Size->isScalable())
> +      return std::nullopt;
> +    return Size;
> +  }
>    return std::nullopt;
>  }
>  
> 
> diff  --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp
> index e0b7f65d18a30..1df4eda2580df 100644
> --- a/llvm/lib/Analysis/MemoryBuiltins.cpp
> +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp
> @@ -589,6 +589,59 @@ bool llvm::getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
>    return true;
>  }
>  
> +std::optional<TypeSize> llvm::getBaseObjectSize(const Value *Ptr,
> +                                                const DataLayout &DL,
> +                                                const TargetLibraryInfo *TLI,
> +                                                ObjectSizeOpts Opts) {
> +  assert(Opts.EvalMode == ObjectSizeOpts::Mode::ExactSizeFromOffset &&
> +         "Other modes are currently not supported");
> +
> +  auto Align = [&](TypeSize Size, MaybeAlign Alignment) {
> +    if (Opts.RoundToAlign && Alignment && !Size.isScalable())
> +      return TypeSize::getFixed(alignTo(Size.getFixedValue(), *Alignment));
> +    return Size;
> +  };
> +
> +  if (isa<UndefValue>(Ptr))
> +    return TypeSize::getZero();
> +
> +  if (isa<ConstantPointerNull>(Ptr)) {
> +    if (Opts.NullIsUnknownSize || Ptr->getType()->getPointerAddressSpace())
> +      return std::nullopt;
> +    return TypeSize::getZero();
> +  }
> +
> +  if (auto *GV = dyn_cast<GlobalVariable>(Ptr)) {
> +    if (!GV->getValueType()->isSized() || GV->hasExternalWeakLinkage() ||
> +        !GV->hasInitializer() || GV->isInterposable())
> +      return std::nullopt;
> +    return Align(DL.getTypeAllocSize(GV->getValueType()), GV->getAlign());
> +  }
> +
> +  if (auto *A = dyn_cast<Argument>(Ptr)) {
> +    Type *MemoryTy = A->getPointeeInMemoryValueType();
> +    if (!MemoryTy || !MemoryTy->isSized())
> +      return std::nullopt;
> +    return Align(DL.getTypeAllocSize(MemoryTy), A->getParamAlign());
> +  }
> +
> +  if (auto *AI = dyn_cast<AllocaInst>(Ptr)) {
> +    if (std::optional<TypeSize> Size = AI->getAllocationSize(DL))
> +      return Align(*Size, AI->getAlign());
> +    return std::nullopt;
> +  }
> +
> +  if (auto *CB = dyn_cast<CallBase>(Ptr)) {
> +    if (std::optional<APInt> Size = getAllocSize(CB, TLI)) {
> +      if (std::optional<uint64_t> ZExtSize = Size->tryZExtValue())
> +        return TypeSize::getFixed(*ZExtSize);
> +    }
> +    return std::nullopt;
> +  }
> +
> +  return std::nullopt;
> +}
> +
>  Value *llvm::lowerObjectSizeCall(IntrinsicInst *ObjectSize,
>                                   const DataLayout &DL,
>                                   const TargetLibraryInfo *TLI,
> 
> 
>         
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list