aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Shader/Translation/Optimizations
diff options
context:
space:
mode:
authorgdk <gab.dark.100@gmail.com>2019-10-13 03:02:07 -0300
committerThog <thog@protonmail.com>2020-01-09 02:13:00 +0100
commit1876b346fea647e8284a66bb6d62c38801035cff (patch)
tree6eeff094298cda84d1613dc5ec0691e51d7b35f1 /Ryujinx.Graphics/Shader/Translation/Optimizations
parentf617fb542a0e3d36012d77a4b5acbde7b08902f2 (diff)
Initial work
Diffstat (limited to 'Ryujinx.Graphics/Shader/Translation/Optimizations')
-rw-r--r--Ryujinx.Graphics/Shader/Translation/Optimizations/BranchElimination.cs64
-rw-r--r--Ryujinx.Graphics/Shader/Translation/Optimizations/ConstantFolding.cs323
-rw-r--r--Ryujinx.Graphics/Shader/Translation/Optimizations/HalfConversion.cs47
-rw-r--r--Ryujinx.Graphics/Shader/Translation/Optimizations/Optimizer.cs172
-rw-r--r--Ryujinx.Graphics/Shader/Translation/Optimizations/Simplification.cs147
5 files changed, 0 insertions, 753 deletions
diff --git a/Ryujinx.Graphics/Shader/Translation/Optimizations/BranchElimination.cs b/Ryujinx.Graphics/Shader/Translation/Optimizations/BranchElimination.cs
deleted file mode 100644
index 070f07a4..00000000
--- a/Ryujinx.Graphics/Shader/Translation/Optimizations/BranchElimination.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using System;
-
-namespace Ryujinx.Graphics.Shader.Translation.Optimizations
-{
- static class BranchElimination
- {
- public static bool Eliminate(BasicBlock block)
- {
- if (block.HasBranch && IsRedundantBranch((Operation)block.GetLastOp(), Next(block)))
- {
- block.Branch = null;
-
- return true;
- }
-
- return false;
- }
-
- private static bool IsRedundantBranch(Operation current, BasicBlock nextBlock)
- {
- // Here we check that:
- // - The current block ends with a branch.
- // - The next block only contains a branch.
- // - The branch on the next block is unconditional.
- // - Both branches are jumping to the same location.
- // In this case, the branch on the current block can be removed,
- // as the next block is going to jump to the same place anyway.
- if (nextBlock == null)
- {
- return false;
- }
-
- if (!(nextBlock.Operations.First?.Value is Operation next))
- {
- return false;
- }
-
- if (next.Inst != Instruction.Branch)
- {
- return false;
- }
-
- return current.Dest == next.Dest;
- }
-
- private static BasicBlock Next(BasicBlock block)
- {
- block = block.Next;
-
- while (block != null && block.Operations.Count == 0)
- {
- if (block.HasBranch)
- {
- throw new InvalidOperationException("Found a bogus empty block that \"ends with a branch\".");
- }
-
- block = block.Next;
- }
-
- return block;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Shader/Translation/Optimizations/ConstantFolding.cs b/Ryujinx.Graphics/Shader/Translation/Optimizations/ConstantFolding.cs
deleted file mode 100644
index a2e05ef1..00000000
--- a/Ryujinx.Graphics/Shader/Translation/Optimizations/ConstantFolding.cs
+++ /dev/null
@@ -1,323 +0,0 @@
-using Ryujinx.Graphics.Shader.Decoders;
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using System;
-
-using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
-
-namespace Ryujinx.Graphics.Shader.Translation.Optimizations
-{
- static class ConstantFolding
- {
- public static void Fold(Operation operation)
- {
- if (!AreAllSourcesConstant(operation))
- {
- return;
- }
-
- switch (operation.Inst)
- {
- case Instruction.Add:
- EvaluateBinary(operation, (x, y) => x + y);
- break;
-
- case Instruction.BitwiseAnd:
- EvaluateBinary(operation, (x, y) => x & y);
- break;
-
- case Instruction.BitwiseExclusiveOr:
- EvaluateBinary(operation, (x, y) => x ^ y);
- break;
-
- case Instruction.BitwiseNot:
- EvaluateUnary(operation, (x) => ~x);
- break;
-
- case Instruction.BitwiseOr:
- EvaluateBinary(operation, (x, y) => x | y);
- break;
-
- case Instruction.BitfieldExtractS32:
- BitfieldExtractS32(operation);
- break;
-
- case Instruction.BitfieldExtractU32:
- BitfieldExtractU32(operation);
- break;
-
- case Instruction.Clamp:
- EvaluateTernary(operation, (x, y, z) => Math.Clamp(x, y, z));
- break;
-
- case Instruction.ClampU32:
- EvaluateTernary(operation, (x, y, z) => (int)Math.Clamp((uint)x, (uint)y, (uint)z));
- break;
-
- case Instruction.CompareEqual:
- EvaluateBinary(operation, (x, y) => x == y);
- break;
-
- case Instruction.CompareGreater:
- EvaluateBinary(operation, (x, y) => x > y);
- break;
-
- case Instruction.CompareGreaterOrEqual:
- EvaluateBinary(operation, (x, y) => x >= y);
- break;
-
- case Instruction.CompareGreaterOrEqualU32:
- EvaluateBinary(operation, (x, y) => (uint)x >= (uint)y);
- break;
-
- case Instruction.CompareGreaterU32:
- EvaluateBinary(operation, (x, y) => (uint)x > (uint)y);
- break;
-
- case Instruction.CompareLess:
- EvaluateBinary(operation, (x, y) => x < y);
- break;
-
- case Instruction.CompareLessOrEqual:
- EvaluateBinary(operation, (x, y) => x <= y);
- break;
-
- case Instruction.CompareLessOrEqualU32:
- EvaluateBinary(operation, (x, y) => (uint)x <= (uint)y);
- break;
-
- case Instruction.CompareLessU32:
- EvaluateBinary(operation, (x, y) => (uint)x < (uint)y);
- break;
-
- case Instruction.CompareNotEqual:
- EvaluateBinary(operation, (x, y) => x != y);
- break;
-
- case Instruction.Divide:
- EvaluateBinary(operation, (x, y) => y != 0 ? x / y : 0);
- break;
-
- case Instruction.FP | Instruction.Add:
- EvaluateFPBinary(operation, (x, y) => x + y);
- break;
-
- case Instruction.FP | Instruction.Clamp:
- EvaluateFPTernary(operation, (x, y, z) => Math.Clamp(x, y, z));
- break;
-
- case Instruction.FP | Instruction.CompareEqual:
- EvaluateFPBinary(operation, (x, y) => x == y);
- break;
-
- case Instruction.FP | Instruction.CompareGreater:
- EvaluateFPBinary(operation, (x, y) => x > y);
- break;
-
- case Instruction.FP | Instruction.CompareGreaterOrEqual:
- EvaluateFPBinary(operation, (x, y) => x >= y);
- break;
-
- case Instruction.FP | Instruction.CompareLess:
- EvaluateFPBinary(operation, (x, y) => x < y);
- break;
-
- case Instruction.FP | Instruction.CompareLessOrEqual:
- EvaluateFPBinary(operation, (x, y) => x <= y);
- break;
-
- case Instruction.FP | Instruction.CompareNotEqual:
- EvaluateFPBinary(operation, (x, y) => x != y);
- break;
-
- case Instruction.FP | Instruction.Divide:
- EvaluateFPBinary(operation, (x, y) => x / y);
- break;
-
- case Instruction.FP | Instruction.Multiply:
- EvaluateFPBinary(operation, (x, y) => x * y);
- break;
-
- case Instruction.FP | Instruction.Negate:
- EvaluateFPUnary(operation, (x) => -x);
- break;
-
- case Instruction.FP | Instruction.Subtract:
- EvaluateFPBinary(operation, (x, y) => x - y);
- break;
-
- case Instruction.IsNan:
- EvaluateFPUnary(operation, (x) => float.IsNaN(x));
- break;
-
- case Instruction.Maximum:
- EvaluateBinary(operation, (x, y) => Math.Max(x, y));
- break;
-
- case Instruction.MaximumU32:
- EvaluateBinary(operation, (x, y) => (int)Math.Max((uint)x, (uint)y));
- break;
-
- case Instruction.Minimum:
- EvaluateBinary(operation, (x, y) => Math.Min(x, y));
- break;
-
- case Instruction.MinimumU32:
- EvaluateBinary(operation, (x, y) => (int)Math.Min((uint)x, (uint)y));
- break;
-
- case Instruction.Multiply:
- EvaluateBinary(operation, (x, y) => x * y);
- break;
-
- case Instruction.Negate:
- EvaluateUnary(operation, (x) => -x);
- break;
-
- case Instruction.ShiftLeft:
- EvaluateBinary(operation, (x, y) => x << y);
- break;
-
- case Instruction.ShiftRightS32:
- EvaluateBinary(operation, (x, y) => x >> y);
- break;
-
- case Instruction.ShiftRightU32:
- EvaluateBinary(operation, (x, y) => (int)((uint)x >> y));
- break;
-
- case Instruction.Subtract:
- EvaluateBinary(operation, (x, y) => x - y);
- break;
-
- case Instruction.UnpackHalf2x16:
- UnpackHalf2x16(operation);
- break;
- }
- }
-
- private static bool AreAllSourcesConstant(Operation operation)
- {
- for (int index = 0; index < operation.SourcesCount; index++)
- {
- if (operation.GetSource(index).Type != OperandType.Constant)
- {
- return false;
- }
- }
-
- return true;
- }
-
- private static void BitfieldExtractS32(Operation operation)
- {
- int value = GetBitfieldExtractValue(operation);
-
- int shift = 32 - operation.GetSource(2).Value;
-
- value = (value << shift) >> shift;
-
- operation.TurnIntoCopy(Const(value));
- }
-
- private static void BitfieldExtractU32(Operation operation)
- {
- operation.TurnIntoCopy(Const(GetBitfieldExtractValue(operation)));
- }
-
- private static int GetBitfieldExtractValue(Operation operation)
- {
- int value = operation.GetSource(0).Value;
- int lsb = operation.GetSource(1).Value;
- int length = operation.GetSource(2).Value;
-
- return value.Extract(lsb, length);
- }
-
- private static void UnpackHalf2x16(Operation operation)
- {
- int value = operation.GetSource(0).Value;
-
- value = (value >> operation.ComponentIndex * 16) & 0xffff;
-
- operation.TurnIntoCopy(ConstF(HalfConversion.HalfToSingle(value)));
- }
-
- private static void FPNegate(Operation operation)
- {
- float value = operation.GetSource(0).AsFloat();
-
- operation.TurnIntoCopy(ConstF(-value));
- }
-
- private static void EvaluateUnary(Operation operation, Func<int, int> op)
- {
- int x = operation.GetSource(0).Value;
-
- operation.TurnIntoCopy(Const(op(x)));
- }
-
- private static void EvaluateFPUnary(Operation operation, Func<float, float> op)
- {
- float x = operation.GetSource(0).AsFloat();
-
- operation.TurnIntoCopy(ConstF(op(x)));
- }
-
- private static void EvaluateFPUnary(Operation operation, Func<float, bool> op)
- {
- float x = operation.GetSource(0).AsFloat();
-
- operation.TurnIntoCopy(Const(op(x) ? IrConsts.True : IrConsts.False));
- }
-
- private static void EvaluateBinary(Operation operation, Func<int, int, int> op)
- {
- int x = operation.GetSource(0).Value;
- int y = operation.GetSource(1).Value;
-
- operation.TurnIntoCopy(Const(op(x, y)));
- }
-
- private static void EvaluateBinary(Operation operation, Func<int, int, bool> op)
- {
- int x = operation.GetSource(0).Value;
- int y = operation.GetSource(1).Value;
-
- operation.TurnIntoCopy(Const(op(x, y) ? IrConsts.True : IrConsts.False));
- }
-
- private static void EvaluateFPBinary(Operation operation, Func<float, float, float> op)
- {
- float x = operation.GetSource(0).AsFloat();
- float y = operation.GetSource(1).AsFloat();
-
- operation.TurnIntoCopy(ConstF(op(x, y)));
- }
-
- private static void EvaluateFPBinary(Operation operation, Func<float, float, bool> op)
- {
- float x = operation.GetSource(0).AsFloat();
- float y = operation.GetSource(1).AsFloat();
-
- operation.TurnIntoCopy(Const(op(x, y) ? IrConsts.True : IrConsts.False));
- }
-
- private static void EvaluateTernary(Operation operation, Func<int, int, int, int> op)
- {
- int x = operation.GetSource(0).Value;
- int y = operation.GetSource(1).Value;
- int z = operation.GetSource(2).Value;
-
- operation.TurnIntoCopy(Const(op(x, y, z)));
- }
-
- private static void EvaluateFPTernary(Operation operation, Func<float, float, float, float> op)
- {
- float x = operation.GetSource(0).AsFloat();
- float y = operation.GetSource(1).AsFloat();
- float z = operation.GetSource(2).AsFloat();
-
- operation.TurnIntoCopy(ConstF(op(x, y, z)));
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Shader/Translation/Optimizations/HalfConversion.cs b/Ryujinx.Graphics/Shader/Translation/Optimizations/HalfConversion.cs
deleted file mode 100644
index 96060272..00000000
--- a/Ryujinx.Graphics/Shader/Translation/Optimizations/HalfConversion.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using System;
-
-namespace Ryujinx.Graphics.Shader.Translation.Optimizations
-{
- static class HalfConversion
- {
- public static float HalfToSingle(int value)
- {
- int mantissa = (value >> 0) & 0x3ff;
- int exponent = (value >> 10) & 0x1f;
- int sign = (value >> 15) & 0x1;
-
- if (exponent == 0x1f)
- {
- // NaN or Infinity.
- mantissa <<= 13;
- exponent = 0xff;
- }
- else if (exponent != 0 || mantissa != 0 )
- {
- if (exponent == 0)
- {
- // Denormal.
- int e = -1;
- int m = mantissa;
-
- do
- {
- e++;
- m <<= 1;
- }
- while ((m & 0x400) == 0);
-
- mantissa = m & 0x3ff;
- exponent = e;
- }
-
- mantissa <<= 13;
- exponent = 127 - 15 + exponent;
- }
-
- int output = (sign << 31) | (exponent << 23) | mantissa;
-
- return BitConverter.Int32BitsToSingle(output);
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Shader/Translation/Optimizations/Optimizer.cs b/Ryujinx.Graphics/Shader/Translation/Optimizations/Optimizer.cs
deleted file mode 100644
index 8cce0e74..00000000
--- a/Ryujinx.Graphics/Shader/Translation/Optimizations/Optimizer.cs
+++ /dev/null
@@ -1,172 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Ryujinx.Graphics.Shader.Translation.Optimizations
-{
- static class Optimizer
- {
- public static void Optimize(BasicBlock[] blocks)
- {
- bool modified;
-
- do
- {
- modified = false;
-
- for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
- {
- BasicBlock block = blocks[blkIndex];
-
- LinkedListNode<INode> node = block.Operations.First;
-
- while (node != null)
- {
- LinkedListNode<INode> nextNode = node.Next;
-
- bool isUnused = IsUnused(node.Value);
-
- if (!(node.Value is Operation operation) || isUnused)
- {
- if (isUnused)
- {
- RemoveNode(block, node);
-
- modified = true;
- }
-
- node = nextNode;
-
- continue;
- }
-
- ConstantFolding.Fold(operation);
-
- Simplification.Simplify(operation);
-
- if (DestIsLocalVar(operation))
- {
- if (operation.Inst == Instruction.Copy)
- {
- PropagateCopy(operation);
-
- RemoveNode(block, node);
-
- modified = true;
- }
- else if (operation.Inst == Instruction.PackHalf2x16 && PropagatePack(operation))
- {
- if (operation.Dest.UseOps.Count == 0)
- {
- RemoveNode(block, node);
- }
-
- modified = true;
- }
- }
-
- node = nextNode;
- }
-
- if (BranchElimination.Eliminate(block))
- {
- RemoveNode(block, block.Operations.Last);
-
- modified = true;
- }
- }
- }
- while (modified);
- }
-
- private static void PropagateCopy(Operation copyOp)
- {
- // Propagate copy source operand to all uses of
- // the destination operand.
- Operand dest = copyOp.Dest;
- Operand src = copyOp.GetSource(0);
-
- INode[] uses = dest.UseOps.ToArray();
-
- foreach (INode useNode in uses)
- {
- for (int index = 0; index < useNode.SourcesCount; index++)
- {
- if (useNode.GetSource(index) == dest)
- {
- useNode.SetSource(index, src);
- }
- }
- }
- }
-
- private static bool PropagatePack(Operation packOp)
- {
- // Propagate pack source operands to uses by unpack
- // instruction. The source depends on the unpack instruction.
- bool modified = false;
-
- Operand dest = packOp.Dest;
- Operand src0 = packOp.GetSource(0);
- Operand src1 = packOp.GetSource(1);
-
- INode[] uses = dest.UseOps.ToArray();
-
- foreach (INode useNode in uses)
- {
- if (!(useNode is Operation operation) || operation.Inst != Instruction.UnpackHalf2x16)
- {
- continue;
- }
-
- if (operation.GetSource(0) == dest)
- {
- operation.TurnIntoCopy(operation.ComponentIndex == 1 ? src1 : src0);
-
- modified = true;
- }
- }
-
- return modified;
- }
-
- private static void RemoveNode(BasicBlock block, LinkedListNode<INode> llNode)
- {
- // Remove a node from the nodes list, and also remove itself
- // from all the use lists on the operands that this node uses.
- block.Operations.Remove(llNode);
-
- Queue<INode> nodes = new Queue<INode>();
-
- nodes.Enqueue(llNode.Value);
-
- while (nodes.TryDequeue(out INode node))
- {
- for (int index = 0; index < node.SourcesCount; index++)
- {
- Operand src = node.GetSource(index);
-
- if (src.Type != OperandType.LocalVariable)
- {
- continue;
- }
-
- if (src.UseOps.Remove(node) && src.UseOps.Count == 0)
- {
- nodes.Enqueue(src.AsgOp);
- }
- }
- }
- }
-
- private static bool IsUnused(INode node)
- {
- return DestIsLocalVar(node) && node.Dest.UseOps.Count == 0;
- }
-
- private static bool DestIsLocalVar(INode node)
- {
- return node.Dest != null && node.Dest.Type == OperandType.LocalVariable;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Shader/Translation/Optimizations/Simplification.cs b/Ryujinx.Graphics/Shader/Translation/Optimizations/Simplification.cs
deleted file mode 100644
index d6366dfe..00000000
--- a/Ryujinx.Graphics/Shader/Translation/Optimizations/Simplification.cs
+++ /dev/null
@@ -1,147 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-
-using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
-
-namespace Ryujinx.Graphics.Shader.Translation.Optimizations
-{
- static class Simplification
- {
- private const int AllOnes = ~0;
-
- public static void Simplify(Operation operation)
- {
- switch (operation.Inst)
- {
- case Instruction.Add:
- case Instruction.BitwiseExclusiveOr:
- TryEliminateBinaryOpCommutative(operation, 0);
- break;
-
- case Instruction.BitwiseAnd:
- TryEliminateBitwiseAnd(operation);
- break;
-
- case Instruction.BitwiseOr:
- TryEliminateBitwiseOr(operation);
- break;
-
- case Instruction.ConditionalSelect:
- TryEliminateConditionalSelect(operation);
- break;
-
- case Instruction.Divide:
- TryEliminateBinaryOpY(operation, 1);
- break;
-
- case Instruction.Multiply:
- TryEliminateBinaryOpCommutative(operation, 1);
- break;
-
- case Instruction.ShiftLeft:
- case Instruction.ShiftRightS32:
- case Instruction.ShiftRightU32:
- case Instruction.Subtract:
- TryEliminateBinaryOpY(operation, 0);
- break;
- }
- }
-
- private static void TryEliminateBitwiseAnd(Operation operation)
- {
- // Try to recognize and optimize those 3 patterns (in order):
- // x & 0xFFFFFFFF == x, 0xFFFFFFFF & y == y,
- // x & 0x00000000 == 0x00000000, 0x00000000 & y == 0x00000000
- Operand x = operation.GetSource(0);
- Operand y = operation.GetSource(1);
-
- if (IsConstEqual(x, AllOnes))
- {
- operation.TurnIntoCopy(y);
- }
- else if (IsConstEqual(y, AllOnes))
- {
- operation.TurnIntoCopy(x);
- }
- else if (IsConstEqual(x, 0) || IsConstEqual(y, 0))
- {
- operation.TurnIntoCopy(Const(0));
- }
- }
-
- private static void TryEliminateBitwiseOr(Operation operation)
- {
- // Try to recognize and optimize those 3 patterns (in order):
- // x | 0x00000000 == x, 0x00000000 | y == y,
- // x | 0xFFFFFFFF == 0xFFFFFFFF, 0xFFFFFFFF | y == 0xFFFFFFFF
- Operand x = operation.GetSource(0);
- Operand y = operation.GetSource(1);
-
- if (IsConstEqual(x, 0))
- {
- operation.TurnIntoCopy(y);
- }
- else if (IsConstEqual(y, 0))
- {
- operation.TurnIntoCopy(x);
- }
- else if (IsConstEqual(x, AllOnes) || IsConstEqual(y, AllOnes))
- {
- operation.TurnIntoCopy(Const(AllOnes));
- }
- }
-
- private static void TryEliminateBinaryOpY(Operation operation, int comparand)
- {
- Operand x = operation.GetSource(0);
- Operand y = operation.GetSource(1);
-
- if (IsConstEqual(y, comparand))
- {
- operation.TurnIntoCopy(x);
- }
- }
-
- private static void TryEliminateBinaryOpCommutative(Operation operation, int comparand)
- {
- Operand x = operation.GetSource(0);
- Operand y = operation.GetSource(1);
-
- if (IsConstEqual(x, comparand))
- {
- operation.TurnIntoCopy(y);
- }
- else if (IsConstEqual(y, comparand))
- {
- operation.TurnIntoCopy(x);
- }
- }
-
- private static void TryEliminateConditionalSelect(Operation operation)
- {
- Operand cond = operation.GetSource(0);
-
- if (cond.Type != OperandType.Constant)
- {
- return;
- }
-
- // The condition is constant, we can turn it into a copy, and select
- // the source based on the condition value.
- int srcIndex = cond.Value != 0 ? 1 : 2;
-
- Operand source = operation.GetSource(srcIndex);
-
- operation.TurnIntoCopy(source);
- }
-
- private static bool IsConstEqual(Operand operand, int comparand)
- {
- if (operand.Type != OperandType.Constant)
- {
- return false;
- }
-
- return operand.Value == comparand;
- }
- }
-} \ No newline at end of file