2525#include " llvm/IR/Constants.h"
2626#include " llvm/IR/DataLayout.h"
2727#include " llvm/IR/DerivedTypes.h"
28+ #include " llvm/IR/Dominators.h"
2829#include " llvm/IR/Function.h"
2930#include " llvm/IR/GlobalAlias.h"
3031#include " llvm/IR/GlobalVariable.h"
@@ -589,19 +590,28 @@ Value *llvm::lowerObjectSizeCall(IntrinsicInst *ObjectSize,
589590 const TargetLibraryInfo *TLI,
590591 bool MustSucceed) {
591592 return lowerObjectSizeCall (ObjectSize, DL, TLI, /* AAResults=*/ nullptr ,
592- MustSucceed);
593+ /* DT= */ nullptr , MustSucceed);
593594}
594595
595596Value *llvm::lowerObjectSizeCall (
596597 IntrinsicInst *ObjectSize, const DataLayout &DL,
597598 const TargetLibraryInfo *TLI, AAResults *AA, bool MustSucceed,
598599 SmallVectorImpl<Instruction *> *InsertedInstructions) {
600+ return lowerObjectSizeCall (ObjectSize, DL, TLI, AA, /* DT=*/ nullptr ,
601+ MustSucceed, InsertedInstructions);
602+ }
603+
604+ Value *llvm::lowerObjectSizeCall (
605+ IntrinsicInst *ObjectSize, const DataLayout &DL,
606+ const TargetLibraryInfo *TLI, AAResults *AA, DominatorTree *DT,
607+ bool MustSucceed, SmallVectorImpl<Instruction *> *InsertedInstructions) {
599608 assert (ObjectSize->getIntrinsicID () == Intrinsic::objectsize &&
600609 " ObjectSize must be a call to llvm.objectsize!" );
601610
602611 bool MaxVal = cast<ConstantInt>(ObjectSize->getArgOperand (1 ))->isZero ();
603612 ObjectSizeOpts EvalOptions;
604613 EvalOptions.AA = AA;
614+ EvalOptions.DT = DT;
605615
606616 // Unless we have to fold this to something, try to be as accurate as
607617 // possible.
@@ -708,14 +718,46 @@ OffsetSpan ObjectSizeOffsetVisitor::computeImpl(Value *V) {
708718 // readjust the APInt as we pass it upwards in order for the APInt to match
709719 // the type the caller passed in.
710720 APInt Offset (InitialIntTyBits, 0 );
721+
722+ // External Analysis used to compute the Min/Max value of individual Offsets
723+ // within a GEP.
724+ auto OffsetRangeAnalysis = [this , V](Value &VOffset, APInt &Offset) {
725+ if (auto *C = dyn_cast<ConstantInt>(&VOffset)) {
726+ Offset = C->getValue ();
727+ return true ;
728+ }
729+ if (Options.EvalMode != ObjectSizeOpts::Mode::Min &&
730+ Options.EvalMode != ObjectSizeOpts::Mode::Max) {
731+ return false ;
732+ }
733+ ConstantRange CR = computeConstantRange (
734+ &VOffset, /* ForSigned*/ true , /* UseInstrInfo*/ true , /* AC=*/ nullptr ,
735+ /* CtxtI=*/ dyn_cast<Instruction>(V), /* DT=*/ Options.DT );
736+ if (CR.isFullSet ())
737+ return false ;
738+
739+ if (Options.EvalMode == ObjectSizeOpts::Mode::Min) {
740+ Offset = CR.getSignedMax ();
741+ // Upper bound actually unknown.
742+ if (Offset.isMaxSignedValue ())
743+ return false ;
744+ } else {
745+ Offset = CR.getSignedMin ();
746+ // Lower bound actually unknown.
747+ if (Offset.isMinSignedValue ())
748+ return false ;
749+ }
750+ return true ;
751+ };
752+
711753 V = V->stripAndAccumulateConstantOffsets (
712- DL, Offset, /* AllowNonInbounds */ true , /* AllowInvariantGroup */ true );
754+ DL, Offset, /* AllowNonInbounds */ true , /* AllowInvariantGroup */ true ,
755+ /* ExternalAnalysis=*/ OffsetRangeAnalysis);
713756
714757 // Later we use the index type size and zero but it will match the type of the
715758 // value that is passed to computeImpl.
716759 IntTyBits = DL.getIndexTypeSizeInBits (V->getType ());
717760 Zero = APInt::getZero (IntTyBits);
718-
719761 OffsetSpan ORT = computeValue (V);
720762
721763 bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits;
@@ -793,6 +835,26 @@ OffsetSpan ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) {
793835 Size = Size.umul_ov (NumElems, Overflow);
794836 return Overflow ? ObjectSizeOffsetVisitor::unknown ()
795837 : OffsetSpan (Zero, align (Size, I.getAlign ()));
838+ } else {
839+ ConstantRange CR =
840+ computeConstantRange (ArraySize, /* ForSigned*/ false ,
841+ /* UseInstrInfo*/ true , /* AC=*/ nullptr ,
842+ /* CtxtI=*/ &I, /* DT=*/ Options.DT );
843+ if (CR.isFullSet ())
844+ return ObjectSizeOffsetVisitor::unknown ();
845+ APInt Bound;
846+ if (Options.EvalMode == ObjectSizeOpts::Mode::Max) {
847+ Bound = CR.getUnsignedMax ();
848+ // Upper bound actually unknown.
849+ if (Bound.isMaxValue ())
850+ return ObjectSizeOffsetVisitor::unknown ();
851+ } else {
852+ Bound = CR.getUnsignedMin ();
853+ // Lower bound actually unknown.
854+ if (Bound.isMinValue ())
855+ return ObjectSizeOffsetVisitor::unknown ();
856+ }
857+ return OffsetSpan (Zero, align (Bound, I.getAlign ()));
796858 }
797859 return ObjectSizeOffsetVisitor::unknown ();
798860}
@@ -810,7 +872,32 @@ OffsetSpan ObjectSizeOffsetVisitor::visitArgument(Argument &A) {
810872}
811873
812874OffsetSpan ObjectSizeOffsetVisitor::visitCallBase (CallBase &CB) {
813- if (std::optional<APInt> Size = getAllocSize (&CB, TLI))
875+ if (std::optional<APInt> Size =
876+ getAllocSize (&CB, TLI, [&CB, this ](const Value *V) -> const Value * {
877+ if (!V->getType ()->isIntegerTy ())
878+ return V;
879+ if (isa<ConstantInt>(V))
880+ return V;
881+ ConstantRange CR = computeConstantRange (
882+ V, /* ForSigned*/ false , /* UseInstrInfo*/ true , /* AC=*/ nullptr ,
883+ /* CtxtI=*/ &CB, /* DT=*/ Options.DT );
884+ if (CR.isFullSet ())
885+ return V;
886+
887+ APInt Bound;
888+ if (Options.EvalMode == ObjectSizeOpts::Mode::Max) {
889+ Bound = CR.getUnsignedMax ();
890+ // Upper bound actually unknown.
891+ if (Bound.isMaxValue ())
892+ return V;
893+ } else {
894+ Bound = CR.getUnsignedMin ();
895+ // Lower bound actually unknown.
896+ if (Bound.isMinValue ())
897+ return V;
898+ }
899+ return ConstantInt::get (V->getType (), Bound);
900+ }))
814901 return OffsetSpan (Zero, *Size);
815902 return ObjectSizeOffsetVisitor::unknown ();
816903}
0 commit comments