25
25
#include " llvm/IR/Constants.h"
26
26
#include " llvm/IR/DataLayout.h"
27
27
#include " llvm/IR/DerivedTypes.h"
28
+ #include " llvm/IR/Dominators.h"
28
29
#include " llvm/IR/Function.h"
29
30
#include " llvm/IR/GlobalAlias.h"
30
31
#include " llvm/IR/GlobalVariable.h"
@@ -589,19 +590,28 @@ Value *llvm::lowerObjectSizeCall(IntrinsicInst *ObjectSize,
589
590
const TargetLibraryInfo *TLI,
590
591
bool MustSucceed) {
591
592
return lowerObjectSizeCall (ObjectSize, DL, TLI, /* AAResults=*/ nullptr ,
592
- MustSucceed);
593
+ /* DT= */ nullptr , MustSucceed);
593
594
}
594
595
595
596
Value *llvm::lowerObjectSizeCall (
596
597
IntrinsicInst *ObjectSize, const DataLayout &DL,
597
598
const TargetLibraryInfo *TLI, AAResults *AA, bool MustSucceed,
598
599
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) {
599
608
assert (ObjectSize->getIntrinsicID () == Intrinsic::objectsize &&
600
609
" ObjectSize must be a call to llvm.objectsize!" );
601
610
602
611
bool MaxVal = cast<ConstantInt>(ObjectSize->getArgOperand (1 ))->isZero ();
603
612
ObjectSizeOpts EvalOptions;
604
613
EvalOptions.AA = AA;
614
+ EvalOptions.DT = DT;
605
615
606
616
// Unless we have to fold this to something, try to be as accurate as
607
617
// possible.
@@ -708,14 +718,46 @@ OffsetSpan ObjectSizeOffsetVisitor::computeImpl(Value *V) {
708
718
// readjust the APInt as we pass it upwards in order for the APInt to match
709
719
// the type the caller passed in.
710
720
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
+
711
753
V = V->stripAndAccumulateConstantOffsets (
712
- DL, Offset, /* AllowNonInbounds */ true , /* AllowInvariantGroup */ true );
754
+ DL, Offset, /* AllowNonInbounds */ true , /* AllowInvariantGroup */ true ,
755
+ /* ExternalAnalysis=*/ OffsetRangeAnalysis);
713
756
714
757
// Later we use the index type size and zero but it will match the type of the
715
758
// value that is passed to computeImpl.
716
759
IntTyBits = DL.getIndexTypeSizeInBits (V->getType ());
717
760
Zero = APInt::getZero (IntTyBits);
718
-
719
761
OffsetSpan ORT = computeValue (V);
720
762
721
763
bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits;
@@ -793,6 +835,26 @@ OffsetSpan ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) {
793
835
Size = Size .umul_ov (NumElems, Overflow);
794
836
return Overflow ? ObjectSizeOffsetVisitor::unknown ()
795
837
: 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 ()));
796
858
}
797
859
return ObjectSizeOffsetVisitor::unknown ();
798
860
}
@@ -810,7 +872,32 @@ OffsetSpan ObjectSizeOffsetVisitor::visitArgument(Argument &A) {
810
872
}
811
873
812
874
OffsetSpan 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
+ }))
814
901
return OffsetSpan (Zero, *Size );
815
902
return ObjectSizeOffsetVisitor::unknown ();
816
903
}
0 commit comments