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 }