@@ -879,6 +879,26 @@ struct DSEState {
879
879
CodeMetrics::collectEphemeralValues (&F, &AC, EphValues);
880
880
}
881
881
882
+ LocationSize strengthenLocationSize (const Instruction *I,
883
+ LocationSize Size) const {
884
+ if (auto *CB = dyn_cast<CallBase>(I)) {
885
+ LibFunc F;
886
+ if (TLI.getLibFunc (*CB, F) && TLI.has (F) && F == LibFunc_memset_chk) {
887
+ // Use the precise location size specified by the 3rd argument
888
+ // for determining KillingI overwrites DeadLoc if it is a memset_chk
889
+ // instruction. memset_chk will write either the amount specified as 3rd
890
+ // argument or the function will immediately abort and exit the program.
891
+ // NOTE: AA may determine NoAlias if it can prove that the access size
892
+ // is larger than the allocation size due to that being UB. To avoid
893
+ // returning potentially invalid NoAlias results by AA, limit the use of
894
+ // the precise location size to isOverwrite.
895
+ if (const auto *Len = dyn_cast<ConstantInt>(CB->getArgOperand (2 )))
896
+ return LocationSize::precise (Len->getZExtValue ());
897
+ }
898
+ }
899
+ return Size;
900
+ }
901
+
882
902
// / Return 'OW_Complete' if a store to the 'KillingLoc' location (by \p
883
903
// / KillingI instruction) completely overwrites a store to the 'DeadLoc'
884
904
// / location (by \p DeadI instruction).
@@ -898,23 +918,25 @@ struct DSEState {
898
918
if (!isGuaranteedLoopIndependent (DeadI, KillingI, DeadLoc))
899
919
return OW_Unknown;
900
920
921
+ LocationSize KillingLocSize =
922
+ strengthenLocationSize (KillingI, KillingLoc.Size );
901
923
const Value *DeadPtr = DeadLoc.Ptr ->stripPointerCasts ();
902
924
const Value *KillingPtr = KillingLoc.Ptr ->stripPointerCasts ();
903
925
const Value *DeadUndObj = getUnderlyingObject (DeadPtr);
904
926
const Value *KillingUndObj = getUnderlyingObject (KillingPtr);
905
927
906
928
// Check whether the killing store overwrites the whole object, in which
907
929
// case the size/offset of the dead store does not matter.
908
- if (DeadUndObj == KillingUndObj && KillingLoc. Size .isPrecise ()) {
930
+ if (DeadUndObj == KillingUndObj && KillingLocSize .isPrecise ()) {
909
931
uint64_t KillingUndObjSize = getPointerSize (KillingUndObj, DL, TLI, &F);
910
932
if (KillingUndObjSize != MemoryLocation::UnknownSize &&
911
- KillingUndObjSize == KillingLoc. Size .getValue ())
933
+ KillingUndObjSize == KillingLocSize .getValue ())
912
934
return OW_Complete;
913
935
}
914
936
915
937
// FIXME: Vet that this works for size upper-bounds. Seems unlikely that we'll
916
938
// get imprecise values here, though (except for unknown sizes).
917
- if (!KillingLoc. Size .isPrecise () || !DeadLoc.Size .isPrecise ()) {
939
+ if (!KillingLocSize .isPrecise () || !DeadLoc.Size .isPrecise ()) {
918
940
// In case no constant size is known, try to an IR values for the number
919
941
// of bytes written and check if they match.
920
942
const auto *KillingMemI = dyn_cast<MemIntrinsic>(KillingI);
@@ -931,7 +953,7 @@ struct DSEState {
931
953
return isMaskedStoreOverwrite (KillingI, DeadI, BatchAA);
932
954
}
933
955
934
- const uint64_t KillingSize = KillingLoc. Size .getValue ();
956
+ const uint64_t KillingSize = KillingLocSize .getValue ();
935
957
const uint64_t DeadSize = DeadLoc.Size .getValue ();
936
958
937
959
// Query the alias information
0 commit comments