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"
@@ -590,19 +591,28 @@ Value *llvm::lowerObjectSizeCall(IntrinsicInst *ObjectSize,
590591 const TargetLibraryInfo *TLI,
591592 bool MustSucceed) {
592593 return lowerObjectSizeCall (ObjectSize, DL, TLI, /* AAResults=*/ nullptr ,
593- MustSucceed);
594+ /* DT= */ nullptr , MustSucceed);
594595}
595596
596597Value *llvm::lowerObjectSizeCall (
597598 IntrinsicInst *ObjectSize, const DataLayout &DL,
598599 const TargetLibraryInfo *TLI, AAResults *AA, bool MustSucceed,
599600 SmallVectorImpl<Instruction *> *InsertedInstructions) {
601+ return lowerObjectSizeCall (ObjectSize, DL, TLI, AA, /* DT=*/ nullptr ,
602+ MustSucceed, InsertedInstructions);
603+ }
604+
605+ Value *llvm::lowerObjectSizeCall (
606+ IntrinsicInst *ObjectSize, const DataLayout &DL,
607+ const TargetLibraryInfo *TLI, AAResults *AA, DominatorTree *DT,
608+ bool MustSucceed, SmallVectorImpl<Instruction *> *InsertedInstructions) {
600609 assert (ObjectSize->getIntrinsicID () == Intrinsic::objectsize &&
601610 " ObjectSize must be a call to llvm.objectsize!" );
602611
603612 bool MaxVal = cast<ConstantInt>(ObjectSize->getArgOperand (1 ))->isZero ();
604613 ObjectSizeOpts EvalOptions;
605614 EvalOptions.AA = AA;
615+ EvalOptions.DT = DT;
606616
607617 // Unless we have to fold this to something, try to be as accurate as
608618 // possible.
@@ -709,14 +719,47 @@ OffsetSpan ObjectSizeOffsetVisitor::computeImpl(Value *V) {
709719 // readjust the APInt as we pass it upwards in order for the APInt to match
710720 // the type the caller passed in.
711721 APInt Offset (InitialIntTyBits, 0 );
722+
723+ // External Analysis used to compute the Min/Max value of individual Offsets
724+ // within a GEP.
725+ auto OffsetRangeAnalysis =
726+ [this , V](Value &VOffset, APInt &Offset) {
727+ if (auto *C = dyn_cast<ConstantInt>(&VOffset)) {
728+ Offset = C->getValue ();
729+ return true ;
730+ }
731+ if (Options.EvalMode != ObjectSizeOpts::Mode::Min &&
732+ Options.EvalMode != ObjectSizeOpts::Mode::Max) {
733+ return false ;
734+ }
735+ ConstantRange CR = computeConstantRange (
736+ &VOffset, /* ForSigned*/ true , /* UseInstrInfo*/ true , /* AC=*/ nullptr ,
737+ /* CtxtI=*/ dyn_cast<Instruction>(V), /* DT=*/ Options.DT );
738+ if (CR.isFullSet ())
739+ return false ;
740+
741+ if (Options.EvalMode == ObjectSizeOpts::Mode::Min) {
742+ Offset = CR.getSignedMax ();
743+ // Upper bound actually unknown.
744+ if (Offset.isMaxSignedValue ())
745+ return false ;
746+ } else {
747+ Offset = CR.getSignedMin ();
748+ // Lower bound actually unknown.
749+ if (Offset.isMinSignedValue ())
750+ return false ;
751+ }
752+ return true ;
753+ };
754+
712755 V = V->stripAndAccumulateConstantOffsets (
713- DL, Offset, /* AllowNonInbounds */ true , /* AllowInvariantGroup */ true );
756+ DL, Offset, /* AllowNonInbounds */ true , /* AllowInvariantGroup */ true ,
757+ /* ExternalAnalysis=*/ OffsetRangeAnalysis);
714758
715759 // Later we use the index type size and zero but it will match the type of the
716760 // value that is passed to computeImpl.
717761 IntTyBits = DL.getIndexTypeSizeInBits (V->getType ());
718762 Zero = APInt::getZero (IntTyBits);
719-
720763 OffsetSpan ORT = computeValue (V);
721764
722765 bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits;
@@ -794,6 +837,26 @@ OffsetSpan ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) {
794837 Size = Size.umul_ov (NumElems, Overflow);
795838 return Overflow ? ObjectSizeOffsetVisitor::unknown ()
796839 : OffsetSpan (Zero, align (Size, I.getAlign ()));
840+ } else {
841+ ConstantRange CR =
842+ computeConstantRange (ArraySize, /* ForSigned*/ false ,
843+ /* UseInstrInfo*/ true , /* AC=*/ nullptr ,
844+ /* CtxtI=*/ &I, /* DT=*/ Options.DT );
845+ if (CR.isFullSet ())
846+ return ObjectSizeOffsetVisitor::unknown ();
847+ APInt Bound;
848+ if (Options.EvalMode == ObjectSizeOpts::Mode::Max) {
849+ Bound = CR.getUnsignedMax ();
850+ // Upper bound actually unknown.
851+ if (Bound.isMaxValue ())
852+ return ObjectSizeOffsetVisitor::unknown ();
853+ } else {
854+ Bound = CR.getUnsignedMin ();
855+ // Lower bound actually unknown.
856+ if (Bound.isMinValue ())
857+ return ObjectSizeOffsetVisitor::unknown ();
858+ }
859+ return OffsetSpan (Zero, align (Bound, I.getAlign ()));
797860 }
798861 return ObjectSizeOffsetVisitor::unknown ();
799862}
@@ -811,7 +874,32 @@ OffsetSpan ObjectSizeOffsetVisitor::visitArgument(Argument &A) {
811874}
812875
813876OffsetSpan ObjectSizeOffsetVisitor::visitCallBase (CallBase &CB) {
814- if (std::optional<APInt> Size = getAllocSize (&CB, TLI))
877+ if (std::optional<APInt> Size =
878+ getAllocSize (&CB, TLI, [&CB, this ](const Value *V) -> const Value * {
879+ if (!V->getType ()->isIntegerTy ())
880+ return V;
881+ if (isa<ConstantInt>(V))
882+ return V;
883+ ConstantRange CR = computeConstantRange (
884+ V, /* ForSigned*/ false , /* UseInstrInfo*/ true , /* AC=*/ nullptr ,
885+ /* CtxtI=*/ &CB, /* DT=*/ Options.DT );
886+ if (CR.isFullSet ())
887+ return V;
888+
889+ APInt Bound;
890+ if (Options.EvalMode == ObjectSizeOpts::Mode::Max) {
891+ Bound = CR.getUnsignedMax ();
892+ // Upper bound actually unknown.
893+ if (Bound.isMaxValue ())
894+ return V;
895+ } else {
896+ Bound = CR.getUnsignedMin ();
897+ // Lower bound actually unknown.
898+ if (Bound.isMinValue ())
899+ return V;
900+ }
901+ return ConstantInt::get (V->getType (), Bound);
902+ }))
815903 return OffsetSpan (Zero, *Size);
816904 return ObjectSizeOffsetVisitor::unknown ();
817905}
0 commit comments