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 /* See resolve_ud_negate() and comment in brw_fs_emit.cpp. */
44 if (inst
->conditional_mod
&&
45 inst
->src
[arg
].type
== BRW_REGISTER_TYPE_UD
&&
49 bool has_source_modifiers
= entry
->src
.abs
|| entry
->src
.negate
;
51 if (intel
->gen
== 6 && inst
->is_math() &&
52 (has_source_modifiers
|| entry
->src
.file
== UNIFORM
))
55 inst
->src
[arg
].file
= entry
->src
.file
;
56 inst
->src
[arg
].reg
= entry
->src
.reg
;
57 inst
->src
[arg
].reg_offset
= entry
->src
.reg_offset
;
59 if (!inst
->src
[arg
].abs
) {
60 inst
->src
[arg
].abs
= entry
->src
.abs
;
61 inst
->src
[arg
].negate
^= entry
->src
.negate
;
67 /** @file brw_fs_copy_propagation.cpp
69 * Support for local copy propagation by walking the list of instructions
70 * and maintaining the ACP table of available copies for propagation.
72 * See Muchnik's Advanced Compiler Design and Implementation, section
76 /* Walks a basic block and does copy propagation on it using the acp
80 fs_visitor::opt_copy_propagate_local(void *mem_ctx
,
81 fs_bblock
*block
, exec_list
*acp
)
83 bool progress
= false;
85 for (fs_inst
*inst
= block
->start
;
86 inst
!= block
->end
->next
;
87 inst
= (fs_inst
*)inst
->next
) {
89 /* Try propagating into this instruction. */
90 foreach_list(entry_node
, acp
) {
91 acp_entry
*entry
= (acp_entry
*)entry_node
;
93 for (int i
= 0; i
< 3; i
++) {
94 if (try_copy_propagate(inst
, i
, entry
))
99 /* kill the destination from the ACP */
100 if (inst
->dst
.file
== GRF
) {
101 int start_offset
= inst
->dst
.reg_offset
;
102 int end_offset
= start_offset
+ inst
->regs_written();
104 foreach_list_safe(entry_node
, acp
) {
105 acp_entry
*entry
= (acp_entry
*)entry_node
;
107 if (entry
->dst
.file
== GRF
&&
108 entry
->dst
.reg
== inst
->dst
.reg
&&
109 entry
->dst
.reg_offset
>= start_offset
&&
110 entry
->dst
.reg_offset
< end_offset
) {
114 if (entry
->src
.file
== GRF
&&
115 entry
->src
.reg
== inst
->dst
.reg
&&
116 entry
->src
.reg_offset
>= start_offset
&&
117 entry
->src
.reg_offset
< end_offset
) {
123 /* If this instruction is a raw copy, add it to the ACP. */
124 if (inst
->opcode
== BRW_OPCODE_MOV
&&
125 inst
->dst
.file
== GRF
&&
126 ((inst
->src
[0].file
== GRF
&&
127 (inst
->src
[0].reg
!= inst
->dst
.reg
||
128 inst
->src
[0].reg_offset
!= inst
->dst
.reg_offset
)) ||
129 inst
->src
[0].file
== UNIFORM
) &&
130 inst
->src
[0].type
== inst
->dst
.type
&&
133 !inst
->force_uncompressed
&&
134 !inst
->force_sechalf
&&
135 inst
->src
[0].smear
== -1) {
136 acp_entry
*entry
= ralloc(mem_ctx
, acp_entry
);
137 entry
->dst
= inst
->dst
;
138 entry
->src
= inst
->src
[0];
139 acp
->push_tail(entry
);
147 fs_visitor::opt_copy_propagate()
149 bool progress
= false;
150 void *mem_ctx
= ralloc_context(this->mem_ctx
);
154 for (int b
= 0; b
< cfg
.num_blocks
; b
++) {
155 fs_bblock
*block
= cfg
.blocks
[b
];
158 progress
= opt_copy_propagate_local(mem_ctx
, block
, &acp
) || progress
;
161 ralloc_free(mem_ctx
);
164 live_intervals_valid
= false;