52 static const int kNoBlock = -1;
54 HBasicBlock*
block() {
return block_; }
55 void set_block(HBasicBlock* block) { block_ = block; }
62 return &additional_limit_;
71 HLoopInformation* loop = data->phi()->block()->current_loop();
72 is_start_ = (block() == loop->loop_header());
73 is_proper_exit_ = (block() == data->induction_exit_target());
74 is_in_loop_ = loop->IsNestedInThisLoop(block()->current_loop());
81 ASSERT(current_dominated_block_ != kNoBlock);
82 return current_dominated_block_ < block()->dominated_blocks()->length() ?
83 block()->dominated_blocks()->at(current_dominated_block_) :
NULL;
86 current_dominated_block_++;
87 return CurrentDominatedBlock();
92 has_check_(
false), additional_limit_(),
93 current_dominated_block_(kNoBlock) {}
102 int current_dominated_block_;
105 HGraph*
graph()
const {
return graph_; }
108 Element*
at(
int index)
const {
return &(elements_.at(index)); }
109 Element*
at(HBasicBlock* block)
const {
return at(block->block_id()); }
112 at(block->block_id())->set_has_check();
120 for (
int i = 0; i < graph()->blocks()->length(); i++) {
121 at(i)->InitializeLoop(data);
123 loop_header_ = data->phi()->block()->current_loop()->loop_header();
145 for (
int i = 0; i < elements_.length(); i++) {
146 at(i)->ResetCurrentDominatedBlock();
150 HBasicBlock* current = loop_header();
151 while (current !=
NULL) {
154 if (at(current)->has_check() || !at(current)->is_in_loop()) {
159 for (
int i = 0; i < current->end()->SuccessorCount(); i ++) {
160 Element* successor = at(current->end()->SuccessorAt(i));
175 return NOT_HOISTABLE;
183 while (next ==
NULL) {
184 current = current->dominator();
185 if (current !=
NULL) {
186 next = at(current)->NextDominatedBlock();
197 return unsafe ? OPTIMISTICALLY_HOISTABLE : HOISTABLE;
201 : graph_(graph), loop_header_(
NULL),
202 elements_(graph->blocks()->length(), graph->zone()) {
203 for (
int i = 0; i < graph->blocks()->length(); i++) {
205 element.
set_block(graph->blocks()->at(i));
206 elements_.Add(element, graph->zone());
207 ASSERT(at(i)->block()->block_id() == i);
213 InductionVariableData::InductionVariableCheck*
check,
214 InductionVariableData* data) {
215 HValue* length = check->check()->length();
216 check->set_processed();
217 HBasicBlock* header =
218 data->phi()->
block()->current_loop()->loop_header();
219 HBasicBlock* pre_header = header->predecessors()->at(0);
221 if (!data->limit()->IsInteger32Constant()) {
222 HBasicBlock* limit_block = data->limit()->block();
223 if (limit_block != pre_header &&
224 !limit_block->Dominates(pre_header)) {
229 if (!(data->limit()->representation().Equals(
231 data->limit()->IsInteger32Constant())) {
235 if (check->check()->length()->block() != pre_header &&
236 !check->check()->length()->block()->Dominates(pre_header)) {
241 for (InductionVariableData::InductionVariableCheck* current_check = check;
242 current_check !=
NULL;
243 current_check = current_check->next()) {
244 if (current_check->check()->length() != length)
continue;
246 AddCheckAt(current_check->check()->block());
247 current_check->set_processed();
252 if (hoistability == NOT_HOISTABLE ||
253 (hoistability == OPTIMISTICALLY_HOISTABLE &&
254 !graph()->use_optimistic_licm())) {
261 bool has_upper_constant_limit =
true;
263 check !=
NULL && check->HasUpperLimit() ? check->upper_limit() : 0;
264 for (InductionVariableData::InductionVariableCheck* current_check = check;
265 current_check !=
NULL;
266 current_check = current_check->next()) {
267 has_upper_constant_limit =
268 has_upper_constant_limit &&
269 check->HasUpperLimit() &&
270 check->upper_limit() == upper_constant_limit;
271 counters()->bounds_checks_eliminated()->Increment();
272 current_check->check()->set_skip_check();
276 Zone* zone = graph()->zone();
277 HValue* context = graph()->GetInvalidContext();
278 HValue* limit = data->limit();
279 if (has_upper_constant_limit) {
280 HConstant* new_limit = HConstant::New(zone, context,
281 upper_constant_limit);
282 new_limit->InsertBefore(pre_header->end());
288 limit->
block() != pre_header &&
289 !limit->
block()->Dominates(pre_header)) {
290 HConstant* new_limit = HConstant::New(zone, context,
292 new_limit->InsertBefore(pre_header->end());
297 HBoundsCheck* hoisted_check = HBoundsCheck::New(
298 zone, context, limit, check->check()->length());
299 hoisted_check->InsertBefore(pre_header->end());
300 hoisted_check->set_allow_equality(
true);
301 counters()->bounds_checks_hoisted()->Increment();
305 bool additional_limit =
false;
307 for (
int i = 0; i < bb->phis()->length(); i++) {
308 HPhi* phi = bb->phis()->at(i);
309 phi->DetectInductionVariable();
312 additional_limit = InductionVariableData::ComputeInductionVariableLimit(
313 bb, at(bb)->additional_limit());
315 if (additional_limit) {
316 at(bb)->additional_limit()->updated_variable->
317 UpdateAdditionalLimit(at(bb)->additional_limit());
321 if (!i->IsBoundsCheck())
continue;
322 HBoundsCheck*
check = HBoundsCheck::cast(i);
323 InductionVariableData::BitwiseDecompositionResult decomposition;
324 InductionVariableData::DecomposeBitwise(check->index(), &decomposition);
325 if (!decomposition.base->IsPhi())
continue;
326 HPhi* phi = HPhi::cast(decomposition.base);
328 if (!phi->IsInductionVariable())
continue;
329 InductionVariableData* data = phi->induction_variable_data();
332 if (data->increment() <= 0)
continue;
333 if (!data->LowerLimitIsNonNegativeConstant())
continue;
336 if (check->length() == data->limit() ||
337 check->length() == data->additional_upper_limit()) {
338 counters()->bounds_checks_eliminated()->Increment();
339 check->set_skip_check();
343 if (!phi->IsLimitedInductionVariable())
continue;
345 int32_t limit = data->ComputeUpperLimit(decomposition.and_mask,
346 decomposition.or_mask);
347 phi->induction_variable_data()->AddCheck(check, limit);
350 for (
int i = 0; i < bb->dominated_blocks()->length(); i++) {
351 CollectInductionVariableData(bb->dominated_blocks()->at(i));
354 if (additional_limit) {
355 at(bb->block_id())->additional_limit()->updated_variable->
356 UpdateAdditionalLimit(at(bb->block_id())->additional_limit());
361 for (
int i = 0; i < bb->phis()->length(); i++) {
362 HPhi* phi = bb->phis()->at(i);
363 if (!phi->IsLimitedInductionVariable())
continue;
365 InductionVariableData* induction_data = phi->induction_variable_data();
366 InductionVariableData::ChecksRelatedToLength* current_length_group =
367 induction_data->checks();
368 while (current_length_group !=
NULL) {
369 current_length_group->CloseCurrentBlock();
370 InductionVariableData::InductionVariableCheck* current_base_check =
371 current_length_group->checks();
372 InitializeLoop(induction_data);
374 while (current_base_check !=
NULL) {
375 ProcessRelatedChecks(current_base_check, induction_data);
376 while (current_base_check !=
NULL &&
377 current_base_check->processed()) {
378 current_base_check = current_base_check->next();
382 current_length_group = current_length_group->next();
389 HBasicBlock* loop_header_;
394 void HBoundsCheckHoistingPhase::HoistRedundantBoundsChecks() {
395 InductionVariableBlocksTable table(
graph());
396 table.CollectInductionVariableData(
graph()->entry_block());
397 for (
int i = 0; i <
graph()->blocks()->length(); i++) {
398 table.EliminateRedundantBoundsChecks(
graph()->blocks()->at(i));
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
void set_block(HBasicBlock *block)
Element * at(HBasicBlock *block) const
HBasicBlock * block() const
void AddCheckAt(HBasicBlock *block)
Hoistability CheckHoistability()
InductionVariableBlocksTable(HGraph *graph)
HBasicBlock * NextDominatedBlock()
#define ASSERT(condition)
HBasicBlock * CurrentDominatedBlock()
Counters * counters() const
Representation representation() const
int32_t GetInteger32Constant()
void check(i::Vector< const uint8_t > string)
void CollectInductionVariableData(HBasicBlock *bb)
void InitializeLoop(InductionVariableData *data)
Element * at(int index) const
void EliminateRedundantBoundsChecks(HBasicBlock *bb)
InductionVariableLimitUpdate * additional_limit()
HBasicBlock * loop_header() const
void InitializeLoop(InductionVariableData *data)
void ResetCurrentDominatedBlock()
bool IsInteger32Constant()
void ProcessRelatedChecks(InductionVariableData::InductionVariableCheck *check, InductionVariableData *data)