src/share/vm/c1/c1_Compilation.cpp

Print this page
rev 4136 : 7153771: array bound check elimination for c1
Summary: when possible optimize out array bound checks, inserting predicates when needed.
Reviewed-by:


  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_CFGPrinter.hpp"
  27 #include "c1/c1_Compilation.hpp"
  28 #include "c1/c1_IR.hpp"
  29 #include "c1/c1_LIRAssembler.hpp"
  30 #include "c1/c1_LinearScan.hpp"
  31 #include "c1/c1_MacroAssembler.hpp"
  32 #include "c1/c1_ValueMap.hpp"
  33 #include "c1/c1_ValueStack.hpp"
  34 #include "code/debugInfoRec.hpp"
  35 #include "compiler/compileLog.hpp"

  36 
  37 
  38 typedef enum {
  39   _t_compile,
  40   _t_setup,
  41   _t_optimizeIR,
  42   _t_buildIR,



  43   _t_emit_lir,
  44   _t_linearScan,
  45   _t_lirGeneration,
  46   _t_lir_schedule,
  47   _t_codeemit,
  48   _t_codeinstall,
  49   max_phase_timers
  50 } TimerName;
  51 
  52 static const char * timer_name[] = {
  53   "compile",
  54   "setup",
  55   "optimizeIR",


  56   "buildIR",
  57   "emit_lir",
  58   "linearScan",
  59   "lirGeneration",
  60   "lir_schedule",
  61   "codeemit",
  62   "codeinstall"
  63 };
  64 
  65 static elapsedTimer timers[max_phase_timers];
  66 static int totalInstructionNodes = 0;
  67 
  68 class PhaseTraceTime: public TraceTime {
  69  private:
  70   JavaThread* _thread;
  71   CompileLog* _log;
  72 
  73  public:
  74   PhaseTraceTime(TimerName timer)
  75   : TraceTime("", &timers[timer], CITime || CITimeEach, Verbose), _log(NULL) {


 142     bailout("invalid parsing");
 143     return;
 144   }
 145 
 146 #ifndef PRODUCT
 147   if (PrintCFGToFile) {
 148     CFGPrinter::print_cfg(_hir, "After Generation of HIR", true, false);
 149   }
 150 #endif
 151 
 152 #ifndef PRODUCT
 153   if (PrintCFG || PrintCFG0) { tty->print_cr("CFG after parsing"); _hir->print(true); }
 154   if (PrintIR  || PrintIR0 ) { tty->print_cr("IR after parsing"); _hir->print(false); }
 155 #endif
 156 
 157   _hir->verify();
 158 
 159   if (UseC1Optimizations) {
 160     NEEDS_CLEANUP
 161     // optimization
 162     PhaseTraceTime timeit(_t_optimizeIR);
 163 
 164     _hir->optimize();
 165   }
 166 
 167   _hir->verify();
 168 
 169   _hir->split_critical_edges();
 170 
 171 #ifndef PRODUCT
 172   if (PrintCFG || PrintCFG1) { tty->print_cr("CFG after optimizations"); _hir->print(true); }
 173   if (PrintIR  || PrintIR1 ) { tty->print_cr("IR after optimizations"); _hir->print(false); }
 174 #endif
 175 
 176   _hir->verify();
 177 
 178   // compute block ordering for code generation
 179   // the control flow must not be changed from here on
 180   _hir->compute_code();
 181 
 182   if (UseGlobalValueNumbering) {
 183     ResourceMark rm;
 184     int instructions = Instruction::number_of_instructions();
 185     GlobalValueNumbering gvn(_hir);
 186     assert(instructions == Instruction::number_of_instructions(),
 187            "shouldn't have created an instructions");
 188   }
 189 




































 190   // compute use counts after global value numbering
 191   _hir->compute_use_counts();
 192 
 193 #ifndef PRODUCT
 194   if (PrintCFG || PrintCFG2) { tty->print_cr("CFG before code generation"); _hir->code()->print(true); }
 195   if (PrintIR  || PrintIR2 ) { tty->print_cr("IR before code generation"); _hir->code()->print(false, true); }
 196 #endif
 197 
 198   _hir->verify();
 199 }
 200 
 201 
 202 void Compilation::emit_lir() {
 203   CHECK_BAILOUT();
 204 
 205   LIRGenerator gen(this, method());
 206   {
 207     PhaseTraceTime timeit(_t_lirGeneration);
 208     hir()->iterate_linear_scan_order(&gen);
 209   }


 485 : _compiler(compiler)
 486 , _env(env)
 487 , _log(env->log())
 488 , _method(method)
 489 , _osr_bci(osr_bci)
 490 , _hir(NULL)
 491 , _max_spills(-1)
 492 , _frame_map(NULL)
 493 , _masm(NULL)
 494 , _has_exception_handlers(false)
 495 , _has_fpu_code(true)   // pessimistic assumption
 496 , _would_profile(false)
 497 , _has_unsafe_access(false)
 498 , _has_method_handle_invokes(false)
 499 , _bailout_msg(NULL)
 500 , _exception_info_list(NULL)
 501 , _allocator(NULL)
 502 , _next_id(0)
 503 , _next_block_id(0)
 504 , _code(buffer_blob)

 505 , _current_instruction(NULL)
 506 #ifndef PRODUCT
 507 , _last_instruction_printed(NULL)
 508 #endif // PRODUCT
 509 {
 510   PhaseTraceTime timeit(_t_compile);
 511   _arena = Thread::current()->resource_area();
 512   _env->set_compiler_data(this);
 513   _exception_info_list = new ExceptionInfoList();
 514   _implicit_exception_table.set_size(0);
 515   compile_method();
 516   if (bailed_out()) {
 517     _env->record_method_not_compilable(bailout_msg(), !TieredCompilation);
 518     if (is_profiling()) {
 519       // Compilation failed, create MDO, which would signal the interpreter
 520       // to start profiling on its own.
 521       _method->ensure_method_data();
 522     }
 523   } else if (is_profiling()) {
 524     ciMethodData *md = method->method_data_or_null();


 550 
 551 
 552 void Compilation::bailout(const char* msg) {
 553   assert(msg != NULL, "bailout message must exist");
 554   if (!bailed_out()) {
 555     // keep first bailout message
 556     if (PrintCompilation || PrintBailouts) tty->print_cr("compilation bailout: %s", msg);
 557     _bailout_msg = msg;
 558   }
 559 }
 560 
 561 
 562 void Compilation::print_timers() {
 563   // tty->print_cr("    Native methods         : %6.3f s, Average : %2.3f", CompileBroker::_t_native_compilation.seconds(), CompileBroker::_t_native_compilation.seconds() / CompileBroker::_total_native_compile_count);
 564   float total = timers[_t_setup].seconds() + timers[_t_buildIR].seconds() + timers[_t_emit_lir].seconds() + timers[_t_lir_schedule].seconds() + timers[_t_codeemit].seconds() + timers[_t_codeinstall].seconds();
 565 
 566 
 567   tty->print_cr("    Detailed C1 Timings");
 568   tty->print_cr("       Setup time:        %6.3f s (%4.1f%%)",    timers[_t_setup].seconds(),           (timers[_t_setup].seconds() / total) * 100.0);
 569   tty->print_cr("       Build IR:          %6.3f s (%4.1f%%)",    timers[_t_buildIR].seconds(),         (timers[_t_buildIR].seconds() / total) * 100.0);
 570   tty->print_cr("         Optimize:           %6.3f s (%4.1f%%)", timers[_t_optimizeIR].seconds(),      (timers[_t_optimizeIR].seconds() / total) * 100.0);


 571   tty->print_cr("       Emit LIR:          %6.3f s (%4.1f%%)",    timers[_t_emit_lir].seconds(),        (timers[_t_emit_lir].seconds() / total) * 100.0);
 572   tty->print_cr("         LIR Gen:          %6.3f s (%4.1f%%)",   timers[_t_lirGeneration].seconds(), (timers[_t_lirGeneration].seconds() / total) * 100.0);
 573   tty->print_cr("         Linear Scan:      %6.3f s (%4.1f%%)",   timers[_t_linearScan].seconds(),    (timers[_t_linearScan].seconds() / total) * 100.0);
 574   NOT_PRODUCT(LinearScan::print_timers(timers[_t_linearScan].seconds()));
 575   tty->print_cr("       LIR Schedule:      %6.3f s (%4.1f%%)",    timers[_t_lir_schedule].seconds(),  (timers[_t_lir_schedule].seconds() / total) * 100.0);
 576   tty->print_cr("       Code Emission:     %6.3f s (%4.1f%%)",    timers[_t_codeemit].seconds(),        (timers[_t_codeemit].seconds() / total) * 100.0);
 577   tty->print_cr("       Code Installation: %6.3f s (%4.1f%%)",    timers[_t_codeinstall].seconds(),     (timers[_t_codeinstall].seconds() / total) * 100.0);
 578   tty->print_cr("       Instruction Nodes: %6d nodes",    totalInstructionNodes);
 579 
 580   NOT_PRODUCT(LinearScan::print_statistics());
 581 }
 582 
 583 
 584 #ifndef PRODUCT
 585 void Compilation::compile_only_this_method() {
 586   ResourceMark rm;
 587   fileStream stream(fopen("c1_compile_only", "wt"));
 588   stream.print_cr("# c1 compile only directives");
 589   compile_only_this_scope(&stream, hir()->top_scope());
 590 }




  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_CFGPrinter.hpp"
  27 #include "c1/c1_Compilation.hpp"
  28 #include "c1/c1_IR.hpp"
  29 #include "c1/c1_LIRAssembler.hpp"
  30 #include "c1/c1_LinearScan.hpp"
  31 #include "c1/c1_MacroAssembler.hpp"
  32 #include "c1/c1_ValueMap.hpp"
  33 #include "c1/c1_ValueStack.hpp"
  34 #include "code/debugInfoRec.hpp"
  35 #include "compiler/compileLog.hpp"
  36 #include "c1/c1_RangeCheckElimination.hpp"
  37 
  38 
  39 typedef enum {
  40   _t_compile,
  41   _t_setup,

  42   _t_buildIR,
  43   _t_optimize_blocks,
  44   _t_optimize_null_checks,
  45   _t_rangeCheckElimination,
  46   _t_emit_lir,
  47   _t_linearScan,
  48   _t_lirGeneration,
  49   _t_lir_schedule,
  50   _t_codeemit,
  51   _t_codeinstall,
  52   max_phase_timers
  53 } TimerName;
  54 
  55 static const char * timer_name[] = {
  56   "compile",
  57   "setup",
  58   "optimize_blocks",
  59   "optimize_null_checks",
  60   "rangeCheckElimination",
  61   "buildIR",
  62   "emit_lir",
  63   "linearScan",
  64   "lirGeneration",
  65   "lir_schedule",
  66   "codeemit",
  67   "codeinstall"
  68 };
  69 
  70 static elapsedTimer timers[max_phase_timers];
  71 static int totalInstructionNodes = 0;
  72 
  73 class PhaseTraceTime: public TraceTime {
  74  private:
  75   JavaThread* _thread;
  76   CompileLog* _log;
  77 
  78  public:
  79   PhaseTraceTime(TimerName timer)
  80   : TraceTime("", &timers[timer], CITime || CITimeEach, Verbose), _log(NULL) {


 147     bailout("invalid parsing");
 148     return;
 149   }
 150 
 151 #ifndef PRODUCT
 152   if (PrintCFGToFile) {
 153     CFGPrinter::print_cfg(_hir, "After Generation of HIR", true, false);
 154   }
 155 #endif
 156 
 157 #ifndef PRODUCT
 158   if (PrintCFG || PrintCFG0) { tty->print_cr("CFG after parsing"); _hir->print(true); }
 159   if (PrintIR  || PrintIR0 ) { tty->print_cr("IR after parsing"); _hir->print(false); }
 160 #endif
 161 
 162   _hir->verify();
 163 
 164   if (UseC1Optimizations) {
 165     NEEDS_CLEANUP
 166     // optimization
 167     PhaseTraceTime timeit(_t_optimize_blocks);
 168 
 169     _hir->optimize_blocks();
 170   }
 171 
 172   _hir->verify();
 173 
 174   _hir->split_critical_edges();
 175 
 176 #ifndef PRODUCT
 177   if (PrintCFG || PrintCFG1) { tty->print_cr("CFG after optimizations"); _hir->print(true); }
 178   if (PrintIR  || PrintIR1 ) { tty->print_cr("IR after optimizations"); _hir->print(false); }
 179 #endif
 180 
 181   _hir->verify();
 182 
 183   // compute block ordering for code generation
 184   // the control flow must not be changed from here on
 185   _hir->compute_code();
 186 
 187   if (UseGlobalValueNumbering) {
 188     // No resource mark here! LoopInvariantCodeMotion can allocate ValueStack objects.
 189     int instructions = Instruction::number_of_instructions();
 190     GlobalValueNumbering gvn(_hir);
 191     assert(instructions == Instruction::number_of_instructions(),
 192            "shouldn't have created an instructions");
 193   }
 194 
 195   _hir->verify();
 196 
 197 #ifndef PRODUCT
 198 
 199   if (PrintCFGToFile) {
 200     CFGPrinter::print_cfg(_hir, "Before RangeCheckElimination", true, false);
 201   }
 202 
 203 #endif
 204 
 205   if (RangeCheckElimination) {
 206     if (_hir->osr_entry() == NULL) {
 207       PhaseTraceTime timeit(_t_rangeCheckElimination);
 208       RangeCheckElimination::eliminate(_hir);
 209     }
 210   }
 211 
 212 #ifndef PRODUCT
 213   if (PrintCFGToFile) {
 214     CFGPrinter::print_cfg(_hir, "After RangeCheckElimination", true, false);
 215   }
 216 #endif
 217 
 218   if (UseC1Optimizations) {
 219     // loop invariant code motion reorders instructions and range
 220     // check elimination adds new instructions so do null check
 221     // elimination after.
 222     NEEDS_CLEANUP
 223     // optimization
 224     PhaseTraceTime timeit(_t_optimize_null_checks);
 225 
 226     _hir->eliminate_null_checks();
 227   }
 228 
 229   _hir->verify();
 230 
 231   // compute use counts after global value numbering
 232   _hir->compute_use_counts();
 233 
 234 #ifndef PRODUCT
 235   if (PrintCFG || PrintCFG2) { tty->print_cr("CFG before code generation"); _hir->code()->print(true); }
 236   if (PrintIR  || PrintIR2 ) { tty->print_cr("IR before code generation"); _hir->code()->print(false, true); }
 237 #endif
 238 
 239   _hir->verify();
 240 }
 241 
 242 
 243 void Compilation::emit_lir() {
 244   CHECK_BAILOUT();
 245 
 246   LIRGenerator gen(this, method());
 247   {
 248     PhaseTraceTime timeit(_t_lirGeneration);
 249     hir()->iterate_linear_scan_order(&gen);
 250   }


 526 : _compiler(compiler)
 527 , _env(env)
 528 , _log(env->log())
 529 , _method(method)
 530 , _osr_bci(osr_bci)
 531 , _hir(NULL)
 532 , _max_spills(-1)
 533 , _frame_map(NULL)
 534 , _masm(NULL)
 535 , _has_exception_handlers(false)
 536 , _has_fpu_code(true)   // pessimistic assumption
 537 , _would_profile(false)
 538 , _has_unsafe_access(false)
 539 , _has_method_handle_invokes(false)
 540 , _bailout_msg(NULL)
 541 , _exception_info_list(NULL)
 542 , _allocator(NULL)
 543 , _next_id(0)
 544 , _next_block_id(0)
 545 , _code(buffer_blob)
 546 , _has_access_indexed(false)
 547 , _current_instruction(NULL)
 548 #ifndef PRODUCT
 549 , _last_instruction_printed(NULL)
 550 #endif // PRODUCT
 551 {
 552   PhaseTraceTime timeit(_t_compile);
 553   _arena = Thread::current()->resource_area();
 554   _env->set_compiler_data(this);
 555   _exception_info_list = new ExceptionInfoList();
 556   _implicit_exception_table.set_size(0);
 557   compile_method();
 558   if (bailed_out()) {
 559     _env->record_method_not_compilable(bailout_msg(), !TieredCompilation);
 560     if (is_profiling()) {
 561       // Compilation failed, create MDO, which would signal the interpreter
 562       // to start profiling on its own.
 563       _method->ensure_method_data();
 564     }
 565   } else if (is_profiling()) {
 566     ciMethodData *md = method->method_data_or_null();


 592 
 593 
 594 void Compilation::bailout(const char* msg) {
 595   assert(msg != NULL, "bailout message must exist");
 596   if (!bailed_out()) {
 597     // keep first bailout message
 598     if (PrintCompilation || PrintBailouts) tty->print_cr("compilation bailout: %s", msg);
 599     _bailout_msg = msg;
 600   }
 601 }
 602 
 603 
 604 void Compilation::print_timers() {
 605   // tty->print_cr("    Native methods         : %6.3f s, Average : %2.3f", CompileBroker::_t_native_compilation.seconds(), CompileBroker::_t_native_compilation.seconds() / CompileBroker::_total_native_compile_count);
 606   float total = timers[_t_setup].seconds() + timers[_t_buildIR].seconds() + timers[_t_emit_lir].seconds() + timers[_t_lir_schedule].seconds() + timers[_t_codeemit].seconds() + timers[_t_codeinstall].seconds();
 607 
 608 
 609   tty->print_cr("    Detailed C1 Timings");
 610   tty->print_cr("       Setup time:        %6.3f s (%4.1f%%)",    timers[_t_setup].seconds(),           (timers[_t_setup].seconds() / total) * 100.0);
 611   tty->print_cr("       Build IR:          %6.3f s (%4.1f%%)",    timers[_t_buildIR].seconds(),         (timers[_t_buildIR].seconds() / total) * 100.0);
 612   float t_optimizeIR = timers[_t_optimize_blocks].seconds() + timers[_t_optimize_null_checks].seconds();
 613   tty->print_cr("         Optimize:           %6.3f s (%4.1f%%)", t_optimizeIR,                         (t_optimizeIR / total) * 100.0);
 614   tty->print_cr("         RCE:                %6.3f s (%4.1f%%)", timers[_t_rangeCheckElimination].seconds(),      (timers[_t_rangeCheckElimination].seconds() / total) * 100.0);
 615   tty->print_cr("       Emit LIR:          %6.3f s (%4.1f%%)",    timers[_t_emit_lir].seconds(),        (timers[_t_emit_lir].seconds() / total) * 100.0);
 616   tty->print_cr("         LIR Gen:          %6.3f s (%4.1f%%)",   timers[_t_lirGeneration].seconds(), (timers[_t_lirGeneration].seconds() / total) * 100.0);
 617   tty->print_cr("         Linear Scan:      %6.3f s (%4.1f%%)",   timers[_t_linearScan].seconds(),    (timers[_t_linearScan].seconds() / total) * 100.0);
 618   NOT_PRODUCT(LinearScan::print_timers(timers[_t_linearScan].seconds()));
 619   tty->print_cr("       LIR Schedule:      %6.3f s (%4.1f%%)",    timers[_t_lir_schedule].seconds(),  (timers[_t_lir_schedule].seconds() / total) * 100.0);
 620   tty->print_cr("       Code Emission:     %6.3f s (%4.1f%%)",    timers[_t_codeemit].seconds(),        (timers[_t_codeemit].seconds() / total) * 100.0);
 621   tty->print_cr("       Code Installation: %6.3f s (%4.1f%%)",    timers[_t_codeinstall].seconds(),     (timers[_t_codeinstall].seconds() / total) * 100.0);
 622   tty->print_cr("       Instruction Nodes: %6d nodes",    totalInstructionNodes);
 623 
 624   NOT_PRODUCT(LinearScan::print_statistics());
 625 }
 626 
 627 
 628 #ifndef PRODUCT
 629 void Compilation::compile_only_this_method() {
 630   ResourceMark rm;
 631   fileStream stream(fopen("c1_compile_only", "wt"));
 632   stream.print_cr("# c1 compile only directives");
 633   compile_only_this_scope(&stream, hir()->top_scope());
 634 }