mirror of
				https://github.com/ryujinx-mirror/ryujinx.git
				synced 2025-11-04 08:59:04 -06:00 
			
		
		
		
	JIT: Coalesce copies on LSRA with simple register preferencing (#6950)
* JIT: Coalesce copies on LSRA with simple register preferencing * PPTC version bump
This commit is contained in:
		@@ -251,7 +251,20 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int selectedReg = GetHighestValueIndex(freePositions);
 | 
			
		||||
            // If this is a copy destination variable, we prefer the register used for the copy source.
 | 
			
		||||
            // If the register is available, then the copy can be eliminated later as both source
 | 
			
		||||
            // and destination will use the same register.
 | 
			
		||||
            int selectedReg;
 | 
			
		||||
 | 
			
		||||
            if (current.TryGetCopySourceRegister(out int preferredReg) && freePositions[preferredReg] >= current.GetEnd())
 | 
			
		||||
            {
 | 
			
		||||
                selectedReg = preferredReg;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                selectedReg = GetHighestValueIndex(freePositions);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int selectedNextUse = freePositions[selectedReg];
 | 
			
		||||
 | 
			
		||||
            // Intervals starts and ends at odd positions, unless they span an entire
 | 
			
		||||
@@ -431,7 +444,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static int GetHighestValueIndex(Span<int> span)
 | 
			
		||||
        private static int GetHighestValueIndex(ReadOnlySpan<int> span)
 | 
			
		||||
        {
 | 
			
		||||
            int highest = int.MinValue;
 | 
			
		||||
 | 
			
		||||
@@ -798,12 +811,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
 | 
			
		||||
            // The "visited" state is stored in the MSB of the local's value.
 | 
			
		||||
            const ulong VisitedMask = 1ul << 63;
 | 
			
		||||
 | 
			
		||||
            bool IsVisited(Operand local)
 | 
			
		||||
            static bool IsVisited(Operand local)
 | 
			
		||||
            {
 | 
			
		||||
                return (local.GetValueUnsafe() & VisitedMask) != 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            void SetVisited(Operand local)
 | 
			
		||||
            static void SetVisited(Operand local)
 | 
			
		||||
            {
 | 
			
		||||
                local.GetValueUnsafe() |= VisitedMask;
 | 
			
		||||
            }
 | 
			
		||||
@@ -826,9 +839,25 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
 | 
			
		||||
                        {
 | 
			
		||||
                            dest.NumberLocal(_intervals.Count);
 | 
			
		||||
 | 
			
		||||
                            _intervals.Add(new LiveInterval(dest));
 | 
			
		||||
                            LiveInterval interval = new LiveInterval(dest);
 | 
			
		||||
                            _intervals.Add(interval);
 | 
			
		||||
 | 
			
		||||
                            SetVisited(dest);
 | 
			
		||||
 | 
			
		||||
                            // If this is a copy (or copy-like operation), set the copy source interval as well.
 | 
			
		||||
                            // This is used for register preferencing later on, which allows the copy to be eliminated
 | 
			
		||||
                            // in some cases.
 | 
			
		||||
                            if (node.Instruction == Instruction.Copy || node.Instruction == Instruction.ZeroExtend32)
 | 
			
		||||
                            {
 | 
			
		||||
                                Operand source = node.GetSource(0);
 | 
			
		||||
 | 
			
		||||
                                if (source.Kind == OperandKind.LocalVariable &&
 | 
			
		||||
                                    source.GetLocalNumber() > 0 &&
 | 
			
		||||
                                    (node.Instruction == Instruction.Copy || source.Type == OperandType.I32))
 | 
			
		||||
                                {
 | 
			
		||||
                                    interval.SetCopySource(_intervals[source.GetLocalNumber()]);
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
 | 
			
		||||
            public LiveRange CurrRange;
 | 
			
		||||
 | 
			
		||||
            public LiveInterval Parent;
 | 
			
		||||
            public LiveInterval CopySource;
 | 
			
		||||
 | 
			
		||||
            public UseList Uses;
 | 
			
		||||
            public LiveIntervalList Children;
 | 
			
		||||
@@ -37,6 +38,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
 | 
			
		||||
        private ref LiveRange CurrRange => ref _data->CurrRange;
 | 
			
		||||
        private ref LiveRange PrevRange => ref _data->PrevRange;
 | 
			
		||||
        private ref LiveInterval Parent => ref _data->Parent;
 | 
			
		||||
        private ref LiveInterval CopySource => ref _data->CopySource;
 | 
			
		||||
        private ref UseList Uses => ref _data->Uses;
 | 
			
		||||
        private ref LiveIntervalList Children => ref _data->Children;
 | 
			
		||||
 | 
			
		||||
@@ -78,6 +80,25 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
 | 
			
		||||
            Register = register;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void SetCopySource(LiveInterval copySource)
 | 
			
		||||
        {
 | 
			
		||||
            CopySource = copySource;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool TryGetCopySourceRegister(out int copySourceRegIndex)
 | 
			
		||||
        {
 | 
			
		||||
            if (CopySource._data != null)
 | 
			
		||||
            {
 | 
			
		||||
                copySourceRegIndex = CopySource.Register.Index;
 | 
			
		||||
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            copySourceRegIndex = 0;
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Reset()
 | 
			
		||||
        {
 | 
			
		||||
            PrevRange = default;
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ namespace ARMeilleure.Translation.PTC
 | 
			
		||||
        private const string OuterHeaderMagicString = "PTCohd\0\0";
 | 
			
		||||
        private const string InnerHeaderMagicString = "PTCihd\0\0";
 | 
			
		||||
 | 
			
		||||
        private const uint InternalVersion = 6634; //! To be incremented manually for each change to the ARMeilleure project.
 | 
			
		||||
        private const uint InternalVersion = 6950; //! To be incremented manually for each change to the ARMeilleure project.
 | 
			
		||||
 | 
			
		||||
        private const string ActualDir = "0";
 | 
			
		||||
        private const string BackupDir = "1";
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user