Index: lib/Transforms/Vectorize/SLPVectorizer.cpp =================================================================== --- lib/Transforms/Vectorize/SLPVectorizer.cpp +++ lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -916,8 +916,8 @@ ScheduleData *NextLoadStore = nullptr; /// The dependent memory instructions. - /// This list is derived on demand in calculateDependencies(). - SmallVector MemoryDependencies; + /// This set is derived on demand in calculateDependencies(). + SmallSet MemoryDependencies; /// This ScheduleData is in the current scheduling region if this matches /// the current SchedulingRegionID of BlockScheduling. @@ -972,6 +972,7 @@ ScheduleEnd = nullptr; FirstLoadStoreInRegion = nullptr; LastLoadStoreInRegion = nullptr; + ExtraScheduleDataMap.clear(); // Reduce the maximum schedule region size by the size of the // previous scheduling run. @@ -1060,13 +1061,23 @@ void doForAllOpcodes(Value *V, function_ref Action) { - if (ScheduleData *SD = getScheduleData(V)) - Action(SD); + bool Found = false; auto I = ExtraScheduleDataMap.find(V); - if (I != ExtraScheduleDataMap.end()) - for (auto &P : I->second) - if (P.second->SchedulingRegionID == SchedulingRegionID) - Action(P.second); + if (I != ExtraScheduleDataMap.end()) { + for (auto &P : I->second) { + ScheduleData *SD = P.second; + if (SD && !SD->isPartOfBundle()) + continue; + if (SD && SD->SchedulingRegionID == SchedulingRegionID) { + Found = true; + Action(SD); + } + } + } + if (ScheduleData *SD = getScheduleData(V)) { + if (!Found || SD->isPartOfBundle()) + Action(SD); + } } /// Put all instructions into the ReadyList which are ready for scheduling. @@ -3897,6 +3908,15 @@ } if (!Bundle->isReady()) { cancelScheduling(VL, S.OpValue); + // We have to clear all dependencies, since all values + // were calculated for the vectorized bundle. + for (auto *I = ScheduleStart; I != ScheduleEnd; + I = I->getNextNode()) { + doForAllOpcodes(I, [](ScheduleData *SD) { + SD->clearDependencies(); + }); + } + resetSchedule(); return false; } return true; @@ -4075,27 +4095,35 @@ // Handle def-use chain dependencies. if (BundleMember->OpValue != BundleMember->Inst) { - ScheduleData *UseSD = getScheduleData(BundleMember->Inst); - if (UseSD && isInSchedulingRegion(UseSD->FirstInBundle)) { - BundleMember->Dependencies++; - ScheduleData *DestBundle = UseSD->FirstInBundle; - if (!DestBundle->IsScheduled) + for (User *U : BundleMember->Inst->users()) { + if (isa(U)) { + doForAllOpcodes(U, [&BundleMember, &WorkList](ScheduleData *UseSD) { + BundleMember->Dependencies++; + ScheduleData *DestBundle = UseSD->FirstInBundle; + if (!DestBundle->IsScheduled) + BundleMember->incrementUnscheduledDeps(1); + if (!DestBundle->hasValidDependencies()) + WorkList.push_back(DestBundle); + }); + } else { + // I'm not sure if this can ever happen. But we need to be safe. + // This lets the instruction/bundle never be scheduled and + // eventually disable vectorization. + BundleMember->Dependencies++; BundleMember->incrementUnscheduledDeps(1); - if (!DestBundle->hasValidDependencies()) - WorkList.push_back(DestBundle); + } } } else { for (User *U : BundleMember->Inst->users()) { if (isa(U)) { - ScheduleData *UseSD = getScheduleData(U); - if (UseSD && isInSchedulingRegion(UseSD->FirstInBundle)) { + doForAllOpcodes(U, [&BundleMember, &WorkList](ScheduleData *UseSD) { BundleMember->Dependencies++; ScheduleData *DestBundle = UseSD->FirstInBundle; if (!DestBundle->IsScheduled) BundleMember->incrementUnscheduledDeps(1); if (!DestBundle->hasValidDependencies()) WorkList.push_back(DestBundle); - } + }); } else { // I'm not sure if this can ever happen. But we need to be safe. // This lets the instruction/bundle never be scheduled and @@ -4135,14 +4163,18 @@ // balance between reduced runtime and accurate dependencies. numAliased++; - DepDest->MemoryDependencies.push_back(BundleMember); - BundleMember->Dependencies++; - ScheduleData *DestBundle = DepDest->FirstInBundle; - if (!DestBundle->IsScheduled) { - BundleMember->incrementUnscheduledDeps(1); - } - if (!DestBundle->hasValidDependencies()) { - WorkList.push_back(DestBundle); + // We don't want any duplicates in the set to have a correct + // dependancies. + if (DepDest->MemoryDependencies.count(BundleMember) == 0) { + DepDest->MemoryDependencies.insert(BundleMember); + BundleMember->Dependencies++; + ScheduleData *DestBundle = DepDest->FirstInBundle; + if (!DestBundle->IsScheduled) { + BundleMember->incrementUnscheduledDeps(1); + } + if (!DestBundle->hasValidDependencies()) { + WorkList.push_back(DestBundle); + } } } DepDest = DepDest->NextLoadStore;