| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866 |
- 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");
- }
- }
- }
- }
- }
|