Sure, that's trivially possible. Something like:
static void M(bool x)
If you compile that in debug mode you get
IL_0004: brfalse.s IL_0008
IL_0006: br.s IL_0011
IL_0009: call void A::M(bool)
IL_000f: br.s IL_0011
if statement goes from
0009, and the consequence of the
if is a goto to
return statements are the same code, so there is a "hole" containing a
nop and an unconditional branch between the main body of the
if and the consequence.
More generally, you should never assume anything whatsoever about the layout of the IL produced by the C# compiler. The compiler makes no guarantees whatsoever other than that the IL produced will be legal and, if safe, verifiable.
You say you are writing some code analysis tools; as the author of significant portions of the C# analyzer, and someone who worked on third-party analysis tools at Coverity, a word of advice: for the majority of questions you typically want answered about C# programs, the parse tree produced by Roslyn is the entity you wish to analyze, not the IL. The parse tree is a concrete syntax tree; it is one-to-one with every character in the source code. It can be very difficult to map optimized IL back to the original source code, and it can be very easy to produce false positives in an IL analysis.
Put another way: source-to-IL is semantics-preserving but also information-losing; you typically want to analyze the artifact that has the most information in it.