1/* 2 * Copyright © 2022 Imagination Technologies Ltd. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 */ 23 24#include "nir/nir.h" 25#include "nir/nir_builder.h" 26#include "nir/nir_search_helpers.h" 27#include "rogue_constreg.h" 28#include "rogue_nir.h" 29 30/* TODO: optimize: if value is in const regs, replace, else, use shared regs and 31 * notify driver they need to be populated? 32 */ 33 34/* Replaces multiple ssa uses from load_const with a single use -> a register. 35 */ 36void rogue_nir_constreg(nir_shader *shader) 37{ 38 nir_function_impl *impl = nir_shader_get_entrypoint(shader); 39 nir_builder b; 40 41 nir_builder_init(&b, impl); 42 43 /* Find load_const instructions. */ 44 nir_foreach_block (block, impl) { 45 nir_foreach_instr_safe (instr, block) { 46 if (instr->type != nir_instr_type_load_const) 47 continue; 48 49 nir_load_const_instr *load_const = nir_instr_as_load_const(instr); 50 51 /* Skip values that can be pulled from constant registers. */ 52 uint32_t value = nir_const_value_as_uint(load_const->value[0], 32); 53 size_t const_reg = rogue_constreg_lookup(value); 54 if (const_reg != ROGUE_NO_CONST_REG) 55 continue; 56 57 b.cursor = nir_after_instr(&load_const->instr); 58 nir_ssa_def *mov = nir_mov(&b, &load_const->def); 59 60 nir_foreach_use_safe (use_src, &load_const->def) { 61 if (use_src->parent_instr == mov->parent_instr) 62 continue; 63 64 /* Skip when used as an index for intrinsics, as we want to 65 * access that value directly. 66 */ 67 if (use_src->parent_instr->type == nir_instr_type_intrinsic) 68 continue; 69 70 nir_instr_rewrite_src_ssa(use_src->parent_instr, use_src, mov); 71 } 72 } 73 } 74} 75