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.
@@ -714,14 +724,54 @@ OffsetSpan ObjectSizeOffsetVisitor::computeImpl(Value *V) {
714
724
// readjust the APInt as we pass it upwards in order for the APInt to match
715
725
// the type the caller passed in.
716
726
APInt Offset (InitialIntTyBits, 0 );
727
+
717
728
V = V->stripAndAccumulateConstantOffsets (
718
729
DL, Offset, /* AllowNonInbounds */ true , /* AllowInvariantGroup */ true );
719
730
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<GetElementPtrInst>(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
+
720
771
// Later we use the index type size and zero but it will match the type of the
721
772
// value that is passed to computeImpl.
722
773
IntTyBits = DL.getIndexTypeSizeInBits (V->getType ());
723
774
Zero = APInt::getZero (IntTyBits);
724
-
725
775
OffsetSpan ORT = computeValue (V);
726
776
727
777
bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits;
@@ -801,6 +851,26 @@ OffsetSpan ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) {
801
851
802
852
return Overflow ? ObjectSizeOffsetVisitor::unknown ()
803
853
: 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 ()));
804
874
}
805
875
return ObjectSizeOffsetVisitor::unknown ();
806
876
}
@@ -818,7 +888,32 @@ OffsetSpan ObjectSizeOffsetVisitor::visitArgument(Argument &A) {
818
888
}
819
889
820
890
OffsetSpan 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)) {
822
917
// Very large unsigned value cannot be represented as OffsetSpan.
823
918
if (Size->isNegative ())
824
919
return ObjectSizeOffsetVisitor::unknown ();
0 commit comments