Simplification.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. using ARMeilleure.IntermediateRepresentation;
  2. using System;
  3. using static ARMeilleure.IntermediateRepresentation.OperandHelper;
  4. namespace ARMeilleure.CodeGen.Optimizations
  5. {
  6. static class Simplification
  7. {
  8. public static void RunPass(Operation operation)
  9. {
  10. switch (operation.Instruction)
  11. {
  12. case Instruction.Add:
  13. if (operation.GetSource(0).Relocatable ||
  14. operation.GetSource(1).Relocatable)
  15. {
  16. break;
  17. }
  18. TryEliminateBinaryOpComutative(operation, 0);
  19. break;
  20. case Instruction.BitwiseAnd:
  21. TryEliminateBitwiseAnd(operation);
  22. break;
  23. case Instruction.BitwiseOr:
  24. TryEliminateBitwiseOr(operation);
  25. break;
  26. case Instruction.BitwiseExclusiveOr:
  27. TryEliminateBitwiseExclusiveOr(operation);
  28. break;
  29. case Instruction.ConditionalSelect:
  30. TryEliminateConditionalSelect(operation);
  31. break;
  32. case Instruction.Divide:
  33. TryEliminateBinaryOpY(operation, 1);
  34. break;
  35. case Instruction.Multiply:
  36. TryEliminateBinaryOpComutative(operation, 1);
  37. break;
  38. case Instruction.ShiftLeft:
  39. case Instruction.ShiftRightSI:
  40. case Instruction.ShiftRightUI:
  41. case Instruction.Subtract:
  42. TryEliminateBinaryOpY(operation, 0);
  43. break;
  44. }
  45. }
  46. private static void TryEliminateBitwiseAnd(Operation operation)
  47. {
  48. // Try to recognize and optimize those 3 patterns (in order):
  49. // x & 0xFFFFFFFF == x, 0xFFFFFFFF & y == y,
  50. // x & 0x00000000 == 0x00000000, 0x00000000 & y == 0x00000000
  51. Operand x = operation.GetSource(0);
  52. Operand y = operation.GetSource(1);
  53. if (IsConstEqual(x, AllOnes(x.Type)))
  54. {
  55. operation.TurnIntoCopy(y);
  56. }
  57. else if (IsConstEqual(y, AllOnes(y.Type)))
  58. {
  59. operation.TurnIntoCopy(x);
  60. }
  61. else if (IsConstEqual(x, 0) || IsConstEqual(y, 0))
  62. {
  63. operation.TurnIntoCopy(Const(0));
  64. }
  65. }
  66. private static void TryEliminateBitwiseOr(Operation operation)
  67. {
  68. // Try to recognize and optimize those 3 patterns (in order):
  69. // x | 0x00000000 == x, 0x00000000 | y == y,
  70. // x | 0xFFFFFFFF == 0xFFFFFFFF, 0xFFFFFFFF | y == 0xFFFFFFFF
  71. Operand x = operation.GetSource(0);
  72. Operand y = operation.GetSource(1);
  73. if (IsConstEqual(x, 0))
  74. {
  75. operation.TurnIntoCopy(y);
  76. }
  77. else if (IsConstEqual(y, 0))
  78. {
  79. operation.TurnIntoCopy(x);
  80. }
  81. else if (IsConstEqual(x, AllOnes(x.Type)) || IsConstEqual(y, AllOnes(y.Type)))
  82. {
  83. operation.TurnIntoCopy(Const(AllOnes(x.Type)));
  84. }
  85. }
  86. private static void TryEliminateBitwiseExclusiveOr(Operation operation)
  87. {
  88. // Try to recognize and optimize those 2 patterns (in order):
  89. // x ^ y == 0x00000000 when x == y
  90. // 0x00000000 ^ y == y, x ^ 0x00000000 == x
  91. Operand x = operation.GetSource(0);
  92. Operand y = operation.GetSource(1);
  93. if (x == y && x.Type.IsInteger())
  94. {
  95. operation.TurnIntoCopy(Const(x.Type, 0));
  96. }
  97. else
  98. {
  99. TryEliminateBinaryOpComutative(operation, 0);
  100. }
  101. }
  102. private static void TryEliminateBinaryOpY(Operation operation, ulong comparand)
  103. {
  104. Operand x = operation.GetSource(0);
  105. Operand y = operation.GetSource(1);
  106. if (IsConstEqual(y, comparand))
  107. {
  108. operation.TurnIntoCopy(x);
  109. }
  110. }
  111. private static void TryEliminateBinaryOpComutative(Operation operation, ulong comparand)
  112. {
  113. Operand x = operation.GetSource(0);
  114. Operand y = operation.GetSource(1);
  115. if (IsConstEqual(x, comparand))
  116. {
  117. operation.TurnIntoCopy(y);
  118. }
  119. else if (IsConstEqual(y, comparand))
  120. {
  121. operation.TurnIntoCopy(x);
  122. }
  123. }
  124. private static void TryEliminateConditionalSelect(Operation operation)
  125. {
  126. Operand cond = operation.GetSource(0);
  127. if (cond.Kind != OperandKind.Constant)
  128. {
  129. return;
  130. }
  131. // The condition is constant, we can turn it into a copy, and select
  132. // the source based on the condition value.
  133. int srcIndex = cond.Value != 0 ? 1 : 2;
  134. Operand source = operation.GetSource(srcIndex);
  135. operation.TurnIntoCopy(source);
  136. }
  137. private static bool IsConstEqual(Operand operand, ulong comparand)
  138. {
  139. if (operand.Kind != OperandKind.Constant || !operand.Type.IsInteger())
  140. {
  141. return false;
  142. }
  143. return operand.Value == comparand;
  144. }
  145. private static ulong AllOnes(OperandType type)
  146. {
  147. switch (type)
  148. {
  149. case OperandType.I32: return ~0U;
  150. case OperandType.I64: return ~0UL;
  151. }
  152. throw new ArgumentException("Invalid operand type \"" + type + "\".");
  153. }
  154. }
  155. }