1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2019 Valve 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#include "aco_builder.h" 26bf215546Sopenharmony_ci#include "aco_ir.h" 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include <algorithm> 29bf215546Sopenharmony_ci#include <map> 30bf215546Sopenharmony_ci#include <vector> 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_cinamespace aco { 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_cienum class pred_defined : uint8_t { 35bf215546Sopenharmony_ci undef = 0, 36bf215546Sopenharmony_ci const_1 = 1, 37bf215546Sopenharmony_ci const_0 = 2, 38bf215546Sopenharmony_ci temp = 3, 39bf215546Sopenharmony_ci zero = 4, /* all disabled lanes are zero'd out */ 40bf215546Sopenharmony_ci}; 41bf215546Sopenharmony_ciMESA_DEFINE_CPP_ENUM_BITFIELD_OPERATORS(pred_defined); 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_cistruct ssa_state { 44bf215546Sopenharmony_ci bool checked_preds_for_uniform; 45bf215546Sopenharmony_ci bool all_preds_uniform; 46bf215546Sopenharmony_ci unsigned loop_nest_depth; 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci std::vector<pred_defined> any_pred_defined; 49bf215546Sopenharmony_ci std::vector<bool> visited; 50bf215546Sopenharmony_ci std::vector<Operand> outputs; /* the output per block */ 51bf215546Sopenharmony_ci}; 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ciOperand 54bf215546Sopenharmony_ciget_ssa(Program* program, unsigned block_idx, ssa_state* state, bool input) 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci if (!input) { 57bf215546Sopenharmony_ci if (state->visited[block_idx]) 58bf215546Sopenharmony_ci return state->outputs[block_idx]; 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci /* otherwise, output == input */ 61bf215546Sopenharmony_ci Operand output = get_ssa(program, block_idx, state, true); 62bf215546Sopenharmony_ci state->visited[block_idx] = true; 63bf215546Sopenharmony_ci state->outputs[block_idx] = output; 64bf215546Sopenharmony_ci return output; 65bf215546Sopenharmony_ci } 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci /* retrieve the Operand by checking the predecessors */ 68bf215546Sopenharmony_ci if (state->any_pred_defined[block_idx] == pred_defined::undef) 69bf215546Sopenharmony_ci return Operand(program->lane_mask); 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci Block& block = program->blocks[block_idx]; 72bf215546Sopenharmony_ci size_t pred = block.linear_preds.size(); 73bf215546Sopenharmony_ci Operand op; 74bf215546Sopenharmony_ci if (block.loop_nest_depth < state->loop_nest_depth) { 75bf215546Sopenharmony_ci /* loop-carried value for loop exit phis */ 76bf215546Sopenharmony_ci op = Operand::zero(program->lane_mask.bytes()); 77bf215546Sopenharmony_ci } else if (block.loop_nest_depth > state->loop_nest_depth || pred == 1 || 78bf215546Sopenharmony_ci block.kind & block_kind_loop_exit) { 79bf215546Sopenharmony_ci op = get_ssa(program, block.linear_preds[0], state, false); 80bf215546Sopenharmony_ci } else { 81bf215546Sopenharmony_ci assert(pred > 1); 82bf215546Sopenharmony_ci bool previously_visited = state->visited[block_idx]; 83bf215546Sopenharmony_ci /* potential recursion: anchor at loop header */ 84bf215546Sopenharmony_ci if (block.kind & block_kind_loop_header) { 85bf215546Sopenharmony_ci assert(!previously_visited); 86bf215546Sopenharmony_ci previously_visited = true; 87bf215546Sopenharmony_ci state->visited[block_idx] = true; 88bf215546Sopenharmony_ci state->outputs[block_idx] = Operand(Temp(program->allocateTmp(program->lane_mask))); 89bf215546Sopenharmony_ci } 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci /* collect predecessor output operands */ 92bf215546Sopenharmony_ci std::vector<Operand> ops(pred); 93bf215546Sopenharmony_ci for (unsigned i = 0; i < pred; i++) 94bf215546Sopenharmony_ci ops[i] = get_ssa(program, block.linear_preds[i], state, false); 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci /* check triviality */ 97bf215546Sopenharmony_ci if (std::all_of(ops.begin() + 1, ops.end(), [&](Operand same) { return same == ops[0]; })) 98bf215546Sopenharmony_ci return ops[0]; 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci /* Return if this was handled in a recursive call by a loop header phi */ 101bf215546Sopenharmony_ci if (!previously_visited && state->visited[block_idx]) 102bf215546Sopenharmony_ci return state->outputs[block_idx]; 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci if (block.kind & block_kind_loop_header) 105bf215546Sopenharmony_ci op = state->outputs[block_idx]; 106bf215546Sopenharmony_ci else 107bf215546Sopenharmony_ci op = Operand(Temp(program->allocateTmp(program->lane_mask))); 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci /* create phi */ 110bf215546Sopenharmony_ci aco_ptr<Pseudo_instruction> phi{ 111bf215546Sopenharmony_ci create_instruction<Pseudo_instruction>(aco_opcode::p_linear_phi, Format::PSEUDO, pred, 1)}; 112bf215546Sopenharmony_ci for (unsigned i = 0; i < pred; i++) 113bf215546Sopenharmony_ci phi->operands[i] = ops[i]; 114bf215546Sopenharmony_ci phi->definitions[0] = Definition(op.getTemp()); 115bf215546Sopenharmony_ci block.instructions.emplace(block.instructions.begin(), std::move(phi)); 116bf215546Sopenharmony_ci } 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci assert(op.size() == program->lane_mask.size()); 119bf215546Sopenharmony_ci return op; 120bf215546Sopenharmony_ci} 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_civoid 123bf215546Sopenharmony_ciinsert_before_logical_end(Block* block, aco_ptr<Instruction> instr) 124bf215546Sopenharmony_ci{ 125bf215546Sopenharmony_ci auto IsLogicalEnd = [](const aco_ptr<Instruction>& inst) -> bool 126bf215546Sopenharmony_ci { return inst->opcode == aco_opcode::p_logical_end; }; 127bf215546Sopenharmony_ci auto it = std::find_if(block->instructions.crbegin(), block->instructions.crend(), IsLogicalEnd); 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci if (it == block->instructions.crend()) { 130bf215546Sopenharmony_ci assert(block->instructions.back()->isBranch()); 131bf215546Sopenharmony_ci block->instructions.insert(std::prev(block->instructions.end()), std::move(instr)); 132bf215546Sopenharmony_ci } else { 133bf215546Sopenharmony_ci block->instructions.insert(std::prev(it.base()), std::move(instr)); 134bf215546Sopenharmony_ci } 135bf215546Sopenharmony_ci} 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_civoid 138bf215546Sopenharmony_cibuild_merge_code(Program* program, ssa_state* state, Block* block, Operand cur) 139bf215546Sopenharmony_ci{ 140bf215546Sopenharmony_ci unsigned block_idx = block->index; 141bf215546Sopenharmony_ci Definition dst = Definition(state->outputs[block_idx].getTemp()); 142bf215546Sopenharmony_ci Operand prev = get_ssa(program, block_idx, state, true); 143bf215546Sopenharmony_ci if (cur.isUndefined()) 144bf215546Sopenharmony_ci cur = Operand::zero(program->lane_mask.bytes()); 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci Builder bld(program); 147bf215546Sopenharmony_ci auto IsLogicalEnd = [](const aco_ptr<Instruction>& instr) -> bool 148bf215546Sopenharmony_ci { return instr->opcode == aco_opcode::p_logical_end; }; 149bf215546Sopenharmony_ci auto it = std::find_if(block->instructions.rbegin(), block->instructions.rend(), IsLogicalEnd); 150bf215546Sopenharmony_ci assert(it != block->instructions.rend()); 151bf215546Sopenharmony_ci bld.reset(&block->instructions, std::prev(it.base())); 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci pred_defined defined = state->any_pred_defined[block_idx]; 154bf215546Sopenharmony_ci if (defined == pred_defined::undef) { 155bf215546Sopenharmony_ci return; 156bf215546Sopenharmony_ci } else if (defined == pred_defined::const_0) { 157bf215546Sopenharmony_ci bld.sop2(Builder::s_and, dst, bld.def(s1, scc), cur, Operand(exec, bld.lm)); 158bf215546Sopenharmony_ci return; 159bf215546Sopenharmony_ci } else if (defined == pred_defined::const_1) { 160bf215546Sopenharmony_ci bld.sop2(Builder::s_orn2, dst, bld.def(s1, scc), cur, Operand(exec, bld.lm)); 161bf215546Sopenharmony_ci return; 162bf215546Sopenharmony_ci } 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci assert(prev.isTemp()); 165bf215546Sopenharmony_ci /* simpler sequence in case prev has only zeros in disabled lanes */ 166bf215546Sopenharmony_ci if ((defined & pred_defined::zero) == pred_defined::zero) { 167bf215546Sopenharmony_ci if (cur.isConstant()) { 168bf215546Sopenharmony_ci if (!cur.constantValue()) { 169bf215546Sopenharmony_ci bld.copy(dst, prev); 170bf215546Sopenharmony_ci return; 171bf215546Sopenharmony_ci } 172bf215546Sopenharmony_ci cur = Operand(exec, bld.lm); 173bf215546Sopenharmony_ci } else { 174bf215546Sopenharmony_ci cur = 175bf215546Sopenharmony_ci bld.sop2(Builder::s_and, bld.def(bld.lm), bld.def(s1, scc), cur, Operand(exec, bld.lm)); 176bf215546Sopenharmony_ci } 177bf215546Sopenharmony_ci bld.sop2(Builder::s_or, dst, bld.def(s1, scc), prev, cur); 178bf215546Sopenharmony_ci return; 179bf215546Sopenharmony_ci } 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci if (cur.isConstant()) { 182bf215546Sopenharmony_ci if (cur.constantValue()) 183bf215546Sopenharmony_ci bld.sop2(Builder::s_or, dst, bld.def(s1, scc), prev, Operand(exec, bld.lm)); 184bf215546Sopenharmony_ci else 185bf215546Sopenharmony_ci bld.sop2(Builder::s_andn2, dst, bld.def(s1, scc), prev, Operand(exec, bld.lm)); 186bf215546Sopenharmony_ci return; 187bf215546Sopenharmony_ci } 188bf215546Sopenharmony_ci prev = 189bf215546Sopenharmony_ci bld.sop2(Builder::s_andn2, bld.def(bld.lm), bld.def(s1, scc), prev, Operand(exec, bld.lm)); 190bf215546Sopenharmony_ci cur = bld.sop2(Builder::s_and, bld.def(bld.lm), bld.def(s1, scc), cur, Operand(exec, bld.lm)); 191bf215546Sopenharmony_ci bld.sop2(Builder::s_or, dst, bld.def(s1, scc), prev, cur); 192bf215546Sopenharmony_ci return; 193bf215546Sopenharmony_ci} 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_civoid 196bf215546Sopenharmony_ciinit_any_pred_defined(Program* program, ssa_state* state, Block* block, aco_ptr<Instruction>& phi) 197bf215546Sopenharmony_ci{ 198bf215546Sopenharmony_ci std::fill(state->any_pred_defined.begin(), state->any_pred_defined.end(), pred_defined::undef); 199bf215546Sopenharmony_ci for (unsigned i = 0; i < block->logical_preds.size(); i++) { 200bf215546Sopenharmony_ci if (phi->operands[i].isUndefined()) 201bf215546Sopenharmony_ci continue; 202bf215546Sopenharmony_ci pred_defined defined = pred_defined::temp; 203bf215546Sopenharmony_ci if (phi->operands[i].isConstant()) 204bf215546Sopenharmony_ci defined = phi->operands[i].constantValue() ? pred_defined::const_1 : pred_defined::const_0; 205bf215546Sopenharmony_ci for (unsigned succ : program->blocks[block->logical_preds[i]].linear_succs) 206bf215546Sopenharmony_ci state->any_pred_defined[succ] |= defined; 207bf215546Sopenharmony_ci } 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci unsigned start = block->logical_preds[0]; 210bf215546Sopenharmony_ci unsigned end = block->index; 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci /* for loop exit phis, start at the loop header */ 213bf215546Sopenharmony_ci if (block->kind & block_kind_loop_exit) { 214bf215546Sopenharmony_ci while (program->blocks[start - 1].loop_nest_depth >= state->loop_nest_depth) 215bf215546Sopenharmony_ci start--; 216bf215546Sopenharmony_ci /* If the loop-header has a back-edge, we need to insert a phi. 217bf215546Sopenharmony_ci * This will contain a defined value */ 218bf215546Sopenharmony_ci if (program->blocks[start].linear_preds.size() > 1) 219bf215546Sopenharmony_ci state->any_pred_defined[start] = pred_defined::temp; 220bf215546Sopenharmony_ci } 221bf215546Sopenharmony_ci /* for loop header phis, end at the loop exit */ 222bf215546Sopenharmony_ci if (block->kind & block_kind_loop_header) { 223bf215546Sopenharmony_ci while (program->blocks[end].loop_nest_depth >= state->loop_nest_depth) 224bf215546Sopenharmony_ci end++; 225bf215546Sopenharmony_ci /* don't propagate the incoming value */ 226bf215546Sopenharmony_ci state->any_pred_defined[block->index] = pred_defined::undef; 227bf215546Sopenharmony_ci } 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci /* add dominating zero: this allows to emit simpler merge sequences 230bf215546Sopenharmony_ci * if we can ensure that all disabled lanes are always zero on incoming values */ 231bf215546Sopenharmony_ci // TODO: find more occasions where pred_defined::zero is beneficial (e.g. with 2+ temp merges) 232bf215546Sopenharmony_ci if (block->kind & block_kind_loop_exit) { 233bf215546Sopenharmony_ci /* zero the loop-carried variable */ 234bf215546Sopenharmony_ci if (program->blocks[start].linear_preds.size() > 1) { 235bf215546Sopenharmony_ci state->any_pred_defined[start] |= pred_defined::zero; 236bf215546Sopenharmony_ci // TODO: emit this zero explicitly 237bf215546Sopenharmony_ci state->any_pred_defined[start - 1] = pred_defined::const_0; 238bf215546Sopenharmony_ci } 239bf215546Sopenharmony_ci } 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci for (unsigned j = start; j < end; j++) { 242bf215546Sopenharmony_ci if (state->any_pred_defined[j] == pred_defined::undef) 243bf215546Sopenharmony_ci continue; 244bf215546Sopenharmony_ci for (unsigned succ : program->blocks[j].linear_succs) 245bf215546Sopenharmony_ci state->any_pred_defined[succ] |= state->any_pred_defined[j]; 246bf215546Sopenharmony_ci } 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci state->any_pred_defined[block->index] = pred_defined::undef; 249bf215546Sopenharmony_ci} 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_civoid 252bf215546Sopenharmony_cilower_divergent_bool_phi(Program* program, ssa_state* state, Block* block, 253bf215546Sopenharmony_ci aco_ptr<Instruction>& phi) 254bf215546Sopenharmony_ci{ 255bf215546Sopenharmony_ci Builder bld(program); 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci if (!state->checked_preds_for_uniform) { 258bf215546Sopenharmony_ci state->all_preds_uniform = !(block->kind & block_kind_merge) && 259bf215546Sopenharmony_ci block->linear_preds.size() == block->logical_preds.size(); 260bf215546Sopenharmony_ci for (unsigned pred : block->logical_preds) 261bf215546Sopenharmony_ci state->all_preds_uniform = 262bf215546Sopenharmony_ci state->all_preds_uniform && (program->blocks[pred].kind & block_kind_uniform); 263bf215546Sopenharmony_ci state->checked_preds_for_uniform = true; 264bf215546Sopenharmony_ci } 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci if (state->all_preds_uniform) { 267bf215546Sopenharmony_ci phi->opcode = aco_opcode::p_linear_phi; 268bf215546Sopenharmony_ci return; 269bf215546Sopenharmony_ci } 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_ci /* do this here to avoid resizing in case of no boolean phis */ 272bf215546Sopenharmony_ci state->visited.resize(program->blocks.size()); 273bf215546Sopenharmony_ci state->outputs.resize(program->blocks.size()); 274bf215546Sopenharmony_ci state->any_pred_defined.resize(program->blocks.size()); 275bf215546Sopenharmony_ci state->loop_nest_depth = block->loop_nest_depth; 276bf215546Sopenharmony_ci if (block->kind & block_kind_loop_exit) 277bf215546Sopenharmony_ci state->loop_nest_depth += 1; 278bf215546Sopenharmony_ci std::fill(state->visited.begin(), state->visited.end(), false); 279bf215546Sopenharmony_ci init_any_pred_defined(program, state, block, phi); 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci for (unsigned i = 0; i < phi->operands.size(); i++) { 282bf215546Sopenharmony_ci unsigned pred = block->logical_preds[i]; 283bf215546Sopenharmony_ci if (state->any_pred_defined[pred] != pred_defined::undef) 284bf215546Sopenharmony_ci state->outputs[pred] = Operand(bld.tmp(bld.lm)); 285bf215546Sopenharmony_ci else 286bf215546Sopenharmony_ci state->outputs[pred] = phi->operands[i]; 287bf215546Sopenharmony_ci assert(state->outputs[pred].size() == bld.lm.size()); 288bf215546Sopenharmony_ci state->visited[pred] = true; 289bf215546Sopenharmony_ci } 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci for (unsigned i = 0; i < phi->operands.size(); i++) 292bf215546Sopenharmony_ci build_merge_code(program, state, &program->blocks[block->logical_preds[i]], phi->operands[i]); 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci unsigned num_preds = block->linear_preds.size(); 295bf215546Sopenharmony_ci if (phi->operands.size() != num_preds) { 296bf215546Sopenharmony_ci Pseudo_instruction* new_phi{create_instruction<Pseudo_instruction>( 297bf215546Sopenharmony_ci aco_opcode::p_linear_phi, Format::PSEUDO, num_preds, 1)}; 298bf215546Sopenharmony_ci new_phi->definitions[0] = phi->definitions[0]; 299bf215546Sopenharmony_ci phi.reset(new_phi); 300bf215546Sopenharmony_ci } else { 301bf215546Sopenharmony_ci phi->opcode = aco_opcode::p_linear_phi; 302bf215546Sopenharmony_ci } 303bf215546Sopenharmony_ci assert(phi->operands.size() == num_preds); 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci for (unsigned i = 0; i < num_preds; i++) 306bf215546Sopenharmony_ci phi->operands[i] = get_ssa(program, block->linear_preds[i], state, false); 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci return; 309bf215546Sopenharmony_ci} 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_civoid 312bf215546Sopenharmony_cilower_subdword_phis(Program* program, Block* block, aco_ptr<Instruction>& phi) 313bf215546Sopenharmony_ci{ 314bf215546Sopenharmony_ci Builder bld(program); 315bf215546Sopenharmony_ci for (unsigned i = 0; i < phi->operands.size(); i++) { 316bf215546Sopenharmony_ci if (phi->operands[i].isUndefined()) 317bf215546Sopenharmony_ci continue; 318bf215546Sopenharmony_ci if (phi->operands[i].regClass() == phi->definitions[0].regClass()) 319bf215546Sopenharmony_ci continue; 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci assert(phi->operands[i].isTemp()); 322bf215546Sopenharmony_ci Block* pred = &program->blocks[block->logical_preds[i]]; 323bf215546Sopenharmony_ci Temp phi_src = phi->operands[i].getTemp(); 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci assert(phi_src.regClass().type() == RegType::sgpr); 326bf215546Sopenharmony_ci Temp tmp = bld.tmp(RegClass(RegType::vgpr, phi_src.size())); 327bf215546Sopenharmony_ci insert_before_logical_end(pred, bld.copy(Definition(tmp), phi_src).get_ptr()); 328bf215546Sopenharmony_ci Temp new_phi_src = bld.tmp(phi->definitions[0].regClass()); 329bf215546Sopenharmony_ci insert_before_logical_end(pred, bld.pseudo(aco_opcode::p_extract_vector, 330bf215546Sopenharmony_ci Definition(new_phi_src), tmp, Operand::zero()) 331bf215546Sopenharmony_ci .get_ptr()); 332bf215546Sopenharmony_ci 333bf215546Sopenharmony_ci phi->operands[i].setTemp(new_phi_src); 334bf215546Sopenharmony_ci } 335bf215546Sopenharmony_ci return; 336bf215546Sopenharmony_ci} 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_civoid 339bf215546Sopenharmony_cilower_phis(Program* program) 340bf215546Sopenharmony_ci{ 341bf215546Sopenharmony_ci ssa_state state; 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci for (Block& block : program->blocks) { 344bf215546Sopenharmony_ci state.checked_preds_for_uniform = false; 345bf215546Sopenharmony_ci for (aco_ptr<Instruction>& phi : block.instructions) { 346bf215546Sopenharmony_ci if (phi->opcode == aco_opcode::p_phi) { 347bf215546Sopenharmony_ci assert(program->wave_size == 64 ? phi->definitions[0].regClass() != s1 348bf215546Sopenharmony_ci : phi->definitions[0].regClass() != s2); 349bf215546Sopenharmony_ci if (phi->definitions[0].regClass() == program->lane_mask) 350bf215546Sopenharmony_ci lower_divergent_bool_phi(program, &state, &block, phi); 351bf215546Sopenharmony_ci else if (phi->definitions[0].regClass().is_subdword()) 352bf215546Sopenharmony_ci lower_subdword_phis(program, &block, phi); 353bf215546Sopenharmony_ci } else if (!is_phi(phi)) { 354bf215546Sopenharmony_ci break; 355bf215546Sopenharmony_ci } 356bf215546Sopenharmony_ci } 357bf215546Sopenharmony_ci } 358bf215546Sopenharmony_ci} 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_ci} // namespace aco 361