glasm: Fix usage counting on phi nodes
This commit is contained in:
		| @@ -178,6 +178,10 @@ void EmitInst(EmitContext& ctx, IR::Inst* inst) { | ||||
|     throw LogicError("Invalid opcode {}", inst->GetOpcode()); | ||||
| } | ||||
|  | ||||
| bool IsReference(IR::Inst& inst) { | ||||
|     return inst.GetOpcode() == IR::Opcode::Reference; | ||||
| } | ||||
|  | ||||
| void Precolor(EmitContext& ctx, const IR::Program& program) { | ||||
|     for (IR::Block* const block : program.blocks) { | ||||
|         for (IR::Inst& phi : block->Instructions() | std::views::take_while(IR::IsPhi)) { | ||||
| @@ -194,11 +198,13 @@ void Precolor(EmitContext& ctx, const IR::Program& program) { | ||||
|             default: | ||||
|                 throw NotImplementedException("Phi node type {}", phi.Type()); | ||||
|             } | ||||
|             // Insert phi moves before references to avoid overwritting them | ||||
|             const size_t num_args{phi.NumArgs()}; | ||||
|             for (size_t i = 0; i < num_args; ++i) { | ||||
|                 IR::IREmitter{*phi.PhiBlock(i)}.PhiMove(phi, phi.Arg(i)); | ||||
|                 IR::Block& phi_block{*phi.PhiBlock(i)}; | ||||
|                 auto it{std::find_if_not(phi_block.rbegin(), phi_block.rend(), IsReference).base()}; | ||||
|                 IR::IREmitter{phi_block, it}.PhiMove(phi, phi.Arg(i)); | ||||
|             } | ||||
|             // Add reference to the phi node on the phi predecessor to avoid overwritting it | ||||
|             for (size_t i = 0; i < num_args; ++i) { | ||||
|                 IR::IREmitter{*phi.PhiBlock(i)}.Reference(IR::Value{&phi}); | ||||
|             } | ||||
| @@ -237,7 +243,7 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { | ||||
|                 } | ||||
|             } else { | ||||
|                 ctx.Add("MOV.S.CC RC,{};" | ||||
|                         "BRK (EQ.x);" | ||||
|                         "BRK(EQ.x);" | ||||
|                         "ENDREP;", | ||||
|                         eval(node.data.repeat.cond)); | ||||
|             } | ||||
|   | ||||
| @@ -23,7 +23,7 @@ void EmitPhi(EmitContext& ctx, IR::Inst& inst); | ||||
| void EmitVoid(EmitContext& ctx); | ||||
| void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); | ||||
| void EmitConditionRef(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); | ||||
| void EmitReference(EmitContext&); | ||||
| void EmitReference(EmitContext&, const IR::Value& value); | ||||
| void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value); | ||||
| void EmitJoin(EmitContext& ctx); | ||||
| void EmitDemoteToHelperInvocation(EmitContext& ctx); | ||||
|   | ||||
| @@ -17,18 +17,26 @@ namespace Shader::Backend::GLASM { | ||||
|  | ||||
| #define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__) | ||||
|  | ||||
| void EmitPhi(EmitContext&, IR::Inst&) {} | ||||
| void EmitPhi(EmitContext& ctx, IR::Inst& inst) { | ||||
|     const size_t num_args{inst.NumArgs()}; | ||||
|     for (size_t i = 0; i < num_args; ++i) { | ||||
|         ctx.reg_alloc.Consume(inst.Arg(i)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void EmitVoid(EmitContext&) {} | ||||
|  | ||||
| void EmitReference(EmitContext&) {} | ||||
| void EmitReference(EmitContext& ctx, const IR::Value& value) { | ||||
|     ctx.reg_alloc.Consume(value); | ||||
| } | ||||
|  | ||||
| void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value) { | ||||
|     const Register phi_reg{ctx.reg_alloc.Consume(phi)}; | ||||
|     const Value eval_value{ctx.reg_alloc.Consume(value)}; | ||||
|  | ||||
|     if (phi == value) { | ||||
|         return; | ||||
|     } | ||||
|     const Register phi_reg{ctx.reg_alloc.Consume(phi)}; | ||||
|     const Value eval_value{ctx.reg_alloc.Consume(value)}; | ||||
|     switch (phi.Inst()->Flags<IR::Type>()) { | ||||
|     case IR::Type::U1: | ||||
|     case IR::Type::U32: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user