@@ -834,6 +834,26 @@ struct DSEState {
834
834
CodeMetrics::collectEphemeralValues (&F, &AC, EphValues);
835
835
}
836
836
837
+ LocationSize strengthenLocationSize (const Instruction *I,
838
+ LocationSize Size) const {
839
+ if (auto *CB = dyn_cast<CallBase>(I)) {
840
+ LibFunc F;
841
+ if (TLI.getLibFunc (*CB, F) && TLI.has (F) && F == LibFunc_memset_chk) {
842
+ // Use the precise location size specified by the 3rd argument
843
+ // for determining KillingI overwrites DeadLoc if it is a memset_chk
844
+ // instruction. memset_chk will write either the amount specified as 3rd
845
+ // argument or the function will immediately abort and exit the program.
846
+ // NOTE: AA may determine NoAlias if it can prove that the access size
847
+ // is larger than the allocation size due to that being UB. To avoid
848
+ // returning potentially invalid NoAlias results by AA, limit the use of
849
+ // the precise location size to isOverwrite.
850
+ if (const auto *Len = dyn_cast<ConstantInt>(CB->getArgOperand (2 )))
851
+ return LocationSize::precise (Len->getZExtValue ());
852
+ }
853
+ }
854
+ return Size;
855
+ }
856
+
837
857
// / Return 'OW_Complete' if a store to the 'KillingLoc' location (by \p
838
858
// / KillingI instruction) completely overwrites a store to the 'DeadLoc'
839
859
// / location (by \p DeadI instruction).
@@ -853,23 +873,25 @@ struct DSEState {
853
873
if (!isGuaranteedLoopIndependent (DeadI, KillingI, DeadLoc))
854
874
return OW_Unknown;
855
875
876
+ LocationSize KillingLocSize =
877
+ strengthenLocationSize (KillingI, KillingLoc.Size );
856
878
const Value *DeadPtr = DeadLoc.Ptr ->stripPointerCasts ();
857
879
const Value *KillingPtr = KillingLoc.Ptr ->stripPointerCasts ();
858
880
const Value *DeadUndObj = getUnderlyingObject (DeadPtr);
859
881
const Value *KillingUndObj = getUnderlyingObject (KillingPtr);
860
882
861
883
// Check whether the killing store overwrites the whole object, in which
862
884
// case the size/offset of the dead store does not matter.
863
- if (DeadUndObj == KillingUndObj && KillingLoc. Size .isPrecise ()) {
885
+ if (DeadUndObj == KillingUndObj && KillingLocSize .isPrecise ()) {
864
886
uint64_t KillingUndObjSize = getPointerSize (KillingUndObj, DL, TLI, &F);
865
887
if (KillingUndObjSize != MemoryLocation::UnknownSize &&
866
- KillingUndObjSize == KillingLoc. Size .getValue ())
888
+ KillingUndObjSize == KillingLocSize .getValue ())
867
889
return OW_Complete;
868
890
}
869
891
870
892
// FIXME: Vet that this works for size upper-bounds. Seems unlikely that we'll
871
893
// get imprecise values here, though (except for unknown sizes).
872
- if (!KillingLoc. Size .isPrecise () || !DeadLoc.Size .isPrecise ()) {
894
+ if (!KillingLocSize .isPrecise () || !DeadLoc.Size .isPrecise ()) {
873
895
// In case no constant size is known, try to an IR values for the number
874
896
// of bytes written and check if they match.
875
897
const auto *KillingMemI = dyn_cast<MemIntrinsic>(KillingI);
@@ -886,7 +908,7 @@ struct DSEState {
886
908
return isMaskedStoreOverwrite (KillingI, DeadI, BatchAA);
887
909
}
888
910
889
- const uint64_t KillingSize = KillingLoc. Size .getValue ();
911
+ const uint64_t KillingSize = KillingLocSize .getValue ();
890
912
const uint64_t DeadSize = DeadLoc.Size .getValue ();
891
913
892
914
// Query the alias information
0 commit comments