diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
index 5ffefaad22..4f838b6997 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
@@ -172,38 +172,29 @@ bool IsReference(IR::Inst& inst) {
     return inst.GetOpcode() == IR::Opcode::Reference;
 }
 
-void Precolor(EmitContext& ctx, const IR::Program& program) {
+void PrecolorInst(IR::Inst& phi) {
+    // Insert phi moves before references to avoid overwritting other phis
+    const size_t num_args{phi.NumArgs()};
+    for (size_t i = 0; i < num_args; ++i) {
+        IR::Block& phi_block{*phi.PhiBlock(i)};
+        auto it{std::find_if_not(phi_block.rbegin(), phi_block.rend(), IsReference).base()};
+        IR::IREmitter ir{phi_block, it};
+        const IR::Value arg{phi.Arg(i)};
+        if (arg.IsImmediate()) {
+            ir.PhiMove(phi, arg);
+        } else {
+            ir.PhiMove(phi, IR::Value{&RegAlloc::AliasInst(*arg.Inst())});
+        }
+    }
+    for (size_t i = 0; i < num_args; ++i) {
+        IR::IREmitter{*phi.PhiBlock(i)}.Reference(IR::Value{&phi});
+    }
+}
+
+void Precolor(const IR::Program& program) {
     for (IR::Block* const block : program.blocks) {
         for (IR::Inst& phi : block->Instructions() | std::views::take_while(IR::IsPhi)) {
-            switch (phi.Arg(0).Type()) {
-            case IR::Type::U1:
-            case IR::Type::U32:
-            case IR::Type::F32:
-                ctx.reg_alloc.Define(phi);
-                break;
-            case IR::Type::U64:
-            case IR::Type::F64:
-                ctx.reg_alloc.LongDefine(phi);
-                break;
-            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::Block& phi_block{*phi.PhiBlock(i)};
-                auto it{std::find_if_not(phi_block.rbegin(), phi_block.rend(), IsReference).base()};
-                IR::IREmitter ir{phi_block, it};
-                const IR::Value arg{phi.Arg(i)};
-                if (arg.IsImmediate()) {
-                    ir.PhiMove(phi, arg);
-                } else {
-                    ir.PhiMove(phi, IR::Value{&RegAlloc::AliasInst(*arg.Inst())});
-                }
-            }
-            for (size_t i = 0; i < num_args; ++i) {
-                IR::IREmitter{*phi.PhiBlock(i)}.Reference(IR::Value{&phi});
-            }
+            PrecolorInst(phi);
         }
     }
 }
@@ -388,7 +379,7 @@ std::string_view GetTessSpacing(TessSpacing spacing) {
 std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, IR::Program& program,
                       Bindings& bindings) {
     EmitContext ctx{program, bindings, profile, runtime_info};
-    Precolor(ctx, program);
+    Precolor(program);
     EmitCode(ctx, program);
     std::string header{StageHeader(program.stage)};
     SetupOptions(program, profile, runtime_info, header);
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
index 3d7a3ebb42..e9d1e0d6bf 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
@@ -17,10 +17,30 @@ namespace Shader::Backend::GLASM {
 
 #define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__)
 
-void EmitPhi(EmitContext& ctx, IR::Inst& inst) {
-    const size_t num_args{inst.NumArgs()};
+static void DefinePhi(EmitContext& ctx, IR::Inst& phi) {
+    switch (phi.Arg(0).Type()) {
+    case IR::Type::U1:
+    case IR::Type::U32:
+    case IR::Type::F32:
+        ctx.reg_alloc.Define(phi);
+        break;
+    case IR::Type::U64:
+    case IR::Type::F64:
+        ctx.reg_alloc.LongDefine(phi);
+        break;
+    default:
+        throw NotImplementedException("Phi node type {}", phi.Type());
+    }
+}
+
+void EmitPhi(EmitContext& ctx, IR::Inst& phi) {
+    const size_t num_args{phi.NumArgs()};
     for (size_t i = 0; i < num_args; ++i) {
-        ctx.reg_alloc.Consume(inst.Arg(i));
+        ctx.reg_alloc.Consume(phi.Arg(i));
+    }
+    if (!phi.Definition<Id>().is_valid) {
+        // The phi node wasn't forward defined
+        DefinePhi(ctx, phi);
     }
 }
 
@@ -30,14 +50,19 @@ 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)};
+void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value& value) {
+    IR::Inst& phi{RegAlloc::AliasInst(*phi_value.Inst())};
+    if (!phi.Definition<Id>().is_valid) {
+        // The phi node wasn't forward defined
+        DefinePhi(ctx, phi);
+    }
+    const Register phi_reg{ctx.reg_alloc.Consume(IR::Value{&phi})};
     const Value eval_value{ctx.reg_alloc.Consume(value)};
 
-    if (phi == value) {
+    if (phi_reg == eval_value) {
         return;
     }
-    switch (phi.Inst()->Flags<IR::Type>()) {
+    switch (phi.Flags<IR::Type>()) {
     case IR::Type::U1:
     case IR::Type::U32:
     case IR::Type::F32: