1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci */
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci/** @file brw_vec4_cmod_propagation.cpp
26bf215546Sopenharmony_ci *
27bf215546Sopenharmony_ci * Really similar to brw_fs_cmod_propagation but adapted to vec4 needs. Check
28bf215546Sopenharmony_ci * brw_fs_cmod_propagation for further details on the rationale behind this
29bf215546Sopenharmony_ci * optimization.
30bf215546Sopenharmony_ci */
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "brw_vec4.h"
33bf215546Sopenharmony_ci#include "brw_cfg.h"
34bf215546Sopenharmony_ci#include "brw_eu.h"
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_cinamespace brw {
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_cistatic bool
39bf215546Sopenharmony_ciwritemasks_incompatible(const vec4_instruction *earlier,
40bf215546Sopenharmony_ci                        const vec4_instruction *later)
41bf215546Sopenharmony_ci{
42bf215546Sopenharmony_ci   return (earlier->dst.writemask != WRITEMASK_X &&
43bf215546Sopenharmony_ci           earlier->dst.writemask != WRITEMASK_XYZW) ||
44bf215546Sopenharmony_ci          (earlier->dst.writemask == WRITEMASK_XYZW &&
45bf215546Sopenharmony_ci           later->src[0].swizzle != BRW_SWIZZLE_XYZW) ||
46bf215546Sopenharmony_ci          (later->dst.writemask & ~earlier->dst.writemask) != 0;
47bf215546Sopenharmony_ci}
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_cistatic bool
50bf215546Sopenharmony_ciopt_cmod_propagation_local(bblock_t *block, vec4_visitor *v)
51bf215546Sopenharmony_ci{
52bf215546Sopenharmony_ci   bool progress = false;
53bf215546Sopenharmony_ci   int ip = block->end_ip + 1;
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_ci   foreach_inst_in_block_reverse_safe(vec4_instruction, inst, block) {
56bf215546Sopenharmony_ci      ip--;
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci      if ((inst->opcode != BRW_OPCODE_AND &&
59bf215546Sopenharmony_ci           inst->opcode != BRW_OPCODE_CMP &&
60bf215546Sopenharmony_ci           inst->opcode != BRW_OPCODE_MOV) ||
61bf215546Sopenharmony_ci          inst->predicate != BRW_PREDICATE_NONE ||
62bf215546Sopenharmony_ci          !inst->dst.is_null() ||
63bf215546Sopenharmony_ci          (inst->src[0].file != VGRF && inst->src[0].file != ATTR &&
64bf215546Sopenharmony_ci           inst->src[0].file != UNIFORM))
65bf215546Sopenharmony_ci         continue;
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci      /* An ABS source modifier can only be handled when processing a compare
68bf215546Sopenharmony_ci       * with a value other than zero.
69bf215546Sopenharmony_ci       */
70bf215546Sopenharmony_ci      if (inst->src[0].abs &&
71bf215546Sopenharmony_ci          (inst->opcode != BRW_OPCODE_CMP || inst->src[1].is_zero()))
72bf215546Sopenharmony_ci         continue;
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ci      if (inst->opcode == BRW_OPCODE_AND &&
75bf215546Sopenharmony_ci          !(inst->src[1].is_one() &&
76bf215546Sopenharmony_ci            inst->conditional_mod == BRW_CONDITIONAL_NZ &&
77bf215546Sopenharmony_ci            !inst->src[0].negate))
78bf215546Sopenharmony_ci         continue;
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci      if (inst->opcode == BRW_OPCODE_MOV &&
81bf215546Sopenharmony_ci          inst->conditional_mod != BRW_CONDITIONAL_NZ)
82bf215546Sopenharmony_ci         continue;
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci      bool read_flag = false;
85bf215546Sopenharmony_ci      foreach_inst_in_block_reverse_starting_from(vec4_instruction, scan_inst, inst) {
86bf215546Sopenharmony_ci         /* A CMP with a second source of zero can match with anything.  A CMP
87bf215546Sopenharmony_ci          * with a second source that is not zero can only match with an ADD
88bf215546Sopenharmony_ci          * instruction.
89bf215546Sopenharmony_ci          */
90bf215546Sopenharmony_ci         if (inst->opcode == BRW_OPCODE_CMP && !inst->src[1].is_zero()) {
91bf215546Sopenharmony_ci            bool negate;
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci            if (scan_inst->opcode != BRW_OPCODE_ADD)
94bf215546Sopenharmony_ci               goto not_match;
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci            if (writemasks_incompatible(scan_inst, inst))
97bf215546Sopenharmony_ci               goto not_match;
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci            /* A CMP is basically a subtraction.  The result of the
100bf215546Sopenharmony_ci             * subtraction must be the same as the result of the addition.
101bf215546Sopenharmony_ci             * This means that one of the operands must be negated.  So (a +
102bf215546Sopenharmony_ci             * b) vs (a == -b) or (a + -b) vs (a == b).
103bf215546Sopenharmony_ci             */
104bf215546Sopenharmony_ci            if ((inst->src[0].equals(scan_inst->src[0]) &&
105bf215546Sopenharmony_ci                 inst->src[1].negative_equals(scan_inst->src[1])) ||
106bf215546Sopenharmony_ci                (inst->src[0].equals(scan_inst->src[1]) &&
107bf215546Sopenharmony_ci                 inst->src[1].negative_equals(scan_inst->src[0]))) {
108bf215546Sopenharmony_ci               negate = false;
109bf215546Sopenharmony_ci            } else if ((inst->src[0].negative_equals(scan_inst->src[0]) &&
110bf215546Sopenharmony_ci                        inst->src[1].equals(scan_inst->src[1])) ||
111bf215546Sopenharmony_ci                       (inst->src[0].negative_equals(scan_inst->src[1]) &&
112bf215546Sopenharmony_ci                        inst->src[1].equals(scan_inst->src[0]))) {
113bf215546Sopenharmony_ci               negate = true;
114bf215546Sopenharmony_ci            } else {
115bf215546Sopenharmony_ci               goto not_match;
116bf215546Sopenharmony_ci            }
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci            if (scan_inst->exec_size != inst->exec_size ||
119bf215546Sopenharmony_ci                scan_inst->group != inst->group)
120bf215546Sopenharmony_ci               goto not_match;
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci            /* From the Sky Lake PRM Vol. 7 "Assigning Conditional Mods":
123bf215546Sopenharmony_ci             *
124bf215546Sopenharmony_ci             *    * Note that the [post condition signal] bits generated at
125bf215546Sopenharmony_ci             *      the output of a compute are before the .sat.
126bf215546Sopenharmony_ci             *
127bf215546Sopenharmony_ci             * So we don't have to bail if scan_inst has saturate.
128bf215546Sopenharmony_ci             */
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci            /* Otherwise, try propagating the conditional. */
131bf215546Sopenharmony_ci            const enum brw_conditional_mod cond =
132bf215546Sopenharmony_ci               negate ? brw_swap_cmod(inst->conditional_mod)
133bf215546Sopenharmony_ci                      : inst->conditional_mod;
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci            if (scan_inst->can_do_cmod() &&
136bf215546Sopenharmony_ci                ((!read_flag && scan_inst->conditional_mod == BRW_CONDITIONAL_NONE) ||
137bf215546Sopenharmony_ci                 scan_inst->conditional_mod == cond)) {
138bf215546Sopenharmony_ci               scan_inst->conditional_mod = cond;
139bf215546Sopenharmony_ci               inst->remove(block);
140bf215546Sopenharmony_ci               progress = true;
141bf215546Sopenharmony_ci            }
142bf215546Sopenharmony_ci            break;
143bf215546Sopenharmony_ci         }
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci         if (regions_overlap(inst->src[0], inst->size_read(0),
146bf215546Sopenharmony_ci                             scan_inst->dst, scan_inst->size_written)) {
147bf215546Sopenharmony_ci            if ((scan_inst->predicate && scan_inst->opcode != BRW_OPCODE_SEL) ||
148bf215546Sopenharmony_ci                scan_inst->dst.offset != inst->src[0].offset ||
149bf215546Sopenharmony_ci                scan_inst->exec_size != inst->exec_size ||
150bf215546Sopenharmony_ci                scan_inst->group != inst->group) {
151bf215546Sopenharmony_ci               break;
152bf215546Sopenharmony_ci            }
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci            /* If scan_inst is a CMP that produces a single value and inst is
155bf215546Sopenharmony_ci             * a CMP.NZ that consumes only that value, remove inst.
156bf215546Sopenharmony_ci             */
157bf215546Sopenharmony_ci            if (inst->conditional_mod == BRW_CONDITIONAL_NZ &&
158bf215546Sopenharmony_ci                (inst->src[0].type == BRW_REGISTER_TYPE_D ||
159bf215546Sopenharmony_ci                 inst->src[0].type == BRW_REGISTER_TYPE_UD) &&
160bf215546Sopenharmony_ci                (inst->opcode == BRW_OPCODE_CMP ||
161bf215546Sopenharmony_ci                 inst->opcode == BRW_OPCODE_MOV) &&
162bf215546Sopenharmony_ci                scan_inst->opcode == BRW_OPCODE_CMP &&
163bf215546Sopenharmony_ci                ((inst->src[0].swizzle == BRW_SWIZZLE_XXXX &&
164bf215546Sopenharmony_ci                  scan_inst->dst.writemask == WRITEMASK_X) ||
165bf215546Sopenharmony_ci                 (inst->src[0].swizzle == BRW_SWIZZLE_YYYY &&
166bf215546Sopenharmony_ci                  scan_inst->dst.writemask == WRITEMASK_Y) ||
167bf215546Sopenharmony_ci                 (inst->src[0].swizzle == BRW_SWIZZLE_ZZZZ &&
168bf215546Sopenharmony_ci                  scan_inst->dst.writemask == WRITEMASK_Z) ||
169bf215546Sopenharmony_ci                 (inst->src[0].swizzle == BRW_SWIZZLE_WWWW &&
170bf215546Sopenharmony_ci                  scan_inst->dst.writemask == WRITEMASK_W))) {
171bf215546Sopenharmony_ci               if (inst->dst.writemask != scan_inst->dst.writemask) {
172bf215546Sopenharmony_ci                  src_reg temp(v, glsl_type::vec4_type, 1);
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci                  /* Given a sequence like:
175bf215546Sopenharmony_ci                   *
176bf215546Sopenharmony_ci                   *    cmp.ge.f0(8)  g21<1>.zF      g20<4>.xF      g18<4>.xF
177bf215546Sopenharmony_ci                   *    ...
178bf215546Sopenharmony_ci                   *    cmp.nz.f0(8)  null<1>D       g21<4>.zD      0D
179bf215546Sopenharmony_ci                   *
180bf215546Sopenharmony_ci                   * Replace it with something like:
181bf215546Sopenharmony_ci                   *
182bf215546Sopenharmony_ci                   *    cmp.ge.f0(8)  g22<1>.zF      g20<4>.xF      g18<4>.xF
183bf215546Sopenharmony_ci                   *    mov(8)        g21<1>.xF      g22<1>.zzzzF
184bf215546Sopenharmony_ci                   *
185bf215546Sopenharmony_ci                   * The added MOV will most likely be removed later.  In the
186bf215546Sopenharmony_ci                   * worst case, it should be cheaper to schedule.
187bf215546Sopenharmony_ci                   */
188bf215546Sopenharmony_ci                  temp.swizzle = brw_swizzle_for_mask(inst->dst.writemask);
189bf215546Sopenharmony_ci                  temp.type = scan_inst->src[0].type;
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci                  vec4_instruction *mov = v->MOV(scan_inst->dst, temp);
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci                  /* Modify the source swizzles on scan_inst.  If scan_inst
194bf215546Sopenharmony_ci                   * was
195bf215546Sopenharmony_ci                   *
196bf215546Sopenharmony_ci                   *    cmp.ge.f0(8)  g21<1>.zF      g20<4>.wzyxF   g18<4>.yxwzF
197bf215546Sopenharmony_ci                   *
198bf215546Sopenharmony_ci                   * replace it with
199bf215546Sopenharmony_ci                   *
200bf215546Sopenharmony_ci                   *    cmp.ge.f0(8)  g21<1>.zF      g20<4>.yyyyF   g18<4>.wwwwF
201bf215546Sopenharmony_ci                   */
202bf215546Sopenharmony_ci                  unsigned src0_chan;
203bf215546Sopenharmony_ci                  unsigned src1_chan;
204bf215546Sopenharmony_ci                  switch (scan_inst->dst.writemask) {
205bf215546Sopenharmony_ci                  case WRITEMASK_X:
206bf215546Sopenharmony_ci                     src0_chan = BRW_GET_SWZ(scan_inst->src[0].swizzle, 0);
207bf215546Sopenharmony_ci                     src1_chan = BRW_GET_SWZ(scan_inst->src[1].swizzle, 0);
208bf215546Sopenharmony_ci                     break;
209bf215546Sopenharmony_ci                  case WRITEMASK_Y:
210bf215546Sopenharmony_ci                     src0_chan = BRW_GET_SWZ(scan_inst->src[0].swizzle, 1);
211bf215546Sopenharmony_ci                     src1_chan = BRW_GET_SWZ(scan_inst->src[1].swizzle, 1);
212bf215546Sopenharmony_ci                     break;
213bf215546Sopenharmony_ci                  case WRITEMASK_Z:
214bf215546Sopenharmony_ci                     src0_chan = BRW_GET_SWZ(scan_inst->src[0].swizzle, 2);
215bf215546Sopenharmony_ci                     src1_chan = BRW_GET_SWZ(scan_inst->src[1].swizzle, 2);
216bf215546Sopenharmony_ci                     break;
217bf215546Sopenharmony_ci                  case WRITEMASK_W:
218bf215546Sopenharmony_ci                     src0_chan = BRW_GET_SWZ(scan_inst->src[0].swizzle, 3);
219bf215546Sopenharmony_ci                     src1_chan = BRW_GET_SWZ(scan_inst->src[1].swizzle, 3);
220bf215546Sopenharmony_ci                     break;
221bf215546Sopenharmony_ci                  default:
222bf215546Sopenharmony_ci                     unreachable("Impossible writemask");
223bf215546Sopenharmony_ci                  }
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci                  scan_inst->src[0].swizzle = BRW_SWIZZLE4(src0_chan,
226bf215546Sopenharmony_ci                                                           src0_chan,
227bf215546Sopenharmony_ci                                                           src0_chan,
228bf215546Sopenharmony_ci                                                           src0_chan);
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci                  /* There's no swizzle on immediate value sources. */
231bf215546Sopenharmony_ci                  if (scan_inst->src[1].file != IMM) {
232bf215546Sopenharmony_ci                     scan_inst->src[1].swizzle = BRW_SWIZZLE4(src1_chan,
233bf215546Sopenharmony_ci                                                              src1_chan,
234bf215546Sopenharmony_ci                                                              src1_chan,
235bf215546Sopenharmony_ci                                                              src1_chan);
236bf215546Sopenharmony_ci                  }
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_ci                  scan_inst->dst = dst_reg(temp);
239bf215546Sopenharmony_ci                  scan_inst->dst.writemask = inst->dst.writemask;
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_ci                  scan_inst->insert_after(block, mov);
242bf215546Sopenharmony_ci               }
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci               inst->remove(block);
245bf215546Sopenharmony_ci               progress = true;
246bf215546Sopenharmony_ci               break;
247bf215546Sopenharmony_ci            }
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_ci            if (writemasks_incompatible(scan_inst, inst))
250bf215546Sopenharmony_ci               break;
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_ci            /* CMP's result is the same regardless of dest type. */
253bf215546Sopenharmony_ci            if (inst->conditional_mod == BRW_CONDITIONAL_NZ &&
254bf215546Sopenharmony_ci                scan_inst->opcode == BRW_OPCODE_CMP &&
255bf215546Sopenharmony_ci                (inst->dst.type == BRW_REGISTER_TYPE_D ||
256bf215546Sopenharmony_ci                 inst->dst.type == BRW_REGISTER_TYPE_UD)) {
257bf215546Sopenharmony_ci               inst->remove(block);
258bf215546Sopenharmony_ci               progress = true;
259bf215546Sopenharmony_ci               break;
260bf215546Sopenharmony_ci            }
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_ci            /* If the AND wasn't handled by the previous case, it isn't safe
263bf215546Sopenharmony_ci             * to remove it.
264bf215546Sopenharmony_ci             */
265bf215546Sopenharmony_ci            if (inst->opcode == BRW_OPCODE_AND)
266bf215546Sopenharmony_ci               break;
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci            /* Comparisons operate differently for ints and floats */
269bf215546Sopenharmony_ci            if (scan_inst->dst.type != inst->dst.type &&
270bf215546Sopenharmony_ci                (scan_inst->dst.type == BRW_REGISTER_TYPE_F ||
271bf215546Sopenharmony_ci                 inst->dst.type == BRW_REGISTER_TYPE_F))
272bf215546Sopenharmony_ci               break;
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci            /* If the instruction generating inst's source also wrote the
275bf215546Sopenharmony_ci             * flag, and inst is doing a simple .nz comparison, then inst
276bf215546Sopenharmony_ci             * is redundant - the appropriate value is already in the flag
277bf215546Sopenharmony_ci             * register.  Delete inst.
278bf215546Sopenharmony_ci             */
279bf215546Sopenharmony_ci            if (inst->conditional_mod == BRW_CONDITIONAL_NZ &&
280bf215546Sopenharmony_ci                !inst->src[0].negate &&
281bf215546Sopenharmony_ci                scan_inst->writes_flag(v->devinfo)) {
282bf215546Sopenharmony_ci               inst->remove(block);
283bf215546Sopenharmony_ci               progress = true;
284bf215546Sopenharmony_ci               break;
285bf215546Sopenharmony_ci            }
286bf215546Sopenharmony_ci
287bf215546Sopenharmony_ci            /* The conditional mod of the CMP/CMPN instructions behaves
288bf215546Sopenharmony_ci             * specially because the flag output is not calculated from the
289bf215546Sopenharmony_ci             * result of the instruction, but the other way around, which
290bf215546Sopenharmony_ci             * means that even if the condmod to propagate and the condmod
291bf215546Sopenharmony_ci             * from the CMP instruction are the same they will in general give
292bf215546Sopenharmony_ci             * different results because they are evaluated based on different
293bf215546Sopenharmony_ci             * inputs.
294bf215546Sopenharmony_ci             */
295bf215546Sopenharmony_ci            if (scan_inst->opcode == BRW_OPCODE_CMP ||
296bf215546Sopenharmony_ci                scan_inst->opcode == BRW_OPCODE_CMPN)
297bf215546Sopenharmony_ci               break;
298bf215546Sopenharmony_ci
299bf215546Sopenharmony_ci            /* From the Sky Lake PRM Vol. 7 "Assigning Conditional Mods":
300bf215546Sopenharmony_ci             *
301bf215546Sopenharmony_ci             *    * Note that the [post condition signal] bits generated at
302bf215546Sopenharmony_ci             *      the output of a compute are before the .sat.
303bf215546Sopenharmony_ci             */
304bf215546Sopenharmony_ci            if (scan_inst->saturate)
305bf215546Sopenharmony_ci               break;
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_ci            /* From the Sky Lake PRM, Vol 2a, "Multiply":
308bf215546Sopenharmony_ci             *
309bf215546Sopenharmony_ci             *    "When multiplying integer data types, if one of the sources
310bf215546Sopenharmony_ci             *    is a DW, the resulting full precision data is stored in
311bf215546Sopenharmony_ci             *    the accumulator. However, if the destination data type is
312bf215546Sopenharmony_ci             *    either W or DW, the low bits of the result are written to
313bf215546Sopenharmony_ci             *    the destination register and the remaining high bits are
314bf215546Sopenharmony_ci             *    discarded. This results in undefined Overflow and Sign
315bf215546Sopenharmony_ci             *    flags. Therefore, conditional modifiers and saturation
316bf215546Sopenharmony_ci             *    (.sat) cannot be used in this case.
317bf215546Sopenharmony_ci             *
318bf215546Sopenharmony_ci             * We just disallow cmod propagation on all integer multiplies.
319bf215546Sopenharmony_ci             */
320bf215546Sopenharmony_ci            if (!brw_reg_type_is_floating_point(scan_inst->dst.type) &&
321bf215546Sopenharmony_ci                scan_inst->opcode == BRW_OPCODE_MUL)
322bf215546Sopenharmony_ci               break;
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ci            /* Otherwise, try propagating the conditional. */
325bf215546Sopenharmony_ci            enum brw_conditional_mod cond =
326bf215546Sopenharmony_ci               inst->src[0].negate ? brw_swap_cmod(inst->conditional_mod)
327bf215546Sopenharmony_ci                                   : inst->conditional_mod;
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci            if (scan_inst->can_do_cmod() &&
330bf215546Sopenharmony_ci                ((!read_flag && scan_inst->conditional_mod == BRW_CONDITIONAL_NONE) ||
331bf215546Sopenharmony_ci                 scan_inst->conditional_mod == cond)) {
332bf215546Sopenharmony_ci               scan_inst->conditional_mod = cond;
333bf215546Sopenharmony_ci               inst->remove(block);
334bf215546Sopenharmony_ci               progress = true;
335bf215546Sopenharmony_ci            }
336bf215546Sopenharmony_ci            break;
337bf215546Sopenharmony_ci         }
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_ci      not_match:
340bf215546Sopenharmony_ci         if (scan_inst->writes_flag(v->devinfo))
341bf215546Sopenharmony_ci            break;
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci         read_flag = read_flag || scan_inst->reads_flag();
344bf215546Sopenharmony_ci      }
345bf215546Sopenharmony_ci   }
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci   return progress;
348bf215546Sopenharmony_ci}
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_cibool
351bf215546Sopenharmony_civec4_visitor::opt_cmod_propagation()
352bf215546Sopenharmony_ci{
353bf215546Sopenharmony_ci   bool progress = false;
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci   foreach_block_reverse(block, cfg) {
356bf215546Sopenharmony_ci      progress = opt_cmod_propagation_local(block, this) || progress;
357bf215546Sopenharmony_ci   }
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_ci   if (progress)
360bf215546Sopenharmony_ci      invalidate_analysis(DEPENDENCY_INSTRUCTIONS);
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_ci   return progress;
363bf215546Sopenharmony_ci}
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ci} /* namespace brw */
366