clang: work around asm input constraint problems
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 8 Apr 2024 18:38:30 +0000 (11:38 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 22 May 2024 21:12:11 +0000 (14:12 -0700)
Work around clang problems with asm constraints that have multiple
possibilities, particularly "g" and "rm".

Clang seems to turn inputs like that into the most generic form, which
is the memory input - but to make matters worse, clang won't even use a
possible original memory location, but will spill the value to stack,
and use the stack for the asm input.

See

  https://github.com/llvm/llvm-project/issues/20571#issuecomment-980933442

for some explanation of why clang has this strange behavior, but the end
result is that "g" and "rm" really end up generating horrid code.

Link: https://github.com/llvm/llvm-project/issues/20571
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
include/linux/compiler-clang.h
include/linux/compiler_types.h

index 49feac0162a5264a5b63b4a5e913bd821ccc66c3..4c1a39dcb624e9918dbaed72bf0c01bd0944b2df 100644 (file)
 
 #define __diag_ignore_all(option, comment) \
        __diag_clang(13, ignore, option)
+
+/*
+ * clang has horrible behavior with "g" or "rm" constraints for asm
+ * inputs, turning them into something worse than "m". Avoid using
+ * constraints with multiple possible uses (but "ir" seems to be ok):
+ *
+ *     https://github.com/llvm/llvm-project/issues/20571
+ */
+#define ASM_INPUT_G "ir"
+#define ASM_INPUT_RM "r"
index 8f8236317d5b15b97d059f3684e16d9ddb247317..f82bdac63961cc16eb71e8be354028c34c9b18d7 100644 (file)
@@ -391,6 +391,15 @@ struct ftrace_likely_data {
 #define asm_goto_output(x...) asm volatile goto(x)
 #endif
 
+/*
+ * Clang has trouble with constraints with multiple
+ * alternative behaviors (mainly "g" and "rm").
+ */
+#ifndef ASM_INPUT_G
+  #define ASM_INPUT_G "g"
+  #define ASM_INPUT_RM "rm"
+#endif
+
 #ifdef CONFIG_CC_HAS_ASM_INLINE
 #define asm_inline asm __inline
 #else