aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/Translation/FunctionMatch.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Shader/Translation/FunctionMatch.cs')
-rw-r--r--Ryujinx.Graphics.Shader/Translation/FunctionMatch.cs866
1 files changed, 0 insertions, 866 deletions
diff --git a/Ryujinx.Graphics.Shader/Translation/FunctionMatch.cs b/Ryujinx.Graphics.Shader/Translation/FunctionMatch.cs
deleted file mode 100644
index 073e120a..00000000
--- a/Ryujinx.Graphics.Shader/Translation/FunctionMatch.cs
+++ /dev/null
@@ -1,866 +0,0 @@
-using Ryujinx.Graphics.Shader.Decoders;
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-
-namespace Ryujinx.Graphics.Shader.Translation
-{
- static class FunctionMatch
- {
- private static IPatternTreeNode[] _fsiGetAddressTree = PatternTrees.GetFsiGetAddress();
- private static IPatternTreeNode[] _fsiGetAddressV2Tree = PatternTrees.GetFsiGetAddressV2();
- private static IPatternTreeNode[] _fsiIsLastWarpThreadPatternTree = PatternTrees.GetFsiIsLastWarpThread();
- private static IPatternTreeNode[] _fsiBeginPatternTree = PatternTrees.GetFsiBeginPattern();
- private static IPatternTreeNode[] _fsiEndPatternTree = PatternTrees.GetFsiEndPattern();
-
- public static void RunPass(DecodedProgram program)
- {
- byte[] externalRegs = new byte[4];
- bool hasGetAddress = false;
-
- foreach (DecodedFunction function in program)
- {
- if (function == program.MainFunction)
- {
- continue;
- }
-
- int externalReg4 = 0;
-
- TreeNode[] functionTree = BuildTree(function.Blocks);
-
- if (Matches(_fsiGetAddressTree, functionTree))
- {
- externalRegs[1] = functionTree[0].GetRd();
- externalRegs[2] = functionTree[2].GetRd();
- externalRegs[3] = functionTree[1].GetRd();
- externalReg4 = functionTree[3].GetRd();
- }
- else if (Matches(_fsiGetAddressV2Tree, functionTree))
- {
- externalRegs[1] = functionTree[2].GetRd();
- externalRegs[2] = functionTree[1].GetRd();
- externalRegs[3] = functionTree[0].GetRd();
- externalReg4 = functionTree[3].GetRd();
- }
-
- // Ensure the register allocation is valid.
- // If so, then we have a match.
- if (externalRegs[1] != externalRegs[2] &&
- externalRegs[2] != externalRegs[3] &&
- externalRegs[1] != externalRegs[3] &&
- externalRegs[1] + 1 != externalRegs[2] &&
- externalRegs[1] + 1 != externalRegs[3] &&
- externalRegs[1] + 1 == externalReg4 &&
- externalRegs[2] != RegisterConsts.RegisterZeroIndex &&
- externalRegs[3] != RegisterConsts.RegisterZeroIndex &&
- externalReg4 != RegisterConsts.RegisterZeroIndex)
- {
- hasGetAddress = true;
- function.Type = FunctionType.Unused;
- break;
- }
- }
-
- foreach (DecodedFunction function in program)
- {
- if (function.IsCompilerGenerated || function == program.MainFunction)
- {
- continue;
- }
-
- if (hasGetAddress)
- {
- TreeNode[] functionTree = BuildTree(function.Blocks);
-
- if (MatchesFsi(_fsiBeginPatternTree, program, function, functionTree, externalRegs))
- {
- function.Type = FunctionType.BuiltInFSIBegin;
- continue;
- }
- else if (MatchesFsi(_fsiEndPatternTree, program, function, functionTree, externalRegs))
- {
- function.Type = FunctionType.BuiltInFSIEnd;
- continue;
- }
- }
- }
- }
-
- private readonly struct TreeNodeUse
- {
- public TreeNode Node { get; }
- public int Index { get; }
- public bool Inverted { get; }
-
- private TreeNodeUse(int index, bool inverted, TreeNode node)
- {
- Index = index;
- Inverted = inverted;
- Node = node;
- }
-
- public TreeNodeUse(int index, TreeNode node) : this(index, false, node)
- {
- }
-
- public TreeNodeUse Flip()
- {
- return new TreeNodeUse(Index, !Inverted, Node);
- }
- }
-
- private enum TreeNodeType : byte
- {
- Op,
- Label
- }
-
- private class TreeNode
- {
- public readonly InstOp Op;
- public readonly List<TreeNodeUse> Uses;
- public TreeNodeType Type { get; }
- public byte Order { get; }
-
- public TreeNode(byte order)
- {
- Type = TreeNodeType.Label;
- Order = order;
- }
-
- public TreeNode(InstOp op, byte order)
- {
- Op = op;
- Uses = new List<TreeNodeUse>();
- Type = TreeNodeType.Op;
- Order = order;
- }
-
- public byte GetPd()
- {
- return (byte)((Op.RawOpCode >> 3) & 7);
- }
-
- public byte GetRd()
- {
- return (byte)Op.RawOpCode;
- }
- }
-
- private static TreeNode[] BuildTree(Block[] blocks)
- {
- List<TreeNode> nodes = new List<TreeNode>();
-
- Dictionary<ulong, TreeNode> labels = new Dictionary<ulong, TreeNode>();
-
- TreeNodeUse[] predDefs = new TreeNodeUse[RegisterConsts.PredsCount];
- TreeNodeUse[] gprDefs = new TreeNodeUse[RegisterConsts.GprsCount];
-
- void DefPred(byte predIndex, int index, TreeNode node)
- {
- if (predIndex != RegisterConsts.PredicateTrueIndex)
- {
- predDefs[predIndex] = new TreeNodeUse(index, node);
- }
- }
-
- void DefGpr(byte regIndex, int index, TreeNode node)
- {
- if (regIndex != RegisterConsts.RegisterZeroIndex)
- {
- gprDefs[regIndex] = new TreeNodeUse(index, node);
- }
- }
-
- TreeNodeUse UsePred(byte predIndex, bool predInv)
- {
- if (predIndex != RegisterConsts.PredicateTrueIndex)
- {
- TreeNodeUse use = predDefs[predIndex];
-
- if (use.Node != null)
- {
- nodes.Remove(use.Node);
- }
- else
- {
- use = new TreeNodeUse(-(predIndex + 2), null);
- }
-
- return predInv ? use.Flip() : use;
- }
-
- return new TreeNodeUse(-1, null);
- }
-
- TreeNodeUse UseGpr(byte regIndex)
- {
- if (regIndex != RegisterConsts.RegisterZeroIndex)
- {
- TreeNodeUse use = gprDefs[regIndex];
-
- if (use.Node != null)
- {
- nodes.Remove(use.Node);
- }
- else
- {
- use = new TreeNodeUse(-(regIndex + 2), null);
- }
-
- return use;
- }
-
- return new TreeNodeUse(-1, null);
- }
-
- byte order = 0;
-
- for (int index = 0; index < blocks.Length; index++)
- {
- Block block = blocks[index];
-
- if (block.Predecessors.Count > 1)
- {
- TreeNode label = new TreeNode(order++);
- nodes.Add(label);
- labels.Add(block.Address, label);
- }
-
- for (int opIndex = 0; opIndex < block.OpCodes.Count; opIndex++)
- {
- InstOp op = block.OpCodes[opIndex];
-
- TreeNode node = new TreeNode(op, IsOrderDependant(op.Name) ? order : (byte)0);
-
- // Add uses.
-
- if (!op.Props.HasFlag(InstProps.NoPred))
- {
- byte predIndex = (byte)((op.RawOpCode >> 16) & 7);
- bool predInv = (op.RawOpCode & 0x80000) != 0;
- node.Uses.Add(UsePred(predIndex, predInv));
- }
-
- if (op.Props.HasFlag(InstProps.Ps))
- {
- byte predIndex = (byte)((op.RawOpCode >> 39) & 7);
- bool predInv = (op.RawOpCode & 0x40000000000) != 0;
- node.Uses.Add(UsePred(predIndex, predInv));
- }
-
- if (op.Props.HasFlag(InstProps.Ra))
- {
- byte ra = (byte)(op.RawOpCode >> 8);
- node.Uses.Add(UseGpr(ra));
- }
-
- if ((op.Props & (InstProps.Rb | InstProps.Rb2)) != 0)
- {
- byte rb = op.Props.HasFlag(InstProps.Rb2) ? (byte)op.RawOpCode : (byte)(op.RawOpCode >> 20);
- node.Uses.Add(UseGpr(rb));
- }
-
- if (op.Props.HasFlag(InstProps.Rc))
- {
- byte rc = (byte)(op.RawOpCode >> 39);
- node.Uses.Add(UseGpr(rc));
- }
-
- if (op.Name == InstName.Bra && labels.TryGetValue(op.GetAbsoluteAddress(), out TreeNode label))
- {
- node.Uses.Add(new TreeNodeUse(0, label));
- }
-
- // Make definitions.
-
- int defIndex = 0;
-
- InstProps pdType = op.Props & InstProps.PdMask;
-
- if (pdType != 0)
- {
- int bit = pdType switch
- {
- InstProps.Pd => 3,
- InstProps.LPd => 48,
- InstProps.SPd => 30,
- InstProps.TPd => 51,
- InstProps.VPd => 45,
- _ => throw new InvalidOperationException($"Table has unknown predicate destination {pdType}.")
- };
-
- byte predIndex = (byte)((op.RawOpCode >> bit) & 7);
- DefPred(predIndex, defIndex++, node);
- }
-
- if (op.Props.HasFlag(InstProps.Rd))
- {
- byte rd = (byte)op.RawOpCode;
- DefGpr(rd, defIndex++, node);
- }
-
- nodes.Add(node);
- }
- }
-
- return nodes.ToArray();
- }
-
- private static bool IsOrderDependant(InstName name)
- {
- switch (name)
- {
- case InstName.Atom:
- case InstName.AtomCas:
- case InstName.Atoms:
- case InstName.AtomsCas:
- case InstName.Ld:
- case InstName.Ldg:
- case InstName.Ldl:
- case InstName.Lds:
- case InstName.Suatom:
- case InstName.SuatomB:
- case InstName.SuatomB2:
- case InstName.SuatomCas:
- case InstName.SuatomCasB:
- case InstName.Suld:
- case InstName.SuldB:
- case InstName.SuldD:
- case InstName.SuldDB:
- return true;
- }
-
- return false;
- }
-
- private interface IPatternTreeNode
- {
- List<PatternTreeNodeUse> Uses { get; }
- InstName Name { get; }
- TreeNodeType Type { get; }
- byte Order { get; }
- bool IsImm { get; }
- bool Matches(in InstOp opInfo);
- }
-
- private readonly struct PatternTreeNodeUse
- {
- public IPatternTreeNode Node { get; }
- public int Index { get; }
- public bool Inverted { get; }
- public PatternTreeNodeUse Inv => new PatternTreeNodeUse(Index, !Inverted, Node);
-
- private PatternTreeNodeUse(int index, bool inverted, IPatternTreeNode node)
- {
- Index = index;
- Inverted = inverted;
- Node = node;
- }
-
- public PatternTreeNodeUse(int index, IPatternTreeNode node) : this(index, false, node)
- {
- }
- }
-
- private class PatternTreeNode<T> : IPatternTreeNode
- {
- public List<PatternTreeNodeUse> Uses { get; }
- private readonly Func<T, bool> _match;
-
- public InstName Name { get; }
- public TreeNodeType Type { get; }
- public byte Order { get; }
- public bool IsImm { get; }
- public PatternTreeNodeUse Out => new PatternTreeNodeUse(0, this);
-
- public PatternTreeNode(InstName name, Func<T, bool> match, TreeNodeType type = TreeNodeType.Op, byte order = 0, bool isImm = false)
- {
- Name = name;
- _match = match;
- Type = type;
- Order = order;
- IsImm = isImm;
- Uses = new List<PatternTreeNodeUse>();
- }
-
- public PatternTreeNode<T> Use(PatternTreeNodeUse use)
- {
- Uses.Add(use);
- return this;
- }
-
- public PatternTreeNodeUse OutAt(int index)
- {
- return new PatternTreeNodeUse(index, this);
- }
-
- public bool Matches(in InstOp opInfo)
- {
- if (opInfo.Name != Name)
- {
- return false;
- }
-
- ulong rawOp = opInfo.RawOpCode;
- T op = Unsafe.As<ulong, T>(ref rawOp);
-
- if (!_match(op))
- {
- return false;
- }
-
- return true;
- }
- }
-
- private static bool MatchesFsi(
- IPatternTreeNode[] pattern,
- DecodedProgram program,
- DecodedFunction function,
- TreeNode[] functionTree,
- byte[] externalRegs)
- {
- if (function.Blocks.Length == 0)
- {
- return false;
- }
-
- InstOp callOp = function.Blocks[0].GetLastOp();
-
- if (callOp.Name != InstName.Cal)
- {
- return false;
- }
-
- DecodedFunction callTarget = program.GetFunctionByAddress(callOp.GetAbsoluteAddress());
- TreeNode[] callTargetTree = null;
-
- if (callTarget == null || !Matches(_fsiIsLastWarpThreadPatternTree, callTargetTree = BuildTree(callTarget.Blocks)))
- {
- return false;
- }
-
- externalRegs[0] = callTargetTree[0].GetPd();
-
- if (Matches(pattern, functionTree, externalRegs))
- {
- callTarget.RemoveCaller(function);
- return true;
- }
-
- return false;
- }
-
- private static bool Matches(IPatternTreeNode[] pTree, TreeNode[] cTree, byte[] externalRegs = null)
- {
- if (pTree.Length != cTree.Length)
- {
- return false;
- }
-
- for (int index = 0; index < pTree.Length; index++)
- {
- if (!Matches(pTree[index], cTree[index], externalRegs))
- {
- return false;
- }
- }
-
- return true;
- }
-
- private static bool Matches(IPatternTreeNode pTreeNode, TreeNode cTreeNode, byte[] externalRegs)
- {
- if (!pTreeNode.Matches(in cTreeNode.Op) ||
- pTreeNode.Type != cTreeNode.Type ||
- pTreeNode.Order != cTreeNode.Order ||
- pTreeNode.IsImm != cTreeNode.Op.Props.HasFlag(InstProps.Ib))
- {
- return false;
- }
-
- if (pTreeNode.Type == TreeNodeType.Op)
- {
- if (pTreeNode.Uses.Count != cTreeNode.Uses.Count)
- {
- return false;
- }
-
- for (int index = 0; index < pTreeNode.Uses.Count; index++)
- {
- var pUse = pTreeNode.Uses[index];
- var cUse = cTreeNode.Uses[index];
-
- if (pUse.Index <= -2)
- {
- if (externalRegs[-pUse.Index - 2] != (-cUse.Index - 2))
- {
- return false;
- }
- }
- else if (pUse.Index != cUse.Index)
- {
- return false;
- }
-
- if (pUse.Inverted != cUse.Inverted || (pUse.Node == null) != (cUse.Node == null))
- {
- return false;
- }
-
- if (pUse.Node != null && !Matches(pUse.Node, cUse.Node, externalRegs))
- {
- return false;
- }
- }
- }
-
- return true;
- }
-
- private static class PatternTrees
- {
- public static IPatternTreeNode[] GetFsiGetAddress()
- {
- var affinityValue = S2r(SReg.Affinity).Use(PT).Out;
- var orderingTicketValue = S2r(SReg.OrderingTicket).Use(PT).Out;
-
- return new IPatternTreeNode[]
- {
- Iscadd(cc: true, 2, 0, 404)
- .Use(PT)
- .Use(Iscadd(cc: false, 8)
- .Use(PT)
- .Use(Lop32i(LogicOp.And, 0xff)
- .Use(PT)
- .Use(affinityValue).Out)
- .Use(Lop32i(LogicOp.And, 0xff)
- .Use(PT)
- .Use(orderingTicketValue).Out).Out),
- ShrU32W(16)
- .Use(PT)
- .Use(orderingTicketValue),
- Iadd32i(0x200)
- .Use(PT)
- .Use(Lop32i(LogicOp.And, 0xfe00)
- .Use(PT)
- .Use(orderingTicketValue).Out),
- Iadd(x: true, 0, 405).Use(PT).Use(RZ),
- Ret().Use(PT)
- };
- }
-
- public static IPatternTreeNode[] GetFsiGetAddressV2()
- {
- var affinityValue = S2r(SReg.Affinity).Use(PT).Out;
- var orderingTicketValue = S2r(SReg.OrderingTicket).Use(PT).Out;
-
- return new IPatternTreeNode[]
- {
- ShrU32W(16)
- .Use(PT)
- .Use(orderingTicketValue),
- Iadd32i(0x200)
- .Use(PT)
- .Use(Lop32i(LogicOp.And, 0xfe00)
- .Use(PT)
- .Use(orderingTicketValue).Out),
- Iscadd(cc: true, 2, 0, 404)
- .Use(PT)
- .Use(Bfi(0x808)
- .Use(PT)
- .Use(affinityValue)
- .Use(Lop32i(LogicOp.And, 0xff)
- .Use(PT)
- .Use(orderingTicketValue).Out).Out),
- Iadd(x: true, 0, 405).Use(PT).Use(RZ),
- Ret().Use(PT)
- };
- }
-
- public static IPatternTreeNode[] GetFsiIsLastWarpThread()
- {
- var threadKillValue = S2r(SReg.ThreadKill).Use(PT).Out;
- var laneIdValue = S2r(SReg.LaneId).Use(PT).Out;
-
- return new IPatternTreeNode[]
- {
- IsetpU32(IComp.Eq)
- .Use(PT)
- .Use(PT)
- .Use(FloU32()
- .Use(PT)
- .Use(Vote(VoteMode.Any)
- .Use(PT)
- .Use(IsetpU32(IComp.Ne)
- .Use(PT)
- .Use(PT)
- .Use(Lop(negB: true, LogicOp.PassB)
- .Use(PT)
- .Use(RZ)
- .Use(threadKillValue).OutAt(1))
- .Use(RZ).Out).OutAt(1)).Out)
- .Use(laneIdValue),
- Ret().Use(PT)
- };
- }
-
- public static IPatternTreeNode[] GetFsiBeginPattern()
- {
- var addressLowValue = CallArg(1);
-
- static PatternTreeNodeUse HighU16Equals(PatternTreeNodeUse x)
- {
- var expectedValue = CallArg(3);
-
- return IsetpU32(IComp.Eq)
- .Use(PT)
- .Use(PT)
- .Use(ShrU32W(16).Use(PT).Use(x).Out)
- .Use(expectedValue).Out;
- }
-
- PatternTreeNode<byte> label;
-
- return new IPatternTreeNode[]
- {
- Cal(),
- Ret().Use(CallArg(0).Inv),
- Ret()
- .Use(HighU16Equals(LdgE(CacheOpLd.Cg, LsSize.B32)
- .Use(PT)
- .Use(addressLowValue).Out)),
- label = Label(),
- Bra()
- .Use(HighU16Equals(LdgE(CacheOpLd.Cg, LsSize.B32, 1)
- .Use(PT)
- .Use(addressLowValue).Out).Inv)
- .Use(label.Out),
- Ret().Use(PT)
- };
- }
-
- public static IPatternTreeNode[] GetFsiEndPattern()
- {
- var voteResult = Vote(VoteMode.All).Use(PT).Use(PT).OutAt(1);
- var popcResult = Popc().Use(PT).Use(voteResult).Out;
- var threadKillValue = S2r(SReg.ThreadKill).Use(PT).Out;
- var laneIdValue = S2r(SReg.LaneId).Use(PT).Out;
-
- var addressLowValue = CallArg(1);
- var incrementValue = CallArg(2);
-
- return new IPatternTreeNode[]
- {
- Cal(),
- Ret().Use(CallArg(0).Inv),
- Membar(Decoders.Membar.Vc).Use(PT),
- Ret().Use(IsetpU32(IComp.Ne)
- .Use(PT)
- .Use(PT)
- .Use(threadKillValue)
- .Use(RZ).Out),
- RedE(RedOp.Add, AtomSize.U32)
- .Use(IsetpU32(IComp.Eq)
- .Use(PT)
- .Use(PT)
- .Use(FloU32()
- .Use(PT)
- .Use(voteResult).Out)
- .Use(laneIdValue).Out)
- .Use(addressLowValue)
- .Use(Xmad(XmadCop.Cbcc, psl: true, hiloA: true, hiloB: true)
- .Use(PT)
- .Use(incrementValue)
- .Use(Xmad(XmadCop.Cfull, mrg: true, hiloB: true)
- .Use(PT)
- .Use(incrementValue)
- .Use(popcResult)
- .Use(RZ).Out)
- .Use(Xmad(XmadCop.Cfull)
- .Use(PT)
- .Use(incrementValue)
- .Use(popcResult)
- .Use(RZ).Out).Out),
- Ret().Use(PT)
- };
- }
-
- private static PatternTreeNode<InstBfiI> Bfi(int imm)
- {
- return new(InstName.Bfi, (op) => !op.WriteCC && op.Imm20 == imm, isImm: true);
- }
-
- private static PatternTreeNode<InstBra> Bra()
- {
- return new(InstName.Bra, (op) => op.Ccc == Ccc.T && !op.Ca);
- }
-
- private static PatternTreeNode<InstCal> Cal()
- {
- return new(InstName.Cal, (op) => !op.Ca && op.Inc);
- }
-
- private static PatternTreeNode<InstFloR> FloU32()
- {
- return new(InstName.Flo, (op) => !op.Signed && !op.Sh && !op.NegB && !op.WriteCC);
- }
-
- private static PatternTreeNode<InstIaddC> Iadd(bool x, int cbufSlot, int cbufOffset)
- {
- return new(InstName.Iadd, (op) =>
- !op.Sat &&
- !op.WriteCC &&
- op.X == x &&
- op.AvgMode == AvgMode.NoNeg &&
- op.CbufSlot == cbufSlot &&
- op.CbufOffset == cbufOffset);
- }
-
- private static PatternTreeNode<InstIadd32i> Iadd32i(int imm)
- {
- return new(InstName.Iadd32i, (op) => !op.Sat && !op.WriteCC && !op.X && op.AvgMode == AvgMode.NoNeg && op.Imm32 == imm);
- }
-
- private static PatternTreeNode<InstIscaddR> Iscadd(bool cc, int imm)
- {
- return new(InstName.Iscadd, (op) => op.WriteCC == cc && op.AvgMode == AvgMode.NoNeg && op.Imm5 == imm);
- }
-
- private static PatternTreeNode<InstIscaddC> Iscadd(bool cc, int imm, int cbufSlot, int cbufOffset)
- {
- return new(InstName.Iscadd, (op) =>
- op.WriteCC == cc &&
- op.AvgMode == AvgMode.NoNeg &&
- op.Imm5 == imm &&
- op.CbufSlot == cbufSlot &&
- op.CbufOffset == cbufOffset);
- }
-
- private static PatternTreeNode<InstIsetpR> IsetpU32(IComp comp)
- {
- return new(InstName.Isetp, (op) => !op.Signed && op.IComp == comp && op.Bop == BoolOp.And);
- }
-
- private static PatternTreeNode<byte> Label()
- {
- return new(InstName.Invalid, (op) => true, type: TreeNodeType.Label);
- }
-
- private static PatternTreeNode<InstLopR> Lop(bool negB, LogicOp logicOp)
- {
- return new(InstName.Lop, (op) => !op.NegA && op.NegB == negB && !op.WriteCC && !op.X && op.Lop == logicOp && op.PredicateOp == PredicateOp.F);
- }
-
- private static PatternTreeNode<InstLop32i> Lop32i(LogicOp logicOp, int imm)
- {
- return new(InstName.Lop32i, (op) => !op.NegA && !op.NegB && !op.X && !op.WriteCC && op.LogicOp == logicOp && op.Imm32 == imm);
- }
-
- private static PatternTreeNode<InstMembar> Membar(Membar membar)
- {
- return new(InstName.Membar, (op) => op.Membar == membar);
- }
-
- private static PatternTreeNode<InstPopcR> Popc()
- {
- return new(InstName.Popc, (op) => !op.NegB);
- }
-
- private static PatternTreeNode<InstRet> Ret()
- {
- return new(InstName.Ret, (op) => op.Ccc == Ccc.T);
- }
-
- private static PatternTreeNode<InstS2r> S2r(SReg reg)
- {
- return new(InstName.S2r, (op) => op.SReg == reg);
- }
-
- private static PatternTreeNode<InstShrI> ShrU32W(int imm)
- {
- return new(InstName.Shr, (op) => !op.Signed && !op.Brev && op.M && op.XMode == 0 && op.Imm20 == imm, isImm: true);
- }
-
- private static PatternTreeNode<InstLdg> LdgE(CacheOpLd cacheOp, LsSize size, byte order = 0)
- {
- return new(InstName.Ldg, (op) => op.E && op.CacheOp == cacheOp && op.LsSize == size, order: order);
- }
-
- private static PatternTreeNode<InstRed> RedE(RedOp redOp, AtomSize size, byte order = 0)
- {
- return new(InstName.Red, (op) => op.E && op.RedOp == redOp && op.RedSize == size, order: order);
- }
-
- private static PatternTreeNode<InstVote> Vote(VoteMode mode)
- {
- return new(InstName.Vote, (op) => op.VoteMode == mode);
- }
-
- private static PatternTreeNode<InstXmadR> Xmad(XmadCop cop, bool psl = false, bool mrg = false, bool hiloA = false, bool hiloB = false)
- {
- return new(InstName.Xmad, (op) => op.XmadCop == cop && op.Psl == psl && op.Mrg == mrg && op.HiloA == hiloA && op.HiloB == hiloB);
- }
-
- private static PatternTreeNodeUse PT => PTOrRZ();
- private static PatternTreeNodeUse RZ => PTOrRZ();
- private static PatternTreeNodeUse Undef => new PatternTreeNodeUse(0, null);
-
- private static PatternTreeNodeUse CallArg(int index)
- {
- return new PatternTreeNodeUse(-(index + 2), null);
- }
-
- private static PatternTreeNodeUse PTOrRZ()
- {
- return new PatternTreeNodeUse(-1, null);
- }
- }
-
- private static void PrintTreeNode(TreeNode node, string indentation)
- {
- Console.WriteLine($" {node.Op.Name}");
-
- for (int i = 0; i < node.Uses.Count; i++)
- {
- TreeNodeUse use = node.Uses[i];
- bool last = i == node.Uses.Count - 1;
- char separator = last ? '`' : '|';
-
- if (use.Node != null)
- {
- Console.Write($"{indentation} {separator}- ({(use.Inverted ? "INV " : "")}{use.Index})");
- PrintTreeNode(use.Node, indentation + (last ? " " : " | "));
- }
- else
- {
- Console.WriteLine($"{indentation} {separator}- ({(use.Inverted ? "INV " : "")}{use.Index}) NULL");
- }
- }
- }
-
- private static void PrintTreeNode(IPatternTreeNode node, string indentation)
- {
- Console.WriteLine($" {node.Name}");
-
- for (int i = 0; i < node.Uses.Count; i++)
- {
- PatternTreeNodeUse use = node.Uses[i];
- bool last = i == node.Uses.Count - 1;
- char separator = last ? '`' : '|';
-
- if (use.Node != null)
- {
- Console.Write($"{indentation} {separator}- ({(use.Inverted ? "INV " : "")}{use.Index})");
- PrintTreeNode(use.Node, indentation + (last ? " " : " | "));
- }
- else
- {
- Console.WriteLine($"{indentation} {separator}- ({(use.Inverted ? "INV " : "")}{use.Index}) NULL");
- }
- }
- }
- }
-}