1 // Copyright (c) 2020 André Perez Maselco 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 15 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_BIT_INSTRUCTION_SYNONYM_H_ 16 #define SOURCE_FUZZ_TRANSFORMATION_ADD_BIT_INSTRUCTION_SYNONYM_H_ 17 18 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h" 19 #include "source/fuzz/transformation.h" 20 #include "source/fuzz/transformation_context.h" 21 #include "source/opt/ir_context.h" 22 23 namespace spvtools { 24 namespace fuzz { 25 26 // clang-format off 27 // SPIR-V code to help understand the transformation. 28 // 29 // ---------------------------------------------------------------------------------------------------------------- 30 // | Reference shader | Variant shader | 31 // ---------------------------------------------------------------------------------------------------------------- 32 // | OpCapability Shader | OpCapability Shader | 33 // | OpCapability Int8 | OpCapability Int8 | 34 // | %1 = OpExtInstImport "GLSL.std.450" | %1 = OpExtInstImport "GLSL.std.450" | 35 // | OpMemoryModel Logical GLSL450 | OpMemoryModel Logical GLSL450 | 36 // | OpEntryPoint Vertex %7 "main" | OpEntryPoint Vertex %7 "main" | 37 // | | | 38 // | ; Types | ; Types | 39 // | %2 = OpTypeInt 8 0 | %2 = OpTypeInt 8 0 | 40 // | %3 = OpTypeVoid | %3 = OpTypeVoid | 41 // | %4 = OpTypeFunction %3 | %4 = OpTypeFunction %3 | 42 // | | | 43 // | ; Constants | ; Constants | 44 // | %5 = OpConstant %2 0 | %5 = OpConstant %2 0 | 45 // | %6 = OpConstant %2 1 | %6 = OpConstant %2 1 | 46 // | | %10 = OpConstant %2 2 | 47 // | ; main function | %11 = OpConstant %2 3 | 48 // | %7 = OpFunction %3 None %4 | %12 = OpConstant %2 4 | 49 // | %8 = OpLabel | %13 = OpConstant %2 5 | 50 // | %9 = OpBitwiseOr %2 %5 %6 ; bit instruction | %14 = OpConstant %2 6 | 51 // | OpReturn | %15 = OpConstant %2 7 | 52 // | OpFunctionEnd | | 53 // | | ; main function | 54 // | | %7 = OpFunction %3 None %4 | 55 // | | %8 = OpLabel | 56 // | | | 57 // | | %16 = OpBitFieldUExtract %2 %5 %5 %6 ; extracts bit 0 from %5 | 58 // | | %17 = OpBitFieldUExtract %2 %6 %5 %6 ; extracts bit 0 from %6 | 59 // | | %18 = OpBitwiseOr %2 %16 %17 | 60 // | | | 61 // | | %19 = OpBitFieldUExtract %2 %5 %6 %6 ; extracts bit 1 from %5 | 62 // | | %20 = OpBitFieldUExtract %2 %6 %6 %6 ; extracts bit 1 from %6 | 63 // | | %21 = OpBitwiseOr %2 %19 %20 | 64 // | | | 65 // | | %22 = OpBitFieldUExtract %2 %5 %10 %6 ; extracts bit 2 from %5 | 66 // | | %23 = OpBitFieldUExtract %2 %6 %10 %6 ; extracts bit 2 from %6 | 67 // | | %24 = OpBitwiseOr %2 %22 %23 | 68 // | | | 69 // | | %25 = OpBitFieldUExtract %2 %5 %11 %6 ; extracts bit 3 from %5 | 70 // | | %26 = OpBitFieldUExtract %2 %6 %11 %6 ; extracts bit 3 from %6 | 71 // | | %27 = OpBitwiseOr %2 %25 %26 | 72 // | | | 73 // | | %28 = OpBitFieldUExtract %2 %5 %12 %6 ; extracts bit 4 from %5 | 74 // | | %29 = OpBitFieldUExtract %2 %6 %12 %6 ; extracts bit 4 from %6 | 75 // | | %30 = OpBitwiseOr %2 %28 %29 | 76 // | | | 77 // | | %31 = OpBitFieldUExtract %2 %5 %13 %6 ; extracts bit 5 from %5 | 78 // | | %32 = OpBitFieldUExtract %2 %6 %13 %6 ; extracts bit 5 from %6 | 79 // | | %33 = OpBitwiseOr %2 %31 %32 | 80 // | | | 81 // | | %34 = OpBitFieldUExtract %2 %5 %14 %6 ; extracts bit 6 from %5 | 82 // | | %35 = OpBitFieldUExtract %2 %6 %14 %6 ; extracts bit 6 from %6 | 83 // | | %36 = OpBitwiseOr %2 %34 %35 | 84 // | | | 85 // | | %37 = OpBitFieldUExtract %2 %5 %15 %6 ; extracts bit 7 from %5 | 86 // | | %38 = OpBitFieldUExtract %2 %6 %15 %6 ; extracts bit 7 from %6 | 87 // | | %39 = OpBitwiseOr %2 %37 %38 | 88 // | | | 89 // | | %40 = OpBitFieldInsert %2 %18 %21 %6 %6 ; inserts bit 1 | 90 // | | %41 = OpBitFieldInsert %2 %40 %24 %10 %6 ; inserts bit 2 | 91 // | | %42 = OpBitFieldInsert %2 %41 %27 %11 %6 ; inserts bit 3 | 92 // | | %43 = OpBitFieldInsert %2 %42 %30 %12 %6 ; inserts bit 4 | 93 // | | %44 = OpBitFieldInsert %2 %43 %33 %13 %6 ; inserts bit 5 | 94 // | | %45 = OpBitFieldInsert %2 %44 %36 %14 %6 ; inserts bit 6 | 95 // | | %46 = OpBitFieldInsert %2 %45 %39 %15 %6 ; inserts bit 7 | 96 // | | %9 = OpBitwiseOr %2 %5 %6 ; bit instruction | 97 // | | OpReturn | 98 // | | OpFunctionEnd | 99 // ---------------------------------------------------------------------------------------------------------------- 100 // 101 // After the transformation, %9 and %46 will be synonymous. 102 // clang-format on 103 class TransformationAddBitInstructionSynonym : public Transformation { 104 public: 105 explicit TransformationAddBitInstructionSynonym( 106 const protobufs::TransformationAddBitInstructionSynonym& message); 107 108 TransformationAddBitInstructionSynonym( 109 const uint32_t instruction_result_id, 110 const std::vector<uint32_t>& fresh_ids); 111 112 // - |message_.instruction_result_id| must be a bit instruction. 113 // - |message_.fresh_ids| must be fresh ids needed to apply the 114 // transformation. 115 bool IsApplicable( 116 opt::IRContext* ir_context, 117 const TransformationContext& transformation_context) const override; 118 119 // Adds a bit instruction synonym. 120 void Apply(opt::IRContext* ir_context, 121 TransformationContext* transformation_context) const override; 122 123 std::unordered_set<uint32_t> GetFreshIds() const override; 124 125 protobufs::Transformation ToMessage() const override; 126 127 // Returns the number of fresh ids required to apply the transformation. 128 static uint32_t GetRequiredFreshIdCount(opt::IRContext* ir_context, 129 opt::Instruction* bit_instruction); 130 131 private: 132 protobufs::TransformationAddBitInstructionSynonym message_; 133 134 // Adds OpBitwise* or OpNot synonym. 135 void AddOpBitwiseOrOpNotSynonym(opt::IRContext* ir_context, 136 TransformationContext* transformation_context, 137 opt::Instruction* bitwise_instruction) const; 138 }; 139 140 } // namespace fuzz 141 } // namespace spvtools 142 143 #endif // SOURCE_FUZZ_TRANSFORMATION_ADD_BIT_INSTRUCTION_SYNONYM_H_ 144