UseList.cs 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. using System;
  2. namespace ARMeilleure.CodeGen.RegisterAllocators
  3. {
  4. unsafe struct UseList
  5. {
  6. private int* _items;
  7. private int _capacity;
  8. private int _count;
  9. public int Count => _count;
  10. public int FirstUse => _count > 0 ? _items[_count - 1] : LiveInterval.NotFound;
  11. public Span<int> Span => new(_items, _count);
  12. public void Add(int position)
  13. {
  14. if (_count + 1 > _capacity)
  15. {
  16. var oldSpan = Span;
  17. _capacity = Math.Max(4, _capacity * 2);
  18. _items = Allocators.Default.Allocate<int>((uint)_capacity);
  19. var newSpan = Span;
  20. oldSpan.CopyTo(newSpan);
  21. }
  22. // Use positions are usually inserted in descending order, so inserting in descending order is faster,
  23. // since the number of half exchanges is reduced.
  24. int i = _count - 1;
  25. while (i >= 0 && _items[i] < position)
  26. {
  27. _items[i + 1] = _items[i--];
  28. }
  29. _items[i + 1] = position;
  30. _count++;
  31. }
  32. public int NextUse(int position)
  33. {
  34. int index = NextUseIndex(position);
  35. return index != LiveInterval.NotFound ? _items[index] : LiveInterval.NotFound;
  36. }
  37. public int NextUseIndex(int position)
  38. {
  39. int i = _count - 1;
  40. if (i == -1 || position > _items[0])
  41. {
  42. return LiveInterval.NotFound;
  43. }
  44. while (i >= 0 && _items[i] < position)
  45. {
  46. i--;
  47. }
  48. return i;
  49. }
  50. public UseList Split(int position)
  51. {
  52. int index = NextUseIndex(position);
  53. // Since the list is in descending order, the new split list takes the front of the list and the current
  54. // list takes the back of the list.
  55. UseList result = new();
  56. result._count = index + 1;
  57. result._capacity = result._count;
  58. result._items = _items;
  59. _count = _count - result._count;
  60. _capacity = _count;
  61. _items = _items + result._count;
  62. return result;
  63. }
  64. }
  65. }