__assume and __forceinline were the first two features I implemented as a developer out of college. I just resolved a bug as 'By Design' that asked the question posed in the title. Here's a brief explanation:
First, __assume(n==x) basically tells the expression optimizer & the global optimizer in the compiler that n is being assigned the value of x. So, if you say __assume(n==5);y=n*n; the compiler will automagically turn that into y=25. Nifty, right? It's also used to flag dead code:
For that switch, there will be no checks for any values other than 1 or 2 - no range check. Again, in performance sensitive code, this can be a big win.
However, the transformation of assert to __assume could have potentially negative impact on security, so it's not defined by default. Individual customers should determine if it's an acceptable optimization.
The trouble lies in the potential lack of code coverage testing. Here's a simplistic case to illustrate the problem:
assert(passwordAlreadyChecked == true);
// Assert is actually false,
// but we don't realize that,
// because we haven't tested it
If the compiler inlines DoSomethingThatChecksSecurity into untestedFunctionFoo, and assert is turned into __assume(passwordAlreadyChecked == true) the optimizer will remove the call to GetPassword(), and then untestedFunctionFoo, which wasn't tested, no longer requires a password to get it. Your visual code reviews don't pick up that doSomethingSecure might occur without a password, because logically, you're assertting that the password has already been checked, or you're calling GetPassword.
Hopefully, that explains the issue. Please use __assume with caution. It can be a performance win, but if you're authoring code with severe security concerns, you're better off without it.