xref: /llvm-project/polly/lib/Transform/ForwardOpTree.cpp (revision 601d7eab0665ba298d81952da11593124fd893a0)
19248fde5SEugene Zelenko //===- ForwardOpTree.h ------------------------------------------*- C++ -*-===//
2a6b2de3bSMichael Kruse //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a6b2de3bSMichael Kruse //
7a6b2de3bSMichael Kruse //===----------------------------------------------------------------------===//
8a6b2de3bSMichael Kruse //
9a6b2de3bSMichael Kruse // Move instructions between statements.
10a6b2de3bSMichael Kruse //
11a6b2de3bSMichael Kruse //===----------------------------------------------------------------------===//
12a6b2de3bSMichael Kruse 
13a6b2de3bSMichael Kruse #include "polly/ForwardOpTree.h"
1470af4f57SMichael Kruse #include "polly/Options.h"
1507e8c36dSMichael Kruse #include "polly/ScopBuilder.h"
16a6b2de3bSMichael Kruse #include "polly/ScopInfo.h"
17a6b2de3bSMichael Kruse #include "polly/ScopPass.h"
18a6b2de3bSMichael Kruse #include "polly/Support/GICHelper.h"
1970af4f57SMichael Kruse #include "polly/Support/ISLOStream.h"
2070af4f57SMichael Kruse #include "polly/Support/ISLTools.h"
21a6b2de3bSMichael Kruse #include "polly/Support/VirtualInstruction.h"
2270af4f57SMichael Kruse #include "polly/ZoneAlgo.h"
239248fde5SEugene Zelenko #include "llvm/ADT/STLExtras.h"
249248fde5SEugene Zelenko #include "llvm/ADT/SmallVector.h"
259248fde5SEugene Zelenko #include "llvm/ADT/Statistic.h"
269248fde5SEugene Zelenko #include "llvm/Analysis/LoopInfo.h"
27a6b2de3bSMichael Kruse #include "llvm/Analysis/ValueTracking.h"
289248fde5SEugene Zelenko #include "llvm/IR/Instruction.h"
299248fde5SEugene Zelenko #include "llvm/IR/Instructions.h"
309248fde5SEugene Zelenko #include "llvm/IR/Value.h"
3105da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
329248fde5SEugene Zelenko #include "llvm/Support/Casting.h"
339248fde5SEugene Zelenko #include "llvm/Support/CommandLine.h"
349248fde5SEugene Zelenko #include "llvm/Support/Compiler.h"
359248fde5SEugene Zelenko #include "llvm/Support/Debug.h"
369248fde5SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
379248fde5SEugene Zelenko #include "llvm/Support/raw_ostream.h"
389248fde5SEugene Zelenko #include "isl/ctx.h"
399248fde5SEugene Zelenko #include "isl/isl-noexceptions.h"
409248fde5SEugene Zelenko #include <cassert>
419248fde5SEugene Zelenko #include <memory>
42a6b2de3bSMichael Kruse 
43*601d7eabSKarthika Devi C #include "polly/Support/PollyDebug.h"
4436550bacSMichael Kruse #define DEBUG_TYPE "polly-optree"
45a6b2de3bSMichael Kruse 
46a6b2de3bSMichael Kruse using namespace llvm;
479248fde5SEugene Zelenko using namespace polly;
48a6b2de3bSMichael Kruse 
4970af4f57SMichael Kruse static cl::opt<bool>
5070af4f57SMichael Kruse     AnalyzeKnown("polly-optree-analyze-known",
5170af4f57SMichael Kruse                  cl::desc("Analyze array contents for load forwarding"),
5270af4f57SMichael Kruse                  cl::cat(PollyCategory), cl::init(true), cl::Hidden);
5370af4f57SMichael Kruse 
5468821a8bSMichael Kruse static cl::opt<bool>
5568821a8bSMichael Kruse     NormalizePHIs("polly-optree-normalize-phi",
5668821a8bSMichael Kruse                   cl::desc("Replace PHIs by their incoming values"),
5768821a8bSMichael Kruse                   cl::cat(PollyCategory), cl::init(false), cl::Hidden);
5868821a8bSMichael Kruse 
59ef8325baSMichael Kruse static cl::opt<unsigned>
6070af4f57SMichael Kruse     MaxOps("polly-optree-max-ops",
6170af4f57SMichael Kruse            cl::desc("Maximum number of ISL operations to invest for known "
6270af4f57SMichael Kruse                     "analysis; 0=no limit"),
6370af4f57SMichael Kruse            cl::init(1000000), cl::cat(PollyCategory), cl::Hidden);
6470af4f57SMichael Kruse 
6570af4f57SMichael Kruse STATISTIC(KnownAnalyzed, "Number of successfully analyzed SCoPs");
6670af4f57SMichael Kruse STATISTIC(KnownOutOfQuota,
6770af4f57SMichael Kruse           "Analyses aborted because max_operations was reached");
6870af4f57SMichael Kruse 
69a6b2de3bSMichael Kruse STATISTIC(TotalInstructionsCopied, "Number of copied instructions");
7070af4f57SMichael Kruse STATISTIC(TotalKnownLoadsForwarded,
7170af4f57SMichael Kruse           "Number of forwarded loads because their value was known");
72822dfe27SMichael Kruse STATISTIC(TotalReloads, "Number of reloaded values");
7307e8c36dSMichael Kruse STATISTIC(TotalReadOnlyCopied, "Number of copied read-only accesses");
74a6b2de3bSMichael Kruse STATISTIC(TotalForwardedTrees, "Number of forwarded operand trees");
75a6b2de3bSMichael Kruse STATISTIC(TotalModifiedStmts,
76a6b2de3bSMichael Kruse           "Number of statements with at least one forwarded tree");
77a6b2de3bSMichael Kruse 
78a6b2de3bSMichael Kruse STATISTIC(ScopsModified, "Number of SCoPs with at least one forwarded tree");
79a6b2de3bSMichael Kruse 
8006ed5292SMichael Kruse STATISTIC(NumValueWrites, "Number of scalar value writes after OpTree");
8106ed5292SMichael Kruse STATISTIC(NumValueWritesInLoops,
8206ed5292SMichael Kruse           "Number of scalar value writes nested in affine loops after OpTree");
8306ed5292SMichael Kruse STATISTIC(NumPHIWrites, "Number of scalar phi writes after OpTree");
8406ed5292SMichael Kruse STATISTIC(NumPHIWritesInLoops,
8506ed5292SMichael Kruse           "Number of scalar phi writes nested in affine loops after OpTree");
8606ed5292SMichael Kruse STATISTIC(NumSingletonWrites, "Number of singleton writes after OpTree");
8706ed5292SMichael Kruse STATISTIC(NumSingletonWritesInLoops,
8806ed5292SMichael Kruse           "Number of singleton writes nested in affine loops after OpTree");
8906ed5292SMichael Kruse 
90a6b2de3bSMichael Kruse namespace {
91a6b2de3bSMichael Kruse 
92a6b2de3bSMichael Kruse /// The state of whether an operand tree was/can be forwarded.
93d85e345cSMichael Kruse ///
94d85e345cSMichael Kruse /// The items apply to an instructions and its operand tree with the instruction
95d85e345cSMichael Kruse /// as the root element. If the value in question is not an instruction in the
96d85e345cSMichael Kruse /// SCoP, it can be a leaf of an instruction's operand tree.
97a6b2de3bSMichael Kruse enum ForwardingDecision {
987175cffbSMichael Kruse   /// An uninitialized value.
997175cffbSMichael Kruse   FD_Unknown,
1007175cffbSMichael Kruse 
101d85e345cSMichael Kruse   /// The root instruction or value cannot be forwarded at all.
102a6b2de3bSMichael Kruse   FD_CannotForward,
103d85e345cSMichael Kruse 
104d85e345cSMichael Kruse   /// The root instruction or value can be forwarded as a leaf of a larger
105d85e345cSMichael Kruse   /// operand tree.
106d85e345cSMichael Kruse   /// It does not make sense to move the value itself, it would just replace it
107d85e345cSMichael Kruse   /// by a use of itself. For instance, a constant "5" used in a statement can
108d85e345cSMichael Kruse   /// be forwarded, but it would just replace it by the same constant "5".
109d85e345cSMichael Kruse   /// However, it makes sense to move as an operand of
110d85e345cSMichael Kruse   ///
111d85e345cSMichael Kruse   ///   %add = add 5, 5
112d85e345cSMichael Kruse   ///
113d85e345cSMichael Kruse   /// where "5" is moved as part of a larger operand tree. "5" would be placed
114d85e345cSMichael Kruse   /// (disregarding for a moment that literal constants don't have a location
115d85e345cSMichael Kruse   /// and can be used anywhere) into the same statement as %add would.
11667752076SMichael Kruse   FD_CanForwardLeaf,
117d85e345cSMichael Kruse 
118822dfe27SMichael Kruse   /// The root instruction can be forwarded and doing so avoids a scalar
119822dfe27SMichael Kruse   /// dependency.
120822dfe27SMichael Kruse   ///
121822dfe27SMichael Kruse   /// This can be either because the operand tree can be moved to the target
122822dfe27SMichael Kruse   /// statement, or a memory access is redirected to read from a different
123822dfe27SMichael Kruse   /// location.
124822dfe27SMichael Kruse   FD_CanForwardProfitably,
125d85e345cSMichael Kruse 
126a9a70863SMichael Kruse   /// A forwarding method cannot be applied to the operand tree.
127a9a70863SMichael Kruse   /// The difference to FD_CannotForward is that there might be other methods
128a9a70863SMichael Kruse   /// that can handle it.
129a9a70863SMichael Kruse   FD_NotApplicable
130a6b2de3bSMichael Kruse };
131a6b2de3bSMichael Kruse 
1327175cffbSMichael Kruse /// Represents the evaluation of and action to taken when forwarding a value
1337175cffbSMichael Kruse /// from an operand tree.
1347175cffbSMichael Kruse struct ForwardingAction {
1357175cffbSMichael Kruse   using KeyTy = std::pair<Value *, ScopStmt *>;
1367175cffbSMichael Kruse 
1377175cffbSMichael Kruse   /// Evaluation of forwarding a value.
1387175cffbSMichael Kruse   ForwardingDecision Decision = FD_Unknown;
1397175cffbSMichael Kruse 
1407175cffbSMichael Kruse   /// Callback to execute the forwarding.
1417175cffbSMichael Kruse   /// Returning true allows deleting the polly::MemoryAccess if the value is the
1427175cffbSMichael Kruse   /// root of the operand tree (and its elimination the reason why the
1437175cffbSMichael Kruse   /// forwarding is done). Return false if the MemoryAccess is reused or there
1447175cffbSMichael Kruse   /// might be other users of the read accesses. In the letter case the
1457175cffbSMichael Kruse   /// polly::SimplifyPass can remove dead MemoryAccesses.
__anon8f337d270202__anon8f337d270111::ForwardingAction1467175cffbSMichael Kruse   std::function<bool()> Execute = []() -> bool {
1477175cffbSMichael Kruse     llvm_unreachable("unspecified how to forward");
1487175cffbSMichael Kruse   };
1497175cffbSMichael Kruse 
1507175cffbSMichael Kruse   /// Other values that need to be forwarded if this action is executed. Their
1517175cffbSMichael Kruse   /// actions are executed after this one.
1527175cffbSMichael Kruse   SmallVector<KeyTy, 4> Depends;
1537175cffbSMichael Kruse 
1547175cffbSMichael Kruse   /// Named ctor: The method creating this object does not apply to the kind of
1557175cffbSMichael Kruse   /// value, but other methods may.
notApplicable__anon8f337d270111::ForwardingAction1567175cffbSMichael Kruse   static ForwardingAction notApplicable() {
1577175cffbSMichael Kruse     ForwardingAction Result;
1587175cffbSMichael Kruse     Result.Decision = FD_NotApplicable;
1597175cffbSMichael Kruse     return Result;
1607175cffbSMichael Kruse   }
1617175cffbSMichael Kruse 
1627175cffbSMichael Kruse   /// Named ctor: The value cannot be forwarded.
cannotForward__anon8f337d270111::ForwardingAction1637175cffbSMichael Kruse   static ForwardingAction cannotForward() {
1647175cffbSMichael Kruse     ForwardingAction Result;
1657175cffbSMichael Kruse     Result.Decision = FD_CannotForward;
1667175cffbSMichael Kruse     return Result;
1677175cffbSMichael Kruse   }
1687175cffbSMichael Kruse 
1697175cffbSMichael Kruse   /// Named ctor: The value can just be used without any preparation.
triviallyForwardable__anon8f337d270111::ForwardingAction170c1cf51e7SMichael Kruse   static ForwardingAction triviallyForwardable(bool IsProfitable, Value *Val) {
1717175cffbSMichael Kruse     ForwardingAction Result;
1727175cffbSMichael Kruse     Result.Decision =
1737175cffbSMichael Kruse         IsProfitable ? FD_CanForwardProfitably : FD_CanForwardLeaf;
174c1cf51e7SMichael Kruse     Result.Execute = [=]() {
175*601d7eabSKarthika Devi C       POLLY_DEBUG(dbgs() << "    trivially forwarded: " << *Val << "\n");
176c1cf51e7SMichael Kruse       return true;
177c1cf51e7SMichael Kruse     };
1787175cffbSMichael Kruse     return Result;
1797175cffbSMichael Kruse   }
1807175cffbSMichael Kruse 
1817175cffbSMichael Kruse   /// Name ctor: The value can be forwarded by executing an action.
canForward__anon8f337d270111::ForwardingAction1827175cffbSMichael Kruse   static ForwardingAction canForward(std::function<bool()> Execute,
1837175cffbSMichael Kruse                                      ArrayRef<KeyTy> Depends,
1847175cffbSMichael Kruse                                      bool IsProfitable) {
1857175cffbSMichael Kruse     ForwardingAction Result;
1867175cffbSMichael Kruse     Result.Decision =
1877175cffbSMichael Kruse         IsProfitable ? FD_CanForwardProfitably : FD_CanForwardLeaf;
1887175cffbSMichael Kruse     Result.Execute = std::move(Execute);
1897175cffbSMichael Kruse     Result.Depends.append(Depends.begin(), Depends.end());
1907175cffbSMichael Kruse     return Result;
1917175cffbSMichael Kruse   }
1927175cffbSMichael Kruse };
1937175cffbSMichael Kruse 
194a6b2de3bSMichael Kruse /// Implementation of operand tree forwarding for a specific SCoP.
195a6b2de3bSMichael Kruse ///
196a6b2de3bSMichael Kruse /// For a statement that requires a scalar value (through a value read
197a6b2de3bSMichael Kruse /// MemoryAccess), see if its operand can be moved into the statement. If so,
198a6b2de3bSMichael Kruse /// the MemoryAccess is removed and the all the operand tree instructions are
199a6b2de3bSMichael Kruse /// moved into the statement. All original instructions are left in the source
200a6b2de3bSMichael Kruse /// statements. The simplification pass can clean these up.
201bd93df93SMichael Kruse class ForwardOpTreeImpl final : ZoneAlgorithm {
202a6b2de3bSMichael Kruse private:
2037175cffbSMichael Kruse   using MemoizationTy = DenseMap<ForwardingAction::KeyTy, ForwardingAction>;
2047175cffbSMichael Kruse 
20589972e21SMichael Kruse   /// Scope guard to limit the number of isl operations for this pass.
20689972e21SMichael Kruse   IslMaxOperationsGuard &MaxOpGuard;
20789972e21SMichael Kruse 
208a6b2de3bSMichael Kruse   /// How many instructions have been copied to other statements.
209a6b2de3bSMichael Kruse   int NumInstructionsCopied = 0;
210a6b2de3bSMichael Kruse 
21170af4f57SMichael Kruse   /// Number of loads forwarded because their value was known.
21270af4f57SMichael Kruse   int NumKnownLoadsForwarded = 0;
21370af4f57SMichael Kruse 
214822dfe27SMichael Kruse   /// Number of values reloaded from known array elements.
215822dfe27SMichael Kruse   int NumReloads = 0;
216822dfe27SMichael Kruse 
21707e8c36dSMichael Kruse   /// How many read-only accesses have been copied.
21807e8c36dSMichael Kruse   int NumReadOnlyCopied = 0;
21907e8c36dSMichael Kruse 
220a6b2de3bSMichael Kruse   /// How many operand trees have been forwarded.
221a6b2de3bSMichael Kruse   int NumForwardedTrees = 0;
222a6b2de3bSMichael Kruse 
223a6b2de3bSMichael Kruse   /// Number of statements with at least one forwarded operand tree.
224a6b2de3bSMichael Kruse   int NumModifiedStmts = 0;
225a6b2de3bSMichael Kruse 
226a6b2de3bSMichael Kruse   /// Whether we carried out at least one change to the SCoP.
227a6b2de3bSMichael Kruse   bool Modified = false;
228a6b2de3bSMichael Kruse 
2297175cffbSMichael Kruse   /// Cache of how to forward values.
2307175cffbSMichael Kruse   /// The key of this map is the llvm::Value to be forwarded and the
2317175cffbSMichael Kruse   /// polly::ScopStmt it is forwarded from. This is because the same llvm::Value
2327175cffbSMichael Kruse   /// can evaluate differently depending on where it is evaluate. For instance,
2337175cffbSMichael Kruse   /// a synthesizable Scev represents a recurrence with an loop but the loop's
2347175cffbSMichael Kruse   /// exit value if evaluated after the loop.
2357175cffbSMichael Kruse   /// The cached results are only valid for the current TargetStmt.
2367175cffbSMichael Kruse   /// CHECKME: ScalarEvolution::getScevAtScope should take care for getting the
2377175cffbSMichael Kruse   /// exit value when instantiated outside of the loop. The primary concern is
2387175cffbSMichael Kruse   /// ambiguity when crossing PHI nodes, which currently is not supported.
2397175cffbSMichael Kruse   MemoizationTy ForwardingActions;
2407175cffbSMichael Kruse 
24170af4f57SMichael Kruse   /// Contains the zones where array elements are known to contain a specific
24270af4f57SMichael Kruse   /// value.
24370af4f57SMichael Kruse   /// { [Element[] -> Zone[]] -> ValInst[] }
24470af4f57SMichael Kruse   /// @see computeKnown()
24570af4f57SMichael Kruse   isl::union_map Known;
24670af4f57SMichael Kruse 
24770af4f57SMichael Kruse   /// Translator for newly introduced ValInsts to already existing ValInsts such
24870af4f57SMichael Kruse   /// that new introduced load instructions can reuse the Known analysis of its
24970af4f57SMichael Kruse   /// original load. { ValInst[] -> ValInst[] }
25070af4f57SMichael Kruse   isl::union_map Translator;
25170af4f57SMichael Kruse 
25270af4f57SMichael Kruse   /// Get list of array elements that do contain the same ValInst[] at Domain[].
25370af4f57SMichael Kruse   ///
25470af4f57SMichael Kruse   /// @param ValInst { Domain[] -> ValInst[] }
25570af4f57SMichael Kruse   ///                The values for which we search for alternative locations,
25670af4f57SMichael Kruse   ///                per statement instance.
25770af4f57SMichael Kruse   ///
25870af4f57SMichael Kruse   /// @return { Domain[] -> Element[] }
25970af4f57SMichael Kruse   ///         For each statement instance, the array elements that contain the
26070af4f57SMichael Kruse   ///         same ValInst.
findSameContentElements(isl::union_map ValInst)26170af4f57SMichael Kruse   isl::union_map findSameContentElements(isl::union_map ValInst) {
262e276e9f3SMichael Kruse     assert(!ValInst.is_single_valued().is_false());
26370af4f57SMichael Kruse 
26470af4f57SMichael Kruse     // { Domain[] }
26570af4f57SMichael Kruse     isl::union_set Domain = ValInst.domain();
26670af4f57SMichael Kruse 
26770af4f57SMichael Kruse     // { Domain[] -> Scatter[] }
26870af4f57SMichael Kruse     isl::union_map Schedule = getScatterFor(Domain);
26970af4f57SMichael Kruse 
27070af4f57SMichael Kruse     // { Element[] -> [Scatter[] -> ValInst[]] }
27170af4f57SMichael Kruse     isl::union_map MustKnownCurried =
27270af4f57SMichael Kruse         convertZoneToTimepoints(Known, isl::dim::in, false, true).curry();
27370af4f57SMichael Kruse 
27470af4f57SMichael Kruse     // { [Domain[] -> ValInst[]] -> Scatter[] }
27570af4f57SMichael Kruse     isl::union_map DomValSched = ValInst.domain_map().apply_range(Schedule);
27670af4f57SMichael Kruse 
27770af4f57SMichael Kruse     // { [Scatter[] -> ValInst[]] -> [Domain[] -> ValInst[]] }
27870af4f57SMichael Kruse     isl::union_map SchedValDomVal =
27970af4f57SMichael Kruse         DomValSched.range_product(ValInst.range_map()).reverse();
28070af4f57SMichael Kruse 
28170af4f57SMichael Kruse     // { Element[] -> [Domain[] -> ValInst[]] }
28270af4f57SMichael Kruse     isl::union_map MustKnownInst = MustKnownCurried.apply_range(SchedValDomVal);
28370af4f57SMichael Kruse 
28470af4f57SMichael Kruse     // { Domain[] -> Element[] }
28570af4f57SMichael Kruse     isl::union_map MustKnownMap =
28670af4f57SMichael Kruse         MustKnownInst.uncurry().domain().unwrap().reverse();
28770af4f57SMichael Kruse     simplify(MustKnownMap);
28870af4f57SMichael Kruse 
28970af4f57SMichael Kruse     return MustKnownMap;
29070af4f57SMichael Kruse   }
29170af4f57SMichael Kruse 
29270af4f57SMichael Kruse   /// Find a single array element for each statement instance, within a single
29370af4f57SMichael Kruse   /// array.
29470af4f57SMichael Kruse   ///
29570af4f57SMichael Kruse   /// @param MustKnown { Domain[] -> Element[] }
29670af4f57SMichael Kruse   ///                  Set of candidate array elements.
29770af4f57SMichael Kruse   /// @param Domain    { Domain[] }
29870af4f57SMichael Kruse   ///                  The statement instance for which we need elements for.
29970af4f57SMichael Kruse   ///
30070af4f57SMichael Kruse   /// @return { Domain[] -> Element[] }
30170af4f57SMichael Kruse   ///         For each statement instance, an array element out of @p MustKnown.
30270af4f57SMichael Kruse   ///         All array elements must be in the same array (Polly does not yet
30370af4f57SMichael Kruse   ///         support reading from different accesses using the same
30470af4f57SMichael Kruse   ///         MemoryAccess). If no mapping for all of @p Domain exists, returns
30570af4f57SMichael Kruse   ///         null.
singleLocation(isl::union_map MustKnown,isl::set Domain)30670af4f57SMichael Kruse   isl::map singleLocation(isl::union_map MustKnown, isl::set Domain) {
30770af4f57SMichael Kruse     // { Domain[] -> Element[] }
30870af4f57SMichael Kruse     isl::map Result;
30970af4f57SMichael Kruse 
3103b9677e1SMichael Kruse     // Make irrelevant elements not interfere.
3113b9677e1SMichael Kruse     Domain = Domain.intersect_params(S->getContext());
3123b9677e1SMichael Kruse 
31370af4f57SMichael Kruse     // MemoryAccesses can read only elements from a single array
31470af4f57SMichael Kruse     // (i.e. not: { Dom[0] -> A[0]; Dom[1] -> B[1] }).
31570af4f57SMichael Kruse     // Look through all spaces until we find one that contains at least the
31670af4f57SMichael Kruse     // wanted statement instance.s
31791f851b1STobias Grosser     for (isl::map Map : MustKnown.get_map_list()) {
31870af4f57SMichael Kruse       // Get the array this is accessing.
31970af4f57SMichael Kruse       isl::id ArrayId = Map.get_tuple_id(isl::dim::out);
32070af4f57SMichael Kruse       ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(ArrayId.get_user());
32170af4f57SMichael Kruse 
32270af4f57SMichael Kruse       // No support for generation of indirect array accesses.
32370af4f57SMichael Kruse       if (SAI->getBasePtrOriginSAI())
32491f851b1STobias Grosser         continue;
32570af4f57SMichael Kruse 
32670af4f57SMichael Kruse       // Determine whether this map contains all wanted values.
32770af4f57SMichael Kruse       isl::set MapDom = Map.domain();
32870af4f57SMichael Kruse       if (!Domain.is_subset(MapDom).is_true())
32991f851b1STobias Grosser         continue;
33070af4f57SMichael Kruse 
33170af4f57SMichael Kruse       // There might be multiple array elements that contain the same value, but
33270af4f57SMichael Kruse       // choose only one of them. lexmin is used because it returns a one-value
33370af4f57SMichael Kruse       // mapping, we do not care about which one.
33470af4f57SMichael Kruse       // TODO: Get the simplest access function.
33570af4f57SMichael Kruse       Result = Map.lexmin();
33691f851b1STobias Grosser       break;
33791f851b1STobias Grosser     }
33870af4f57SMichael Kruse 
33970af4f57SMichael Kruse     return Result;
34070af4f57SMichael Kruse   }
34170af4f57SMichael Kruse 
34270af4f57SMichael Kruse public:
ForwardOpTreeImpl(Scop * S,LoopInfo * LI,IslMaxOperationsGuard & MaxOpGuard)34389972e21SMichael Kruse   ForwardOpTreeImpl(Scop *S, LoopInfo *LI, IslMaxOperationsGuard &MaxOpGuard)
34489972e21SMichael Kruse       : ZoneAlgorithm("polly-optree", S, LI), MaxOpGuard(MaxOpGuard) {}
3459248fde5SEugene Zelenko 
34670af4f57SMichael Kruse   /// Compute the zones of known array element contents.
34770af4f57SMichael Kruse   ///
34870af4f57SMichael Kruse   /// @return True if the computed #Known is usable.
computeKnownValues()34970af4f57SMichael Kruse   bool computeKnownValues() {
35070af4f57SMichael Kruse     isl::union_map MustKnown, KnownFromLoad, KnownFromInit;
35170af4f57SMichael Kruse 
35270af4f57SMichael Kruse     // Check that nothing strange occurs.
35347281843SMichael Kruse     collectCompatibleElts();
35470af4f57SMichael Kruse 
35570af4f57SMichael Kruse     {
35689972e21SMichael Kruse       IslQuotaScope QuotaScope = MaxOpGuard.enter();
35770af4f57SMichael Kruse 
35870af4f57SMichael Kruse       computeCommon();
35968821a8bSMichael Kruse       if (NormalizePHIs)
36068821a8bSMichael Kruse         computeNormalizedPHIs();
36170af4f57SMichael Kruse       Known = computeKnown(true, true);
36270af4f57SMichael Kruse 
36370af4f57SMichael Kruse       // Preexisting ValInsts use the known content analysis of themselves.
36470af4f57SMichael Kruse       Translator = makeIdentityMap(Known.range(), false);
36570af4f57SMichael Kruse     }
36670af4f57SMichael Kruse 
3677c7978a1Spatacca     if (Known.is_null() || Translator.is_null() || NormalizeMap.is_null()) {
36870af4f57SMichael Kruse       assert(isl_ctx_last_error(IslCtx.get()) == isl_error_quota);
3699b41d095Spatacca       Known = {};
3709b41d095Spatacca       Translator = {};
3719b41d095Spatacca       NormalizeMap = {};
372*601d7eabSKarthika Devi C       POLLY_DEBUG(dbgs() << "Known analysis exceeded max_operations\n");
37370af4f57SMichael Kruse       return false;
37470af4f57SMichael Kruse     }
37570af4f57SMichael Kruse 
37670af4f57SMichael Kruse     KnownAnalyzed++;
377*601d7eabSKarthika Devi C     POLLY_DEBUG(dbgs() << "All known: " << Known << "\n");
37870af4f57SMichael Kruse 
37970af4f57SMichael Kruse     return true;
38070af4f57SMichael Kruse   }
38170af4f57SMichael Kruse 
printStatistics(raw_ostream & OS,int Indent=0)382a6b2de3bSMichael Kruse   void printStatistics(raw_ostream &OS, int Indent = 0) {
383a6b2de3bSMichael Kruse     OS.indent(Indent) << "Statistics {\n";
384a6b2de3bSMichael Kruse     OS.indent(Indent + 4) << "Instructions copied: " << NumInstructionsCopied
385a6b2de3bSMichael Kruse                           << '\n';
38670af4f57SMichael Kruse     OS.indent(Indent + 4) << "Known loads forwarded: " << NumKnownLoadsForwarded
38770af4f57SMichael Kruse                           << '\n';
388822dfe27SMichael Kruse     OS.indent(Indent + 4) << "Reloads: " << NumReloads << '\n';
38907e8c36dSMichael Kruse     OS.indent(Indent + 4) << "Read-only accesses copied: " << NumReadOnlyCopied
39007e8c36dSMichael Kruse                           << '\n';
391a6b2de3bSMichael Kruse     OS.indent(Indent + 4) << "Operand trees forwarded: " << NumForwardedTrees
392a6b2de3bSMichael Kruse                           << '\n';
393a6b2de3bSMichael Kruse     OS.indent(Indent + 4) << "Statements with forwarded operand trees: "
394a6b2de3bSMichael Kruse                           << NumModifiedStmts << '\n';
395a6b2de3bSMichael Kruse     OS.indent(Indent) << "}\n";
396a6b2de3bSMichael Kruse   }
397a6b2de3bSMichael Kruse 
printStatements(raw_ostream & OS,int Indent=0) const3989248fde5SEugene Zelenko   void printStatements(raw_ostream &OS, int Indent = 0) const {
399a6b2de3bSMichael Kruse     OS.indent(Indent) << "After statements {\n";
400a6b2de3bSMichael Kruse     for (auto &Stmt : *S) {
401a6b2de3bSMichael Kruse       OS.indent(Indent + 4) << Stmt.getBaseName() << "\n";
402a6b2de3bSMichael Kruse       for (auto *MA : Stmt)
403a6b2de3bSMichael Kruse         MA->print(OS);
404a6b2de3bSMichael Kruse 
405a6b2de3bSMichael Kruse       OS.indent(Indent + 12);
406a6b2de3bSMichael Kruse       Stmt.printInstructions(OS);
407a6b2de3bSMichael Kruse     }
408a6b2de3bSMichael Kruse     OS.indent(Indent) << "}\n";
409a6b2de3bSMichael Kruse   }
410a6b2de3bSMichael Kruse 
41170af4f57SMichael Kruse   /// Create a new MemoryAccess of type read and MemoryKind::Array.
41270af4f57SMichael Kruse   ///
41370af4f57SMichael Kruse   /// @param Stmt           The statement in which the access occurs.
41470af4f57SMichael Kruse   /// @param LI             The instruction that does the access.
41570af4f57SMichael Kruse   /// @param AccessRelation The array element that each statement instance
41670af4f57SMichael Kruse   ///                       accesses.
41770af4f57SMichael Kruse   ///
41870af4f57SMichael Kruse   /// @param The newly created access.
makeReadArrayAccess(ScopStmt * Stmt,LoadInst * LI,isl::map AccessRelation)41970af4f57SMichael Kruse   MemoryAccess *makeReadArrayAccess(ScopStmt *Stmt, LoadInst *LI,
42070af4f57SMichael Kruse                                     isl::map AccessRelation) {
42170af4f57SMichael Kruse     isl::id ArrayId = AccessRelation.get_tuple_id(isl::dim::out);
42270af4f57SMichael Kruse     ScopArrayInfo *SAI = reinterpret_cast<ScopArrayInfo *>(ArrayId.get_user());
42370af4f57SMichael Kruse 
42470af4f57SMichael Kruse     // Create a dummy SCEV access, to be replaced anyway.
42570af4f57SMichael Kruse     SmallVector<const SCEV *, 4> Sizes;
42670af4f57SMichael Kruse     Sizes.reserve(SAI->getNumberOfDimensions());
42770af4f57SMichael Kruse     SmallVector<const SCEV *, 4> Subscripts;
42870af4f57SMichael Kruse     Subscripts.reserve(SAI->getNumberOfDimensions());
42970af4f57SMichael Kruse     for (unsigned i = 0; i < SAI->getNumberOfDimensions(); i += 1) {
43070af4f57SMichael Kruse       Sizes.push_back(SAI->getDimensionSize(i));
43170af4f57SMichael Kruse       Subscripts.push_back(nullptr);
43270af4f57SMichael Kruse     }
43370af4f57SMichael Kruse 
43470af4f57SMichael Kruse     MemoryAccess *Access =
43570af4f57SMichael Kruse         new MemoryAccess(Stmt, LI, MemoryAccess::READ, SAI->getBasePtr(),
43670af4f57SMichael Kruse                          LI->getType(), true, {}, Sizes, LI, MemoryKind::Array);
43770af4f57SMichael Kruse     S->addAccessFunction(Access);
43870af4f57SMichael Kruse     Stmt->addAccess(Access, true);
43970af4f57SMichael Kruse 
44070af4f57SMichael Kruse     Access->setNewAccessRelation(AccessRelation);
44170af4f57SMichael Kruse 
44270af4f57SMichael Kruse     return Access;
44370af4f57SMichael Kruse   }
44470af4f57SMichael Kruse 
44570af4f57SMichael Kruse   /// Forward a load by reading from an array element that contains the same
44670af4f57SMichael Kruse   /// value. Typically the location it was loaded from.
44770af4f57SMichael Kruse   ///
44870af4f57SMichael Kruse   /// @param TargetStmt  The statement the operand tree will be copied to.
44970af4f57SMichael Kruse   /// @param Inst        The (possibly speculatable) instruction to forward.
45070af4f57SMichael Kruse   /// @param UseStmt     The statement that uses @p Inst.
45170af4f57SMichael Kruse   /// @param UseLoop     The loop @p Inst is used in.
45270af4f57SMichael Kruse   /// @param DefStmt     The statement @p Inst is defined in.
45370af4f57SMichael Kruse   /// @param DefLoop     The loop which contains @p Inst.
45470af4f57SMichael Kruse   ///
4557175cffbSMichael Kruse   /// @return A ForwardingAction object describing the feasibility and
4567175cffbSMichael Kruse   ///         profitability evaluation and the callback carrying-out the value
4577175cffbSMichael Kruse   ///         forwarding.
forwardKnownLoad(ScopStmt * TargetStmt,Instruction * Inst,ScopStmt * UseStmt,Loop * UseLoop,ScopStmt * DefStmt,Loop * DefLoop)4587175cffbSMichael Kruse   ForwardingAction forwardKnownLoad(ScopStmt *TargetStmt, Instruction *Inst,
45970af4f57SMichael Kruse                                     ScopStmt *UseStmt, Loop *UseLoop,
4607175cffbSMichael Kruse                                     ScopStmt *DefStmt, Loop *DefLoop) {
46170af4f57SMichael Kruse     // Cannot do anything without successful known analysis.
462d3ce899dSMichael Kruse     if (Known.is_null() || Translator.is_null() ||
463d3ce899dSMichael Kruse         MaxOpGuard.hasQuotaExceeded())
4647175cffbSMichael Kruse       return ForwardingAction::notApplicable();
46570af4f57SMichael Kruse 
46670af4f57SMichael Kruse     LoadInst *LI = dyn_cast<LoadInst>(Inst);
46770af4f57SMichael Kruse     if (!LI)
4687175cffbSMichael Kruse       return ForwardingAction::notApplicable();
46970af4f57SMichael Kruse 
4707175cffbSMichael Kruse     ForwardingDecision OpDecision =
4717175cffbSMichael Kruse         forwardTree(TargetStmt, LI->getPointerOperand(), DefStmt, DefLoop);
47270af4f57SMichael Kruse     switch (OpDecision) {
473822dfe27SMichael Kruse     case FD_CanForwardProfitably:
4747175cffbSMichael Kruse     case FD_CanForwardLeaf:
47570af4f57SMichael Kruse       break;
4767175cffbSMichael Kruse     case FD_CannotForward:
4777175cffbSMichael Kruse       return ForwardingAction::cannotForward();
47870af4f57SMichael Kruse     default:
47970af4f57SMichael Kruse       llvm_unreachable("Shouldn't return this");
48070af4f57SMichael Kruse     }
48170af4f57SMichael Kruse 
4827175cffbSMichael Kruse     MemoryAccess *Access = TargetStmt->getArrayAccessOrNULLFor(LI);
4837175cffbSMichael Kruse     if (Access) {
4847175cffbSMichael Kruse       // If the load is already in the statement, no forwarding is necessary.
4857175cffbSMichael Kruse       // However, it might happen that the LoadInst is already present in the
4867175cffbSMichael Kruse       // statement's instruction list. In that case we do as follows:
4877175cffbSMichael Kruse       // - For the evaluation, we can trivially forward it as it is
4887175cffbSMichael Kruse       //   benefit of forwarding an already present instruction.
4897175cffbSMichael Kruse       // - For the execution, prepend the instruction (to make it
4907175cffbSMichael Kruse       //   available to all instructions following in the instruction list), but
4917175cffbSMichael Kruse       //   do not add another MemoryAccess.
4927175cffbSMichael Kruse       auto ExecAction = [this, TargetStmt, LI, Access]() -> bool {
4937175cffbSMichael Kruse         TargetStmt->prependInstruction(LI);
494*601d7eabSKarthika Devi C         POLLY_DEBUG(
4957175cffbSMichael Kruse             dbgs() << "    forwarded known load with preexisting MemoryAccess"
4967175cffbSMichael Kruse                    << Access << "\n");
49798031b66SFangrui Song         (void)Access;
4987175cffbSMichael Kruse 
4997175cffbSMichael Kruse         NumKnownLoadsForwarded++;
5007175cffbSMichael Kruse         TotalKnownLoadsForwarded++;
5017175cffbSMichael Kruse         return true;
5027175cffbSMichael Kruse       };
5037175cffbSMichael Kruse       return ForwardingAction::canForward(
5047175cffbSMichael Kruse           ExecAction, {{LI->getPointerOperand(), DefStmt}}, true);
5057175cffbSMichael Kruse     }
5067175cffbSMichael Kruse 
5077175cffbSMichael Kruse     // Allow the following Isl calculations (until we return the
5087175cffbSMichael Kruse     // ForwardingAction, excluding the code inside the lambda that will be
5097175cffbSMichael Kruse     // executed later) to fail.
5107175cffbSMichael Kruse     IslQuotaScope QuotaScope = MaxOpGuard.enter();
51189972e21SMichael Kruse 
51270af4f57SMichael Kruse     // { DomainDef[] -> ValInst[] }
51370af4f57SMichael Kruse     isl::map ExpectedVal = makeValInst(Inst, UseStmt, UseLoop);
514d51fbfcaSMichael Kruse     assert(!isNormalized(ExpectedVal).is_false() &&
515d51fbfcaSMichael Kruse            "LoadInsts are always normalized");
51670af4f57SMichael Kruse 
517d3ce899dSMichael Kruse     // { DomainUse[] -> DomainTarget[] }
518d3ce899dSMichael Kruse     isl::map UseToTarget = getDefToTarget(UseStmt, TargetStmt);
519d3ce899dSMichael Kruse 
52070af4f57SMichael Kruse     // { DomainTarget[] -> ValInst[] }
52170af4f57SMichael Kruse     isl::map TargetExpectedVal = ExpectedVal.apply_domain(UseToTarget);
52270af4f57SMichael Kruse     isl::union_map TranslatedExpectedVal =
52370af4f57SMichael Kruse         isl::union_map(TargetExpectedVal).apply_range(Translator);
52470af4f57SMichael Kruse 
52570af4f57SMichael Kruse     // { DomainTarget[] -> Element[] }
52670af4f57SMichael Kruse     isl::union_map Candidates = findSameContentElements(TranslatedExpectedVal);
52770af4f57SMichael Kruse 
52870af4f57SMichael Kruse     isl::map SameVal = singleLocation(Candidates, getDomainFor(TargetStmt));
5297c7978a1Spatacca     if (SameVal.is_null())
5307175cffbSMichael Kruse       return ForwardingAction::notApplicable();
531822dfe27SMichael Kruse 
532*601d7eabSKarthika Devi C     POLLY_DEBUG(dbgs() << "      expected values where " << TargetExpectedVal
5337175cffbSMichael Kruse                        << "\n");
534*601d7eabSKarthika Devi C     POLLY_DEBUG(dbgs() << "      candidate elements where " << Candidates
5357175cffbSMichael Kruse                        << "\n");
53670af4f57SMichael Kruse 
53770af4f57SMichael Kruse     // { ValInst[] }
53870af4f57SMichael Kruse     isl::space ValInstSpace = ExpectedVal.get_space().range();
53970af4f57SMichael Kruse 
54070af4f57SMichael Kruse     // After adding a new load to the SCoP, also update the Known content
54170af4f57SMichael Kruse     // about it. The new load will have a known ValInst of
54270af4f57SMichael Kruse     // { [DomainTarget[] -> Value[]] }
54370af4f57SMichael Kruse     // but which -- because it is a copy of it -- has same value as the
54470af4f57SMichael Kruse     // { [DomainDef[] -> Value[]] }
54570af4f57SMichael Kruse     // that it replicates. Instead of  cloning the known content of
54670af4f57SMichael Kruse     // [DomainDef[] -> Value[]]
54770af4f57SMichael Kruse     // for DomainTarget[], we add a 'translator' that maps
54870af4f57SMichael Kruse     // [DomainTarget[] -> Value[]] to [DomainDef[] -> Value[]]
54970af4f57SMichael Kruse     // before comparing to the known content.
55070af4f57SMichael Kruse     // TODO: 'Translator' could also be used to map PHINodes to their incoming
55170af4f57SMichael Kruse     // ValInsts.
5527175cffbSMichael Kruse     isl::map LocalTranslator;
5537175cffbSMichael Kruse     if (!ValInstSpace.is_wrapping().is_false()) {
55470af4f57SMichael Kruse       // { DefDomain[] -> Value[] }
55570af4f57SMichael Kruse       isl::map ValInsts = ExpectedVal.range().unwrap();
55670af4f57SMichael Kruse 
55770af4f57SMichael Kruse       // { DefDomain[] }
55870af4f57SMichael Kruse       isl::set DefDomain = ValInsts.domain();
55970af4f57SMichael Kruse 
56070af4f57SMichael Kruse       // { Value[] }
56170af4f57SMichael Kruse       isl::space ValSpace = ValInstSpace.unwrap().range();
56270af4f57SMichael Kruse 
56370af4f57SMichael Kruse       // { Value[] -> Value[] }
56470af4f57SMichael Kruse       isl::map ValToVal =
56570af4f57SMichael Kruse           isl::map::identity(ValSpace.map_from_domain_and_range(ValSpace));
56670af4f57SMichael Kruse 
567d3ce899dSMichael Kruse       // { DomainDef[] -> DomainTarget[] }
568d3ce899dSMichael Kruse       isl::map DefToTarget = getDefToTarget(DefStmt, TargetStmt);
569d3ce899dSMichael Kruse 
57070af4f57SMichael Kruse       // { [TargetDomain[] -> Value[]] -> [DefDomain[] -> Value] }
5717175cffbSMichael Kruse       LocalTranslator = DefToTarget.reverse().product(ValToVal);
572*601d7eabSKarthika Devi C       POLLY_DEBUG(dbgs() << "      local translator is " << LocalTranslator
57370af4f57SMichael Kruse                          << "\n");
5747175cffbSMichael Kruse 
5757c7978a1Spatacca       if (LocalTranslator.is_null())
5767175cffbSMichael Kruse         return ForwardingAction::notApplicable();
57770af4f57SMichael Kruse     }
5787175cffbSMichael Kruse 
5797175cffbSMichael Kruse     auto ExecAction = [this, TargetStmt, LI, SameVal,
5807175cffbSMichael Kruse                        LocalTranslator]() -> bool {
5817175cffbSMichael Kruse       TargetStmt->prependInstruction(LI);
5827175cffbSMichael Kruse       MemoryAccess *Access = makeReadArrayAccess(TargetStmt, LI, SameVal);
583*601d7eabSKarthika Devi C       POLLY_DEBUG(dbgs() << "    forwarded known load with new MemoryAccess"
5847175cffbSMichael Kruse                          << Access << "\n");
58598031b66SFangrui Song       (void)Access;
5867175cffbSMichael Kruse 
5877c7978a1Spatacca       if (!LocalTranslator.is_null())
588d5ee355fSRiccardo Mori         Translator = Translator.unite(LocalTranslator);
58970af4f57SMichael Kruse 
59070af4f57SMichael Kruse       NumKnownLoadsForwarded++;
59170af4f57SMichael Kruse       TotalKnownLoadsForwarded++;
5927175cffbSMichael Kruse       return true;
5937175cffbSMichael Kruse     };
5947175cffbSMichael Kruse     return ForwardingAction::canForward(
5957175cffbSMichael Kruse         ExecAction, {{LI->getPointerOperand(), DefStmt}}, true);
596822dfe27SMichael Kruse   }
597822dfe27SMichael Kruse 
598822dfe27SMichael Kruse   /// Forward a scalar by redirecting the access to an array element that stores
599822dfe27SMichael Kruse   /// the same value.
600822dfe27SMichael Kruse   ///
601822dfe27SMichael Kruse   /// @param TargetStmt  The statement the operand tree will be copied to.
602822dfe27SMichael Kruse   /// @param Inst        The scalar to forward.
603822dfe27SMichael Kruse   /// @param UseStmt     The statement that uses @p Inst.
604822dfe27SMichael Kruse   /// @param UseLoop     The loop @p Inst is used in.
605822dfe27SMichael Kruse   /// @param DefStmt     The statement @p Inst is defined in.
606822dfe27SMichael Kruse   /// @param DefLoop     The loop which contains @p Inst.
607822dfe27SMichael Kruse   ///
6087175cffbSMichael Kruse   /// @return A ForwardingAction object describing the feasibility and
6097175cffbSMichael Kruse   ///         profitability evaluation and the callback carrying-out the value
6107175cffbSMichael Kruse   ///         forwarding.
reloadKnownContent(ScopStmt * TargetStmt,Instruction * Inst,ScopStmt * UseStmt,Loop * UseLoop,ScopStmt * DefStmt,Loop * DefLoop)6117175cffbSMichael Kruse   ForwardingAction reloadKnownContent(ScopStmt *TargetStmt, Instruction *Inst,
612822dfe27SMichael Kruse                                       ScopStmt *UseStmt, Loop *UseLoop,
6137175cffbSMichael Kruse                                       ScopStmt *DefStmt, Loop *DefLoop) {
614822dfe27SMichael Kruse     // Cannot do anything without successful known analysis.
615d3ce899dSMichael Kruse     if (Known.is_null() || Translator.is_null() ||
616d3ce899dSMichael Kruse         MaxOpGuard.hasQuotaExceeded())
6177175cffbSMichael Kruse       return ForwardingAction::notApplicable();
618822dfe27SMichael Kruse 
6197175cffbSMichael Kruse     // Don't spend too much time analyzing whether it can be reloaded.
6207175cffbSMichael Kruse     IslQuotaScope QuotaScope = MaxOpGuard.enter();
6214d3f3c72SMichael Kruse 
622822dfe27SMichael Kruse     // { DomainDef[] -> ValInst[] }
62368821a8bSMichael Kruse     isl::union_map ExpectedVal = makeNormalizedValInst(Inst, UseStmt, UseLoop);
624822dfe27SMichael Kruse 
625d3ce899dSMichael Kruse     // { DomainUse[] -> DomainTarget[] }
626d3ce899dSMichael Kruse     isl::map UseToTarget = getDefToTarget(UseStmt, TargetStmt);
627d3ce899dSMichael Kruse 
628822dfe27SMichael Kruse     // { DomainTarget[] -> ValInst[] }
629822dfe27SMichael Kruse     isl::union_map TargetExpectedVal = ExpectedVal.apply_domain(UseToTarget);
630822dfe27SMichael Kruse     isl::union_map TranslatedExpectedVal =
631822dfe27SMichael Kruse         TargetExpectedVal.apply_range(Translator);
632822dfe27SMichael Kruse 
633822dfe27SMichael Kruse     // { DomainTarget[] -> Element[] }
634822dfe27SMichael Kruse     isl::union_map Candidates = findSameContentElements(TranslatedExpectedVal);
635822dfe27SMichael Kruse 
636822dfe27SMichael Kruse     isl::map SameVal = singleLocation(Candidates, getDomainFor(TargetStmt));
6377175cffbSMichael Kruse     simplify(SameVal);
6387c7978a1Spatacca     if (SameVal.is_null())
6397175cffbSMichael Kruse       return ForwardingAction::notApplicable();
640822dfe27SMichael Kruse 
6417175cffbSMichael Kruse     auto ExecAction = [this, TargetStmt, Inst, SameVal]() {
6427175cffbSMichael Kruse       MemoryAccess *Access = TargetStmt->lookupInputAccessOf(Inst);
643822dfe27SMichael Kruse       if (!Access)
644822dfe27SMichael Kruse         Access = TargetStmt->ensureValueRead(Inst);
645822dfe27SMichael Kruse       Access->setNewAccessRelation(SameVal);
646822dfe27SMichael Kruse 
647*601d7eabSKarthika Devi C       POLLY_DEBUG(dbgs() << "    forwarded known content of " << *Inst
648c1cf51e7SMichael Kruse                          << " which is " << SameVal << "\n");
649822dfe27SMichael Kruse       TotalReloads++;
650822dfe27SMichael Kruse       NumReloads++;
6517175cffbSMichael Kruse       return false;
6527175cffbSMichael Kruse     };
6537175cffbSMichael Kruse 
6547175cffbSMichael Kruse     return ForwardingAction::canForward(ExecAction, {}, true);
65570af4f57SMichael Kruse   }
65670af4f57SMichael Kruse 
657a9a70863SMichael Kruse   /// Forwards a speculatively executable instruction.
658a9a70863SMichael Kruse   ///
65970af4f57SMichael Kruse   /// @param TargetStmt  The statement the operand tree will be copied to.
66070af4f57SMichael Kruse   /// @param UseInst     The (possibly speculatable) instruction to forward.
66170af4f57SMichael Kruse   /// @param DefStmt     The statement @p UseInst is defined in.
66270af4f57SMichael Kruse   /// @param DefLoop     The loop which contains @p UseInst.
663a9a70863SMichael Kruse   ///
6647175cffbSMichael Kruse   /// @return A ForwardingAction object describing the feasibility and
6657175cffbSMichael Kruse   ///         profitability evaluation and the callback carrying-out the value
6667175cffbSMichael Kruse   ///         forwarding.
forwardSpeculatable(ScopStmt * TargetStmt,Instruction * UseInst,ScopStmt * DefStmt,Loop * DefLoop)6677175cffbSMichael Kruse   ForwardingAction forwardSpeculatable(ScopStmt *TargetStmt,
6687175cffbSMichael Kruse                                        Instruction *UseInst, ScopStmt *DefStmt,
6697175cffbSMichael Kruse                                        Loop *DefLoop) {
670a9a70863SMichael Kruse     // PHIs, unless synthesizable, are not yet supported.
671a9a70863SMichael Kruse     if (isa<PHINode>(UseInst))
6727175cffbSMichael Kruse       return ForwardingAction::notApplicable();
673a9a70863SMichael Kruse 
674a9a70863SMichael Kruse     // Compatible instructions must satisfy the following conditions:
675a9a70863SMichael Kruse     // 1. Idempotent (instruction will be copied, not moved; although its
676a9a70863SMichael Kruse     //    original instance might be removed by simplification)
677a9a70863SMichael Kruse     // 2. Not access memory (There might be memory writes between)
678a9a70863SMichael Kruse     // 3. Not cause undefined behaviour (we might copy to a location when the
679a9a70863SMichael Kruse     //    original instruction was no executed; this is currently not possible
680a9a70863SMichael Kruse     //    because we do not forward PHINodes)
681a9a70863SMichael Kruse     // 4. Not leak memory if executed multiple times (i.e. malloc)
682a9a70863SMichael Kruse     //
683a9a70863SMichael Kruse     // Instruction::mayHaveSideEffects is not sufficient because it considers
684a9a70863SMichael Kruse     // malloc to not have side-effects. llvm::isSafeToSpeculativelyExecute is
685a9a70863SMichael Kruse     // not sufficient because it allows memory accesses.
68693102505SPhilip Reames     if (mayHaveNonDefUseDependency(*UseInst))
6877175cffbSMichael Kruse       return ForwardingAction::notApplicable();
688a9a70863SMichael Kruse 
6897175cffbSMichael Kruse     SmallVector<ForwardingAction::KeyTy, 4> Depends;
6907175cffbSMichael Kruse     Depends.reserve(UseInst->getNumOperands());
691a9a70863SMichael Kruse     for (Value *OpVal : UseInst->operand_values()) {
692a9a70863SMichael Kruse       ForwardingDecision OpDecision =
6937175cffbSMichael Kruse           forwardTree(TargetStmt, OpVal, DefStmt, DefLoop);
694a9a70863SMichael Kruse       switch (OpDecision) {
695a9a70863SMichael Kruse       case FD_CannotForward:
6967175cffbSMichael Kruse         return ForwardingAction::cannotForward();
697a9a70863SMichael Kruse 
698a9a70863SMichael Kruse       case FD_CanForwardLeaf:
699822dfe27SMichael Kruse       case FD_CanForwardProfitably:
7007175cffbSMichael Kruse         Depends.emplace_back(OpVal, DefStmt);
701a9a70863SMichael Kruse         break;
702a9a70863SMichael Kruse 
703a9a70863SMichael Kruse       case FD_NotApplicable:
7047175cffbSMichael Kruse       case FD_Unknown:
7057175cffbSMichael Kruse         llvm_unreachable(
7067175cffbSMichael Kruse             "forwardTree should never return FD_NotApplicable/FD_Unknown");
707a9a70863SMichael Kruse       }
708a9a70863SMichael Kruse     }
709a9a70863SMichael Kruse 
7102213a354SFangrui Song     auto ExecAction = [this, TargetStmt, UseInst]() {
7117175cffbSMichael Kruse       // To ensure the right order, prepend this instruction before its
7127175cffbSMichael Kruse       // operands. This ensures that its operands are inserted before the
7137175cffbSMichael Kruse       // instruction using them.
7147175cffbSMichael Kruse       TargetStmt->prependInstruction(UseInst);
715c1cf51e7SMichael Kruse 
716*601d7eabSKarthika Devi C       POLLY_DEBUG(dbgs() << "    forwarded speculable instruction: " << *UseInst
717c1cf51e7SMichael Kruse                          << "\n");
7187175cffbSMichael Kruse       NumInstructionsCopied++;
7197175cffbSMichael Kruse       TotalInstructionsCopied++;
7207175cffbSMichael Kruse       return true;
7217175cffbSMichael Kruse     };
7227175cffbSMichael Kruse     return ForwardingAction::canForward(ExecAction, Depends, true);
723a9a70863SMichael Kruse   }
724a9a70863SMichael Kruse 
7257175cffbSMichael Kruse   /// Determines whether an operand tree can be forwarded and returns
7267175cffbSMichael Kruse   /// instructions how to do so in the form of a ForwardingAction object.
727a6b2de3bSMichael Kruse   ///
728a6b2de3bSMichael Kruse   /// @param TargetStmt  The statement the operand tree will be copied to.
729a6b2de3bSMichael Kruse   /// @param UseVal      The value (usually an instruction) which is root of an
730a6b2de3bSMichael Kruse   ///                    operand tree.
731a6b2de3bSMichael Kruse   /// @param UseStmt     The statement that uses @p UseVal.
732a6b2de3bSMichael Kruse   /// @param UseLoop     The loop @p UseVal is used in.
733a6b2de3bSMichael Kruse   ///
7347175cffbSMichael Kruse   /// @return A ForwardingAction object describing the feasibility and
7357175cffbSMichael Kruse   ///         profitability evaluation and the callback carrying-out the value
7367175cffbSMichael Kruse   ///         forwarding.
forwardTreeImpl(ScopStmt * TargetStmt,Value * UseVal,ScopStmt * UseStmt,Loop * UseLoop)7377175cffbSMichael Kruse   ForwardingAction forwardTreeImpl(ScopStmt *TargetStmt, Value *UseVal,
7387175cffbSMichael Kruse                                    ScopStmt *UseStmt, Loop *UseLoop) {
73970af4f57SMichael Kruse     ScopStmt *DefStmt = nullptr;
74070af4f57SMichael Kruse     Loop *DefLoop = nullptr;
74170af4f57SMichael Kruse 
74270af4f57SMichael Kruse     // { DefDomain[] -> TargetDomain[] }
74370af4f57SMichael Kruse     isl::map DefToTarget;
74470af4f57SMichael Kruse 
745a6b2de3bSMichael Kruse     VirtualUse VUse = VirtualUse::create(UseStmt, UseLoop, UseVal, true);
746a6b2de3bSMichael Kruse     switch (VUse.getKind()) {
747a6b2de3bSMichael Kruse     case VirtualUse::Constant:
748a6b2de3bSMichael Kruse     case VirtualUse::Block:
749e5f4706aSMichael Kruse     case VirtualUse::Hoisted:
750a6b2de3bSMichael Kruse       // These can be used anywhere without special considerations.
751c1cf51e7SMichael Kruse       return ForwardingAction::triviallyForwardable(false, UseVal);
752a6b2de3bSMichael Kruse 
7539f6e41cdSMichael Kruse     case VirtualUse::Synthesizable: {
7549f6e41cdSMichael Kruse       // Check if the value is synthesizable at the new location as well. This
7559f6e41cdSMichael Kruse       // might be possible when leaving a loop for which ScalarEvolution is
7569f6e41cdSMichael Kruse       // unable to derive the exit value for.
7579f6e41cdSMichael Kruse       // TODO: If there is a LCSSA PHI at the loop exit, use that one.
7589f6e41cdSMichael Kruse       // If the SCEV contains a SCEVAddRecExpr, we currently depend on that we
7599f6e41cdSMichael Kruse       // do not forward past its loop header. This would require us to use a
7609f6e41cdSMichael Kruse       // previous loop induction variable instead the current one. We currently
7619f6e41cdSMichael Kruse       // do not allow forwarding PHI nodes, thus this should never occur (the
7629f6e41cdSMichael Kruse       // only exception where no phi is necessary being an unreachable loop
7639f6e41cdSMichael Kruse       // without edge from the outside).
7649f6e41cdSMichael Kruse       VirtualUse TargetUse = VirtualUse::create(
7659f6e41cdSMichael Kruse           S, TargetStmt, TargetStmt->getSurroundingLoop(), UseVal, true);
7669f6e41cdSMichael Kruse       if (TargetUse.getKind() == VirtualUse::Synthesizable)
767c1cf51e7SMichael Kruse         return ForwardingAction::triviallyForwardable(false, UseVal);
7689f6e41cdSMichael Kruse 
769*601d7eabSKarthika Devi C       POLLY_DEBUG(
770349506a9SNicola Zaghen           dbgs() << "    Synthesizable would not be synthesizable anymore: "
7719f6e41cdSMichael Kruse                  << *UseVal << "\n");
7727175cffbSMichael Kruse       return ForwardingAction::cannotForward();
7739f6e41cdSMichael Kruse     }
774a6b2de3bSMichael Kruse 
7757175cffbSMichael Kruse     case VirtualUse::ReadOnly: {
776c1cf51e7SMichael Kruse       if (!ModelReadOnlyScalars)
777c1cf51e7SMichael Kruse         return ForwardingAction::triviallyForwardable(false, UseVal);
778c1cf51e7SMichael Kruse 
77907e8c36dSMichael Kruse       // If we model read-only scalars, we need to create a MemoryAccess for it.
7807175cffbSMichael Kruse       auto ExecAction = [this, TargetStmt, UseVal]() {
78107e8c36dSMichael Kruse         TargetStmt->ensureValueRead(UseVal);
78207e8c36dSMichael Kruse 
783*601d7eabSKarthika Devi C         POLLY_DEBUG(dbgs() << "    forwarded read-only value " << *UseVal
784c1cf51e7SMichael Kruse                            << "\n");
78507e8c36dSMichael Kruse         NumReadOnlyCopied++;
78607e8c36dSMichael Kruse         TotalReadOnlyCopied++;
7877175cffbSMichael Kruse 
7887175cffbSMichael Kruse         // Note that we cannot return true here. With a operand tree
7897175cffbSMichael Kruse         // depth of 0, UseVal is the use in TargetStmt that we try to replace.
7907175cffbSMichael Kruse         // With -polly-analyze-read-only-scalars=true we would ensure the
7917175cffbSMichael Kruse         // existence of a MemoryAccess (which already exists for a leaf) and be
7927175cffbSMichael Kruse         // removed again by tryForwardTree because it's goal is to remove this
7937175cffbSMichael Kruse         // scalar MemoryAccess. It interprets FD_CanForwardTree as the
7947175cffbSMichael Kruse         // permission to do so.
7957175cffbSMichael Kruse         return false;
7967175cffbSMichael Kruse       };
7977175cffbSMichael Kruse       return ForwardingAction::canForward(ExecAction, {}, false);
7987175cffbSMichael Kruse     }
799a6b2de3bSMichael Kruse 
800a6b2de3bSMichael Kruse     case VirtualUse::Intra:
80170af4f57SMichael Kruse       // Knowing that UseStmt and DefStmt are the same statement instance, just
80270af4f57SMichael Kruse       // reuse the information about UseStmt for DefStmt
80370af4f57SMichael Kruse       DefStmt = UseStmt;
804a6b2de3bSMichael Kruse 
8050972a390SFangrui Song       [[fallthrough]];
80670af4f57SMichael Kruse     case VirtualUse::Inter:
80770af4f57SMichael Kruse       Instruction *Inst = cast<Instruction>(UseVal);
80870af4f57SMichael Kruse 
809cd3b9fedSMichael Kruse       if (!DefStmt) {
81070af4f57SMichael Kruse         DefStmt = S->getStmtFor(Inst);
811cd3b9fedSMichael Kruse         if (!DefStmt)
8127175cffbSMichael Kruse           return ForwardingAction::cannotForward();
813cd3b9fedSMichael Kruse       }
814cd3b9fedSMichael Kruse 
81570af4f57SMichael Kruse       DefLoop = LI->getLoopFor(Inst->getParent());
81670af4f57SMichael Kruse 
8177175cffbSMichael Kruse       ForwardingAction SpeculativeResult =
8187175cffbSMichael Kruse           forwardSpeculatable(TargetStmt, Inst, DefStmt, DefLoop);
8197175cffbSMichael Kruse       if (SpeculativeResult.Decision != FD_NotApplicable)
820a9a70863SMichael Kruse         return SpeculativeResult;
821a9a70863SMichael Kruse 
8227175cffbSMichael Kruse       ForwardingAction KnownResult = forwardKnownLoad(
8237175cffbSMichael Kruse           TargetStmt, Inst, UseStmt, UseLoop, DefStmt, DefLoop);
8247175cffbSMichael Kruse       if (KnownResult.Decision != FD_NotApplicable)
82570af4f57SMichael Kruse         return KnownResult;
82670af4f57SMichael Kruse 
8277175cffbSMichael Kruse       ForwardingAction ReloadResult = reloadKnownContent(
8287175cffbSMichael Kruse           TargetStmt, Inst, UseStmt, UseLoop, DefStmt, DefLoop);
8297175cffbSMichael Kruse       if (ReloadResult.Decision != FD_NotApplicable)
830822dfe27SMichael Kruse         return ReloadResult;
831822dfe27SMichael Kruse 
832a9a70863SMichael Kruse       // When no method is found to forward the operand tree, we effectively
833a9a70863SMichael Kruse       // cannot handle it.
834*601d7eabSKarthika Devi C       POLLY_DEBUG(dbgs() << "    Cannot forward instruction: " << *Inst
835*601d7eabSKarthika Devi C                          << "\n");
8367175cffbSMichael Kruse       return ForwardingAction::cannotForward();
8379f6e41cdSMichael Kruse     }
8389f6e41cdSMichael Kruse 
839a6b2de3bSMichael Kruse     llvm_unreachable("Case unhandled");
840a6b2de3bSMichael Kruse   }
841a6b2de3bSMichael Kruse 
8427175cffbSMichael Kruse   /// Determines whether an operand tree can be forwarded. Previous evaluations
8437175cffbSMichael Kruse   /// are cached.
8447175cffbSMichael Kruse   ///
8457175cffbSMichael Kruse   /// @param TargetStmt  The statement the operand tree will be copied to.
8467175cffbSMichael Kruse   /// @param UseVal      The value (usually an instruction) which is root of an
8477175cffbSMichael Kruse   ///                    operand tree.
8487175cffbSMichael Kruse   /// @param UseStmt     The statement that uses @p UseVal.
8497175cffbSMichael Kruse   /// @param UseLoop     The loop @p UseVal is used in.
8507175cffbSMichael Kruse   ///
8517175cffbSMichael Kruse   /// @return FD_CannotForward        if @p UseVal cannot be forwarded.
8527175cffbSMichael Kruse   ///         FD_CanForwardLeaf       if @p UseVal is forwardable, but not
8537175cffbSMichael Kruse   ///                                 profitable.
8547175cffbSMichael Kruse   ///         FD_CanForwardProfitably if @p UseVal is forwardable and useful to
8557175cffbSMichael Kruse   ///                                 do.
forwardTree(ScopStmt * TargetStmt,Value * UseVal,ScopStmt * UseStmt,Loop * UseLoop)8567175cffbSMichael Kruse   ForwardingDecision forwardTree(ScopStmt *TargetStmt, Value *UseVal,
8577175cffbSMichael Kruse                                  ScopStmt *UseStmt, Loop *UseLoop) {
8587175cffbSMichael Kruse     // Lookup any cached evaluation.
8597175cffbSMichael Kruse     auto It = ForwardingActions.find({UseVal, UseStmt});
8607175cffbSMichael Kruse     if (It != ForwardingActions.end())
8617175cffbSMichael Kruse       return It->second.Decision;
8627175cffbSMichael Kruse 
8637175cffbSMichael Kruse     // Make a new evaluation.
8647175cffbSMichael Kruse     ForwardingAction Action =
8657175cffbSMichael Kruse         forwardTreeImpl(TargetStmt, UseVal, UseStmt, UseLoop);
8667175cffbSMichael Kruse     ForwardingDecision Result = Action.Decision;
8677175cffbSMichael Kruse 
8687175cffbSMichael Kruse     // Remember for the next time.
8697175cffbSMichael Kruse     assert(!ForwardingActions.count({UseVal, UseStmt}) &&
8707175cffbSMichael Kruse            "circular dependency?");
8717175cffbSMichael Kruse     ForwardingActions.insert({{UseVal, UseStmt}, std::move(Action)});
8727175cffbSMichael Kruse 
8737175cffbSMichael Kruse     return Result;
8747175cffbSMichael Kruse   }
8757175cffbSMichael Kruse 
8767175cffbSMichael Kruse   /// Forward an operand tree using cached actions.
8777175cffbSMichael Kruse   ///
8787175cffbSMichael Kruse   /// @param Stmt   Statement the operand tree is moved into.
8797175cffbSMichael Kruse   /// @param UseVal Root of the operand tree within @p Stmt.
8807175cffbSMichael Kruse   /// @param RA     The MemoryAccess for @p UseVal that the forwarding intends
8817175cffbSMichael Kruse   ///               to remove.
applyForwardingActions(ScopStmt * Stmt,Value * UseVal,MemoryAccess * RA)8827175cffbSMichael Kruse   void applyForwardingActions(ScopStmt *Stmt, Value *UseVal, MemoryAccess *RA) {
8837175cffbSMichael Kruse     using ChildItTy =
8847175cffbSMichael Kruse         decltype(std::declval<ForwardingAction>().Depends.begin());
8857175cffbSMichael Kruse     using EdgeTy = std::pair<ForwardingAction *, ChildItTy>;
8867175cffbSMichael Kruse 
8877175cffbSMichael Kruse     DenseSet<ForwardingAction::KeyTy> Visited;
8887175cffbSMichael Kruse     SmallVector<EdgeTy, 32> Stack;
8897175cffbSMichael Kruse     SmallVector<ForwardingAction *, 32> Ordered;
8907175cffbSMichael Kruse 
8917175cffbSMichael Kruse     // Seed the tree search using the root value.
8927175cffbSMichael Kruse     assert(ForwardingActions.count({UseVal, Stmt}));
8937175cffbSMichael Kruse     ForwardingAction *RootAction = &ForwardingActions[{UseVal, Stmt}];
8947175cffbSMichael Kruse     Stack.emplace_back(RootAction, RootAction->Depends.begin());
8957175cffbSMichael Kruse 
8967175cffbSMichael Kruse     // Compute the postorder of the operand tree: all operands of an instruction
8977175cffbSMichael Kruse     // must be visited before the instruction itself. As an additional
8987175cffbSMichael Kruse     // requirement, the topological ordering must be 'compact': Any subtree node
8997175cffbSMichael Kruse     // must not be interleaved with nodes from a non-shared subtree. This is
9007175cffbSMichael Kruse     // because the same llvm::Instruction can be materialized multiple times as
9017175cffbSMichael Kruse     // used at different ScopStmts which might be different values. Intersecting
9027175cffbSMichael Kruse     // these lifetimes may result in miscompilations.
9037175cffbSMichael Kruse     // FIXME: Intersecting lifetimes might still be possible for the roots
9047175cffbSMichael Kruse     // themselves, since instructions are just prepended to a ScopStmt's
9057175cffbSMichael Kruse     // instruction list.
9067175cffbSMichael Kruse     while (!Stack.empty()) {
9077175cffbSMichael Kruse       EdgeTy &Top = Stack.back();
9087175cffbSMichael Kruse       ForwardingAction *TopAction = Top.first;
9097175cffbSMichael Kruse       ChildItTy &TopEdge = Top.second;
9107175cffbSMichael Kruse 
9117175cffbSMichael Kruse       if (TopEdge == TopAction->Depends.end()) {
9127175cffbSMichael Kruse         // Postorder sorting
9137175cffbSMichael Kruse         Ordered.push_back(TopAction);
9147175cffbSMichael Kruse         Stack.pop_back();
9157175cffbSMichael Kruse         continue;
9167175cffbSMichael Kruse       }
9177175cffbSMichael Kruse       ForwardingAction::KeyTy Key = *TopEdge;
9187175cffbSMichael Kruse 
9197175cffbSMichael Kruse       // Next edge for this level
9207175cffbSMichael Kruse       ++TopEdge;
9217175cffbSMichael Kruse 
9227175cffbSMichael Kruse       auto VisitIt = Visited.insert(Key);
9237175cffbSMichael Kruse       if (!VisitIt.second)
9247175cffbSMichael Kruse         continue;
9257175cffbSMichael Kruse 
9267175cffbSMichael Kruse       assert(ForwardingActions.count(Key) &&
9277175cffbSMichael Kruse              "Must not insert new actions during execution phase");
9287175cffbSMichael Kruse       ForwardingAction *ChildAction = &ForwardingActions[Key];
9297175cffbSMichael Kruse       Stack.emplace_back(ChildAction, ChildAction->Depends.begin());
9307175cffbSMichael Kruse     }
9317175cffbSMichael Kruse 
9327175cffbSMichael Kruse     // Actually, we need the reverse postorder because actions prepend new
9337175cffbSMichael Kruse     // instructions. Therefore, the first one will always be the action for the
9347175cffbSMichael Kruse     // operand tree's root.
9357175cffbSMichael Kruse     assert(Ordered.back() == RootAction);
9367175cffbSMichael Kruse     if (RootAction->Execute())
9377175cffbSMichael Kruse       Stmt->removeSingleMemoryAccess(RA);
9387175cffbSMichael Kruse     Ordered.pop_back();
9397175cffbSMichael Kruse     for (auto DepAction : reverse(Ordered)) {
9407175cffbSMichael Kruse       assert(DepAction->Decision != FD_Unknown &&
9417175cffbSMichael Kruse              DepAction->Decision != FD_CannotForward);
9427175cffbSMichael Kruse       assert(DepAction != RootAction);
9437175cffbSMichael Kruse       DepAction->Execute();
9447175cffbSMichael Kruse     }
9457175cffbSMichael Kruse   }
9467175cffbSMichael Kruse 
947a6b2de3bSMichael Kruse   /// Try to forward an operand tree rooted in @p RA.
tryForwardTree(MemoryAccess * RA)948a6b2de3bSMichael Kruse   bool tryForwardTree(MemoryAccess *RA) {
949a6b2de3bSMichael Kruse     assert(RA->isLatestScalarKind());
950*601d7eabSKarthika Devi C     POLLY_DEBUG(dbgs() << "Trying to forward operand tree " << RA << "...\n");
951a6b2de3bSMichael Kruse 
952a6b2de3bSMichael Kruse     ScopStmt *Stmt = RA->getStatement();
953a6b2de3bSMichael Kruse     Loop *InLoop = Stmt->getSurroundingLoop();
954a6b2de3bSMichael Kruse 
95570af4f57SMichael Kruse     isl::map TargetToUse;
95670af4f57SMichael Kruse     if (!Known.is_null()) {
95770af4f57SMichael Kruse       isl::space DomSpace = Stmt->getDomainSpace();
95870af4f57SMichael Kruse       TargetToUse =
95970af4f57SMichael Kruse           isl::map::identity(DomSpace.map_from_domain_and_range(DomSpace));
96070af4f57SMichael Kruse     }
96170af4f57SMichael Kruse 
962d3ce899dSMichael Kruse     ForwardingDecision Assessment =
9637175cffbSMichael Kruse         forwardTree(Stmt, RA->getAccessValue(), Stmt, InLoop);
964a6b2de3bSMichael Kruse 
9657175cffbSMichael Kruse     // If considered feasible and profitable, forward it.
9667175cffbSMichael Kruse     bool Changed = false;
9677175cffbSMichael Kruse     if (Assessment == FD_CanForwardProfitably) {
9687175cffbSMichael Kruse       applyForwardingActions(Stmt, RA->getAccessValue(), RA);
9697175cffbSMichael Kruse       Changed = true;
9707175cffbSMichael Kruse     }
971a6b2de3bSMichael Kruse 
9727175cffbSMichael Kruse     ForwardingActions.clear();
9737175cffbSMichael Kruse     return Changed;
974a6b2de3bSMichael Kruse   }
975a6b2de3bSMichael Kruse 
976a6b2de3bSMichael Kruse   /// Return which SCoP this instance is processing.
getScop() const977a6b2de3bSMichael Kruse   Scop *getScop() const { return S; }
978a6b2de3bSMichael Kruse 
979a6b2de3bSMichael Kruse   /// Run the algorithm: Use value read accesses as operand tree roots and try
980a6b2de3bSMichael Kruse   /// to forward them into the statement.
forwardOperandTrees()981a6b2de3bSMichael Kruse   bool forwardOperandTrees() {
982a6b2de3bSMichael Kruse     for (ScopStmt &Stmt : *S) {
983a6b2de3bSMichael Kruse       bool StmtModified = false;
984a6b2de3bSMichael Kruse 
985a6b2de3bSMichael Kruse       // Because we are modifying the MemoryAccess list, collect them first to
986a6b2de3bSMichael Kruse       // avoid iterator invalidation.
987c8a0e27cSMichael Kruse       SmallVector<MemoryAccess *, 16> Accs(Stmt.begin(), Stmt.end());
988c8a0e27cSMichael Kruse 
989c8a0e27cSMichael Kruse       for (MemoryAccess *RA : Accs) {
990a6b2de3bSMichael Kruse         if (!RA->isRead())
991a6b2de3bSMichael Kruse           continue;
992a6b2de3bSMichael Kruse         if (!RA->isLatestScalarKind())
993a6b2de3bSMichael Kruse           continue;
994a6b2de3bSMichael Kruse 
995a6b2de3bSMichael Kruse         if (tryForwardTree(RA)) {
996a6b2de3bSMichael Kruse           Modified = true;
997a6b2de3bSMichael Kruse           StmtModified = true;
998a6b2de3bSMichael Kruse           NumForwardedTrees++;
999a6b2de3bSMichael Kruse           TotalForwardedTrees++;
1000a6b2de3bSMichael Kruse         }
1001a6b2de3bSMichael Kruse       }
1002a6b2de3bSMichael Kruse 
1003a6b2de3bSMichael Kruse       if (StmtModified) {
1004a6b2de3bSMichael Kruse         NumModifiedStmts++;
1005a6b2de3bSMichael Kruse         TotalModifiedStmts++;
1006a6b2de3bSMichael Kruse       }
1007a6b2de3bSMichael Kruse     }
1008a6b2de3bSMichael Kruse 
1009e8227804SMichael Kruse     if (Modified) {
1010a6b2de3bSMichael Kruse       ScopsModified++;
1011e8227804SMichael Kruse       S->realignParams();
1012e8227804SMichael Kruse     }
1013a6b2de3bSMichael Kruse     return Modified;
1014a6b2de3bSMichael Kruse   }
1015a6b2de3bSMichael Kruse 
1016a6b2de3bSMichael Kruse   /// Print the pass result, performed transformations and the SCoP after the
1017a6b2de3bSMichael Kruse   /// transformation.
print(raw_ostream & OS,int Indent=0)10189248fde5SEugene Zelenko   void print(raw_ostream &OS, int Indent = 0) {
1019a6b2de3bSMichael Kruse     printStatistics(OS, Indent);
1020a6b2de3bSMichael Kruse 
1021a6b2de3bSMichael Kruse     if (!Modified) {
1022a6b2de3bSMichael Kruse       // This line can easily be checked in regression tests.
1023a6b2de3bSMichael Kruse       OS << "ForwardOpTree executed, but did not modify anything\n";
1024a6b2de3bSMichael Kruse       return;
1025a6b2de3bSMichael Kruse     }
1026a6b2de3bSMichael Kruse 
1027a6b2de3bSMichael Kruse     printStatements(OS, Indent);
1028a6b2de3bSMichael Kruse   }
10294c64d8eeSMichael Kruse 
isModified() const10304c64d8eeSMichael Kruse   bool isModified() const { return Modified; }
1031a6b2de3bSMichael Kruse };
1032a6b2de3bSMichael Kruse 
runForwardOpTree(Scop & S,LoopInfo & LI)10334c64d8eeSMichael Kruse static std::unique_ptr<ForwardOpTreeImpl> runForwardOpTree(Scop &S,
10344c64d8eeSMichael Kruse                                                            LoopInfo &LI) {
1035a6b2de3bSMichael Kruse   std::unique_ptr<ForwardOpTreeImpl> Impl;
103689972e21SMichael Kruse   {
103700fd43b3SPhilip Pfaffe     IslMaxOperationsGuard MaxOpGuard(S.getIslCtx().get(), MaxOps, false);
1038736259e3SJonas Devlieghere     Impl = std::make_unique<ForwardOpTreeImpl>(&S, &LI, MaxOpGuard);
1039a6b2de3bSMichael Kruse 
104070af4f57SMichael Kruse     if (AnalyzeKnown) {
1041*601d7eabSKarthika Devi C       POLLY_DEBUG(dbgs() << "Prepare forwarders...\n");
104270af4f57SMichael Kruse       Impl->computeKnownValues();
104370af4f57SMichael Kruse     }
104470af4f57SMichael Kruse 
1045*601d7eabSKarthika Devi C     POLLY_DEBUG(dbgs() << "Forwarding operand trees...\n");
1046a6b2de3bSMichael Kruse     Impl->forwardOperandTrees();
1047a6b2de3bSMichael Kruse 
104889972e21SMichael Kruse     if (MaxOpGuard.hasQuotaExceeded()) {
1049*601d7eabSKarthika Devi C       POLLY_DEBUG(dbgs() << "Not all operations completed because of "
105089972e21SMichael Kruse                             "max_operations exceeded\n");
105189972e21SMichael Kruse       KnownOutOfQuota++;
105289972e21SMichael Kruse     }
105389972e21SMichael Kruse   }
105489972e21SMichael Kruse 
1055*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << "\nFinal Scop:\n");
1056*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << S);
1057a6b2de3bSMichael Kruse 
105806ed5292SMichael Kruse   // Update statistics
10594c64d8eeSMichael Kruse   Scop::ScopStatistics ScopStats = S.getStatistics();
106006ed5292SMichael Kruse   NumValueWrites += ScopStats.NumValueWrites;
106106ed5292SMichael Kruse   NumValueWritesInLoops += ScopStats.NumValueWritesInLoops;
106206ed5292SMichael Kruse   NumPHIWrites += ScopStats.NumPHIWrites;
106306ed5292SMichael Kruse   NumPHIWritesInLoops += ScopStats.NumPHIWritesInLoops;
106406ed5292SMichael Kruse   NumSingletonWrites += ScopStats.NumSingletonWrites;
106506ed5292SMichael Kruse   NumSingletonWritesInLoops += ScopStats.NumSingletonWritesInLoops;
106606ed5292SMichael Kruse 
10674c64d8eeSMichael Kruse   return Impl;
10684c64d8eeSMichael Kruse }
10694c64d8eeSMichael Kruse 
10704c64d8eeSMichael Kruse static PreservedAnalyses
runForwardOpTreeUsingNPM(Scop & S,ScopAnalysisManager & SAM,ScopStandardAnalysisResults & SAR,SPMUpdater & U,raw_ostream * OS)10714c64d8eeSMichael Kruse runForwardOpTreeUsingNPM(Scop &S, ScopAnalysisManager &SAM,
10724c64d8eeSMichael Kruse                          ScopStandardAnalysisResults &SAR, SPMUpdater &U,
10734c64d8eeSMichael Kruse                          raw_ostream *OS) {
10744c64d8eeSMichael Kruse   LoopInfo &LI = SAR.LI;
10754c64d8eeSMichael Kruse 
10764c64d8eeSMichael Kruse   std::unique_ptr<ForwardOpTreeImpl> Impl = runForwardOpTree(S, LI);
10774c64d8eeSMichael Kruse   if (OS) {
10784c64d8eeSMichael Kruse     *OS << "Printing analysis 'Polly - Forward operand tree' for region: '"
10794c64d8eeSMichael Kruse         << S.getName() << "' in function '" << S.getFunction().getName()
10804c64d8eeSMichael Kruse         << "':\n";
10814c64d8eeSMichael Kruse     if (Impl) {
10824c64d8eeSMichael Kruse       assert(Impl->getScop() == &S);
10834c64d8eeSMichael Kruse 
10844c64d8eeSMichael Kruse       Impl->print(*OS);
10854c64d8eeSMichael Kruse     }
10864c64d8eeSMichael Kruse   }
10874c64d8eeSMichael Kruse 
10884c64d8eeSMichael Kruse   if (!Impl->isModified())
10894c64d8eeSMichael Kruse     return PreservedAnalyses::all();
10904c64d8eeSMichael Kruse 
10914c64d8eeSMichael Kruse   PreservedAnalyses PA;
10924c64d8eeSMichael Kruse   PA.preserveSet<AllAnalysesOn<Module>>();
10934c64d8eeSMichael Kruse   PA.preserveSet<AllAnalysesOn<Function>>();
10944c64d8eeSMichael Kruse   PA.preserveSet<AllAnalysesOn<Loop>>();
10954c64d8eeSMichael Kruse   return PA;
10964c64d8eeSMichael Kruse }
10974c64d8eeSMichael Kruse 
10984c64d8eeSMichael Kruse /// Pass that redirects scalar reads to array elements that are known to contain
10994c64d8eeSMichael Kruse /// the same value.
11004c64d8eeSMichael Kruse ///
11014c64d8eeSMichael Kruse /// This reduces the number of scalar accesses and therefore potentially
11024c64d8eeSMichael Kruse /// increases the freedom of the scheduler. In the ideal case, all reads of a
11034c64d8eeSMichael Kruse /// scalar definition are redirected (We currently do not care about removing
11044c64d8eeSMichael Kruse /// the write in this case).  This is also useful for the main DeLICM pass as
11054c64d8eeSMichael Kruse /// there are less scalars to be mapped.
1106bd93df93SMichael Kruse class ForwardOpTreeWrapperPass final : public ScopPass {
11074c64d8eeSMichael Kruse private:
11084c64d8eeSMichael Kruse   /// The pass implementation, also holding per-scop data.
11094c64d8eeSMichael Kruse   std::unique_ptr<ForwardOpTreeImpl> Impl;
11104c64d8eeSMichael Kruse 
11114c64d8eeSMichael Kruse public:
11124c64d8eeSMichael Kruse   static char ID;
11134c64d8eeSMichael Kruse 
ForwardOpTreeWrapperPass()11144c64d8eeSMichael Kruse   explicit ForwardOpTreeWrapperPass() : ScopPass(ID) {}
11154c64d8eeSMichael Kruse   ForwardOpTreeWrapperPass(const ForwardOpTreeWrapperPass &) = delete;
11164c64d8eeSMichael Kruse   ForwardOpTreeWrapperPass &
11174c64d8eeSMichael Kruse   operator=(const ForwardOpTreeWrapperPass &) = delete;
11184c64d8eeSMichael Kruse 
getAnalysisUsage(AnalysisUsage & AU) const11194c64d8eeSMichael Kruse   void getAnalysisUsage(AnalysisUsage &AU) const override {
11204c64d8eeSMichael Kruse     AU.addRequiredTransitive<ScopInfoRegionPass>();
11214c64d8eeSMichael Kruse     AU.addRequired<LoopInfoWrapperPass>();
11224c64d8eeSMichael Kruse     AU.setPreservesAll();
11234c64d8eeSMichael Kruse   }
11244c64d8eeSMichael Kruse 
runOnScop(Scop & S)11254c64d8eeSMichael Kruse   bool runOnScop(Scop &S) override {
11264c64d8eeSMichael Kruse     // Free resources for previous SCoP's computation, if not yet done.
11274c64d8eeSMichael Kruse     releaseMemory();
11284c64d8eeSMichael Kruse 
11294c64d8eeSMichael Kruse     LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
11304c64d8eeSMichael Kruse 
11314c64d8eeSMichael Kruse     Impl = runForwardOpTree(S, LI);
11324c64d8eeSMichael Kruse 
1133a6b2de3bSMichael Kruse     return false;
1134a6b2de3bSMichael Kruse   }
1135a6b2de3bSMichael Kruse 
printScop(raw_ostream & OS,Scop & S) const11369248fde5SEugene Zelenko   void printScop(raw_ostream &OS, Scop &S) const override {
1137a6b2de3bSMichael Kruse     if (!Impl)
1138a6b2de3bSMichael Kruse       return;
1139a6b2de3bSMichael Kruse 
1140a6b2de3bSMichael Kruse     assert(Impl->getScop() == &S);
1141a6b2de3bSMichael Kruse     Impl->print(OS);
1142a6b2de3bSMichael Kruse   }
1143a6b2de3bSMichael Kruse 
releaseMemory()11449248fde5SEugene Zelenko   void releaseMemory() override { Impl.reset(); }
1145a6b2de3bSMichael Kruse }; // class ForwardOpTree
1146a6b2de3bSMichael Kruse 
11474c64d8eeSMichael Kruse char ForwardOpTreeWrapperPass::ID;
11485c028081SMichael Kruse 
11495c028081SMichael Kruse /// Print result from ForwardOpTreeWrapperPass.
1150bd93df93SMichael Kruse class ForwardOpTreePrinterLegacyPass final : public ScopPass {
11515c028081SMichael Kruse public:
11525c028081SMichael Kruse   static char ID;
11535c028081SMichael Kruse 
ForwardOpTreePrinterLegacyPass()11548de23009SOwen Pan   ForwardOpTreePrinterLegacyPass() : ForwardOpTreePrinterLegacyPass(outs()) {}
ForwardOpTreePrinterLegacyPass(llvm::raw_ostream & OS)11555c028081SMichael Kruse   explicit ForwardOpTreePrinterLegacyPass(llvm::raw_ostream &OS)
11565c028081SMichael Kruse       : ScopPass(ID), OS(OS) {}
11575c028081SMichael Kruse 
runOnScop(Scop & S)11585c028081SMichael Kruse   bool runOnScop(Scop &S) override {
11595c028081SMichael Kruse     ForwardOpTreeWrapperPass &P = getAnalysis<ForwardOpTreeWrapperPass>();
11605c028081SMichael Kruse 
11615c028081SMichael Kruse     OS << "Printing analysis '" << P.getPassName() << "' for region: '"
11625c028081SMichael Kruse        << S.getRegion().getNameStr() << "' in function '"
11635c028081SMichael Kruse        << S.getFunction().getName() << "':\n";
11645c028081SMichael Kruse     P.printScop(OS, S);
11655c028081SMichael Kruse 
11665c028081SMichael Kruse     return false;
11675c028081SMichael Kruse   }
11685c028081SMichael Kruse 
getAnalysisUsage(AnalysisUsage & AU) const11695c028081SMichael Kruse   void getAnalysisUsage(AnalysisUsage &AU) const override {
11705c028081SMichael Kruse     ScopPass::getAnalysisUsage(AU);
11715c028081SMichael Kruse     AU.addRequired<ForwardOpTreeWrapperPass>();
11725c028081SMichael Kruse     AU.setPreservesAll();
11735c028081SMichael Kruse   }
11745c028081SMichael Kruse 
11755c028081SMichael Kruse private:
11765c028081SMichael Kruse   llvm::raw_ostream &OS;
11775c028081SMichael Kruse };
11785c028081SMichael Kruse 
11795c028081SMichael Kruse char ForwardOpTreePrinterLegacyPass::ID = 0;
11809248fde5SEugene Zelenko } // namespace
1181a6b2de3bSMichael Kruse 
createForwardOpTreeWrapperPass()11824c64d8eeSMichael Kruse Pass *polly::createForwardOpTreeWrapperPass() {
11834c64d8eeSMichael Kruse   return new ForwardOpTreeWrapperPass();
11844c64d8eeSMichael Kruse }
1185a6b2de3bSMichael Kruse 
createForwardOpTreePrinterLegacyPass(llvm::raw_ostream & OS)11865c028081SMichael Kruse Pass *polly::createForwardOpTreePrinterLegacyPass(llvm::raw_ostream &OS) {
11875c028081SMichael Kruse   return new ForwardOpTreePrinterLegacyPass(OS);
11885c028081SMichael Kruse }
11895c028081SMichael Kruse 
run(Scop & S,ScopAnalysisManager & SAM,ScopStandardAnalysisResults & SAR,SPMUpdater & U)11904c64d8eeSMichael Kruse llvm::PreservedAnalyses ForwardOpTreePass::run(Scop &S,
11914c64d8eeSMichael Kruse                                                ScopAnalysisManager &SAM,
11924c64d8eeSMichael Kruse                                                ScopStandardAnalysisResults &SAR,
11934c64d8eeSMichael Kruse                                                SPMUpdater &U) {
11944c64d8eeSMichael Kruse   return runForwardOpTreeUsingNPM(S, SAM, SAR, U, nullptr);
11954c64d8eeSMichael Kruse }
11964c64d8eeSMichael Kruse 
11974c64d8eeSMichael Kruse llvm::PreservedAnalyses
run(Scop & S,ScopAnalysisManager & SAM,ScopStandardAnalysisResults & SAR,SPMUpdater & U)11984c64d8eeSMichael Kruse ForwardOpTreePrinterPass::run(Scop &S, ScopAnalysisManager &SAM,
11994c64d8eeSMichael Kruse                               ScopStandardAnalysisResults &SAR, SPMUpdater &U) {
12004c64d8eeSMichael Kruse   return runForwardOpTreeUsingNPM(S, SAM, SAR, U, &OS);
12014c64d8eeSMichael Kruse }
1202ad84c6f6SMichael Kruse 
1203ad84c6f6SMichael Kruse INITIALIZE_PASS_BEGIN(ForwardOpTreeWrapperPass, "polly-optree",
1204ad84c6f6SMichael Kruse                       "Polly - Forward operand tree", false, false)
1205ad84c6f6SMichael Kruse INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
1206ad84c6f6SMichael Kruse INITIALIZE_PASS_END(ForwardOpTreeWrapperPass, "polly-optree",
1207ad84c6f6SMichael Kruse                     "Polly - Forward operand tree", false, false)
12085c028081SMichael Kruse 
12095c028081SMichael Kruse INITIALIZE_PASS_BEGIN(ForwardOpTreePrinterLegacyPass, "polly-print-optree",
12105c028081SMichael Kruse                       "Polly - Print forward operand tree result", false, false)
12115c028081SMichael Kruse INITIALIZE_PASS_DEPENDENCY(ForwardOpTreeWrapperPass)
12125c028081SMichael Kruse INITIALIZE_PASS_END(ForwardOpTreePrinterLegacyPass, "polly-print-optree",
12135c028081SMichael Kruse                     "Polly - Print forward operand tree result", false, false)
1214