1bf215546Sopenharmony_ci/* -*- mesa-c++ -*- 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright (c) 2022 Collabora LTD 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Author: Gert Wollny <gert.wollny@collabora.com> 6bf215546Sopenharmony_ci * 7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 9bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 10bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 11bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 12bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 15bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 16bf215546Sopenharmony_ci * Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 22bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "sfn_optimizer.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "sfn_instr_alugroup.h" 30bf215546Sopenharmony_ci#include "sfn_instr_controlflow.h" 31bf215546Sopenharmony_ci#include "sfn_instr_export.h" 32bf215546Sopenharmony_ci#include "sfn_instr_tex.h" 33bf215546Sopenharmony_ci#include "sfn_instr_fetch.h" 34bf215546Sopenharmony_ci#include "sfn_instr_lds.h" 35bf215546Sopenharmony_ci#include "sfn_peephole.h" 36bf215546Sopenharmony_ci#include "sfn_debug.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#include <sstream> 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_cinamespace r600 { 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_cibool optimize(Shader& shader) 43bf215546Sopenharmony_ci{ 44bf215546Sopenharmony_ci bool progress; 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci sfn_log << SfnLog::opt << "Shader before optimization\n"; 47bf215546Sopenharmony_ci if (sfn_log.has_debug_flag(SfnLog::opt)) { 48bf215546Sopenharmony_ci std::stringstream ss; 49bf215546Sopenharmony_ci shader.print(ss); 50bf215546Sopenharmony_ci sfn_log << ss.str() << "\n\n"; 51bf215546Sopenharmony_ci } 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci do { 54bf215546Sopenharmony_ci progress = false; 55bf215546Sopenharmony_ci progress |= copy_propagation_fwd(shader); 56bf215546Sopenharmony_ci progress |= dead_code_elimination(shader); 57bf215546Sopenharmony_ci progress |= copy_propagation_backward(shader); 58bf215546Sopenharmony_ci progress |= dead_code_elimination(shader); 59bf215546Sopenharmony_ci progress |= simplify_source_vectors(shader); 60bf215546Sopenharmony_ci progress |= peephole(shader); 61bf215546Sopenharmony_ci progress |= dead_code_elimination(shader); 62bf215546Sopenharmony_ci } while (progress); 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci return progress; 65bf215546Sopenharmony_ci} 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ciclass DCEVisitor : public InstrVisitor { 68bf215546Sopenharmony_cipublic: 69bf215546Sopenharmony_ci DCEVisitor(); 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci void visit(AluInstr *instr) override; 72bf215546Sopenharmony_ci void visit(AluGroup *instr) override; 73bf215546Sopenharmony_ci void visit(TexInstr *instr) override; 74bf215546Sopenharmony_ci void visit(ExportInstr *instr) override {(void)instr;}; 75bf215546Sopenharmony_ci void visit(FetchInstr *instr) override; 76bf215546Sopenharmony_ci void visit(Block *instr) override; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci void visit(ControlFlowInstr *instr) override {(void)instr;}; 79bf215546Sopenharmony_ci void visit(IfInstr *instr) override {(void)instr;}; 80bf215546Sopenharmony_ci void visit(ScratchIOInstr *instr) override {(void)instr;}; 81bf215546Sopenharmony_ci void visit(StreamOutInstr *instr) override {(void)instr;}; 82bf215546Sopenharmony_ci void visit(MemRingOutInstr *instr) override {(void)instr;}; 83bf215546Sopenharmony_ci void visit(EmitVertexInstr *instr) override {(void)instr;}; 84bf215546Sopenharmony_ci void visit(GDSInstr *instr) override {(void)instr;}; 85bf215546Sopenharmony_ci void visit(WriteTFInstr *instr) override {(void)instr;}; 86bf215546Sopenharmony_ci void visit(LDSAtomicInstr *instr) override {(void)instr;}; 87bf215546Sopenharmony_ci void visit(LDSReadInstr *instr) override; 88bf215546Sopenharmony_ci void visit(RatInstr *instr) override {(void)instr;}; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci bool progress; 92bf215546Sopenharmony_ci}; 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_cibool dead_code_elimination(Shader& shader) 95bf215546Sopenharmony_ci{ 96bf215546Sopenharmony_ci DCEVisitor dce; 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci do { 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci sfn_log << SfnLog::opt << "start dce run\n"; 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci dce.progress = false; 103bf215546Sopenharmony_ci for (auto& b : shader.func()) 104bf215546Sopenharmony_ci b->accept(dce); 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci sfn_log << SfnLog::opt << "finished dce run\n\n"; 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci } while (dce.progress); 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci sfn_log << SfnLog::opt << "Shader after DCE\n"; 111bf215546Sopenharmony_ci if (sfn_log.has_debug_flag(SfnLog::opt)) { 112bf215546Sopenharmony_ci std::stringstream ss; 113bf215546Sopenharmony_ci shader.print(ss); 114bf215546Sopenharmony_ci sfn_log << ss.str() << "\n\n"; 115bf215546Sopenharmony_ci } 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci return dce.progress; 118bf215546Sopenharmony_ci} 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ciDCEVisitor::DCEVisitor():progress(false) 121bf215546Sopenharmony_ci{ 122bf215546Sopenharmony_ci} 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_civoid DCEVisitor::visit(AluInstr *instr) 125bf215546Sopenharmony_ci{ 126bf215546Sopenharmony_ci sfn_log << SfnLog::opt << "DCE: visit '" << *instr; 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci if (instr->has_instr_flag(Instr::dead)) 129bf215546Sopenharmony_ci return; 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci if (instr->dest() && 132bf215546Sopenharmony_ci (instr->dest()->has_uses() || !instr->dest()->is_ssa()) ) { 133bf215546Sopenharmony_ci sfn_log << SfnLog::opt << " dest used\n"; 134bf215546Sopenharmony_ci return; 135bf215546Sopenharmony_ci } 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci switch (instr->opcode()) { 138bf215546Sopenharmony_ci case op2_kille: 139bf215546Sopenharmony_ci case op2_killne: 140bf215546Sopenharmony_ci case op2_kille_int: 141bf215546Sopenharmony_ci case op2_killne_int: 142bf215546Sopenharmony_ci case op2_killge: 143bf215546Sopenharmony_ci case op2_killge_int: 144bf215546Sopenharmony_ci case op2_killge_uint: 145bf215546Sopenharmony_ci case op2_killgt: 146bf215546Sopenharmony_ci case op2_killgt_int: 147bf215546Sopenharmony_ci case op2_killgt_uint: 148bf215546Sopenharmony_ci case op0_group_barrier: 149bf215546Sopenharmony_ci sfn_log << SfnLog::opt << " never kill\n"; 150bf215546Sopenharmony_ci return; 151bf215546Sopenharmony_ci default: 152bf215546Sopenharmony_ci ; 153bf215546Sopenharmony_ci } 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci bool dead = instr->set_dead(); 156bf215546Sopenharmony_ci sfn_log << SfnLog::opt << (dead ? "dead" : "alive") << "\n"; 157bf215546Sopenharmony_ci progress |= dead; 158bf215546Sopenharmony_ci} 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_civoid DCEVisitor::visit(LDSReadInstr *instr) 161bf215546Sopenharmony_ci{ 162bf215546Sopenharmony_ci sfn_log << SfnLog::opt << "visit " << *instr << "\n"; 163bf215546Sopenharmony_ci progress |= instr->remove_unused_components(); 164bf215546Sopenharmony_ci} 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_civoid DCEVisitor::visit(AluGroup *instr) 167bf215546Sopenharmony_ci{ 168bf215546Sopenharmony_ci /* Groups are created because the instructions are used together 169bf215546Sopenharmony_ci * so don't try to eliminate code there */ 170bf215546Sopenharmony_ci (void)instr; 171bf215546Sopenharmony_ci} 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_civoid DCEVisitor::visit(TexInstr *instr) 174bf215546Sopenharmony_ci{ 175bf215546Sopenharmony_ci auto& dest = instr->dst(); 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci bool has_uses = false; 178bf215546Sopenharmony_ci RegisterVec4::Swizzle swz = instr->all_dest_swizzle(); 179bf215546Sopenharmony_ci for (int i = 0; i < 4; ++i) { 180bf215546Sopenharmony_ci if (!dest[i]->has_uses()) 181bf215546Sopenharmony_ci swz[i] = 7; 182bf215546Sopenharmony_ci else 183bf215546Sopenharmony_ci has_uses |= true; 184bf215546Sopenharmony_ci } 185bf215546Sopenharmony_ci instr->set_dest_swizzle(swz); 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci if (has_uses) 188bf215546Sopenharmony_ci return; 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci progress |= instr->set_dead(); 191bf215546Sopenharmony_ci} 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_civoid DCEVisitor::visit(FetchInstr *instr) 194bf215546Sopenharmony_ci{ 195bf215546Sopenharmony_ci auto& dest = instr->dst(); 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci bool has_uses = false; 198bf215546Sopenharmony_ci RegisterVec4::Swizzle swz = instr->all_dest_swizzle(); 199bf215546Sopenharmony_ci for (int i = 0; i < 4; ++i) { 200bf215546Sopenharmony_ci if (!dest[i]->has_uses()) 201bf215546Sopenharmony_ci swz[i] = 7; 202bf215546Sopenharmony_ci else 203bf215546Sopenharmony_ci has_uses |= true; 204bf215546Sopenharmony_ci } 205bf215546Sopenharmony_ci instr->set_dest_swizzle(swz); 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci if (has_uses) 208bf215546Sopenharmony_ci return; 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci sfn_log << SfnLog::opt << "set dead: " << *instr << "\n"; 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci progress |= instr->set_dead(); 213bf215546Sopenharmony_ci} 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_civoid DCEVisitor::visit(Block *block) 216bf215546Sopenharmony_ci{ 217bf215546Sopenharmony_ci auto i = block->begin(); 218bf215546Sopenharmony_ci auto e = block->end(); 219bf215546Sopenharmony_ci while (i != e) { 220bf215546Sopenharmony_ci auto n = i++; 221bf215546Sopenharmony_ci if (!(*n)->keep()) { 222bf215546Sopenharmony_ci (*n)->accept(*this); 223bf215546Sopenharmony_ci if ((*n)->is_dead()) { 224bf215546Sopenharmony_ci block->erase(n); 225bf215546Sopenharmony_ci } 226bf215546Sopenharmony_ci } 227bf215546Sopenharmony_ci } 228bf215546Sopenharmony_ci} 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_civoid visit(ControlFlowInstr *instr) 231bf215546Sopenharmony_ci{ 232bf215546Sopenharmony_ci (void)instr; 233bf215546Sopenharmony_ci} 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_civoid visit(IfInstr *instr) 236bf215546Sopenharmony_ci{ 237bf215546Sopenharmony_ci (void)instr; 238bf215546Sopenharmony_ci} 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ciclass CopyPropFwdVisitor : public InstrVisitor { 241bf215546Sopenharmony_cipublic: 242bf215546Sopenharmony_ci CopyPropFwdVisitor(); 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci void visit(AluInstr *instr) override; 245bf215546Sopenharmony_ci void visit(AluGroup *instr) override; 246bf215546Sopenharmony_ci void visit(TexInstr *instr) override; 247bf215546Sopenharmony_ci void visit(ExportInstr *instr) override {(void)instr;} 248bf215546Sopenharmony_ci void visit(FetchInstr *instr) override; 249bf215546Sopenharmony_ci void visit(Block *instr) override; 250bf215546Sopenharmony_ci void visit(ControlFlowInstr *instr) override {(void)instr;} 251bf215546Sopenharmony_ci void visit(IfInstr *instr) override {(void)instr;} 252bf215546Sopenharmony_ci void visit(ScratchIOInstr *instr) override {(void)instr;} 253bf215546Sopenharmony_ci void visit(StreamOutInstr *instr) override {(void)instr;} 254bf215546Sopenharmony_ci void visit(MemRingOutInstr *instr) override {(void)instr;} 255bf215546Sopenharmony_ci void visit(EmitVertexInstr *instr) override {(void)instr;} 256bf215546Sopenharmony_ci void visit(GDSInstr *instr) override {(void)instr;}; 257bf215546Sopenharmony_ci void visit(WriteTFInstr *instr) override {(void)instr;}; 258bf215546Sopenharmony_ci void visit(RatInstr *instr) override {(void)instr;}; 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci // TODO: these two should use copy propagation 261bf215546Sopenharmony_ci void visit(LDSAtomicInstr *instr) override {(void)instr;}; 262bf215546Sopenharmony_ci void visit(LDSReadInstr *instr) override {(void)instr;}; 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci bool progress; 265bf215546Sopenharmony_ci}; 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ciclass CopyPropBackVisitor : public InstrVisitor { 269bf215546Sopenharmony_cipublic: 270bf215546Sopenharmony_ci CopyPropBackVisitor(); 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci void visit(AluInstr *instr) override; 273bf215546Sopenharmony_ci void visit(AluGroup *instr) override; 274bf215546Sopenharmony_ci void visit(TexInstr *instr) override; 275bf215546Sopenharmony_ci void visit(ExportInstr *instr) override {(void)instr;} 276bf215546Sopenharmony_ci void visit(FetchInstr *instr) override; 277bf215546Sopenharmony_ci void visit(Block *instr) override; 278bf215546Sopenharmony_ci void visit(ControlFlowInstr *instr) override {(void)instr;} 279bf215546Sopenharmony_ci void visit(IfInstr *instr) override {(void)instr;} 280bf215546Sopenharmony_ci void visit(ScratchIOInstr *instr) override {(void)instr;} 281bf215546Sopenharmony_ci void visit(StreamOutInstr *instr) override {(void)instr;} 282bf215546Sopenharmony_ci void visit(MemRingOutInstr *instr) override {(void)instr;} 283bf215546Sopenharmony_ci void visit(EmitVertexInstr *instr) override {(void)instr;} 284bf215546Sopenharmony_ci void visit(GDSInstr *instr) override {(void)instr;}; 285bf215546Sopenharmony_ci void visit(WriteTFInstr *instr) override {(void)instr;}; 286bf215546Sopenharmony_ci void visit(LDSAtomicInstr *instr) override {(void)instr;}; 287bf215546Sopenharmony_ci void visit(LDSReadInstr *instr) override {(void)instr;}; 288bf215546Sopenharmony_ci void visit(RatInstr *instr) override {(void)instr;}; 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ci bool progress; 291bf215546Sopenharmony_ci}; 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_cibool copy_propagation_fwd(Shader& shader) 294bf215546Sopenharmony_ci{ 295bf215546Sopenharmony_ci auto& root = shader.func(); 296bf215546Sopenharmony_ci CopyPropFwdVisitor copy_prop; 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci do { 299bf215546Sopenharmony_ci copy_prop.progress = false; 300bf215546Sopenharmony_ci for (auto b : root) 301bf215546Sopenharmony_ci b->accept(copy_prop); 302bf215546Sopenharmony_ci } while (copy_prop.progress); 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci sfn_log << SfnLog::opt << "Shader after Copy Prop forward\n"; 305bf215546Sopenharmony_ci if (sfn_log.has_debug_flag(SfnLog::opt)) { 306bf215546Sopenharmony_ci std::stringstream ss; 307bf215546Sopenharmony_ci shader.print(ss); 308bf215546Sopenharmony_ci sfn_log << ss.str() << "\n\n"; 309bf215546Sopenharmony_ci } 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_ci return copy_prop.progress; 313bf215546Sopenharmony_ci} 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_cibool copy_propagation_backward(Shader& shader) 316bf215546Sopenharmony_ci{ 317bf215546Sopenharmony_ci CopyPropBackVisitor copy_prop; 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci do { 320bf215546Sopenharmony_ci copy_prop.progress = false; 321bf215546Sopenharmony_ci for (auto b: shader.func()) 322bf215546Sopenharmony_ci b->accept(copy_prop); 323bf215546Sopenharmony_ci } while (copy_prop.progress); 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci sfn_log << SfnLog::opt << "Shader after Copy Prop backwards\n"; 326bf215546Sopenharmony_ci if (sfn_log.has_debug_flag(SfnLog::opt)) { 327bf215546Sopenharmony_ci std::stringstream ss; 328bf215546Sopenharmony_ci shader.print(ss); 329bf215546Sopenharmony_ci sfn_log << ss.str() << "\n\n"; 330bf215546Sopenharmony_ci } 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci return copy_prop.progress; 333bf215546Sopenharmony_ci} 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_ciCopyPropFwdVisitor::CopyPropFwdVisitor(): 336bf215546Sopenharmony_ci progress(false) 337bf215546Sopenharmony_ci{} 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_civoid CopyPropFwdVisitor::visit(AluInstr *instr) 340bf215546Sopenharmony_ci{ 341bf215546Sopenharmony_ci sfn_log << SfnLog::opt << "CopyPropFwdVisitor:[" 342bf215546Sopenharmony_ci << instr->block_id() << ":" << instr->index() << "] " << *instr 343bf215546Sopenharmony_ci << " dset=" << instr->dest() << " "; 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci if (instr->dest()) { 348bf215546Sopenharmony_ci sfn_log << SfnLog::opt << "has uses; " 349bf215546Sopenharmony_ci << instr->dest()->uses().size(); 350bf215546Sopenharmony_ci } 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci sfn_log << SfnLog::opt << "\n"; 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ci if (!instr->can_propagate_src()) { 355bf215546Sopenharmony_ci return; 356bf215546Sopenharmony_ci } 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci auto src = instr->psrc(0); 359bf215546Sopenharmony_ci auto dest = instr->dest(); 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci for (auto& i : instr->dest()->uses()) { 362bf215546Sopenharmony_ci /* SSA can always be propagated, registers only in the same block 363bf215546Sopenharmony_ci * and only if they are not assigned to more than once */ 364bf215546Sopenharmony_ci if (dest->is_ssa() || 365bf215546Sopenharmony_ci (instr->block_id() == i->block_id() && 366bf215546Sopenharmony_ci instr->index() < i->index() && 367bf215546Sopenharmony_ci dest->uses().size() == 1)) { 368bf215546Sopenharmony_ci sfn_log << SfnLog::opt << " Try replace in " 369bf215546Sopenharmony_ci << i->block_id() << ":" << i->index() 370bf215546Sopenharmony_ci << *i<< "\n"; 371bf215546Sopenharmony_ci progress |= i->replace_source(dest, src); 372bf215546Sopenharmony_ci } 373bf215546Sopenharmony_ci } 374bf215546Sopenharmony_ci if (instr->dest()) { 375bf215546Sopenharmony_ci sfn_log << SfnLog::opt << "has uses; " 376bf215546Sopenharmony_ci << instr->dest()->uses().size(); 377bf215546Sopenharmony_ci } 378bf215546Sopenharmony_ci sfn_log << SfnLog::opt << " done\n"; 379bf215546Sopenharmony_ci} 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_civoid CopyPropFwdVisitor::visit(AluGroup *instr) 383bf215546Sopenharmony_ci{ 384bf215546Sopenharmony_ci (void)instr; 385bf215546Sopenharmony_ci} 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_civoid CopyPropFwdVisitor::visit(TexInstr *instr) 388bf215546Sopenharmony_ci{ 389bf215546Sopenharmony_ci (void)instr; 390bf215546Sopenharmony_ci} 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_civoid CopyPropFwdVisitor::visit(FetchInstr *instr) 393bf215546Sopenharmony_ci{ 394bf215546Sopenharmony_ci (void)instr; 395bf215546Sopenharmony_ci} 396bf215546Sopenharmony_ci 397bf215546Sopenharmony_civoid CopyPropFwdVisitor::visit(Block *instr) 398bf215546Sopenharmony_ci{ 399bf215546Sopenharmony_ci for (auto& i: *instr) 400bf215546Sopenharmony_ci i->accept(*this); 401bf215546Sopenharmony_ci} 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ciCopyPropBackVisitor::CopyPropBackVisitor(): 404bf215546Sopenharmony_ci progress(false) 405bf215546Sopenharmony_ci{ 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ci} 408bf215546Sopenharmony_ci 409bf215546Sopenharmony_civoid CopyPropBackVisitor::visit(AluInstr *instr) 410bf215546Sopenharmony_ci{ 411bf215546Sopenharmony_ci bool local_progress = false; 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_ci sfn_log << SfnLog::opt << "CopyPropBackVisitor:[" 414bf215546Sopenharmony_ci << instr->block_id() << ":" << instr->index() << "] " << *instr << "\n"; 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci 417bf215546Sopenharmony_ci if (!instr->can_propagate_dest()) { 418bf215546Sopenharmony_ci return; 419bf215546Sopenharmony_ci } 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_ci auto src_reg = instr->psrc(0)->as_register(); 422bf215546Sopenharmony_ci if (!src_reg) { 423bf215546Sopenharmony_ci return; 424bf215546Sopenharmony_ci } 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ci if (src_reg->uses().size() > 1) 427bf215546Sopenharmony_ci return; 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci auto dest = instr->dest(); 430bf215546Sopenharmony_ci if (!dest || 431bf215546Sopenharmony_ci !instr->has_alu_flag(alu_write)) { 432bf215546Sopenharmony_ci return; 433bf215546Sopenharmony_ci } 434bf215546Sopenharmony_ci 435bf215546Sopenharmony_ci if (!dest->is_ssa() && dest->parents().size() > 1) 436bf215546Sopenharmony_ci return; 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_ci for (auto& i: src_reg->parents()) { 439bf215546Sopenharmony_ci sfn_log << SfnLog::opt << "Try replace dest in " 440bf215546Sopenharmony_ci << i->block_id() << ":" << i->index() 441bf215546Sopenharmony_ci << *i<< "\n"; 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci if (i->replace_dest(dest, instr)) { 444bf215546Sopenharmony_ci dest->del_parent(instr); 445bf215546Sopenharmony_ci dest->add_parent(i); 446bf215546Sopenharmony_ci for (auto d : instr->dependend_instr()) { 447bf215546Sopenharmony_ci d->add_required_instr(i); 448bf215546Sopenharmony_ci } 449bf215546Sopenharmony_ci local_progress = true; 450bf215546Sopenharmony_ci } 451bf215546Sopenharmony_ci } 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci if (local_progress) 454bf215546Sopenharmony_ci instr->set_dead(); 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci progress |= local_progress; 457bf215546Sopenharmony_ci} 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_civoid CopyPropBackVisitor::visit(AluGroup *instr) 460bf215546Sopenharmony_ci{ 461bf215546Sopenharmony_ci for (auto& i: *instr) { 462bf215546Sopenharmony_ci if (i) 463bf215546Sopenharmony_ci i->accept(*this); 464bf215546Sopenharmony_ci } 465bf215546Sopenharmony_ci} 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_civoid CopyPropBackVisitor::visit(TexInstr *instr) 468bf215546Sopenharmony_ci{ 469bf215546Sopenharmony_ci (void)instr; 470bf215546Sopenharmony_ci} 471bf215546Sopenharmony_ci 472bf215546Sopenharmony_civoid CopyPropBackVisitor::visit(FetchInstr *instr) 473bf215546Sopenharmony_ci{ 474bf215546Sopenharmony_ci (void)instr; 475bf215546Sopenharmony_ci} 476bf215546Sopenharmony_ci 477bf215546Sopenharmony_civoid CopyPropBackVisitor::visit(Block *instr) 478bf215546Sopenharmony_ci{ 479bf215546Sopenharmony_ci for (auto i = instr->rbegin(); i != instr->rend(); ++i) 480bf215546Sopenharmony_ci if (!(*i)->is_dead()) 481bf215546Sopenharmony_ci (*i)->accept(*this); 482bf215546Sopenharmony_ci} 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ciclass SimplifySourceVecVisitor : public InstrVisitor { 485bf215546Sopenharmony_cipublic: 486bf215546Sopenharmony_ci SimplifySourceVecVisitor():progress(false) {} 487bf215546Sopenharmony_ci 488bf215546Sopenharmony_ci void visit(AluInstr *instr) override{(void)instr;} 489bf215546Sopenharmony_ci void visit(AluGroup *instr) override{(void)instr;} 490bf215546Sopenharmony_ci void visit(TexInstr *instr) override; 491bf215546Sopenharmony_ci void visit(ExportInstr *instr) override; 492bf215546Sopenharmony_ci void visit(FetchInstr *instr) override; 493bf215546Sopenharmony_ci void visit(Block *instr) override; 494bf215546Sopenharmony_ci void visit(ControlFlowInstr *instr) override; 495bf215546Sopenharmony_ci void visit(IfInstr *instr) override; 496bf215546Sopenharmony_ci void visit(ScratchIOInstr *instr) override; 497bf215546Sopenharmony_ci void visit(StreamOutInstr *instr) override; 498bf215546Sopenharmony_ci void visit(MemRingOutInstr *instr) override; 499bf215546Sopenharmony_ci void visit(EmitVertexInstr *instr) override {(void)instr;} 500bf215546Sopenharmony_ci void visit(GDSInstr *instr) override {(void)instr;}; 501bf215546Sopenharmony_ci void visit(WriteTFInstr *instr) override {(void)instr;}; 502bf215546Sopenharmony_ci void visit(LDSAtomicInstr *instr) override {(void)instr;}; 503bf215546Sopenharmony_ci void visit(LDSReadInstr *instr) override {(void)instr;}; 504bf215546Sopenharmony_ci void visit(RatInstr *instr) override {(void)instr;}; 505bf215546Sopenharmony_ci 506bf215546Sopenharmony_ci void replace_src(Instr *instr, RegisterVec4& reg4); 507bf215546Sopenharmony_ci 508bf215546Sopenharmony_ci bool progress; 509bf215546Sopenharmony_ci}; 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_cibool simplify_source_vectors(Shader& sh) 512bf215546Sopenharmony_ci{ 513bf215546Sopenharmony_ci SimplifySourceVecVisitor visitor; 514bf215546Sopenharmony_ci 515bf215546Sopenharmony_ci for (auto b: sh.func()) 516bf215546Sopenharmony_ci b->accept(visitor); 517bf215546Sopenharmony_ci 518bf215546Sopenharmony_ci return visitor.progress; 519bf215546Sopenharmony_ci} 520bf215546Sopenharmony_ci 521bf215546Sopenharmony_civoid SimplifySourceVecVisitor::visit(TexInstr *instr) 522bf215546Sopenharmony_ci{ 523bf215546Sopenharmony_ci if (instr->opcode() != TexInstr::get_resinfo) { 524bf215546Sopenharmony_ci replace_src(instr, instr->src()); 525bf215546Sopenharmony_ci } 526bf215546Sopenharmony_ci} 527bf215546Sopenharmony_ci 528bf215546Sopenharmony_civoid SimplifySourceVecVisitor::visit(ScratchIOInstr *instr) 529bf215546Sopenharmony_ci{ 530bf215546Sopenharmony_ci (void) instr; 531bf215546Sopenharmony_ci} 532bf215546Sopenharmony_ci 533bf215546Sopenharmony_ciclass ReplaceConstSource : public AluInstrVisitor { 534bf215546Sopenharmony_cipublic: 535bf215546Sopenharmony_ci ReplaceConstSource(Instr *old_use_, RegisterVec4& vreg_, int i): 536bf215546Sopenharmony_ci old_use(old_use_), vreg(vreg_), index(i),success(false) {} 537bf215546Sopenharmony_ci 538bf215546Sopenharmony_ci using AluInstrVisitor::visit; 539bf215546Sopenharmony_ci 540bf215546Sopenharmony_ci void visit(AluInstr *alu) override; 541bf215546Sopenharmony_ci 542bf215546Sopenharmony_ci Instr *old_use; 543bf215546Sopenharmony_ci RegisterVec4& vreg; 544bf215546Sopenharmony_ci int index; 545bf215546Sopenharmony_ci bool success; 546bf215546Sopenharmony_ci}; 547bf215546Sopenharmony_ci 548bf215546Sopenharmony_civoid SimplifySourceVecVisitor::visit(ExportInstr *instr) 549bf215546Sopenharmony_ci{ 550bf215546Sopenharmony_ci replace_src(instr, instr->value()); 551bf215546Sopenharmony_ci} 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_civoid SimplifySourceVecVisitor::replace_src(Instr *instr, RegisterVec4& reg4) 554bf215546Sopenharmony_ci{ 555bf215546Sopenharmony_ci for (int i = 0; i < 4; ++i) { 556bf215546Sopenharmony_ci auto s = reg4[i]; 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci if (s->chan() > 3) 559bf215546Sopenharmony_ci continue; 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci if (!s->is_ssa()) 562bf215546Sopenharmony_ci continue; 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_ci /* Cayman trans ops have more then one parent for 565bf215546Sopenharmony_ci * one dest */ 566bf215546Sopenharmony_ci if (s->parents().size() != 1) 567bf215546Sopenharmony_ci continue; 568bf215546Sopenharmony_ci 569bf215546Sopenharmony_ci auto& op = *s->parents().begin(); 570bf215546Sopenharmony_ci 571bf215546Sopenharmony_ci ReplaceConstSource visitor(instr, reg4, i); 572bf215546Sopenharmony_ci 573bf215546Sopenharmony_ci op->accept(visitor); 574bf215546Sopenharmony_ci 575bf215546Sopenharmony_ci progress |= visitor.success; 576bf215546Sopenharmony_ci } 577bf215546Sopenharmony_ci} 578bf215546Sopenharmony_ci 579bf215546Sopenharmony_civoid SimplifySourceVecVisitor::visit(StreamOutInstr *instr) 580bf215546Sopenharmony_ci{ 581bf215546Sopenharmony_ci (void)instr; 582bf215546Sopenharmony_ci} 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_civoid SimplifySourceVecVisitor::visit(MemRingOutInstr *instr) 585bf215546Sopenharmony_ci{ 586bf215546Sopenharmony_ci (void)instr; 587bf215546Sopenharmony_ci} 588bf215546Sopenharmony_ci 589bf215546Sopenharmony_civoid ReplaceConstSource::visit(AluInstr *alu) 590bf215546Sopenharmony_ci{ 591bf215546Sopenharmony_ci if (alu->opcode() != op1_mov) 592bf215546Sopenharmony_ci return; 593bf215546Sopenharmony_ci 594bf215546Sopenharmony_ci if (alu->has_alu_flag(alu_src0_abs) || 595bf215546Sopenharmony_ci alu->has_alu_flag(alu_src0_neg)) 596bf215546Sopenharmony_ci return; 597bf215546Sopenharmony_ci 598bf215546Sopenharmony_ci auto src = alu->psrc(0); 599bf215546Sopenharmony_ci assert(src); 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_ci int override_chan = -1; 602bf215546Sopenharmony_ci 603bf215546Sopenharmony_ci auto ic = src->as_inline_const(); 604bf215546Sopenharmony_ci if (ic) { 605bf215546Sopenharmony_ci if (ic->sel() == ALU_SRC_0) 606bf215546Sopenharmony_ci override_chan = 4; 607bf215546Sopenharmony_ci 608bf215546Sopenharmony_ci if (ic->sel() == ALU_SRC_1) 609bf215546Sopenharmony_ci override_chan = 5; 610bf215546Sopenharmony_ci } 611bf215546Sopenharmony_ci 612bf215546Sopenharmony_ci auto literal = src->as_literal(); 613bf215546Sopenharmony_ci if (literal) { 614bf215546Sopenharmony_ci 615bf215546Sopenharmony_ci if (literal->value() == 0) 616bf215546Sopenharmony_ci override_chan = 4; 617bf215546Sopenharmony_ci 618bf215546Sopenharmony_ci if (literal->value() == 0x3F800000) 619bf215546Sopenharmony_ci override_chan = 5; 620bf215546Sopenharmony_ci } 621bf215546Sopenharmony_ci 622bf215546Sopenharmony_ci if (override_chan >= 0) { 623bf215546Sopenharmony_ci vreg[index]->del_use(old_use); 624bf215546Sopenharmony_ci auto reg = new Register(vreg.sel(), override_chan, vreg[index]->pin()); 625bf215546Sopenharmony_ci vreg.set_value(index, reg); 626bf215546Sopenharmony_ci success = true; 627bf215546Sopenharmony_ci } 628bf215546Sopenharmony_ci} 629bf215546Sopenharmony_ci 630bf215546Sopenharmony_civoid SimplifySourceVecVisitor::visit(FetchInstr *instr) 631bf215546Sopenharmony_ci{ 632bf215546Sopenharmony_ci (void) instr; 633bf215546Sopenharmony_ci} 634bf215546Sopenharmony_ci 635bf215546Sopenharmony_civoid SimplifySourceVecVisitor::visit(Block *instr) 636bf215546Sopenharmony_ci{ 637bf215546Sopenharmony_ci for (auto i = instr->rbegin(); i != instr->rend(); ++i) 638bf215546Sopenharmony_ci if (!(*i)->is_dead()) 639bf215546Sopenharmony_ci (*i)->accept(*this); 640bf215546Sopenharmony_ci} 641bf215546Sopenharmony_ci 642bf215546Sopenharmony_civoid SimplifySourceVecVisitor::visit(ControlFlowInstr *instr) 643bf215546Sopenharmony_ci{ 644bf215546Sopenharmony_ci (void) instr; 645bf215546Sopenharmony_ci} 646bf215546Sopenharmony_ci 647bf215546Sopenharmony_civoid SimplifySourceVecVisitor::visit(IfInstr *instr) 648bf215546Sopenharmony_ci{ 649bf215546Sopenharmony_ci (void) instr; 650bf215546Sopenharmony_ci} 651bf215546Sopenharmony_ci 652bf215546Sopenharmony_ci 653bf215546Sopenharmony_ci 654bf215546Sopenharmony_ci} 655