| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are |
| 4 // met: |
| 5 // |
| 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. |
| 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 |
| 28 #ifndef V8_HYDROGEN_PHASES_H_ |
| 29 #define V8_HYDROGEN_PHASES_H_ |
| 30 |
| 31 #include "hydrogen.h" |
| 32 |
| 33 namespace v8 { |
| 34 namespace internal { |
| 35 |
| 36 |
| 37 class BoundsCheckBbData; |
| 38 class BoundsCheckKey; |
| 39 class BoundsCheckTable : private ZoneHashMap { |
| 40 public: |
| 41 explicit BoundsCheckTable(Zone* zone); |
| 42 |
| 43 INLINE(BoundsCheckBbData** LookupOrInsert(BoundsCheckKey* key, Zone* zone)); |
| 44 INLINE(void Insert(BoundsCheckKey* key, BoundsCheckBbData* data, Zone* zone)); |
| 45 INLINE(void Delete(BoundsCheckKey* key)); |
| 46 |
| 47 private: |
| 48 DISALLOW_COPY_AND_ASSIGN(BoundsCheckTable); |
| 49 }; |
| 50 |
| 51 |
| 52 class HBoundsCheckEliminationPhase : public HPhase { |
| 53 public: |
| 54 explicit HBoundsCheckEliminationPhase(HGraph* graph) |
| 55 : HPhase("H_Bounds checks elimination", graph), table_(zone()) { } |
| 56 |
| 57 void Run() { EliminateRedundantBoundsChecks(graph()->entry_block()); } |
| 58 |
| 59 private: |
| 60 void EliminateRedundantBoundsChecks(HBasicBlock* bb); |
| 61 |
| 62 BoundsCheckTable table_; |
| 63 |
| 64 DISALLOW_COPY_AND_ASSIGN(HBoundsCheckEliminationPhase); |
| 65 }; |
| 66 |
| 67 |
| 68 class HCanonicalizePhase : public HPhase { |
| 69 public: |
| 70 explicit HCanonicalizePhase(HGraph* graph) |
| 71 : HPhase("H_Canonicalize", graph) { } |
| 72 |
| 73 void Run(); |
| 74 |
| 75 private: |
| 76 DISALLOW_COPY_AND_ASSIGN(HCanonicalizePhase); |
| 77 }; |
| 78 |
| 79 |
| 80 class HDeadCodeEliminationPhase : public HPhase { |
| 81 public: |
| 82 explicit HDeadCodeEliminationPhase(HGraph* graph) |
| 83 : HPhase("H_Dead code elimination", graph) { } |
| 84 |
| 85 void Run() { |
| 86 MarkLiveInstructions(); |
| 87 RemoveDeadInstructions(); |
| 88 } |
| 89 |
| 90 private: |
| 91 bool MarkLive(HValue* ref, HValue* instr); |
| 92 void MarkLiveInstructions(); |
| 93 void RemoveDeadInstructions(); |
| 94 |
| 95 DISALLOW_COPY_AND_ASSIGN(HDeadCodeEliminationPhase); |
| 96 }; |
| 97 |
| 98 |
| 99 class HDehoistIndexComputationsPhase : public HPhase { |
| 100 public: |
| 101 explicit HDehoistIndexComputationsPhase(HGraph* graph) |
| 102 : HPhase("H_Dehoist index computations", graph) { } |
| 103 |
| 104 void Run(); |
| 105 |
| 106 private: |
| 107 DISALLOW_COPY_AND_ASSIGN(HDehoistIndexComputationsPhase); |
| 108 }; |
| 109 |
| 110 |
| 111 // Mark all blocks that are dominated by an unconditional soft deoptimize to |
| 112 // prevent code motion across those blocks. |
| 113 class HPropagateDeoptimizingMarkPhase : public HPhase { |
| 114 public: |
| 115 explicit HPropagateDeoptimizingMarkPhase(HGraph* graph) |
| 116 : HPhase("H_Propagate deoptimizing mark", graph) { } |
| 117 |
| 118 void Run(); |
| 119 |
| 120 private: |
| 121 void MarkAsDeoptimizing(); |
| 122 void NullifyUnreachableInstructions(); |
| 123 |
| 124 DISALLOW_COPY_AND_ASSIGN(HPropagateDeoptimizingMarkPhase); |
| 125 }; |
| 126 |
| 127 |
| 128 // Trims live ranges of environment slots by doing explicit liveness analysis. |
| 129 // Values in the environment are kept alive by every subsequent LInstruction |
| 130 // that is assigned an LEnvironment, which creates register pressure and |
| 131 // unnecessary spill slot moves. Therefore it is beneficial to trim the |
| 132 // live ranges of environment slots by zapping them with a constant after |
| 133 // the last lookup that refers to them. |
| 134 // Slots are identified by their index and only affected if whitelisted in |
| 135 // HOptimizedGraphBuilder::IsEligibleForEnvironmentLivenessAnalysis(). |
| 136 class HEnvironmentLivenessAnalysisPhase : public HPhase { |
| 137 public: |
| 138 explicit HEnvironmentLivenessAnalysisPhase(HGraph* graph); |
| 139 |
| 140 void Run(); |
| 141 |
| 142 private: |
| 143 void ZapEnvironmentSlot(int index, HSimulate* simulate); |
| 144 void ZapEnvironmentSlotsInSuccessors(HBasicBlock* block, BitVector* live); |
| 145 void ZapEnvironmentSlotsForInstruction(HEnvironmentMarker* marker); |
| 146 void UpdateLivenessAtBlockEnd(HBasicBlock* block, BitVector* live); |
| 147 void UpdateLivenessAtInstruction(HInstruction* instr, BitVector* live); |
| 148 |
| 149 int block_count_; |
| 150 |
| 151 // Largest number of local variables in any environment in the graph |
| 152 // (including inlined environments). |
| 153 int maximum_environment_size_; |
| 154 |
| 155 // Per-block data. All these lists are indexed by block_id. |
| 156 ZoneList<BitVector*> live_at_block_start_; |
| 157 ZoneList<HSimulate*> first_simulate_; |
| 158 ZoneList<BitVector*> first_simulate_invalid_for_index_; |
| 159 |
| 160 // List of all HEnvironmentMarker instructions for quick iteration/deletion. |
| 161 // It is populated during the first pass over the graph, controlled by |
| 162 // |collect_markers_|. |
| 163 ZoneList<HEnvironmentMarker*> markers_; |
| 164 bool collect_markers_; |
| 165 |
| 166 // Keeps track of the last simulate seen, as well as the environment slots |
| 167 // for which a new live range has started since (so they must not be zapped |
| 168 // in that simulate when the end of another live range of theirs is found). |
| 169 HSimulate* last_simulate_; |
| 170 BitVector went_live_since_last_simulate_; |
| 171 |
| 172 DISALLOW_COPY_AND_ASSIGN(HEnvironmentLivenessAnalysisPhase); |
| 173 }; |
| 174 |
| 175 |
| 176 class HEscapeAnalysisPhase : public HPhase { |
| 177 public: |
| 178 explicit HEscapeAnalysisPhase(HGraph* graph) |
| 179 : HPhase("H_Escape analysis", graph), captured_(0, zone()) { } |
| 180 |
| 181 void Run() { CollectCapturedValues(); } |
| 182 |
| 183 private: |
| 184 void CollectCapturedValues(); |
| 185 void CollectIfNoEscapingUses(HInstruction* instr); |
| 186 |
| 187 ZoneList<HValue*> captured_; |
| 188 |
| 189 DISALLOW_COPY_AND_ASSIGN(HEscapeAnalysisPhase); |
| 190 }; |
| 191 |
| 192 |
| 193 class HInferRepresentationPhase : public HPhase { |
| 194 public: |
| 195 explicit HInferRepresentationPhase(HGraph* graph) |
| 196 : HPhase("H_Infer representations", graph), |
| 197 worklist_(8, zone()), |
| 198 in_worklist_(graph->GetMaximumValueID(), zone()) { } |
| 199 |
| 200 void Run(); |
| 201 void AddToWorklist(HValue* current); |
| 202 |
| 203 private: |
| 204 ZoneList<HValue*> worklist_; |
| 205 BitVector in_worklist_; |
| 206 |
| 207 DISALLOW_COPY_AND_ASSIGN(HInferRepresentationPhase); |
| 208 }; |
| 209 |
| 210 |
| 211 class HInferTypesPhase : public HPhase { |
| 212 public: |
| 213 explicit HInferTypesPhase(HGraph* graph) |
| 214 : HPhase("H_Inferring types", graph), worklist_(8, zone()), |
| 215 in_worklist_(graph->GetMaximumValueID(), zone()) { } |
| 216 |
| 217 void Run() { InferTypes(0, graph()->blocks()->length() - 1); } |
| 218 |
| 219 private: |
| 220 void InferTypes(int from_inclusive, int to_inclusive); |
| 221 |
| 222 ZoneList<HValue*> worklist_; |
| 223 BitVector in_worklist_; |
| 224 |
| 225 DISALLOW_COPY_AND_ASSIGN(HInferTypesPhase); |
| 226 }; |
| 227 |
| 228 |
| 229 // Perform common subexpression elimination and loop-invariant code motion. |
| 230 class HGlobalValueNumberingPhase : public HPhase { |
| 231 public: |
| 232 explicit HGlobalValueNumberingPhase(HGraph* graph); |
| 233 |
| 234 void Run() { |
| 235 Analyze(); |
| 236 // Trigger a second analysis pass to further eliminate duplicate values |
| 237 // that could only be discovered by removing side-effect-generating |
| 238 // instructions during the first pass. |
| 239 if (FLAG_smi_only_arrays && removed_side_effects_) { |
| 240 Analyze(); |
| 241 ASSERT(!removed_side_effects_); |
| 242 } |
| 243 } |
| 244 |
| 245 private: |
| 246 void Analyze(); |
| 247 GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock( |
| 248 HBasicBlock* dominator, |
| 249 HBasicBlock* dominated); |
| 250 void AnalyzeGraph(); |
| 251 void ComputeBlockSideEffects(); |
| 252 void LoopInvariantCodeMotion(); |
| 253 void ProcessLoopBlock(HBasicBlock* block, |
| 254 HBasicBlock* before_loop, |
| 255 GVNFlagSet loop_kills, |
| 256 GVNFlagSet* accumulated_first_time_depends, |
| 257 GVNFlagSet* accumulated_first_time_changes); |
| 258 bool AllowCodeMotion(); |
| 259 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); |
| 260 |
| 261 bool removed_side_effects_; |
| 262 |
| 263 // A map of block IDs to their side effects. |
| 264 ZoneList<GVNFlagSet> block_side_effects_; |
| 265 |
| 266 // A map of loop header block IDs to their loop's side effects. |
| 267 ZoneList<GVNFlagSet> loop_side_effects_; |
| 268 |
| 269 // Used when collecting side effects on paths from dominator to |
| 270 // dominated. |
| 271 BitVector visited_on_paths_; |
| 272 |
| 273 DISALLOW_COPY_AND_ASSIGN(HGlobalValueNumberingPhase); |
| 274 }; |
| 275 |
| 276 |
| 277 class HComputeMinusZeroChecksPhase : public HPhase { |
| 278 public: |
| 279 explicit HComputeMinusZeroChecksPhase(HGraph* graph) |
| 280 : HPhase("H_Compute minus zero checks", graph), |
| 281 visited_(graph->GetMaximumValueID(), zone()) { } |
| 282 |
| 283 void Run(); |
| 284 |
| 285 private: |
| 286 void PropagateMinusZeroChecks(HValue* value); |
| 287 |
| 288 BitVector visited_; |
| 289 |
| 290 DISALLOW_COPY_AND_ASSIGN(HComputeMinusZeroChecksPhase); |
| 291 }; |
| 292 |
| 293 |
| 294 class HRangeAnalysisPhase : public HPhase { |
| 295 public: |
| 296 explicit HRangeAnalysisPhase(HGraph* graph) |
| 297 : HPhase("H_Range analysis", graph), changed_ranges_(16, zone()) { } |
| 298 |
| 299 void Run(); |
| 300 |
| 301 private: |
| 302 void TraceRange(const char* msg, ...); |
| 303 void InferControlFlowRange(HCompareNumericAndBranch* test, |
| 304 HBasicBlock* dest); |
| 305 void UpdateControlFlowRange(Token::Value op, HValue* value, HValue* other); |
| 306 void InferRange(HValue* value); |
| 307 void RollBackTo(int index); |
| 308 void AddRange(HValue* value, Range* range); |
| 309 |
| 310 ZoneList<HValue*> changed_ranges_; |
| 311 |
| 312 DISALLOW_COPY_AND_ASSIGN(HRangeAnalysisPhase); |
| 313 }; |
| 314 |
| 315 |
| 316 // Replace all phis consisting of a single non-loop operand plus any number of |
| 317 // loop operands by that single non-loop operand. |
| 318 class HRedundantPhiEliminationPhase : public HPhase { |
| 319 public: |
| 320 explicit HRedundantPhiEliminationPhase(HGraph* graph) |
| 321 : HPhase("H_Redundant phi elimination", graph) { } |
| 322 |
| 323 void Run(); |
| 324 |
| 325 private: |
| 326 DISALLOW_COPY_AND_ASSIGN(HRedundantPhiEliminationPhase); |
| 327 }; |
| 328 |
| 329 |
| 330 class HMergeRemovableSimulatesPhase : public HPhase { |
| 331 public: |
| 332 explicit HMergeRemovableSimulatesPhase(HGraph* graph) |
| 333 : HPhase("H_Merge removable simulates", graph) { } |
| 334 |
| 335 void Run(); |
| 336 |
| 337 private: |
| 338 DISALLOW_COPY_AND_ASSIGN(HMergeRemovableSimulatesPhase); |
| 339 }; |
| 340 |
| 341 |
| 342 class HRepresentationChangesPhase : public HPhase { |
| 343 public: |
| 344 explicit HRepresentationChangesPhase(HGraph* graph) |
| 345 : HPhase("H_Representation changes", graph) { } |
| 346 |
| 347 void Run(); |
| 348 |
| 349 private: |
| 350 void InsertRepresentationChangeForUse(HValue* value, |
| 351 HValue* use_value, |
| 352 int use_index, |
| 353 Representation to); |
| 354 void InsertRepresentationChangesForValue(HValue* value); |
| 355 |
| 356 DISALLOW_COPY_AND_ASSIGN(HRepresentationChangesPhase); |
| 357 }; |
| 358 |
| 359 |
| 360 class HStackCheckEliminationPhase : public HPhase { |
| 361 public: |
| 362 explicit HStackCheckEliminationPhase(HGraph* graph) |
| 363 : HPhase("H_Stack check elimination", graph) { } |
| 364 |
| 365 void Run(); |
| 366 |
| 367 private: |
| 368 DISALLOW_COPY_AND_ASSIGN(HStackCheckEliminationPhase); |
| 369 }; |
| 370 |
| 371 |
| 372 // Discover instructions that can be marked with kUint32 flag allowing |
| 373 // them to produce full range uint32 values. |
| 374 class HUint32AnalysisPhase : public HPhase { |
| 375 public: |
| 376 explicit HUint32AnalysisPhase(HGraph* graph) |
| 377 : HPhase("H_Compute safe UInt32 operations", graph), phis_(4, zone()) { } |
| 378 |
| 379 void Run(); |
| 380 |
| 381 private: |
| 382 INLINE(bool IsSafeUint32Use(HValue* val, HValue* use)); |
| 383 INLINE(bool Uint32UsesAreSafe(HValue* uint32val)); |
| 384 INLINE(bool CheckPhiOperands(HPhi* phi)); |
| 385 INLINE(void UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist)); |
| 386 INLINE(void UnmarkUnsafePhis()); |
| 387 |
| 388 ZoneList<HPhi*> phis_; |
| 389 |
| 390 DISALLOW_COPY_AND_ASSIGN(HUint32AnalysisPhase); |
| 391 }; |
| 392 |
| 393 |
| 394 } } // namespace v8::internal |
| 395 |
| 396 #endif // V8_HYDROGEN_PHASES_H_ |
| OLD | NEW |