diff options
Diffstat (limited to 'arch/mips/include/asm/compiler.h')
-rw-r--r-- | arch/mips/include/asm/compiler.h | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/arch/mips/include/asm/compiler.h b/arch/mips/include/asm/compiler.h index e081a265f422..cc2eb1b06050 100644 --- a/arch/mips/include/asm/compiler.h +++ b/arch/mips/include/asm/compiler.h | |||
@@ -8,6 +8,41 @@ | |||
8 | #ifndef _ASM_COMPILER_H | 8 | #ifndef _ASM_COMPILER_H |
9 | #define _ASM_COMPILER_H | 9 | #define _ASM_COMPILER_H |
10 | 10 | ||
11 | /* | ||
12 | * With GCC 4.5 onwards we can use __builtin_unreachable to indicate to the | ||
13 | * compiler that a particular code path will never be hit. This allows it to be | ||
14 | * optimised out of the generated binary. | ||
15 | * | ||
16 | * Unfortunately at least GCC 4.6.3 through 7.3.0 inclusive suffer from a bug | ||
17 | * that can lead to instructions from beyond an unreachable statement being | ||
18 | * incorrectly reordered into earlier delay slots if the unreachable statement | ||
19 | * is the only content of a case in a switch statement. This can lead to | ||
20 | * seemingly random behaviour, such as invalid memory accesses from incorrectly | ||
21 | * reordered loads or stores. See this potential GCC fix for details: | ||
22 | * | ||
23 | * https://gcc.gnu.org/ml/gcc-patches/2015-09/msg00360.html | ||
24 | * | ||
25 | * It is unclear whether GCC 8 onwards suffer from the same issue - nothing | ||
26 | * relevant is mentioned in GCC 8 release notes and nothing obviously relevant | ||
27 | * stands out in GCC commit logs, but these newer GCC versions generate very | ||
28 | * different code for the testcase which doesn't exhibit the bug. | ||
29 | * | ||
30 | * GCC also handles stack allocation suboptimally when calling noreturn | ||
31 | * functions or calling __builtin_unreachable(): | ||
32 | * | ||
33 | * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82365 | ||
34 | * | ||
35 | * We work around both of these issues by placing a volatile asm statement, | ||
36 | * which GCC is prevented from reordering past, prior to __builtin_unreachable | ||
37 | * calls. | ||
38 | * | ||
39 | * The .insn statement is required to ensure that any branches to the | ||
40 | * statement, which sadly must be kept due to the asm statement, are known to | ||
41 | * be branches to code and satisfy linker requirements for microMIPS kernels. | ||
42 | */ | ||
43 | #undef barrier_before_unreachable | ||
44 | #define barrier_before_unreachable() asm volatile(".insn") | ||
45 | |||
11 | #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) | 46 | #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) |
12 | #define GCC_IMM_ASM() "n" | 47 | #define GCC_IMM_ASM() "n" |
13 | #define GCC_REG_ACCUM "$0" | 48 | #define GCC_REG_ACCUM "$0" |