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 @@ -873,11 +873,15 @@ auto CurrNode = WorkList.pop_back_val(); BasicBlock *CurrBB = CurrNode.first; const PhiTransPtr &CurrPtr = CurrNode.second; + int64_t Offset = 0; + Value *const BasePtr = + GetPointerBaseWithConstantOffset(CurrPtr.first, Offset, DL); + const int64_t BaseOffset = CurrPtr.second + Offset; for (pred_iterator PI = pred_begin(CurrBB), E = pred_end(CurrBB); PI != E; ++PI) { BasicBlock *PredBB = *PI; - PHITransAddr TransAddr{CurrPtr.first, DL, AC}; + PHITransAddr TransAddr{BasePtr, DL, AC}; // TODO: if (!DT.dominates(ToBB, PredBB)) @@ -889,11 +893,11 @@ return PhiTransPtr{}; auto Inserted = - Visited.try_emplace(PredBB, TransAddr.getAddr(), CurrPtr.second); + Visited.try_emplace(PredBB, TransAddr.getAddr(), BaseOffset); auto &TransPtr = Inserted.first->second; if (!Inserted.second) { if (TransAddr.getAddr() != TransPtr.first || - CurrPtr.second != TransPtr.second) + BaseOffset != TransPtr.second) // We already visited this block before. If it was with a different // address - bail out! return PhiTransPtr{}; @@ -911,8 +915,6 @@ assert(ResPtr.first.pointsToAliveValue() && "PHI translation is expected to complete successfully"); - assert(ResPtr.second == 0 && - "Unexpected non-zero offset during phi translation"); return ResPtr; } @@ -1039,6 +1041,14 @@ /// \p DeadI, but they both write to the same underlying object. In that /// case, use isPartialOverwrite to check if \p KillingI partially overwrites /// \p DeadI. Returns 'OW_Unknown' if nothing can be determined. + /// Parameters: + /// KillingI/DeadI - Instructions accessing \p KillingLoc/DeadLoc memory + /// locations + /// KillingLoc/DeadLoc - Memory locations under question + /// KillingOff/DeadOff [in, out] - On input, may provide initial offset of + /// access relative to KillingLoc/DeadLoc memory location. On output, if + /// returned value is not "OW_Unknown" will keep absolute offset of access + /// relative to some common base of KillingLoc and DeadLoc locations. OverwriteResult isOverwrite(const Instruction *KillingI, const Instruction *DeadI, const MemoryLocation &KillingLoc, @@ -1060,7 +1070,8 @@ if (KillingMemI && DeadMemI) { const Value *KillingV = KillingMemI->getLength(); const Value *DeadV = DeadMemI->getLength(); - if (KillingV == DeadV && BatchAA.isMustAlias(DeadLoc, KillingLoc)) + if (KillingV == DeadV && KillingOff == DeadOff && + BatchAA.isMustAlias(DeadLoc, KillingLoc)) return OW_Complete; } @@ -1075,19 +1086,19 @@ // Query the alias information AliasResult AAR = BatchAA.alias(KillingLoc, DeadLoc); - // If the start pointers are the same, we just have to compare sizes to see if - // the killing store was larger than the dead store. - if (AAR == AliasResult::MustAlias) { - // Make sure that the KillingSize size is >= the DeadSize size. - if (KillingSize >= DeadSize) - return OW_Complete; - } - - // 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 + DeadSize <= KillingSize) + // If the start pointers are the same, it's enough to compare sizes and + // offsets to see if the killing store fully overwrites the dead one. + if (AAR == AliasResult::MustAlias || + (AAR == AliasResult::PartialAlias && AAR.hasOffset() && + AAR.getOffset() >= 0)) { + int64_t AdjEarlierOff = + DeadOff + (AAR == AliasResult::PartialAlias ? AAR.getOffset() : 0); + // Make sure that the dead access is "inside" the killing one. + if (AdjEarlierOff >= KillingOff && + uint64_t(AdjEarlierOff - KillingOff) + DeadSize <= KillingSize) { + DeadOff = AdjEarlierOff; return OW_Complete; + } } // Check to see if the killing store is to the entire object (either a @@ -1110,14 +1121,16 @@ 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. - DeadOff = 0; - KillingOff = 0; + // 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 ExtraDeadOff = 0; + int64_t ExtraKillingOff = 0; const Value *DeadBasePtr = - GetPointerBaseWithConstantOffset(DeadPtr, DeadOff, DL); + GetPointerBaseWithConstantOffset(DeadPtr, ExtraDeadOff, DL); const Value *KillingBasePtr = - GetPointerBaseWithConstantOffset(KillingPtr, KillingOff, DL); + GetPointerBaseWithConstantOffset(KillingPtr, ExtraKillingOff, DL); + DeadOff += ExtraDeadOff; + KillingOff += ExtraKillingOff; // If the base pointers still differ, we have two completely different // stores. @@ -1245,7 +1258,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, InstWriteOffset, DepWriteOffset) == OW_Complete; @@ -1579,7 +1593,6 @@ int64_t KillingMemOffset = PhiTransKillingLocAndOffset ? (*PhiTransKillingLocAndOffset).second : 0; - assert(KillingMemOffset == 0 && "Unexpected non-zero offset"); auto OR = isOverwrite(KillingI, CurrentI, KillingMemLoc, *CurrentLoc, KillingMemOffset, CurrOffset); // If Current does not write to the same object as KillingDef, check @@ -2156,7 +2169,6 @@ .getWithoutAATags(); KillingOffset = ExDeadAccess.second.second; } - assert(KillingOffset == 0 && "Unexpected non-zero offset"); OverwriteResult OR = State.isOverwrite( KillingI, DeadI, KillingLoc, DeadLoc, KillingOffset, DeadOffset);