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.
@@ -714,14 +724,54 @@ OffsetSpan ObjectSizeOffsetVisitor::computeImpl(Value *V) {
714724 // readjust the APInt as we pass it upwards in order for the APInt to match
715725 // the type the caller passed in.
716726 APInt Offset (InitialIntTyBits, 0 );
727+
717728 V = V->stripAndAccumulateConstantOffsets (
718729 DL, Offset, /* AllowNonInbounds */ true , /* AllowInvariantGroup */ true );
719730
731+ // Give it another try with approximated analysis. We don't start with this
732+ // one because stripAndAccumulateConstantOffsets behaves differently wrt.
733+ // overflows if we provide an external Analysis.
734+ if (isa<GEPOperator>(V)) {
735+ // External Analysis used to compute the Min/Max value of individual Offsets
736+ // within a GEP.
737+ auto OffsetRangeAnalysis = [this , V](Value &VOffset, APInt &Offset) {
738+ if (auto *C = dyn_cast<ConstantInt>(&VOffset)) {
739+ Offset = C->getValue ();
740+ return true ;
741+ }
742+ if (Options.EvalMode != ObjectSizeOpts::Mode::Min &&
743+ Options.EvalMode != ObjectSizeOpts::Mode::Max) {
744+ return false ;
745+ }
746+ ConstantRange CR = computeConstantRange (
747+ &VOffset, /* ForSigned*/ true , /* UseInstrInfo*/ true , /* AC=*/ nullptr ,
748+ /* CtxtI=*/ dyn_cast<Instruction>(V), /* DT=*/ Options.DT );
749+ if (CR.isFullSet ())
750+ return false ;
751+
752+ if (Options.EvalMode == ObjectSizeOpts::Mode::Min) {
753+ Offset = CR.getSignedMax ();
754+ // Upper bound actually unknown.
755+ if (Offset.isMaxSignedValue ())
756+ return false ;
757+ } else {
758+ Offset = CR.getSignedMin ();
759+ // Lower bound actually unknown.
760+ if (Offset.isMinSignedValue ())
761+ return false ;
762+ }
763+ return true ;
764+ };
765+
766+ V = V->stripAndAccumulateConstantOffsets (
767+ DL, Offset, /* AllowNonInbounds */ true , /* AllowInvariantGroup */ true ,
768+ /* ExternalAnalysis=*/ OffsetRangeAnalysis);
769+ }
770+
720771 // Later we use the index type size and zero but it will match the type of the
721772 // value that is passed to computeImpl.
722773 IntTyBits = DL.getIndexTypeSizeInBits (V->getType ());
723774 Zero = APInt::getZero (IntTyBits);
724-
725775 OffsetSpan ORT = computeValue (V);
726776
727777 bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits;
@@ -801,6 +851,26 @@ OffsetSpan ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) {
801851
802852 return Overflow ? ObjectSizeOffsetVisitor::unknown ()
803853 : OffsetSpan (Zero, alignAndCap (Size, I.getAlign ()));
854+ } else {
855+ ConstantRange CR =
856+ computeConstantRange (ArraySize, /* ForSigned*/ false ,
857+ /* UseInstrInfo*/ true , /* AC=*/ nullptr ,
858+ /* CtxtI=*/ &I, /* DT=*/ Options.DT );
859+ if (CR.isFullSet ())
860+ return ObjectSizeOffsetVisitor::unknown ();
861+ APInt Bound;
862+ if (Options.EvalMode == ObjectSizeOpts::Mode::Max) {
863+ Bound = CR.getUnsignedMax ();
864+ // Upper bound actually unknown.
865+ if (Bound.isMaxValue ())
866+ return ObjectSizeOffsetVisitor::unknown ();
867+ } else {
868+ Bound = CR.getUnsignedMin ();
869+ // Lower bound actually unknown.
870+ if (Bound.isMinValue ())
871+ return ObjectSizeOffsetVisitor::unknown ();
872+ }
873+ return OffsetSpan (Zero, alignAndCap (Bound, I.getAlign ()));
804874 }
805875 return ObjectSizeOffsetVisitor::unknown ();
806876}
@@ -818,7 +888,32 @@ OffsetSpan ObjectSizeOffsetVisitor::visitArgument(Argument &A) {
818888}
819889
820890OffsetSpan ObjectSizeOffsetVisitor::visitCallBase (CallBase &CB) {
821- if (std::optional<APInt> Size = getAllocSize (&CB, TLI)) {
891+ auto Mapper = [&CB, this ](const Value *V) -> const Value * {
892+ if (!V->getType ()->isIntegerTy ())
893+ return V;
894+ if (isa<ConstantInt>(V))
895+ return V;
896+ ConstantRange CR = computeConstantRange (
897+ V, /* ForSigned*/ false , /* UseInstrInfo*/ true , /* AC=*/ nullptr ,
898+ /* CtxtI=*/ &CB, /* DT=*/ Options.DT );
899+ if (CR.isFullSet ())
900+ return V;
901+
902+ APInt Bound;
903+ if (Options.EvalMode == ObjectSizeOpts::Mode::Max) {
904+ Bound = CR.getUnsignedMax ();
905+ // Upper bound actually unknown.
906+ if (Bound.isMaxValue ())
907+ return V;
908+ } else {
909+ Bound = CR.getUnsignedMin ();
910+ // Lower bound actually unknown.
911+ if (Bound.isMinValue ())
912+ return V;
913+ }
914+ return ConstantInt::get (V->getType (), Bound);
915+ };
916+ if (std::optional<APInt> Size = getAllocSize (&CB, TLI, Mapper)) {
822917 // Very large unsigned value cannot be represented as OffsetSpan.
823918 if (Size->isNegative ())
824919 return ObjectSizeOffsetVisitor::unknown ();
0 commit comments