IonAnalysis.h (8111B)
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 <stddef.h> 13 #include <stdint.h> 14 15 #include "jit/IonTypes.h" 16 #include "jit/JitAllocPolicy.h" 17 #include "js/TypeDecls.h" 18 #include "js/Utility.h" 19 #include "js/Vector.h" 20 21 namespace js { 22 23 class JS_PUBLIC_API GenericPrinter; 24 class PlainObject; 25 26 namespace jit { 27 28 class MBasicBlock; 29 class MCompare; 30 class MDefinition; 31 class MIRGenerator; 32 class MIRGraph; 33 class MTest; 34 35 [[nodiscard]] bool PruneUnusedBranches(const MIRGenerator* mir, 36 MIRGraph& graph); 37 38 [[nodiscard]] bool FoldTests(MIRGraph& graph); 39 40 [[nodiscard]] bool FoldEmptyBlocks(MIRGraph& graph, bool* changed); 41 42 [[nodiscard]] bool SplitCriticalEdges(MIRGraph& graph); 43 44 [[nodiscard]] bool OptimizeIteratorIndices(const MIRGenerator* mir, 45 MIRGraph& graph); 46 47 bool IsUint32Type(const MDefinition* def); 48 49 enum Observability { ConservativeObservability, AggressiveObservability }; 50 51 [[nodiscard]] bool EliminatePhis(const MIRGenerator* mir, MIRGraph& graph, 52 Observability observe); 53 54 size_t MarkLoopBlocks(MIRGraph& graph, const MBasicBlock* header, bool* canOsr); 55 56 void UnmarkLoopBlocks(MIRGraph& graph, const MBasicBlock* header); 57 58 [[nodiscard]] bool MakeLoopsContiguous(MIRGraph& graph); 59 60 [[nodiscard]] bool EliminateTriviallyDeadResumePointOperands( 61 const MIRGenerator* mir, MIRGraph& graph); 62 63 [[nodiscard]] bool EliminateDeadResumePointOperands(const MIRGenerator* mir, 64 MIRGraph& graph); 65 66 [[nodiscard]] bool EliminateDeadCode(const MIRGenerator* mir, MIRGraph& graph); 67 68 [[nodiscard]] bool FoldLoadsWithUnbox(const MIRGenerator* mir, MIRGraph& graph); 69 70 [[nodiscard]] bool ApplyTypeInformation(const MIRGenerator* mir, 71 MIRGraph& graph); 72 73 void RenumberBlocks(MIRGraph& graph); 74 75 [[nodiscard]] bool AccountForCFGChanges(const MIRGenerator* mir, 76 MIRGraph& graph, 77 bool updateAliasAnalysis, 78 bool underValueNumberer = false); 79 80 [[nodiscard]] bool RemoveUnmarkedBlocks(const MIRGenerator* mir, 81 MIRGraph& graph, 82 uint32_t numMarkedBlocks); 83 84 [[nodiscard]] bool BuildPhiReverseMapping(MIRGraph& graph); 85 86 void AssertBasicGraphCoherency(MIRGraph& graph, bool force = false); 87 88 void AssertGraphCoherency(MIRGraph& graph, bool force = false); 89 90 void AssertExtendedGraphCoherency(MIRGraph& graph, 91 bool underValueNumberer = false, 92 bool force = false); 93 94 [[nodiscard]] bool EliminateRedundantChecks(MIRGraph& graph); 95 96 [[nodiscard]] bool EliminateRedundantShapeGuards(MIRGraph& graph); 97 98 [[nodiscard]] bool EliminateRedundantGCBarriers(MIRGraph& graph); 99 100 [[nodiscard]] bool AddKeepAliveInstructions(MIRGraph& graph); 101 102 [[nodiscard]] bool MarkLoadsUsedAsPropertyKeys(MIRGraph& graph); 103 104 [[nodiscard]] bool TrackWasmRefTypes(MIRGraph& graph); 105 106 // Simple linear sum of the form 'n' or 'x + n'. 107 struct SimpleLinearSum { 108 MDefinition* term; 109 int32_t constant; 110 111 SimpleLinearSum(MDefinition* term, int32_t constant) 112 : term(term), constant(constant) {} 113 }; 114 115 // Math done in a Linear sum can either be in a modulo space, in which case 116 // overflow are wrapped around, or they can be computed in the integer-space in 117 // which case we have to check that no overflow can happen when summing 118 // constants. 119 // 120 // When the caller ignores which space it is, the definition would be used to 121 // deduce it. 122 enum class MathSpace { Modulo, Infinite, Unknown }; 123 124 SimpleLinearSum ExtractLinearSum(MDefinition* ins, 125 MathSpace space = MathSpace::Unknown, 126 int32_t recursionDepth = 0); 127 128 [[nodiscard]] bool ExtractLinearInequality(const MTest* test, 129 BranchDirection direction, 130 SimpleLinearSum* plhs, 131 MDefinition** prhs, 132 bool* plessEqual); 133 134 struct LinearTerm { 135 MDefinition* term; 136 int32_t scale; 137 138 LinearTerm(MDefinition* term, int32_t scale) : term(term), scale(scale) {} 139 }; 140 141 // General linear sum of the form 'x1*n1 + x2*n2 + ... + n' 142 class LinearSum { 143 public: 144 explicit LinearSum(TempAllocator& alloc) : terms_(alloc), constant_(0) {} 145 146 LinearSum(const LinearSum& other) 147 : terms_(other.terms_.allocPolicy()), constant_(other.constant_) { 148 AutoEnterOOMUnsafeRegion oomUnsafe; 149 if (!terms_.appendAll(other.terms_)) { 150 oomUnsafe.crash("LinearSum::LinearSum"); 151 } 152 } 153 154 // These return false on an integer overflow, and afterwards the sum must 155 // not be used. 156 [[nodiscard]] bool multiply(int32_t scale); 157 [[nodiscard]] bool add(const LinearSum& other, int32_t scale = 1); 158 [[nodiscard]] bool add(SimpleLinearSum other, int32_t scale = 1); 159 [[nodiscard]] bool add(MDefinition* term, int32_t scale); 160 [[nodiscard]] bool add(int32_t constant); 161 162 // Unlike the above function, on failure this leaves the sum unchanged and 163 // it can still be used. 164 [[nodiscard]] bool divide(uint32_t scale); 165 166 int32_t constant() const { return constant_; } 167 size_t numTerms() const { return terms_.length(); } 168 LinearTerm term(size_t i) const { return terms_[i]; } 169 void replaceTerm(size_t i, MDefinition* def) { terms_[i].term = def; } 170 171 void dump(GenericPrinter& out) const; 172 void dump() const; 173 174 private: 175 Vector<LinearTerm, 2, JitAllocPolicy> terms_; 176 int32_t constant_; 177 }; 178 179 // Convert all components of a linear sum (except the constant) 180 // and add any new instructions to the end of block. 181 MDefinition* ConvertLinearSum(TempAllocator& alloc, MBasicBlock* block, 182 const LinearSum& sum, BailoutKind bailoutKind); 183 184 bool DeadIfUnused(const MDefinition* def); 185 bool DeadIfUnusedAllowEffectful(const MDefinition* def); 186 187 bool IsDiscardable(const MDefinition* def); 188 bool IsDiscardableAllowEffectful(const MDefinition* def); 189 190 class CompileInfo; 191 192 // Debug printing. When `showDetails` is `true`, extra details are shown. 193 // Also, in that case, these routines will show an integer base-26 hashed 194 // version of pointers. This helps avoid ambiguities resulting from use of IDs 195 // for MBasicBlocks and MDefinitions. Be aware the hashed pointers are not 196 // guaranteed to be unique, although collisions are very unlikely. 197 198 // Dump `p`, hashed, to `out`. 199 void DumpHashedPointer(GenericPrinter& out, const void* p); 200 201 // Dump the ID and possibly the pointer hash of `def`, to `out`. 202 void DumpMIRDefinitionID(GenericPrinter& out, const MDefinition* def, 203 bool showDetails = false); 204 // Dump an MDefinition to `out`. 205 void DumpMIRDefinition(GenericPrinter& out, const MDefinition* def, 206 bool showDetails = false); 207 208 // Dump the ID and possibly the pointer hash of `block`, to `out`. 209 void DumpMIRBlockID(GenericPrinter& out, const MBasicBlock* block, 210 bool showDetails = false); 211 // Dump an MBasicBlock to `out`. 212 void DumpMIRBlock(GenericPrinter& out, MBasicBlock* block, 213 bool showDetails = false); 214 215 // Dump an entire MIRGraph to `out`. 216 void DumpMIRGraph(GenericPrinter& out, MIRGraph& graph, 217 bool showDetails = false); 218 219 // Legacy entry point for DumpMIRGraph. 220 void DumpMIRExpressions(GenericPrinter& out, MIRGraph& graph, 221 const CompileInfo& info, const char* phase, 222 bool showDetails = false); 223 } // namespace jit 224 } // namespace js 225 226 #endif /* jit_IonAnalysis_h */