Q:

volatile, Interlocked: trying to break code

First of all, I was trying to find out if using Interlocked still requires volatile field definition, and that is my real question.
But. Being too lazy to analyse generated MSIL I decided to check it in practice.
I'm trying MSDN example for volatile usage when code should break in release build with optimizations on. 
And nothing breaks. Code works fine (in this case - main thread terminates gracefully) with optimizations on and off.

Do I still require volatile keyword on a field when I'm writing to it from one thread using Interlocked and reading from another thread without lock?
Simple example of code from 1-st question where volatile makes difference?
Why does MSDN example still working when I remove volatile keyword and build in release?

Code snippet to illustrate question 1.
class Example
{
    volatile int val;

    void Do()
    {
        Task.Run(() => { while (val == 0) Console.WriteLine("running"); });

        Thread.Sleep(1000);
        Interlocked.Increment(ref val);
        Console.WriteLine("done.");
        Console.ReadLine();
    }
}

A:

If the variable is not marked as volatile, then code that reads it cannot know that it might be modified by some other thread. So the JIT compiler won't know that keeping the value in a register is potentially unsafe.
volatile is how you tell the JIT compiler that other threads can modify the value. That the other thread might use Interlocked when changing the value is irrelevant because the JITer might not even know that the other code exists!
It might be that your simple example works because the JIT compiler can see all of the code. Things might be much different if those two bits of code were in separate methods or even different assemblies altogether.

