1 /*
2  * Copyright (C) 2018 Alyssa Rosenzweig
3  * Copyright (C) 2019-2020 Collabora, Ltd.
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 FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 
25 #include "compiler.h"
26 
27 /* A simple scalar-only SSA-based copy-propagation pass. TODO: vectors */
28 
29 static bool
bi_is_copy(bi_instr * ins)30 bi_is_copy(bi_instr *ins)
31 {
32         return (ins->op == BI_OPCODE_MOV_I32) && bi_is_ssa(ins->dest[0])
33                 && (bi_is_ssa(ins->src[0]) || ins->src[0].type == BI_INDEX_FAU
34                                 || ins->src[0].type == BI_INDEX_CONSTANT);
35 }
36 
37 static bool
bi_reads_fau(bi_instr * ins)38 bi_reads_fau(bi_instr *ins)
39 {
40         bi_foreach_src(ins, s) {
41                 if (ins->src[s].type == BI_INDEX_FAU)
42                         return true;
43         }
44 
45         return false;
46 }
47 
48 void
bi_opt_copy_prop(bi_context * ctx)49 bi_opt_copy_prop(bi_context *ctx)
50 {
51         bi_index *replacement = calloc(sizeof(bi_index), ((ctx->ssa_alloc + 1) << 2));
52 
53         bi_foreach_instr_global_safe(ctx, ins) {
54                 if (bi_is_copy(ins)) {
55                         bi_index replace = ins->src[0];
56 
57                         /* Peek through one layer so copyprop converges in one
58                          * iteration for chained moves */
59                         if (bi_is_ssa(replace)) {
60                                 bi_index chained = replacement[bi_word_node(replace)];
61 
62                                 if (!bi_is_null(chained))
63                                         replace = chained;
64                         }
65 
66                         replacement[bi_word_node(ins->dest[0])] = replace;
67                 }
68 
69                 bi_foreach_src(ins, s) {
70                         bi_index use = ins->src[s];
71 
72                         if (use.type != BI_INDEX_NORMAL || use.reg) continue;
73                         if (s == 0 && bi_opcode_props[ins->op].sr_read) continue;
74 
75                         bi_index repl = replacement[bi_word_node(use)];
76 
77                         if (repl.type == BI_INDEX_CONSTANT && bi_reads_fau(ins))
78                                 continue;
79 
80                         if (!bi_is_null(repl))
81                                 ins->src[s] = bi_replace_index(ins->src[s], repl);
82                 }
83         }
84 
85         free(replacement);
86 }
87