pass_manager.cpp 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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(SPV_ENV_UNIVERSAL_1_2);
  32. std::string disassembly;
  33. t.Disassemble(binary, &disassembly, 0);
  34. *print_all_stream_ << preamble << (pass ? pass->name() : "") << "\n"
  35. << disassembly << std::endl;
  36. }
  37. };
  38. SPIRV_TIMER_DESCRIPTION(time_report_stream_, /* measure_mem_usage = */ true);
  39. for (auto& pass : passes_) {
  40. print_disassembly("; IR before pass ", pass.get());
  41. SPIRV_TIMER_SCOPED(time_report_stream_, (pass ? pass->name() : ""), true);
  42. const auto one_status = pass->Run(context);
  43. if (one_status == Pass::Status::Failure) return one_status;
  44. if (one_status == Pass::Status::SuccessWithChange) status = one_status;
  45. if (validate_after_all_) {
  46. spvtools::SpirvTools tools(target_env_);
  47. tools.SetMessageConsumer(consumer());
  48. std::vector<uint32_t> binary;
  49. context->module()->ToBinary(&binary, true);
  50. if (!tools.Validate(binary.data(), binary.size(), val_options_)) {
  51. std::string msg = "Validation failed after pass ";
  52. msg += pass->name();
  53. spv_position_t null_pos{0, 0, 0};
  54. consumer()(SPV_MSG_INTERNAL_ERROR, "", null_pos, msg.c_str());
  55. return Pass::Status::Failure;
  56. }
  57. }
  58. // Reset the pass to free any memory used by the pass.
  59. pass.reset(nullptr);
  60. }
  61. print_disassembly("; IR after last pass", nullptr);
  62. // Set the Id bound in the header in case a pass forgot to do so.
  63. //
  64. // TODO(dnovillo): This should be unnecessary and automatically maintained by
  65. // the IRContext.
  66. if (status == Pass::Status::SuccessWithChange) {
  67. context->module()->SetIdBound(context->module()->ComputeIdBound());
  68. }
  69. passes_.clear();
  70. return status;
  71. }
  72. } // namespace opt
  73. } // namespace spvtools