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 
4336550bacSMichael Kruse #define DEBUG_TYPE "polly-optree"
44a6b2de3bSMichael Kruse 
45a6b2de3bSMichael Kruse using namespace llvm;
469248fde5SEugene Zelenko using namespace polly;
47a6b2de3bSMichael Kruse 
4870af4f57SMichael Kruse static cl::opt<bool>
4970af4f57SMichael Kruse     AnalyzeKnown("polly-optree-analyze-known",
5070af4f57SMichael Kruse                  cl::desc("Analyze array contents for load forwarding"),
5170af4f57SMichael Kruse                  cl::cat(PollyCategory), cl::init(true), cl::Hidden);
5270af4f57SMichael Kruse 
5368821a8bSMichael Kruse static cl::opt<bool>
5468821a8bSMichael Kruse     NormalizePHIs("polly-optree-normalize-phi",
5568821a8bSMichael Kruse                   cl::desc("Replace PHIs by their incoming values"),
5668821a8bSMichael Kruse                   cl::cat(PollyCategory), cl::init(false), cl::Hidden);
5768821a8bSMichael Kruse 
58ef8325baSMichael Kruse static cl::opt<unsigned>
5970af4f57SMichael Kruse     MaxOps("polly-optree-max-ops",
6070af4f57SMichael Kruse            cl::desc("Maximum number of ISL operations to invest for known "
6170af4f57SMichael Kruse                     "analysis; 0=no limit"),
6270af4f57SMichael Kruse            cl::init(1000000), cl::cat(PollyCategory), cl::Hidden);
6370af4f57SMichael Kruse 
6470af4f57SMichael Kruse STATISTIC(KnownAnalyzed, "Number of successfully analyzed SCoPs");
6570af4f57SMichael Kruse STATISTIC(KnownOutOfQuota,
6670af4f57SMichael Kruse           "Analyses aborted because max_operations was reached");
6770af4f57SMichael Kruse 
68a6b2de3bSMichael Kruse STATISTIC(TotalInstructionsCopied, "Number of copied instructions");
6970af4f57SMichael Kruse STATISTIC(TotalKnownLoadsForwarded,
7070af4f57SMichael Kruse           "Number of forwarded loads because their value was known");
71822dfe27SMichael Kruse STATISTIC(TotalReloads, "Number of reloaded values");
7207e8c36dSMichael Kruse STATISTIC(TotalReadOnlyCopied, "Number of copied read-only accesses");
73a6b2de3bSMichael Kruse STATISTIC(TotalForwardedTrees, "Number of forwarded operand trees");
74a6b2de3bSMichael Kruse STATISTIC(TotalModifiedStmts,
75a6b2de3bSMichael Kruse           "Number of statements with at least one forwarded tree");
76a6b2de3bSMichael Kruse 
77a6b2de3bSMichael Kruse STATISTIC(ScopsModified, "Number of SCoPs with at least one forwarded tree");
78a6b2de3bSMichael Kruse 
7906ed5292SMichael Kruse STATISTIC(NumValueWrites, "Number of scalar value writes after OpTree");
8006ed5292SMichael Kruse STATISTIC(NumValueWritesInLoops,
8106ed5292SMichael Kruse           "Number of scalar value writes nested in affine loops after OpTree");
8206ed5292SMichael Kruse STATISTIC(NumPHIWrites, "Number of scalar phi writes after OpTree");
8306ed5292SMichael Kruse STATISTIC(NumPHIWritesInLoops,
8406ed5292SMichael Kruse           "Number of scalar phi writes nested in affine loops after OpTree");
8506ed5292SMichael Kruse STATISTIC(NumSingletonWrites, "Number of singleton writes after OpTree");
8606ed5292SMichael Kruse STATISTIC(NumSingletonWritesInLoops,
8706ed5292SMichael Kruse           "Number of singleton writes nested in affine loops after OpTree");
8806ed5292SMichael Kruse 
89a6b2de3bSMichael Kruse namespace {
90a6b2de3bSMichael Kruse 
91a6b2de3bSMichael Kruse /// The state of whether an operand tree was/can be forwarded.
92d85e345cSMichael Kruse ///
93d85e345cSMichael Kruse /// The items apply to an instructions and its operand tree with the instruction
94d85e345cSMichael Kruse /// as the root element. If the value in question is not an instruction in the
95d85e345cSMichael Kruse /// SCoP, it can be a leaf of an instruction's operand tree.
96a6b2de3bSMichael Kruse enum ForwardingDecision {
977175cffbSMichael Kruse   /// An uninitialized value.
987175cffbSMichael Kruse   FD_Unknown,
997175cffbSMichael Kruse 
100d85e345cSMichael Kruse   /// The root instruction or value cannot be forwarded at all.
101a6b2de3bSMichael Kruse   FD_CannotForward,
102d85e345cSMichael Kruse 
103d85e345cSMichael Kruse   /// The root instruction or value can be forwarded as a leaf of a larger
104d85e345cSMichael Kruse   /// operand tree.
105d85e345cSMichael Kruse   /// It does not make sense to move the value itself, it would just replace it
106d85e345cSMichael Kruse   /// by a use of itself. For instance, a constant "5" used in a statement can
107d85e345cSMichael Kruse   /// be forwarded, but it would just replace it by the same constant "5".
108d85e345cSMichael Kruse   /// However, it makes sense to move as an operand of
109d85e345cSMichael Kruse   ///
110d85e345cSMichael Kruse   ///   %add = add 5, 5
111d85e345cSMichael Kruse   ///
112d85e345cSMichael Kruse   /// where "5" is moved as part of a larger operand tree. "5" would be placed
113d85e345cSMichael Kruse   /// (disregarding for a moment that literal constants don't have a location
114d85e345cSMichael Kruse   /// and can be used anywhere) into the same statement as %add would.
11567752076SMichael Kruse   FD_CanForwardLeaf,
116d85e345cSMichael Kruse 
117822dfe27SMichael Kruse   /// The root instruction can be forwarded and doing so avoids a scalar
118822dfe27SMichael Kruse   /// dependency.
119822dfe27SMichael Kruse   ///
120822dfe27SMichael Kruse   /// This can be either because the operand tree can be moved to the target
121822dfe27SMichael Kruse   /// statement, or a memory access is redirected to read from a different
122822dfe27SMichael Kruse   /// location.
123822dfe27SMichael Kruse   FD_CanForwardProfitably,
124d85e345cSMichael Kruse 
125a9a70863SMichael Kruse   /// A forwarding method cannot be applied to the operand tree.
126a9a70863SMichael Kruse   /// The difference to FD_CannotForward is that there might be other methods
127a9a70863SMichael Kruse   /// that can handle it.
128a9a70863SMichael Kruse   FD_NotApplicable
129a6b2de3bSMichael Kruse };
130a6b2de3bSMichael Kruse 
1317175cffbSMichael Kruse /// Represents the evaluation of and action to taken when forwarding a value
1327175cffbSMichael Kruse /// from an operand tree.
1337175cffbSMichael Kruse struct ForwardingAction {
1347175cffbSMichael Kruse   using KeyTy = std::pair<Value *, ScopStmt *>;
1357175cffbSMichael Kruse 
1367175cffbSMichael Kruse   /// Evaluation of forwarding a value.
1377175cffbSMichael Kruse   ForwardingDecision Decision = FD_Unknown;
1387175cffbSMichael Kruse 
1397175cffbSMichael Kruse   /// Callback to execute the forwarding.
1407175cffbSMichael Kruse   /// Returning true allows deleting the polly::MemoryAccess if the value is the
1417175cffbSMichael Kruse   /// root of the operand tree (and its elimination the reason why the
1427175cffbSMichael Kruse   /// forwarding is done). Return false if the MemoryAccess is reused or there
1437175cffbSMichael Kruse   /// might be other users of the read accesses. In the letter case the
1447175cffbSMichael Kruse   /// polly::SimplifyPass can remove dead MemoryAccesses.
__anon533823240202__anon533823240111::ForwardingAction1457175cffbSMichael Kruse   std::function<bool()> Execute = []() -> bool {
1467175cffbSMichael Kruse     llvm_unreachable("unspecified how to forward");
1477175cffbSMichael Kruse   };
1487175cffbSMichael Kruse 
1497175cffbSMichael Kruse   /// Other values that need to be forwarded if this action is executed. Their
1507175cffbSMichael Kruse   /// actions are executed after this one.
1517175cffbSMichael Kruse   SmallVector<KeyTy, 4> Depends;
1527175cffbSMichael Kruse 
1537175cffbSMichael Kruse   /// Named ctor: The method creating this object does not apply to the kind of
1547175cffbSMichael Kruse   /// value, but other methods may.
notApplicable__anon533823240111::ForwardingAction1557175cffbSMichael Kruse   static ForwardingAction notApplicable() {
1567175cffbSMichael Kruse     ForwardingAction Result;
1577175cffbSMichael Kruse     Result.Decision = FD_NotApplicable;
1587175cffbSMichael Kruse     return Result;
1597175cffbSMichael Kruse   }
1607175cffbSMichael Kruse 
1617175cffbSMichael Kruse   /// Named ctor: The value cannot be forwarded.
cannotForward__anon533823240111::ForwardingAction1627175cffbSMichael Kruse   static ForwardingAction cannotForward() {
1637175cffbSMichael Kruse     ForwardingAction Result;
1647175cffbSMichael Kruse     Result.Decision = FD_CannotForward;
1657175cffbSMichael Kruse     return Result;
1667175cffbSMichael Kruse   }
1677175cffbSMichael Kruse 
1687175cffbSMichael Kruse   /// Named ctor: The value can just be used without any preparation.
triviallyForwardable__anon533823240111::ForwardingAction169c1cf51e7SMichael Kruse   static ForwardingAction triviallyForwardable(bool IsProfitable, Value *Val) {
1707175cffbSMichael Kruse     ForwardingAction Result;
1717175cffbSMichael Kruse     Result.Decision =
1727175cffbSMichael Kruse         IsProfitable ? FD_CanForwardProfitably : FD_CanForwardLeaf;
173c1cf51e7SMichael Kruse     Result.Execute = [=]() {
174c1cf51e7SMichael Kruse       LLVM_DEBUG(dbgs() << "    trivially forwarded: " << *Val << "\n");
175c1cf51e7SMichael Kruse       return true;
176c1cf51e7SMichael Kruse     };
1777175cffbSMichael Kruse     return Result;
1787175cffbSMichael Kruse   }
1797175cffbSMichael Kruse 
1807175cffbSMichael Kruse   /// Name ctor: The value can be forwarded by executing an action.
canForward__anon533823240111::ForwardingAction1817175cffbSMichael Kruse   static ForwardingAction canForward(std::function<bool()> Execute,
1827175cffbSMichael Kruse                                      ArrayRef<KeyTy> Depends,
1837175cffbSMichael Kruse                                      bool IsProfitable) {
1847175cffbSMichael Kruse     ForwardingAction Result;
1857175cffbSMichael Kruse     Result.Decision =
1867175cffbSMichael Kruse         IsProfitable ? FD_CanForwardProfitably : FD_CanForwardLeaf;
1877175cffbSMichael Kruse     Result.Execute = std::move(Execute);
1887175cffbSMichael Kruse     Result.Depends.append(Depends.begin(), Depends.end());
1897175cffbSMichael Kruse     return Result;
1907175cffbSMichael Kruse   }
1917175cffbSMichael Kruse };
1927175cffbSMichael Kruse 
193a6b2de3bSMichael Kruse /// Implementation of operand tree forwarding for a specific SCoP.
194a6b2de3bSMichael Kruse ///
195a6b2de3bSMichael Kruse /// For a statement that requires a scalar value (through a value read
196a6b2de3bSMichael Kruse /// MemoryAccess), see if its operand can be moved into the statement. If so,
197a6b2de3bSMichael Kruse /// the MemoryAccess is removed and the all the operand tree instructions are
198a6b2de3bSMichael Kruse /// moved into the statement. All original instructions are left in the source
199a6b2de3bSMichael Kruse /// statements. The simplification pass can clean these up.
200*bd93df93SMichael Kruse class ForwardOpTreeImpl final : ZoneAlgorithm {
201a6b2de3bSMichael Kruse private:
2027175cffbSMichael Kruse   using MemoizationTy = DenseMap<ForwardingAction::KeyTy, ForwardingAction>;
2037175cffbSMichael Kruse 
20489972e21SMichael Kruse   /// Scope guard to limit the number of isl operations for this pass.
20589972e21SMichael Kruse   IslMaxOperationsGuard &MaxOpGuard;
20689972e21SMichael Kruse 
207a6b2de3bSMichael Kruse   /// How many instructions have been copied to other statements.
208a6b2de3bSMichael Kruse   int NumInstructionsCopied = 0;
209a6b2de3bSMichael Kruse 
21070af4f57SMichael Kruse   /// Number of loads forwarded because their value was known.
21170af4f57SMichael Kruse   int NumKnownLoadsForwarded = 0;
21270af4f57SMichael Kruse 
213822dfe27SMichael Kruse   /// Number of values reloaded from known array elements.
214822dfe27SMichael Kruse   int NumReloads = 0;
215822dfe27SMichael Kruse 
21607e8c36dSMichael Kruse   /// How many read-only accesses have been copied.
21707e8c36dSMichael Kruse   int NumReadOnlyCopied = 0;
21807e8c36dSMichael Kruse 
219a6b2de3bSMichael Kruse   /// How many operand trees have been forwarded.
220a6b2de3bSMichael Kruse   int NumForwardedTrees = 0;
221a6b2de3bSMichael Kruse 
222a6b2de3bSMichael Kruse   /// Number of statements with at least one forwarded operand tree.
223a6b2de3bSMichael Kruse   int NumModifiedStmts = 0;
224a6b2de3bSMichael Kruse 
225a6b2de3bSMichael Kruse   /// Whether we carried out at least one change to the SCoP.
226a6b2de3bSMichael Kruse   bool Modified = false;
227a6b2de3bSMichael Kruse 
2287175cffbSMichael Kruse   /// Cache of how to forward values.
2297175cffbSMichael Kruse   /// The key of this map is the llvm::Value to be forwarded and the
2307175cffbSMichael Kruse   /// polly::ScopStmt it is forwarded from. This is because the same llvm::Value
2317175cffbSMichael Kruse   /// can evaluate differently depending on where it is evaluate. For instance,
2327175cffbSMichael Kruse   /// a synthesizable Scev represents a recurrence with an loop but the loop's
2337175cffbSMichael Kruse   /// exit value if evaluated after the loop.
2347175cffbSMichael Kruse   /// The cached results are only valid for the current TargetStmt.
2357175cffbSMichael Kruse   /// CHECKME: ScalarEvolution::getScevAtScope should take care for getting the
2367175cffbSMichael Kruse   /// exit value when instantiated outside of the loop. The primary concern is
2377175cffbSMichael Kruse   /// ambiguity when crossing PHI nodes, which currently is not supported.
2387175cffbSMichael Kruse   MemoizationTy ForwardingActions;
2397175cffbSMichael Kruse 
24070af4f57SMichael Kruse   /// Contains the zones where array elements are known to contain a specific
24170af4f57SMichael Kruse   /// value.
24270af4f57SMichael Kruse   /// { [Element[] -> Zone[]] -> ValInst[] }
24370af4f57SMichael Kruse   /// @see computeKnown()
24470af4f57SMichael Kruse   isl::union_map Known;
24570af4f57SMichael Kruse 
24670af4f57SMichael Kruse   /// Translator for newly introduced ValInsts to already existing ValInsts such
24770af4f57SMichael Kruse   /// that new introduced load instructions can reuse the Known analysis of its
24870af4f57SMichael Kruse   /// original load. { ValInst[] -> ValInst[] }
24970af4f57SMichael Kruse   isl::union_map Translator;
25070af4f57SMichael Kruse 
25170af4f57SMichael Kruse   /// Get list of array elements that do contain the same ValInst[] at Domain[].
25270af4f57SMichael Kruse   ///
25370af4f57SMichael Kruse   /// @param ValInst { Domain[] -> ValInst[] }
25470af4f57SMichael Kruse   ///                The values for which we search for alternative locations,
25570af4f57SMichael Kruse   ///                per statement instance.
25670af4f57SMichael Kruse   ///
25770af4f57SMichael Kruse   /// @return { Domain[] -> Element[] }
25870af4f57SMichael Kruse   ///         For each statement instance, the array elements that contain the
25970af4f57SMichael Kruse   ///         same ValInst.
findSameContentElements(isl::union_map ValInst)26070af4f57SMichael Kruse   isl::union_map findSameContentElements(isl::union_map ValInst) {
261e276e9f3SMichael Kruse     assert(!ValInst.is_single_valued().is_false());
26270af4f57SMichael Kruse 
26370af4f57SMichael Kruse     // { Domain[] }
26470af4f57SMichael Kruse     isl::union_set Domain = ValInst.domain();
26570af4f57SMichael Kruse 
26670af4f57SMichael Kruse     // { Domain[] -> Scatter[] }
26770af4f57SMichael Kruse     isl::union_map Schedule = getScatterFor(Domain);
26870af4f57SMichael Kruse 
26970af4f57SMichael Kruse     // { Element[] -> [Scatter[] -> ValInst[]] }
27070af4f57SMichael Kruse     isl::union_map MustKnownCurried =
27170af4f57SMichael Kruse         convertZoneToTimepoints(Known, isl::dim::in, false, true).curry();
27270af4f57SMichael Kruse 
27370af4f57SMichael Kruse     // { [Domain[] -> ValInst[]] -> Scatter[] }
27470af4f57SMichael Kruse     isl::union_map DomValSched = ValInst.domain_map().apply_range(Schedule);
27570af4f57SMichael Kruse 
27670af4f57SMichael Kruse     // { [Scatter[] -> ValInst[]] -> [Domain[] -> ValInst[]] }
27770af4f57SMichael Kruse     isl::union_map SchedValDomVal =
27870af4f57SMichael Kruse         DomValSched.range_product(ValInst.range_map()).reverse();
27970af4f57SMichael Kruse 
28070af4f57SMichael Kruse     // { Element[] -> [Domain[] -> ValInst[]] }
28170af4f57SMichael Kruse     isl::union_map MustKnownInst = MustKnownCurried.apply_range(SchedValDomVal);
28270af4f57SMichael Kruse 
28370af4f57SMichael Kruse     // { Domain[] -> Element[] }
28470af4f57SMichael Kruse     isl::union_map MustKnownMap =
28570af4f57SMichael Kruse         MustKnownInst.uncurry().domain().unwrap().reverse();
28670af4f57SMichael Kruse     simplify(MustKnownMap);
28770af4f57SMichael Kruse 
28870af4f57SMichael Kruse     return MustKnownMap;
28970af4f57SMichael Kruse   }
29070af4f57SMichael Kruse 
29170af4f57SMichael Kruse   /// Find a single array element for each statement instance, within a single
29270af4f57SMichael Kruse   /// array.
29370af4f57SMichael Kruse   ///
29470af4f57SMichael Kruse   /// @param MustKnown { Domain[] -> Element[] }
29570af4f57SMichael Kruse   ///                  Set of candidate array elements.
29670af4f57SMichael Kruse   /// @param Domain    { Domain[] }
29770af4f57SMichael Kruse   ///                  The statement instance for which we need elements for.
29870af4f57SMichael Kruse   ///
29970af4f57SMichael Kruse   /// @return { Domain[] -> Element[] }
30070af4f57SMichael Kruse   ///         For each statement instance, an array element out of @p MustKnown.
30170af4f57SMichael Kruse   ///         All array elements must be in the same array (Polly does not yet
30270af4f57SMichael Kruse   ///         support reading from different accesses using the same
30370af4f57SMichael Kruse   ///         MemoryAccess). If no mapping for all of @p Domain exists, returns
30470af4f57SMichael Kruse   ///         null.
singleLocation(isl::union_map MustKnown,isl::set Domain)30570af4f57SMichael Kruse   isl::map singleLocation(isl::union_map MustKnown, isl::set Domain) {
30670af4f57SMichael Kruse     // { Domain[] -> Element[] }
30770af4f57SMichael Kruse     isl::map Result;
30870af4f57SMichael Kruse 
3093b9677e1SMichael Kruse     // Make irrelevant elements not interfere.
3103b9677e1SMichael Kruse     Domain = Domain.intersect_params(S->getContext());
3113b9677e1SMichael Kruse 
31270af4f57SMichael Kruse     // MemoryAccesses can read only elements from a single array
31370af4f57SMichael Kruse     // (i.e. not: { Dom[0] -> A[0]; Dom[1] -> B[1] }).
31470af4f57SMichael Kruse     // Look through all spaces until we find one that contains at least the
31570af4f57SMichael Kruse     // wanted statement instance.s
31691f851b1STobias Grosser     for (isl::map Map : MustKnown.get_map_list()) {
31770af4f57SMichael Kruse       // Get the array this is accessing.
31870af4f57SMichael Kruse       isl::id ArrayId = Map.get_tuple_id(isl::dim::out);
31970af4f57SMichael Kruse       ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(ArrayId.get_user());
32070af4f57SMichael Kruse 
32170af4f57SMichael Kruse       // No support for generation of indirect array accesses.
32270af4f57SMichael Kruse       if (SAI->getBasePtrOriginSAI())
32391f851b1STobias Grosser         continue;
32470af4f57SMichael Kruse 
32570af4f57SMichael Kruse       // Determine whether this map contains all wanted values.
32670af4f57SMichael Kruse       isl::set MapDom = Map.domain();
32770af4f57SMichael Kruse       if (!Domain.is_subset(MapDom).is_true())
32891f851b1STobias Grosser         continue;
32970af4f57SMichael Kruse 
33070af4f57SMichael Kruse       // There might be multiple array elements that contain the same value, but
33170af4f57SMichael Kruse       // choose only one of them. lexmin is used because it returns a one-value
33270af4f57SMichael Kruse       // mapping, we do not care about which one.
33370af4f57SMichael Kruse       // TODO: Get the simplest access function.
33470af4f57SMichael Kruse       Result = Map.lexmin();
33591f851b1STobias Grosser       break;
33691f851b1STobias Grosser     }
33770af4f57SMichael Kruse 
33870af4f57SMichael Kruse     return Result;
33970af4f57SMichael Kruse   }
34070af4f57SMichael Kruse 
34170af4f57SMichael Kruse public:
ForwardOpTreeImpl(Scop * S,LoopInfo * LI,IslMaxOperationsGuard & MaxOpGuard)34289972e21SMichael Kruse   ForwardOpTreeImpl(Scop *S, LoopInfo *LI, IslMaxOperationsGuard &MaxOpGuard)
34389972e21SMichael Kruse       : ZoneAlgorithm("polly-optree", S, LI), MaxOpGuard(MaxOpGuard) {}
3449248fde5SEugene Zelenko 
34570af4f57SMichael Kruse   /// Compute the zones of known array element contents.
34670af4f57SMichael Kruse   ///
34770af4f57SMichael Kruse   /// @return True if the computed #Known is usable.
computeKnownValues()34870af4f57SMichael Kruse   bool computeKnownValues() {
34970af4f57SMichael Kruse     isl::union_map MustKnown, KnownFromLoad, KnownFromInit;
35070af4f57SMichael Kruse 
35170af4f57SMichael Kruse     // Check that nothing strange occurs.
35247281843SMichael Kruse     collectCompatibleElts();
35370af4f57SMichael Kruse 
35470af4f57SMichael Kruse     {
35589972e21SMichael Kruse       IslQuotaScope QuotaScope = MaxOpGuard.enter();
35670af4f57SMichael Kruse 
35770af4f57SMichael Kruse       computeCommon();
35868821a8bSMichael Kruse       if (NormalizePHIs)
35968821a8bSMichael Kruse         computeNormalizedPHIs();
36070af4f57SMichael Kruse       Known = computeKnown(true, true);
36170af4f57SMichael Kruse 
36270af4f57SMichael Kruse       // Preexisting ValInsts use the known content analysis of themselves.
36370af4f57SMichael Kruse       Translator = makeIdentityMap(Known.range(), false);
36470af4f57SMichael Kruse     }
36570af4f57SMichael Kruse 
3667c7978a1Spatacca     if (Known.is_null() || Translator.is_null() || NormalizeMap.is_null()) {
36770af4f57SMichael Kruse       assert(isl_ctx_last_error(IslCtx.get()) == isl_error_quota);
3689b41d095Spatacca       Known = {};
3699b41d095Spatacca       Translator = {};
3709b41d095Spatacca       NormalizeMap = {};
371349506a9SNicola Zaghen       LLVM_DEBUG(dbgs() << "Known analysis exceeded max_operations\n");
37270af4f57SMichael Kruse       return false;
37370af4f57SMichael Kruse     }
37470af4f57SMichael Kruse 
37570af4f57SMichael Kruse     KnownAnalyzed++;
376349506a9SNicola Zaghen     LLVM_DEBUG(dbgs() << "All known: " << Known << "\n");
37770af4f57SMichael Kruse 
37870af4f57SMichael Kruse     return true;
37970af4f57SMichael Kruse   }
38070af4f57SMichael Kruse 
printStatistics(raw_ostream & OS,int Indent=0)381a6b2de3bSMichael Kruse   void printStatistics(raw_ostream &OS, int Indent = 0) {
382a6b2de3bSMichael Kruse     OS.indent(Indent) << "Statistics {\n";
383a6b2de3bSMichael Kruse     OS.indent(Indent + 4) << "Instructions copied: " << NumInstructionsCopied
384a6b2de3bSMichael Kruse                           << '\n';
38570af4f57SMichael Kruse     OS.indent(Indent + 4) << "Known loads forwarded: " << NumKnownLoadsForwarded
38670af4f57SMichael Kruse                           << '\n';
387822dfe27SMichael Kruse     OS.indent(Indent + 4) << "Reloads: " << NumReloads << '\n';
38807e8c36dSMichael Kruse     OS.indent(Indent + 4) << "Read-only accesses copied: " << NumReadOnlyCopied
38907e8c36dSMichael Kruse                           << '\n';
390a6b2de3bSMichael Kruse     OS.indent(Indent + 4) << "Operand trees forwarded: " << NumForwardedTrees
391a6b2de3bSMichael Kruse                           << '\n';
392a6b2de3bSMichael Kruse     OS.indent(Indent + 4) << "Statements with forwarded operand trees: "
393a6b2de3bSMichael Kruse                           << NumModifiedStmts << '\n';
394a6b2de3bSMichael Kruse     OS.indent(Indent) << "}\n";
395a6b2de3bSMichael Kruse   }
396a6b2de3bSMichael Kruse 
printStatements(raw_ostream & OS,int Indent=0) const3979248fde5SEugene Zelenko   void printStatements(raw_ostream &OS, int Indent = 0) const {
398a6b2de3bSMichael Kruse     OS.indent(Indent) << "After statements {\n";
399a6b2de3bSMichael Kruse     for (auto &Stmt : *S) {
400a6b2de3bSMichael Kruse       OS.indent(Indent + 4) << Stmt.getBaseName() << "\n";
401a6b2de3bSMichael Kruse       for (auto *MA : Stmt)
402a6b2de3bSMichael Kruse         MA->print(OS);
403a6b2de3bSMichael Kruse 
404a6b2de3bSMichael Kruse       OS.indent(Indent + 12);
405a6b2de3bSMichael Kruse       Stmt.printInstructions(OS);
406a6b2de3bSMichael Kruse     }
407a6b2de3bSMichael Kruse     OS.indent(Indent) << "}\n";
408a6b2de3bSMichael Kruse   }
409a6b2de3bSMichael Kruse 
41070af4f57SMichael Kruse   /// Create a new MemoryAccess of type read and MemoryKind::Array.
41170af4f57SMichael Kruse   ///
41270af4f57SMichael Kruse   /// @param Stmt           The statement in which the access occurs.
41370af4f57SMichael Kruse   /// @param LI             The instruction that does the access.
41470af4f57SMichael Kruse   /// @param AccessRelation The array element that each statement instance
41570af4f57SMichael Kruse   ///                       accesses.
41670af4f57SMichael Kruse   ///
41770af4f57SMichael Kruse   /// @param The newly created access.
makeReadArrayAccess(ScopStmt * Stmt,LoadInst * LI,isl::map AccessRelation)41870af4f57SMichael Kruse   MemoryAccess *makeReadArrayAccess(ScopStmt *Stmt, LoadInst *LI,
41970af4f57SMichael Kruse                                     isl::map AccessRelation) {
42070af4f57SMichael Kruse     isl::id ArrayId = AccessRelation.get_tuple_id(isl::dim::out);
42170af4f57SMichael Kruse     ScopArrayInfo *SAI = reinterpret_cast<ScopArrayInfo *>(ArrayId.get_user());
42270af4f57SMichael Kruse 
42370af4f57SMichael Kruse     // Create a dummy SCEV access, to be replaced anyway.
42470af4f57SMichael Kruse     SmallVector<const SCEV *, 4> Sizes;
42570af4f57SMichael Kruse     Sizes.reserve(SAI->getNumberOfDimensions());
42670af4f57SMichael Kruse     SmallVector<const SCEV *, 4> Subscripts;
42770af4f57SMichael Kruse     Subscripts.reserve(SAI->getNumberOfDimensions());
42870af4f57SMichael Kruse     for (unsigned i = 0; i < SAI->getNumberOfDimensions(); i += 1) {
42970af4f57SMichael Kruse       Sizes.push_back(SAI->getDimensionSize(i));
43070af4f57SMichael Kruse       Subscripts.push_back(nullptr);
43170af4f57SMichael Kruse     }
43270af4f57SMichael Kruse 
43370af4f57SMichael Kruse     MemoryAccess *Access =
43470af4f57SMichael Kruse         new MemoryAccess(Stmt, LI, MemoryAccess::READ, SAI->getBasePtr(),
43570af4f57SMichael Kruse                          LI->getType(), true, {}, Sizes, LI, MemoryKind::Array);
43670af4f57SMichael Kruse     S->addAccessFunction(Access);
43770af4f57SMichael Kruse     Stmt->addAccess(Access, true);
43870af4f57SMichael Kruse 
43970af4f57SMichael Kruse     Access->setNewAccessRelation(AccessRelation);
44070af4f57SMichael Kruse 
44170af4f57SMichael Kruse     return Access;
44270af4f57SMichael Kruse   }
44370af4f57SMichael Kruse 
44470af4f57SMichael Kruse   /// Forward a load by reading from an array element that contains the same
44570af4f57SMichael Kruse   /// value. Typically the location it was loaded from.
44670af4f57SMichael Kruse   ///
44770af4f57SMichael Kruse   /// @param TargetStmt  The statement the operand tree will be copied to.
44870af4f57SMichael Kruse   /// @param Inst        The (possibly speculatable) instruction to forward.
44970af4f57SMichael Kruse   /// @param UseStmt     The statement that uses @p Inst.
45070af4f57SMichael Kruse   /// @param UseLoop     The loop @p Inst is used in.
45170af4f57SMichael Kruse   /// @param DefStmt     The statement @p Inst is defined in.
45270af4f57SMichael Kruse   /// @param DefLoop     The loop which contains @p Inst.
45370af4f57SMichael Kruse   ///
4547175cffbSMichael Kruse   /// @return A ForwardingAction object describing the feasibility and
4557175cffbSMichael Kruse   ///         profitability evaluation and the callback carrying-out the value
4567175cffbSMichael Kruse   ///         forwarding.
forwardKnownLoad(ScopStmt * TargetStmt,Instruction * Inst,ScopStmt * UseStmt,Loop * UseLoop,ScopStmt * DefStmt,Loop * DefLoop)4577175cffbSMichael Kruse   ForwardingAction forwardKnownLoad(ScopStmt *TargetStmt, Instruction *Inst,
45870af4f57SMichael Kruse                                     ScopStmt *UseStmt, Loop *UseLoop,
4597175cffbSMichael Kruse                                     ScopStmt *DefStmt, Loop *DefLoop) {
46070af4f57SMichael Kruse     // Cannot do anything without successful known analysis.
461d3ce899dSMichael Kruse     if (Known.is_null() || Translator.is_null() ||
462d3ce899dSMichael Kruse         MaxOpGuard.hasQuotaExceeded())
4637175cffbSMichael Kruse       return ForwardingAction::notApplicable();
46470af4f57SMichael Kruse 
46570af4f57SMichael Kruse     LoadInst *LI = dyn_cast<LoadInst>(Inst);
46670af4f57SMichael Kruse     if (!LI)
4677175cffbSMichael Kruse       return ForwardingAction::notApplicable();
46870af4f57SMichael Kruse 
4697175cffbSMichael Kruse     ForwardingDecision OpDecision =
4707175cffbSMichael Kruse         forwardTree(TargetStmt, LI->getPointerOperand(), DefStmt, DefLoop);
47170af4f57SMichael Kruse     switch (OpDecision) {
472822dfe27SMichael Kruse     case FD_CanForwardProfitably:
4737175cffbSMichael Kruse     case FD_CanForwardLeaf:
47470af4f57SMichael Kruse       break;
4757175cffbSMichael Kruse     case FD_CannotForward:
4767175cffbSMichael Kruse       return ForwardingAction::cannotForward();
47770af4f57SMichael Kruse     default:
47870af4f57SMichael Kruse       llvm_unreachable("Shouldn't return this");
47970af4f57SMichael Kruse     }
48070af4f57SMichael Kruse 
4817175cffbSMichael Kruse     MemoryAccess *Access = TargetStmt->getArrayAccessOrNULLFor(LI);
4827175cffbSMichael Kruse     if (Access) {
4837175cffbSMichael Kruse       // If the load is already in the statement, no forwarding is necessary.
4847175cffbSMichael Kruse       // However, it might happen that the LoadInst is already present in the
4857175cffbSMichael Kruse       // statement's instruction list. In that case we do as follows:
4867175cffbSMichael Kruse       // - For the evaluation, we can trivially forward it as it is
4877175cffbSMichael Kruse       //   benefit of forwarding an already present instruction.
4887175cffbSMichael Kruse       // - For the execution, prepend the instruction (to make it
4897175cffbSMichael Kruse       //   available to all instructions following in the instruction list), but
4907175cffbSMichael Kruse       //   do not add another MemoryAccess.
4917175cffbSMichael Kruse       auto ExecAction = [this, TargetStmt, LI, Access]() -> bool {
4927175cffbSMichael Kruse         TargetStmt->prependInstruction(LI);
4937175cffbSMichael Kruse         LLVM_DEBUG(
4947175cffbSMichael Kruse             dbgs() << "    forwarded known load with preexisting MemoryAccess"
4957175cffbSMichael Kruse                    << Access << "\n");
49698031b66SFangrui Song         (void)Access;
4977175cffbSMichael Kruse 
4987175cffbSMichael Kruse         NumKnownLoadsForwarded++;
4997175cffbSMichael Kruse         TotalKnownLoadsForwarded++;
5007175cffbSMichael Kruse         return true;
5017175cffbSMichael Kruse       };
5027175cffbSMichael Kruse       return ForwardingAction::canForward(
5037175cffbSMichael Kruse           ExecAction, {{LI->getPointerOperand(), DefStmt}}, true);
5047175cffbSMichael Kruse     }
5057175cffbSMichael Kruse 
5067175cffbSMichael Kruse     // Allow the following Isl calculations (until we return the
5077175cffbSMichael Kruse     // ForwardingAction, excluding the code inside the lambda that will be
5087175cffbSMichael Kruse     // executed later) to fail.
5097175cffbSMichael Kruse     IslQuotaScope QuotaScope = MaxOpGuard.enter();
51089972e21SMichael Kruse 
51170af4f57SMichael Kruse     // { DomainDef[] -> ValInst[] }
51270af4f57SMichael Kruse     isl::map ExpectedVal = makeValInst(Inst, UseStmt, UseLoop);
513d51fbfcaSMichael Kruse     assert(!isNormalized(ExpectedVal).is_false() &&
514d51fbfcaSMichael Kruse            "LoadInsts are always normalized");
51570af4f57SMichael Kruse 
516d3ce899dSMichael Kruse     // { DomainUse[] -> DomainTarget[] }
517d3ce899dSMichael Kruse     isl::map UseToTarget = getDefToTarget(UseStmt, TargetStmt);
518d3ce899dSMichael Kruse 
51970af4f57SMichael Kruse     // { DomainTarget[] -> ValInst[] }
52070af4f57SMichael Kruse     isl::map TargetExpectedVal = ExpectedVal.apply_domain(UseToTarget);
52170af4f57SMichael Kruse     isl::union_map TranslatedExpectedVal =
52270af4f57SMichael Kruse         isl::union_map(TargetExpectedVal).apply_range(Translator);
52370af4f57SMichael Kruse 
52470af4f57SMichael Kruse     // { DomainTarget[] -> Element[] }
52570af4f57SMichael Kruse     isl::union_map Candidates = findSameContentElements(TranslatedExpectedVal);
52670af4f57SMichael Kruse 
52770af4f57SMichael Kruse     isl::map SameVal = singleLocation(Candidates, getDomainFor(TargetStmt));
5287c7978a1Spatacca     if (SameVal.is_null())
5297175cffbSMichael Kruse       return ForwardingAction::notApplicable();
530822dfe27SMichael Kruse 
5317175cffbSMichael Kruse     LLVM_DEBUG(dbgs() << "      expected values where " << TargetExpectedVal
5327175cffbSMichael Kruse                       << "\n");
5337175cffbSMichael Kruse     LLVM_DEBUG(dbgs() << "      candidate elements where " << Candidates
5347175cffbSMichael Kruse                       << "\n");
53570af4f57SMichael Kruse 
53670af4f57SMichael Kruse     // { ValInst[] }
53770af4f57SMichael Kruse     isl::space ValInstSpace = ExpectedVal.get_space().range();
53870af4f57SMichael Kruse 
53970af4f57SMichael Kruse     // After adding a new load to the SCoP, also update the Known content
54070af4f57SMichael Kruse     // about it. The new load will have a known ValInst of
54170af4f57SMichael Kruse     // { [DomainTarget[] -> Value[]] }
54270af4f57SMichael Kruse     // but which -- because it is a copy of it -- has same value as the
54370af4f57SMichael Kruse     // { [DomainDef[] -> Value[]] }
54470af4f57SMichael Kruse     // that it replicates. Instead of  cloning the known content of
54570af4f57SMichael Kruse     // [DomainDef[] -> Value[]]
54670af4f57SMichael Kruse     // for DomainTarget[], we add a 'translator' that maps
54770af4f57SMichael Kruse     // [DomainTarget[] -> Value[]] to [DomainDef[] -> Value[]]
54870af4f57SMichael Kruse     // before comparing to the known content.
54970af4f57SMichael Kruse     // TODO: 'Translator' could also be used to map PHINodes to their incoming
55070af4f57SMichael Kruse     // ValInsts.
5517175cffbSMichael Kruse     isl::map LocalTranslator;
5527175cffbSMichael Kruse     if (!ValInstSpace.is_wrapping().is_false()) {
55370af4f57SMichael Kruse       // { DefDomain[] -> Value[] }
55470af4f57SMichael Kruse       isl::map ValInsts = ExpectedVal.range().unwrap();
55570af4f57SMichael Kruse 
55670af4f57SMichael Kruse       // { DefDomain[] }
55770af4f57SMichael Kruse       isl::set DefDomain = ValInsts.domain();
55870af4f57SMichael Kruse 
55970af4f57SMichael Kruse       // { Value[] }
56070af4f57SMichael Kruse       isl::space ValSpace = ValInstSpace.unwrap().range();
56170af4f57SMichael Kruse 
56270af4f57SMichael Kruse       // { Value[] -> Value[] }
56370af4f57SMichael Kruse       isl::map ValToVal =
56470af4f57SMichael Kruse           isl::map::identity(ValSpace.map_from_domain_and_range(ValSpace));
56570af4f57SMichael Kruse 
566d3ce899dSMichael Kruse       // { DomainDef[] -> DomainTarget[] }
567d3ce899dSMichael Kruse       isl::map DefToTarget = getDefToTarget(DefStmt, TargetStmt);
568d3ce899dSMichael Kruse 
56970af4f57SMichael Kruse       // { [TargetDomain[] -> Value[]] -> [DefDomain[] -> Value] }
5707175cffbSMichael Kruse       LocalTranslator = DefToTarget.reverse().product(ValToVal);
571349506a9SNicola Zaghen       LLVM_DEBUG(dbgs() << "      local translator is " << LocalTranslator
57270af4f57SMichael Kruse                         << "\n");
5737175cffbSMichael Kruse 
5747c7978a1Spatacca       if (LocalTranslator.is_null())
5757175cffbSMichael Kruse         return ForwardingAction::notApplicable();
57670af4f57SMichael Kruse     }
5777175cffbSMichael Kruse 
5787175cffbSMichael Kruse     auto ExecAction = [this, TargetStmt, LI, SameVal,
5797175cffbSMichael Kruse                        LocalTranslator]() -> bool {
5807175cffbSMichael Kruse       TargetStmt->prependInstruction(LI);
5817175cffbSMichael Kruse       MemoryAccess *Access = makeReadArrayAccess(TargetStmt, LI, SameVal);
5827175cffbSMichael Kruse       LLVM_DEBUG(dbgs() << "    forwarded known load with new MemoryAccess"
5837175cffbSMichael Kruse                         << Access << "\n");
58498031b66SFangrui Song       (void)Access;
5857175cffbSMichael Kruse 
5867c7978a1Spatacca       if (!LocalTranslator.is_null())
587d5ee355fSRiccardo Mori         Translator = Translator.unite(LocalTranslator);
58870af4f57SMichael Kruse 
58970af4f57SMichael Kruse       NumKnownLoadsForwarded++;
59070af4f57SMichael Kruse       TotalKnownLoadsForwarded++;
5917175cffbSMichael Kruse       return true;
5927175cffbSMichael Kruse     };
5937175cffbSMichael Kruse     return ForwardingAction::canForward(
5947175cffbSMichael Kruse         ExecAction, {{LI->getPointerOperand(), DefStmt}}, true);
595822dfe27SMichael Kruse   }
596822dfe27SMichael Kruse 
597822dfe27SMichael Kruse   /// Forward a scalar by redirecting the access to an array element that stores
598822dfe27SMichael Kruse   /// the same value.
599822dfe27SMichael Kruse   ///
600822dfe27SMichael Kruse   /// @param TargetStmt  The statement the operand tree will be copied to.
601822dfe27SMichael Kruse   /// @param Inst        The scalar to forward.
602822dfe27SMichael Kruse   /// @param UseStmt     The statement that uses @p Inst.
603822dfe27SMichael Kruse   /// @param UseLoop     The loop @p Inst is used in.
604822dfe27SMichael Kruse   /// @param DefStmt     The statement @p Inst is defined in.
605822dfe27SMichael Kruse   /// @param DefLoop     The loop which contains @p Inst.
606822dfe27SMichael Kruse   ///
6077175cffbSMichael Kruse   /// @return A ForwardingAction object describing the feasibility and
6087175cffbSMichael Kruse   ///         profitability evaluation and the callback carrying-out the value
6097175cffbSMichael Kruse   ///         forwarding.
reloadKnownContent(ScopStmt * TargetStmt,Instruction * Inst,ScopStmt * UseStmt,Loop * UseLoop,ScopStmt * DefStmt,Loop * DefLoop)6107175cffbSMichael Kruse   ForwardingAction reloadKnownContent(ScopStmt *TargetStmt, Instruction *Inst,
611822dfe27SMichael Kruse                                       ScopStmt *UseStmt, Loop *UseLoop,
6127175cffbSMichael Kruse                                       ScopStmt *DefStmt, Loop *DefLoop) {
613822dfe27SMichael Kruse     // Cannot do anything without successful known analysis.
614d3ce899dSMichael Kruse     if (Known.is_null() || Translator.is_null() ||
615d3ce899dSMichael Kruse         MaxOpGuard.hasQuotaExceeded())
6167175cffbSMichael Kruse       return ForwardingAction::notApplicable();
617822dfe27SMichael Kruse 
6187175cffbSMichael Kruse     // Don't spend too much time analyzing whether it can be reloaded.
6197175cffbSMichael Kruse     IslQuotaScope QuotaScope = MaxOpGuard.enter();
6204d3f3c72SMichael Kruse 
621822dfe27SMichael Kruse     // { DomainDef[] -> ValInst[] }
62268821a8bSMichael Kruse     isl::union_map ExpectedVal = makeNormalizedValInst(Inst, UseStmt, UseLoop);
623822dfe27SMichael Kruse 
624d3ce899dSMichael Kruse     // { DomainUse[] -> DomainTarget[] }
625d3ce899dSMichael Kruse     isl::map UseToTarget = getDefToTarget(UseStmt, TargetStmt);
626d3ce899dSMichael Kruse 
627822dfe27SMichael Kruse     // { DomainTarget[] -> ValInst[] }
628822dfe27SMichael Kruse     isl::union_map TargetExpectedVal = ExpectedVal.apply_domain(UseToTarget);
629822dfe27SMichael Kruse     isl::union_map TranslatedExpectedVal =
630822dfe27SMichael Kruse         TargetExpectedVal.apply_range(Translator);
631822dfe27SMichael Kruse 
632822dfe27SMichael Kruse     // { DomainTarget[] -> Element[] }
633822dfe27SMichael Kruse     isl::union_map Candidates = findSameContentElements(TranslatedExpectedVal);
634822dfe27SMichael Kruse 
635822dfe27SMichael Kruse     isl::map SameVal = singleLocation(Candidates, getDomainFor(TargetStmt));
6367175cffbSMichael Kruse     simplify(SameVal);
6377c7978a1Spatacca     if (SameVal.is_null())
6387175cffbSMichael Kruse       return ForwardingAction::notApplicable();
639822dfe27SMichael Kruse 
6407175cffbSMichael Kruse     auto ExecAction = [this, TargetStmt, Inst, SameVal]() {
6417175cffbSMichael Kruse       MemoryAccess *Access = TargetStmt->lookupInputAccessOf(Inst);
642822dfe27SMichael Kruse       if (!Access)
643822dfe27SMichael Kruse         Access = TargetStmt->ensureValueRead(Inst);
644822dfe27SMichael Kruse       Access->setNewAccessRelation(SameVal);
645822dfe27SMichael Kruse 
646c1cf51e7SMichael Kruse       LLVM_DEBUG(dbgs() << "    forwarded known content of " << *Inst
647c1cf51e7SMichael Kruse                         << " which is " << SameVal << "\n");
648822dfe27SMichael Kruse       TotalReloads++;
649822dfe27SMichael Kruse       NumReloads++;
6507175cffbSMichael Kruse       return false;
6517175cffbSMichael Kruse     };
6527175cffbSMichael Kruse 
6537175cffbSMichael Kruse     return ForwardingAction::canForward(ExecAction, {}, true);
65470af4f57SMichael Kruse   }
65570af4f57SMichael Kruse 
656a9a70863SMichael Kruse   /// Forwards a speculatively executable instruction.
657a9a70863SMichael Kruse   ///
65870af4f57SMichael Kruse   /// @param TargetStmt  The statement the operand tree will be copied to.
65970af4f57SMichael Kruse   /// @param UseInst     The (possibly speculatable) instruction to forward.
66070af4f57SMichael Kruse   /// @param DefStmt     The statement @p UseInst is defined in.
66170af4f57SMichael Kruse   /// @param DefLoop     The loop which contains @p UseInst.
662a9a70863SMichael Kruse   ///
6637175cffbSMichael Kruse   /// @return A ForwardingAction object describing the feasibility and
6647175cffbSMichael Kruse   ///         profitability evaluation and the callback carrying-out the value
6657175cffbSMichael Kruse   ///         forwarding.
forwardSpeculatable(ScopStmt * TargetStmt,Instruction * UseInst,ScopStmt * DefStmt,Loop * DefLoop)6667175cffbSMichael Kruse   ForwardingAction forwardSpeculatable(ScopStmt *TargetStmt,
6677175cffbSMichael Kruse                                        Instruction *UseInst, ScopStmt *DefStmt,
6687175cffbSMichael Kruse                                        Loop *DefLoop) {
669a9a70863SMichael Kruse     // PHIs, unless synthesizable, are not yet supported.
670a9a70863SMichael Kruse     if (isa<PHINode>(UseInst))
6717175cffbSMichael Kruse       return ForwardingAction::notApplicable();
672a9a70863SMichael Kruse 
673a9a70863SMichael Kruse     // Compatible instructions must satisfy the following conditions:
674a9a70863SMichael Kruse     // 1. Idempotent (instruction will be copied, not moved; although its
675a9a70863SMichael Kruse     //    original instance might be removed by simplification)
676a9a70863SMichael Kruse     // 2. Not access memory (There might be memory writes between)
677a9a70863SMichael Kruse     // 3. Not cause undefined behaviour (we might copy to a location when the
678a9a70863SMichael Kruse     //    original instruction was no executed; this is currently not possible
679a9a70863SMichael Kruse     //    because we do not forward PHINodes)
680a9a70863SMichael Kruse     // 4. Not leak memory if executed multiple times (i.e. malloc)
681a9a70863SMichael Kruse     //
682a9a70863SMichael Kruse     // Instruction::mayHaveSideEffects is not sufficient because it considers
683a9a70863SMichael Kruse     // malloc to not have side-effects. llvm::isSafeToSpeculativelyExecute is
684a9a70863SMichael Kruse     // not sufficient because it allows memory accesses.
68593102505SPhilip Reames     if (mayHaveNonDefUseDependency(*UseInst))
6867175cffbSMichael Kruse       return ForwardingAction::notApplicable();
687a9a70863SMichael Kruse 
6887175cffbSMichael Kruse     SmallVector<ForwardingAction::KeyTy, 4> Depends;
6897175cffbSMichael Kruse     Depends.reserve(UseInst->getNumOperands());
690a9a70863SMichael Kruse     for (Value *OpVal : UseInst->operand_values()) {
691a9a70863SMichael Kruse       ForwardingDecision OpDecision =
6927175cffbSMichael Kruse           forwardTree(TargetStmt, OpVal, DefStmt, DefLoop);
693a9a70863SMichael Kruse       switch (OpDecision) {
694a9a70863SMichael Kruse       case FD_CannotForward:
6957175cffbSMichael Kruse         return ForwardingAction::cannotForward();
696a9a70863SMichael Kruse 
697a9a70863SMichael Kruse       case FD_CanForwardLeaf:
698822dfe27SMichael Kruse       case FD_CanForwardProfitably:
6997175cffbSMichael Kruse         Depends.emplace_back(OpVal, DefStmt);
700a9a70863SMichael Kruse         break;
701a9a70863SMichael Kruse 
702a9a70863SMichael Kruse       case FD_NotApplicable:
7037175cffbSMichael Kruse       case FD_Unknown:
7047175cffbSMichael Kruse         llvm_unreachable(
7057175cffbSMichael Kruse             "forwardTree should never return FD_NotApplicable/FD_Unknown");
706a9a70863SMichael Kruse       }
707a9a70863SMichael Kruse     }
708a9a70863SMichael Kruse 
7092213a354SFangrui Song     auto ExecAction = [this, TargetStmt, UseInst]() {
7107175cffbSMichael Kruse       // To ensure the right order, prepend this instruction before its
7117175cffbSMichael Kruse       // operands. This ensures that its operands are inserted before the
7127175cffbSMichael Kruse       // instruction using them.
7137175cffbSMichael Kruse       TargetStmt->prependInstruction(UseInst);
714c1cf51e7SMichael Kruse 
715c1cf51e7SMichael Kruse       LLVM_DEBUG(dbgs() << "    forwarded speculable instruction: " << *UseInst
716c1cf51e7SMichael Kruse                         << "\n");
7177175cffbSMichael Kruse       NumInstructionsCopied++;
7187175cffbSMichael Kruse       TotalInstructionsCopied++;
7197175cffbSMichael Kruse       return true;
7207175cffbSMichael Kruse     };
7217175cffbSMichael Kruse     return ForwardingAction::canForward(ExecAction, Depends, true);
722a9a70863SMichael Kruse   }
723a9a70863SMichael Kruse 
7247175cffbSMichael Kruse   /// Determines whether an operand tree can be forwarded and returns
7257175cffbSMichael Kruse   /// instructions how to do so in the form of a ForwardingAction object.
726a6b2de3bSMichael Kruse   ///
727a6b2de3bSMichael Kruse   /// @param TargetStmt  The statement the operand tree will be copied to.
728a6b2de3bSMichael Kruse   /// @param UseVal      The value (usually an instruction) which is root of an
729a6b2de3bSMichael Kruse   ///                    operand tree.
730a6b2de3bSMichael Kruse   /// @param UseStmt     The statement that uses @p UseVal.
731a6b2de3bSMichael Kruse   /// @param UseLoop     The loop @p UseVal is used in.
732a6b2de3bSMichael Kruse   ///
7337175cffbSMichael Kruse   /// @return A ForwardingAction object describing the feasibility and
7347175cffbSMichael Kruse   ///         profitability evaluation and the callback carrying-out the value
7357175cffbSMichael Kruse   ///         forwarding.
forwardTreeImpl(ScopStmt * TargetStmt,Value * UseVal,ScopStmt * UseStmt,Loop * UseLoop)7367175cffbSMichael Kruse   ForwardingAction forwardTreeImpl(ScopStmt *TargetStmt, Value *UseVal,
7377175cffbSMichael Kruse                                    ScopStmt *UseStmt, Loop *UseLoop) {
73870af4f57SMichael Kruse     ScopStmt *DefStmt = nullptr;
73970af4f57SMichael Kruse     Loop *DefLoop = nullptr;
74070af4f57SMichael Kruse 
74170af4f57SMichael Kruse     // { DefDomain[] -> TargetDomain[] }
74270af4f57SMichael Kruse     isl::map DefToTarget;
74370af4f57SMichael Kruse 
744a6b2de3bSMichael Kruse     VirtualUse VUse = VirtualUse::create(UseStmt, UseLoop, UseVal, true);
745a6b2de3bSMichael Kruse     switch (VUse.getKind()) {
746a6b2de3bSMichael Kruse     case VirtualUse::Constant:
747a6b2de3bSMichael Kruse     case VirtualUse::Block:
748e5f4706aSMichael Kruse     case VirtualUse::Hoisted:
749a6b2de3bSMichael Kruse       // These can be used anywhere without special considerations.
750c1cf51e7SMichael Kruse       return ForwardingAction::triviallyForwardable(false, UseVal);
751a6b2de3bSMichael Kruse 
7529f6e41cdSMichael Kruse     case VirtualUse::Synthesizable: {
7539f6e41cdSMichael Kruse       // Check if the value is synthesizable at the new location as well. This
7549f6e41cdSMichael Kruse       // might be possible when leaving a loop for which ScalarEvolution is
7559f6e41cdSMichael Kruse       // unable to derive the exit value for.
7569f6e41cdSMichael Kruse       // TODO: If there is a LCSSA PHI at the loop exit, use that one.
7579f6e41cdSMichael Kruse       // If the SCEV contains a SCEVAddRecExpr, we currently depend on that we
7589f6e41cdSMichael Kruse       // do not forward past its loop header. This would require us to use a
7599f6e41cdSMichael Kruse       // previous loop induction variable instead the current one. We currently
7609f6e41cdSMichael Kruse       // do not allow forwarding PHI nodes, thus this should never occur (the
7619f6e41cdSMichael Kruse       // only exception where no phi is necessary being an unreachable loop
7629f6e41cdSMichael Kruse       // without edge from the outside).
7639f6e41cdSMichael Kruse       VirtualUse TargetUse = VirtualUse::create(
7649f6e41cdSMichael Kruse           S, TargetStmt, TargetStmt->getSurroundingLoop(), UseVal, true);
7659f6e41cdSMichael Kruse       if (TargetUse.getKind() == VirtualUse::Synthesizable)
766c1cf51e7SMichael Kruse         return ForwardingAction::triviallyForwardable(false, UseVal);
7679f6e41cdSMichael Kruse 
768349506a9SNicola Zaghen       LLVM_DEBUG(
769349506a9SNicola Zaghen           dbgs() << "    Synthesizable would not be synthesizable anymore: "
7709f6e41cdSMichael Kruse                  << *UseVal << "\n");
7717175cffbSMichael Kruse       return ForwardingAction::cannotForward();
7729f6e41cdSMichael Kruse     }
773a6b2de3bSMichael Kruse 
7747175cffbSMichael Kruse     case VirtualUse::ReadOnly: {
775c1cf51e7SMichael Kruse       if (!ModelReadOnlyScalars)
776c1cf51e7SMichael Kruse         return ForwardingAction::triviallyForwardable(false, UseVal);
777c1cf51e7SMichael Kruse 
77807e8c36dSMichael Kruse       // If we model read-only scalars, we need to create a MemoryAccess for it.
7797175cffbSMichael Kruse       auto ExecAction = [this, TargetStmt, UseVal]() {
78007e8c36dSMichael Kruse         TargetStmt->ensureValueRead(UseVal);
78107e8c36dSMichael Kruse 
782c1cf51e7SMichael Kruse         LLVM_DEBUG(dbgs() << "    forwarded read-only value " << *UseVal
783c1cf51e7SMichael Kruse                           << "\n");
78407e8c36dSMichael Kruse         NumReadOnlyCopied++;
78507e8c36dSMichael Kruse         TotalReadOnlyCopied++;
7867175cffbSMichael Kruse 
7877175cffbSMichael Kruse         // Note that we cannot return true here. With a operand tree
7887175cffbSMichael Kruse         // depth of 0, UseVal is the use in TargetStmt that we try to replace.
7897175cffbSMichael Kruse         // With -polly-analyze-read-only-scalars=true we would ensure the
7907175cffbSMichael Kruse         // existence of a MemoryAccess (which already exists for a leaf) and be
7917175cffbSMichael Kruse         // removed again by tryForwardTree because it's goal is to remove this
7927175cffbSMichael Kruse         // scalar MemoryAccess. It interprets FD_CanForwardTree as the
7937175cffbSMichael Kruse         // permission to do so.
7947175cffbSMichael Kruse         return false;
7957175cffbSMichael Kruse       };
7967175cffbSMichael Kruse       return ForwardingAction::canForward(ExecAction, {}, false);
7977175cffbSMichael Kruse     }
798a6b2de3bSMichael Kruse 
799a6b2de3bSMichael Kruse     case VirtualUse::Intra:
80070af4f57SMichael Kruse       // Knowing that UseStmt and DefStmt are the same statement instance, just
80170af4f57SMichael Kruse       // reuse the information about UseStmt for DefStmt
80270af4f57SMichael Kruse       DefStmt = UseStmt;
803a6b2de3bSMichael Kruse 
80470af4f57SMichael Kruse       LLVM_FALLTHROUGH;
80570af4f57SMichael Kruse     case VirtualUse::Inter:
80670af4f57SMichael Kruse       Instruction *Inst = cast<Instruction>(UseVal);
80770af4f57SMichael Kruse 
808cd3b9fedSMichael Kruse       if (!DefStmt) {
80970af4f57SMichael Kruse         DefStmt = S->getStmtFor(Inst);
810cd3b9fedSMichael Kruse         if (!DefStmt)
8117175cffbSMichael Kruse           return ForwardingAction::cannotForward();
812cd3b9fedSMichael Kruse       }
813cd3b9fedSMichael Kruse 
81470af4f57SMichael Kruse       DefLoop = LI->getLoopFor(Inst->getParent());
81570af4f57SMichael Kruse 
8167175cffbSMichael Kruse       ForwardingAction SpeculativeResult =
8177175cffbSMichael Kruse           forwardSpeculatable(TargetStmt, Inst, DefStmt, DefLoop);
8187175cffbSMichael Kruse       if (SpeculativeResult.Decision != FD_NotApplicable)
819a9a70863SMichael Kruse         return SpeculativeResult;
820a9a70863SMichael Kruse 
8217175cffbSMichael Kruse       ForwardingAction KnownResult = forwardKnownLoad(
8227175cffbSMichael Kruse           TargetStmt, Inst, UseStmt, UseLoop, DefStmt, DefLoop);
8237175cffbSMichael Kruse       if (KnownResult.Decision != FD_NotApplicable)
82470af4f57SMichael Kruse         return KnownResult;
82570af4f57SMichael Kruse 
8267175cffbSMichael Kruse       ForwardingAction ReloadResult = reloadKnownContent(
8277175cffbSMichael Kruse           TargetStmt, Inst, UseStmt, UseLoop, DefStmt, DefLoop);
8287175cffbSMichael Kruse       if (ReloadResult.Decision != FD_NotApplicable)
829822dfe27SMichael Kruse         return ReloadResult;
830822dfe27SMichael Kruse 
831a9a70863SMichael Kruse       // When no method is found to forward the operand tree, we effectively
832a9a70863SMichael Kruse       // cannot handle it.
833349506a9SNicola Zaghen       LLVM_DEBUG(dbgs() << "    Cannot forward instruction: " << *Inst << "\n");
8347175cffbSMichael Kruse       return ForwardingAction::cannotForward();
8359f6e41cdSMichael Kruse     }
8369f6e41cdSMichael Kruse 
837a6b2de3bSMichael Kruse     llvm_unreachable("Case unhandled");
838a6b2de3bSMichael Kruse   }
839a6b2de3bSMichael Kruse 
8407175cffbSMichael Kruse   /// Determines whether an operand tree can be forwarded. Previous evaluations
8417175cffbSMichael Kruse   /// are cached.
8427175cffbSMichael Kruse   ///
8437175cffbSMichael Kruse   /// @param TargetStmt  The statement the operand tree will be copied to.
8447175cffbSMichael Kruse   /// @param UseVal      The value (usually an instruction) which is root of an
8457175cffbSMichael Kruse   ///                    operand tree.
8467175cffbSMichael Kruse   /// @param UseStmt     The statement that uses @p UseVal.
8477175cffbSMichael Kruse   /// @param UseLoop     The loop @p UseVal is used in.
8487175cffbSMichael Kruse   ///
8497175cffbSMichael Kruse   /// @return FD_CannotForward        if @p UseVal cannot be forwarded.
8507175cffbSMichael Kruse   ///         FD_CanForwardLeaf       if @p UseVal is forwardable, but not
8517175cffbSMichael Kruse   ///                                 profitable.
8527175cffbSMichael Kruse   ///         FD_CanForwardProfitably if @p UseVal is forwardable and useful to
8537175cffbSMichael Kruse   ///                                 do.
forwardTree(ScopStmt * TargetStmt,Value * UseVal,ScopStmt * UseStmt,Loop * UseLoop)8547175cffbSMichael Kruse   ForwardingDecision forwardTree(ScopStmt *TargetStmt, Value *UseVal,
8557175cffbSMichael Kruse                                  ScopStmt *UseStmt, Loop *UseLoop) {
8567175cffbSMichael Kruse     // Lookup any cached evaluation.
8577175cffbSMichael Kruse     auto It = ForwardingActions.find({UseVal, UseStmt});
8587175cffbSMichael Kruse     if (It != ForwardingActions.end())
8597175cffbSMichael Kruse       return It->second.Decision;
8607175cffbSMichael Kruse 
8617175cffbSMichael Kruse     // Make a new evaluation.
8627175cffbSMichael Kruse     ForwardingAction Action =
8637175cffbSMichael Kruse         forwardTreeImpl(TargetStmt, UseVal, UseStmt, UseLoop);
8647175cffbSMichael Kruse     ForwardingDecision Result = Action.Decision;
8657175cffbSMichael Kruse 
8667175cffbSMichael Kruse     // Remember for the next time.
8677175cffbSMichael Kruse     assert(!ForwardingActions.count({UseVal, UseStmt}) &&
8687175cffbSMichael Kruse            "circular dependency?");
8697175cffbSMichael Kruse     ForwardingActions.insert({{UseVal, UseStmt}, std::move(Action)});
8707175cffbSMichael Kruse 
8717175cffbSMichael Kruse     return Result;
8727175cffbSMichael Kruse   }
8737175cffbSMichael Kruse 
8747175cffbSMichael Kruse   /// Forward an operand tree using cached actions.
8757175cffbSMichael Kruse   ///
8767175cffbSMichael Kruse   /// @param Stmt   Statement the operand tree is moved into.
8777175cffbSMichael Kruse   /// @param UseVal Root of the operand tree within @p Stmt.
8787175cffbSMichael Kruse   /// @param RA     The MemoryAccess for @p UseVal that the forwarding intends
8797175cffbSMichael Kruse   ///               to remove.
applyForwardingActions(ScopStmt * Stmt,Value * UseVal,MemoryAccess * RA)8807175cffbSMichael Kruse   void applyForwardingActions(ScopStmt *Stmt, Value *UseVal, MemoryAccess *RA) {
8817175cffbSMichael Kruse     using ChildItTy =
8827175cffbSMichael Kruse         decltype(std::declval<ForwardingAction>().Depends.begin());
8837175cffbSMichael Kruse     using EdgeTy = std::pair<ForwardingAction *, ChildItTy>;
8847175cffbSMichael Kruse 
8857175cffbSMichael Kruse     DenseSet<ForwardingAction::KeyTy> Visited;
8867175cffbSMichael Kruse     SmallVector<EdgeTy, 32> Stack;
8877175cffbSMichael Kruse     SmallVector<ForwardingAction *, 32> Ordered;
8887175cffbSMichael Kruse 
8897175cffbSMichael Kruse     // Seed the tree search using the root value.
8907175cffbSMichael Kruse     assert(ForwardingActions.count({UseVal, Stmt}));
8917175cffbSMichael Kruse     ForwardingAction *RootAction = &ForwardingActions[{UseVal, Stmt}];
8927175cffbSMichael Kruse     Stack.emplace_back(RootAction, RootAction->Depends.begin());
8937175cffbSMichael Kruse 
8947175cffbSMichael Kruse     // Compute the postorder of the operand tree: all operands of an instruction
8957175cffbSMichael Kruse     // must be visited before the instruction itself. As an additional
8967175cffbSMichael Kruse     // requirement, the topological ordering must be 'compact': Any subtree node
8977175cffbSMichael Kruse     // must not be interleaved with nodes from a non-shared subtree. This is
8987175cffbSMichael Kruse     // because the same llvm::Instruction can be materialized multiple times as
8997175cffbSMichael Kruse     // used at different ScopStmts which might be different values. Intersecting
9007175cffbSMichael Kruse     // these lifetimes may result in miscompilations.
9017175cffbSMichael Kruse     // FIXME: Intersecting lifetimes might still be possible for the roots
9027175cffbSMichael Kruse     // themselves, since instructions are just prepended to a ScopStmt's
9037175cffbSMichael Kruse     // instruction list.
9047175cffbSMichael Kruse     while (!Stack.empty()) {
9057175cffbSMichael Kruse       EdgeTy &Top = Stack.back();
9067175cffbSMichael Kruse       ForwardingAction *TopAction = Top.first;
9077175cffbSMichael Kruse       ChildItTy &TopEdge = Top.second;
9087175cffbSMichael Kruse 
9097175cffbSMichael Kruse       if (TopEdge == TopAction->Depends.end()) {
9107175cffbSMichael Kruse         // Postorder sorting
9117175cffbSMichael Kruse         Ordered.push_back(TopAction);
9127175cffbSMichael Kruse         Stack.pop_back();
9137175cffbSMichael Kruse         continue;
9147175cffbSMichael Kruse       }
9157175cffbSMichael Kruse       ForwardingAction::KeyTy Key = *TopEdge;
9167175cffbSMichael Kruse 
9177175cffbSMichael Kruse       // Next edge for this level
9187175cffbSMichael Kruse       ++TopEdge;
9197175cffbSMichael Kruse 
9207175cffbSMichael Kruse       auto VisitIt = Visited.insert(Key);
9217175cffbSMichael Kruse       if (!VisitIt.second)
9227175cffbSMichael Kruse         continue;
9237175cffbSMichael Kruse 
9247175cffbSMichael Kruse       assert(ForwardingActions.count(Key) &&
9257175cffbSMichael Kruse              "Must not insert new actions during execution phase");
9267175cffbSMichael Kruse       ForwardingAction *ChildAction = &ForwardingActions[Key];
9277175cffbSMichael Kruse       Stack.emplace_back(ChildAction, ChildAction->Depends.begin());
9287175cffbSMichael Kruse     }
9297175cffbSMichael Kruse 
9307175cffbSMichael Kruse     // Actually, we need the reverse postorder because actions prepend new
9317175cffbSMichael Kruse     // instructions. Therefore, the first one will always be the action for the
9327175cffbSMichael Kruse     // operand tree's root.
9337175cffbSMichael Kruse     assert(Ordered.back() == RootAction);
9347175cffbSMichael Kruse     if (RootAction->Execute())
9357175cffbSMichael Kruse       Stmt->removeSingleMemoryAccess(RA);
9367175cffbSMichael Kruse     Ordered.pop_back();
9377175cffbSMichael Kruse     for (auto DepAction : reverse(Ordered)) {
9387175cffbSMichael Kruse       assert(DepAction->Decision != FD_Unknown &&
9397175cffbSMichael Kruse              DepAction->Decision != FD_CannotForward);
9407175cffbSMichael Kruse       assert(DepAction != RootAction);
9417175cffbSMichael Kruse       DepAction->Execute();
9427175cffbSMichael Kruse     }
9437175cffbSMichael Kruse   }
9447175cffbSMichael Kruse 
945a6b2de3bSMichael Kruse   /// Try to forward an operand tree rooted in @p RA.
tryForwardTree(MemoryAccess * RA)946a6b2de3bSMichael Kruse   bool tryForwardTree(MemoryAccess *RA) {
947a6b2de3bSMichael Kruse     assert(RA->isLatestScalarKind());
948349506a9SNicola Zaghen     LLVM_DEBUG(dbgs() << "Trying to forward operand tree " << RA << "...\n");
949a6b2de3bSMichael Kruse 
950a6b2de3bSMichael Kruse     ScopStmt *Stmt = RA->getStatement();
951a6b2de3bSMichael Kruse     Loop *InLoop = Stmt->getSurroundingLoop();
952a6b2de3bSMichael Kruse 
95370af4f57SMichael Kruse     isl::map TargetToUse;
95470af4f57SMichael Kruse     if (!Known.is_null()) {
95570af4f57SMichael Kruse       isl::space DomSpace = Stmt->getDomainSpace();
95670af4f57SMichael Kruse       TargetToUse =
95770af4f57SMichael Kruse           isl::map::identity(DomSpace.map_from_domain_and_range(DomSpace));
95870af4f57SMichael Kruse     }
95970af4f57SMichael Kruse 
960d3ce899dSMichael Kruse     ForwardingDecision Assessment =
9617175cffbSMichael Kruse         forwardTree(Stmt, RA->getAccessValue(), Stmt, InLoop);
962a6b2de3bSMichael Kruse 
9637175cffbSMichael Kruse     // If considered feasible and profitable, forward it.
9647175cffbSMichael Kruse     bool Changed = false;
9657175cffbSMichael Kruse     if (Assessment == FD_CanForwardProfitably) {
9667175cffbSMichael Kruse       applyForwardingActions(Stmt, RA->getAccessValue(), RA);
9677175cffbSMichael Kruse       Changed = true;
9687175cffbSMichael Kruse     }
969a6b2de3bSMichael Kruse 
9707175cffbSMichael Kruse     ForwardingActions.clear();
9717175cffbSMichael Kruse     return Changed;
972a6b2de3bSMichael Kruse   }
973a6b2de3bSMichael Kruse 
974a6b2de3bSMichael Kruse   /// Return which SCoP this instance is processing.
getScop() const975a6b2de3bSMichael Kruse   Scop *getScop() const { return S; }
976a6b2de3bSMichael Kruse 
977a6b2de3bSMichael Kruse   /// Run the algorithm: Use value read accesses as operand tree roots and try
978a6b2de3bSMichael Kruse   /// to forward them into the statement.
forwardOperandTrees()979a6b2de3bSMichael Kruse   bool forwardOperandTrees() {
980a6b2de3bSMichael Kruse     for (ScopStmt &Stmt : *S) {
981a6b2de3bSMichael Kruse       bool StmtModified = false;
982a6b2de3bSMichael Kruse 
983a6b2de3bSMichael Kruse       // Because we are modifying the MemoryAccess list, collect them first to
984a6b2de3bSMichael Kruse       // avoid iterator invalidation.
985c8a0e27cSMichael Kruse       SmallVector<MemoryAccess *, 16> Accs(Stmt.begin(), Stmt.end());
986c8a0e27cSMichael Kruse 
987c8a0e27cSMichael Kruse       for (MemoryAccess *RA : Accs) {
988a6b2de3bSMichael Kruse         if (!RA->isRead())
989a6b2de3bSMichael Kruse           continue;
990a6b2de3bSMichael Kruse         if (!RA->isLatestScalarKind())
991a6b2de3bSMichael Kruse           continue;
992a6b2de3bSMichael Kruse 
993a6b2de3bSMichael Kruse         if (tryForwardTree(RA)) {
994a6b2de3bSMichael Kruse           Modified = true;
995a6b2de3bSMichael Kruse           StmtModified = true;
996a6b2de3bSMichael Kruse           NumForwardedTrees++;
997a6b2de3bSMichael Kruse           TotalForwardedTrees++;
998a6b2de3bSMichael Kruse         }
999a6b2de3bSMichael Kruse       }
1000a6b2de3bSMichael Kruse 
1001a6b2de3bSMichael Kruse       if (StmtModified) {
1002a6b2de3bSMichael Kruse         NumModifiedStmts++;
1003a6b2de3bSMichael Kruse         TotalModifiedStmts++;
1004a6b2de3bSMichael Kruse       }
1005a6b2de3bSMichael Kruse     }
1006a6b2de3bSMichael Kruse 
1007e8227804SMichael Kruse     if (Modified) {
1008a6b2de3bSMichael Kruse       ScopsModified++;
1009e8227804SMichael Kruse       S->realignParams();
1010e8227804SMichael Kruse     }
1011a6b2de3bSMichael Kruse     return Modified;
1012a6b2de3bSMichael Kruse   }
1013a6b2de3bSMichael Kruse 
1014a6b2de3bSMichael Kruse   /// Print the pass result, performed transformations and the SCoP after the
1015a6b2de3bSMichael Kruse   /// transformation.
print(raw_ostream & OS,int Indent=0)10169248fde5SEugene Zelenko   void print(raw_ostream &OS, int Indent = 0) {
1017a6b2de3bSMichael Kruse     printStatistics(OS, Indent);
1018a6b2de3bSMichael Kruse 
1019a6b2de3bSMichael Kruse     if (!Modified) {
1020a6b2de3bSMichael Kruse       // This line can easily be checked in regression tests.
1021a6b2de3bSMichael Kruse       OS << "ForwardOpTree executed, but did not modify anything\n";
1022a6b2de3bSMichael Kruse       return;
1023a6b2de3bSMichael Kruse     }
1024a6b2de3bSMichael Kruse 
1025a6b2de3bSMichael Kruse     printStatements(OS, Indent);
1026a6b2de3bSMichael Kruse   }
10274c64d8eeSMichael Kruse 
isModified() const10284c64d8eeSMichael Kruse   bool isModified() const { return Modified; }
1029a6b2de3bSMichael Kruse };
1030a6b2de3bSMichael Kruse 
runForwardOpTree(Scop & S,LoopInfo & LI)10314c64d8eeSMichael Kruse static std::unique_ptr<ForwardOpTreeImpl> runForwardOpTree(Scop &S,
10324c64d8eeSMichael Kruse                                                            LoopInfo &LI) {
1033a6b2de3bSMichael Kruse   std::unique_ptr<ForwardOpTreeImpl> Impl;
103489972e21SMichael Kruse   {
103500fd43b3SPhilip Pfaffe     IslMaxOperationsGuard MaxOpGuard(S.getIslCtx().get(), MaxOps, false);
1036736259e3SJonas Devlieghere     Impl = std::make_unique<ForwardOpTreeImpl>(&S, &LI, MaxOpGuard);
1037a6b2de3bSMichael Kruse 
103870af4f57SMichael Kruse     if (AnalyzeKnown) {
1039349506a9SNicola Zaghen       LLVM_DEBUG(dbgs() << "Prepare forwarders...\n");
104070af4f57SMichael Kruse       Impl->computeKnownValues();
104170af4f57SMichael Kruse     }
104270af4f57SMichael Kruse 
1043349506a9SNicola Zaghen     LLVM_DEBUG(dbgs() << "Forwarding operand trees...\n");
1044a6b2de3bSMichael Kruse     Impl->forwardOperandTrees();
1045a6b2de3bSMichael Kruse 
104689972e21SMichael Kruse     if (MaxOpGuard.hasQuotaExceeded()) {
1047349506a9SNicola Zaghen       LLVM_DEBUG(dbgs() << "Not all operations completed because of "
104889972e21SMichael Kruse                            "max_operations exceeded\n");
104989972e21SMichael Kruse       KnownOutOfQuota++;
105089972e21SMichael Kruse     }
105189972e21SMichael Kruse   }
105289972e21SMichael Kruse 
1053349506a9SNicola Zaghen   LLVM_DEBUG(dbgs() << "\nFinal Scop:\n");
1054349506a9SNicola Zaghen   LLVM_DEBUG(dbgs() << S);
1055a6b2de3bSMichael Kruse 
105606ed5292SMichael Kruse   // Update statistics
10574c64d8eeSMichael Kruse   Scop::ScopStatistics ScopStats = S.getStatistics();
105806ed5292SMichael Kruse   NumValueWrites += ScopStats.NumValueWrites;
105906ed5292SMichael Kruse   NumValueWritesInLoops += ScopStats.NumValueWritesInLoops;
106006ed5292SMichael Kruse   NumPHIWrites += ScopStats.NumPHIWrites;
106106ed5292SMichael Kruse   NumPHIWritesInLoops += ScopStats.NumPHIWritesInLoops;
106206ed5292SMichael Kruse   NumSingletonWrites += ScopStats.NumSingletonWrites;
106306ed5292SMichael Kruse   NumSingletonWritesInLoops += ScopStats.NumSingletonWritesInLoops;
106406ed5292SMichael Kruse 
10654c64d8eeSMichael Kruse   return Impl;
10664c64d8eeSMichael Kruse }
10674c64d8eeSMichael Kruse 
10684c64d8eeSMichael Kruse static PreservedAnalyses
runForwardOpTreeUsingNPM(Scop & S,ScopAnalysisManager & SAM,ScopStandardAnalysisResults & SAR,SPMUpdater & U,raw_ostream * OS)10694c64d8eeSMichael Kruse runForwardOpTreeUsingNPM(Scop &S, ScopAnalysisManager &SAM,
10704c64d8eeSMichael Kruse                          ScopStandardAnalysisResults &SAR, SPMUpdater &U,
10714c64d8eeSMichael Kruse                          raw_ostream *OS) {
10724c64d8eeSMichael Kruse   LoopInfo &LI = SAR.LI;
10734c64d8eeSMichael Kruse 
10744c64d8eeSMichael Kruse   std::unique_ptr<ForwardOpTreeImpl> Impl = runForwardOpTree(S, LI);
10754c64d8eeSMichael Kruse   if (OS) {
10764c64d8eeSMichael Kruse     *OS << "Printing analysis 'Polly - Forward operand tree' for region: '"
10774c64d8eeSMichael Kruse         << S.getName() << "' in function '" << S.getFunction().getName()
10784c64d8eeSMichael Kruse         << "':\n";
10794c64d8eeSMichael Kruse     if (Impl) {
10804c64d8eeSMichael Kruse       assert(Impl->getScop() == &S);
10814c64d8eeSMichael Kruse 
10824c64d8eeSMichael Kruse       Impl->print(*OS);
10834c64d8eeSMichael Kruse     }
10844c64d8eeSMichael Kruse   }
10854c64d8eeSMichael Kruse 
10864c64d8eeSMichael Kruse   if (!Impl->isModified())
10874c64d8eeSMichael Kruse     return PreservedAnalyses::all();
10884c64d8eeSMichael Kruse 
10894c64d8eeSMichael Kruse   PreservedAnalyses PA;
10904c64d8eeSMichael Kruse   PA.preserveSet<AllAnalysesOn<Module>>();
10914c64d8eeSMichael Kruse   PA.preserveSet<AllAnalysesOn<Function>>();
10924c64d8eeSMichael Kruse   PA.preserveSet<AllAnalysesOn<Loop>>();
10934c64d8eeSMichael Kruse   return PA;
10944c64d8eeSMichael Kruse }
10954c64d8eeSMichael Kruse 
10964c64d8eeSMichael Kruse /// Pass that redirects scalar reads to array elements that are known to contain
10974c64d8eeSMichael Kruse /// the same value.
10984c64d8eeSMichael Kruse ///
10994c64d8eeSMichael Kruse /// This reduces the number of scalar accesses and therefore potentially
11004c64d8eeSMichael Kruse /// increases the freedom of the scheduler. In the ideal case, all reads of a
11014c64d8eeSMichael Kruse /// scalar definition are redirected (We currently do not care about removing
11024c64d8eeSMichael Kruse /// the write in this case).  This is also useful for the main DeLICM pass as
11034c64d8eeSMichael Kruse /// there are less scalars to be mapped.
1104*bd93df93SMichael Kruse class ForwardOpTreeWrapperPass final : public ScopPass {
11054c64d8eeSMichael Kruse private:
11064c64d8eeSMichael Kruse   /// The pass implementation, also holding per-scop data.
11074c64d8eeSMichael Kruse   std::unique_ptr<ForwardOpTreeImpl> Impl;
11084c64d8eeSMichael Kruse 
11094c64d8eeSMichael Kruse public:
11104c64d8eeSMichael Kruse   static char ID;
11114c64d8eeSMichael Kruse 
ForwardOpTreeWrapperPass()11124c64d8eeSMichael Kruse   explicit ForwardOpTreeWrapperPass() : ScopPass(ID) {}
11134c64d8eeSMichael Kruse   ForwardOpTreeWrapperPass(const ForwardOpTreeWrapperPass &) = delete;
11144c64d8eeSMichael Kruse   ForwardOpTreeWrapperPass &
11154c64d8eeSMichael Kruse   operator=(const ForwardOpTreeWrapperPass &) = delete;
11164c64d8eeSMichael Kruse 
getAnalysisUsage(AnalysisUsage & AU) const11174c64d8eeSMichael Kruse   void getAnalysisUsage(AnalysisUsage &AU) const override {
11184c64d8eeSMichael Kruse     AU.addRequiredTransitive<ScopInfoRegionPass>();
11194c64d8eeSMichael Kruse     AU.addRequired<LoopInfoWrapperPass>();
11204c64d8eeSMichael Kruse     AU.setPreservesAll();
11214c64d8eeSMichael Kruse   }
11224c64d8eeSMichael Kruse 
runOnScop(Scop & S)11234c64d8eeSMichael Kruse   bool runOnScop(Scop &S) override {
11244c64d8eeSMichael Kruse     // Free resources for previous SCoP's computation, if not yet done.
11254c64d8eeSMichael Kruse     releaseMemory();
11264c64d8eeSMichael Kruse 
11274c64d8eeSMichael Kruse     LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
11284c64d8eeSMichael Kruse 
11294c64d8eeSMichael Kruse     Impl = runForwardOpTree(S, LI);
11304c64d8eeSMichael Kruse 
1131a6b2de3bSMichael Kruse     return false;
1132a6b2de3bSMichael Kruse   }
1133a6b2de3bSMichael Kruse 
printScop(raw_ostream & OS,Scop & S) const11349248fde5SEugene Zelenko   void printScop(raw_ostream &OS, Scop &S) const override {
1135a6b2de3bSMichael Kruse     if (!Impl)
1136a6b2de3bSMichael Kruse       return;
1137a6b2de3bSMichael Kruse 
1138a6b2de3bSMichael Kruse     assert(Impl->getScop() == &S);
1139a6b2de3bSMichael Kruse     Impl->print(OS);
1140a6b2de3bSMichael Kruse   }
1141a6b2de3bSMichael Kruse 
releaseMemory()11429248fde5SEugene Zelenko   void releaseMemory() override { Impl.reset(); }
1143a6b2de3bSMichael Kruse }; // class ForwardOpTree
1144a6b2de3bSMichael Kruse 
11454c64d8eeSMichael Kruse char ForwardOpTreeWrapperPass::ID;
11465c028081SMichael Kruse 
11475c028081SMichael Kruse /// Print result from ForwardOpTreeWrapperPass.
1148*bd93df93SMichael Kruse class ForwardOpTreePrinterLegacyPass final : public ScopPass {
11495c028081SMichael Kruse public:
11505c028081SMichael Kruse   static char ID;
11515c028081SMichael Kruse 
ForwardOpTreePrinterLegacyPass()11525c028081SMichael Kruse   ForwardOpTreePrinterLegacyPass() : ForwardOpTreePrinterLegacyPass(outs()){};
ForwardOpTreePrinterLegacyPass(llvm::raw_ostream & OS)11535c028081SMichael Kruse   explicit ForwardOpTreePrinterLegacyPass(llvm::raw_ostream &OS)
11545c028081SMichael Kruse       : ScopPass(ID), OS(OS) {}
11555c028081SMichael Kruse 
runOnScop(Scop & S)11565c028081SMichael Kruse   bool runOnScop(Scop &S) override {
11575c028081SMichael Kruse     ForwardOpTreeWrapperPass &P = getAnalysis<ForwardOpTreeWrapperPass>();
11585c028081SMichael Kruse 
11595c028081SMichael Kruse     OS << "Printing analysis '" << P.getPassName() << "' for region: '"
11605c028081SMichael Kruse        << S.getRegion().getNameStr() << "' in function '"
11615c028081SMichael Kruse        << S.getFunction().getName() << "':\n";
11625c028081SMichael Kruse     P.printScop(OS, S);
11635c028081SMichael Kruse 
11645c028081SMichael Kruse     return false;
11655c028081SMichael Kruse   }
11665c028081SMichael Kruse 
getAnalysisUsage(AnalysisUsage & AU) const11675c028081SMichael Kruse   void getAnalysisUsage(AnalysisUsage &AU) const override {
11685c028081SMichael Kruse     ScopPass::getAnalysisUsage(AU);
11695c028081SMichael Kruse     AU.addRequired<ForwardOpTreeWrapperPass>();
11705c028081SMichael Kruse     AU.setPreservesAll();
11715c028081SMichael Kruse   }
11725c028081SMichael Kruse 
11735c028081SMichael Kruse private:
11745c028081SMichael Kruse   llvm::raw_ostream &OS;
11755c028081SMichael Kruse };
11765c028081SMichael Kruse 
11775c028081SMichael Kruse char ForwardOpTreePrinterLegacyPass::ID = 0;
11789248fde5SEugene Zelenko } // namespace
1179a6b2de3bSMichael Kruse 
createForwardOpTreeWrapperPass()11804c64d8eeSMichael Kruse Pass *polly::createForwardOpTreeWrapperPass() {
11814c64d8eeSMichael Kruse   return new ForwardOpTreeWrapperPass();
11824c64d8eeSMichael Kruse }
1183a6b2de3bSMichael Kruse 
createForwardOpTreePrinterLegacyPass(llvm::raw_ostream & OS)11845c028081SMichael Kruse Pass *polly::createForwardOpTreePrinterLegacyPass(llvm::raw_ostream &OS) {
11855c028081SMichael Kruse   return new ForwardOpTreePrinterLegacyPass(OS);
11865c028081SMichael Kruse }
11875c028081SMichael Kruse 
run(Scop & S,ScopAnalysisManager & SAM,ScopStandardAnalysisResults & SAR,SPMUpdater & U)11884c64d8eeSMichael Kruse llvm::PreservedAnalyses ForwardOpTreePass::run(Scop &S,
11894c64d8eeSMichael Kruse                                                ScopAnalysisManager &SAM,
11904c64d8eeSMichael Kruse                                                ScopStandardAnalysisResults &SAR,
11914c64d8eeSMichael Kruse                                                SPMUpdater &U) {
11924c64d8eeSMichael Kruse   return runForwardOpTreeUsingNPM(S, SAM, SAR, U, nullptr);
11934c64d8eeSMichael Kruse }
11944c64d8eeSMichael Kruse 
11954c64d8eeSMichael Kruse llvm::PreservedAnalyses
run(Scop & S,ScopAnalysisManager & SAM,ScopStandardAnalysisResults & SAR,SPMUpdater & U)11964c64d8eeSMichael Kruse ForwardOpTreePrinterPass::run(Scop &S, ScopAnalysisManager &SAM,
11974c64d8eeSMichael Kruse                               ScopStandardAnalysisResults &SAR, SPMUpdater &U) {
11984c64d8eeSMichael Kruse   return runForwardOpTreeUsingNPM(S, SAM, SAR, U, &OS);
11994c64d8eeSMichael Kruse }
1200ad84c6f6SMichael Kruse 
1201ad84c6f6SMichael Kruse INITIALIZE_PASS_BEGIN(ForwardOpTreeWrapperPass, "polly-optree",
1202ad84c6f6SMichael Kruse                       "Polly - Forward operand tree", false, false)
1203ad84c6f6SMichael Kruse INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
1204ad84c6f6SMichael Kruse INITIALIZE_PASS_END(ForwardOpTreeWrapperPass, "polly-optree",
1205ad84c6f6SMichael Kruse                     "Polly - Forward operand tree", false, false)
12065c028081SMichael Kruse 
12075c028081SMichael Kruse INITIALIZE_PASS_BEGIN(ForwardOpTreePrinterLegacyPass, "polly-print-optree",
12085c028081SMichael Kruse                       "Polly - Print forward operand tree result", false, false)
12095c028081SMichael Kruse INITIALIZE_PASS_DEPENDENCY(ForwardOpTreeWrapperPass)
12105c028081SMichael Kruse INITIALIZE_PASS_END(ForwardOpTreePrinterLegacyPass, "polly-print-optree",
12115c028081SMichael Kruse                     "Polly - Print forward operand tree result", false, false)
1212