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