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