private bool LoopExpansion(ref DILOperationSet operations) { if (!operations.ContainsLoops()) { return(false); } for (int i = 0; i < operations.Count; i++) { var operation = operations[i]; if (!(operation is LoopOp)) { continue; } var loopOp = (LoopOp)operation; var unrolled = loopOp.Unroll(); if (unrolled.WasLoopUnrolled) //if (false) { operations.RemoveAt(i); // remove the loop operations.InsertRange(i, unrolled.UnrolledInstructions); return(true); // One loop at a time } // TODO: The problem I'm having with loop unrolling is with the two statements operations.RemoveAt(i); operations.Insert(i, new LoopOp(unrolled.UnrolledInstructions)); } return(false); }
private bool CompactRepeatableOperations(ref DILOperationSet operations) { var wasOptimized = false; for (int i = 0; i < operations.Count; i++) { var loopInstruction = operations[i] as LoopOp; if (loopInstruction != null) { var loopInstructions = loopInstruction.Instructions; CompactRepeatableOperations(ref loopInstructions); loopInstruction.Instructions = loopInstructions; continue; } var repeatable = operations[i] as IRepeatable; if (repeatable != null) { if (repeatable.Repeat(operations, i)) { wasOptimized = true; } } } return(wasOptimized); }
public bool Optimize(ref DILOperationSet optimized) { while (CompactRepeatableOperations(ref optimized)) { } // expand all the simple loops while (LoopExpansion(ref optimized)) { return(true); // After some loops have been expanded, there might be new repeatable operations which need to be compacted. } optimized.RemoveAll(i => i == null); //if (!WereConstantsSubstituted) //{ // int currentIndex = 0, nextIOOperationIndex, currentPtrIndex = 0; // while ( // currentIndex <= optimized.Count && // (nextIOOperationIndex = optimized.FindIndex(currentIndex, // i => i is WriteOp || i is ReadOp || i is LoopOp)) != -1) // { // var subOperationSet = new DILOperationSet(optimized.Skip(currentIndex).Take(nextIOOperationIndex - currentIndex)); // var walk = new CodeWalker().Walk(subOperationSet, subOperationSet.Count); // //var walk = new CodeWalker().Walk(optimized, nextIOOperationIndex); // //var walk = Walk(i); // var tempSet = new DILOperationSet(); // foreach (var cell in walk.Domain) // { // if (cell.Value != 0) // { // tempSet.Add(new AdditionMemoryOp(cell.Key, cell.Value)); // } // } // if (walk.EndPtrPosition != 0) // { // tempSet.Add(new PtrOp(walk.EndPtrPosition)); // } // //foreach (var miscOperation in walk.MiscOperations) // //{ // // tempSet.Add(miscOperation.Value); // //} // currentPtrIndex += walk.EndPtrPosition; // //if (nextIOOperationIndex - currentIndex < optimized.Count) // //{ // // var op = optimized[nextIOOperationIndex - currentIndex]; // // if (op is ReadOp || op is WriteOp) // // { // // ((IOffsettable)op).Offset = currentPtrIndex; // // } // //} // optimized.RemoveRange(currentIndex, nextIOOperationIndex - currentIndex); // optimized.InsertRange(currentIndex, tempSet); // currentIndex += tempSet.Count + 1; // + 1 to skip the IO operation // //// If the instruction that we stopped at is a loop, then break from // //// this optimization step because then we wouldn't be able to do // //// any more walks. // //// This may change in the future... // //if (optimized[currentIndex - 1] is LoopOp) // //{ // // break; // //} // } //} /* Constant Substitution */ //if (CanWeSubstituteConstants()) //{ // if (SubstituteConstants(ref optimized)) // { // return true; // } //} /* String walking */ //var stringWalkResults = StringWalk(); //if (stringWalkResults != null && stringWalkResults.Strings.Count > 0) //{ // optimized.Clear(); // var combine = String.Join("", stringWalkResults.Strings); // optimized.Add(new WriteLiteralOp(combine)); // return true; //} return(false); }
/// <summary> /// Optimization #6: /// Constant substitution /// /// TODO: This method has some inconsistencies when setting the offset with the new memory operations. /// For some memory operations, I'm using "new {Op}(ptr + {op}.Offset)" /// and for others I'm just using "new {Op}({op}.Offset)". /// I'm pretty sure this inconsistency is causing some problems. /// </summary> /// <param name="operations"></param> private bool SubstituteConstants(ref DILOperationSet operations) { if (WereConstantsSubstituted) { return(false); } var ptr = 0; var arr = operations.ToArray(); var didAnysubstitutions = false; for (int i = 0; i < arr.Length; i++) { var operation = arr[i]; if (operation is AdditionMemoryOp) { var add = (AdditionMemoryOp)operation; if (add.Constant == null) { arr[i] = new AdditionMemoryOp(ptr + add.Offset, add.Scalar, new ConstantValue(ptr + add.Offset)); didAnysubstitutions = true; } } else if (operation is MultiplicationMemoryOp) { var mul = (MultiplicationMemoryOp)operation; if (mul.Constant == null) { arr[i] = new MultiplicationMemoryOp(ptr + mul.Offset, mul.Scalar, new ConstantValue(ptr + mul.Offset), new ConstantValue(ptr)); } } else if (operation is AssignOp) { var ass = arr[i] as AssignOp; if (ass.Constant == null) { arr[i] = new AssignOp(ptr + ass.Offset, ass.Value, new ConstantValue(ptr + ass.Offset)); didAnysubstitutions = true; } } else if (operation is PtrOp) { arr[i] = null; // if we're using constants, then we don't need pointer movements var ptrOp = (PtrOp)operation; ptr += ptrOp.Delta; //didAnysubstitutions = true; } else if (operation is WriteOp) { var write = ((WriteOp)arr[i]); if (write.Constant == null) { arr[i] = new WriteOp(write.Offset, write.Repeated, new ConstantValue(ptr)); didAnysubstitutions = true; } } else if (operation is ReadOp) { var read = ((ReadOp)arr[i]); if (read.Constant == null) { arr[i] = new ReadOp(read.Offset, read.Repeated, new ConstantValue(ptr)); didAnysubstitutions = true; } } } var list = arr.ToList(); list.RemoveAll(l => l == null); operations = new DILOperationSet(list); operations.WereConstantsSubstituted = true; return(didAnysubstitutions); }