diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -944,10 +944,20 @@ /// case, use isPartialOverwrite to check if \p Later partially overwrites /// \p Earlier. Returns 'OR_None' if later is known to not overwrite the /// earlier. 'OW_Unknown' if nothing can be determined. - OverwriteResult - isOverwrite(const Instruction *LaterI, const Instruction *EarlierI, - const MemoryLocation &Later, const MemoryLocation &Earlier, - int64_t &EarlierOff, int64_t &LaterOff) { + /// + /// Parameters: + /// LaterI/EarlierI - Instructions accessing \p Later/Earlier memory + /// locations + /// Later/Earlier - Memory locations under question + /// EarlierOff/LaterOff [in, out] - On input, may provide initial offset of + /// access relative to Later/Earlier memory location. On output, if + /// returned value is not "OW_Unknown" will keep absolute offset of access + /// relative to some common base of Later and Earlier locations. + OverwriteResult isOverwrite(const Instruction *LaterI, + const Instruction *EarlierI, + const MemoryLocation &Later, + const MemoryLocation &Earlier, + int64_t &EarlierOff, int64_t &LaterOff) { // AliasAnalysis does not always account for loops. Limit overwrite checks // to dependencies for which we can guarantee they are independant of any // loops they are in. @@ -964,7 +974,8 @@ if (LaterMemI && EarlierMemI) { const Value *LaterV = LaterMemI->getLength(); const Value *EarlierV = EarlierMemI->getLength(); - if (LaterV == EarlierV && BatchAA.isMustAlias(Earlier, Later)) + if (LaterV == EarlierV && EarlierOff == LaterOff && + BatchAA.isMustAlias(Earlier, Later)) return OW_Complete; } @@ -979,23 +990,24 @@ // Query the alias information AliasResult AAR = BatchAA.alias(Later, Earlier); - // If the start pointers are the same, we just have to compare sizes to see if - // the later store was larger than the earlier store. - if (AAR == AliasResult::MustAlias) { - // Make sure that the Later size is >= the Earlier size. - if (LaterSize >= EarlierSize) - return OW_Complete; - } - + // If the start pointers are the same, it's enough to compare sizes and + // offsets to see if the later store fully overwrites the earlier one. // If we hit a partial alias we may have a full overwrite - if (AAR == AliasResult::PartialAlias && AAR.hasOffset()) { - int32_t Off = AAR.getOffset(); - if (Off >= 0 && (uint64_t)Off + EarlierSize <= LaterSize) + if (AAR == AliasResult::MustAlias || + (AAR == AliasResult::PartialAlias && AAR.hasOffset() && + AAR.getOffset() >= 0)) { + int64_t AdjEarlierOff = + EarlierOff + (AAR == AliasResult::PartialAlias ? AAR.getOffset() : 0); + // Make sure that the earlier access is "inside" the later one. + if (AdjEarlierOff >= LaterOff && + uint64_t(AdjEarlierOff - LaterOff) + EarlierSize <= LaterSize) { + EarlierOff = AdjEarlierOff; return OW_Complete; + } } - // Check to see if the later store is to the entire object (either a global, - // an alloca, or a byval/inalloca argument). If so, then it clearly + // Check to see if the later store is to the entire object (either a + // global, an alloca, or a byval/inalloca argument). If so, then it clearly // overwrites any other store to the same object. const Value *P1 = Earlier.Ptr->stripPointerCasts(); const Value *P2 = Later.Ptr->stripPointerCasts(); @@ -1013,14 +1025,18 @@ return OW_Complete; // Okay, we have stores to two completely different pointers. Try to - // decompose the pointer into a "base + constant_offset" form. If the base - // pointers are equal, then we can reason about the two stores. - EarlierOff = 0; - LaterOff = 0; - const Value *BP1 = GetPointerBaseWithConstantOffset(P1, EarlierOff, DL); - const Value *BP2 = GetPointerBaseWithConstantOffset(P2, LaterOff, DL); - - // If the base pointers still differ, we have two completely different stores. + // decompose the pointer into a "base + constant_offset" form. If the + // base pointers are equal, then we can reason about the two stores. + int64_t ExtraEarlierOff = 0; + int64_t ExtraLaterOff = 0; + const Value *BP1 = + GetPointerBaseWithConstantOffset(P1, ExtraEarlierOff, DL); + const Value *BP2 = GetPointerBaseWithConstantOffset(P2, ExtraLaterOff, DL); + EarlierOff += ExtraEarlierOff; + LaterOff += ExtraLaterOff; + + // If the base pointers still differ, we have two completely different + // stores. if (BP1 != BP2) return OW_Unknown; @@ -1040,12 +1056,12 @@ // Check if the earlier access starts "not before" the later one. if (EarlierOff >= LaterOff) { - // If the earlier access ends "not after" the later access then the earlier - // one is completely overwritten by the later one. + // If the earlier access ends "not after" the later access then the + // earlier one is completely overwritten by the later one. if (uint64_t(EarlierOff - LaterOff) + EarlierSize <= LaterSize) return OW_Complete; - // If start of the earlier access is "before" end of the later access then - // accesses overlap. + // If start of the earlier access is "before" end of the later access + // then accesses overlap. else if ((uint64_t)(EarlierOff - LaterOff) < LaterSize) return OW_MaybePartial; } @@ -1144,7 +1160,8 @@ if (CB->onlyAccessesInaccessibleMemory()) return false; - int64_t InstWriteOffset, DepWriteOffset; + int64_t InstWriteOffset = 0; + int64_t DepWriteOffset = 0; if (auto CC = getLocForWriteEx(UseInst)) return isOverwrite(UseInst, DefInst, *CC, DefLoc, DepWriteOffset, InstWriteOffset) == OW_Complete; @@ -1249,7 +1266,8 @@ const Value *LocUO = getUnderlyingObject(Loc.Ptr); return BatchAA.isMustAlias(TermLoc.Ptr, LocUO); } - int64_t InstWriteOffset, DepWriteOffset; + int64_t InstWriteOffset = 0; + int64_t DepWriteOffset = 0; return isOverwrite(MaybeTerm, AccessI, TermLoc, Loc, DepWriteOffset, InstWriteOffset) == OW_Complete; } @@ -1451,7 +1469,8 @@ if (!isMemTerminator(*CurrentLoc, CurrentI, KillingI)) continue; } else { - int64_t InstWriteOffset, DepWriteOffset; + int64_t InstWriteOffset = 0; + int64_t DepWriteOffset = 0; auto OR = isOverwrite(KillingI, CurrentI, DefLoc, *CurrentLoc, DepWriteOffset, InstWriteOffset); // If Current does not write to the same object as KillingDef, check @@ -1979,7 +1998,8 @@ MadeChange = true; } else { // Check if NI overwrites SI. - int64_t InstWriteOffset, DepWriteOffset; + int64_t InstWriteOffset = 0; + int64_t DepWriteOffset = 0; OverwriteResult OR = State.isOverwrite(SI, NI, SILoc, NILoc, DepWriteOffset, InstWriteOffset); if (OR == OW_MaybePartial) {