1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef jit_IonAnalysis_h
8 #define jit_IonAnalysis_h
9 
10 // This file declares various analysis passes that operate on MIR.
11 
12 #include "jit/JitAllocPolicy.h"
13 
14 namespace js {
15 
16 class PlainObject;
17 
18 namespace jit {
19 
20 class MBasicBlock;
21 class MCompare;
22 class MDefinition;
23 class MIRGenerator;
24 class MIRGraph;
25 class MTest;
26 
27 MOZ_MUST_USE bool PruneUnusedBranches(MIRGenerator* mir, MIRGraph& graph);
28 
29 MOZ_MUST_USE bool FoldTests(MIRGraph& graph);
30 
31 MOZ_MUST_USE bool FoldEmptyBlocks(MIRGraph& graph);
32 
33 MOZ_MUST_USE bool SplitCriticalEdges(MIRGraph& graph);
34 
35 bool IsUint32Type(const MDefinition* def);
36 
37 enum Observability { ConservativeObservability, AggressiveObservability };
38 
39 MOZ_MUST_USE bool EliminatePhis(MIRGenerator* mir, MIRGraph& graph,
40                                 Observability observe);
41 
42 size_t MarkLoopBlocks(MIRGraph& graph, MBasicBlock* header, bool* canOsr);
43 
44 void UnmarkLoopBlocks(MIRGraph& graph, MBasicBlock* header);
45 
46 MOZ_MUST_USE bool MakeLoopsContiguous(MIRGraph& graph);
47 
48 MOZ_MUST_USE bool EliminateDeadResumePointOperands(MIRGenerator* mir,
49                                                    MIRGraph& graph);
50 
51 MOZ_MUST_USE bool EliminateDeadCode(MIRGenerator* mir, MIRGraph& graph);
52 
53 MOZ_MUST_USE bool FoldLoadsWithUnbox(MIRGenerator* mir, MIRGraph& graph);
54 
55 MOZ_MUST_USE bool ApplyTypeInformation(MIRGenerator* mir, MIRGraph& graph);
56 
57 void RenumberBlocks(MIRGraph& graph);
58 
59 MOZ_MUST_USE bool AccountForCFGChanges(MIRGenerator* mir, MIRGraph& graph,
60                                        bool updateAliasAnalysis,
61                                        bool underValueNumberer = false);
62 
63 MOZ_MUST_USE bool RemoveUnmarkedBlocks(MIRGenerator* mir, MIRGraph& graph,
64                                        uint32_t numMarkedBlocks);
65 
66 void ClearDominatorTree(MIRGraph& graph);
67 
68 MOZ_MUST_USE bool BuildDominatorTree(MIRGraph& graph);
69 
70 MOZ_MUST_USE bool BuildPhiReverseMapping(MIRGraph& graph);
71 
72 void AssertBasicGraphCoherency(MIRGraph& graph, bool force = false);
73 
74 void AssertGraphCoherency(MIRGraph& graph, bool force = false);
75 
76 void AssertExtendedGraphCoherency(MIRGraph& graph,
77                                   bool underValueNumberer = false,
78                                   bool force = false);
79 
80 MOZ_MUST_USE bool EliminateRedundantChecks(MIRGraph& graph);
81 
82 MOZ_MUST_USE bool AddKeepAliveInstructions(MIRGraph& graph);
83 
84 // Simple linear sum of the form 'n' or 'x + n'.
85 struct SimpleLinearSum {
86   MDefinition* term;
87   int32_t constant;
88 
SimpleLinearSumSimpleLinearSum89   SimpleLinearSum(MDefinition* term, int32_t constant)
90       : term(term), constant(constant) {}
91 };
92 
93 // Math done in a Linear sum can either be in a modulo space, in which case
94 // overflow are wrapped around, or they can be computed in the integer-space in
95 // which case we have to check that no overflow can happen when summing
96 // constants.
97 //
98 // When the caller ignores which space it is, the definition would be used to
99 // deduce it.
100 enum class MathSpace { Modulo, Infinite, Unknown };
101 
102 SimpleLinearSum ExtractLinearSum(MDefinition* ins,
103                                  MathSpace space = MathSpace::Unknown);
104 
105 MOZ_MUST_USE bool ExtractLinearInequality(MTest* test,
106                                           BranchDirection direction,
107                                           SimpleLinearSum* plhs,
108                                           MDefinition** prhs, bool* plessEqual);
109 
110 struct LinearTerm {
111   MDefinition* term;
112   int32_t scale;
113 
LinearTermLinearTerm114   LinearTerm(MDefinition* term, int32_t scale) : term(term), scale(scale) {}
115 };
116 
117 // General linear sum of the form 'x1*n1 + x2*n2 + ... + n'
118 class LinearSum {
119  public:
LinearSum(TempAllocator & alloc)120   explicit LinearSum(TempAllocator& alloc) : terms_(alloc), constant_(0) {}
121 
LinearSum(const LinearSum & other)122   LinearSum(const LinearSum& other)
123       : terms_(other.terms_.allocPolicy()), constant_(other.constant_) {
124     AutoEnterOOMUnsafeRegion oomUnsafe;
125     if (!terms_.appendAll(other.terms_)) {
126       oomUnsafe.crash("LinearSum::LinearSum");
127     }
128   }
129 
130   // These return false on an integer overflow, and afterwards the sum must
131   // not be used.
132   MOZ_MUST_USE bool multiply(int32_t scale);
133   MOZ_MUST_USE bool add(const LinearSum& other, int32_t scale = 1);
134   MOZ_MUST_USE bool add(SimpleLinearSum other, int32_t scale = 1);
135   MOZ_MUST_USE bool add(MDefinition* term, int32_t scale);
136   MOZ_MUST_USE bool add(int32_t constant);
137 
138   // Unlike the above function, on failure this leaves the sum unchanged and
139   // it can still be used.
140   MOZ_MUST_USE bool divide(uint32_t scale);
141 
constant()142   int32_t constant() const { return constant_; }
numTerms()143   size_t numTerms() const { return terms_.length(); }
term(size_t i)144   LinearTerm term(size_t i) const { return terms_[i]; }
replaceTerm(size_t i,MDefinition * def)145   void replaceTerm(size_t i, MDefinition* def) { terms_[i].term = def; }
146 
147   void dump(GenericPrinter& out) const;
148   void dump() const;
149 
150  private:
151   Vector<LinearTerm, 2, JitAllocPolicy> terms_;
152   int32_t constant_;
153 };
154 
155 // Convert all components of a linear sum (except, optionally, the constant)
156 // and add any new instructions to the end of block.
157 MDefinition* ConvertLinearSum(TempAllocator& alloc, MBasicBlock* block,
158                               const LinearSum& sum,
159                               bool convertConstant = false);
160 
161 // Convert the test 'sum >= 0' to a comparison, adding any necessary
162 // instructions to the end of block.
163 MCompare* ConvertLinearInequality(TempAllocator& alloc, MBasicBlock* block,
164                                   const LinearSum& sum);
165 
166 MOZ_MUST_USE bool AnalyzeNewScriptDefiniteProperties(
167     JSContext* cx, DPAConstraintInfo& constraintInfo, HandleFunction fun,
168     ObjectGroup* group, Handle<PlainObject*> baseobj,
169     Vector<TypeNewScriptInitializer>* initializerList);
170 
171 MOZ_MUST_USE bool AnalyzeArgumentsUsage(JSContext* cx, JSScript* script);
172 
173 bool DeadIfUnused(const MDefinition* def);
174 
175 bool IsDiscardable(const MDefinition* def);
176 
177 class CompileInfo;
178 void DumpMIRExpressions(MIRGraph& graph, const CompileInfo& info,
179                         const char* phase);
180 
181 }  // namespace jit
182 }  // namespace js
183 
184 #endif /* jit_IonAnalysis_h */
185