[analyzer;alternate edges] - add in events (loop iterations, etc)

These were being dropped due a transcription mistake from the original
algorithm.
[analyzer; alternate edges] prune edges whose end/begin locations have the same statement parents.

This change required some minor changes to LocationContextMap to have it map
from PathPieces to LocationContexts instead of PathDiagnosticCallPieces to
LocationContexts.  These changes are in the other diagnostic
generation logic as well, but are functionally equivalent.

Interestingly, this optimize requires delaying "cleanUpLocation()" until
later; possibly after all edges have been optimized.  This is because
we need PathDiagnosticLocations to refer to the semantic entity (e.g. a statement)
as long as possible.  Raw source locations tell us nothing about
the semantic relationship between two locations in a path.
[analyzer; alternate edges] - merge control edges where we descend to a subexpression and pop back out.
[analyzer; alternate edges] - eliminate unnecessary edges where between parents and subexpressions.
[analyzer;alternate edges] ignore parentheses when determining edge levels.
[analyzer;alternate edges] start experimenting with control flow "barriers" to prevent an edge being optimized away.