TODO: In asynchronous mode, return early if the query is cancelled or finished.
| 1428 | |
| 1429 | /// TODO: In asynchronous mode, return early if the query is cancelled or finished. |
| 1430 | Status LlvmCodeGen::OptimizeModule() { |
| 1431 | SCOPED_TIMER(optimization_timer_); |
| 1432 | |
| 1433 | llvm::LoopAnalysisManager LAM; |
| 1434 | llvm::FunctionAnalysisManager FAM; |
| 1435 | llvm::CGSCCAnalysisManager CGAM; |
| 1436 | llvm::ModuleAnalysisManager MAM; |
| 1437 | |
| 1438 | // This pass manager will construct optimizations passes that are "typical" for |
| 1439 | // c/c++ programs. We're relying on llvm to pick the best passes for us. |
| 1440 | // TODO: we can likely muck with this to get better compile speeds or write |
| 1441 | // our own passes. Our subexpression elimination optimization can be rolled into |
| 1442 | // a pass. |
| 1443 | llvm::PassBuilder pass_builder(execution_engine()->getTargetMachine()); |
| 1444 | pass_builder.registerModuleAnalyses(MAM); |
| 1445 | pass_builder.registerCGSCCAnalyses(CGAM); |
| 1446 | pass_builder.registerFunctionAnalyses(FAM); |
| 1447 | pass_builder.registerLoopAnalyses(LAM); |
| 1448 | pass_builder.crossRegisterProxies(LAM, FAM, CGAM, MAM); |
| 1449 | |
| 1450 | TCodeGenOptLevel::type opt_level = state_->query_options().codegen_opt_level; |
| 1451 | llvm::PassBuilder::OptimizationLevel opt; |
| 1452 | // GCC's -Werror=switch errors if a case is not covered. |
| 1453 | switch (opt_level) { |
| 1454 | case TCodeGenOptLevel::O0: |
| 1455 | // Default optimization pipeline requires O1 or greater, so for O0 we skip. |
| 1456 | return Status::OK(); |
| 1457 | case TCodeGenOptLevel::O1: |
| 1458 | opt = llvm::PassBuilder::OptimizationLevel::O1; |
| 1459 | break; |
| 1460 | case TCodeGenOptLevel::Os: |
| 1461 | opt = llvm::PassBuilder::OptimizationLevel::Os; |
| 1462 | break; |
| 1463 | case TCodeGenOptLevel::O2: |
| 1464 | opt = llvm::PassBuilder::OptimizationLevel::O2; |
| 1465 | break; |
| 1466 | case TCodeGenOptLevel::O3: |
| 1467 | opt = llvm::PassBuilder::OptimizationLevel::O3; |
| 1468 | break; |
| 1469 | } |
| 1470 | llvm::ModulePassManager pass_manager = pass_builder.buildPerModuleDefaultPipeline(opt); |
| 1471 | |
| 1472 | int64_t estimated_memory = ESTIMATED_OPTIMIZER_BYTES_PER_INST |
| 1473 | * num_instructions_->value(); |
| 1474 | if (!mem_tracker_->TryConsume(estimated_memory)) { |
| 1475 | const string& msg = Substitute( |
| 1476 | "Codegen failed to reserve '$0' bytes for optimization", estimated_memory); |
| 1477 | return mem_tracker_->MemLimitExceeded(NULL, msg, estimated_memory); |
| 1478 | } |
| 1479 | |
| 1480 | // Create and run module pass manager |
| 1481 | pass_manager.run(*module_, MAM); |
| 1482 | if (FLAGS_print_llvm_ir_instruction_count) { |
| 1483 | for (auto& entry : fns_to_jit_compile_) { |
| 1484 | InstructionCounter counter; |
| 1485 | llvm::Function* llvm_function = entry.second.first; |
| 1486 | const llvm::StringRef& llvm_function_name = entry.first; |
| 1487 | counter.visit(*llvm_function); |