From 9f3ffb996b0d02ca64b492d22ff158e8f3659257 Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Sun, 30 May 2021 19:13:22 -0400
Subject: [PATCH] glsl: Rework var alloc to not assign unused results

---
 .../backend/glsl/emit_context.cpp             |  8 ++-
 .../backend/glsl/emit_context.h               |  8 ++-
 .../backend/glsl/emit_glsl_atomic.cpp         |  9 ++--
 .../glsl/emit_glsl_bitwise_conversion.cpp     |  8 ++-
 .../backend/glsl/emit_glsl_composite.cpp      | 50 ++++++++++++-------
 .../backend/glsl/emit_glsl_instructions.h     | 26 +++++-----
 .../glsl/emit_glsl_not_implemented.cpp        |  8 +--
 .../backend/glsl/var_alloc.cpp                | 17 ++++++-
 .../backend/glsl/var_alloc.h                  |  6 +++
 9 files changed, 91 insertions(+), 49 deletions(-)

diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp
index b9594de40..da29290a2 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_context.cpp
@@ -122,11 +122,9 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
 
 void EmitContext::SetupExtensions(std::string&) {
     header += "#extension GL_ARB_separate_shader_objects : enable\n";
-    if (stage != Stage::Compute) {
-        // TODO: track this usage
-        header += "#extension GL_ARB_sparse_texture2 : enable\n";
-        header += "#extension GL_EXT_texture_shadow_lod : enable\n";
-    }
+    // TODO: track this usage
+    header += "#extension GL_ARB_sparse_texture2 : enable\n";
+    header += "#extension GL_EXT_texture_shadow_lod : enable\n";
     if (info.uses_int64) {
         header += "#extension GL_ARB_gpu_shader_int64 : enable\n";
     }
diff --git a/src/shader_recompiler/backend/glsl/emit_context.h b/src/shader_recompiler/backend/glsl/emit_context.h
index 2f1062954..423fc6104 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.h
+++ b/src/shader_recompiler/backend/glsl/emit_context.h
@@ -37,7 +37,13 @@ public:
 
     template <GlslVarType type, typename... Args>
     void Add(const char* format_str, IR::Inst& inst, Args&&... args) {
-        code += fmt::format(format_str, var_alloc.Define(inst, type), std::forward<Args>(args)...);
+        const auto var_def{var_alloc.AddDefine(inst, type)};
+        if (var_def.empty()) {
+            // skip assigment.
+            code += fmt::format(&format_str[3], std::forward<Args>(args)...);
+        } else {
+            code += fmt::format(format_str, var_def, std::forward<Args>(args)...);
+        }
         // TODO: Remove this
         code += '\n';
     }
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
index 918f90058..db4c60002 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
@@ -11,8 +11,7 @@
 
 namespace Shader::Backend::GLSL {
 namespace {
-static constexpr std::string_view cas_loop{R"({};
-for (;;){{
+static constexpr std::string_view cas_loop{R"(for (;;){{
     uint old_value={};
     {}=atomicCompSwap({},old_value,{}({},{}));
     if ({}==old_value){{break;}}
@@ -22,14 +21,14 @@ void SharedCasFunction(EmitContext& ctx, IR::Inst& inst, std::string_view offset
                        std::string_view value, std::string_view function) {
     const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)};
     const std::string smem{fmt::format("smem[{}/4]", offset)};
-    ctx.Add(cas_loop.data(), ret, smem, ret, smem, function, smem, value, ret);
+    ctx.Add(cas_loop.data(), smem, ret, smem, function, smem, value, ret);
 }
 
 void SsboCasFunction(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
                      const IR::Value& offset, std::string_view value, std::string_view function) {
     const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)};
     const std::string ssbo{fmt::format("ssbo{}[{}]", binding.U32(), offset.U32())};
-    ctx.Add(cas_loop.data(), ret, ssbo, ret, ssbo, function, ssbo, value, ret);
+    ctx.Add(cas_loop.data(), ssbo, ret, ssbo, function, ssbo, value, ret);
 }
 
 void SsboCasFunctionF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
@@ -37,7 +36,7 @@ void SsboCasFunctionF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& bindi
                         std::string_view function) {
     const std::string ssbo{fmt::format("ssbo{}[{}]", binding.U32(), offset.U32())};
     const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)};
-    ctx.Add(cas_loop.data(), ret, ssbo, ret, ssbo, function, ssbo, value, ret);
+    ctx.Add(cas_loop.data(), ssbo, ret, ssbo, function, ssbo, value, ret);
     ctx.AddF32("{}=uintBitsToFloat({});", inst, ret);
 }
 } // namespace
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
index 2b08aa593..9d844b831 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
@@ -26,7 +26,13 @@ void EmitIdentity(EmitContext&, IR::Inst& inst, const IR::Value& value) {
 }
 
 void EmitConditionRef(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) {
-    ctx.AddU1("{}={};", inst, ctx.var_alloc.Consume(value));
+    // Fake one usage to get a real variable out of the condition
+    inst.DestructiveAddUsage(1);
+    const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U1)};
+    const auto input{ctx.var_alloc.Consume(value)};
+    if (ret != input) {
+        ctx.Add("{}={};", ret, input);
+    }
 }
 
 void EmitBitCastU16F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst) {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
index 0fd667c8f..44a719fc3 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
@@ -9,8 +9,14 @@
 #include "shader_recompiler/frontend/ir/value.h"
 
 namespace Shader::Backend::GLSL {
+namespace {
 static constexpr std::string_view SWIZZLE{"xyzw"};
-
+void CompositeInsert(EmitContext& ctx, std::string_view result, std::string_view composite,
+                     std::string_view object, u32 index) {
+    ctx.Add("{}={};", result, composite);
+    ctx.Add("{}.{}={};", result, SWIZZLE[index], object);
+}
+} // namespace
 void EmitCompositeConstructU32x2(EmitContext& ctx, IR::Inst& inst, std::string_view e1,
                                  std::string_view e2) {
     ctx.AddU32x2("{}=uvec2({},{});", inst, e1, e2);
@@ -41,19 +47,22 @@ void EmitCompositeExtractU32x4(EmitContext& ctx, IR::Inst& inst, std::string_vie
     ctx.AddU32("{}={}.{};", inst, composite, SWIZZLE[index]);
 }
 
-void EmitCompositeInsertU32x2(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index) {
-    ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
+void EmitCompositeInsertU32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index) {
+    const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32x2)};
+    CompositeInsert(ctx, ret, composite, object, index);
 }
 
-void EmitCompositeInsertU32x3(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index) {
-    ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
+void EmitCompositeInsertU32x3(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index) {
+    const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32x3)};
+    CompositeInsert(ctx, ret, composite, object, index);
 }
 
-void EmitCompositeInsertU32x4(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index) {
-    ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
+void EmitCompositeInsertU32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index) {
+    const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32x4)};
+    CompositeInsert(ctx, ret, composite, object, index);
 }
 
 void EmitCompositeConstructF16x2([[maybe_unused]] EmitContext& ctx,
@@ -146,19 +155,22 @@ void EmitCompositeExtractF32x4(EmitContext& ctx, IR::Inst& inst, std::string_vie
     ctx.AddF32("{}={}.{};", inst, composite, SWIZZLE[index]);
 }
 
-void EmitCompositeInsertF32x2(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index) {
-    ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
+void EmitCompositeInsertF32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index) {
+    const auto ret{ctx.var_alloc.Define(inst, GlslVarType::F32x2)};
+    CompositeInsert(ctx, ret, composite, object, index);
 }
 
-void EmitCompositeInsertF32x3(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index) {
-    ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
+void EmitCompositeInsertF32x3(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index) {
+    const auto ret{ctx.var_alloc.Define(inst, GlslVarType::F32x3)};
+    CompositeInsert(ctx, ret, composite, object, index);
 }
 
-void EmitCompositeInsertF32x4(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index) {
-    ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
+void EmitCompositeInsertF32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index) {
+    const auto ret{ctx.var_alloc.Define(inst, GlslVarType::F32x4)};
+    CompositeInsert(ctx, ret, composite, object, index);
 }
 
 void EmitCompositeConstructF64x2([[maybe_unused]] EmitContext& ctx) {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
index 703db80ee..c2e5aff16 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
@@ -26,7 +26,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& ctx, const IR::Value& value);
 void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value);
 void EmitBranch(EmitContext& ctx, std::string_view label);
 void EmitBranchConditional(EmitContext& ctx, std::string_view condition,
@@ -165,12 +165,12 @@ void EmitCompositeExtractU32x3(EmitContext& ctx, IR::Inst& inst, std::string_vie
                                u32 index);
 void EmitCompositeExtractU32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
                                u32 index);
-void EmitCompositeInsertU32x2(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index);
-void EmitCompositeInsertU32x3(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index);
-void EmitCompositeInsertU32x4(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index);
+void EmitCompositeInsertU32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index);
+void EmitCompositeInsertU32x3(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index);
+void EmitCompositeInsertU32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index);
 void EmitCompositeConstructF16x2(EmitContext& ctx, std::string_view e1, std::string_view e2);
 void EmitCompositeConstructF16x3(EmitContext& ctx, std::string_view e1, std::string_view e2,
                                  std::string_view e3);
@@ -197,12 +197,12 @@ void EmitCompositeExtractF32x3(EmitContext& ctx, IR::Inst& inst, std::string_vie
                                u32 index);
 void EmitCompositeExtractF32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
                                u32 index);
-void EmitCompositeInsertF32x2(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index);
-void EmitCompositeInsertF32x3(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index);
-void EmitCompositeInsertF32x4(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index);
+void EmitCompositeInsertF32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index);
+void EmitCompositeInsertF32x3(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index);
+void EmitCompositeInsertF32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index);
 void EmitCompositeConstructF64x2(EmitContext& ctx);
 void EmitCompositeConstructF64x3(EmitContext& ctx);
 void EmitCompositeConstructF64x4(EmitContext& ctx);
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
index 806c4777b..599ff90e0 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
@@ -25,7 +25,7 @@ void EmitPhi(EmitContext& ctx, IR::Inst& phi) {
     }
     if (!phi.Definition<Id>().is_valid) {
         // The phi node wasn't forward defined
-        ctx.Add("{};", ctx.var_alloc.Define(phi, phi.Arg(0).Type()));
+        ctx.var_alloc.PhiDefine(phi, phi.Arg(0).Type());
     }
 }
 
@@ -33,8 +33,8 @@ void EmitVoid(EmitContext& ctx) {
     // NotImplemented();
 }
 
-void EmitReference(EmitContext&) {
-    // NotImplemented();
+void EmitReference(EmitContext& ctx, const IR::Value& value) {
+    ctx.var_alloc.Consume(value);
 }
 
 void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value& value) {
@@ -42,7 +42,7 @@ void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value&
     const auto phi_type{phi.Arg(0).Type()};
     if (!phi.Definition<Id>().is_valid) {
         // The phi node wasn't forward defined
-        ctx.Add("{};", ctx.var_alloc.Define(phi, phi_type));
+        ctx.var_alloc.PhiDefine(phi, phi_type);
     }
     const auto phi_reg{ctx.var_alloc.Consume(IR::Value{&phi})};
     const auto val_reg{ctx.var_alloc.Consume(value)};
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.cpp b/src/shader_recompiler/backend/glsl/var_alloc.cpp
index 8c6944f07..896457248 100644
--- a/src/shader_recompiler/backend/glsl/var_alloc.cpp
+++ b/src/shader_recompiler/backend/glsl/var_alloc.cpp
@@ -110,7 +110,6 @@ std::string VarAlloc::Define(IR::Inst& inst, GlslVarType type) {
     } else {
         Id id{};
         id.type.Assign(type);
-        // id.is_null.Assign(1);
         GetUseTracker(type).uses_temp = true;
         inst.SetDefinition<Id>(id);
     }
@@ -121,6 +120,20 @@ std::string VarAlloc::Define(IR::Inst& inst, IR::Type type) {
     return Define(inst, RegType(type));
 }
 
+std::string VarAlloc::PhiDefine(IR::Inst& inst, IR::Type type) {
+    return AddDefine(inst, RegType(type));
+}
+
+std::string VarAlloc::AddDefine(IR::Inst& inst, GlslVarType type) {
+    if (inst.HasUses()) {
+        inst.SetDefinition<Id>(Alloc(type));
+        return Representation(inst.Definition<Id>());
+    } else {
+        return "";
+    }
+    return Representation(inst.Definition<Id>());
+}
+
 std::string VarAlloc::Consume(const IR::Value& value) {
     return value.IsImmediate() ? MakeImm(value) : ConsumeInst(*value.InstRecursive());
 }
@@ -223,6 +236,8 @@ VarAlloc::UseTracker& VarAlloc::GetUseTracker(GlslVarType type) {
     switch (type) {
     case GlslVarType::U1:
         return var_bool;
+    case GlslVarType::F16x2:
+        return var_f16x2;
     case GlslVarType::U32:
         return var_u32;
     case GlslVarType::S32:
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.h b/src/shader_recompiler/backend/glsl/var_alloc.h
index 29d78a571..574960b1a 100644
--- a/src/shader_recompiler/backend/glsl/var_alloc.h
+++ b/src/shader_recompiler/backend/glsl/var_alloc.h
@@ -62,9 +62,15 @@ public:
         bool uses_temp{};
     };
 
+    /// Used for explicit usages of variables, may revert to temporaries
     std::string Define(IR::Inst& inst, GlslVarType type);
     std::string Define(IR::Inst& inst, IR::Type type);
 
+    /// Used to assign variables used by the IR. May return a blank string if
+    /// the instruction's result is unused in the IR.
+    std::string AddDefine(IR::Inst& inst, GlslVarType type);
+    std::string PhiDefine(IR::Inst& inst, IR::Type type);
+
     std::string Consume(const IR::Value& value);
     std::string ConsumeInst(IR::Inst& inst);