/// <summary> /// when current and other use spans are regular spans we can have only 2 conflict cases: /// [1, 3) conflicts with [0, 2) /// [1, 3) conflicts with [2, 4) /// specifically: /// [1, 3) does not conflict with [0, 1) /// /// NOTE: with regular spans, it is not possible /// to have start1 == start2 or end1 == end /// since at the same node we can access only one real local. /// /// However at the same node we can access one or more dummy locals. /// So we can have start1 == start2 and end1 == end2 scenarios, but only if /// other span is a span of a dummy. /// /// In such cases we consider /// start2 == span1.start ==> start2 IS included in span1 /// end2 == span1.end ==> end2 IS NOT included in span1 /// </summary> public bool ConflictsWith(LocalDefUseSpan other) { var containsStart = other.ContainsStart(this.start); var containsEnd = other.ContainsEnd(this.end); return containsStart ^ containsEnd; }
private void RecordVarWrite(LocalSymbol local) { if (!CanScheduleToStack(local)) { return; } var locInfo = _locals[local]; if (locInfo.CannotSchedule) { return; } // if accessing real val, check stack if (local.SynthesizedKind != SynthesizedLocalKind.OptimizerTemp) { // -1 because real assignment "consumes, assigns, and then pushes back" the value. var evalStack = StackDepth() - 1; if (locInfo.stackAtDeclaration != evalStack) { //writing at different eval stack. locInfo.ShouldNotSchedule(); return; } } else { // dummy must be accessed on same stack. Debug.Assert(local == empty || locInfo.stackAtDeclaration == StackDepth()); } var locDef = new LocalDefUseSpan(_counter); locInfo.LocalDefs.Add(locDef); }
private void RecordVarRead(LocalSymbol local) { if (!CanScheduleToStack(local)) { return; } var locInfo = _locals[local]; if (locInfo.CannotSchedule) { return; } if (locInfo.LocalDefs.Count == 0) { //reading before writing. locInfo.ShouldNotSchedule(); return; } // if accessing real val, check stack if (local.SynthesizedKind != SynthesizedLocalKind.OptimizerTemp) { if (locInfo.stackAtDeclaration != StackDepth() && !EvalStackHasLocal(local)) { //reading at different eval stack. locInfo.ShouldNotSchedule(); return; } } else { // dummy must be accessed on same stack. Debug.Assert(local == empty || locInfo.stackAtDeclaration == StackDepth()); } var definedAt = locInfo.LocalDefs.Last(); definedAt.end = _counter; var locDef = new LocalDefUseSpan(_counter); locInfo.LocalDefs.Add(locDef); }
/// <summary> /// Dummy locals represent implicit control flow /// It is not allowed for a regular local span to cross into or /// be immediately adjacent to a dummy span. /// /// specifically: /// [1, 3) does conflict with [0, 1) since that would imply a value flowing into or out of a span surrounded by a branch/label /// /// </summary> public bool ConflictsWithDummy(LocalDefUseSpan dummy) { return Includes(dummy.Start) ^ Includes(dummy.End); }
/// <summary> /// when current and other use spans are regular spans we can have only 2 conflict cases: /// [1, 3) conflicts with [0, 2) /// [1, 3) conflicts with [2, 4) /// /// NOTE: with regular spans, it is not possible for two spans to share an edge point /// unless they belong to the same local. (because we cannot aceess two real locals at the same time) /// /// specifically: /// [1, 3) does not conflict with [0, 1) since such spans would need to belong to the same local /// </summary> public bool ConflictsWith(LocalDefUseSpan other) { return Contains(other.Start) ^ Contains(other.End); }
private void RecordDummyWrite(LocalSymbol local) { Debug.Assert(local.SynthesizedKind == SynthesizedLocalKind.OptimizerTemp); var locInfo = _locals[local]; // dummy must be accessed on same stack. Debug.Assert(local == empty || locInfo.StackAtDeclaration == StackDepth()); var locDef = new LocalDefUseSpan(_counter); locInfo.LocalDefs.Add(locDef); }