1616#include " llvm/ADT/STLExtras.h"
1717#include " llvm/ADT/Statistic.h"
1818#include " llvm/Analysis/AliasAnalysis.h"
19+ #include " llvm/Analysis/AssumptionCache.h"
1920#include " llvm/Analysis/TargetFolder.h"
2021#include " llvm/Analysis/TargetLibraryInfo.h"
2122#include " llvm/Analysis/Utils/Local.h"
2526#include " llvm/IR/Constants.h"
2627#include " llvm/IR/DataLayout.h"
2728#include " llvm/IR/DerivedTypes.h"
29+ #include " llvm/IR/Dominators.h"
2830#include " llvm/IR/Function.h"
2931#include " llvm/IR/GlobalAlias.h"
3032#include " llvm/IR/GlobalVariable.h"
@@ -590,19 +592,31 @@ Value *llvm::lowerObjectSizeCall(IntrinsicInst *ObjectSize,
590592 const TargetLibraryInfo *TLI,
591593 bool MustSucceed) {
592594 return lowerObjectSizeCall (ObjectSize, DL, TLI, /* AAResults=*/ nullptr ,
593- MustSucceed);
595+ /* DT=*/ nullptr ,
596+ /* AC=*/ nullptr , MustSucceed);
594597}
595598
596599Value *llvm::lowerObjectSizeCall (
597600 IntrinsicInst *ObjectSize, const DataLayout &DL,
598601 const TargetLibraryInfo *TLI, AAResults *AA, bool MustSucceed,
599602 SmallVectorImpl<Instruction *> *InsertedInstructions) {
603+ return lowerObjectSizeCall (ObjectSize, DL, TLI, AA, /* DT=*/ nullptr ,
604+ /* AC=*/ nullptr , MustSucceed, InsertedInstructions);
605+ }
606+
607+ Value *llvm::lowerObjectSizeCall (
608+ IntrinsicInst *ObjectSize, const DataLayout &DL,
609+ const TargetLibraryInfo *TLI, AAResults *AA, DominatorTree *DT,
610+ AssumptionCache *AC, bool MustSucceed,
611+ SmallVectorImpl<Instruction *> *InsertedInstructions) {
600612 assert (ObjectSize->getIntrinsicID () == Intrinsic::objectsize &&
601613 " ObjectSize must be a call to llvm.objectsize!" );
602614
603615 bool MaxVal = cast<ConstantInt>(ObjectSize->getArgOperand (1 ))->isZero ();
604616 ObjectSizeOpts EvalOptions;
605617 EvalOptions.AA = AA;
618+ EvalOptions.DT = DT;
619+ EvalOptions.AC = AC;
606620
607621 // Unless we have to fold this to something, try to be as accurate as
608622 // possible.
@@ -716,7 +730,6 @@ OffsetSpan ObjectSizeOffsetVisitor::computeImpl(Value *V) {
716730 // value that is passed to computeImpl.
717731 IntTyBits = DL.getIndexTypeSizeInBits (V->getType ());
718732 Zero = APInt::getZero (IntTyBits);
719-
720733 OffsetSpan ORT = computeValue (V);
721734
722735 bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits;
@@ -794,6 +807,26 @@ OffsetSpan ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) {
794807 Size = Size.umul_ov (NumElems, Overflow);
795808 return Overflow ? ObjectSizeOffsetVisitor::unknown ()
796809 : OffsetSpan (Zero, align (Size, I.getAlign ()));
810+ } else {
811+ ConstantRange CR = computeConstantRange (ArraySize, /* ForSigned*/ false ,
812+ /* UseInstrInfo*/ true ,
813+ /* AssumptionCache=*/ Options.AC ,
814+ /* CtxtI=*/ &I, /* DT=*/ Options.DT );
815+ if (CR.isFullSet ())
816+ return ObjectSizeOffsetVisitor::unknown ();
817+ APInt Bound;
818+ if (Options.EvalMode == ObjectSizeOpts::Mode::Max) {
819+ Bound = CR.getUnsignedMax ();
820+ // Upper bound actually unknown.
821+ if (Bound.isMaxValue ())
822+ return ObjectSizeOffsetVisitor::unknown ();
823+ } else {
824+ Bound = CR.getUnsignedMin ();
825+ // Lower bound actually unknown.
826+ if (Bound.isMinValue ())
827+ return ObjectSizeOffsetVisitor::unknown ();
828+ }
829+ return OffsetSpan (Zero, align (Bound, I.getAlign ()));
797830 }
798831 return ObjectSizeOffsetVisitor::unknown ();
799832}
@@ -811,7 +844,31 @@ OffsetSpan ObjectSizeOffsetVisitor::visitArgument(Argument &A) {
811844}
812845
813846OffsetSpan ObjectSizeOffsetVisitor::visitCallBase (CallBase &CB) {
814- if (std::optional<APInt> Size = getAllocSize (&CB, TLI))
847+ if (std::optional<APInt> Size =
848+ getAllocSize (&CB, TLI, [&CB, this ](const Value *V) -> const Value * {
849+ if (!V->getType ()->isIntegerTy ())
850+ return V;
851+ ConstantRange CR = computeConstantRange (
852+ V, /* ForSigned*/ false , /* UseInstrInfo*/ true ,
853+ /* AssumptionCache=*/ Options.AC ,
854+ /* CtxtI=*/ &CB, /* DT=*/ Options.DT );
855+ if (CR.isFullSet ())
856+ return V;
857+
858+ APInt Bound;
859+ if (Options.EvalMode == ObjectSizeOpts::Mode::Max) {
860+ Bound = CR.getUnsignedMax ();
861+ // Upper bound actually unknown.
862+ if (Bound.isMaxValue ())
863+ return V;
864+ } else {
865+ Bound = CR.getUnsignedMin ();
866+ // Lower bound actually unknown.
867+ if (Bound.isMinValue ())
868+ return V;
869+ }
870+ return ConstantInt::get (V->getType (), Bound);
871+ }))
815872 return OffsetSpan (Zero, *Size);
816873 return ObjectSizeOffsetVisitor::unknown ();
817874}
@@ -856,6 +913,49 @@ OffsetSpan ObjectSizeOffsetVisitor::visitGlobalVariable(GlobalVariable &GV) {
856913 return OffsetSpan (Zero, align (Size, GV.getAlign ()));
857914}
858915
916+ OffsetSpan ObjectSizeOffsetVisitor::visitGetElementPtr (GetElementPtrInst &GEP) {
917+ OffsetSpan PtrData = computeImpl (GEP.getPointerOperand ());
918+ if (!PtrData.bothKnown ())
919+ return ObjectSizeOffsetVisitor::unknown ();
920+
921+ if (Options.EvalMode == ObjectSizeOpts::Mode::Min ||
922+ Options.EvalMode == ObjectSizeOpts::Mode::Max) {
923+ unsigned BitWidth = PtrData.After .getBitWidth ();
924+ APInt ConstantOffset = Zero;
925+ SmallMapVector<Value *, APInt, 4 > VariableOffsets;
926+ if (!GEP.collectOffset (DL, BitWidth, VariableOffsets, ConstantOffset))
927+ return ObjectSizeOffsetVisitor::unknown ();
928+
929+ ConstantRange AccumulatedRange = ConstantOffset;
930+ for (auto const &VO : VariableOffsets) {
931+ ConstantRange CR = computeConstantRange (
932+ VO.first , /* ForSigned*/ true , /* UseInstrInfo*/ true ,
933+ /* AssumptionCache=*/ Options.AC ,
934+ /* CtxtI=*/ &GEP, /* DT=*/ Options.DT );
935+ if (CR.isFullSet ())
936+ return ObjectSizeOffsetVisitor::unknown ();
937+
938+ AccumulatedRange = AccumulatedRange.add (CR.multiply (VO.second ));
939+ }
940+
941+ APInt Bound;
942+ if (Options.EvalMode == ObjectSizeOpts::Mode::Min) {
943+ Bound = AccumulatedRange.getSignedMax ();
944+ // Upper bound actually unknown.
945+ if (Bound.isMaxSignedValue ())
946+ return ObjectSizeOffsetVisitor::unknown ();
947+ } else {
948+ Bound = AccumulatedRange.getSignedMin ();
949+ // Lower bound actually unknown.
950+ if (Bound.isMinSignedValue ())
951+ return ObjectSizeOffsetVisitor::unknown ();
952+ }
953+
954+ return {PtrData.Before + Bound, PtrData.After - Bound};
955+ }
956+ return ObjectSizeOffsetVisitor::unknown ();
957+ }
958+
859959OffsetSpan ObjectSizeOffsetVisitor::visitIntToPtrInst (IntToPtrInst &) {
860960 // clueless
861961 return ObjectSizeOffsetVisitor::unknown ();
0 commit comments