Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC Commits: 67de53a6 by Cheng Shao at 2025-09-23T14:37:31-04:00 rts: remove obsolete __GNUC__ related logic This patch removes obsolete `__GNUC__` related logic, given on any currently supported platform and toolchain, `__GNUC__ >= 4` is universally true. Also pulls some other weeds and most notably, use `__builtin___clear_cache` for clang as well, since clang has supported this gcc intrinsic since 2014, see https://github.com/llvm/llvm-project/commit/c491a8d4577052bc6b3b4c72a7db6a7c.... - - - - - 10 changed files: - libraries/ghc-internal/cbits/atomic.c - libraries/ghc-internal/cbits/ctz.c - rts/RtsStartup.c - rts/RtsSymbols.c - rts/include/Rts.h - rts/include/Stg.h - rts/include/rts/Types.h - rts/sm/BlockAlloc.c - rts/sm/Evac.h - rts/sm/Storage.c Changes: ===================================== libraries/ghc-internal/cbits/atomic.c ===================================== @@ -163,7 +163,7 @@ hs_atomic_and64(StgWord x, StgWord64 val) #pragma GCC diagnostic push #if defined(__clang__) #pragma GCC diagnostic ignored "-Wsync-fetch-and-nand-semantics-changed" -#elif defined(__GNUC__) +#else #pragma GCC diagnostic ignored "-Wsync-nand" #endif ===================================== libraries/ghc-internal/cbits/ctz.c ===================================== @@ -31,7 +31,7 @@ hs_ctz32(StgWord x) StgWord hs_ctz64(StgWord64 x) { -#if defined(__GNUC__) && (defined(i386_HOST_ARCH) || defined(powerpc_HOST_ARCH)) +#if defined(i386_HOST_ARCH) || defined(powerpc_HOST_ARCH) /* On Linux/i386, the 64bit `__builtin_ctzll()` intrinsic doesn't get inlined by GCC but rather a short `__ctzdi2` runtime function is inserted when needed into compiled object files. ===================================== rts/RtsStartup.c ===================================== @@ -125,13 +125,7 @@ void _fpreset(void) x86_init_fpu(); } -#if defined(__GNUC__) void __attribute__((alias("_fpreset"))) fpreset(void); -#else -void fpreset(void) { - _fpreset(); -} -#endif /* Set the console's CodePage to UTF-8 if using the new I/O manager and the CP is still the default one. */ ===================================== rts/RtsSymbols.c ===================================== @@ -963,7 +963,7 @@ extern char **environ; RTS_INTCHAR_SYMBOLS // 64-bit support functions in libgcc.a -#if defined(__GNUC__) && SIZEOF_VOID_P <= 4 && !defined(_ABIN32) +#if SIZEOF_VOID_P <= 4 && !defined(_ABIN32) #define RTS_LIBGCC_SYMBOLS \ SymI_NeedsProto(__divdi3) \ SymI_NeedsProto(__udivdi3) \ @@ -974,7 +974,7 @@ extern char **environ; SymI_NeedsProto(__ashrdi3) \ SymI_NeedsProto(__lshrdi3) \ SymI_NeedsProto(__fixunsdfdi) -#elif defined(__GNUC__) && SIZEOF_VOID_P == 8 +#elif SIZEOF_VOID_P == 8 #define RTS_LIBGCC_SYMBOLS \ SymI_NeedsProto(__udivti3) \ SymI_NeedsProto(__umodti3) ===================================== rts/include/Rts.h ===================================== @@ -54,35 +54,19 @@ extern "C" { #include "rts/Types.h" #include "rts/Time.h" -#if __GNUC__ >= 3 #define ATTRIBUTE_ALIGNED(n) __attribute__((aligned(n))) -#else -#define ATTRIBUTE_ALIGNED(n) /*nothing*/ -#endif // Symbols that are extern, but private to the RTS, are declared // with visibility "hidden" to hide them outside the RTS shared // library. #define RTS_PRIVATE GNUC3_ATTRIBUTE(visibility("hidden")) -#if __GNUC__ >= 4 #define RTS_UNLIKELY(p) __builtin_expect((p),0) -#else -#define RTS_UNLIKELY(p) (p) -#endif -#if __GNUC__ >= 4 #define RTS_LIKELY(p) __builtin_expect(!!(p), 1) -#else -#define RTS_LIKELY(p) (p) -#endif /* __builtin_unreachable is supported since GNU C 4.5 */ -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #define RTS_UNREACHABLE __builtin_unreachable() -#else -#define RTS_UNREACHABLE abort() -#endif /* Prefetch primitives */ #define prefetchForRead(ptr) __builtin_prefetch(ptr, 0) @@ -374,17 +358,8 @@ TICK_VAR(2) Useful macros and inline functions -------------------------------------------------------------------------- */ -#if defined(__GNUC__) -#define SUPPORTS_TYPEOF -#endif - -#if defined(SUPPORTS_TYPEOF) #define stg_min(a,b) ({typeof(a) _a = (a), _b = (b); _a <= _b ? _a : _b; }) #define stg_max(a,b) ({typeof(a) _a = (a), _b = (b); _a <= _b ? _b : _a; }) -#else -#define stg_min(a,b) ((a) <= (b) ? (a) : (b)) -#define stg_max(a,b) ((a) <= (b) ? (b) : (a)) -#endif /* -------------------------------------------------------------------------- */ ===================================== rts/include/Stg.h ===================================== @@ -131,20 +131,12 @@ /* * GCC attributes */ -#if defined(__GNUC__) #define GNU_ATTRIBUTE(at) __attribute__((at)) -#else -#define GNU_ATTRIBUTE(at) -#endif -#if __GNUC__ >= 3 #define GNUC3_ATTRIBUTE(at) __attribute__((at)) -#else -#define GNUC3_ATTRIBUTE(at) -#endif /* Used to mark a switch case that falls-through */ -#if (defined(__GNUC__) && __GNUC__ >= 7) +#if __GNUC__ >= 7 // N.B. Don't enable fallthrough annotations when compiling with Clang. // Apparently clang doesn't enable implicitly fallthrough warnings by default // http://llvm.org/viewvc/llvm-project?revision=167655&view=revision @@ -154,7 +146,7 @@ #define FALLTHROUGH ((void)0) #endif /* __GNUC__ >= 7 */ -#if !defined(DEBUG) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) +#if !defined(DEBUG) #define GNUC_ATTR_HOT __attribute__((hot)) #else #define GNUC_ATTR_HOT /* nothing */ @@ -168,21 +160,13 @@ See Note [Windows Stack allocations] */ #if defined(__clang__) #define STG_NO_OPTIMIZE __attribute__((optnone)) -#elif defined(__GNUC__) || defined(__GNUG__) -#define STG_NO_OPTIMIZE __attribute__((optimize("O0"))) #else -#define STG_NO_OPTIMIZE /* nothing */ +#define STG_NO_OPTIMIZE __attribute__((optimize("O0"))) #endif // Mark a function as accepting a printf-like format string. -#if !defined(__GNUC__) && defined(mingw32_HOST_OS) -/* On Win64, if we say "printf" then gcc thinks we are going to use - MS format specifiers like %I64d rather than %llu */ -#define STG_PRINTF_ATTR(fmt_arg, rest) GNUC3_ATTRIBUTE(format(gnu_printf, fmt_arg, rest)) -#else /* However, on OS X, "gnu_printf" isn't recognised */ #define STG_PRINTF_ATTR(fmt_arg, rest) GNUC3_ATTRIBUTE(format(printf, fmt_arg, rest)) -#endif #define STG_RESTRICT __restrict__ @@ -204,13 +188,9 @@ # define stg__has_attribute(attr) (0) #endif -#ifdef __GNUC__ -# define STG_GNUC_GUARD_VERSION(major, minor) \ +#define STG_GNUC_GUARD_VERSION(major, minor) \ ((__GNUC__ > (major)) || \ ((__GNUC__ == (major)) && (__GNUC_MINOR__ >= (minor)))) -#else -# define STG_GNUC_GUARD_VERSION(major, minor) (0) -#endif /* * The versions of the `__malloc__` attribute which take arguments are only ===================================== rts/include/rts/Types.h ===================================== @@ -16,16 +16,6 @@ #include <stddef.h> #include <stdbool.h> -// Deprecated, use uint32_t instead. -typedef unsigned int nat __attribute__((deprecated)); /* uint32_t */ - -/* ullong (64|128-bit) type: only include if needed (not ANSI) */ -#if defined(__GNUC__) -#define LL(x) (x##LL) -#else -#define LL(x) (x##L) -#endif - typedef struct StgClosure_ StgClosure; typedef struct StgInfoTable_ StgInfoTable; typedef struct StgTSO_ StgTSO; ===================================== rts/sm/BlockAlloc.c ===================================== @@ -274,19 +274,9 @@ STATIC_INLINE uint32_t log_2(W_ n) { ASSERT(n > 0 && n < (1<<NUM_FREE_LISTS)); -#if defined(__GNUC__) return CLZW(n) ^ (sizeof(StgWord)*8 - 1); // generates good code on x86. __builtin_clz() compiles to bsr+xor, but // we want just bsr, so the xor here cancels out gcc's xor. -#else - W_ i, x; - x = n; - for (i=0; i < NUM_FREE_LISTS; i++) { - x = x >> 1; - if (x == 0) return i; - } - return NUM_FREE_LISTS; -#endif } // log base 2 (ceiling), needs to support up to (2^NUM_FREE_LISTS)-1 @@ -294,18 +284,8 @@ STATIC_INLINE uint32_t log_2_ceil(W_ n) { ASSERT(n > 0 && n < (1<<NUM_FREE_LISTS)); -#if defined(__GNUC__) uint32_t r = log_2(n); return (n & (n-1)) ? r+1 : r; -#else - W_ i, x; - x = 1; - for (i=0; i < MAX_FREE_LIST; i++) { - if (x >= n) return i; - x = x << 1; - } - return MAX_FREE_LIST; -#endif } STATIC_INLINE void ===================================== rts/sm/Evac.h ===================================== @@ -25,7 +25,7 @@ // registers EAX, EDX, and ECX instead of on the stack. Functions that // take a variable number of arguments will continue to be passed all of // their arguments on the stack. -#if __GNUC__ >= 2 && (defined(x86_64_HOST_ARCH) || defined(i386_HOST_ARCH)) +#if defined(x86_64_HOST_ARCH) || defined(i386_HOST_ARCH) #define REGPARM1 __attribute__((regparm(1))) #else #define REGPARM1 ===================================== rts/sm/Storage.c ===================================== @@ -1818,25 +1818,6 @@ StgWord calcTotalCompactW (void) #include <libkern/OSCacheControl.h> #endif -/* __builtin___clear_cache is supported since GNU C 4.3.6. - * We pick 4.4 to simplify condition a bit. - */ -#define GCC_HAS_BUILTIN_CLEAR_CACHE (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) - -#if defined(__clang__) -/* clang defines __clear_cache as a builtin on some platforms. - * For example on armv7-linux-androideabi. The type slightly - * differs from gcc. - */ -extern void __clear_cache(void * begin, void * end); -#elif defined(__GNUC__) && !GCC_HAS_BUILTIN_CLEAR_CACHE -/* __clear_cache is a libgcc function. - * It existed before __builtin___clear_cache was introduced. - * See #8562. - */ -extern void __clear_cache(char * begin, char * end); -#endif /* __GNUC__ */ - /* On ARM and other platforms, we need to flush the cache after writing code into memory, so the processor reliably sees it. */ void flushExec (W_ len, AdjustorExecutable exec_addr) @@ -1849,26 +1830,11 @@ void flushExec (W_ len, AdjustorExecutable exec_addr) /* On iOS we need to use the special 'sys_icache_invalidate' call. */ sys_icache_invalidate(exec_addr, len); #elif defined(wasm32_HOST_ARCH) -#elif defined(__clang__) - unsigned char* begin = (unsigned char*)exec_addr; - unsigned char* end = begin + len; -# if __has_builtin(__builtin___clear_cache) - __builtin___clear_cache((void*)begin, (void*)end); -# else - __clear_cache((void*)begin, (void*)end); -# endif -#elif defined(__GNUC__) - /* For all other platforms, fall back to a libgcc builtin. */ +#else + /* For all other platforms, fall back to __builtin___clear_cache. */ unsigned char* begin = (unsigned char*)exec_addr; unsigned char* end = begin + len; -# if GCC_HAS_BUILTIN_CLEAR_CACHE __builtin___clear_cache((void*)begin, (void*)end); -# else - /* For all other platforms, fall back to a libgcc builtin. */ - __clear_cache((void*)begin, (void*)end); -# endif -#else -#error Missing support to flush the instruction cache #endif } View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/67de53a6ced23caad640d2c742108924... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/67de53a6ced23caad640d2c742108924... You're receiving this email because of your account on gitlab.haskell.org.