public void EmitMul(Type type, bool @checked) { if (@checked) { Emit(MulOvfInstruction.Create(type)); } else { Emit(MulInstruction.Create(type)); } }
// Replaces copy and multiplication loops with Mul (clear loop [-] will also be replaced with Clear) // [->++>>>+++++>++<+<<<<<] becomes Mul(1,2) Mul(4,5) Mul(5,2) Mul(6,1) Clear(0) public List <InstructionBase> OptimizeCopyMultiplyLoop(List <InstructionBase> instructions) { List <InstructionBase> optimized = new List <InstructionBase>(); int i = 0; while (true) { int previousI = i; // Find next leaf loop (loop without inner loop) bool found = false; while (i < instructions.Count) { if (instructions[i] is OpenInstruction) { found = true; break; } i++; } if (!found) // no Open found { optimized.AddRange(instructions.Skip(previousI)); // copy remaining instructions break; } int j = i + 1; found = false; while (j < instructions.Count) { if (instructions[j] is CloseInstruction) { found = true; break; } if (instructions[j] is OpenInstruction) { i = j; } j++; } if (!found) // no leaf loop found { optimized.AddRange(instructions.Skip(previousI)); // copy remaining instructions break; } // copy instructions before loop optimized.AddRange(instructions.Skip(previousI).Take(i - previousI)); // check it contains only Add, Sub, Left, Right List <InstructionBase> loopInstructions = instructions.Skip(i + 1).Take(j - i - 1).ToList(); bool ok = loopInstructions.All(x => x is ArithmeticInstructionBase || x is PositionInstructionBase); if (!ok) { optimized.AddRange(instructions.Skip(i).Take(j - i + 1)); // copy loop instructions i = j + 1; continue; // search another loop } // interpret loop and track pointer position and what arithmetic operations it carries out Dictionary <int, int> mem = new Dictionary <int, int>(); int p = 0; foreach (InstructionBase instruction in loopInstructions) // contains only Add/Sub/Left/Right { switch (instruction) { // Add case AddInstruction add: mem[p + add.Offset] = mem.Get(p + add.Offset, 0) + add.X; break; // Sub case SubInstruction sub: mem[p + sub.Offset] = mem.Get(p + sub.Offset, 0) - sub.X; break; // Left case LeftInstruction left: p -= left.X; break; // Right case RightInstruction right: p += right.X; break; } } // if pointed ended where it started and we subtracted exactly 1 from cell 0, then loop can be replaced with copy/mul instruction if (p != 0 || mem.Get(0, 0) != -1) // not a copy/mul instruction { optimized.AddRange(instructions.Skip(i).Take(j - i + 1)); // copy loop instructions i = j + 1; continue; } mem.Remove(0); Debug.Write($"Replacing loop {string.Join(" ", loopInstructions.Select(x => x.ToIntermediateRepresentation()))} with "); // add Mul operations foreach (KeyValuePair <int, int> kv in mem) { MulInstruction mulInstruction = new MulInstruction { Factor = (short)kv.Value, Offset = kv.Key, }; optimized.Add(mulInstruction); Debug.Write($"{mulInstruction.ToIntermediateRepresentation()}, "); } // add Clear operation ClearInstruction clearInstruction = new ClearInstruction(); optimized.Add(clearInstruction); Debug.WriteLine(clearInstruction.ToIntermediateRepresentation()); // i = j + 1; } return(optimized); }
public void EmitMul(Type type, bool @checked) { Emit(@checked ? MulOvfInstruction.Create(type) : MulInstruction.Create(type)); }
private bool GenerateNode(out OneOperandNode node) { node = null; InstructionToken instructionToken; if (this.ExpectInstructionToken(out instructionToken)) { Instructions instruction = instructionToken.Instruction; switch (instruction) { case Instructions.Mov: { Token operand1; Token operand2; if (this.ExpectTwoOperands(out operand1, out operand2)) { node = new MovInstruction(this.rawInput, instructionToken, operand1, operand2); } else { this.LogExpectedTwoOperandsError(instructionToken); return(false); } } break; case Instructions.Add: { Token operand1; Token operand2; if (this.ExpectTwoOperands(out operand1, out operand2)) { node = new AddInstruction(this.rawInput, instructionToken, operand1, operand2); } else { this.LogExpectedTwoOperandsError(instructionToken); return(false); } } break; case Instructions.Sub: { Token operand1; Token operand2; if (this.ExpectTwoOperands(out operand1, out operand2)) { node = new SubInstruction(this.rawInput, instructionToken, operand1, operand2); } else { this.LogExpectedTwoOperandsError(instructionToken); return(false); } } break; case Instructions.Mul: { Token operand1; Token operand2; if (this.ExpectTwoOperands(out operand1, out operand2)) { node = new MulInstruction(this.rawInput, instructionToken, operand1, operand2); } else { this.LogExpectedTwoOperandsError(instructionToken); return(false); } } break; case Instructions.Div: { Token operand1; Token operand2; if (this.ExpectTwoOperands(out operand1, out operand2)) { node = new DivInstruction(this.rawInput, instructionToken, operand1, operand2); } else { this.LogExpectedTwoOperandsError(instructionToken); return(false); } } break; case Instructions.Cmp: { Token operand1; Token operand2; if (this.ExpectTwoOperands(out operand1, out operand2)) { node = new CmpInstruction(this.rawInput, instructionToken, operand1, operand2); } else { this.LogExpectedTwoOperandsError(instructionToken); return(false); } } break; case Instructions.Inc: { Token operand; if (this.ExpectOneOperand(out operand)) { node = new IncInstruction(this.rawInput, instructionToken, operand); } else { this.LogExpectedOneOperandError(instructionToken); return(false); } } break; case Instructions.Dec: { Token operand; if (this.ExpectOneOperand(out operand)) { node = new DecInstruction(this.rawInput, instructionToken, operand); } else { this.LogExpectedOneOperandError(instructionToken); return(false); } } break; case Instructions.Jmp: { Token operand; if (this.ExpectOneOperand(out operand)) { node = new JmpInstruction(this.rawInput, instructionToken, operand); } else { this.LogExpectedOneOperandError(instructionToken); return(false); } } break; case Instructions.Jeq: { Token operand; if (this.ExpectOneOperand(out operand)) { node = new JeqInstruction(this.rawInput, instructionToken, operand); } else { this.LogExpectedOneOperandError(instructionToken); return(false); } } break; case Instructions.Jne: { Token operand; if (this.ExpectOneOperand(out operand)) { node = new JneInstruction(this.rawInput, instructionToken, operand); } else { this.LogExpectedOneOperandError(instructionToken); return(false); } } break; case Instructions.Jsm: { Token operand; if (this.ExpectOneOperand(out operand)) { node = new JsmInstruction(this.rawInput, instructionToken, operand); } else { this.LogExpectedOneOperandError(instructionToken); return(false); } } break; case Instructions.Jns: { Token operand; if (this.ExpectOneOperand(out operand)) { node = new JnsInstruction(this.rawInput, instructionToken, operand); } else { this.LogExpectedOneOperandError(instructionToken); return(false); } } break; } } return(true); }