1 /*
2 * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "c1/c1_Canonicalizer.hpp"
27 #include "c1/c1_Optimizer.hpp"
28 #include "c1/c1_ValueMap.hpp"
29 #include "c1/c1_ValueSet.hpp"
30 #include "c1/c1_ValueStack.hpp"
31 #include "utilities/bitMap.inline.hpp"
32 #include "compiler/compileLog.hpp"
33
34 define_array(ValueSetArray, ValueSet*);
35 define_stack(ValueSetList, ValueSetArray);
36
37
38 Optimizer::Optimizer(IR* ir) {
39 assert(ir->is_valid(), "IR must be valid");
40 _ir = ir;
41 }
42
43 class CE_Eliminator: public BlockClosure {
44 private:
45 IR* _hir;
46 int _cee_count; // the number of CEs successfully eliminated
47 int _ifop_count; // the number of IfOps successfully simplified
48 int _has_substitution;
49
50 public:
51 CE_Eliminator(IR* hir) : _cee_count(0), _ifop_count(0), _hir(hir) {
52 _has_substitution = false;
53 _hir->iterate_preorder(this);
54 if (_has_substitution) {
55 // substituted some ifops/phis, so resolve the substitution
56 SubstitutionResolver sr(_hir);
566 assert(_visitable_instructions != NULL, "check");
567 _visitable_instructions->clear();
568 }
569
570 ValueSet* _set; // current state, propagated to subsequent BlockBegins
571 ValueSetList _block_states; // BlockBegin null-check states for all processed blocks
572 NullCheckVisitor _visitor;
573 NullCheck* _last_explicit_null_check;
574
575 bool set_contains(Value x) { assert(_set != NULL, "check"); return _set->contains(x); }
576 void set_put (Value x) { assert(_set != NULL, "check"); _set->put(x); }
577 void set_remove (Value x) { assert(_set != NULL, "check"); _set->remove(x); }
578
579 BlockList* work_list() { return _work_list; }
580
581 void iterate_all();
582 void iterate_one(BlockBegin* block);
583
584 ValueSet* state() { return _set; }
585 void set_state_from (ValueSet* state) { _set->set_from(state); }
586 ValueSet* state_for (BlockBegin* block) { return _block_states[block->block_id()]; }
587 void set_state_for (BlockBegin* block, ValueSet* stack) { _block_states[block->block_id()] = stack; }
588 // Returns true if caused a change in the block's state.
589 bool merge_state_for(BlockBegin* block,
590 ValueSet* incoming_state);
591
592 public:
593 // constructor
594 NullCheckEliminator(Optimizer* opt)
595 : _opt(opt)
596 , _set(new ValueSet())
597 , _last_explicit_null_check(NULL)
598 , _block_states(BlockBegin::number_of_blocks(), NULL)
599 , _work_list(new BlockList()) {
600 _visitable_instructions = new ValueSet();
601 _visitor.set_eliminator(this);
602 CompileLog* log = _opt->ir()->compilation()->log();
603 if (log != NULL)
604 log->set_context("optimize name='null_check_elimination'");
605 }
606
607 ~NullCheckEliminator() {
608 CompileLog* log = _opt->ir()->compilation()->log();
609 if (log != NULL)
610 log->clear_context(); // skip marker if nothing was printed
611 }
612
613 Optimizer* opt() { return _opt; }
614 IR* ir () { return opt()->ir(); }
615
616 // Process a graph
617 void iterate(BlockBegin* root);
618
1147
1148 void Optimizer::eliminate_null_checks() {
1149 ResourceMark rm;
1150
1151 NullCheckEliminator nce(this);
1152
1153 if (PrintNullCheckElimination) {
1154 tty->print_cr("Starting null check elimination for method %s::%s%s",
1155 ir()->method()->holder()->name()->as_utf8(),
1156 ir()->method()->name()->as_utf8(),
1157 ir()->method()->signature()->as_symbol()->as_utf8());
1158 }
1159
1160 // Apply to graph
1161 nce.iterate(ir()->start());
1162
1163 // walk over the graph looking for exception
1164 // handlers and iterate over them as well
1165 int nblocks = BlockBegin::number_of_blocks();
1166 BlockList blocks(nblocks);
1167 boolArray visited_block(nblocks, false);
1168
1169 blocks.push(ir()->start());
1170 visited_block[ir()->start()->block_id()] = true;
1171 for (int i = 0; i < blocks.length(); i++) {
1172 BlockBegin* b = blocks[i];
1173 // exception handlers need to be treated as additional roots
1174 for (int e = b->number_of_exception_handlers(); e-- > 0; ) {
1175 BlockBegin* excp = b->exception_handler_at(e);
1176 int id = excp->block_id();
1177 if (!visited_block[id]) {
1178 blocks.push(excp);
1179 visited_block[id] = true;
1180 nce.iterate(excp);
1181 }
1182 }
1183 // traverse successors
1184 BlockEnd *end = b->end();
1185 for (int s = end->number_of_sux(); s-- > 0; ) {
1186 BlockBegin* next = end->sux_at(s);
1187 int id = next->block_id();
1188 if (!visited_block[id]) {
1189 blocks.push(next);
1190 visited_block[id] = true;
1191 }
1192 }
1193 }
1194
1195
1196 if (PrintNullCheckElimination) {
1197 tty->print_cr("Done with null check elimination for method %s::%s%s",
1198 ir()->method()->holder()->name()->as_utf8(),
1199 ir()->method()->name()->as_utf8(),
1200 ir()->method()->signature()->as_symbol()->as_utf8());
1201 }
1202 }
|
1 /*
2 * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "c1/c1_Canonicalizer.hpp"
27 #include "c1/c1_Optimizer.hpp"
28 #include "c1/c1_ValueMap.hpp"
29 #include "c1/c1_ValueSet.hpp"
30 #include "c1/c1_ValueStack.hpp"
31 #include "utilities/bitMap.inline.hpp"
32 #include "compiler/compileLog.hpp"
33
34 typedef GrowableArray<ValueSet*> ValueSetList;
35
36 Optimizer::Optimizer(IR* ir) {
37 assert(ir->is_valid(), "IR must be valid");
38 _ir = ir;
39 }
40
41 class CE_Eliminator: public BlockClosure {
42 private:
43 IR* _hir;
44 int _cee_count; // the number of CEs successfully eliminated
45 int _ifop_count; // the number of IfOps successfully simplified
46 int _has_substitution;
47
48 public:
49 CE_Eliminator(IR* hir) : _cee_count(0), _ifop_count(0), _hir(hir) {
50 _has_substitution = false;
51 _hir->iterate_preorder(this);
52 if (_has_substitution) {
53 // substituted some ifops/phis, so resolve the substitution
54 SubstitutionResolver sr(_hir);
564 assert(_visitable_instructions != NULL, "check");
565 _visitable_instructions->clear();
566 }
567
568 ValueSet* _set; // current state, propagated to subsequent BlockBegins
569 ValueSetList _block_states; // BlockBegin null-check states for all processed blocks
570 NullCheckVisitor _visitor;
571 NullCheck* _last_explicit_null_check;
572
573 bool set_contains(Value x) { assert(_set != NULL, "check"); return _set->contains(x); }
574 void set_put (Value x) { assert(_set != NULL, "check"); _set->put(x); }
575 void set_remove (Value x) { assert(_set != NULL, "check"); _set->remove(x); }
576
577 BlockList* work_list() { return _work_list; }
578
579 void iterate_all();
580 void iterate_one(BlockBegin* block);
581
582 ValueSet* state() { return _set; }
583 void set_state_from (ValueSet* state) { _set->set_from(state); }
584 ValueSet* state_for (BlockBegin* block) { return _block_states.at(block->block_id()); }
585 void set_state_for (BlockBegin* block, ValueSet* stack) { _block_states.at_put(block->block_id(), stack); }
586 // Returns true if caused a change in the block's state.
587 bool merge_state_for(BlockBegin* block,
588 ValueSet* incoming_state);
589
590 public:
591 // constructor
592 NullCheckEliminator(Optimizer* opt)
593 : _opt(opt)
594 , _set(new ValueSet())
595 , _last_explicit_null_check(NULL)
596 , _block_states(BlockBegin::number_of_blocks(), BlockBegin::number_of_blocks(), NULL)
597 , _work_list(new BlockList()) {
598 _visitable_instructions = new ValueSet();
599 _visitor.set_eliminator(this);
600 CompileLog* log = _opt->ir()->compilation()->log();
601 if (log != NULL)
602 log->set_context("optimize name='null_check_elimination'");
603 }
604
605 ~NullCheckEliminator() {
606 CompileLog* log = _opt->ir()->compilation()->log();
607 if (log != NULL)
608 log->clear_context(); // skip marker if nothing was printed
609 }
610
611 Optimizer* opt() { return _opt; }
612 IR* ir () { return opt()->ir(); }
613
614 // Process a graph
615 void iterate(BlockBegin* root);
616
1145
1146 void Optimizer::eliminate_null_checks() {
1147 ResourceMark rm;
1148
1149 NullCheckEliminator nce(this);
1150
1151 if (PrintNullCheckElimination) {
1152 tty->print_cr("Starting null check elimination for method %s::%s%s",
1153 ir()->method()->holder()->name()->as_utf8(),
1154 ir()->method()->name()->as_utf8(),
1155 ir()->method()->signature()->as_symbol()->as_utf8());
1156 }
1157
1158 // Apply to graph
1159 nce.iterate(ir()->start());
1160
1161 // walk over the graph looking for exception
1162 // handlers and iterate over them as well
1163 int nblocks = BlockBegin::number_of_blocks();
1164 BlockList blocks(nblocks);
1165 boolArray visited_block(nblocks, nblocks, false);
1166
1167 blocks.push(ir()->start());
1168 visited_block.at_put(ir()->start()->block_id(), true);
1169 for (int i = 0; i < blocks.length(); i++) {
1170 BlockBegin* b = blocks.at(i);
1171 // exception handlers need to be treated as additional roots
1172 for (int e = b->number_of_exception_handlers(); e-- > 0; ) {
1173 BlockBegin* excp = b->exception_handler_at(e);
1174 int id = excp->block_id();
1175 if (!visited_block.at(id)) {
1176 blocks.push(excp);
1177 visited_block.at_put(id, true);
1178 nce.iterate(excp);
1179 }
1180 }
1181 // traverse successors
1182 BlockEnd *end = b->end();
1183 for (int s = end->number_of_sux(); s-- > 0; ) {
1184 BlockBegin* next = end->sux_at(s);
1185 int id = next->block_id();
1186 if (!visited_block.at(id)) {
1187 blocks.push(next);
1188 visited_block.at_put(id, true);
1189 }
1190 }
1191 }
1192
1193
1194 if (PrintNullCheckElimination) {
1195 tty->print_cr("Done with null check elimination for method %s::%s%s",
1196 ir()->method()->holder()->name()->as_utf8(),
1197 ir()->method()->name()->as_utf8(),
1198 ir()->method()->signature()->as_symbol()->as_utf8());
1199 }
1200 }
|