pass_manager.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // Copyright (c) 2016 Google Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "source/opt/pass_manager.h"
  15. #include <iostream>
  16. #include <string>
  17. #include <vector>
  18. #include "source/opt/ir_context.h"
  19. #include "source/util/timer.h"
  20. #include "spirv-tools/libspirv.hpp"
  21. namespace spvtools {
  22. namespace opt {
  23. Pass::Status PassManager::Run(IRContext* context) {
  24. auto status = Pass::Status::SuccessWithoutChange;
  25. // If print_all_stream_ is not null, prints the disassembly of the module
  26. // to that stream, with the given preamble and optionally the pass name.
  27. auto print_disassembly = [&context, this](const char* preamble, Pass* pass) {
  28. if (print_all_stream_) {
  29. std::vector<uint32_t> binary;
  30. context->module()->ToBinary(&binary, false);
  31. SpirvTools t(target_env_);
  32. t.SetMessageConsumer(consumer());
  33. std::string disassembly;
  34. std::string pass_name = (pass ? pass->name() : "");
  35. if (!t.Disassemble(binary, &disassembly)) {
  36. std::string msg = "Disassembly failed before pass ";
  37. msg += pass_name + "\n";
  38. spv_position_t null_pos{0, 0, 0};
  39. consumer()(SPV_MSG_WARNING, "", null_pos, msg.c_str());
  40. return;
  41. }
  42. *print_all_stream_ << preamble << pass_name << "\n"
  43. << disassembly << std::endl;
  44. }
  45. };
  46. SPIRV_TIMER_DESCRIPTION(time_report_stream_, /* measure_mem_usage = */ true);
  47. for (auto& pass : passes_) {
  48. print_disassembly("; IR before pass ", pass.get());
  49. SPIRV_TIMER_SCOPED(time_report_stream_, (pass ? pass->name() : ""), true);
  50. const auto one_status = pass->Run(context);
  51. if (one_status == Pass::Status::Failure) return one_status;
  52. if (one_status == Pass::Status::SuccessWithChange) status = one_status;
  53. if (validate_after_all_) {
  54. spvtools::SpirvTools tools(target_env_);
  55. tools.SetMessageConsumer(consumer());
  56. std::vector<uint32_t> binary;
  57. context->module()->ToBinary(&binary, true);
  58. if (!tools.Validate(binary.data(), binary.size(), val_options_)) {
  59. std::string msg = "Validation failed after pass ";
  60. msg += pass->name();
  61. spv_position_t null_pos{0, 0, 0};
  62. consumer()(SPV_MSG_INTERNAL_ERROR, "", null_pos, msg.c_str());
  63. return Pass::Status::Failure;
  64. }
  65. }
  66. // Reset the pass to free any memory used by the pass.
  67. pass.reset(nullptr);
  68. }
  69. print_disassembly("; IR after last pass", nullptr);
  70. // Set the Id bound in the header in case a pass forgot to do so.
  71. //
  72. // TODO(dnovillo): This should be unnecessary and automatically maintained by
  73. // the IRContext.
  74. if (status == Pass::Status::SuccessWithChange) {
  75. context->module()->SetIdBound(context->module()->ComputeIdBound());
  76. }
  77. passes_.clear();
  78. return status;
  79. }
  80. } // namespace opt
  81. } // namespace spvtools