[PATCH] D125111: [SLP] Make reordering aware of external vectorizable scalar stores.

Vasileios Porpodas via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri May 6 18:31:32 PDT 2022


vporpo added inline comments.


================
Comment at: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp:4084
+  // it into `ExternalReorderIndices`
+  for (const auto &Pair : PtrToStoresMap) {
+    auto &StoresVec = Pair.second;
----------------
vdmitrie wrote:
> Hi Vasileios.
> 
> May I offer you to make some stylistic changes to this method to improve code readability?
> I was bit lazy to place all comments inline - sorry for that :). It was much easier for me to just apply your patch and use editor locally. So I'm only putting summary here:
> - reduce abuse of "auto"
> - do not create thin lambdas just for minor reducing amount of code.
> - improve Cmp to not call getPointerDiff if we already failed once
> - added type check to Cmp before querying for diff (although I'm not sure whether we can have different store types here)
> - inline Cmp into the call for stable_sort
> - inline stable_sort into CanFormVector
> - outline CanFromVector outside the loop
> - I'm not sure we need to look at each store to find out whether they are all sequential.
>   We probably can take diff between the first and the last ones.
> - use range loop for sequential index traversing
> 
> After applying all these suggestions here is how the method could possibly look:
> 
> SmallVector<BoUpSLP::OrdersType, 1>
> BoUpSLP::findExternalStoreUsersReorderIndices(TreeEntry *TE) const {
>   unsigned NumLanes = TE->Scalars.size();
> 
>   DenseMap<Value *, SmallVector<StoreInst *, 4>> PtrToStoresMap =
>       collectUserStores(TE);
> 
>   // Holds the reorder indices for each candidate store vector that is a user of
>   // the current TreeEntry.
>   SmallVector<OrdersType, 1> ExternalReorderIndices;
> 
>   // \Returns true if the stores in `SortedStoresVec` are consecutive and can
>   // form a vector.
>   auto &&CanFormVector = [this](SmallVector<StoreInst *, 4> &StoresVecSorted) {
>     Type *Ty = StoresVecSorted.front()->getValueOperand()->getType();
>     bool FailedToSort = false;
>     stable_sort(StoresVecSorted, [this, &FailedToSort, Ty](StoreInst *S1,
>                                                            StoreInst *S2) {
>       if (FailedToSort)
>         return false;
>       if (S1->getValueOperand()->getType() != Ty ||
>           S2->getValueOperand()->getType() != Ty) {
>         FailedToSort = true;
>         return false;
>       }
>       Optional<int> Diff = getPointersDiff(Ty, S2->getPointerOperand(), Ty,
>                                            S1->getPointerOperand(), *DL, *SE,
>                                            /*StrictCheck=*/true);
>       if (!Diff) {
>         FailedToSort = true;
>         return false;
>       }
>       return Diff < 0;
>     });
>     // If we failed to compare stores, then just abandon this stores vector.
>     if (FailedToSort)
>       return false;
>     Optional<int> Range =
>         getPointersDiff(Ty, StoresVecSorted.front()->getPointerOperand(), Ty,
>                         StoresVecSorted.back()->getPointerOperand(), *DL, *SE,
>                         /*StrictCheck=*/true);
>     return *Range == (int)StoresVecSorted.size() - 1;
>   };
> 
>   // Now inspect the stores collected per pointer and look for vectorization
>   // candidates. For each candidate calculate the reorder index vector and push
>   // it into `ExternalReorderIndices`
>   for (const auto &Pair : PtrToStoresMap) {
>     const SmallVector<StoreInst *, 4> &StoresVec = Pair.second;
> 
>     // If we have fewer than NumLanes stores, then we can't form a vector.
>     if (StoresVec.size() != NumLanes)
>       continue;
> 
>     // Sort the vector based on the pointers. We create a copy because we may
>     // need the original later for calculating the reorder (shuffle) indices.
>     auto StoresVecSorted = StoresVec;
> 
>     // If the stores are not consecutive then abandon this sotres vector.
>     if (!CanFormVector(StoresVecSorted))
>       continue;
> 
>     // The scalars in StoresVec can form a vector instruction, so calculate the
>     // shuffle indices.
>     ExternalReorderIndices.resize(ExternalReorderIndices.size() + 1);
>     OrdersType &ReorderIndices = ExternalReorderIndices.back();
>     for (StoreInst *SI : StoresVec) {
>       unsigned Idx = llvm::find(StoresVecSorted, SI) - StoresVecSorted.begin();
>       ReorderIndices.push_back(Idx);
>     }
> 
>     // Identity order (e.g., {0,1,2,3}) is modeled as an empty OrdersType in
>     // reorderTopToBottom() and reorderBottomToTop(), so we are following the
>     // same convention here.
>     auto IsIdentityOrder = [](const OrdersType &Order) {
>       for (unsigned Idx : seq<unsigned>(0, Order.size()))
>         if (Idx != Order[Idx])
>           return false;
>       return true;
>     };
>     if (IsIdentityOrder(ReorderIndices))
>       ReorderIndices.clear();
>   }
>   return ExternalReorderIndices;
> }
>  
I think I addressed most of these points. Please take a look.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125111/new/

https://reviews.llvm.org/D125111



More information about the llvm-commits mailing list