Skip to content

Commit 68c87b9

Browse files
committed
Address cpp-docs 4075 __assume issues
1 parent 64857d3 commit 68c87b9

File tree

1 file changed

+37
-42
lines changed

1 file changed

+37
-42
lines changed

docs/intrinsics/assume.md

Lines changed: 37 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
---
22
description: "Learn more about: __assume"
33
title: "__assume"
4-
ms.date: "09/02/2019"
4+
ms.date: 08/03/2022
55
f1_keywords: ["__assume", "_assume", "__assume_cpp"]
66
helpviewer_keywords: ["__assume keyword [C++]"]
77
ms.assetid: d8565123-b132-44b1-8235-5a8c8bff85a7
88
---
9-
# __assume
9+
# `__assume`
1010

1111
**Microsoft Specific**
1212

@@ -22,85 +22,80 @@ __assume(
2222

2323
### Parameters
2424

25-
*expression*\
26-
Any expression that is assumed to evaluate to true.
25+
*`expression`*\
26+
For reachable code, any expression that is assumed to evaluate to **`true`**. Use `0` to indicate unreachable code to the optimizer.
2727

2828
## Remarks
2929

30-
The optimizer assumes that the condition represented by `expression` is true at the point where the keyword appears and remains true until `expression` is modified (for example, by assignment to a variable). Selective use of hints passed to the optimizer by **`__assume`** can improve optimization.
30+
The optimizer assumes that the condition represented by `expression` is **`true`** at the point where the keyword appears and remains true until `expression` is modified (for example, by assignment to a variable). Selective use of hints passed to the optimizer by **`__assume`** can improve optimization.
3131

32-
If the **`__assume`** statement is written as a contradiction (an expression that always evaluates to false), it is always treated as `__assume(0)`. If your code isnt behaving as expected, ensure that the `expression` you defined is valid and true, as described earlier. For more information about expected `__assume(0)` behavior, see the later remarks.
32+
If the **`__assume`** statement is written as a contradiction (an expression that always evaluates to **`false`**), it's always treated as `__assume(0)`. If your code isn't behaving as expected, ensure that the `expression` you defined is valid and **`true`**, as described earlier. The `__assume(0)` statement is a special case. Use `__assume(0)` to indicate a code path that can't be reached.
3333

3434
> [!WARNING]
3535
> A program must not contain an invalid **`__assume`** statement on a reachable path. If the compiler can reach an invalid **`__assume`** statement, the program might cause unpredictable and potentially dangerous behavior.
3636
37-
`__assume` is not a genuine intrinsic. It does not have to be declared as a function and it cannot be used in a `#pragma intrinsic` directive. Although no code is generated, the code generated by the optimizer is affected.
37+
For compatibility with previous versions, **`_assume`** is a synonym for **`__assume`** unless compiler option [`/Za` (Disable language extensions)](../build/reference/za-ze-disable-language-extensions.md) is specified.
3838

39-
Use **`__assume`** in an [ASSERT](../c-runtime-library/reference/assert-asserte-assert-expr-macros.md) only when the assert is not recoverable. Do not use **`__assume`** in an assert for which you have subsequent error recovery code because the compiler might optimize away the error-handling code.
39+
`__assume` isn't a genuine intrinsic. It doesn't have to be declared as a function and it can't be used in a `#pragma intrinsic` directive. Although no code is generated, the code generated by the optimizer is affected.
4040

41-
The `__assume(0)` statement is a special case. Use `__assume(0)` to indicate a code path that cannot be reached. The following example shows how to use `__assume(0)` to indicate that the default case of a switch statement cannot be reached. This shows the most typical use of `__assume(0)`.
42-
43-
For compatibility with previous versions, **`_assume`** is a synonym for **`__assume`** unless compiler option [/Za \(Disable language extensions)](../build/reference/za-ze-disable-language-extensions.md) is specified.
41+
Use **`__assume`** in an [`ASSERT`](../c-runtime-library/reference/assert-asserte-assert-expr-macros.md) only when the assertion isn't recoverable. Don't use **`__assume`** in an assertion for which you have subsequent error recovery code because the compiler might optimize away the error-handling code.
4442

4543
## Requirements
4644

47-
|Intrinsic|Architecture|
48-
|---------------|------------------|
49-
|**`__assume`**|x86, ARM, x64, ARM64|
45+
| Intrinsic | Architecture |
46+
|--|--|
47+
| **`__assume`** | x86, ARM, x64, ARM64, ARM64EC |
5048

5149
## Example
5250

51+
The following example shows how to use `__assume(0)` to indicate that the **`default`** case of a **`switch`** statement can't be reached. It's the most typical use of `__assume(0)`. Here, the programmer knows that the only possible inputs for `p` will be 1 or 2. If another value is passed in for `p`, the program becomes invalid and causes unpredictable behavior.
52+
5353
```cpp
5454
// compiler_intrinsics__assume.cpp
55-
#ifdef DEBUG
56-
# define ASSERT(e) ( ((e) || assert(__FILE__, __LINE__) )
57-
#else
58-
# define ASSERT(e) ( __assume(e) )
59-
#endif
6055

61-
void func1(int i)
56+
void func1(int /*ignored*/)
6257
{
6358
}
6459

6560
int main(int p)
6661
{
67-
switch(p){
68-
case 1:
69-
func1(1);
70-
break;
71-
case 2:
72-
func1(-1);
73-
break;
74-
default:
75-
__assume(0);
76-
// This tells the optimizer that the default
77-
// cannot be reached. As so, it does not have to generate
78-
// the extra code to check that 'p' has a value
79-
// not represented by a case arm. This makes the switch
80-
// run faster.
62+
switch(p)
63+
{
64+
case 1:
65+
func1(1);
66+
break;
67+
case 2:
68+
func1(-1);
69+
break;
70+
default:
71+
__assume(0);
72+
// This tells the optimizer that the default
73+
// cannot be reached. As so, it does not have to generate
74+
// the extra code to check that 'p' has a value
75+
// not represented by a case arm. This makes the switch
76+
// run faster.
8177
}
8278
}
8379
```
8480
85-
The use of `__assume(0)` tells the optimizer that the default case cannot be reached. The example demonstrates that the programmer knows that the only possible inputs for `p` will be 1 or 2. If another value is passed in for `p`, the program becomes invalid and causes unpredictable behavior.
81+
As a result of the `__assume(0)` statement, the compiler doesn't generate code to test whether `p` has a value that isn't represented in a case statement.
8682
87-
As a result of the `__assume(0)` statement, the compiler does not generate code to test whether `p` has a value that is not represented in a case statement. For this to work, the `__assume(0)` statement must be the first statement in the body of the default case.
88-
89-
Because the compiler generates code based on **`__assume`**, that code might not run correctly if the expression inside the **`__assume`** statement is false at run time. If you are not sure that the expression will always be true at run time, you can use the `assert` function to protect the code.
83+
If you aren't sure that the expression will always be **`true`** at runtime, you can use the `assert` function to protect the code. This macro definition wraps the **`__assume`** statement with a check:
9084
9185
```C
92-
#define ASSERT(e) ( ((e) || assert(__FILE__, __LINE__)), __assume(e) )
86+
#define ASSUME(e) (((e) || (assert(e), (e))), __assume(e))
9387
```
9488

95-
Unfortunately, this use of `assert` prevents the compiler from performing the default-case optimization that was described earlier in this document. As an alternative, you can use a separate macro, as follows.
89+
For the **`default`** case optimization to work, the `__assume(0)` statement must be the first statement in the body of the **`default`** case. Unfortunately, the `assert` in the `ASSUME` macro prevents the compiler from performing this optimization. As an alternative, you can use a separate macro, as shown here:
9690

9791
```C
9892
#ifdef DEBUG
99-
# define NODEFAULT ASSERT(0)
93+
// This code is supposed to be unreachable, so assert
94+
# define NODEFAULT assert(0)
10095
#else
10196
# define NODEFAULT __assume(0)
10297
#endif
103-
98+
// . . .
10499
default:
105100
NODEFAULT;
106101
```

0 commit comments

Comments
 (0)