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