fuzzer_pass_interchange_zero_like_constants.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Copyright (c) 2020 Stefano Milizia
  2. // Copyright (c) 2020 Google LLC
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #include "source/fuzz/fuzzer_pass_interchange_zero_like_constants.h"
  16. #include "source/fuzz/fuzzer_util.h"
  17. #include "source/fuzz/id_use_descriptor.h"
  18. #include "source/fuzz/transformation_record_synonymous_constants.h"
  19. #include "source/fuzz/transformation_replace_id_with_synonym.h"
  20. namespace spvtools {
  21. namespace fuzz {
  22. FuzzerPassInterchangeZeroLikeConstants::FuzzerPassInterchangeZeroLikeConstants(
  23. opt::IRContext* ir_context, TransformationContext* transformation_context,
  24. FuzzerContext* fuzzer_context,
  25. protobufs::TransformationSequence* transformations,
  26. bool ignore_inapplicable_transformations)
  27. : FuzzerPass(ir_context, transformation_context, fuzzer_context,
  28. transformations, ignore_inapplicable_transformations) {}
  29. uint32_t FuzzerPassInterchangeZeroLikeConstants::FindOrCreateToggledConstant(
  30. opt::Instruction* declaration) {
  31. // |declaration| must not be a specialization constant because we do not know
  32. // the value of specialization constants.
  33. if (opt::IsSpecConstantInst(declaration->opcode())) {
  34. return 0;
  35. }
  36. auto constant = GetIRContext()->get_constant_mgr()->FindDeclaredConstant(
  37. declaration->result_id());
  38. // This pass only toggles zero-like constants
  39. if (!constant->IsZero()) {
  40. return 0;
  41. }
  42. if (constant->AsScalarConstant()) {
  43. return FindOrCreateNullConstant(declaration->type_id());
  44. } else if (constant->AsNullConstant()) {
  45. // Add declaration of equivalent scalar constant
  46. auto kind = constant->type()->kind();
  47. if (kind == opt::analysis::Type::kBool ||
  48. kind == opt::analysis::Type::kInteger ||
  49. kind == opt::analysis::Type::kFloat) {
  50. return FindOrCreateZeroConstant(declaration->type_id(), false);
  51. }
  52. }
  53. return 0;
  54. }
  55. void FuzzerPassInterchangeZeroLikeConstants::Apply() {
  56. // Make vector keeping track of all the uses we want to replace.
  57. // This is a vector of pairs, where the first element is an id use descriptor
  58. // identifying the use of a constant id and the second is the id that should
  59. // be used to replace it.
  60. std::vector<std::pair<protobufs::IdUseDescriptor, uint32_t>> uses_to_replace;
  61. for (auto constant : GetIRContext()->GetConstants()) {
  62. uint32_t constant_id = constant->result_id();
  63. if (GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
  64. constant_id)) {
  65. continue;
  66. }
  67. uint32_t toggled_id = FindOrCreateToggledConstant(constant);
  68. if (!toggled_id) {
  69. // Not a zero-like constant
  70. continue;
  71. }
  72. assert(!GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
  73. toggled_id) &&
  74. "FindOrCreateToggledConstant can't produce an irrelevant id");
  75. // Record synonymous constants
  76. ApplyTransformation(
  77. TransformationRecordSynonymousConstants(constant_id, toggled_id));
  78. // Find all the uses of the constant and, for each, probabilistically
  79. // decide whether to replace it.
  80. GetIRContext()->get_def_use_mgr()->ForEachUse(
  81. constant_id,
  82. [this, toggled_id, &uses_to_replace](opt::Instruction* use_inst,
  83. uint32_t use_index) -> void {
  84. if (GetFuzzerContext()->ChoosePercentage(
  85. GetFuzzerContext()
  86. ->GetChanceOfInterchangingZeroLikeConstants())) {
  87. MaybeAddUseToReplace(use_inst, use_index, toggled_id,
  88. &uses_to_replace);
  89. }
  90. });
  91. }
  92. // Replace the ids if it is allowed.
  93. for (auto use_to_replace : uses_to_replace) {
  94. MaybeApplyTransformation(TransformationReplaceIdWithSynonym(
  95. use_to_replace.first, use_to_replace.second));
  96. }
  97. }
  98. } // namespace fuzz
  99. } // namespace spvtools