1/* 2 * Copyright © 2016 Intel Corporation 3 * Copyright © 2018 Valve Corporation 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24 25#include "nir.h" 26 27/** 28 * \file nir_opt_move_load_ubo.c 29 * 30 * This pass moves load UBO operations just before their first use inside 31 * the same basic block. 32 */ 33static bool 34move_load_ubo_source(nir_src *src, nir_block *block, nir_instr *before) 35{ 36 if (!src->is_ssa) 37 return false; 38 39 nir_instr *src_instr = src->ssa->parent_instr; 40 41 if (src_instr->block == block && 42 src_instr->type == nir_instr_type_intrinsic && 43 nir_instr_as_intrinsic(src_instr)->intrinsic == nir_intrinsic_load_ubo) { 44 45 exec_node_remove(&src_instr->node); 46 47 if (before) 48 exec_node_insert_node_before(&before->node, &src_instr->node); 49 else 50 exec_list_push_tail(&block->instr_list, &src_instr->node); 51 52 return true; 53 } 54 return false; 55} 56 57static bool 58move_load_ubo_source_cb(nir_src *src, void *data) 59{ 60 bool *progress = data; 61 62 nir_instr *instr = src->parent_instr; 63 if (move_load_ubo_source(src, instr->block, instr)) 64 *progress = true; 65 66 return true; /* nir_foreach_src should keep going */ 67} 68 69static bool 70move_load_ubo(nir_block *block) 71{ 72 bool progress = false; 73 74 nir_if *iff = nir_block_get_following_if(block); 75 if (iff) { 76 progress |= move_load_ubo_source(&iff->condition, block, NULL); 77 } 78 79 nir_foreach_instr_reverse(instr, block) { 80 81 if (instr->type == nir_instr_type_phi) { 82 /* We're going backwards so everything else is a phi too */ 83 } else if (instr->type == nir_instr_type_alu) { 84 nir_alu_instr *alu = nir_instr_as_alu(instr); 85 86 for (int i = nir_op_infos[alu->op].num_inputs - 1; i >= 0; i--) { 87 progress |= move_load_ubo_source(&alu->src[i].src, block, instr); 88 } 89 } else { 90 nir_foreach_src(instr, move_load_ubo_source_cb, &progress); 91 } 92 } 93 94 return progress; 95} 96 97bool 98nir_opt_move_load_ubo(nir_shader *shader) 99{ 100 bool progress = false; 101 102 nir_foreach_function(func, shader) { 103 if (!func->impl) 104 continue; 105 106 nir_foreach_block(block, func->impl) { 107 if (move_load_ubo(block)) { 108 nir_metadata_preserve(func->impl, nir_metadata_block_index | 109 nir_metadata_dominance | 110 nir_metadata_live_ssa_defs); 111 progress = true; 112 } 113 } 114 } 115 116 return progress; 117} 118