[polly] [Polly] Data flow reduction detection to cover more cases (PR #84901)
Michael Kruse via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 22 08:22:17 PDT 2024
================
@@ -2568,49 +2579,196 @@ bool checkCandidatePairAccesses(MemoryAccess *LoadMA, MemoryAccess *StoreMA,
// Finally, check if they are no other instructions accessing this memory
isl::map AllAccsRel = LoadAccs.unite(StoreAccs);
AllAccsRel = AllAccsRel.intersect_domain(Domain);
+
isl::set AllAccs = AllAccsRel.range();
+
Valid = !hasIntersectingAccesses(AllAccs, LoadMA, StoreMA, Domain, MemAccs);
LLVM_DEBUG(dbgs() << " == The accessed memory is " << (Valid ? "not " : "")
<< "accessed by other instructions!\n");
}
+
return Valid;
}
-void ScopBuilder::checkForReductions(ScopStmt &Stmt) {
- SmallVector<MemoryAccess *, 2> Loads;
- SmallVector<std::pair<MemoryAccess *, MemoryAccess *>, 4> Candidates;
+/// Perform a data flow analysis on the current basic block to propagate the
+/// uses of loaded values. Then check and mark the memory accesses which are
+/// part of reduction like chains.
+///
+/// NOTE: This assumes independent blocks and breaks otherwise.
+void ScopBuilder::checkForReductions(ScopStmt &Stmt, BasicBlock *Block) {
+ // During the data flow anaylis we use the State variable to keep track of
+ // the used "load-instructions" for each instruction in the basic block.
+ // This includes the LLVM-IR of the load and the "number of uses" (or the
+ // number of paths in the operand tree which end in this load).
+ using StatePairTy = std::pair<unsigned, MemoryAccess::ReductionType>;
+ using FlowInSetTy = MapVector<const LoadInst *, StatePairTy>;
+ using StateTy = MapVector<const Instruction *, FlowInSetTy>;
+ StateTy State;
+
+ // Invalid loads are loads which have uses we can't track properly in the
+ // state map. This includes loads which:
+ // o do not form a reduction when they flow into a memory location:
+ // (e.g., A[i] = B[i] * 3 and A[i] = A[i] * A[i] + A[i])
+ // o are used by a non binary operator or one which is not commutative
+ // and associative (e.g., A[i] = A[i] % 3)
+ // o might change the control flow (e.g., if (A[i]))
+ // o are used in indirect memory accesses (e.g., A[B[i]])
+ // o are used outside the current basic block
+ SmallPtrSet<const Instruction *, 8> InvalidLoads;
+
+ // Run the data flow analysis for all values in the basic block
+ for (Instruction &Inst : *Block) {
+ bool UsedOutsideBlock = any_of(Inst.users(), [Block](User *U) {
+ return cast<Instruction>(U)->getParent() != Block;
----------------
Meinersbur wrote:
I think you would rather want to check whether the instruction is in the same statement, instead of BasicBlock. See https://github.com/llvm/llvm-project/blob/70abbd9084e25d2485edfeb252b603b3910a23bc/polly/include/polly/Support/VirtualInstruction.h#L31 .
https://github.com/llvm/llvm-project/pull/84901
More information about the llvm-commits
mailing list