2 * Copyright © 2012 Intel Corporation
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:
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
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
25 #include "brw_fs_cfg.h"
27 namespace { /* avoid conflict with opt_copy_propagation_elements */
28 struct acp_entry
: public exec_node
{
35 fs_visitor::try_copy_propagate(fs_inst
*inst
, int arg
, acp_entry
*entry
)
37 if (inst
->src
[arg
].file
!= entry
->dst
.file
||
38 inst
->src
[arg
].reg
!= entry
->dst
.reg
||
39 inst
->src
[arg
].reg_offset
!= entry
->dst
.reg_offset
) {
43 inst
->src
[arg
].reg
= entry
->src
.reg
;
44 inst
->src
[arg
].reg_offset
= entry
->src
.reg_offset
;
49 /** @file brw_fs_copy_propagation.cpp
51 * Support for local copy propagation by walking the list of instructions
52 * and maintaining the ACP table of available copies for propagation.
54 * See Muchnik's Advanced Compiler Design and Implementation, section
58 /* Walks a basic block and does copy propagation on it using the acp
62 fs_visitor::opt_copy_propagate_local(void *mem_ctx
,
63 fs_bblock
*block
, exec_list
*acp
)
65 bool progress
= false;
67 for (fs_inst
*inst
= block
->start
;
68 inst
!= block
->end
->next
;
69 inst
= (fs_inst
*)inst
->next
) {
71 /* Try propagating into this instruction. */
72 foreach_list(entry_node
, acp
) {
73 acp_entry
*entry
= (acp_entry
*)entry_node
;
75 for (int i
= 0; i
< 3; i
++) {
76 if (try_copy_propagate(inst
, i
, entry
))
81 /* kill the destination from the ACP */
82 if (inst
->dst
.file
== GRF
) {
83 int start_offset
= inst
->dst
.reg_offset
;
84 int end_offset
= start_offset
+ inst
->regs_written();
86 foreach_list_safe(entry_node
, acp
) {
87 acp_entry
*entry
= (acp_entry
*)entry_node
;
89 if (entry
->dst
.file
== GRF
&&
90 entry
->dst
.reg
== inst
->dst
.reg
&&
91 entry
->dst
.reg_offset
>= start_offset
&&
92 entry
->dst
.reg_offset
< end_offset
) {
96 if (entry
->src
.file
== GRF
&&
97 entry
->src
.reg
== inst
->dst
.reg
&&
98 entry
->src
.reg_offset
>= start_offset
&&
99 entry
->src
.reg_offset
< end_offset
) {
105 /* If this instruction is a raw copy, add it to the ACP. */
106 if (inst
->opcode
== BRW_OPCODE_MOV
&&
107 inst
->dst
.file
== GRF
&&
108 inst
->src
[0].file
== GRF
&&
109 (inst
->src
[0].reg
!= inst
->dst
.reg
||
110 inst
->src
[0].reg_offset
!= inst
->dst
.reg_offset
) &&
111 inst
->src
[0].type
== inst
->dst
.type
&&
114 !inst
->force_uncompressed
&&
115 !inst
->force_sechalf
&&
116 inst
->src
[0].smear
== -1 &&
118 !inst
->src
[0].negate
) {
119 acp_entry
*entry
= ralloc(mem_ctx
, acp_entry
);
120 entry
->dst
= inst
->dst
;
121 entry
->src
= inst
->src
[0];
122 acp
->push_tail(entry
);
130 fs_visitor::opt_copy_propagate()
132 bool progress
= false;
133 void *mem_ctx
= ralloc_context(this->mem_ctx
);
137 for (int b
= 0; b
< cfg
.num_blocks
; b
++) {
138 fs_bblock
*block
= cfg
.blocks
[b
];
141 progress
= opt_copy_propagate_local(mem_ctx
, block
, &acp
) || progress
;
144 ralloc_free(mem_ctx
);