• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2019 Vasily Khoruzhick <anarsoul@gmail.com>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is 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
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "nir.h"
25 #include "nir_builder.h"
26 
27 #include "lima_ir.h"
28 
29 static bool
lima_nir_split_load_input_block(nir_block * block,nir_builder * b)30 lima_nir_split_load_input_block(nir_block *block, nir_builder *b)
31 {
32    bool progress = false;
33 
34    nir_foreach_instr_safe(instr, block) {
35       if (instr->type != nir_instr_type_alu)
36          continue;
37 
38       nir_alu_instr *alu = nir_instr_as_alu(instr);
39       if (alu->op != nir_op_mov)
40          continue;
41 
42       if (!alu->dest.dest.is_ssa)
43          continue;
44 
45       if (!alu->src[0].src.is_ssa)
46          continue;
47 
48       nir_ssa_def *ssa = alu->src[0].src.ssa;
49       if (ssa->parent_instr->type != nir_instr_type_intrinsic)
50          continue;
51 
52       nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(ssa->parent_instr);
53       if (intrin->intrinsic != nir_intrinsic_load_input)
54          continue;
55 
56       uint8_t swizzle = alu->src[0].swizzle[0];
57       int i;
58 
59       for (i = 1; i < nir_dest_num_components(alu->dest.dest); i++)
60          if (alu->src[0].swizzle[i] != (swizzle + i))
61             break;
62 
63       if (i != nir_dest_num_components(alu->dest.dest))
64          continue;
65 
66       /* mali4xx can't access unaligned vec3, don't split load input */
67       if (nir_dest_num_components(alu->dest.dest) == 3 && swizzle > 0)
68          continue;
69 
70       b->cursor = nir_before_instr(&intrin->instr);
71       nir_intrinsic_instr *new_intrin = nir_intrinsic_instr_create(
72                                              b->shader,
73                                              intrin->intrinsic);
74       nir_ssa_dest_init(&new_intrin->instr, &new_intrin->dest,
75                         nir_dest_num_components(alu->dest.dest),
76                         ssa->bit_size,
77                         NULL);
78       new_intrin->num_components = nir_dest_num_components(alu->dest.dest);
79       nir_intrinsic_set_base(new_intrin, nir_intrinsic_base(intrin));
80       nir_intrinsic_set_component(new_intrin, nir_intrinsic_component(intrin) + swizzle);
81       nir_intrinsic_set_dest_type(new_intrin, nir_intrinsic_dest_type(intrin));
82 
83       /* offset */
84       nir_src_copy(&new_intrin->src[0], &intrin->src[0], new_intrin);
85 
86       nir_builder_instr_insert(b, &new_intrin->instr);
87       nir_ssa_def_rewrite_uses(&alu->dest.dest.ssa,
88                                nir_src_for_ssa(&new_intrin->dest.ssa));
89       nir_instr_remove(&alu->instr);
90       progress = true;
91    }
92 
93    return progress;
94 }
95 
96 static bool
lima_nir_split_load_input_impl(nir_function_impl * impl)97 lima_nir_split_load_input_impl(nir_function_impl *impl)
98 {
99    bool progress = false;
100    nir_builder builder;
101    nir_builder_init(&builder, impl);
102 
103    nir_foreach_block(block, impl) {
104       progress |= lima_nir_split_load_input_block(block, &builder);
105    }
106 
107    nir_metadata_preserve(impl, nir_metadata_block_index |
108                                nir_metadata_dominance);
109    return progress;
110 }
111 
112 /* Replaces a single load of several packed varyings and number of movs with
113  * a number of loads of smaller size
114  */
115 bool
lima_nir_split_load_input(nir_shader * shader)116 lima_nir_split_load_input(nir_shader *shader)
117 {
118    bool progress = false;
119 
120    nir_foreach_function(function, shader) {
121       if (function->impl)
122          progress |= lima_nir_split_load_input_impl(function->impl);
123    }
124 
125    return progress;
126 }
127 
128