protected override bool InnerOptimize(OptimizationContext context, Instruction matchedInstruction, Backtracer backtracer, int i) { var changed = false; var j = i; var patchedLabels = new Dictionary <(ushort label, short offset), ushort>(); context.RemoveAt(j); while (!IsChainBreaker(context[j], matchedInstruction, new BacktracerView(backtracer, j - 1, false))) { var instruction = context[j]; switch (instruction.Type) { case InstructionType.BoundsCheck: case InstructionType.Char: var targetLabel = instruction.Label; if (patchedLabels.TryGetValue((targetLabel, matchedInstruction.Offset), out var newTarget)) { targetLabel = newTarget; } else { var oldLabel = targetLabel; targetLabel = AddStub(context, targetLabel, matchedInstruction, ref j); patchedLabels[(oldLabel, matchedInstruction.Offset)] = targetLabel;
protected override bool InnerOptimize(OptimizationContext context, Instruction matchedInstruction, Backtracer backtracer, int i) { var changed = false; var j = i; var patchedLabels = new Dictionary <(ushort label, short offset), ushort>(); var offset = matchedInstruction.Offset; var removedAt = 0; context.RemoveAt(j); while (!IsChainBreaker(context[j], Instruction.Advance(offset), null)) { var instruction = context[j]; switch (instruction.Type) { case InstructionType.Advance: offset += instruction.Offset; removedAt = j; context.RemoveAt(j); break; case InstructionType.BoundsCheck: case InstructionType.Char: var targetLabel = instruction.Label; if (context[context.GetLabelPosition(targetLabel) + 1].Type != InstructionType.RestorePosition) { if (patchedLabels.TryGetValue((targetLabel, offset), out var newTarget)) { targetLabel = newTarget; } else if (offset != 0) { var oldLabel = targetLabel; targetLabel = AddStub(context, targetLabel, Instruction.Advance(offset), ref j); patchedLabels[(oldLabel, offset)] = targetLabel;
public string GetSqlText(SelectQuery query) { var provider = ((IDataContext)this).CreateSqlProvider(); var optimizer = ((IDataContext)this).GetSqlOptimizer(); var optimizationContext = new OptimizationContext(new EvaluationContext(SqlParameterValues.Empty), null, false); var statement = (SqlSelectStatement)optimizer.Finalize(new SqlSelectStatement(query)); statement = (SqlSelectStatement)optimizer.PrepareStatementForRemoting(statement, MappingSchema, optimizationContext.Context); var cc = provider.CommandCount(statement); var sb = new StringBuilder(); var commands = new string[cc]; for (var i = 0; i < cc; i++) { sb.Length = 0; provider.BuildSql(i, statement, sb, optimizationContext); commands[i] = sb.ToString(); } return(string.Join("\n\n", commands)); }
protected override void BuildSql(int commandNumber, SqlStatement statement, StringBuilder sb, OptimizationContext optimizationContext, int indent, bool skipAlias) { Statement = statement; StringBuilder = sb; OptimizationContext = optimizationContext; Indent = indent; SkipAlias = skipAlias; if (_identityField != null) { indent += 2; AppendIndent().AppendLine("SELECT"); AppendIndent().Append('\t'); BuildExpression(_identityField, false, true); sb.AppendLine(); AppendIndent().AppendLine("FROM"); AppendIndent().AppendLine("\tNEW TABLE"); AppendIndent().Append('\t').AppendLine(OpenParens); } base.BuildSql(commandNumber, statement, sb, optimizationContext, indent, skipAlias); if (_identityField != null) { sb.AppendLine("\t)"); } }
private static bool RemoveDeadCodeAfter(OptimizationContext context, int[] labelsUsed, int i, Instruction instruction, bool subtractValues = false) { var changed = false; while (i + 1 < context.Count && !context[i + 1].Matches(InstructionType.MarkLabel)) { if (subtractValues) { switch (context[i + 1].Type) { case InstructionType.Call: foreach (var(_, targetLabel) in context.FailureLabelMap[instruction.Data2].Mapping) { labelsUsed[targetLabel]--; } break; case InstructionType.Char: case InstructionType.BoundsCheck: case InstructionType.Jump: labelsUsed[instruction.Label]--; break; } } context.RemoveAt(i + 1, true); changed = true; } return(changed); }
private bool HasVariableAround(OptimizationContext context, int i, ushort variable) { var pos = i; while (pos > 0 && context[pos].Type == InstructionType.StorePosition) { if (context[pos].Data1 == variable) { return(true); } pos--; } pos = i; while (pos < context.Count && context[pos].Type == InstructionType.StorePosition) { if (context[pos].Data1 == variable) { return(true); } pos++; } return(false); }
protected ushort?FindOrMarkExistingStub(OptimizationContext context, Instruction[] neededInstructions, ushort targetLabel, ref int position) { for (var i = 0; i < context.Count; i++) { if (SequencesEqual(context, i, neededInstructions) && (context[i + neededInstructions.Length].Matches(InstructionType.MarkLabel, targetLabel) || context[i + neededInstructions.Length].Matches(InstructionType.Jump, targetLabel))) { if (i > 0 && context[i - 1].Matches(InstructionType.MarkLabel, out var existingLabel)) { return(existingLabel); } else { var newLabel = context.LabelAllocator++; context.Insert(i, Instruction.MarkLabel(newLabel)); if (position >= i) { position++; } return(newLabel); } } } return(null); }
/// <summary> /// Optimizes the provided expression using an <see cref="OptimizationContext{TSettings}"/> /// created with <see cref="OptimizationContext.CreateDefault(DefaultOptimizationSettings?, IEnumerable{IOptimizationPass{DefaultOptimizationSettings}})"/> /// </summary> /// <param name="expr">the expression to optimize</param> /// <returns>the optimized expression</returns> public override MathExpression Optimize(MathExpression expr) { var ctx = OptimizationContext.CreateDefault(OptimizerSettings, OptimizerPasses); ctx.SetParentDataContext(SharedDataStore); return(ctx.Optimize(expr)); }
public override bool Optimize(OptimizationContext context) { var changed = false; var offsetInfo = new VariableOffset[context.Count]; for (var i = 0; i < offsetInfo.Length; i++) { offsetInfo[i] = new VariableOffset(); } BuildOffsetInfo(context, offsetInfo); for (var i = context.Count - 1; i >= 0; i--) { var instruction = context[i]; switch (instruction.Type) { case InstructionType.RestorePosition: var offset = offsetInfo[i].Get(instruction.Data1); if (offset == 0) { changed = true; context.RemoveAt(i); } else if (offset > 0) { changed = true; context[i] = Instruction.Advance((short)-offset); } break; } } return(changed); }
protected override bool InnerOptimize(OptimizationContext context, Instruction matchedInstruction, Backtracer backtracer, int i) { var changed = false; var j = i; context.RemoveAt(j); while (!IsChainBreaker(context[j], matchedInstruction, null)) { var instruction = context[j]; if (instruction.Matches(InstructionType.BoundsCheck, matchedInstruction.Label)) { changed = true; matchedInstruction = Instruction.BoundsCheck(instruction.Label, Math.Max(instruction.Offset, context[j].Offset)); context.RemoveAt(j); } else { j++; } } context.Insert(i, matchedInstruction); return(changed); }
public CharCheckEntry MatchFail(OptimizationContext context, Instruction instruction) { var failing = FailingCharacters.Clone(); AddEntry(instruction, true, instruction.Offset, failing); return(new CharCheckEntry(MatchingCharacters, failing)); }
public NdState MatchFail(OptimizationContext context, Instruction instruction, int offset) { var failing = FailingCharacters.Clone(); AddEntry(instruction, true, offset, failing); return(new NdState(Variable, Vug, PositionA, PositionB, AdvancesA, AdvancesB, MinBounds, MaxBounds, VarAs, VarBs, MatchingCharacters, failing)); }
public void BinaryCombinerLiteralCombinerPasses(MathExpression input, MathExpression expect) { var context = OptimizationContext.CreateWith(new DefaultOptimizationSettings(), new BinaryExpressionCombinerPass(), new LiteralCombinerPass()); var actual = context.Optimize(input); Assert.Equal(expect, actual); }
public void ExponentConstantReductionPass(MathExpression input, MathExpression expect) { var context = OptimizationContext.CreateWith(null, new BuiltinExponentConstantReductionPass()); var actual = context.Optimize(input); Assert.Equal(expect, actual); }
public void LiteralCombinerPass(MathExpression input, MathExpression expect) { var context = OptimizationContext.CreateWith(null, new LiteralCombinerPass()); var actual = context.Optimize(input); Assert.Equal(expect, actual); }
public override bool Optimize(OptimizationContext context) { var changed = false; for (var i = context.Count - 1; i >= 0; i--) { var instructionCount = context.Count; var instruction = context[i]; switch (instruction.Type) { // TODO: Can we optimize a Call-instruction here? case InstructionType.Char: case InstructionType.BoundsCheck: case InstructionType.Jump: { var backtracer = new BacktracerView(context.Backtracer, i, true); if (!instruction.IsCharOrBoundsCheck) { backtracer = new BacktracerView(context.Backtracer, i - 1, false); } var result = InstructionHelper.FindJumpTargetEx(context, backtracer, context.GetLabelPosition(instruction.Label), FullPathSearch, false); if (!context[result.Position - 1].Matches(InstructionType.MarkLabel, instruction.Label)) { if (context[result.Position - 1].Matches(InstructionType.MarkLabel, out var newTarget)) { context.NonDestructiveUpdate(i, instruction.WithLabel(newTarget)); } else { var newLabel = context.LabelAllocator++; context.NonDestructiveUpdate(i, instruction.WithLabel(newLabel)); context.Insert(result.Position, Instruction.MarkLabel(newLabel), true); } changed = true; } } break; } } for (var i = context.Count - 1; i >= 0; i--) { var instructionCount = context.Count; var instruction = context[i]; if (instruction.Matches(InstructionType.Jump, out var targetLabel)) { var jumpingTo = context[context.GetLabelPosition(targetLabel) + 1]; if (jumpingTo.Matches(InstructionType.Return)) { context[i] = jumpingTo; } } } return(changed); }
private bool[] CreateUsageGraph(bool[] graph, ushort variable, OptimizationContext context, int pos) { var positionStack = new Stack <int>(); positionStack.Push(pos); while (positionStack.Count > 0) { var currentPos = positionStack.Pop(); var instruction = context[currentPos]; if (!graph[currentPos]) { graph[currentPos] = true; switch (instruction.Type) { case InstructionType.StorePosition when instruction.Data1 == variable: break; case InstructionType.MarkLabel: for (var i = 0; i < context.Count; i++) { switch (context[i].Type) { case InstructionType.BoundsCheck: case InstructionType.Char: case InstructionType.Jump: if (context[i].Label == instruction.Label) { positionStack.Push(i); } break; case InstructionType.Call: foreach (var(_, jumpTarget) in context.FailureLabelMap[context[i].Data2].Mapping) { if (jumpTarget == instruction.Label) { positionStack.Push(i); } } break; } } goto default; default: if (currentPos > 0 && context[currentPos - 1].Type != InstructionType.Jump && context[currentPos - 1].Type != InstructionType.Return) { positionStack.Push(currentPos - 1); } break; } } } return(graph); }
public override bool Optimize(OptimizationContext context) { var changed = false; changed |= Deduplicate(context); //changed |= Stitch(context); return(changed); }
public NdState MatchSuccess(OptimizationContext context, Instruction instruction, int offset) { var matching = MatchingCharacters.Clone(); AddEntry(instruction, true, offset, matching); matching[offset].RemoveAll(existing => InstructionHelper.NonJumpMatchWillFail(context, existing, instruction)); return(new NdState(Variable, Vug, PositionA, PositionB, AdvancesA, AdvancesB, MinBounds, MaxBounds, VarAs, VarBs, matching, FailingCharacters)); }
public CharCheckEntry MatchSuccess(OptimizationContext context, Instruction instruction) { var matching = MatchingCharacters.Clone(); AddEntry(instruction, true, instruction.Offset, matching); matching[instruction.Offset].RemoveAll(existing => InstructionHelper.NonJumpMatchWillFail(context, existing, instruction)); return(new CharCheckEntry(matching, FailingCharacters)); }
private bool Analyze(OptimizationContext context, NdState initialState) { var processed = new List <NdState> [context.Count]; for (var i = 0; i < processed.Length; i++) { processed[i] = new List <NdState>(); } var overflowProtection = 0; var stack = new Stack <NdState>(); stack.Push(initialState); while (stack.Count > 0) { if (stack.Count > context.Count) { // Bailout if stack starts to explode return(false); } else if (overflowProtection++ >= context.Count * 250) { // Or if we're just taking too long return(false); } var current = stack.Pop(); if (current.AAndBAreSameState() || !validPositionsForB[current.PositionB] || processed[current.PositionA].Any(item => current.PracticallyEquivalent(item, context, stack))) { // Already processed this state. continue; } processed[current.PositionA].Add(current); NdStateView view; if (current.AdvancesB < current.AdvancesA || context[current.PositionA].Matches(InstructionType.Return)) { view = current.B; } else { view = current.A; } if (!Step(context, stack, view, current)) { return(false); } } return(true); }
public Backtracer(OptimizationContext context) { Context = context; boundsCheckMemo = new List <BoundsCheckEntry>(); charCheckMemo = new List <CharCheckEntry>(); while (boundsCheckMemo.Count < context.Instructions.Count) { boundsCheckMemo.Add(null); charCheckMemo.Add(null); } }
private static int CheckEquality(OptimizationContext context, int refPoint, int refCount, int point) { for (var offset = 0; offset < refCount && point - offset >= 0; offset++) { if (context[refPoint - offset] != context[point - offset]) { return(offset); } } return(0); }
private static int GetNumChars(Instruction instruction, OptimizationContext context) { var numChars = 0; for (var i = instruction.Data1; i < instruction.Data2; i++) { var range = context.CharacterRanges[i]; numChars += range.Max - range.Min + 1; } return(numChars); }
protected bool SequencesEqual(OptimizationContext context, int offset, Instruction[] neededInstructions) { for (var j = 0; j < neededInstructions.Length; j++) { if (context[offset + j] != neededInstructions[j]) { return(false); } } return(true); }
private bool Unifies(OptimizationContext context, int leftOffset, int rightOffset, int length) { var labelMapping = new Dictionary <ushort, ushort>(); var variableMapping = new Dictionary <ushort, ushort>(); for (var i = 0; i < length; i++) { var left = context[leftOffset + i]; var right = context[rightOffset + i]; if (left.Type != right.Type || left.Data1 != right.Data1 || (left.Type != InstructionType.Call && right.Type != InstructionType.Call && left.Data2 != right.Data2) || left.Type == InstructionType.RestorePosition || left.Type == InstructionType.StorePosition || left.Type == InstructionType.MarkLabel) { return(false); } if (left.Type != InstructionType.Call) { if (!Unify(variableMapping, left.Label, right.Label)) { return(false); } } else { var leftMapping = context.FailureLabelMap[left.Data2]; var rightMapping = context.FailureLabelMap[right.Data2]; if (leftMapping.Mapping.Count != rightMapping.Mapping.Count) { return(false); } foreach (var(failureLabel, jumpTarget) in leftMapping.Mapping) { if (!rightMapping.TryGet(failureLabel, out var rightLabel)) { return(false); } if (!Unify(variableMapping, jumpTarget, rightLabel)) { return(false); } } } } return(true); }
public override ISqlPredicate ConvertSearchStringPredicate(MappingSchema mappingSchema, SqlPredicate.SearchString predicate, ConvertVisitor visitor, OptimizationContext optimizationContext) { if (!predicate.IgnoreCase) { return(ConvertSearchStringPredicateViaLike(mappingSchema, predicate, visitor, optimizationContext)); } ISqlExpression expr; switch (predicate.Kind) { case SqlPredicate.SearchString.SearchKind.EndsWith: { predicate = new SqlPredicate.SearchString( new SqlFunction(typeof(string), "$ToLower$", predicate.Expr1), predicate.IsNot, new SqlFunction(typeof(string), "$ToLower$", predicate.Expr2), predicate.Kind, predicate.IgnoreCase); return(ConvertSearchStringPredicateViaLike(mappingSchema, predicate, visitor, optimizationContext)); } case SqlPredicate.SearchString.SearchKind.StartsWith: { expr = new SqlExpression(typeof(bool), predicate.IsNot ? "{0} NOT STARTING WITH {1}" : "{0} STARTING WITH {1}", Precedence.Comparison, TryConvertToValue(predicate.Expr1, optimizationContext.Context), TryConvertToValue(predicate.Expr2, optimizationContext.Context)) { CanBeNull = false }; break; } case SqlPredicate.SearchString.SearchKind.Contains: expr = new SqlExpression(typeof(bool), predicate.IsNot ? "{0} NOT CONTAINING {1}" : "{0} CONTAINING {1}", Precedence.Comparison, TryConvertToValue(predicate.Expr1, optimizationContext.Context), TryConvertToValue(predicate.Expr2, optimizationContext.Context)) { CanBeNull = false }; break; default: throw new InvalidOperationException($"Unexpected predicate: {predicate.Kind}"); } return(new SqlSearchCondition(new SqlCondition(false, new SqlPredicate.Expr(expr)))); }
private void BuildOffsetInfo(OptimizationContext context, VariableOffset[] offsetInfo) { VariableOffset[] oldOffsetInfo; do { var labelPositions = CalculateLabelPositions(context); oldOffsetInfo = offsetInfo.Select(item => item.Clone()).ToArray(); for (var i = 0; i < context.Count - 1; i++) { var instruction = context[i]; var currentInfo = offsetInfo[i]; switch (instruction.Type) { case InstructionType.BoundsCheck: case InstructionType.Char: offsetInfo[labelPositions[instruction.Label]].UnionWith(currentInfo); break; case InstructionType.StorePosition: currentInfo.DoStore(instruction.Data1); break; case InstructionType.Jump: offsetInfo[labelPositions[instruction.Label]].UnionWith(currentInfo); break; case InstructionType.Call: currentInfo.Invalidate(); foreach (var(_, jumpTarget) in context.FailureLabelMap[instruction.Data2].Mapping) { offsetInfo[labelPositions[jumpTarget]].UnionWith(currentInfo); } break; } if (instruction.Type != InstructionType.Jump) { switch (context[i + 1].Type) { case InstructionType.Advance: offsetInfo[i + 1].UnionWith(currentInfo, (int)context[i + 1].Offset); break; default: offsetInfo[i + 1].UnionWith(currentInfo); break; } } } } while (!OffsetsAreEqual(offsetInfo, oldOffsetInfo)); }
protected static IEnumerable <ushort> GetJumpTargets(OptimizationContext context, Instruction instruction) { if (instruction.CanJumpToLabel) { yield return(instruction.Label); } else if (instruction.Type == InstructionType.Call) { foreach (var kvp in context.FailureLabelMap[instruction.Data2].Mapping) { yield return(kvp.jumpTarget); } } }
private static bool ReindexLabels(OptimizationContext context, int[] labelsUsed, int[] labelMappings) { var reindexedLabels = new ushort[context.LabelAllocator]; var numUsedLabels = (ushort)0; for (var i = 0; i < labelsUsed.Length; i++) { if (labelsUsed[i] > 0 && labelMappings[i] == i) { reindexedLabels[i] = numUsedLabels++; } } if (context.LabelAllocator != numUsedLabels) { for (var i = context.Count - 1; i >= 0; i--) { var instruction = context[i]; switch (instruction.Type) { case InstructionType.Char: case InstructionType.BoundsCheck: case InstructionType.Jump: case InstructionType.MarkLabel: var newLabel = reindexedLabels[labelMappings[instruction.Label]]; if (i + 1 < context.Count && context[i + 1].Matches(InstructionType.MarkLabel, newLabel)) { context.RemoveAt(i); } else { context[i] = context[i].WithLabel(newLabel); } break; } } context.FailureLabelMap = context.FailureLabelMap .Select(map => new LabelMap(map .Mapping .Select(kvp => (kvp.failureLabel, reindexedLabels[labelMappings[kvp.jumpTarget]]))) ) .ToList(); context.LabelAllocator = numUsedLabels; context.ClearCache(); return(true); } return(false); }