[compiler-rt] 674a17e - MIPS/compiler_rt: use synci to flush icache on r6

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 7 17:43:46 PST 2022


Author: YunQiang Su
Date: 2022-11-07T17:43:41-08:00
New Revision: 674a17e9bbe82e8c53952fd94dcd862b17cb2d2f

URL: https://github.com/llvm/llvm-project/commit/674a17e9bbe82e8c53952fd94dcd862b17cb2d2f
DIFF: https://github.com/llvm/llvm-project/commit/674a17e9bbe82e8c53952fd94dcd862b17cb2d2f.diff

LOG: MIPS/compiler_rt: use synci to flush icache on r6

syscall makes it failed to build on mips64 for mipsel:
```
compiler-rt/lib/builtins/clear_cache.c:97:3: error:
call to undeclared function 'syscall'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
  syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE);
```

In this patch, we use `rdhwr` to get synci_step.
If synci_step is zero, it means that the hardware will maintain the coherence. We need to do nothing.
Then for r6+, `synci` is required to keep icache global.
So we can use `synci` to flush icache.
The ISA documents ask a `sync` and a `jr.hb` after `synci`.

For pre-r6, we can use cacheflush libc function, which is same on Linux and FreeBSD.

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D135565

Added: 
    

Modified: 
    compiler-rt/lib/builtins/clear_cache.c

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/builtins/clear_cache.c b/compiler-rt/lib/builtins/clear_cache.c
index bcc5922e073b..8993761eb3d4 100644
--- a/compiler-rt/lib/builtins/clear_cache.c
+++ b/compiler-rt/lib/builtins/clear_cache.c
@@ -93,12 +93,29 @@ void __clear_cache(void *start, void *end) {
 #endif
 #elif defined(__linux__) && defined(__loongarch__)
   __asm__ volatile("ibar 0");
-#elif defined(__linux__) && defined(__mips__)
+#elif defined(__mips__)
   const uintptr_t start_int = (uintptr_t)start;
   const uintptr_t end_int = (uintptr_t)end;
-  syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE);
-#elif defined(__mips__) && defined(__OpenBSD__)
-  cacheflush(start, (uintptr_t)end - (uintptr_t)start, BCACHE);
+  uintptr_t synci_step;
+  __asm__ volatile("rdhwr %0, $1" : "=r"(synci_step));
+  if (synci_step != 0) {
+#if __mips_isa_rev >= 6
+    for (uintptr_t p = start_int; p < end_int; p += synci_step)
+      __asm__ volatile("synci 0(%0)" : : "r"(p));
+
+    // The last "move $at, $0" is the target of jr.hb instead of delay slot.
+    __asm__ volatile(".set noat\n"
+                     "sync\n"
+                     "addiupc $at, 12\n"
+                     "jr.hb $at\n"
+                     "move $at, $0\n"
+                     ".set at");
+#else
+    // Pre-R6 may not be globalized. And some implementations may give strange
+    // synci_step. So, let's use libc call for it.
+    cacheflush(start, end_int - start_int, BCACHE);
+#endif
+  }
 #elif defined(__aarch64__) && !defined(__APPLE__)
   uint64_t xstart = (uint64_t)(uintptr_t)start;
   uint64_t xend = (uint64_t)(uintptr_t)end;


        


More information about the llvm-commits mailing list