1fd4e5da5Sopenharmony_ci// Copyright (c) 2019 Google LLC 2fd4e5da5Sopenharmony_ci// 3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License. 5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at 6fd4e5da5Sopenharmony_ci// 7fd4e5da5Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8fd4e5da5Sopenharmony_ci// 9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and 13fd4e5da5Sopenharmony_ci// limitations under the License. 14fd4e5da5Sopenharmony_ci 15fd4e5da5Sopenharmony_ci#ifndef SOURCE_OPT_GRAPHICS_ROBUST_ACCESS_PASS_H_ 16fd4e5da5Sopenharmony_ci#define SOURCE_OPT_GRAPHICS_ROBUST_ACCESS_PASS_H_ 17fd4e5da5Sopenharmony_ci 18fd4e5da5Sopenharmony_ci#include <map> 19fd4e5da5Sopenharmony_ci#include <unordered_map> 20fd4e5da5Sopenharmony_ci 21fd4e5da5Sopenharmony_ci#include "constants.h" 22fd4e5da5Sopenharmony_ci#include "def_use_manager.h" 23fd4e5da5Sopenharmony_ci#include "instruction.h" 24fd4e5da5Sopenharmony_ci#include "module.h" 25fd4e5da5Sopenharmony_ci#include "pass.h" 26fd4e5da5Sopenharmony_ci#include "source/diagnostic.h" 27fd4e5da5Sopenharmony_ci#include "type_manager.h" 28fd4e5da5Sopenharmony_ci 29fd4e5da5Sopenharmony_cinamespace spvtools { 30fd4e5da5Sopenharmony_cinamespace opt { 31fd4e5da5Sopenharmony_ci 32fd4e5da5Sopenharmony_ci// See optimizer.hpp for documentation. 33fd4e5da5Sopenharmony_ciclass GraphicsRobustAccessPass : public Pass { 34fd4e5da5Sopenharmony_ci public: 35fd4e5da5Sopenharmony_ci GraphicsRobustAccessPass(); 36fd4e5da5Sopenharmony_ci const char* name() const override { return "graphics-robust-access"; } 37fd4e5da5Sopenharmony_ci Status Process() override; 38fd4e5da5Sopenharmony_ci 39fd4e5da5Sopenharmony_ci IRContext::Analysis GetPreservedAnalyses() override { 40fd4e5da5Sopenharmony_ci return IRContext::kAnalysisDefUse | 41fd4e5da5Sopenharmony_ci IRContext::kAnalysisInstrToBlockMapping | 42fd4e5da5Sopenharmony_ci IRContext::kAnalysisConstants | IRContext::kAnalysisTypes | 43fd4e5da5Sopenharmony_ci IRContext::kAnalysisIdToFuncMapping; 44fd4e5da5Sopenharmony_ci } 45fd4e5da5Sopenharmony_ci 46fd4e5da5Sopenharmony_ci private: 47fd4e5da5Sopenharmony_ci // Records failure for the current module, and returns a stream 48fd4e5da5Sopenharmony_ci // that can be used to provide user error information to the message 49fd4e5da5Sopenharmony_ci // consumer. 50fd4e5da5Sopenharmony_ci spvtools::DiagnosticStream Fail(); 51fd4e5da5Sopenharmony_ci 52fd4e5da5Sopenharmony_ci // Returns SPV_SUCCESS if this pass can correctly process the module, 53fd4e5da5Sopenharmony_ci // as far as we can tell from capabilities and the memory model. 54fd4e5da5Sopenharmony_ci // Otherwise logs a message and returns a failure code. 55fd4e5da5Sopenharmony_ci spv_result_t IsCompatibleModule(); 56fd4e5da5Sopenharmony_ci 57fd4e5da5Sopenharmony_ci // Transform the current module, if possible. Failure and modification 58fd4e5da5Sopenharmony_ci // status is recorded in the |_| member. On failure, error information is 59fd4e5da5Sopenharmony_ci // posted to the message consumer. The return value has no significance. 60fd4e5da5Sopenharmony_ci spv_result_t ProcessCurrentModule(); 61fd4e5da5Sopenharmony_ci 62fd4e5da5Sopenharmony_ci // Process the given function. Updates the state value |_|. Returns true 63fd4e5da5Sopenharmony_ci // if the module was modified. This can log a failure. 64fd4e5da5Sopenharmony_ci bool ProcessAFunction(opt::Function*); 65fd4e5da5Sopenharmony_ci 66fd4e5da5Sopenharmony_ci // Clamps indices in the OpAccessChain or OpInBoundsAccessChain instruction 67fd4e5da5Sopenharmony_ci // |access_chain|. Inserts instructions before the given instruction. Updates 68fd4e5da5Sopenharmony_ci // analyses and records that the module is modified. This can log a failure. 69fd4e5da5Sopenharmony_ci void ClampIndicesForAccessChain(Instruction* access_chain); 70fd4e5da5Sopenharmony_ci 71fd4e5da5Sopenharmony_ci // Returns the id of the instruction importing the "GLSL.std.450" extended 72fd4e5da5Sopenharmony_ci // instruction set. If it does not yet exist, the import instruction is 73fd4e5da5Sopenharmony_ci // created and inserted into the module, and updates |_.modified| and 74fd4e5da5Sopenharmony_ci // |_.glsl_insts_id|. 75fd4e5da5Sopenharmony_ci uint32_t GetGlslInsts(); 76fd4e5da5Sopenharmony_ci 77fd4e5da5Sopenharmony_ci // Returns an instruction which is constant with the given value of the given 78fd4e5da5Sopenharmony_ci // type. Ignores any value bits beyond the width of the type. 79fd4e5da5Sopenharmony_ci Instruction* GetValueForType(uint64_t value, const analysis::Integer* type); 80fd4e5da5Sopenharmony_ci 81fd4e5da5Sopenharmony_ci // Converts an integer value to an unsigned wider integer type, using either 82fd4e5da5Sopenharmony_ci // sign extension or zero extension. The new instruction is inserted 83fd4e5da5Sopenharmony_ci // immediately before |before_inst|, and is analyzed for definitions and uses. 84fd4e5da5Sopenharmony_ci // Returns the newly inserted instruction. Assumes the |value| is an integer 85fd4e5da5Sopenharmony_ci // scalar of a narrower type than |bit_width| bits. 86fd4e5da5Sopenharmony_ci Instruction* WidenInteger(bool sign_extend, uint32_t bit_width, 87fd4e5da5Sopenharmony_ci Instruction* value, Instruction* before_inst); 88fd4e5da5Sopenharmony_ci 89fd4e5da5Sopenharmony_ci // Returns a new instruction that invokes the UMin GLSL.std.450 extended 90fd4e5da5Sopenharmony_ci // instruction with the two given operands. That is, the result of the 91fd4e5da5Sopenharmony_ci // instruction is: 92fd4e5da5Sopenharmony_ci // - |x| if |x| is unsigned-less than |y| 93fd4e5da5Sopenharmony_ci // - |y| otherwise 94fd4e5da5Sopenharmony_ci // We assume that |x| and |y| are scalar integer types with the same 95fd4e5da5Sopenharmony_ci // width. The instruction is inserted before |where|. 96fd4e5da5Sopenharmony_ci opt::Instruction* MakeUMinInst(const analysis::TypeManager& tm, 97fd4e5da5Sopenharmony_ci Instruction* x, Instruction* y, 98fd4e5da5Sopenharmony_ci Instruction* where); 99fd4e5da5Sopenharmony_ci 100fd4e5da5Sopenharmony_ci // Returns a new instruction that invokes the SClamp GLSL.std.450 extended 101fd4e5da5Sopenharmony_ci // instruction with the three given operands. That is, the result of the 102fd4e5da5Sopenharmony_ci // instruction is: 103fd4e5da5Sopenharmony_ci // - |min| if |x| is signed-less than |min| 104fd4e5da5Sopenharmony_ci // - |max| if |x| is signed-more than |max| 105fd4e5da5Sopenharmony_ci // - |x| otherwise. 106fd4e5da5Sopenharmony_ci // We assume that |min| is signed-less-or-equal to |max|, and that the 107fd4e5da5Sopenharmony_ci // operands all have the same scalar integer type. The instruction is 108fd4e5da5Sopenharmony_ci // inserted before |where|. 109fd4e5da5Sopenharmony_ci opt::Instruction* MakeSClampInst(const analysis::TypeManager& tm, 110fd4e5da5Sopenharmony_ci Instruction* x, Instruction* min, 111fd4e5da5Sopenharmony_ci Instruction* max, Instruction* where); 112fd4e5da5Sopenharmony_ci 113fd4e5da5Sopenharmony_ci // Returns a new instruction which evaluates to the length the runtime array 114fd4e5da5Sopenharmony_ci // referenced by the access chain at the specified index. The instruction is 115fd4e5da5Sopenharmony_ci // inserted before the access chain instruction. Returns a null pointer in 116fd4e5da5Sopenharmony_ci // some cases if assumptions are violated (rather than asserting out). 117fd4e5da5Sopenharmony_ci opt::Instruction* MakeRuntimeArrayLengthInst(Instruction* access_chain, 118fd4e5da5Sopenharmony_ci uint32_t operand_index); 119fd4e5da5Sopenharmony_ci 120fd4e5da5Sopenharmony_ci // Clamps the coordinate for an OpImageTexelPointer so it stays within 121fd4e5da5Sopenharmony_ci // the bounds of the size of the image. Updates analyses and records that 122fd4e5da5Sopenharmony_ci // the module is modified. Returns a status code to indicate success 123fd4e5da5Sopenharmony_ci // or failure. If assumptions are not met, returns an error status code 124fd4e5da5Sopenharmony_ci // and emits a diagnostic. 125fd4e5da5Sopenharmony_ci spv_result_t ClampCoordinateForImageTexelPointer( 126fd4e5da5Sopenharmony_ci opt::Instruction* image_texel_pointer); 127fd4e5da5Sopenharmony_ci 128fd4e5da5Sopenharmony_ci // Gets the instruction that defines the given id. 129fd4e5da5Sopenharmony_ci opt::Instruction* GetDef(uint32_t id) { 130fd4e5da5Sopenharmony_ci return context()->get_def_use_mgr()->GetDef(id); 131fd4e5da5Sopenharmony_ci } 132fd4e5da5Sopenharmony_ci 133fd4e5da5Sopenharmony_ci // Returns a new instruction inserted before |where_inst|, and created from 134fd4e5da5Sopenharmony_ci // the remaining arguments. Registers the definitions and uses of the new 135fd4e5da5Sopenharmony_ci // instruction and also records its block. 136fd4e5da5Sopenharmony_ci opt::Instruction* InsertInst(opt::Instruction* where_inst, spv::Op opcode, 137fd4e5da5Sopenharmony_ci uint32_t type_id, uint32_t result_id, 138fd4e5da5Sopenharmony_ci const Instruction::OperandList& operands); 139fd4e5da5Sopenharmony_ci 140fd4e5da5Sopenharmony_ci // State required for the current module. 141fd4e5da5Sopenharmony_ci struct PerModuleState { 142fd4e5da5Sopenharmony_ci // This pass modified the module. 143fd4e5da5Sopenharmony_ci bool modified = false; 144fd4e5da5Sopenharmony_ci // True if there is an error processing the current module, e.g. if 145fd4e5da5Sopenharmony_ci // preconditions are not met. 146fd4e5da5Sopenharmony_ci bool failed = false; 147fd4e5da5Sopenharmony_ci // The id of the GLSL.std.450 extended instruction set. Zero if it does 148fd4e5da5Sopenharmony_ci // not exist. 149fd4e5da5Sopenharmony_ci uint32_t glsl_insts_id = 0; 150fd4e5da5Sopenharmony_ci } module_status_; 151fd4e5da5Sopenharmony_ci}; 152fd4e5da5Sopenharmony_ci 153fd4e5da5Sopenharmony_ci} // namespace opt 154fd4e5da5Sopenharmony_ci} // namespace spvtools 155fd4e5da5Sopenharmony_ci 156fd4e5da5Sopenharmony_ci#endif // SOURCE_OPT_GRAPHICS_ROBUST_ACCESS_PASS_H_ 157