Index: common/Logging.cpp
===================================================================
--- common/Logging.cpp	(revision 23566)
+++ common/Logging.cpp	(working copy)
@@ -216,7 +216,7 @@
 	Direction    Direction;
 };
 
-static MPT_FORCEINLINE bool operator < (const Entry &a, const Entry &b) noexcept
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static bool operator < (const Entry &a, const Entry &b) noexcept
 {
 /*
 	return false
@@ -267,7 +267,7 @@
 	g_Enabled = false;
 }
 
-MPT_NOINLINE void Trace(const mpt::source_location & loc, Direction direction) noexcept
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void Trace(const mpt::source_location & loc, Direction direction) noexcept
 {
 	// This will get called in realtime contexts and hot paths.
 	// No blocking allowed here.
Index: common/Logging.h
===================================================================
--- common/Logging.h	(revision 23566)
+++ common/Logging.h	(working copy)
@@ -113,7 +113,7 @@
 void SetFacilities(const std::string &solo, const std::string &blocked);
 bool IsFacilityActive(const char *facility) noexcept;
 #else
-MPT_FORCEINLINE bool IsFacilityActive(const char * /*facility*/ ) noexcept { return true; }
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool IsFacilityActive(const char * /*facility*/ ) noexcept { return true; }
 #endif
 
 
@@ -162,7 +162,7 @@
 	Leave   = -1,
 };
 
-MPT_NOINLINE void Trace(const mpt::source_location & loc, Direction direction = Direction::Unknown) noexcept;
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void Trace(const mpt::source_location & loc, Direction direction = Direction::Unknown) noexcept;
 
 enum ThreadKind {
 	ThreadKindGUI,
@@ -185,7 +185,7 @@
 private:
 	const mpt::source_location loc;
 public:
-	MPT_FORCEINLINE Scope(mpt::source_location loc) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE Scope(mpt::source_location loc) noexcept
 		: loc(loc)
 	{
 		if(mpt::log::Trace::g_Enabled)
@@ -193,7 +193,7 @@
 			mpt::log::Trace::Trace(loc, mpt::log::Trace::Direction::Enter);
 		}
 	}
-	MPT_FORCEINLINE ~Scope() noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE ~Scope() noexcept
 	{
 		if(mpt::log::Trace::g_Enabled)
 		{
Index: common/mptAssert.h
===================================================================
--- common/mptAssert.h	(revision 23566)
+++ common/mptAssert.h	(working copy)
@@ -131,7 +131,7 @@
 
 #if defined(MPT_ASSERT_HANDLER_NEEDED)
 // custom assert handler needed
-MPT_NOINLINE void AssertHandler(const mpt::source_location &loc, const char *expr, const char *msg=nullptr);
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void AssertHandler(const mpt::source_location &loc, const char *expr, const char *msg=nullptr);
 #endif // MPT_ASSERT_HANDLER_NEEDED
 
 
Index: common/mptBaseUtils.h
===================================================================
--- common/mptBaseUtils.h	(revision 23566)
+++ common/mptBaseUtils.h	(working copy)
@@ -115,7 +115,7 @@
 
 	// Multiply two 32-bit integers, receive 64-bit result.
 	// MSVC generates unnecessarily complicated code for the unoptimized variant using _allmul.
-	MPT_CONSTEXPR20_FUN int64 mul32to64(int32 a, int32 b)
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN int64 mul32to64(int32 a, int32 b)
 	{
 		#if MPT_COMPILER_MSVC && (MPT_ARCH_X86 || MPT_ARCH_AMD64)
 			MPT_MAYBE_CONSTANT_IF(MPT_IS_CONSTANT_EVALUATED20())
@@ -130,7 +130,7 @@
 		#endif
 	}
 
-	MPT_CONSTEXPR20_FUN uint64 mul32to64_unsigned(uint32 a, uint32 b)
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN uint64 mul32to64_unsigned(uint32 a, uint32 b)
 	{
 		#if MPT_COMPILER_MSVC && (MPT_ARCH_X86 || MPT_ARCH_AMD64)
 			MPT_MAYBE_CONSTANT_IF(MPT_IS_CONSTANT_EVALUATED20())
@@ -145,27 +145,27 @@
 		#endif
 	}
 
-	MPT_CONSTEXPR20_FUN int32 muldiv(int32 a, int32 b, int32 c)
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN int32 muldiv(int32 a, int32 b, int32 c)
 	{
 		return mpt::saturate_cast<int32>( mul32to64( a, b ) / c );
 	}
 
-	MPT_CONSTEXPR20_FUN int32 muldivr(int32 a, int32 b, int32 c)
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN int32 muldivr(int32 a, int32 b, int32 c)
 	{
 		return mpt::saturate_cast<int32>( ( mul32to64( a, b ) + ( c / 2 ) ) / c );
 	}
 
 	// Do not use overloading because catching unsigned version by accident results in slower X86 code.
-	MPT_CONSTEXPR20_FUN uint32 muldiv_unsigned(uint32 a, uint32 b, uint32 c)
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN uint32 muldiv_unsigned(uint32 a, uint32 b, uint32 c)
 	{
 		return mpt::saturate_cast<uint32>( mul32to64_unsigned( a, b ) / c );
 	}
-	MPT_CONSTEXPR20_FUN uint32 muldivr_unsigned(uint32 a, uint32 b, uint32 c)
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN uint32 muldivr_unsigned(uint32 a, uint32 b, uint32 c)
 	{
 		return mpt::saturate_cast<uint32>( ( mul32to64_unsigned( a, b ) + ( c / 2u ) ) / c );
 	}
 
-	constexpr MPT_FORCEINLINE int32 muldivrfloor(int64 a, uint32 b, uint32 c)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr int32 muldivrfloor(int64 a, uint32 b, uint32 c)
 	{
 		a *= b;
 		a += c / 2u;
Index: common/mptCPU.h
===================================================================
--- common/mptCPU.h	(revision 23566)
+++ common/mptCPU.h	(working copy)
@@ -46,11 +46,11 @@
 }
 
 // enabled processor features for inline asm and intrinsics
-[[nodiscard]] MPT_FORCEINLINE mpt::arch::current::feature_flags GetEnabledFeatures() noexcept
+[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE mpt::arch::current::feature_flags GetEnabledFeatures() noexcept
 {
 	return CPU::detail::EnabledFeatures;
 }
-[[nodiscard]] MPT_FORCEINLINE mpt::arch::current::mode_flags GetEnabledModes() noexcept
+[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE mpt::arch::current::mode_flags GetEnabledModes() noexcept
 {
 	return CPU::detail::EnabledModes;
 }
@@ -57,11 +57,11 @@
 
 struct Info
 {
-	[[nodiscard]] MPT_FORCEINLINE bool HasFeatureSet(mpt::arch::current::feature_flags features) const noexcept
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool HasFeatureSet(mpt::arch::current::feature_flags features) const noexcept
 	{
 		return features == (GetEnabledFeatures() & features);
 	}
-	[[nodiscard]] MPT_FORCEINLINE bool HasModesEnabled(mpt::arch::current::mode_flags modes) const noexcept
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool HasModesEnabled(mpt::arch::current::mode_flags modes) const noexcept
 	{
 		return modes == (GetEnabledModes() & modes);
 	}
@@ -76,11 +76,11 @@
 private:
 	const mpt::arch::flags_cache m_flags{mpt::arch::get_cpu_info()};
 public:
-	[[nodiscard]] MPT_FORCEINLINE bool HasFeatureSet(mpt::arch::current::feature_flags features) const noexcept
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool HasFeatureSet(mpt::arch::current::feature_flags features) const noexcept
 	{
 		return m_flags[features];
 	}
-	[[nodiscard]] MPT_FORCEINLINE bool HasModesEnabled(mpt::arch::current::mode_flags modes) const noexcept
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool HasModesEnabled(mpt::arch::current::mode_flags modes) const noexcept
 	{
 		return m_flags[modes];
 	}
@@ -93,12 +93,12 @@
 namespace feature = mpt::arch::current::feature;
 namespace mode = mpt::arch::current::mode;
 
-[[nodiscard]] MPT_FORCEINLINE bool HasFeatureSet(mpt::arch::current::feature_flags features) noexcept
+[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool HasFeatureSet(mpt::arch::current::feature_flags features) noexcept
 {
 	return CPU::Info{}.HasFeatureSet(features);
 }
 
-[[nodiscard]] MPT_FORCEINLINE bool HasModesEnabled(mpt::arch::current::mode_flags modes) noexcept
+[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool HasModesEnabled(mpt::arch::current::mode_flags modes) noexcept
 {
 	return CPU::Info{}.HasModesEnabled(modes);
 }
Index: common/mptRandom.h
===================================================================
--- common/mptRandom.h	(revision 23566)
+++ common/mptRandom.h	(working copy)
@@ -71,15 +71,15 @@
 		return;
 	}
 public:
-	static MPT_CONSTEXPRINLINE typename engine_traits<Trng>::result_type min()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static typename engine_traits<Trng>::result_type min()
 	{
 		return Trng::min();
 	}
-	static MPT_CONSTEXPRINLINE typename engine_traits<Trng>::result_type max()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static typename engine_traits<Trng>::result_type max()
 	{
 		return Trng::max();
 	}
-	static MPT_CONSTEXPRINLINE int result_bits()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static int result_bits()
 	{
 		return engine_traits<Trng>::result_bits();
 	}
Index: common/version.h
===================================================================
--- common/version.h	(revision 23566)
+++ common/version.h	(working copy)
@@ -44,15 +44,15 @@
 
 public:
 
-	MPT_CONSTEXPRINLINE Version() noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr Version() noexcept
 		: m_Version(0)
 	{}
 
-	explicit MPT_CONSTEXPRINLINE Version(uint32 version) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr explicit Version(uint32 version) noexcept
 		: m_Version(version)
 	{}
 
-	explicit MPT_CONSTEXPRINLINE Version(uint8 v1, uint8 v2, uint8 v3, uint8 v4) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr explicit Version(uint8 v1, uint8 v2, uint8 v3, uint8 v4) noexcept
 		: m_Version((static_cast<uint32>(v1) << 24) | (static_cast<uint32>(v2) << 16) | (static_cast<uint32>(v3) << 8) | (static_cast<uint32>(v4) << 0))
 	{}
 
@@ -65,26 +65,26 @@
 
 public:
 
-	explicit MPT_CONSTEXPRINLINE operator bool () const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr explicit operator bool () const noexcept
 	{
 		return m_Version != 0;
 	}
-	MPT_CONSTEXPRINLINE bool operator ! () const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator ! () const noexcept
 	{
 		return m_Version == 0;
 	}
 
-	MPT_CONSTEXPRINLINE uint32 GetRawVersion() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint32 GetRawVersion() const noexcept
 	{
 		return m_Version;
 	}
 
-	MPT_CONSTEXPRINLINE Version Masked(uint32 mask) const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr Version Masked(uint32 mask) const noexcept
 	{
 		return Version(m_Version & mask);
 	}
 
-	MPT_CONSTEXPRINLINE uint8 GetField(Field field) const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint8 GetField(Field field) const noexcept
 	{
 		return
 			(field == Field::Major) ? static_cast<uint8>((m_Version >> 24) & 0xffu) :
@@ -121,7 +121,7 @@
 
 	private:
 
-		static MPT_CONSTEXPRINLINE uint8 NibbleFromChar(char x)
+		MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static uint8 NibbleFromChar(char x)
 		{
 			return
 				('0' <= x && x <= '9') ? static_cast<uint8>(x - '0' +  0) :
@@ -132,7 +132,7 @@
 
 	public:
 
-		static MPT_CONSTEXPRINLINE Version Parse(const char * str, std::size_t len)
+		MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static Version Parse(const char * str, std::size_t len)
 		{
 			// 0123456789
 			// 1.23.45.67
@@ -179,33 +179,33 @@
 
 };
 
-MPT_CONSTEXPRINLINE bool operator == (const Version &a, const Version &b) noexcept
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator == (const Version &a, const Version &b) noexcept
 {
 	return a.GetRawVersion() == b.GetRawVersion();
 }
-MPT_CONSTEXPRINLINE bool operator != (const Version &a, const Version &b) noexcept
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator != (const Version &a, const Version &b) noexcept
 {
 	return a.GetRawVersion() != b.GetRawVersion();
 }
-MPT_CONSTEXPRINLINE bool operator <= (const Version &a, const Version &b) noexcept
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator <= (const Version &a, const Version &b) noexcept
 {
 	return a.GetRawVersion() <= b.GetRawVersion();
 }
-MPT_CONSTEXPRINLINE bool operator >= (const Version &a, const Version &b) noexcept
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator >= (const Version &a, const Version &b) noexcept
 {
 	return a.GetRawVersion() >= b.GetRawVersion();
 }
-MPT_CONSTEXPRINLINE bool operator < (const Version &a, const Version &b) noexcept
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator < (const Version &a, const Version &b) noexcept
 {
 	return a.GetRawVersion() < b.GetRawVersion();
 }
-MPT_CONSTEXPRINLINE bool operator > (const Version &a, const Version &b) noexcept
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator > (const Version &a, const Version &b) noexcept
 {
 	return a.GetRawVersion() > b.GetRawVersion();
 }
 
 
-MPT_CONSTEVAL Version operator ""_LiteralVersionImpl (const char * str, std::size_t len)
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL Version operator ""_LiteralVersionImpl (const char * str, std::size_t len)
 {
 	return Version::LiteralParser::Parse(str, len);
 }
Index: installer/updatesigntool/updatesigntool.cpp
===================================================================
--- installer/updatesigntool/updatesigntool.cpp	(revision 23566)
+++ installer/updatesigntool/updatesigntool.cpp	(working copy)
@@ -54,7 +54,7 @@
 
 
 #if defined(MPT_ASSERT_HANDLER_NEEDED) && defined(MPT_BUILD_UPDATESIGNTOOL)
-MPT_NOINLINE void AssertHandler(const mpt::source_location &loc, const char *expr, const char *msg)
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void AssertHandler(const mpt::source_location &loc, const char *expr, const char *msg)
 {
 	if(msg)
 	{
Index: libopenmpt/libopenmpt_impl.cpp
===================================================================
--- libopenmpt/libopenmpt_impl.cpp	(revision 23566)
+++ libopenmpt/libopenmpt_impl.cpp	(working copy)
@@ -88,7 +88,7 @@
 
 #if defined(MPT_ASSERT_HANDLER_NEEDED) && !defined(ENABLE_TESTS)
 
-MPT_NOINLINE void AssertHandler(const mpt::source_location &loc, const char *expr, const char *msg) {
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void AssertHandler(const mpt::source_location &loc, const char *expr, const char *msg) {
 	if(msg) {
 		mpt::log::GlobalLogger().SendLogMessage(loc, LogError, "ASSERT",
 			MPT_USTRING("ASSERTION FAILED: ") + mpt::transcode<mpt::ustring>(mpt::source_encoding, msg) + MPT_USTRING(" (") + mpt::transcode<mpt::ustring>(mpt::source_encoding, expr) + MPT_USTRING(")")
Index: misc/WriteMemoryDump.h
===================================================================
--- misc/WriteMemoryDump.h	(revision 23566)
+++ misc/WriteMemoryDump.h	(working copy)
@@ -26,7 +26,7 @@
 
 OPENMPT_NAMESPACE_BEGIN
 
-inline MPT_NOINLINE bool WriteMemoryDump(_EXCEPTION_POINTERS *pExceptionInfo, const TCHAR *filename, bool fullMemDump)
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE inline bool WriteMemoryDump(_EXCEPTION_POINTERS *pExceptionInfo, const TCHAR *filename, bool fullMemDump)
 {
 	bool result = false;
 	HMODULE hDll = ::LoadLibrary(_T("DBGHELP.DLL"));
Index: mptrack/Ctrl_pat.h
===================================================================
--- mptrack/Ctrl_pat.h	(revision 23566)
+++ mptrack/Ctrl_pat.h	(working copy)
@@ -66,7 +66,7 @@
 	};
 	void SetSelection(ORDERINDEX firstOrd, ORDERINDEX lastOrd = ORDERINDEX_INVALID);
 	// Why VC wants to inline this huge function is beyond my understanding...
-	MPT_NOINLINE bool SetCurSel(ORDERINDEX sel, bool setPlayPos = true, bool shiftClick = false, bool ignoreCurSel = false);
+	MPT_ATTR_NOINLINE MPT_DECL_NOINLINE bool SetCurSel(ORDERINDEX sel, bool setPlayPos = true, bool shiftClick = false, bool ignoreCurSel = false);
 	void UpdateScrollInfo();
 	void UpdateInfoText();
 	int GetFontWidth();
Index: mptrack/Ctrl_smp.h
===================================================================
--- mptrack/Ctrl_smp.h	(revision 23566)
+++ mptrack/Ctrl_smp.h	(working copy)
@@ -158,7 +158,7 @@
 
 	afx_msg void OnInitOPLInstrument();
 
-	MPT_NOINLINE void SetModified(SAMPLEINDEX smp, SampleHint hint, bool updateAll, bool waveformModified);
+	MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void SetModified(SAMPLEINDEX smp, SampleHint hint, bool updateAll, bool waveformModified);
 	void SetModified(SampleHint hint, bool updateAll, bool waveformModified) { SetModified(m_nSample, hint, updateAll, waveformModified); }
 	void PrepareUndo(const char *description, sampleUndoTypes type = sundo_none, SmpLength start = 0, SmpLength end = 0);
 
Index: mptrack/Draw_pat.cpp
===================================================================
--- mptrack/Draw_pat.cpp	(revision 23566)
+++ mptrack/Draw_pat.cpp	(working copy)
@@ -381,7 +381,7 @@
 }
 #endif
 
-static MPT_FORCEINLINE void DrawPadding(CFastBitmap &dib, const PATTERNFONT *pfnt, int x, int y, PatternCursor::Columns col)
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void DrawPadding(CFastBitmap &dib, const PATTERNFONT *pfnt, int x, int y, PatternCursor::Columns col)
 {
 	if(pfnt->padding[col])
 		dib.TextBlt(x + pfnt->nEltWidths[col] - pfnt->padding[col], y, pfnt->padding[col], pfnt->spacingY, pfnt->nClrX + pfnt->nEltWidths[col] - pfnt->padding[col], pfnt->nClrY, pfnt->dib);
Index: mptrack/ExceptionHandler.cpp
===================================================================
--- mptrack/ExceptionHandler.cpp	(revision 23566)
+++ mptrack/ExceptionHandler.cpp	(working copy)
@@ -810,7 +810,7 @@
 
 #if defined(MPT_ASSERT_HANDLER_NEEDED)
 
-MPT_NOINLINE void AssertHandler(const mpt::source_location &loc, const char *expr, const char *msg)
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void AssertHandler(const mpt::source_location &loc, const char *expr, const char *msg)
 {
 	DebugReporter report(msg ? DumpModeWarning : DumpModeCrash, nullptr);
 	if(IsDebuggerPresent())
Index: mptrack/HighDPISupport.h
===================================================================
--- mptrack/HighDPISupport.h	(revision 23566)
+++ mptrack/HighDPISupport.h	(working copy)
@@ -51,13 +51,13 @@
 	bool GetWindowPlacement(HWND hwnd, WINDOWPLACEMENT &wpl);
 
 	// Applies DPI scaling factor to some given size
-	MPT_FORCEINLINE int ScalePixels(int pixels, HWND hwnd)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE int ScalePixels(int pixels, HWND hwnd)
 	{
 		return MulDiv(pixels, HighDPISupport::GetDpiForWindow(hwnd), 96);
 	}
 
 	// Removes DPI scaling factor from some given size
-	MPT_FORCEINLINE int ScalePixelsInv(int pixels, HWND hwnd)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE int ScalePixelsInv(int pixels, HWND hwnd)
 	{
 		return MulDiv(pixels, 96, HighDPISupport::GetDpiForWindow(hwnd));
 	}
Index: mptrack/Image.h
===================================================================
--- mptrack/Image.h	(revision 23566)
+++ mptrack/Image.h	(working copy)
@@ -55,8 +55,8 @@
 public:
 	constexpr uint32 Width() const noexcept { return width; }
 	constexpr uint32 Height() const noexcept { return height; }
-	MPT_FORCEINLINE Pixel &operator()(uint32 x, uint32 y) noexcept { return pixels[y * width + x]; }
-	MPT_FORCEINLINE const Pixel &operator()(uint32 x, uint32 y) const noexcept { return pixels[y * width + x]; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE Pixel &operator()(uint32 x, uint32 y) noexcept { return pixels[y * width + x]; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE const Pixel &operator()(uint32 x, uint32 y) const noexcept { return pixels[y * width + x]; }
 	std::vector<Pixel> &Pixels() { return pixels; }
 	const std::vector<Pixel> &Pixels() const { return pixels; }
 };
Index: mptrack/UpdateHints.h
===================================================================
--- mptrack/UpdateHints.h	(revision 23566)
+++ mptrack/UpdateHints.h	(working copy)
@@ -97,24 +97,24 @@
 	}
 
 	template<typename T>
-	MPT_FORCEINLINE T GetData() const { return static_cast<T>(item); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE T GetData() const { return static_cast<T>(item); }
 
 public:
 	UpdateHint() : type(HINT_NONE), category(HINTCAT_GLOBAL), item(0) { }
 
 	template<typename T>
-	MPT_FORCEINLINE UpdateHint &SetData(T i) { item = i; MPT_ASSERT(item == i); return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE UpdateHint &SetData(T i) { item = i; MPT_ASSERT(item == i); return *this; }
 
-	MPT_FORCEINLINE HintCategory GetCategory() const { return static_cast<HintCategory>(category); }
-	MPT_FORCEINLINE FlagSet<HintType> GetType() const { return FlagSet<HintType>(static_cast<FlagSet<HintType>::store_type>(type)); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE HintCategory GetCategory() const { return static_cast<HintCategory>(category); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE FlagSet<HintType> GetType() const { return FlagSet<HintType>(static_cast<FlagSet<HintType>::store_type>(type)); }
 
 	// CModDoc hint tunnelling
-	static MPT_FORCEINLINE UpdateHint FromLPARAM(LPARAM rawData) { UpdateHint hint; hint.rawData = static_cast<store_t>(rawData); return hint; }
-	MPT_FORCEINLINE LPARAM AsLPARAM() const { return rawData; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static UpdateHint FromLPARAM(LPARAM rawData) { UpdateHint hint; hint.rawData = static_cast<store_t>(rawData); return hint; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE LPARAM AsLPARAM() const { return rawData; }
 
 	// Discard any hints that don't belong to class T.
 	template<typename T>
-	MPT_FORCEINLINE T ToType() const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE T ToType() const
 	{
 		T hint = static_cast<const T &>(*this);
 		if(T::classCategory != static_cast<HintCategory>(category))
@@ -126,9 +126,9 @@
 	}
 
 	// Set global hint flags
-	MPT_FORCEINLINE UpdateHint &ModType() { type |= HINT_MODTYPE; return *this; }
-	MPT_FORCEINLINE UpdateHint &MPTOptions() { type |= HINT_MPTOPTIONS; return *this; }
-	MPT_FORCEINLINE UpdateHint &Undo() { type |= HINT_UNDO; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE UpdateHint &ModType() { type |= HINT_MODTYPE; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE UpdateHint &MPTOptions() { type |= HINT_MPTOPTIONS; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE UpdateHint &Undo() { type |= HINT_UNDO; return *this; }
 };
 
 struct GeneralHint : public UpdateHint
@@ -136,11 +136,11 @@
 	static constexpr HintCategory classCategory = HINTCAT_GENERAL;
 	GeneralHint() : UpdateHint(classCategory, 0) { }
 	GeneralHint(CHANNELINDEX channel) : UpdateHint(classCategory, 1 + channel) { }
-	MPT_FORCEINLINE GeneralHint &General() { type |= HINT_MODGENERAL; return *this; }
-	MPT_FORCEINLINE GeneralHint &Channels() { type |= HINT_MODCHANNELS; return *this; }
-	MPT_FORCEINLINE GeneralHint &Tunings() { type |= HINT_TUNINGS; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE GeneralHint &General() { type |= HINT_MODGENERAL; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE GeneralHint &Channels() { type |= HINT_MODCHANNELS; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE GeneralHint &Tunings() { type |= HINT_TUNINGS; return *this; }
 
-	MPT_FORCEINLINE CHANNELINDEX GetChannel() const { return item ? static_cast<CHANNELINDEX>(item - 1) : CHANNELINDEX_INVALID; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE CHANNELINDEX GetChannel() const { return item ? static_cast<CHANNELINDEX>(item - 1) : CHANNELINDEX_INVALID; }
 };
 
 struct PatternHint : public UpdateHint
@@ -147,8 +147,8 @@
 {
 	static constexpr HintCategory classCategory = HINTCAT_PATTERNS;
 	PatternHint(PATTERNINDEX item = 0) : UpdateHint(classCategory, item) { }
-	MPT_FORCEINLINE PatternHint &Data() { type |= HINT_PATTERNDATA; return *this; }
-	MPT_FORCEINLINE PatternHint &Names() { type |= HINT_PATNAMES; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE PatternHint &Data() { type |= HINT_PATTERNDATA; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE PatternHint &Names() { type |= HINT_PATNAMES; return *this; }
 
 	PATTERNINDEX GetPattern() const { return GetData<PATTERNINDEX>(); }
 };
@@ -158,7 +158,7 @@
 	static constexpr HintCategory classCategory = HINTCAT_PATTERNS;
 	RowHint(ROWINDEX item = 0) : UpdateHint(classCategory, item) { type = HINT_PATTERNROW; }
 
-	MPT_FORCEINLINE ROWINDEX GetRow() const { return GetData<ROWINDEX>(); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE ROWINDEX GetRow() const { return GetData<ROWINDEX>(); }
 };
 
 struct SampleHint : public UpdateHint
@@ -165,11 +165,11 @@
 {
 	static constexpr HintCategory classCategory = HINTCAT_SAMPLES;
 	SampleHint(SAMPLEINDEX item = 0) : UpdateHint(classCategory, item) { }
-	MPT_FORCEINLINE SampleHint &Info() { type |= HINT_SAMPLEINFO; return *this; }
-	MPT_FORCEINLINE SampleHint &Data() { type |= HINT_SAMPLEDATA; return *this; }
-	MPT_FORCEINLINE SampleHint &Names() { type |= HINT_SMPNAMES; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE SampleHint &Info() { type |= HINT_SAMPLEINFO; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE SampleHint &Data() { type |= HINT_SAMPLEDATA; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE SampleHint &Names() { type |= HINT_SMPNAMES; return *this; }
 
-	MPT_FORCEINLINE SAMPLEINDEX GetSample() const { return GetData<SAMPLEINDEX>(); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE SAMPLEINDEX GetSample() const { return GetData<SAMPLEINDEX>(); }
 };
 
 struct InstrumentHint : public UpdateHint
@@ -176,11 +176,11 @@
 {
 	static constexpr HintCategory classCategory = HINTCAT_INSTRUMENTS;
 	InstrumentHint(INSTRUMENTINDEX item = 0) : UpdateHint(classCategory, item) { }
-	MPT_FORCEINLINE InstrumentHint &Info() { type |= HINT_INSTRUMENT; return *this; }
-	MPT_FORCEINLINE InstrumentHint &Envelope() { type |= HINT_ENVELOPE; return *this; }
-	MPT_FORCEINLINE InstrumentHint &Names() { type |= HINT_INSNAMES; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE InstrumentHint &Info() { type |= HINT_INSTRUMENT; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE InstrumentHint &Envelope() { type |= HINT_ENVELOPE; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE InstrumentHint &Names() { type |= HINT_INSNAMES; return *this; }
 
-	MPT_FORCEINLINE INSTRUMENTINDEX GetInstrument() const { return GetData<INSTRUMENTINDEX>(); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE INSTRUMENTINDEX GetInstrument() const { return GetData<INSTRUMENTINDEX>(); }
 };
 
 struct SequenceHint : public UpdateHint
@@ -187,11 +187,11 @@
 {
 	static constexpr HintCategory classCategory = HINTCAT_SEQUENCE;
 	SequenceHint(SEQUENCEINDEX item = 0) : UpdateHint(classCategory, item) { }
-	MPT_FORCEINLINE SequenceHint &Data() { type |= HINT_MODSEQUENCE; return *this; }
-	MPT_FORCEINLINE SequenceHint &Names() { type |= HINT_SEQNAMES; return *this; }
-	MPT_FORCEINLINE SequenceHint &RestartPos() { type |= HINT_RESTARTPOS; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE SequenceHint &Data() { type |= HINT_MODSEQUENCE; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE SequenceHint &Names() { type |= HINT_SEQNAMES; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE SequenceHint &RestartPos() { type |= HINT_RESTARTPOS; return *this; }
 
-	MPT_FORCEINLINE SEQUENCEINDEX GetSequence() const { return GetData<SEQUENCEINDEX>(); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE SEQUENCEINDEX GetSequence() const { return GetData<SEQUENCEINDEX>(); }
 };
 
 struct PluginHint : public UpdateHint
@@ -198,11 +198,11 @@
 {
 	static constexpr HintCategory classCategory = HINTCAT_PLUGINS;
 	PluginHint(PLUGINDEX item = 0) : UpdateHint(classCategory, item) { }
-	MPT_FORCEINLINE PluginHint &Info() { type |= HINT_MIXPLUGINS; return *this; }
-	MPT_FORCEINLINE PluginHint &Names() { type |= HINT_PLUGINNAMES; return *this; }
-	MPT_FORCEINLINE PluginHint &Parameter() { type |= HINT_PLUGINPARAM; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE PluginHint &Info() { type |= HINT_MIXPLUGINS; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE PluginHint &Names() { type |= HINT_PLUGINNAMES; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE PluginHint &Parameter() { type |= HINT_PLUGINPARAM; return *this; }
 
-	MPT_FORCEINLINE PLUGINDEX GetPlugin() const { return GetData<PLUGINDEX>(); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE PLUGINDEX GetPlugin() const { return GetData<PLUGINDEX>(); }
 };
 
 struct CommentHint : public UpdateHint
Index: mptrack/View_smp.h
===================================================================
--- mptrack/View_smp.h	(revision 23566)
+++ mptrack/View_smp.h	(working copy)
@@ -103,7 +103,7 @@
 	DECLARE_SERIAL(CViewSample)
 
 protected:
-	MPT_NOINLINE void SetModified(SampleHint hint, bool updateAll, bool waveformModified);
+	MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void SetModified(SampleHint hint, bool updateAll, bool waveformModified);
 	void UpdateScrollSize() { UpdateScrollSize(m_nZoom, true); }
 	void UpdateScrollSize(int newZoom, bool forceRefresh, SmpLength centeredSample = SmpLength(-1));
 	void UpdateOPLEditor();
Index: mptrack/wine/Native.cpp
===================================================================
--- mptrack/wine/Native.cpp	(revision 23566)
+++ mptrack/wine/Native.cpp	(working copy)
@@ -37,7 +37,7 @@
 OPENMPT_NAMESPACE_BEGIN
 
 #if defined(MPT_ASSERT_HANDLER_NEEDED) && defined(MPT_BUILD_WINESUPPORT)
-MPT_NOINLINE void AssertHandler(const mpt::source_location &loc, const char *expr, const char *msg)
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void AssertHandler(const mpt::source_location &loc, const char *expr, const char *msg)
 {
 	if(msg)
 	{
Index: sounddsp/Reverb.cpp
===================================================================
--- sounddsp/Reverb.cpp	(revision 23566)
+++ sounddsp/Reverb.cpp	(working copy)
@@ -42,20 +42,20 @@
 
 #if defined(MPT_WANT_ARCH_INTRINSICS_X86_SSE2) && defined(MPT_ARCH_INTRINSICS_X86_SSE2)
 #if defined(MPT_ARCH_QUIRK_SSE2_NO_UNALIGNED_LOAD_STORE)
-static MPT_FORCEINLINE __m128i mpt_mm_loadu_si64(void const *mem_addr) {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static __m128i mpt_mm_loadu_si64(void const *mem_addr) {
 	__m128i tmp;
 	std::memset(&tmp, 0, sizeof(__m128i));
 	std::memcpy(&tmp, mem_addr, 8);
 	return _mm_loadl_epi64(&tmp);
 }
-static MPT_FORCEINLINE void mpt_mm_storeu_si64(void *mem_addr, __m128i a) {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void mpt_mm_storeu_si64(void *mem_addr, __m128i a) {
 	std::memcpy(mem_addr, &a, 8);
 }
 #else
-static MPT_FORCEINLINE __m128i mpt_mm_loadu_si64(void const *mem_addr) {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static __m128i mpt_mm_loadu_si64(void const *mem_addr) {
 	return _mm_loadu_si64(mem_addr);
 }
-static MPT_FORCEINLINE void mpt_mm_storeu_si64(void *mem_addr, __m128i a) {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void mpt_mm_storeu_si64(void *mem_addr, __m128i a) {
 	_mm_storeu_si64(mem_addr, a);
 }
 #endif
@@ -729,7 +729,7 @@
 //
 
 // Save some typing
-static MPT_FORCEINLINE int32 Clamp16(int32 x) { return Clamp(x, std::numeric_limits<int16>::min(), std::numeric_limits<int16>::max()); }
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static int32 Clamp16(int32 x) { return Clamp(x, std::numeric_limits<int16>::min(), std::numeric_limits<int16>::max()); }
 
 void CReverb::ProcessPreDelay(SWRvbRefDelay * MPT_RESTRICT pPreDelay, const int32 * MPT_RESTRICT pIn, uint32 nSamples)
 {
Index: soundlib/Fastmix.cpp
===================================================================
--- soundlib/Fastmix.cpp	(revision 23566)
+++ soundlib/Fastmix.cpp	(working copy)
@@ -89,13 +89,13 @@
 	}
 
 	// Returns the buffer length required to render a certain amount of samples, based on the channel's playback speed.
-	static MPT_FORCEINLINE uint32 DistanceToBufferLength(SamplePosition from, SamplePosition to, SamplePosition inc)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static uint32 DistanceToBufferLength(SamplePosition from, SamplePosition to, SamplePosition inc)
 	{
 		return static_cast<uint32>((to - from - SamplePosition(1)) / inc) + 1;
 	}
 
 	// Check how many samples can be rendered without encountering loop or sample end, and also update loop position / direction
-	MPT_FORCEINLINE uint32 GetSampleCount(ModChannel &chn, uint32 nSamples) const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE uint32 GetSampleCount(ModChannel &chn, uint32 nSamples) const
 	{
 		int32 nLoopStart = chn.dwFlags[CHN_LOOP] ? chn.nLoopStart : 0;
 		SamplePosition nInc = chn.increment;
Index: soundlib/FloatMixer.h
===================================================================
--- soundlib/FloatMixer.h	(revision 23566)
+++ soundlib/FloatMixer.h	(working copy)
@@ -23,7 +23,7 @@
 	static_assert(std::numeric_limits<input_t>::is_integer, "Input must be integer");
 	static_assert(!std::numeric_limits<output_t>::is_integer, "Output must be floating point");
 
-	static MPT_CONSTEXPRINLINE output_t Convert(const input_t x)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static output_t Convert(const input_t x)
 	{
 		return static_cast<output_t>(x) * (static_cast<output_t>(1) / static_cast<output_t>(int2float));
 	}
@@ -41,9 +41,9 @@
 template<class Traits>
 struct LinearInterpolation
 {
-	MPT_FORCEINLINE LinearInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE LinearInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
 
-	MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const uint32 posLo)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const uint32 posLo)
 	{
 		static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
 		const typename Traits::output_t fract = posLo / static_cast<typename Traits::output_t>(0x100000000); //CResampler::LinearTablef[posLo >> 24];
@@ -62,9 +62,9 @@
 template<class Traits>
 struct FastSincInterpolation
 {
-	MPT_FORCEINLINE FastSincInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE FastSincInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
 
-	MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const uint32 posLo)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const uint32 posLo)
 	{
 		static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
 		const typename Traits::output_t *lut = CResampler::FastSincTablef + ((posLo >> 22) & 0x3FC);
@@ -86,13 +86,13 @@
 {
 	const typename Traits::output_t *sinc;
 
-	MPT_FORCEINLINE PolyphaseInterpolation(const ModChannel &chn, const CResampler &resampler, unsigned int)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE PolyphaseInterpolation(const ModChannel &chn, const CResampler &resampler, unsigned int)
 	{
 		sinc = (((chn.increment > SamplePosition(0x130000000ll)) || (chn.increment < -SamplePosition(-0x130000000ll))) ?
 			(((chn.increment > SamplePosition(0x180000000ll)) || (chn.increment < SamplePosition(-0x180000000ll))) ? resampler.gDownsample2x : resampler.gDownsample13x) : resampler.gKaiserSinc);
 	}
 
-	MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const uint32 posLo)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const uint32 posLo)
 	{
 		static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
 		const typename Traits::output_t *lut = sinc + ((posLo >> (32 - SINC_PHASES_BITS)) & SINC_MASK) * SINC_WIDTH;
@@ -118,12 +118,12 @@
 {
 	const typename Traits::output_t *WFIRlut;
 
-	MPT_FORCEINLINE FIRFilterInterpolation(const ModChannel &, const CResampler &resampler, unsigned int)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE FIRFilterInterpolation(const ModChannel &, const CResampler &resampler, unsigned int)
 	{
 		WFIRlut = resampler.m_WindowedFIR.lut;
 	}
 
-	MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const uint32 posLo)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const uint32 posLo)
 	{
 		static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
 		const typename Traits::output_t * const lut = WFIRlut + ((((posLo >> 16) + WFIR_FRACHALVE) >> WFIR_FRACSHIFT) & WFIR_FRACMASK);
@@ -152,7 +152,7 @@
 {
 	typename Traits::output_t lVol, rVol;
 
-	MPT_FORCEINLINE NoRamp(const ModChannel &chn)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE NoRamp(const ModChannel &chn)
 	{
 		lVol = static_cast<Traits::output_t>(chn.leftVol) * (1.0f / 4096.0f);
 		rVol = static_cast<Traits::output_t>(chn.rightVol) * (1.0f / 4096.0f);
@@ -165,7 +165,7 @@
 	ModChannel &channel;
 	int32 lRamp, rRamp;
 
-	MPT_FORCEINLINE Ramp(ModChannel &chn)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE Ramp(ModChannel &chn)
 		: channel{chn}
 	{
 		lRamp = chn.rampLeftVol;
@@ -172,7 +172,7 @@
 		rRamp = chn.rampRightVol;
 	}
 
-	MPT_FORCEINLINE ~Ramp()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE ~Ramp()
 	{
 		channel.rampLeftVol = lRamp; channel.leftVol = lRamp >> VOLUMERAMPPRECISION;
 		channel.rampRightVol = rRamp; channel.rightVol = rRamp >> VOLUMERAMPPRECISION;
@@ -184,7 +184,7 @@
 template<class Traits>
 struct MixMonoFastNoRamp : public NoRamp<Traits>
 {
-	MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &chn, typename Traits::output_t * const outBuffer)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &chn, typename Traits::output_t * const outBuffer)
 	{
 		typename Traits::output_t vol = outSample[0] * lVol;
 		for(int i = 0; i < Traits::numChannelsOut; i++)
@@ -198,7 +198,7 @@
 template<class Traits>
 struct MixMonoNoRamp : public NoRamp<Traits>
 {
-	MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &, typename Traits::output_t * const outBuffer)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &, typename Traits::output_t * const outBuffer)
 	{
 		outBuffer[0] += outSample[0] * lVol;
 		outBuffer[1] += outSample[0] * rVol;
@@ -209,7 +209,7 @@
 template<class Traits>
 struct MixMonoRamp : public Ramp
 {
-	MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &chn, typename Traits::output_t * const outBuffer)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &chn, typename Traits::output_t * const outBuffer)
 	{
 		// TODO volume is not float, can we optimize this?
 		lRamp += chn.leftRamp;
@@ -223,7 +223,7 @@
 template<class Traits>
 struct MixStereoNoRamp : public NoRamp<Traits>
 {
-	MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &, typename Traits::output_t * const outBuffer)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &, typename Traits::output_t * const outBuffer)
 	{
 		outBuffer[0] += outSample[0] * lVol;
 		outBuffer[1] += outSample[1] * rVol;
@@ -234,7 +234,7 @@
 template<class Traits>
 struct MixStereoRamp : public Ramp
 {
-	MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &chn, typename Traits::output_t * const outBuffer)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &chn, typename Traits::output_t * const outBuffer)
 	{
 		// TODO volume is not float, can we optimize this?
 		lRamp += chn.leftRamp;
@@ -252,9 +252,9 @@
 template<class Traits>
 struct NoFilter
 {
-	MPT_FORCEINLINE NoFilter(const ModChannel &) { }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE NoFilter(const ModChannel &) { }
 
-	MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &, const ModChannel &) { }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (const typename Traits::outbuf_t &, const ModChannel &) { }
 };
 
 
@@ -266,7 +266,7 @@
 	// Filter history
 	typename Traits::output_t fy[Traits::numChannelsIn][2];
 
-	MPT_FORCEINLINE ResonantFilter(ModChannel &chn)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE ResonantFilter(ModChannel &chn)
 		: channel{chn}
 	{
 		for(int i = 0; i < Traits::numChannelsIn; i++)
@@ -276,7 +276,7 @@
 		}
 	}
 
-	MPT_FORCEINLINE ~ResonantFilter(ModChannel &chn)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE ~ResonantFilter(ModChannel &chn)
 	{
 		for(int i = 0; i < Traits::numChannelsIn; i++)
 		{
@@ -288,7 +288,7 @@
 	// Filter values are clipped to double the input range
 #define ClipFilter(x) Clamp(x, static_cast<Traits::output_t>(-2.0f), static_cast<Traits::output_t>(2.0f))
 
-	MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const ModChannel &chn)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (typename Traits::outbuf_t &outSample, const ModChannel &chn)
 	{
 		static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
 
Index: soundlib/InstrumentSynth.h
===================================================================
--- soundlib/InstrumentSynth.h	(revision 23566)
+++ soundlib/InstrumentSynth.h	(working copy)
@@ -203,7 +203,7 @@
 		constexpr Event &operator=(const Event &other) noexcept = default;
 		constexpr Event &operator=(Event &&other) noexcept = default;
 
-		MPT_CONSTEXPR20_FUN bool IsJumpEvent() const noexcept
+		MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN bool IsJumpEvent() const noexcept
 		{
 			return mpt::contains(JumpEvents, type);
 		}
Index: soundlib/IntMixer.h
===================================================================
--- soundlib/IntMixer.h	(revision 23566)
+++ soundlib/IntMixer.h	(working copy)
@@ -26,7 +26,7 @@
 	using input_t = typename base_t::input_t;
 	using output_t = typename base_t::output_t;
 
-	static MPT_CONSTEXPRINLINE output_t Convert(const input_t x)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static output_t Convert(const input_t x)
 	{
 		static_assert(std::numeric_limits<input_t>::is_integer, "Input must be integer");
 		static_assert(std::numeric_limits<output_t>::is_integer, "Output must be integer");
@@ -55,7 +55,7 @@
 	const int numSteps;
 	unsigned int remainingSamples = 0;
 
-	MPT_FORCEINLINE AmigaBlepInterpolation(ModChannel &chn, const CResampler &resampler, unsigned int numSamples)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE AmigaBlepInterpolation(ModChannel &chn, const CResampler &resampler, unsigned int numSamples)
 		: paula{chn.paulaState}
 		, WinSincIntegral{resampler.blepTables.GetAmigaTable(resampler.m_Settings.emulateAmiga, chn.dwFlags[CHN_AMIGAFILTER])}
 		, numSteps{chn.paulaState.numSteps}
@@ -73,7 +73,7 @@
 		
 	}
 
-	MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const MPT_RESTRICT inBuffer, const uint32 posLo)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const MPT_RESTRICT inBuffer, const uint32 posLo)
 	{
 		if(--remainingSamples == 0)
 			subIncrement = {};
@@ -115,9 +115,9 @@
 template<class Traits>
 struct LinearInterpolation
 {
-	MPT_FORCEINLINE LinearInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE LinearInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
 
-	MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const MPT_RESTRICT inBuffer, const uint32 posLo)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const MPT_RESTRICT inBuffer, const uint32 posLo)
 	{
 		static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
 		const typename Traits::output_t fract = posLo >> 18u;
@@ -136,9 +136,9 @@
 template<class Traits>
 struct FastSincInterpolation
 {
-	MPT_FORCEINLINE FastSincInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE FastSincInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
 
-	MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const MPT_RESTRICT inBuffer, const uint32 posLo)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const MPT_RESTRICT inBuffer, const uint32 posLo)
 	{
 		static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
 		const int16 *lut = CResampler::FastSincTable + ((posLo >> 22) & 0x3FC);
@@ -160,7 +160,7 @@
 {
 	const SINC_TYPE *sinc;
 
-	MPT_FORCEINLINE PolyphaseInterpolation(const ModChannel &chn, const CResampler &resampler, unsigned int)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE PolyphaseInterpolation(const ModChannel &chn, const CResampler &resampler, unsigned int)
 	{
 		#ifdef MODPLUG_TRACKER
 			// Otherwise causes "warning C4100: 'resampler' : unreferenced formal parameter"
@@ -172,7 +172,7 @@
 			(((chn.increment > SamplePosition(0x180000000ll)) || (chn.increment < SamplePosition(-0x180000000ll))) ? resampler.gDownsample2x : resampler.gDownsample13x) : resampler.gKaiserSinc);
 	}
 
-	MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const MPT_RESTRICT inBuffer, const uint32 posLo)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const MPT_RESTRICT inBuffer, const uint32 posLo)
 	{
 		static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
 		const SINC_TYPE *lut = sinc + ((posLo >> (32 - SINC_PHASES_BITS)) & SINC_MASK) * SINC_WIDTH;
@@ -198,12 +198,12 @@
 {
 	const int16 *WFIRlut;
 
-	MPT_FORCEINLINE FIRFilterInterpolation(const ModChannel &, const CResampler &resampler, unsigned int)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE FIRFilterInterpolation(const ModChannel &, const CResampler &resampler, unsigned int)
 	{
 		WFIRlut = resampler.m_WindowedFIR.lut;
 	}
 
-	MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const MPT_RESTRICT inBuffer, const uint32 posLo)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const MPT_RESTRICT inBuffer, const uint32 posLo)
 	{
 		static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
 		const int16 * const lut = WFIRlut + ((((posLo >> 16) + WFIR_FRACHALVE) >> WFIR_FRACSHIFT) & WFIR_FRACMASK);
@@ -234,7 +234,7 @@
 {
 	typename Traits::output_t lVol, rVol;
 
-	MPT_FORCEINLINE NoRamp(const ModChannel &chn)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE NoRamp(const ModChannel &chn)
 	{
 		lVol = chn.leftVol;
 		rVol = chn.rightVol;
@@ -247,7 +247,7 @@
 	ModChannel &channel;
 	int32 lRamp, rRamp;
 
-	MPT_FORCEINLINE Ramp(ModChannel &chn)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE Ramp(ModChannel &chn)
 		: channel{chn}
 	{
 		lRamp = chn.rampLeftVol;
@@ -254,7 +254,7 @@
 		rRamp = chn.rampRightVol;
 	}
 
-	MPT_FORCEINLINE ~Ramp()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE ~Ramp()
 	{
 		channel.rampLeftVol = lRamp; channel.leftVol = lRamp >> VOLUMERAMPPRECISION;
 		channel.rampRightVol = rRamp; channel.rightVol = rRamp >> VOLUMERAMPPRECISION;
@@ -267,7 +267,7 @@
 struct MixMonoFastNoRamp : public NoRamp<Traits>
 {
 	using base_t = NoRamp<Traits>;
-	MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &, typename Traits::output_t * const MPT_RESTRICT outBuffer)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &, typename Traits::output_t * const MPT_RESTRICT outBuffer)
 	{
 		typename Traits::output_t vol = outSample[0] * base_t::lVol;
 		for(int i = 0; i < Traits::numChannelsOut; i++)
@@ -282,7 +282,7 @@
 struct MixMonoNoRamp : public NoRamp<Traits>
 {
 	using base_t = NoRamp<Traits>;
-	MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &, typename Traits::output_t * const MPT_RESTRICT outBuffer)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &, typename Traits::output_t * const MPT_RESTRICT outBuffer)
 	{
 		outBuffer[0] += outSample[0] * base_t::lVol;
 		outBuffer[1] += outSample[0] * base_t::rVol;
@@ -293,7 +293,7 @@
 template<class Traits>
 struct MixMonoRamp : public Ramp
 {
-	MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &chn, typename Traits::output_t * const MPT_RESTRICT outBuffer)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &chn, typename Traits::output_t * const MPT_RESTRICT outBuffer)
 	{
 		lRamp += chn.leftRamp;
 		rRamp += chn.rightRamp;
@@ -307,7 +307,7 @@
 struct MixStereoNoRamp : public NoRamp<Traits>
 {
 	using base_t = NoRamp<Traits>;
-	MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &, typename Traits::output_t * const MPT_RESTRICT outBuffer)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &, typename Traits::output_t * const MPT_RESTRICT outBuffer)
 	{
 		outBuffer[0] += outSample[0] * base_t::lVol;
 		outBuffer[1] += outSample[1] * base_t::rVol;
@@ -318,7 +318,7 @@
 template<class Traits>
 struct MixStereoRamp : public Ramp
 {
-	MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &chn, typename Traits::output_t * const MPT_RESTRICT outBuffer)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &chn, typename Traits::output_t * const MPT_RESTRICT outBuffer)
 	{
 		lRamp += chn.leftRamp;
 		rRamp += chn.rightRamp;
@@ -335,9 +335,9 @@
 template<class Traits>
 struct NoFilter
 {
-	MPT_FORCEINLINE NoFilter(const ModChannel &) { }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE NoFilter(const ModChannel &) { }
 
-	MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &, const ModChannel &) { }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (const typename Traits::outbuf_t &, const ModChannel &) { }
 };
 
 
@@ -349,7 +349,7 @@
 	// Filter history
 	typename Traits::output_t fy[Traits::numChannelsIn][2];
 
-	MPT_FORCEINLINE ResonantFilter(ModChannel &chn)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE ResonantFilter(ModChannel &chn)
 		: channel{chn}
 	{
 		for(int i = 0; i < Traits::numChannelsIn; i++)
@@ -359,7 +359,7 @@
 		}
 	}
 
-	MPT_FORCEINLINE ~ResonantFilter()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE ~ResonantFilter()
 	{
 		for(int i = 0; i < Traits::numChannelsIn; i++)
 		{
@@ -373,7 +373,7 @@
 	// Filter values are clipped to double the input range
 #define ClipFilter(x) Clamp<typename Traits::output_t, typename Traits::output_t>(x, int16_min * 2 * MIXING_FILTER_PREAMP, int16_max * 2 * MIXING_FILTER_PREAMP)
 
-	MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const ModChannel &chn)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (typename Traits::outbuf_t &outSample, const ModChannel &chn)
 	{
 		static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
 
Index: soundlib/Load_symmod.cpp
===================================================================
--- soundlib/Load_symmod.cpp	(revision 23566)
+++ soundlib/Load_symmod.cpp	(working copy)
@@ -328,7 +328,7 @@
 		return true;
 	}
 
-	static MPT_FORCEINLINE double TranswaveInterpolate(const ModSample &smp, double offset)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static double TranswaveInterpolate(const ModSample &smp, double offset)
 	{
 		if(!smp.HasSampleData())
 			return 0.0;
Index: soundlib/Load_xm.cpp
===================================================================
--- soundlib/Load_xm.cpp	(revision 23566)
+++ soundlib/Load_xm.cpp	(working copy)
@@ -1138,7 +1138,7 @@
 // work-around massively confused GCC 13/14 optimizer:
 // /usr/include/c++/13/bits/stl_algobase.h:437:30: warning: 'void* __builtin_memcpy(void*, const void*, long unsigned int)' writing between 3 and 9223372036854775806 bytes into a region of size 0 overflows the destination [-Wstringop-overflow=]
 template <typename Tcont2, typename Tcont1>
-static MPT_NOINLINE Tcont1 & gcc_append(Tcont1 & cont1, const Tcont2 & cont2) {
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static Tcont1 & gcc_append(Tcont1 & cont1, const Tcont2 & cont2) {
 	cont1.insert(cont1.end(), cont2.begin(), cont2.end());
 	return cont1;
 }
Index: soundlib/MIDIMacros.h
===================================================================
--- soundlib/MIDIMacros.h	(revision 23566)
+++ soundlib/MIDIMacros.h	(working copy)
@@ -120,12 +120,12 @@
 			return {m_data.data(), Length()};
 		}
 
-		MPT_CONSTEXPR20_FUN size_t Length() const noexcept
+		MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN size_t Length() const noexcept
 		{
 			return static_cast<size_t>(std::distance(m_data.begin(), std::find(m_data.begin(), m_data.end(), '\0')));
 		}
 
-		MPT_CONSTEXPR20_FUN void Clear() noexcept
+		MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN void Clear() noexcept
 		{
 			m_data.fill('\0');
 		}
Index: soundlib/MixerInterface.h
===================================================================
--- soundlib/MixerInterface.h	(revision 23566)
+++ soundlib/MixerInterface.h	(working copy)
@@ -31,7 +31,7 @@
 	using input_t = in;                                 // Input buffer sample type
 	using outbuf_t = out[channelsOut];                  // Output buffer sampling point type
 	// To perform sample conversion, add a function with the following signature to your derived classes:
-	// static MPT_CONSTEXPRINLINE output_t Convert(const input_t x)
+	// MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static output_t Convert(const input_t x)
 };
 
 
@@ -43,7 +43,7 @@
 {
 	ModChannel &channel;
 
-	MPT_FORCEINLINE NoInterpolation(ModChannel &c, const CResampler &, unsigned int)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE NoInterpolation(ModChannel &c, const CResampler &, unsigned int)
 		: channel{c}
 	{
 		// Adding 0.5 to the sample position before the interpolation loop starts
@@ -51,12 +51,12 @@
 		// This gives us more consistent behaviour between forward and reverse playing of a sample.
 		c.position += SamplePosition::Ratio(1, 2);
 	}
-	MPT_FORCEINLINE ~NoInterpolation()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE ~NoInterpolation()
 	{
 		channel.position -= SamplePosition::Ratio(1, 2);
 	}
 
-	MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const int32)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const int32)
 	{
 		static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
 
Index: soundlib/mod_specifications.h
===================================================================
--- soundlib/mod_specifications.h	(revision 23566)
+++ soundlib/mod_specifications.h	(working copy)
@@ -83,8 +83,8 @@
 	bool hasFractionalTempo;         // Are fractional tempos allowed?
 	const char *commands;            // An array holding all commands this format supports; commands that are not supported are marked with "?"
 	const char *volcommands;         // Ditto, but for volume column
-	MPT_CONSTEXPRINLINE TEMPO GetTempoMin() const { return TEMPO(tempoMinInt, 0); }
-	MPT_CONSTEXPRINLINE TEMPO GetTempoMax() const { return TEMPO(tempoMaxInt, 0); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr TEMPO GetTempoMin() const { return TEMPO(tempoMinInt, 0); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr TEMPO GetTempoMax() const { return TEMPO(tempoMaxInt, 0); }
 };
 
 
Index: soundlib/modcommand.h
===================================================================
--- soundlib/modcommand.h	(revision 23566)
+++ soundlib/modcommand.h	(working copy)
@@ -159,12 +159,12 @@
 	}
 	bool operator!=(const ModCommand& mc) const { return !(*this == mc); }
 
-	MPT_FORCEINLINE void SetVolumeCommand(const VolumeCommand c, const VOL v) { volcmd = c; vol = v; }
-	MPT_FORCEINLINE void SetVolumeCommand(const std::pair<VolumeCommand, VOL> cmd) { volcmd = cmd.first; vol = cmd.second; }
-	MPT_FORCEINLINE void SetVolumeCommand(const ModCommand &other) { volcmd = other.volcmd; vol = other. vol; }
-	MPT_FORCEINLINE void SetEffectCommand(const EffectCommand c, const PARAM p) { command = c; param = p; }
-	MPT_FORCEINLINE void SetEffectCommand(const std::pair<EffectCommand, PARAM> cmd) { command = cmd.first; param = cmd.second; }
-	MPT_FORCEINLINE void SetEffectCommand(const ModCommand &other) { command = other.command; param = other.param; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void SetVolumeCommand(const VolumeCommand c, const VOL v) { volcmd = c; vol = v; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void SetVolumeCommand(const std::pair<VolumeCommand, VOL> cmd) { volcmd = cmd.first; vol = cmd.second; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void SetVolumeCommand(const ModCommand &other) { volcmd = other.volcmd; vol = other. vol; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void SetEffectCommand(const EffectCommand c, const PARAM p) { command = c; param = p; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void SetEffectCommand(const std::pair<EffectCommand, PARAM> cmd) { command = cmd.first; param = cmd.second; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void SetEffectCommand(const ModCommand &other) { command = other.command; param = other.param; }
 
 	void Set(NOTE n, INSTR ins, uint16 volcol, uint16 effectcol) { note = n; instr = ins; SetValueVolCol(volcol); SetValueEffectCol(effectcol); }
 
Index: soundlib/ModInstrument.h
===================================================================
--- soundlib/ModInstrument.h	(revision 23566)
+++ soundlib/ModInstrument.h	(working copy)
@@ -128,7 +128,7 @@
 	// WHEN adding new members here, ALSO update InstrumentExtensions.cpp
 	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-	MPT_CONSTEXPR20_CONTAINER_FUN explicit ModInstrument(SAMPLEINDEX sample = 0)
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_CONTAINER_FUN explicit ModInstrument(SAMPLEINDEX sample = 0)
 		: NoteMap{mpt::generate_array<uint8, 128>([](std::size_t i){ return static_cast<uint8>(NOTE_MIN + i); })}
 		, Keyboard{mpt::init_array<SAMPLEINDEX, 128>(sample)}
 	{
@@ -136,13 +136,13 @@
 	}
 
 	// Assign all notes to a given sample.
-	MPT_CONSTEXPR20_ALGORITHM_FUN void AssignSample(SAMPLEINDEX sample)
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_ALGORITHM_FUN void AssignSample(SAMPLEINDEX sample)
 	{
 		Keyboard.fill(sample);
 	}
 
 	// Reset note mapping (i.e. every note is mapped to itself)
-	MPT_CONSTEXPR20_ALGORITHM_FUN void ResetNoteMap()
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_ALGORITHM_FUN void ResetNoteMap()
 	{
 		std::iota(NoteMap.begin(), NoteMap.end(), static_cast<uint8>(NOTE_MIN));
 	}
@@ -154,23 +154,23 @@
 	// Transpose entire note mapping by given number of semitones
 	void Transpose(int8 amount);
 
-	MPT_CONSTEXPRINLINE bool IsCutoffEnabled() const { return (nIFC & 0x80) != 0; }
-	MPT_CONSTEXPRINLINE bool IsResonanceEnabled() const { return (nIFR & 0x80) != 0; }
-	MPT_CONSTEXPRINLINE uint8 GetCutoff() const { return (nIFC & 0x7F); }
-	MPT_CONSTEXPRINLINE uint8 GetResonance() const { return (nIFR & 0x7F); }
-	MPT_CONSTEXPRINLINE void SetCutoff(uint8 cutoff, bool enable) { nIFC = std::min(cutoff, uint8(0x7F)) | (enable ? 0x80 : 0x00); }
-	MPT_CONSTEXPRINLINE void SetResonance(uint8 resonance, bool enable) { nIFR = std::min(resonance, uint8(0x7F)) | (enable ? 0x80 : 0x00); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool IsCutoffEnabled() const { return (nIFC & 0x80) != 0; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool IsResonanceEnabled() const { return (nIFR & 0x80) != 0; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint8 GetCutoff() const { return (nIFC & 0x7F); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint8 GetResonance() const { return (nIFR & 0x7F); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr void SetCutoff(uint8 cutoff, bool enable) { nIFC = std::min(cutoff, uint8(0x7F)) | (enable ? 0x80 : 0x00); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr void SetResonance(uint8 resonance, bool enable) { nIFR = std::min(resonance, uint8(0x7F)) | (enable ? 0x80 : 0x00); }
 
-	MPT_CONSTEXPRINLINE bool HasValidMIDIChannel() const { return (nMidiChannel >= 1 && nMidiChannel <= 17); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool HasValidMIDIChannel() const { return (nMidiChannel >= 1 && nMidiChannel <= 17); }
 	uint8 GetMIDIChannel(const ModChannel &channel, CHANNELINDEX chn) const;
 
-	MPT_CONSTEXPRINLINE void SetTuning(CTuning *pT)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr void SetTuning(CTuning *pT)
 	{
 		pTuning = pT;
 	}
 
 	// Get a reference to a specific envelope of this instrument
-	MPT_CONSTEXPRINLINE const InstrumentEnvelope &GetEnvelope(EnvelopeType envType) const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr const InstrumentEnvelope &GetEnvelope(EnvelopeType envType) const
 	{
 		switch(envType)
 		{
Index: soundlib/ModSample.h
===================================================================
--- soundlib/ModSample.h	(revision 23566)
+++ soundlib/ModSample.h	(working copy)
@@ -64,46 +64,46 @@
 		return pData.pSample != nullptr && nLength != 0;
 	}
 
-	MPT_FORCEINLINE const void *samplev() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE const void *samplev() const noexcept
 	{
 		return pData.pSample;
 	}
-	MPT_FORCEINLINE void *samplev() noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void *samplev() noexcept
 	{
 		return pData.pSample;
 	}
-	MPT_FORCEINLINE const std::byte *sampleb() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE const std::byte *sampleb() const noexcept
 	{
 		return mpt::void_cast<const std::byte*>(pData.pSample);
 	}
-	MPT_FORCEINLINE std::byte *sampleb() noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::byte *sampleb() noexcept
 	{
 		return mpt::void_cast<std::byte*>(pData.pSample);
 	}
-	MPT_FORCEINLINE const int8 *sample8() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE const int8 *sample8() const noexcept
 	{
 		MPT_ASSERT(GetElementarySampleSize() == sizeof(int8));
 		return pData.pSample8;
 	}
-	MPT_FORCEINLINE int8 *sample8() noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE int8 *sample8() noexcept
 	{
 		MPT_ASSERT(GetElementarySampleSize() == sizeof(int8));
 		return pData.pSample8;
 	}
-	MPT_FORCEINLINE const int16 *sample16() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE const int16 *sample16() const noexcept
 	{
 		MPT_ASSERT(GetElementarySampleSize() == sizeof(int16));
 		return pData.pSample16;
 	}
-	MPT_FORCEINLINE int16 *sample16() noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE int16 *sample16() noexcept
 	{
 		MPT_ASSERT(GetElementarySampleSize() == sizeof(int16));
 		return pData.pSample16;
 	}
 	template <typename Tsample>
-	MPT_FORCEINLINE const Tsample *sample() const noexcept = delete;
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE const Tsample *sample() const noexcept = delete;
 	template <typename Tsample>
-	MPT_FORCEINLINE Tsample *sample() noexcept = delete;
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE Tsample *sample() noexcept = delete;
 
 	// Return the size of one (elementary) sample in bytes.
 	uint8 GetElementarySampleSize() const noexcept { return (uFlags & CHN_16BIT) ? 2 : 1; }
@@ -188,25 +188,25 @@
 };
 
 template <>
-MPT_FORCEINLINE const int8 *ModSample::sample<int8>() const noexcept
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE const int8 *ModSample::sample<int8>() const noexcept
 {
 	MPT_ASSERT(GetElementarySampleSize() == sizeof(int8));
 	return pData.pSample8;
 }
 template <>
-MPT_FORCEINLINE int8 *ModSample::sample<int8>() noexcept
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE int8 *ModSample::sample<int8>() noexcept
 {
 	MPT_ASSERT(GetElementarySampleSize() == sizeof(int8));
 	return pData.pSample8;
 }
 template <>
-MPT_FORCEINLINE const int16 *ModSample::sample<int16>() const noexcept
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE const int16 *ModSample::sample<int16>() const noexcept
 {
 	MPT_ASSERT(GetElementarySampleSize() == sizeof(int16));
 	return pData.pSample16;
 }
 template <>
-MPT_FORCEINLINE int16 *ModSample::sample<int16>() noexcept
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE int16 *ModSample::sample<int16>() noexcept
 {
 	MPT_ASSERT(GetElementarySampleSize() == sizeof(int16));
 	return pData.pSample16;
Index: soundlib/Paula.cpp
===================================================================
--- soundlib/Paula.cpp	(revision 23566)
+++ soundlib/Paula.cpp	(working copy)
@@ -25,7 +25,7 @@
 namespace
 {
 
-MPT_NOINLINE std::vector<double> KaiserFIR(int numTaps, double cutoff, double beta)
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE std::vector<double> KaiserFIR(int numTaps, double cutoff, double beta)
 {
 	const double izeroBeta = Izero(beta);
 	const double kPi = 4.0 * std::atan(1.0) * cutoff;
@@ -52,7 +52,7 @@
 }
 
 
-MPT_NOINLINE void FIR_MinPhase(std::vector<double> &table, const TinyFFT &fft)
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void FIR_MinPhase(std::vector<double> &table, const TinyFFT &fft)
 {
 	std::vector<std::complex<double>> cepstrum(fft.Size());
 	MPT_ASSERT(cepstrum.size() >= table.size());
@@ -166,7 +166,7 @@
 }
 
 
-MPT_NOINLINE void Integrate(std::vector<double> &table)
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void Integrate(std::vector<double> &table)
 {
 	const double total = std::accumulate(table.begin(), table.end(), 0.0);
 	double startVal = -total;
@@ -179,7 +179,7 @@
 }
 
 
-MPT_NOINLINE void Quantize(const std::vector<double> &in, Paula::BlepArray &quantized)
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void Quantize(const std::vector<double> &in, Paula::BlepArray &quantized)
 {
 	MPT_ASSERT(in.size() == Paula::BLEP_SIZE);
 	constexpr int fact = 1 << Paula::BLEP_SCALE;
Index: soundlib/plugins/dmo/I3DL2Reverb.cpp
===================================================================
--- soundlib/plugins/dmo/I3DL2Reverb.cpp	(revision 23566)
+++ soundlib/plugins/dmo/I3DL2Reverb.cpp	(working copy)
@@ -51,7 +51,7 @@
 }
 
 
-MPT_FORCEINLINE void I3DL2Reverb::DelayLine::Set(float value)
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void I3DL2Reverb::DelayLine::Set(float value)
 {
 	at(m_position) = value;
 }
@@ -66,7 +66,7 @@
 }
 
 
-MPT_FORCEINLINE float I3DL2Reverb::DelayLine::Get() const
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE float I3DL2Reverb::DelayLine::Get() const
 {
 	return at(m_delayPosition);
 }
Index: soundlib/SampleFormatMP3.cpp
===================================================================
--- soundlib/SampleFormatMP3.cpp	(revision 23566)
+++ soundlib/SampleFormatMP3.cpp	(working copy)
@@ -223,7 +223,7 @@
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wframe-larger-than"
 #endif // MPT_COMPILER_CLANG
-static MPT_NOINLINE int mp3dec_decode_frame_no_inline(mp3dec_t *dec, const uint8_t *mp3, int mp3_bytes, mp3d_sample_t *pcm, mp3dec_frame_info_t *info)
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static int mp3dec_decode_frame_no_inline(mp3dec_t *dec, const uint8_t *mp3, int mp3_bytes, mp3d_sample_t *pcm, mp3dec_frame_info_t *info)
 {
 	return mp3dec_decode_frame(dec, mp3, mp3_bytes, pcm, info);
 }
Index: soundlib/SampleIO.h
===================================================================
--- soundlib/SampleIO.h	(revision 23566)
+++ soundlib/SampleIO.h	(working copy)
@@ -131,7 +131,7 @@
 	}
 
 	// Return 0 in case of variable-length encoded samples.
-	MPT_CONSTEXPRINLINE uint8 GetEncodedBitsPerSample() const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint8 GetEncodedBitsPerSample() const
 	{
 		switch(GetEncoding())
 		{
@@ -168,7 +168,7 @@
 	}
 
 	// Return the static header size additional to the raw encoded sample data.
-	MPT_CONSTEXPRINLINE std::size_t GetEncodedHeaderSize() const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr std::size_t GetEncodedHeaderSize() const
 	{
 		switch(GetEncoding())
 		{
@@ -180,13 +180,13 @@
 	}
 
 	// Returns true if the encoded size cannot be calculated apriori from the encoding format and the sample length.
-	MPT_CONSTEXPRINLINE bool IsVariableLengthEncoded() const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool IsVariableLengthEncoded() const
 	{
 		return GetEncodedBitsPerSample() == 0;
 	}
 
 	// Returns true if the decoder for a given format uses FileReader interface and thus do not need to call GetPinnedView()
-	MPT_CONSTEXPRINLINE bool UsesFileReaderForDecoding() const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool UsesFileReaderForDecoding() const
 	{
 		switch(GetEncoding())
 		{
Index: soundlib/SampleNormalize.h
===================================================================
--- soundlib/SampleNormalize.h	(revision 23566)
+++ soundlib/SampleNormalize.h	(working copy)
@@ -31,9 +31,9 @@
 	using output_t = int32;
 	using peak_t = uint32;
 	uint32 maxVal;
-	MPT_FORCEINLINE Normalize()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE Normalize()
 		: maxVal(0) {}
-	MPT_FORCEINLINE void FindMax(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void FindMax(input_t val)
 	{
 		if(val < 0)
 		{
@@ -49,15 +49,15 @@
 			maxVal = static_cast<uint32>(val);
 		}
 	}
-	MPT_FORCEINLINE bool IsSilent() const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool IsSilent() const
 	{
 		return maxVal == 0;
 	}
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return Util::muldivrfloor(val, static_cast<uint32>(1) << 31, maxVal);
 	}
-	MPT_FORCEINLINE peak_t GetSrcPeak() const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE peak_t GetSrcPeak() const
 	{
 		return maxVal;
 	}
@@ -71,9 +71,9 @@
 	using peak_t = somefloat32;
 	float maxVal;
 	float maxValInv;
-	MPT_FORCEINLINE Normalize()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE Normalize()
 		: maxVal(0.0f), maxValInv(1.0f) {}
-	MPT_FORCEINLINE void FindMax(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void FindMax(input_t val)
 	{
 		float absval = std::fabs(val);
 		if(absval > maxVal)
@@ -81,7 +81,7 @@
 			maxVal = absval;
 		}
 	}
-	MPT_FORCEINLINE bool IsSilent()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool IsSilent()
 	{
 		if(maxVal == 0.0f)
 		{
@@ -93,11 +93,11 @@
 			return false;
 		}
 	}
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return val * maxValInv;
 	}
-	MPT_FORCEINLINE peak_t GetSrcPeak() const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE peak_t GetSrcPeak() const
 	{
 		return maxVal;
 	}
@@ -111,9 +111,9 @@
 	using peak_t = somefloat64;
 	double maxVal;
 	double maxValInv;
-	MPT_FORCEINLINE Normalize()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE Normalize()
 		: maxVal(0.0), maxValInv(1.0) {}
-	MPT_FORCEINLINE void FindMax(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void FindMax(input_t val)
 	{
 		double absval = std::fabs(val);
 		if(absval > maxVal)
@@ -121,7 +121,7 @@
 			maxVal = absval;
 		}
 	}
-	MPT_FORCEINLINE bool IsSilent()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool IsSilent()
 	{
 		if(maxVal == 0.0)
 		{
@@ -133,11 +133,11 @@
 			return false;
 		}
 	}
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return val * maxValInv;
 	}
-	MPT_FORCEINLINE peak_t GetSrcPeak() const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE peak_t GetSrcPeak() const
 	{
 		return maxVal;
 	}
@@ -159,23 +159,23 @@
 	Func1 func1;
 	Normalize<normalize_t> normalize;
 	Func2 func2;
-	MPT_FORCEINLINE void FindMax(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void FindMax(const input_t *inBuf)
 	{
 		normalize.FindMax(func1(inBuf));
 	}
-	MPT_FORCEINLINE bool IsSilent()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool IsSilent()
 	{
 		return normalize.IsSilent();
 	}
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		return func2(normalize(func1(inBuf)));
 	}
-	MPT_FORCEINLINE peak_t GetSrcPeak() const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE peak_t GetSrcPeak() const
 	{
 		return normalize.GetSrcPeak();
 	}
-	MPT_FORCEINLINE NormalizationChain(Func2 f2 = Func2(), Func1 f1 = Func1())
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE NormalizationChain(Func2 f2 = Func2(), Func1 f1 = Func1())
 		: func1(f1)
 		, func2(f2)
 	{
Index: soundlib/Snd_defs.h
===================================================================
--- soundlib/Snd_defs.h	(revision 23566)
+++ soundlib/Snd_defs.h	(working copy)
@@ -651,41 +651,41 @@
 public:
 	static constexpr uint32 fractMax = 0xFFFFFFFFu;
 
-	MPT_CONSTEXPRINLINE SamplePosition() { }
-	MPT_CONSTEXPRINLINE explicit SamplePosition(value_t pos) : v(pos) { }
-	MPT_CONSTEXPRINLINE SamplePosition(int32 intPart, uint32 fractPart) : v((static_cast<value_t>(intPart) * (1ll << 32)) | fractPart) { }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr SamplePosition() { }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr explicit SamplePosition(value_t pos) : v(pos) { }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr SamplePosition(int32 intPart, uint32 fractPart) : v((static_cast<value_t>(intPart) * (1ll << 32)) | fractPart) { }
 	static SamplePosition Ratio(uint32 dividend, uint32 divisor) { return SamplePosition((static_cast<int64>(dividend) << 32) / divisor); }
 	static SamplePosition FromDouble(double pos) { return SamplePosition(static_cast<value_t>(pos * 4294967296.0)); }
 	double ToDouble() const { return static_cast<double>(v) / 4294967296.0; }
 
 	// Set integer and fractional part
-	MPT_CONSTEXPRINLINE SamplePosition &Set(int32 intPart, uint32 fractPart = 0) { v = (static_cast<int64>(intPart) << 32) | fractPart; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr SamplePosition &Set(int32 intPart, uint32 fractPart = 0) { v = (static_cast<int64>(intPart) << 32) | fractPart; return *this; }
 	// Set integer part, keep fractional part
-	MPT_CONSTEXPRINLINE SamplePosition &SetInt(int32 intPart) { v = (static_cast<value_t>(intPart) << 32) | GetFract(); return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr SamplePosition &SetInt(int32 intPart) { v = (static_cast<value_t>(intPart) << 32) | GetFract(); return *this; }
 	// Get integer part (as sample length / position)
-	MPT_CONSTEXPRINLINE SmpLength GetUInt() const { return static_cast<SmpLength>(static_cast<unsigned_value_t>(v) >> 32); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr SmpLength GetUInt() const { return static_cast<SmpLength>(static_cast<unsigned_value_t>(v) >> 32); }
 	// Get integer part
-	MPT_CONSTEXPRINLINE int32 GetInt() const { return static_cast<int32>(static_cast<unsigned_value_t>(v) >> 32); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr int32 GetInt() const { return static_cast<int32>(static_cast<unsigned_value_t>(v) >> 32); }
 	// Get fractional part
-	MPT_CONSTEXPRINLINE uint32 GetFract() const { return static_cast<uint32>(v); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint32 GetFract() const { return static_cast<uint32>(v); }
 	// Get the inverted fractional part
-	MPT_CONSTEXPRINLINE SamplePosition GetInvertedFract() const { return SamplePosition(0x100000000ll - GetFract()); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr SamplePosition GetInvertedFract() const { return SamplePosition(0x100000000ll - GetFract()); }
 	// Get the raw fixed-point value
-	MPT_CONSTEXPRINLINE int64 GetRaw() const { return v; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr int64 GetRaw() const { return v; }
 	// Negate the current value
-	MPT_CONSTEXPRINLINE SamplePosition &Negate() { v = -v; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr SamplePosition &Negate() { v = -v; return *this; }
 	// Multiply and divide by given integer scalars
-	MPT_CONSTEXPRINLINE SamplePosition &MulDiv(uint32 mul, uint32 div) { v = (v * mul) / div; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr SamplePosition &MulDiv(uint32 mul, uint32 div) { v = (v * mul) / div; return *this; }
 	// Removes the integer part, only keeping fractions
-	MPT_CONSTEXPRINLINE SamplePosition &RemoveInt() { v &= fractMax; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr SamplePosition &RemoveInt() { v &= fractMax; return *this; }
 	// Check if value is 1.0
-	MPT_CONSTEXPRINLINE bool IsUnity() const { return v == 0x100000000ll; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool IsUnity() const { return v == 0x100000000ll; }
 	// Check if value is 0
-	MPT_CONSTEXPRINLINE bool IsZero() const { return v == 0; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool IsZero() const { return v == 0; }
 	// Check if value is > 0
-	MPT_CONSTEXPRINLINE bool IsPositive() const { return v > 0; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool IsPositive() const { return v > 0; }
 	// Check if value is < 0
-	MPT_CONSTEXPRINLINE bool IsNegative() const { return v < 0; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool IsNegative() const { return v < 0; }
 
 	// Addition / subtraction of another fixed-point number
 	SamplePosition operator+ (const SamplePosition &other) const { return SamplePosition(v + other.v); }
@@ -704,12 +704,12 @@
 	// Division by scalar; returns fractional point number
 	SamplePosition operator/ (int div) const { return SamplePosition(v / div); }
 
-	MPT_CONSTEXPRINLINE bool operator==(const SamplePosition &other) const { return v == other.v; }
-	MPT_CONSTEXPRINLINE bool operator!=(const SamplePosition &other) const { return v != other.v; }
-	MPT_CONSTEXPRINLINE bool operator<=(const SamplePosition &other) const { return v <= other.v; }
-	MPT_CONSTEXPRINLINE bool operator>=(const SamplePosition &other) const { return v >= other.v; }
-	MPT_CONSTEXPRINLINE bool operator<(const SamplePosition &other) const { return v < other.v; }
-	MPT_CONSTEXPRINLINE bool operator>(const SamplePosition &other) const { return v > other.v; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator==(const SamplePosition &other) const { return v == other.v; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator!=(const SamplePosition &other) const { return v != other.v; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator<=(const SamplePosition &other) const { return v <= other.v; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator>=(const SamplePosition &other) const { return v >= other.v; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator<(const SamplePosition &other) const { return v < other.v; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator>(const SamplePosition &other) const { return v > other.v; }
 };
 
 
@@ -723,41 +723,41 @@
 {
 protected:
 	T v;
-	MPT_CONSTEXPRINLINE FPInt(T rawValue) : v(rawValue) { }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FPInt(T rawValue) : v(rawValue) { }
 
 public:
 	enum : T { fractFact = static_cast<T>(FFact) };
 	using store_t = T;
 
-	MPT_CONSTEXPRINLINE FPInt() : v(0) { }
-	MPT_CONSTEXPRINLINE FPInt(T intPart, T fractPart) : v((intPart * fractFact) + (fractPart % fractFact)) { }
-	explicit MPT_CONSTEXPRINLINE FPInt(float f) : v(mpt::saturate_round<T>(f * float(fractFact))) { }
-	explicit MPT_CONSTEXPRINLINE FPInt(double f) : v(mpt::saturate_round<T>(f * double(fractFact))) { }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FPInt() : v(0) { }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FPInt(T intPart, T fractPart) : v((intPart * fractFact) + (fractPart % fractFact)) { }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr explicit FPInt(float f) : v(mpt::saturate_round<T>(f * float(fractFact))) { }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr explicit FPInt(double f) : v(mpt::saturate_round<T>(f * double(fractFact))) { }
 
 	// Set integer and fractional part
-	MPT_CONSTEXPRINLINE FPInt<fractFact, T> &Set(T intPart, T fractPart = 0) { v = (intPart * fractFact) + (fractPart % fractFact); return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FPInt<fractFact, T> &Set(T intPart, T fractPart = 0) { v = (intPart * fractFact) + (fractPart % fractFact); return *this; }
 	// Set raw internal representation directly
-	MPT_CONSTEXPRINLINE FPInt<fractFact, T> &SetRaw(T value) { v = value; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FPInt<fractFact, T> &SetRaw(T value) { v = value; return *this; }
 	// Retrieve the integer part of the stored value
-	MPT_CONSTEXPRINLINE T GetInt() const { return v / fractFact; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr T GetInt() const { return v / fractFact; }
 	// Retrieve the fractional part of the stored value
-	MPT_CONSTEXPRINLINE T GetFract() const { return v % fractFact; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr T GetFract() const { return v % fractFact; }
 	// Retrieve the raw internal representation of the stored value
-	MPT_CONSTEXPRINLINE T GetRaw() const { return v; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr T GetRaw() const { return v; }
 	// Formats the stored value as a floating-point value
-	MPT_CONSTEXPRINLINE double ToDouble() const { return v / double(fractFact); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr double ToDouble() const { return v / double(fractFact); }
 
-	MPT_CONSTEXPRINLINE friend FPInt<fractFact, T> operator+ (const FPInt<fractFact, T> &a, const FPInt<fractFact, T> &b) noexcept { return FPInt<fractFact, T>(a.v + b.v); }
-	MPT_CONSTEXPRINLINE friend FPInt<fractFact, T> operator- (const FPInt<fractFact, T> &a, const FPInt<fractFact, T> &b) noexcept { return FPInt<fractFact, T>(a.v - b.v); }
-	MPT_CONSTEXPRINLINE FPInt<fractFact, T> operator+= (const FPInt<fractFact, T> &other) noexcept { v += other.v; return *this; }
-	MPT_CONSTEXPRINLINE FPInt<fractFact, T> operator-= (const FPInt<fractFact, T> &other) noexcept { v -= other.v; return *this; }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr FPInt<fractFact, T> operator+ (const FPInt<fractFact, T> &a, const FPInt<fractFact, T> &b) noexcept { return FPInt<fractFact, T>(a.v + b.v); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr FPInt<fractFact, T> operator- (const FPInt<fractFact, T> &a, const FPInt<fractFact, T> &b) noexcept { return FPInt<fractFact, T>(a.v - b.v); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FPInt<fractFact, T> operator+= (const FPInt<fractFact, T> &other) noexcept { v += other.v; return *this; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FPInt<fractFact, T> operator-= (const FPInt<fractFact, T> &other) noexcept { v -= other.v; return *this; }
 
-	MPT_CONSTEXPRINLINE friend bool operator== (const FPInt<fractFact, T> &a, const FPInt<fractFact, T> &b) noexcept { return a.v == b.v; }
-	MPT_CONSTEXPRINLINE friend bool operator!= (const FPInt<fractFact, T> &a, const FPInt<fractFact, T> &b) noexcept { return a.v != b.v; }
-	MPT_CONSTEXPRINLINE friend bool operator<= (const FPInt<fractFact, T> &a, const FPInt<fractFact, T> &b) noexcept { return a.v <= b.v; }
-	MPT_CONSTEXPRINLINE friend bool operator>= (const FPInt<fractFact, T> &a, const FPInt<fractFact, T> &b) noexcept { return a.v >= b.v; }
-	MPT_CONSTEXPRINLINE friend bool operator< (const FPInt<fractFact, T> &a, const FPInt<fractFact, T> &b) noexcept { return a.v < b.v; }
-	MPT_CONSTEXPRINLINE friend bool operator> (const FPInt<fractFact, T> &a, const FPInt<fractFact, T> &b) noexcept { return a.v > b.v; }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator== (const FPInt<fractFact, T> &a, const FPInt<fractFact, T> &b) noexcept { return a.v == b.v; }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!= (const FPInt<fractFact, T> &a, const FPInt<fractFact, T> &b) noexcept { return a.v != b.v; }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator<= (const FPInt<fractFact, T> &a, const FPInt<fractFact, T> &b) noexcept { return a.v <= b.v; }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator>= (const FPInt<fractFact, T> &a, const FPInt<fractFact, T> &b) noexcept { return a.v >= b.v; }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator< (const FPInt<fractFact, T> &a, const FPInt<fractFact, T> &b) noexcept { return a.v < b.v; }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator> (const FPInt<fractFact, T> &a, const FPInt<fractFact, T> &b) noexcept { return a.v > b.v; }
 };
 
 using TEMPO = FPInt<10000, uint32>;
Index: soundlib/Sndfile.h
===================================================================
--- soundlib/Sndfile.h	(revision 23566)
+++ soundlib/Sndfile.h	(working copy)
@@ -715,7 +715,7 @@
 	constexpr SAMPLEINDEX GetNumSamples() const noexcept { return m_nSamples; }
 	constexpr PATTERNINDEX GetCurrentPattern() const noexcept { return m_PlayState.m_nPattern; }
 	constexpr ORDERINDEX GetCurrentOrder() const noexcept { return m_PlayState.m_nCurrentOrder; }
-	MPT_FORCEINLINE CHANNELINDEX GetNumChannels() const noexcept { return static_cast<CHANNELINDEX>(ChnSettings.size()); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE CHANNELINDEX GetNumChannels() const noexcept { return static_cast<CHANNELINDEX>(ChnSettings.size()); }
 
 	constexpr bool CanAddMoreSamples(SAMPLEINDEX amount = 1) const noexcept { return (amount < MAX_SAMPLES) && m_nSamples < (MAX_SAMPLES - amount); }
 	constexpr bool CanAddMoreInstruments(INSTRUMENTINDEX amount = 1) const noexcept { return (amount < MAX_INSTRUMENTS) && m_nInstruments < (MAX_INSTRUMENTS - amount); }
@@ -1307,8 +1307,8 @@
 
 #define FADESONGDELAY		100
 
-MPT_CONSTEXPRINLINE int8 MOD2XMFineTune(int v) { return static_cast<int8>(static_cast<uint8>(v) << 4); }
-MPT_CONSTEXPRINLINE int8 XM2MODFineTune(int v) { return static_cast<int8>(static_cast<uint8>(v) >> 4); }
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr int8 MOD2XMFineTune(int v) { return static_cast<int8>(static_cast<uint8>(v) << 4); }
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr int8 XM2MODFineTune(int v) { return static_cast<int8>(static_cast<uint8>(v) >> 4); }
 
 
 OPENMPT_NAMESPACE_END
Index: soundlib/Sndmix.cpp
===================================================================
--- soundlib/Sndmix.cpp	(revision 23566)
+++ soundlib/Sndmix.cpp	(working copy)
@@ -2750,7 +2750,7 @@
 
 
 template<int channels>
-MPT_FORCEINLINE void ApplyGlobalVolumeWithRamping(int32 *SoundBuffer, int32 *RearBuffer, uint32 lCount, int32 m_nGlobalVolume, int32 step, int32 &m_nSamplesToGlobalVolRampDest, int32 &m_lHighResRampingGlobalVolume)
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void ApplyGlobalVolumeWithRamping(int32 *SoundBuffer, int32 *RearBuffer, uint32 lCount, int32 m_nGlobalVolume, int32 step, int32 &m_nSamplesToGlobalVolRampDest, int32 &m_lHighResRampingGlobalVolume)
 {
 	const bool isStereo = (channels >= 2);
 	const bool hasRear = (channels >= 4);
Index: soundlib/tuning.h
===================================================================
--- soundlib/tuning.h	(revision 23566)
+++ soundlib/tuning.h	(working copy)
@@ -54,18 +54,18 @@
 	//Tuning might not be valid for arbitrarily large range,
 	//so this can be used to ask where it is valid. Tells the lowest and highest
 	//note that are valid.
-	MPT_FORCEINLINE NoteRange GetNoteRange() const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE NoteRange GetNoteRange() const
 	{
 		return NoteRange{m_NoteMin, static_cast<NOTEINDEXTYPE>(m_NoteMin + static_cast<NOTEINDEXTYPE>(m_RatioTable.size()) - 1)};
 	}
 
 	// Return true if note is within note range
-	MPT_FORCEINLINE bool IsValidNote(const NOTEINDEXTYPE n) const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool IsValidNote(const NOTEINDEXTYPE n) const
 	{
 		return (GetNoteRange().first <= n && n <= GetNoteRange().last);
 	}
 
-	MPT_FORCEINLINE UNOTEINDEXTYPE GetGroupSize() const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE UNOTEINDEXTYPE GetGroupSize() const
 	{
 		return m_GroupSize;
 	}
@@ -73,7 +73,7 @@
 	RATIOTYPE GetGroupRatio() const {return m_GroupRatio;}
 
 	// To return (fine)stepcount between two consecutive mainsteps.
-	MPT_FORCEINLINE USTEPINDEXTYPE GetFineStepCount() const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE USTEPINDEXTYPE GetFineStepCount() const
 	{
 		return m_FineStepCount;
 	}
@@ -96,7 +96,7 @@
 
 	bool SetRatio(const NOTEINDEXTYPE& s, const RATIOTYPE& r);
 
-	MPT_FORCEINLINE Tuning::Type GetType() const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE Tuning::Type GetType() const
 	{
 		return m_TuningType;
 	}
@@ -216,7 +216,7 @@
 	// GroupPeriodic-specific.
 	// Get the corresponding note in [0, period-1].
 	// For example GetRefNote(-1) is to return note :'groupsize-1'.
-	MPT_FORCEINLINE NOTEINDEXTYPE GetRefNote(NOTEINDEXTYPE note) const
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE NOTEINDEXTYPE GetRefNote(NOTEINDEXTYPE note) const
 	{
 		MPT_ASSERT(GetType() == Type::GROUPGEOMETRIC || GetType() == Type::GEOMETRIC);
 		return static_cast<NOTEINDEXTYPE>(mpt::wrapping_modulo(note, GetGroupSize()));
Index: src/mpt/arch/arch.hpp
===================================================================
--- src/mpt/arch/arch.hpp	(revision 23566)
+++ src/mpt/arch/arch.hpp	(working copy)
@@ -88,31 +88,31 @@
 public:
 	cpu_info() = default;
 public:
-	MPT_CONSTEXPRINLINE bool operator[](feature_flags) const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator[](feature_flags) const noexcept {
 		return true;
 	}
-	MPT_CONSTEXPRINLINE bool has_features(feature_flags) const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool has_features(feature_flags) const noexcept {
 		return true;
 	}
-	MPT_CONSTEXPRINLINE feature_flags get_features() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr feature_flags get_features() const noexcept {
 		return {};
 	}
-	MPT_CONSTEXPRINLINE bool operator[](mode_flags) const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator[](mode_flags) const noexcept {
 		return true;
 	}
-	MPT_CONSTEXPRINLINE bool enabled_modes(mode_flags) const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool enabled_modes(mode_flags) const noexcept {
 		return true;
 	}
-	MPT_CONSTEXPRINLINE mode_flags get_modes() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr mode_flags get_modes() const noexcept {
 		return {};
 	}
 };
 
-[[nodiscard]] MPT_CONSTEVAL feature_flags assumed_features() noexcept {
+[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL feature_flags assumed_features() noexcept {
 	return {};
 }
 
-[[nodiscard]] MPT_CONSTEVAL mode_flags assumed_modes() noexcept {
+[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL mode_flags assumed_modes() noexcept {
 	return {};
 }
 
@@ -160,27 +160,27 @@
 	const mpt::arch::current::feature_flags Features;
 	const mpt::arch::current::mode_flags Modes;
 public:
-	MPT_CONSTEXPRINLINE flags_cache(const mpt::arch::cpu_info & info) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr flags_cache(const mpt::arch::cpu_info & info) noexcept
 		: Features(info.get_features())
 		, Modes(info.get_modes()) {
 		return;
 	}
-	[[nodiscard]] MPT_CONSTEXPRINLINE bool operator[](mpt::arch::current::feature_flags query_features) const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator[](mpt::arch::current::feature_flags query_features) const noexcept {
 		return ((Features & query_features) == query_features);
 	}
-	[[nodiscard]] MPT_CONSTEXPRINLINE bool has_features(mpt::arch::current::feature_flags query_features) const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool has_features(mpt::arch::current::feature_flags query_features) const noexcept {
 		return ((Features & query_features) == query_features);
 	}
-	[[nodiscard]] MPT_CONSTEXPRINLINE mpt::arch::current::feature_flags get_features() const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr mpt::arch::current::feature_flags get_features() const noexcept {
 		return Features;
 	}
-	[[nodiscard]] MPT_CONSTEXPRINLINE bool operator[](mpt::arch::current::mode_flags query_modes) const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator[](mpt::arch::current::mode_flags query_modes) const noexcept {
 		return ((Modes & query_modes) == query_modes);
 	}
-	[[nodiscard]] MPT_CONSTEXPRINLINE bool has_features(mpt::arch::current::mode_flags query_modes) const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool has_features(mpt::arch::current::mode_flags query_modes) const noexcept {
 		return ((Modes & query_modes) == query_modes);
 	}
-	[[nodiscard]] MPT_CONSTEXPRINLINE mpt::arch::current::mode_flags get_modes() const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr mpt::arch::current::mode_flags get_modes() const noexcept {
 		return Modes;
 	}
 };
Index: src/mpt/arch/x86_amd64.hpp
===================================================================
--- src/mpt/arch/x86_amd64.hpp	(revision 23566)
+++ src/mpt/arch/x86_amd64.hpp	(working copy)
@@ -203,7 +203,7 @@
 
 
 // clang-format off
-[[nodiscard]] MPT_CONSTEVAL feature_flags assumed_features() noexcept {
+[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL feature_flags assumed_features() noexcept {
 	feature_flags flags{};
 #if MPT_ARCH_X86 || MPT_ARCH_AMD64
 	#ifdef MPT_ARCH_X86_I386
@@ -309,7 +309,7 @@
 
 
 // clang-format off
-[[nodiscard]] MPT_CONSTEVAL mode_flags assumed_modes() noexcept {
+[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL mode_flags assumed_modes() noexcept {
 	mode_flags flags{};
 #if MPT_ARCH_X86 || MPT_ARCH_AMD64
 	#ifdef MPT_ARCH_X86_SSE
@@ -363,7 +363,7 @@
 #endif
 	}
 	template <std::size_t M>
-	[[nodiscard]] friend MPT_CONSTEXPR20_FUN auto operator+(fixed_string<N> a, fixed_string<M> b) -> fixed_string<N + M> {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE friend MPT_CONSTEXPR20_FUN auto operator+(fixed_string<N> a, fixed_string<M> b) -> fixed_string<N + M> {
 		fixed_string<N + M> result;
 		std::copy(a.begin(), a.end(), result.data() + 0);
 		std::copy(b.begin(), b.end(), result.data() + N);
@@ -397,47 +397,47 @@
 
 public:
 
-	[[nodiscard]] MPT_CONSTEXPRINLINE bool operator[](feature_flags query_features) const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator[](feature_flags query_features) const noexcept {
 		return ((Features & query_features) == query_features);
 	}
 
-	[[nodiscard]] MPT_CONSTEXPRINLINE bool has_features(feature_flags query_features) const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool has_features(feature_flags query_features) const noexcept {
 		return ((Features & query_features) == query_features);
 	}
 
-	[[nodiscard]] MPT_CONSTEXPRINLINE feature_flags get_features() const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr feature_flags get_features() const noexcept {
 		return Features;
 	}
 
-	[[nodiscard]] MPT_CONSTEXPRINLINE bool operator[](mode_flags query_modes) const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator[](mode_flags query_modes) const noexcept {
 		return ((Modes & query_modes) == query_modes);
 	}
 
-	[[nodiscard]] MPT_CONSTEXPRINLINE bool enabled_modes(mode_flags query_modes) const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool enabled_modes(mode_flags query_modes) const noexcept {
 		return ((Modes & query_modes) == query_modes);
 	}
 
-	[[nodiscard]] MPT_CONSTEXPRINLINE mode_flags get_modes() const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr mode_flags get_modes() const noexcept {
 		return Modes;
 	}
 
-	[[nodiscard]] MPT_CONSTEXPRINLINE uint32 get_cpuid() const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint32 get_cpuid() const noexcept {
 		return CPUID;
 	}
 
-	[[nodiscard]] MPT_CONSTEXPRINLINE vendor get_vendor() const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr vendor get_vendor() const noexcept {
 		return Vendor;
 	}
 
-	[[nodiscard]] MPT_CONSTEXPRINLINE uint16 get_family() const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint16 get_family() const noexcept {
 		return Family;
 	}
 
-	[[nodiscard]] MPT_CONSTEXPRINLINE uint8 get_model() const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint8 get_model() const noexcept {
 		return Model;
 	}
 
-	[[nodiscard]] MPT_CONSTEXPRINLINE uint8 get_stepping() const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint8 get_stepping() const noexcept {
 		return Stepping;
 	}
 
@@ -449,11 +449,11 @@
 		return std::string(BrandID);
 	}
 
-	[[nodiscard]] MPT_CONSTEXPRINLINE bool is_virtual() const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool is_virtual() const noexcept {
 		return Virtualized;
 	}
 
-	[[nodiscard]] MPT_CONSTEXPRINLINE bool can_long_mode() const noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool can_long_mode() const noexcept {
 #if !MPT_ARCH_AMD64
 		return LongMode;
 #else  // MPT_ARCH_AMD64
@@ -472,7 +472,7 @@
 		uint32 c = 0;
 		uint32 d = 0;
 
-		[[nodiscard]] MPT_CONSTEXPR20_FUN fixed_string<4> as_text4() const noexcept {
+		[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN fixed_string<4> as_text4() const noexcept {
 			fixed_string<4> result;
 			result[0 + 0] = static_cast<char>((a >> 0) & 0xff);
 			result[0 + 1] = static_cast<char>((a >> 8) & 0xff);
@@ -481,7 +481,7 @@
 			return result;
 		}
 
-		[[nodiscard]] MPT_CONSTEXPR20_FUN fixed_string<12> as_text12bcd() const noexcept {
+		[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN fixed_string<12> as_text12bcd() const noexcept {
 			fixed_string<12> result;
 			result[0 + 0] = static_cast<char>((b >> 0) & 0xff);
 			result[0 + 1] = static_cast<char>((b >> 8) & 0xff);
@@ -498,7 +498,7 @@
 			return result;
 		}
 
-		[[nodiscard]] MPT_CONSTEXPR20_FUN fixed_string<12> as_text12bdc() const noexcept {
+		[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN fixed_string<12> as_text12bdc() const noexcept {
 			fixed_string<12> result;
 			result[0 + 0] = static_cast<char>((b >> 0) & 0xff);
 			result[0 + 1] = static_cast<char>((b >> 8) & 0xff);
@@ -515,7 +515,7 @@
 			return result;
 		}
 
-		[[nodiscard]] MPT_CONSTEXPR20_FUN fixed_string<16> as_text16() const noexcept {
+		[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN fixed_string<16> as_text16() const noexcept {
 			fixed_string<16> result;
 			result[0 + 0] = static_cast<char>((a >> 0) & 0xff);
 			result[0 + 1] = static_cast<char>((a >> 8) & 0xff);
@@ -1608,7 +1608,7 @@
 
 #if MPT_COMPILER_MSVC
 
-	[[nodiscard]] static MPT_FORCEINLINE uint16 get_x87fcw() noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static uint16 get_x87fcw() noexcept {
 		uint16 tmp = 0;
 		// clang-format off
 		_asm {
@@ -1619,7 +1619,7 @@
 		return tmp;
 	}
 
-	static MPT_FORCEINLINE void set_x87fcw(uint16 fcw) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void set_x87fcw(uint16 fcw) noexcept {
 		// clang-format off
 		_asm {
 			fldcw fcw
@@ -1627,25 +1627,25 @@
 		// clang-format on
 	}
 
-	[[nodiscard]] static MPT_FORCEINLINE uint32 get_mxcsr() noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static uint32 get_mxcsr() noexcept {
 		return _mm_getcsr();
 	}
 
-	static MPT_FORCEINLINE void set_mxcsr(uint32 csr) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void set_mxcsr(uint32 csr) noexcept {
 		_mm_setcsr(csr);
 	}
 
-	static MPT_FORCEINLINE void fxsave(fxsave_state * state) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void fxsave(fxsave_state * state) noexcept {
 		_fxsave(state);
 	}
 
-	static MPT_FORCEINLINE void fxrstor(const fxsave_state * state) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void fxrstor(const fxsave_state * state) noexcept {
 		_fxrstor(state);
 	}
 
 #elif MPT_COMPILER_GCC || MPT_COMPILER_CLANG
 
-	[[nodiscard]] static MPT_FORCEINLINE uint16 get_x87fcw() noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static uint16 get_x87fcw() noexcept {
 		typedef unsigned int fpu_control_t __attribute__((__mode__(__HI__)));
 		fpu_control_t tmp = 0;
 		// clang-format off
@@ -1654,7 +1654,7 @@
 		return static_cast<uint16>(tmp);
 	}
 
-	static MPT_FORCEINLINE void set_x87fcw(uint16 fcw) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void set_x87fcw(uint16 fcw) noexcept {
 		typedef unsigned int fpu_control_t __attribute__((__mode__(__HI__)));
 		fpu_control_t tmp = fcw;
 		// clang-format off
@@ -1662,7 +1662,7 @@
 		// clang-format on
 	}
 
-	[[nodiscard]] static MPT_FORCEINLINE uint32 get_mxcsr() noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static uint32 get_mxcsr() noexcept {
 #ifdef MPT_ARCH_X86_SSE
 		return __builtin_ia32_stmxcsr();
 #else
@@ -1674,7 +1674,7 @@
 #endif
 	}
 
-	static MPT_FORCEINLINE void set_mxcsr(uint32 csr) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void set_mxcsr(uint32 csr) noexcept {
 #ifdef MPT_ARCH_X86_SSE
 #if MPT_COMPILER_GCC
 		// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55752
@@ -1692,7 +1692,7 @@
 #endif
 	}
 
-	static MPT_FORCEINLINE void fxsave(fxsave_state * state) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void fxsave(fxsave_state * state) noexcept {
 #ifdef MPT_ARCH_X86_FXSR
 		__builtin_ia32_fxsave(state);
 #else
@@ -1702,7 +1702,7 @@
 #endif
 	}
 
-	static MPT_FORCEINLINE void fxrstor(const fxsave_state * state) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void fxrstor(const fxsave_state * state) noexcept {
 #ifdef MPT_ARCH_X86_FXSR
 		__builtin_ia32_fxrstor(const_cast<fxsave_state *>(state));
 #else
@@ -1714,7 +1714,7 @@
 
 #endif // MPT_COMPILER
 
-	static MPT_FORCEINLINE bool have_fxsr() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static bool have_fxsr() noexcept {
 #ifdef MPT_ARCH_X86_FXSR
 		return true;
 #else
@@ -1722,7 +1722,7 @@
 #endif
 	}
 
-	static MPT_FORCEINLINE bool have_sse() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static bool have_sse() noexcept {
 #ifdef MPT_ARCH_X86_SSE
 		return true;
 #else
@@ -1731,7 +1731,7 @@
 #endif
 	}
 
-	static MPT_FORCEINLINE uint8 get_fpu_level() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static uint8 get_fpu_level() noexcept {
 #ifdef MPT_ARCH_X86_FSIN
 		return 3;
 #elif defined(MPT_ARCH_X86_FPU)
@@ -1743,7 +1743,7 @@
 #endif
 	}
 
-	static MPT_FORCEINLINE control_state get_state() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static control_state get_state() noexcept {
 		control_state result;
 #ifdef MPT_ARCH_X86_FXSR
 		fxsave_state tmp = {};
@@ -1770,7 +1770,7 @@
 		return result;
 	}
 
-	static MPT_FORCEINLINE void set_state(control_state state) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void set_state(control_state state) noexcept {
 #ifdef MPT_ARCH_X86_SSE
 		if (state.x87_level) {
 			set_x87fcw(state.x87fcw);
@@ -1822,13 +1822,13 @@
 
 #if MPT_COMPILER_MSVC
 
-	[[nodiscard]] static MPT_FORCEINLINE uint16 get_x87fcw() noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static uint16 get_x87fcw() noexcept {
 		fxsave_state state = {};
 		fxsave(&state);
 		return state.fcw;
 	}
 
-	static MPT_FORCEINLINE void set_x87fcw(uint16 fcw) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void set_x87fcw(uint16 fcw) noexcept {
 		fxsave_state state = {};
 		fxsave(&state);
 		state.fcw = fcw;
@@ -1835,27 +1835,27 @@
 		fxrstor(&state);
 	}
 
-	[[nodiscard]] static MPT_FORCEINLINE uint32 get_mxcsr() noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static uint32 get_mxcsr() noexcept {
 		return _mm_getcsr();
 	}
 
-	static MPT_FORCEINLINE void set_mxcsr(uint32 csr) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void set_mxcsr(uint32 csr) noexcept {
 		_mm_setcsr(csr);
 	}
 
-	static MPT_FORCEINLINE void fxsave(fxsave_state * state) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void fxsave(fxsave_state * state) noexcept {
 		_fxsave(state);
 	}
 
-	static MPT_FORCEINLINE void fxrstor(const fxsave_state * state) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void fxrstor(const fxsave_state * state) noexcept {
 		_fxrstor(state);
 	}
 
-	static MPT_FORCEINLINE bool have_fxsr() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static bool have_fxsr() noexcept {
 		return true;
 	}
 
-	static MPT_FORCEINLINE control_state get_state() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static control_state get_state() noexcept {
 		control_state result;
 		fxsave_state tmp = {};
 		fxsave(&tmp);
@@ -1866,7 +1866,7 @@
 		return result;
 	}
 
-	static MPT_FORCEINLINE void set_state(control_state state) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void set_state(control_state state) noexcept {
 		fxsave_state tmp = {};
 		fxsave(&tmp);
 		tmp.fcw = state.x87fcw;
@@ -1877,7 +1877,7 @@
 
 #elif MPT_COMPILER_GCC || MPT_COMPILER_CLANG
 
-	[[nodiscard]] static MPT_FORCEINLINE uint16 get_x87fcw() noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static uint16 get_x87fcw() noexcept {
 		typedef unsigned int fpu_control_t __attribute__((__mode__(__HI__)));
 		fpu_control_t tmp = 0;
 		// clang-format off
@@ -1886,7 +1886,7 @@
 		return static_cast<uint16>(tmp);
 	}
 
-	static MPT_FORCEINLINE void set_x87fcw(uint16 fcw) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void set_x87fcw(uint16 fcw) noexcept {
 		typedef unsigned int fpu_control_t __attribute__((__mode__(__HI__)));
 		fpu_control_t tmp = fcw;
 		// clang-format off
@@ -1894,11 +1894,11 @@
 		// clang-format on
 	}
 
-	[[nodiscard]] static MPT_FORCEINLINE uint32 get_mxcsr() noexcept {
+	[[nodiscard]] MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static uint32 get_mxcsr() noexcept {
 		return __builtin_ia32_stmxcsr();
 	}
 
-	static MPT_FORCEINLINE void set_mxcsr(uint32 csr) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void set_mxcsr(uint32 csr) noexcept {
 #if MPT_COMPILER_GCC
 		// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55752
 		std::atomic_thread_fence(std::memory_order_seq_cst);
@@ -1910,19 +1910,19 @@
 #endif
 	}
 
-	static MPT_FORCEINLINE void fxsave(fxsave_state * state) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void fxsave(fxsave_state * state) noexcept {
 		__builtin_ia32_fxsave(state);
 	}
 
-	static MPT_FORCEINLINE void fxrstor(const fxsave_state * state) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void fxrstor(const fxsave_state * state) noexcept {
 		__builtin_ia32_fxrstor(const_cast<fxsave_state *>(state));
 	}
 
-	static MPT_FORCEINLINE bool have_fxsr() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static bool have_fxsr() noexcept {
 		return true;
 	}
 
-	static MPT_FORCEINLINE control_state get_state() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static control_state get_state() noexcept {
 		control_state result;
 		result.x87_level = 3;
 		result.x87fcw = get_x87fcw();
@@ -1931,7 +1931,7 @@
 		return result;
 	}
 
-	static MPT_FORCEINLINE void set_state(control_state state) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE static void set_state(control_state state) noexcept {
 		set_x87fcw(state.x87fcw);
 		set_mxcsr(state.mxcsr);
 	}
@@ -1946,7 +1946,7 @@
 
 	public:
 
-		MPT_FORCEINLINE guard(std::optional<rounding> rounding, std::optional<bool> denormals_as_zero, std::optional<precision> precision, std::optional<bool> infinity_projective) noexcept
+		MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE guard(std::optional<rounding> rounding, std::optional<bool> denormals_as_zero, std::optional<precision> precision, std::optional<bool> infinity_projective) noexcept
 			: m_oldstate(get_state()) {
 			control_state state = m_oldstate;
 			if (rounding) {
@@ -1975,7 +1975,7 @@
 			set_state(state);
 		}
 
-		MPT_FORCEINLINE ~guard() {
+		MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE ~guard() {
 			set_state(m_oldstate);
 		}
 	};
Index: src/mpt/audio/span.hpp
===================================================================
--- src/mpt/audio/span.hpp	(revision 23566)
+++ src/mpt/audio/span.hpp	(working copy)
@@ -34,40 +34,40 @@
 	std::size_t m_frames;
 
 public:
-	MPT_CONSTEXPRINLINE audio_span_interleaved(sample_type * buffer, std::size_t channels, std::size_t frames) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr audio_span_interleaved(sample_type * buffer, std::size_t channels, std::size_t frames) noexcept
 		: m_buffer(buffer)
 		, m_channels(channels)
 		, m_frames(frames) {
 		return;
 	}
-	MPT_FORCEINLINE sample_type * const * data_planar() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type * const * data_planar() const noexcept {
 		return nullptr;
 	}
-	MPT_FORCEINLINE sample_type * data() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type * data() const noexcept {
 		return m_buffer;
 	}
-	MPT_FORCEINLINE sample_type & operator()(std::size_t channel, std::size_t frame) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type & operator()(std::size_t channel, std::size_t frame) const {
 		return m_buffer[m_channels * frame + channel];
 	}
-	MPT_FORCEINLINE bool is_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool is_contiguous() const noexcept {
 		return true;
 	}
-	MPT_FORCEINLINE bool channels_are_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool channels_are_contiguous() const noexcept {
 		return false;
 	}
-	MPT_FORCEINLINE bool frames_are_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool frames_are_contiguous() const noexcept {
 		return true;
 	}
-	MPT_FORCEINLINE std::size_t size_channels() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_channels() const noexcept {
 		return m_channels;
 	}
-	MPT_FORCEINLINE std::size_t size_frames() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_frames() const noexcept {
 		return m_frames;
 	}
-	MPT_FORCEINLINE std::size_t size_samples() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_samples() const noexcept {
 		return m_channels * m_frames;
 	}
-	MPT_FORCEINLINE std::ptrdiff_t frame_stride() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::ptrdiff_t frame_stride() const noexcept {
 		return m_channels;
 	}
 };
@@ -92,40 +92,40 @@
 	std::size_t m_frames;
 
 public:
-	MPT_CONSTEXPRINLINE audio_span_contiguous(sample_type * buffer, std::size_t channels, std::size_t frames) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr audio_span_contiguous(sample_type * buffer, std::size_t channels, std::size_t frames) noexcept
 		: m_buffer(buffer)
 		, m_channels(channels)
 		, m_frames(frames) {
 		return;
 	}
-	MPT_FORCEINLINE sample_type * const * data_planar() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type * const * data_planar() const noexcept {
 		return nullptr;
 	}
-	MPT_FORCEINLINE sample_type * data() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type * data() const noexcept {
 		return m_buffer;
 	}
-	MPT_FORCEINLINE sample_type & operator()(std::size_t channel, std::size_t frame) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type & operator()(std::size_t channel, std::size_t frame) const {
 		return m_buffer[(m_frames * channel) + frame];
 	}
-	MPT_FORCEINLINE bool is_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool is_contiguous() const noexcept {
 		return true;
 	}
-	MPT_FORCEINLINE bool channels_are_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool channels_are_contiguous() const noexcept {
 		return true;
 	}
-	MPT_FORCEINLINE bool frames_are_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool frames_are_contiguous() const noexcept {
 		return false;
 	}
-	MPT_FORCEINLINE std::size_t size_channels() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_channels() const noexcept {
 		return m_channels;
 	}
-	MPT_FORCEINLINE std::size_t size_frames() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_frames() const noexcept {
 		return m_frames;
 	}
-	MPT_FORCEINLINE std::size_t size_samples() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_samples() const noexcept {
 		return m_channels * m_frames;
 	}
-	MPT_FORCEINLINE std::ptrdiff_t frame_stride() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::ptrdiff_t frame_stride() const noexcept {
 		return 1;
 	}
 };
@@ -150,40 +150,40 @@
 	std::size_t m_frames;
 
 public:
-	MPT_CONSTEXPRINLINE audio_span_planar(sample_type * const * buffers, std::size_t channels, std::size_t frames) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr audio_span_planar(sample_type * const * buffers, std::size_t channels, std::size_t frames) noexcept
 		: m_buffers(buffers)
 		, m_channels(channels)
 		, m_frames(frames) {
 		return;
 	}
-	MPT_FORCEINLINE sample_type * const * data_planar() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type * const * data_planar() const noexcept {
 		return m_buffers;
 	}
-	MPT_FORCEINLINE sample_type * data() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type * data() const noexcept {
 		return nullptr;
 	}
-	MPT_FORCEINLINE sample_type & operator()(std::size_t channel, std::size_t frame) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type & operator()(std::size_t channel, std::size_t frame) const {
 		return m_buffers[channel][frame];
 	}
-	MPT_FORCEINLINE bool is_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool is_contiguous() const noexcept {
 		return false;
 	}
-	MPT_FORCEINLINE bool channels_are_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool channels_are_contiguous() const noexcept {
 		return true;
 	}
-	MPT_FORCEINLINE bool frames_are_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool frames_are_contiguous() const noexcept {
 		return false;
 	}
-	MPT_FORCEINLINE std::size_t size_channels() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_channels() const noexcept {
 		return m_channels;
 	}
-	MPT_FORCEINLINE std::size_t size_frames() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_frames() const noexcept {
 		return m_frames;
 	}
-	MPT_FORCEINLINE std::size_t size_samples() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_samples() const noexcept {
 		return m_channels * m_frames;
 	}
-	MPT_FORCEINLINE std::ptrdiff_t frame_stride() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::ptrdiff_t frame_stride() const noexcept {
 		return 1;
 	}
 };
@@ -208,7 +208,7 @@
 	std::size_t m_frames;
 
 public:
-	MPT_CONSTEXPRINLINE audio_span_planar_strided(sample_type * const * buffers, std::size_t channels, std::size_t frames, std::ptrdiff_t frame_stride) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr audio_span_planar_strided(sample_type * const * buffers, std::size_t channels, std::size_t frames, std::ptrdiff_t frame_stride) noexcept
 		: m_buffers(buffers)
 		, m_frame_stride(frame_stride)
 		, m_channels(channels)
@@ -215,34 +215,34 @@
 		, m_frames(frames) {
 		return;
 	}
-	MPT_FORCEINLINE sample_type * const * data_planar() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type * const * data_planar() const noexcept {
 		return m_buffers;
 	}
-	MPT_FORCEINLINE sample_type * data() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type * data() const noexcept {
 		return nullptr;
 	}
-	MPT_FORCEINLINE sample_type & operator()(std::size_t channel, std::size_t frame) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type & operator()(std::size_t channel, std::size_t frame) const {
 		return m_buffers[channel][static_cast<std::ptrdiff_t>(frame) * m_frame_stride];
 	}
-	MPT_FORCEINLINE bool is_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool is_contiguous() const noexcept {
 		return false;
 	}
-	MPT_FORCEINLINE bool channels_are_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool channels_are_contiguous() const noexcept {
 		return false;
 	}
-	MPT_FORCEINLINE bool frames_are_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool frames_are_contiguous() const noexcept {
 		return false;
 	}
-	MPT_FORCEINLINE std::size_t size_channels() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_channels() const noexcept {
 		return m_channels;
 	}
-	MPT_FORCEINLINE std::size_t size_frames() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_frames() const noexcept {
 		return m_frames;
 	}
-	MPT_FORCEINLINE std::size_t size_samples() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_samples() const noexcept {
 		return m_channels * m_frames;
 	}
-	MPT_FORCEINLINE std::ptrdiff_t frame_stride() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::ptrdiff_t frame_stride() const noexcept {
 		return m_frame_stride;
 	}
 };
@@ -270,7 +270,7 @@
 	std::size_t m_frames;
 
 public:
-	MPT_CONSTEXPRINLINE audio_span(audio_span_interleaved<sample_type> buffer) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr audio_span(audio_span_interleaved<sample_type> buffer) noexcept
 		: m_frame_stride(static_cast<std::ptrdiff_t>(buffer.size_channels()))
 		, m_channel_stride(1)
 		, m_channels(buffer.size_channels())
@@ -277,7 +277,7 @@
 		, m_frames(buffer.size_frames()) {
 		m_buffer.contiguous = buffer.data();
 	}
-	MPT_CONSTEXPRINLINE audio_span(sample_type * buffer, std::size_t channels, std::size_t frames, audio_span_frames_are_contiguous_t) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr audio_span(sample_type * buffer, std::size_t channels, std::size_t frames, audio_span_frames_are_contiguous_t) noexcept
 		: m_frame_stride(static_cast<std::ptrdiff_t>(channels))
 		, m_channel_stride(1)
 		, m_channels(channels)
@@ -284,7 +284,7 @@
 		, m_frames(frames) {
 		m_buffer.contiguous = buffer;
 	}
-	MPT_CONSTEXPRINLINE audio_span(audio_span_contiguous<sample_type> buffer) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr audio_span(audio_span_contiguous<sample_type> buffer) noexcept
 		: m_frame_stride(1)
 		, m_channel_stride(buffer.size_frames())
 		, m_channels(buffer.size_channels())
@@ -291,7 +291,7 @@
 		, m_frames(buffer.size_frames()) {
 		m_buffer.contiguous = buffer.data();
 	}
-	MPT_CONSTEXPRINLINE audio_span(sample_type * buffer, std::size_t channels, std::size_t frames, audio_span_channels_are_contiguous_t) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr audio_span(sample_type * buffer, std::size_t channels, std::size_t frames, audio_span_channels_are_contiguous_t) noexcept
 		: m_frame_stride(1)
 		, m_channel_stride(static_cast<std::ptrdiff_t>(frames))
 		, m_channels(channels)
@@ -298,7 +298,7 @@
 		, m_frames(frames) {
 		m_buffer.contiguous = buffer;
 	}
-	MPT_CONSTEXPRINLINE audio_span(audio_span_planar<sample_type> buffer) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr audio_span(audio_span_planar<sample_type> buffer) noexcept
 		: m_frame_stride(1)
 		, m_channel_stride(0)
 		, m_channels(buffer.size_channels())
@@ -305,7 +305,7 @@
 		, m_frames(buffer.size_frames()) {
 		m_buffer.planes = buffer.data_planar();
 	}
-	MPT_CONSTEXPRINLINE audio_span(sample_type * const * planes, std::size_t channels, std::size_t frames, audio_span_channels_are_planar_t) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr audio_span(sample_type * const * planes, std::size_t channels, std::size_t frames, audio_span_channels_are_planar_t) noexcept
 		: m_frame_stride(1)
 		, m_channel_stride(0)
 		, m_channels(channels)
@@ -312,7 +312,7 @@
 		, m_frames(frames) {
 		m_buffer.planes = planes;
 	}
-	MPT_CONSTEXPRINLINE audio_span(audio_span_planar_strided<sample_type> buffer) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr audio_span(audio_span_planar_strided<sample_type> buffer) noexcept
 		: m_frame_stride(static_cast<std::ptrdiff_t>(buffer.frame_stride()))
 		, m_channel_stride(0)
 		, m_channels(buffer.size_channels())
@@ -319,7 +319,7 @@
 		, m_frames(buffer.size_frames()) {
 		m_buffer.planes = buffer.data_planar();
 	}
-	MPT_CONSTEXPRINLINE audio_span(sample_type * const * planes, std::size_t channels, std::size_t frames, std::ptrdiff_t frame_stride, audio_span_channels_are_planar_and_strided_t) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr audio_span(sample_type * const * planes, std::size_t channels, std::size_t frames, std::ptrdiff_t frame_stride, audio_span_channels_are_planar_and_strided_t) noexcept
 		: m_frame_stride(frame_stride)
 		, m_channel_stride(0)
 		, m_channels(channels)
@@ -326,34 +326,34 @@
 		, m_frames(frames) {
 		m_buffer.planes = planes;
 	}
-	MPT_FORCEINLINE bool is_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool is_contiguous() const noexcept {
 		return (m_channel_stride != 0);
 	}
-	MPT_FORCEINLINE sample_type * const * data_planar() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type * const * data_planar() const noexcept {
 		return (!is_contiguous()) ? m_buffer.planes : nullptr;
 	}
-	MPT_FORCEINLINE sample_type * data() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type * data() const noexcept {
 		return is_contiguous() ? m_buffer.contiguous : nullptr;
 	}
-	MPT_FORCEINLINE sample_type & operator()(std::size_t channel, std::size_t frame) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type & operator()(std::size_t channel, std::size_t frame) const {
 		return is_contiguous() ? m_buffer.contiguous[(m_channel_stride * static_cast<std::ptrdiff_t>(channel)) + (m_frame_stride * static_cast<std::ptrdiff_t>(frame))] : m_buffer.planes[channel][frame * static_cast<std::ptrdiff_t>(m_frame_stride)];
 	}
-	MPT_FORCEINLINE bool channels_are_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool channels_are_contiguous() const noexcept {
 		return (m_frame_stride == 1);
 	}
-	MPT_FORCEINLINE bool frames_are_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool frames_are_contiguous() const noexcept {
 		return (m_channel_stride == 1);
 	}
-	MPT_FORCEINLINE std::size_t size_channels() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_channels() const noexcept {
 		return m_channels;
 	}
-	MPT_FORCEINLINE std::size_t size_frames() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_frames() const noexcept {
 		return m_frames;
 	}
-	MPT_FORCEINLINE std::size_t size_samples() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_samples() const noexcept {
 		return m_channels * m_frames;
 	}
-	MPT_FORCEINLINE std::ptrdiff_t frame_stride() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::ptrdiff_t frame_stride() const noexcept {
 		return m_frame_stride;
 	}
 };
@@ -370,42 +370,42 @@
 	std::size_t m_offset;
 
 public:
-	MPT_CONSTEXPRINLINE audio_span_with_offset(Taudio_span buffer, std::size_t offsetFrames) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr audio_span_with_offset(Taudio_span buffer, std::size_t offsetFrames) noexcept
 		: m_buffer(buffer)
 		, m_offset(offsetFrames) {
 		return;
 	}
-	MPT_FORCEINLINE sample_type * const * data_planar() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type * const * data_planar() const noexcept {
 		return nullptr;
 	}
-	MPT_FORCEINLINE sample_type * data() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type * data() const noexcept {
 		if (!is_contiguous()) {
 			return nullptr;
 		}
 		return m_buffer.data() + (size_channels() * m_offset);
 	}
-	MPT_FORCEINLINE sample_type & operator()(std::size_t channel, std::size_t frame) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE sample_type & operator()(std::size_t channel, std::size_t frame) const {
 		return m_buffer(channel, m_offset + frame);
 	}
-	MPT_FORCEINLINE bool is_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool is_contiguous() const noexcept {
 		return m_buffer.is_contiguous() && m_buffer.frames_are_contiguous();
 	}
-	MPT_FORCEINLINE bool channels_are_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool channels_are_contiguous() const noexcept {
 		return m_buffer.channels_are_contiguous();
 	}
-	MPT_FORCEINLINE bool frames_are_contiguous() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool frames_are_contiguous() const noexcept {
 		return m_buffer.frames_are_contiguous();
 	}
-	MPT_FORCEINLINE std::size_t size_channels() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_channels() const noexcept {
 		return m_buffer.size_channels();
 	}
-	MPT_FORCEINLINE std::size_t size_frames() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_frames() const noexcept {
 		return m_buffer.size_frames() - m_offset;
 	}
-	MPT_FORCEINLINE std::size_t size_samples() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::size_t size_samples() const noexcept {
 		return size_channels() * size_frames();
 	}
-	MPT_FORCEINLINE std::ptrdiff_t frame_stride() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::ptrdiff_t frame_stride() const noexcept {
 		return m_buffer.frame_stride();
 	}
 };
@@ -413,7 +413,7 @@
 
 
 template <typename Tspan, typename Tfunc>
-MPT_FORCEINLINE auto audio_span_optimized_visit(Tspan span, Tfunc && f) -> decltype(std::forward<Tfunc>(f)(span)) const {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE auto audio_span_optimized_visit(Tspan span, Tfunc && f) -> decltype(std::forward<Tfunc>(f)(span)) const {
 	using sample_type = typename Tspan::sample_type;
 	std::variant<Tspan, audio_span_interleaved<sample_type>, audio_span_contiguous<sample_type>, audio_span_planar<sample_type>, audio_span_planar_strided<sample_type>> v{span};
 	if (span.data() && span.is_contiguous() && span.frames_are_contiguous()) {
Index: src/mpt/base/algorithm.hpp
===================================================================
--- src/mpt/base/algorithm.hpp	(revision 23566)
+++ src/mpt/base/algorithm.hpp	(working copy)
@@ -73,22 +73,22 @@
 };
 
 template <typename Tcontainer, typename Tval>
-MPT_CONSTEXPR20_FUN bool contains_class_find_impl(const Tcontainer & container, const Tval & value, std::true_type) noexcept(noexcept(container.find(value) != container.end())) {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN bool contains_class_find_impl(const Tcontainer & container, const Tval & value, std::true_type) noexcept(noexcept(container.find(value) != container.end())) {
 	return container.find(value) != container.end();
 }
 
 template <typename Tcontainer, typename Tval>
-MPT_CONSTEXPR20_FUN bool contains_class_find_impl(const Tcontainer & container, const Tval & value, std::false_type) noexcept(noexcept(std::find(std::begin(container), std::end(container), value))) {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN bool contains_class_find_impl(const Tcontainer & container, const Tval & value, std::false_type) noexcept(noexcept(std::find(std::begin(container), std::end(container), value))) {
 	return std::find(std::begin(container), std::end(container), value) != std::end(container);
 }
 
 template <typename Tcontainer, typename Tval>
-MPT_CONSTEXPR20_FUN bool contains_class_impl(const Tcontainer & container, const Tval & value, std::true_type) noexcept(noexcept(mpt::detail::contains::contains_class_find_impl<Tcontainer, Tval>(container, value, typename mpt::detail::contains::has_find<Tcontainer, typename Tcontainer::iterator(Tval)>::type{}))) {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN bool contains_class_impl(const Tcontainer & container, const Tval & value, std::true_type) noexcept(noexcept(mpt::detail::contains::contains_class_find_impl<Tcontainer, Tval>(container, value, typename mpt::detail::contains::has_find<Tcontainer, typename Tcontainer::iterator(Tval)>::type{}))) {
 	return mpt::detail::contains::contains_class_find_impl<Tcontainer, Tval>(container, value, typename mpt::detail::contains::has_find<Tcontainer, typename Tcontainer::iterator(Tval)>::type{});
 }
 
 template <typename Tcontainer, typename Tval>
-MPT_CONSTEXPR20_FUN bool contains_class_impl(const Tcontainer & container, const Tval & value, std::false_type) noexcept(noexcept(std::find(std::begin(container), std::end(container), value))) {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN bool contains_class_impl(const Tcontainer & container, const Tval & value, std::false_type) noexcept(noexcept(std::find(std::begin(container), std::end(container), value))) {
 	return std::find(std::begin(container), std::end(container), value) != std::end(container);
 }
 
@@ -96,7 +96,7 @@
 } // namespace detail
 
 template <typename Tcontainer, typename Tval>
-MPT_CONSTEXPR20_FUN bool contains(const Tcontainer & container, const Tval & value) noexcept(noexcept(mpt::detail::contains::contains_class_impl<Tcontainer, Tval>(container, value, typename std::is_class<Tcontainer>::type{}))) {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN bool contains(const Tcontainer & container, const Tval & value) noexcept(noexcept(mpt::detail::contains::contains_class_impl<Tcontainer, Tval>(container, value, typename std::is_class<Tcontainer>::type{}))) {
 	return mpt::detail::contains::contains_class_impl<Tcontainer, Tval>(container, value, typename std::is_class<Tcontainer>::type{});
 }
 
Index: src/mpt/base/bit.hpp
===================================================================
--- src/mpt/base/bit.hpp	(revision 23566)
+++ src/mpt/base/bit.hpp	(working copy)
@@ -44,7 +44,7 @@
 // causing an ICE with LTCG turned on.
 // We try to work-around this problem by placing signal fences as an optimization barrier around the (presumably) confused operation.
 template <typename Tdst, typename Tsrc>
-MPT_FORCEINLINE typename std::enable_if<(sizeof(Tdst) == sizeof(Tsrc)) && std::is_trivially_copyable<Tsrc>::value && std::is_trivially_copyable<Tdst>::value, Tdst>::type bit_cast(const Tsrc & src) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE typename std::enable_if<(sizeof(Tdst) == sizeof(Tsrc)) && std::is_trivially_copyable<Tsrc>::value && std::is_trivially_copyable<Tdst>::value, Tdst>::type bit_cast(const Tsrc & src) noexcept {
 	Tdst dst{};
 	std::atomic_signal_fence(std::memory_order_seq_cst);
 	std::memcpy(&dst, &src, sizeof(Tdst));
@@ -57,7 +57,7 @@
 // C++2a compatible bit_cast.
 // Not implementing constexpr because this is not easily possible pre C++20.
 template <typename Tdst, typename Tsrc>
-MPT_FORCEINLINE typename std::enable_if<(sizeof(Tdst) == sizeof(Tsrc)) && std::is_trivially_copyable<Tsrc>::value && std::is_trivially_copyable<Tdst>::value, Tdst>::type bit_cast(const Tsrc & src) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE typename std::enable_if<(sizeof(Tdst) == sizeof(Tsrc)) && std::is_trivially_copyable<Tsrc>::value && std::is_trivially_copyable<Tdst>::value, Tdst>::type bit_cast(const Tsrc & src) noexcept {
 	Tdst dst{};
 	std::memcpy(&dst, &src, sizeof(Tdst));
 	return dst;
@@ -117,7 +117,7 @@
 
 static_assert(mpt::endian::big != mpt::endian::little, "platform with all scalar types having size 1 is not supported");
 
-MPT_FORCEINLINE mpt::endian endian_probe() noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE mpt::endian endian_probe() noexcept {
 	using endian_probe_type = uint32;
 	static_assert(sizeof(endian_probe_type) == 4);
 	constexpr endian_probe_type endian_probe_big = 0x12345678u;
@@ -141,7 +141,7 @@
 	return result;
 }
 
-MPT_FORCEINLINE mpt::endian get_endian() noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE mpt::endian get_endian() noexcept {
 #if MPT_COMPILER_MSVC
 #pragma warning(push)
 #pragma warning(disable : 6285) // false-positive: (<non-zero constant> || <non-zero constant>) is always a non-zero constant.
@@ -156,15 +156,15 @@
 #endif // MPT_COMPILER_MSVC
 }
 
-MPT_FORCEINLINE bool endian_is_little() noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool endian_is_little() noexcept {
 	return get_endian() == mpt::endian::little;
 }
 
-MPT_FORCEINLINE bool endian_is_big() noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool endian_is_big() noexcept {
 	return get_endian() == mpt::endian::big;
 }
 
-MPT_FORCEINLINE bool endian_is_weird() noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool endian_is_weird() noexcept {
 	return !endian_is_little() && !endian_is_big();
 }
 
@@ -418,7 +418,7 @@
 #define MPT_byteswap_impl64(x) byteswap_impl_constexpr64(x)
 #endif
 
-MPT_CONSTEXPR20_FUN uint64 byteswap_impl(uint64 value) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN uint64 byteswap_impl(uint64 value) noexcept {
 	MPT_MAYBE_CONSTANT_IF (MPT_IS_CONSTANT_EVALUATED20()) {
 		return byteswap_impl_constexpr64(value);
 	} else {
@@ -426,7 +426,7 @@
 	}
 }
 
-MPT_CONSTEXPR20_FUN uint32 byteswap_impl(uint32 value) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN uint32 byteswap_impl(uint32 value) noexcept {
 	MPT_MAYBE_CONSTANT_IF (MPT_IS_CONSTANT_EVALUATED20()) {
 		return byteswap_impl_constexpr32(value);
 	} else {
@@ -434,7 +434,7 @@
 	}
 }
 
-MPT_CONSTEXPR20_FUN uint16 byteswap_impl(uint16 value) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN uint16 byteswap_impl(uint16 value) noexcept {
 	MPT_MAYBE_CONSTANT_IF (MPT_IS_CONSTANT_EVALUATED20()) {
 		return byteswap_impl_constexpr16(value);
 	} else {
@@ -442,7 +442,7 @@
 	}
 }
 
-MPT_CONSTEXPR20_FUN int64 byteswap_impl(int64 value) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN int64 byteswap_impl(int64 value) noexcept {
 	MPT_MAYBE_CONSTANT_IF (MPT_IS_CONSTANT_EVALUATED20()) {
 		return byteswap_impl_constexpr64(value);
 	} else {
@@ -450,7 +450,7 @@
 	}
 }
 
-MPT_CONSTEXPR20_FUN int32 byteswap_impl(int32 value) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN int32 byteswap_impl(int32 value) noexcept {
 	MPT_MAYBE_CONSTANT_IF (MPT_IS_CONSTANT_EVALUATED20()) {
 		return byteswap_impl_constexpr32(value);
 	} else {
@@ -458,7 +458,7 @@
 	}
 }
 
-MPT_CONSTEXPR20_FUN int16 byteswap_impl(int16 value) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN int16 byteswap_impl(int16 value) noexcept {
 	MPT_MAYBE_CONSTANT_IF (MPT_IS_CONSTANT_EVALUATED20()) {
 		return byteswap_impl_constexpr16(value);
 	} else {
Index: src/mpt/base/debugging.hpp
===================================================================
--- src/mpt/base/debugging.hpp	(revision 23566)
+++ src/mpt/base/debugging.hpp	(working copy)
@@ -62,7 +62,7 @@
 	return (IsDebuggerPresent() != FALSE);
 }
 
-MPT_FORCEINLINE void breakpoint() noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void breakpoint() noexcept {
 #if MPT_COMPILER_MSVC
 	__debugbreak();
 #elif MPT_COMPILER_CLANG
@@ -178,11 +178,11 @@
 } // namespace debugging
 } // namespace detail
 
-inline MPT_NOINLINE bool is_debugger_present() noexcept {
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE inline bool is_debugger_present() noexcept {
 	return mpt::detail::debugging::parse_proc_status();
 }
 
-MPT_FORCEINLINE void breakpoint() noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void breakpoint() noexcept {
 #if MPT_COMPILER_CLANG
 	__builtin_debugtrap();
 #elif MPT_COMPILER_GCC && (MPT_ARCH_X86 || MPT_ARCH_AMD64)
@@ -198,7 +198,7 @@
 	return false;
 }
 
-MPT_FORCEINLINE void breakpoint() noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void breakpoint() noexcept {
 #if MPT_COMPILER_MSVC
 	__debugbreak();
 #elif MPT_COMPILER_CLANG
@@ -210,7 +210,7 @@
 
 #endif
 
-MPT_FORCEINLINE void breakpoint_if_debugging() noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE void breakpoint_if_debugging() noexcept {
 	if (mpt::is_debugger_present()) {
 		mpt::breakpoint();
 	}
Index: src/mpt/base/float.hpp
===================================================================
--- src/mpt/base/float.hpp	(revision 23566)
+++ src/mpt/base/float.hpp	(working copy)
@@ -27,7 +27,7 @@
 // fp single
 using single_float = float;
 namespace float_literals {
-MPT_CONSTEVAL single_float operator""_fs(long double lit) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL single_float operator""_fs(long double lit) noexcept {
 	return static_cast<single_float>(lit);
 }
 } // namespace float_literals
@@ -35,7 +35,7 @@
 // fp double
 using double_float = float;
 namespace float_literals {
-MPT_CONSTEVAL double_float operator""_fd(long double lit) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL double_float operator""_fd(long double lit) noexcept {
 	return static_cast<double_float>(lit);
 }
 } // namespace float_literals
@@ -43,7 +43,7 @@
 // fp extended
 using extended_float = long double;
 namespace float_literals {
-MPT_CONSTEVAL extended_float operator""_fe(long double lit) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL extended_float operator""_fe(long double lit) noexcept {
 	return static_cast<extended_float>(lit);
 }
 } // namespace float_literals
@@ -110,16 +110,16 @@
 #undef MPT_BASE_STDFLOAT_FLOAT128
 
 namespace float_literals {
-MPT_CONSTEVAL stdfloat16 operator""_stdf16(long double lit) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL stdfloat16 operator""_stdf16(long double lit) noexcept {
 	return static_cast<stdfloat16>(lit);
 }
-MPT_CONSTEVAL stdfloat32 operator""_stdf32(long double lit) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL stdfloat32 operator""_stdf32(long double lit) noexcept {
 	return static_cast<stdfloat32>(lit);
 }
-MPT_CONSTEVAL stdfloat64 operator""_stdf64(long double lit) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL stdfloat64 operator""_stdf64(long double lit) noexcept {
 	return static_cast<stdfloat64>(lit);
 }
-MPT_CONSTEVAL stdfloat128 operator""_stdf128(long double lit) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL stdfloat128 operator""_stdf128(long double lit) noexcept {
 	return static_cast<stdfloat128>(lit);
 }
 } // namespace float_literals
@@ -128,7 +128,7 @@
 
 using fastfloat32 = std::conditional<sizeof(float) == 4, float, std::conditional<sizeof(double) == 4, double, std::conditional<sizeof(long double) == 4, long double, float>::type>::type>::type;
 namespace float_literals {
-MPT_CONSTEVAL fastfloat32 operator""_ff32(long double lit) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL fastfloat32 operator""_ff32(long double lit) noexcept {
 	return static_cast<fastfloat32>(lit);
 }
 } // namespace float_literals
@@ -135,7 +135,7 @@
 
 using fastfloat64 = std::conditional<sizeof(float) == 8, float, std::conditional<sizeof(double) == 8, double, std::conditional<sizeof(long double) == 8, long double, double>::type>::type>::type;
 namespace float_literals {
-MPT_CONSTEVAL fastfloat64 operator""_ff64(long double lit) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL fastfloat64 operator""_ff64(long double lit) noexcept {
 	return static_cast<fastfloat64>(lit);
 }
 } // namespace float_literals
@@ -144,7 +144,7 @@
 
 using somefloat32 = std::conditional<sizeof(fastfloat32) == 4, fastfloat32, std::conditional<sizeof(stdfloat32) == 4, stdfloat32, float>::type>::type;
 namespace float_literals {
-MPT_CONSTEVAL somefloat32 operator""_sf32(long double lit) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL somefloat32 operator""_sf32(long double lit) noexcept {
 	return static_cast<somefloat32>(lit);
 }
 } // namespace float_literals
@@ -151,7 +151,7 @@
 
 using somefloat64 = std::conditional<sizeof(fastfloat64) == 8, fastfloat64, std::conditional<sizeof(stdfloat64) == 8, stdfloat64, double>::type>::type;
 namespace float_literals {
-MPT_CONSTEVAL somefloat64 operator""_sf64(long double lit) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL somefloat64 operator""_sf64(long double lit) noexcept {
 	return static_cast<somefloat64>(lit);
 }
 } // namespace float_literals
@@ -174,7 +174,7 @@
 using nativefloat =
 	std::conditional<mpt::float_traits<somefloat32>::is_preferred, somefloat32, std::conditional<mpt::float_traits<somefloat64>::is_preferred, somefloat64, std::conditional<std::numeric_limits<float>::is_iec559, float, std::conditional<std::numeric_limits<double>::is_iec559, double, std::conditional<std::numeric_limits<long double>::is_iec559, long double, float>::type>::type>::type>::type>::type;
 namespace float_literals {
-MPT_CONSTEVAL nativefloat operator""_nf(long double lit) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL nativefloat operator""_nf(long double lit) noexcept {
 	return static_cast<nativefloat>(lit);
 }
 } // namespace float_literals
Index: src/mpt/base/macros.hpp
===================================================================
--- src/mpt/base/macros.hpp	(revision 23566)
+++ src/mpt/base/macros.hpp	(working copy)
@@ -57,35 +57,38 @@
 
 
 
-#if MPT_COMPILER_MSVC
-#define MPT_FORCEINLINE __forceinline
-#define MPT_NOINLINE    __declspec(noinline)
-#elif MPT_COMPILER_GCC || MPT_COMPILER_CLANG
-#define MPT_FORCEINLINE __attribute__((always_inline)) inline
-#define MPT_NOINLINE    __attribute__((noinline))
+// for compilers that do not support C++ attribute syntax for noinline
+#if MPT_MSVC_BEFORE(2019, 1) || MPT_CXX_BEFORE(20)
+#define MPT_DECL_NOINLINE __declspec(noinline)
 #else
-#define MPT_FORCEINLINE inline
-#define MPT_NOINLINE
+#define MPT_DECL_NOINLINE
 #endif
 
 
 
-#define MPT_CONSTEXPRINLINE constexpr MPT_FORCEINLINE
+// for compilers that do not support C++ attribute syntax for forced inline
+#if MPT_MSVC_BEFORE(2019, 1) || MPT_CXX_BEFORE(20)
+#define MPT_INLINE_FORCE __forceinline
+#else
+#define MPT_INLINE_FORCE inline
+#endif
 
+
+
 #if MPT_CXX_AT_LEAST(23)
-#define MPT_CONSTEXPR20_FUN constexpr MPT_FORCEINLINE
+#define MPT_CONSTEXPR20_FUN MPT_INLINE_FORCE constexpr
 #define MPT_CONSTEXPR20_VAR constexpr
-#define MPT_CONSTEXPR23_FUN constexpr MPT_FORCEINLINE
+#define MPT_CONSTEXPR23_FUN MPT_INLINE_FORCE constexpr
 #define MPT_CONSTEXPR23_VAR constexpr
 #elif MPT_CXX_AT_LEAST(20)
-#define MPT_CONSTEXPR20_FUN constexpr MPT_FORCEINLINE
+#define MPT_CONSTEXPR20_FUN MPT_INLINE_FORCE constexpr
 #define MPT_CONSTEXPR20_VAR constexpr
-#define MPT_CONSTEXPR23_FUN MPT_FORCEINLINE
+#define MPT_CONSTEXPR23_FUN MPT_INLINE_FORCE
 #define MPT_CONSTEXPR23_VAR const
 #else // C++
-#define MPT_CONSTEXPR20_FUN MPT_FORCEINLINE
+#define MPT_CONSTEXPR20_FUN MPT_INLINE_FORCE
 #define MPT_CONSTEXPR20_VAR const
-#define MPT_CONSTEXPR23_FUN MPT_FORCEINLINE
+#define MPT_CONSTEXPR23_FUN MPT_INLINE_FORCE
 #define MPT_CONSTEXPR23_VAR const
 #endif // C++
 
@@ -111,7 +114,7 @@
 #define MPT_CONSTEVAL consteval
 #else // !C++20
 // fallback to constexpr
-#define MPT_CONSTEVAL MPT_CONSTEXPRINLINE
+#define MPT_CONSTEVAL MPT_INLINE_FORCE constexpr
 #endif // C++20
 
 
Index: src/mpt/base/memory.hpp
===================================================================
--- src/mpt/base/memory.hpp	(revision 23566)
+++ src/mpt/base/memory.hpp	(working copy)
@@ -207,7 +207,7 @@
 
 
 template <typename T>
-MPT_CONSTEXPRINLINE std::byte as_byte(T src) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr std::byte as_byte(T src) noexcept {
 	static_assert(std::is_integral<T>::value);
 	return static_cast<std::byte>(static_cast<uint8>(src));
 }
Index: src/mpt/base/pointer.hpp
===================================================================
--- src/mpt/base/pointer.hpp	(revision 23566)
+++ src/mpt/base/pointer.hpp	(working copy)
@@ -51,20 +51,20 @@
 private:
 	T * m_ptr = nullptr;
 public:
-	MPT_FORCEINLINE explicit void_ptr(void * ptr)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE explicit void_ptr(void * ptr)
 		: m_ptr(reinterpret_cast<T *>(ptr)) {
 		return;
 	}
-	MPT_FORCEINLINE T & operator*() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE T & operator*() {
 		return *m_ptr;
 	}
-	MPT_FORCEINLINE T * operator->() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE T * operator->() {
 		return m_ptr;
 	}
-	MPT_FORCEINLINE operator void *() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE operator void *() {
 		return m_ptr;
 	}
-	MPT_FORCEINLINE operator T *() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE operator T *() {
 		return m_ptr;
 	}
 };
Index: src/mpt/base/secure.hpp
===================================================================
--- src/mpt/base/secure.hpp	(revision 23566)
+++ src/mpt/base/secure.hpp	(working copy)
@@ -23,7 +23,7 @@
 
 
 // C23 memset_explicit
-inline MPT_NOINLINE void * memset_explicit(void * const dst, int const value, std::size_t const len) noexcept {
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE inline void * memset_explicit(void * const dst, int const value, std::size_t const len) noexcept {
 	std::atomic_thread_fence(std::memory_order_seq_cst);
 	volatile unsigned char * volatile p = static_cast<volatile unsigned char *>(dst);
 	std::atomic_thread_fence(std::memory_order_seq_cst);
@@ -40,7 +40,7 @@
 
 
 
-inline MPT_NOINLINE void memzero(std::byte * const dst, std::size_t const len) noexcept {
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE inline void memzero(std::byte * const dst, std::size_t const len) noexcept {
 	std::atomic_thread_fence(std::memory_order_seq_cst);
 	volatile std::byte * volatile p = static_cast<volatile std::byte *>(dst);
 	std::atomic_thread_fence(std::memory_order_seq_cst);
@@ -50,7 +50,7 @@
 	std::atomic_thread_fence(std::memory_order_seq_cst);
 }
 
-inline MPT_NOINLINE void memzero(void * const dst, std::size_t const len) noexcept {
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE inline void memzero(void * const dst, std::size_t const len) noexcept {
 	std::atomic_thread_fence(std::memory_order_seq_cst);
 	volatile std::byte * volatile p = static_cast<volatile std::byte *>(dst);
 	std::atomic_thread_fence(std::memory_order_seq_cst);
@@ -60,7 +60,7 @@
 	std::atomic_thread_fence(std::memory_order_seq_cst);
 }
 
-inline MPT_NOINLINE void memzero(char * const dst, std::size_t const len) noexcept {
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE inline void memzero(char * const dst, std::size_t const len) noexcept {
 	std::atomic_thread_fence(std::memory_order_seq_cst);
 	volatile std::byte * volatile p = reinterpret_cast<volatile std::byte *>(dst);
 	std::atomic_thread_fence(std::memory_order_seq_cst);
@@ -70,7 +70,7 @@
 	std::atomic_thread_fence(std::memory_order_seq_cst);
 }
 
-inline MPT_NOINLINE void memzero(uint8 * const dst, std::size_t const len) noexcept {
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE inline void memzero(uint8 * const dst, std::size_t const len) noexcept {
 	std::atomic_thread_fence(std::memory_order_seq_cst);
 	volatile std::byte * volatile p = reinterpret_cast<volatile std::byte *>(dst);
 	std::atomic_thread_fence(std::memory_order_seq_cst);
@@ -83,7 +83,7 @@
 
 
 template <typename T>
-inline MPT_NOINLINE void clear(T & val) {
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE inline void clear(T & val) {
 	std::atomic_signal_fence(std::memory_order_seq_cst);
 	volatile T * volatile v = &val;
 	std::atomic_thread_fence(std::memory_order_seq_cst);
Index: src/mpt/base/utility.hpp
===================================================================
--- src/mpt/base/utility.hpp	(revision 23566)
+++ src/mpt/base/utility.hpp	(working copy)
@@ -30,7 +30,7 @@
 
 
 template <typename Tdst, typename Tsrc>
-MPT_CONSTEXPRINLINE Tdst c_cast(Tsrc && x) {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr Tdst c_cast(Tsrc && x) {
 	return (Tdst)std::forward<Tsrc>(x);
 }
 
@@ -37,7 +37,7 @@
 
 
 template <typename Tdst, typename Tsrc>
-MPT_CONSTEXPRINLINE Tdst function_pointer_cast(Tsrc f) {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr Tdst function_pointer_cast(Tsrc f) {
 #if !defined(MPT_LIBCXX_QUIRK_INCOMPLETE_IS_FUNCTION)
 	// MinGW64 std::is_function is always false for non __cdecl functions.
 	// Issue is similar to <https://connect.microsoft.com/VisualStudio/feedback/details/774720/stl-is-function-bug>.
Index: src/mpt/endian/floatingpoint.hpp
===================================================================
--- src/mpt/endian/floatingpoint.hpp	(revision 23566)
+++ src/mpt/endian/floatingpoint.hpp	(working copy)
@@ -27,7 +27,7 @@
 
 
 // 1.0f --> 0x3f800000u
-MPT_FORCEINLINE uint32 EncodeIEEE754binary32(somefloat32 f) {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE uint32 EncodeIEEE754binary32(somefloat32 f) {
 	if constexpr (mpt::float_traits<somefloat32>::is_float32 && mpt::float_traits<somefloat32>::is_ieee754_binary && mpt::float_traits<somefloat32>::is_native_endian) {
 		return mpt::bit_cast<uint32>(f);
 	} else {
@@ -55,7 +55,7 @@
 	}
 }
 
-MPT_FORCEINLINE uint64 EncodeIEEE754binary64(somefloat64 f) {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE uint64 EncodeIEEE754binary64(somefloat64 f) {
 	if constexpr (mpt::float_traits<somefloat64>::is_float64 && mpt::float_traits<somefloat64>::is_ieee754_binary && mpt::float_traits<somefloat64>::is_native_endian) {
 		return mpt::bit_cast<uint64>(f);
 	} else {
@@ -84,7 +84,7 @@
 }
 
 // 0x3f800000u --> 1.0f
-MPT_FORCEINLINE somefloat32 DecodeIEEE754binary32(uint32 i) {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE somefloat32 DecodeIEEE754binary32(uint32 i) {
 	if constexpr (mpt::float_traits<somefloat32>::is_float32 && mpt::float_traits<somefloat32>::is_ieee754_binary && mpt::float_traits<somefloat32>::is_native_endian) {
 		return mpt::bit_cast<somefloat32>(i);
 	} else {
@@ -106,7 +106,7 @@
 	}
 }
 
-MPT_FORCEINLINE somefloat64 DecodeIEEE754binary64(uint64 i) {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE somefloat64 DecodeIEEE754binary64(uint64 i) {
 	if constexpr (mpt::float_traits<somefloat64>::is_float64 && mpt::float_traits<somefloat64>::is_ieee754_binary && mpt::float_traits<somefloat64>::is_native_endian) {
 		return mpt::bit_cast<somefloat64>(i);
 	} else {
@@ -137,14 +137,14 @@
 	std::byte bytes[4];
 
 public:
-	MPT_FORCEINLINE std::byte GetByte(std::size_t i) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::byte GetByte(std::size_t i) const {
 		return bytes[i];
 	}
 	IEEE754binary32Emulated() = default;
-	MPT_FORCEINLINE explicit IEEE754binary32Emulated(somefloat32 f) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE explicit IEEE754binary32Emulated(somefloat32 f) {
 		SetInt32(EncodeIEEE754binary32(f));
 	}
-	MPT_FORCEINLINE IEEE754binary32Emulated & operator=(somefloat32 f) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE IEEE754binary32Emulated & operator=(somefloat32 f) {
 		SetInt32(EncodeIEEE754binary32(f));
 		return *this;
 	}
@@ -151,23 +151,23 @@
 	// b0...b3 are in memory order, i.e. depend on the endianness of this type
 	// little endian: (0x00,0x00,0x80,0x3f)
 	// big endian:    (0x3f,0x80,0x00,0x00)
-	MPT_FORCEINLINE explicit IEEE754binary32Emulated(std::byte b0, std::byte b1, std::byte b2, std::byte b3) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE explicit IEEE754binary32Emulated(std::byte b0, std::byte b1, std::byte b2, std::byte b3) {
 		bytes[0] = b0;
 		bytes[1] = b1;
 		bytes[2] = b2;
 		bytes[3] = b3;
 	}
-	MPT_FORCEINLINE operator somefloat32() const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE operator somefloat32() const {
 		return DecodeIEEE754binary32(GetInt32());
 	}
-	MPT_FORCEINLINE self_t & set(somefloat32 f) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE self_t & set(somefloat32 f) {
 		SetInt32(EncodeIEEE754binary32(f));
 		return *this;
 	}
-	MPT_FORCEINLINE somefloat32 get() const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE somefloat32 get() const {
 		return DecodeIEEE754binary32(GetInt32());
 	}
-	MPT_FORCEINLINE self_t & SetInt32(uint32 i) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE self_t & SetInt32(uint32 i) {
 		bytes[hihi] = static_cast<std::byte>(i >> 24);
 		bytes[hilo] = static_cast<std::byte>(i >> 16);
 		bytes[lohi] = static_cast<std::byte>(i >> 8);
@@ -174,7 +174,7 @@
 		bytes[lolo] = static_cast<std::byte>(i >> 0);
 		return *this;
 	}
-	MPT_FORCEINLINE uint32 GetInt32() const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE uint32 GetInt32() const {
 		return 0u
 			 | (static_cast<uint32>(bytes[hihi]) << 24)
 			 | (static_cast<uint32>(bytes[hilo]) << 16)
@@ -181,7 +181,7 @@
 			 | (static_cast<uint32>(bytes[lohi]) << 8)
 			 | (static_cast<uint32>(bytes[lolo]) << 0);
 	}
-	MPT_FORCEINLINE bool operator==(const self_t & cmp) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool operator==(const self_t & cmp) const {
 		return true
 			&& bytes[0] == cmp.bytes[0]
 			&& bytes[1] == cmp.bytes[1]
@@ -188,7 +188,7 @@
 			&& bytes[2] == cmp.bytes[2]
 			&& bytes[3] == cmp.bytes[3];
 	}
-	MPT_FORCEINLINE bool operator!=(const self_t & cmp) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool operator!=(const self_t & cmp) const {
 		return !(*this == cmp);
 	}
 };
@@ -199,18 +199,18 @@
 	std::byte bytes[8];
 
 public:
-	MPT_FORCEINLINE std::byte GetByte(std::size_t i) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::byte GetByte(std::size_t i) const {
 		return bytes[i];
 	}
 	IEEE754binary64Emulated() = default;
-	MPT_FORCEINLINE explicit IEEE754binary64Emulated(somefloat64 f) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE explicit IEEE754binary64Emulated(somefloat64 f) {
 		SetInt64(EncodeIEEE754binary64(f));
 	}
-	MPT_FORCEINLINE IEEE754binary64Emulated & operator=(somefloat64 f) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE IEEE754binary64Emulated & operator=(somefloat64 f) {
 		SetInt64(EncodeIEEE754binary64(f));
 		return *this;
 	}
-	MPT_FORCEINLINE explicit IEEE754binary64Emulated(std::byte b0, std::byte b1, std::byte b2, std::byte b3, std::byte b4, std::byte b5, std::byte b6, std::byte b7) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE explicit IEEE754binary64Emulated(std::byte b0, std::byte b1, std::byte b2, std::byte b3, std::byte b4, std::byte b5, std::byte b6, std::byte b7) {
 		bytes[0] = b0;
 		bytes[1] = b1;
 		bytes[2] = b2;
@@ -220,17 +220,17 @@
 		bytes[6] = b6;
 		bytes[7] = b7;
 	}
-	MPT_FORCEINLINE operator somefloat64() const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE operator somefloat64() const {
 		return DecodeIEEE754binary64(GetInt64());
 	}
-	MPT_FORCEINLINE self_t & set(somefloat64 f) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE self_t & set(somefloat64 f) {
 		SetInt64(EncodeIEEE754binary64(f));
 		return *this;
 	}
-	MPT_FORCEINLINE somefloat64 get() const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE somefloat64 get() const {
 		return DecodeIEEE754binary64(GetInt64());
 	}
-	MPT_FORCEINLINE self_t & SetInt64(uint64 i) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE self_t & SetInt64(uint64 i) {
 		bytes[hihihi] = static_cast<std::byte>(i >> 56);
 		bytes[hihilo] = static_cast<std::byte>(i >> 48);
 		bytes[hilohi] = static_cast<std::byte>(i >> 40);
@@ -241,7 +241,7 @@
 		bytes[lololo] = static_cast<std::byte>(i >> 0);
 		return *this;
 	}
-	MPT_FORCEINLINE uint64 GetInt64() const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE uint64 GetInt64() const {
 		return 0u
 			 | (static_cast<uint64>(bytes[hihihi]) << 56)
 			 | (static_cast<uint64>(bytes[hihilo]) << 48)
@@ -252,7 +252,7 @@
 			 | (static_cast<uint64>(bytes[lolohi]) << 8)
 			 | (static_cast<uint64>(bytes[lololo]) << 0);
 	}
-	MPT_FORCEINLINE bool operator==(const self_t & cmp) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool operator==(const self_t & cmp) const {
 		return true
 			&& bytes[0] == cmp.bytes[0]
 			&& bytes[1] == cmp.bytes[1]
@@ -263,7 +263,7 @@
 			&& bytes[6] == cmp.bytes[6]
 			&& bytes[7] == cmp.bytes[7];
 	}
-	MPT_FORCEINLINE bool operator!=(const self_t & cmp) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool operator!=(const self_t & cmp) const {
 		return !(*this == cmp);
 	}
 };
@@ -297,7 +297,7 @@
 	somefloat32 value;
 
 public:
-	MPT_FORCEINLINE std::byte GetByte(std::size_t i) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::byte GetByte(std::size_t i) const {
 		static_assert(endian == mpt::endian::little || endian == mpt::endian::big);
 		if constexpr (endian == mpt::endian::little) {
 			return static_cast<std::byte>(EncodeIEEE754binary32(value) >> (i * 8));
@@ -307,10 +307,10 @@
 		}
 	}
 	IEEE754binary32Native() = default;
-	MPT_FORCEINLINE explicit IEEE754binary32Native(somefloat32 f) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE explicit IEEE754binary32Native(somefloat32 f) {
 		value = f;
 	}
-	MPT_FORCEINLINE IEEE754binary32Native & operator=(somefloat32 f) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE IEEE754binary32Native & operator=(somefloat32 f) {
 		value = f;
 		return *this;
 	}
@@ -317,7 +317,7 @@
 	// b0...b3 are in memory order, i.e. depend on the endianness of this type
 	// little endian: (0x00,0x00,0x80,0x3f)
 	// big endian:    (0x3f,0x80,0x00,0x00)
-	MPT_FORCEINLINE explicit IEEE754binary32Native(std::byte b0, std::byte b1, std::byte b2, std::byte b3) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE explicit IEEE754binary32Native(std::byte b0, std::byte b1, std::byte b2, std::byte b3) {
 		static_assert(endian == mpt::endian::little || endian == mpt::endian::big);
 		if constexpr (endian == mpt::endian::little) {
 			value = DecodeIEEE754binary32(0u | (static_cast<uint32>(b0) << 0) | (static_cast<uint32>(b1) << 8) | (static_cast<uint32>(b2) << 16) | (static_cast<uint32>(b3) << 24));
@@ -326,27 +326,27 @@
 			value = DecodeIEEE754binary32(0u | (static_cast<uint32>(b0) << 24) | (static_cast<uint32>(b1) << 16) | (static_cast<uint32>(b2) << 8) | (static_cast<uint32>(b3) << 0));
 		}
 	}
-	MPT_FORCEINLINE operator somefloat32() const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE operator somefloat32() const {
 		return value;
 	}
-	MPT_FORCEINLINE IEEE754binary32Native & set(somefloat32 f) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE IEEE754binary32Native & set(somefloat32 f) {
 		value = f;
 		return *this;
 	}
-	MPT_FORCEINLINE somefloat32 get() const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE somefloat32 get() const {
 		return value;
 	}
-	MPT_FORCEINLINE IEEE754binary32Native & SetInt32(uint32 i) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE IEEE754binary32Native & SetInt32(uint32 i) {
 		value = DecodeIEEE754binary32(i);
 		return *this;
 	}
-	MPT_FORCEINLINE uint32 GetInt32() const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE uint32 GetInt32() const {
 		return EncodeIEEE754binary32(value);
 	}
-	MPT_FORCEINLINE bool operator==(const IEEE754binary32Native & cmp) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool operator==(const IEEE754binary32Native & cmp) const {
 		return value == cmp.value;
 	}
-	MPT_FORCEINLINE bool operator!=(const IEEE754binary32Native & cmp) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool operator!=(const IEEE754binary32Native & cmp) const {
 		return value != cmp.value;
 	}
 };
@@ -357,7 +357,7 @@
 	somefloat64 value;
 
 public:
-	MPT_FORCEINLINE std::byte GetByte(std::size_t i) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE std::byte GetByte(std::size_t i) const {
 		static_assert(endian == mpt::endian::little || endian == mpt::endian::big);
 		if constexpr (endian == mpt::endian::little) {
 			return mpt::byte_cast<std::byte>(static_cast<uint8>(EncodeIEEE754binary64(value) >> (i * 8)));
@@ -367,14 +367,14 @@
 		}
 	}
 	IEEE754binary64Native() = default;
-	MPT_FORCEINLINE explicit IEEE754binary64Native(somefloat64 f) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE explicit IEEE754binary64Native(somefloat64 f) {
 		value = f;
 	}
-	MPT_FORCEINLINE IEEE754binary64Native & operator=(somefloat64 f) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE IEEE754binary64Native & operator=(somefloat64 f) {
 		value = f;
 		return *this;
 	}
-	MPT_FORCEINLINE explicit IEEE754binary64Native(std::byte b0, std::byte b1, std::byte b2, std::byte b3, std::byte b4, std::byte b5, std::byte b6, std::byte b7) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE explicit IEEE754binary64Native(std::byte b0, std::byte b1, std::byte b2, std::byte b3, std::byte b4, std::byte b5, std::byte b6, std::byte b7) {
 		static_assert(endian == mpt::endian::little || endian == mpt::endian::big);
 		if constexpr (endian == mpt::endian::little) {
 			value = DecodeIEEE754binary64(0ull | (static_cast<uint64>(b0) << 0) | (static_cast<uint64>(b1) << 8) | (static_cast<uint64>(b2) << 16) | (static_cast<uint64>(b3) << 24) | (static_cast<uint64>(b4) << 32) | (static_cast<uint64>(b5) << 40) | (static_cast<uint64>(b6) << 48) | (static_cast<uint64>(b7) << 56));
@@ -383,27 +383,27 @@
 			value = DecodeIEEE754binary64(0ull | (static_cast<uint64>(b0) << 56) | (static_cast<uint64>(b1) << 48) | (static_cast<uint64>(b2) << 40) | (static_cast<uint64>(b3) << 32) | (static_cast<uint64>(b4) << 24) | (static_cast<uint64>(b5) << 16) | (static_cast<uint64>(b6) << 8) | (static_cast<uint64>(b7) << 0));
 		}
 	}
-	MPT_FORCEINLINE operator somefloat64() const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE operator somefloat64() const {
 		return value;
 	}
-	MPT_FORCEINLINE IEEE754binary64Native & set(somefloat64 f) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE IEEE754binary64Native & set(somefloat64 f) {
 		value = f;
 		return *this;
 	}
-	MPT_FORCEINLINE somefloat64 get() const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE somefloat64 get() const {
 		return value;
 	}
-	MPT_FORCEINLINE IEEE754binary64Native & SetInt64(uint64 i) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE IEEE754binary64Native & SetInt64(uint64 i) {
 		value = DecodeIEEE754binary64(i);
 		return *this;
 	}
-	MPT_FORCEINLINE uint64 GetInt64() const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE uint64 GetInt64() const {
 		return EncodeIEEE754binary64(value);
 	}
-	MPT_FORCEINLINE bool operator==(const IEEE754binary64Native & cmp) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool operator==(const IEEE754binary64Native & cmp) const {
 		return value == cmp.value;
 	}
-	MPT_FORCEINLINE bool operator!=(const IEEE754binary64Native & cmp) const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE bool operator!=(const IEEE754binary64Native & cmp) const {
 		return value != cmp.value;
 	}
 };
Index: src/mpt/endian/int24.hpp
===================================================================
--- src/mpt/endian/int24.hpp	(revision 23566)
+++ src/mpt/endian/int24.hpp	(working copy)
@@ -107,7 +107,7 @@
 
 
 template <typename base_type, mpt::endian endian, typename int_type = base_type>
-MPT_CONSTEXPRINLINE std::array<std::byte, sizeof(base_type)> EndianEncode24(base_type val) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr std::array<std::byte, sizeof(base_type)> EndianEncode24(base_type val) noexcept {
 	static_assert(std::is_same<base_type, int24>::value || std::is_same<base_type, uint24>::value);
 	static_assert(endian == mpt::endian::little || endian == mpt::endian::big);
 	static_assert(std::numeric_limits<int_type>::is_integer);
@@ -123,7 +123,7 @@
 }
 
 template <typename base_type, mpt::endian endian, typename int_type = base_type>
-MPT_CONSTEXPRINLINE base_type EndianDecode24(std::array<std::byte, sizeof(base_type)> data) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr base_type EndianDecode24(std::array<std::byte, sizeof(base_type)> data) noexcept {
 	static_assert(std::is_same<base_type, int24>::value || std::is_same<base_type, uint24>::value);
 	static_assert(endian == mpt::endian::little || endian == mpt::endian::big);
 	static_assert(std::numeric_limits<int_type>::is_integer);
@@ -141,36 +141,36 @@
 
 
 template <>
-MPT_CONSTEXPRINLINE std::array<std::byte, 3> EndianEncode<int24, mpt::endian::little, int32>(int24 val) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr std::array<std::byte, 3> EndianEncode<int24, mpt::endian::little, int32>(int24 val) noexcept {
 	return mpt::EndianEncode24<int24, mpt::endian::little, int32>(val);
 }
 template <>
-MPT_CONSTEXPRINLINE int24 EndianDecode<int24, mpt::endian::little, int32>(std::array<std::byte, 3> data) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr int24 EndianDecode<int24, mpt::endian::little, int32>(std::array<std::byte, 3> data) noexcept {
 	return mpt::EndianDecode24<int24, mpt::endian::little, int32>(data);
 }
 template <>
-MPT_CONSTEXPRINLINE std::array<std::byte, 3> EndianEncode<int24, mpt::endian::big, int32>(int24 val) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr std::array<std::byte, 3> EndianEncode<int24, mpt::endian::big, int32>(int24 val) noexcept {
 	return mpt::EndianEncode24<int24, mpt::endian::big, int32>(val);
 }
 template <>
-MPT_CONSTEXPRINLINE int24 EndianDecode<int24, mpt::endian::big, int32>(std::array<std::byte, 3> data) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr int24 EndianDecode<int24, mpt::endian::big, int32>(std::array<std::byte, 3> data) noexcept {
 	return mpt::EndianDecode24<int24, mpt::endian::big, int32>(data);
 }
 
 template <>
-MPT_CONSTEXPRINLINE std::array<std::byte, 3> EndianEncode<uint24, mpt::endian::little, uint32>(uint24 val) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr std::array<std::byte, 3> EndianEncode<uint24, mpt::endian::little, uint32>(uint24 val) noexcept {
 	return mpt::EndianEncode24<uint24, mpt::endian::little, uint32>(val);
 }
 template <>
-MPT_CONSTEXPRINLINE uint24 EndianDecode<uint24, mpt::endian::little, uint32>(std::array<std::byte, 3> data) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint24 EndianDecode<uint24, mpt::endian::little, uint32>(std::array<std::byte, 3> data) noexcept {
 	return mpt::EndianDecode24<uint24, mpt::endian::little, uint32>(data);
 }
 template <>
-MPT_CONSTEXPRINLINE std::array<std::byte, 3> EndianEncode<uint24, mpt::endian::big, uint32>(uint24 val) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr std::array<std::byte, 3> EndianEncode<uint24, mpt::endian::big, uint32>(uint24 val) noexcept {
 	return mpt::EndianEncode24<uint24, mpt::endian::big, uint32>(val);
 }
 template <>
-MPT_CONSTEXPRINLINE uint24 EndianDecode<uint24, mpt::endian::big, uint32>(std::array<std::byte, 3> data) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint24 EndianDecode<uint24, mpt::endian::big, uint32>(std::array<std::byte, 3> data) noexcept {
 	return mpt::EndianDecode24<uint24, mpt::endian::big, uint32>(data);
 }
 
Index: src/mpt/endian/integer.hpp
===================================================================
--- src/mpt/endian/integer.hpp	(revision 23566)
+++ src/mpt/endian/integer.hpp	(working copy)
@@ -29,7 +29,7 @@
 
 
 template <typename base_type, mpt::endian endian, typename int_type = base_type>
-MPT_CONSTEXPRINLINE std::array<std::byte, sizeof(base_type)> EndianEncodeImpl(base_type val) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr std::array<std::byte, sizeof(base_type)> EndianEncodeImpl(base_type val) noexcept {
 	static_assert(endian == mpt::endian::little || endian == mpt::endian::big);
 	static_assert(std::numeric_limits<int_type>::is_integer);
 	using unsigned_int_type = typename std::make_unsigned<int_type>::type;
@@ -48,12 +48,12 @@
 }
 
 template <typename base_type, mpt::endian endian, typename int_type = base_type>
-MPT_CONSTEXPRINLINE std::array<std::byte, sizeof(base_type)> EndianEncode(base_type val) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr std::array<std::byte, sizeof(base_type)> EndianEncode(base_type val) noexcept {
 	return EndianEncodeImpl<base_type, endian, int_type>(val);
 }
 
 template <typename base_type, mpt::endian endian, typename int_type = base_type>
-MPT_CONSTEXPRINLINE base_type EndianDecodeImpl(std::array<std::byte, sizeof(base_type)> data) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr base_type EndianDecodeImpl(std::array<std::byte, sizeof(base_type)> data) noexcept {
 	static_assert(endian == mpt::endian::little || endian == mpt::endian::big);
 	static_assert(std::numeric_limits<int_type>::is_integer);
 	using unsigned_int_type = typename std::make_unsigned<int_type>::type;
@@ -73,7 +73,7 @@
 }
 
 template <typename base_type, mpt::endian endian, typename int_type = base_type>
-MPT_CONSTEXPRINLINE base_type EndianDecode(std::array<std::byte, sizeof(base_type)> data) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr base_type EndianDecode(std::array<std::byte, sizeof(base_type)> data) noexcept {
 	return EndianDecodeImpl<base_type, endian, int_type>(data);
 }
 
@@ -99,7 +99,7 @@
 	std::array<std::byte, sizeof(base_type)> data;
 
 public:
-	MPT_CONSTEXPR20_FUN void set(base_type val) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN void set(base_type val) noexcept {
 		static_assert(std::numeric_limits<int_type>::is_integer);
 		MPT_MAYBE_CONSTANT_IF (MPT_IS_CONSTANT_EVALUATED20()) {
 			if constexpr (endian == mpt::endian::big) {
@@ -124,7 +124,7 @@
 			}
 		}
 	}
-	MPT_CONSTEXPR20_FUN base_type get() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN base_type get() const noexcept {
 		static_assert(std::numeric_limits<int_type>::is_integer);
 		MPT_MAYBE_CONSTANT_IF (MPT_IS_CONSTANT_EVALUATED20()) {
 			if constexpr (endian == mpt::endian::big) {
@@ -153,61 +153,61 @@
 			}
 		}
 	}
-	MPT_CONSTEXPR20_FUN packed & operator=(const base_type & val) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN packed & operator=(const base_type & val) noexcept {
 		set(val);
 		return *this;
 	}
-	MPT_CONSTEXPR20_FUN operator base_type() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN operator base_type() const noexcept {
 		return get();
 	}
 
 public:
-	MPT_CONSTEXPR20_FUN packed & operator&=(base_type val) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN packed & operator&=(base_type val) noexcept {
 		set(get() & val);
 		return *this;
 	}
-	MPT_CONSTEXPR20_FUN packed & operator|=(base_type val) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN packed & operator|=(base_type val) noexcept {
 		set(get() | val);
 		return *this;
 	}
-	MPT_CONSTEXPR20_FUN packed & operator^=(base_type val) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN packed & operator^=(base_type val) noexcept {
 		set(get() ^ val);
 		return *this;
 	}
-	MPT_CONSTEXPR20_FUN packed & operator+=(base_type val) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN packed & operator+=(base_type val) noexcept {
 		set(get() + val);
 		return *this;
 	}
-	MPT_CONSTEXPR20_FUN packed & operator-=(base_type val) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN packed & operator-=(base_type val) noexcept {
 		set(get() - val);
 		return *this;
 	}
-	MPT_CONSTEXPR20_FUN packed & operator*=(base_type val) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN packed & operator*=(base_type val) noexcept {
 		set(get() * val);
 		return *this;
 	}
-	MPT_CONSTEXPR20_FUN packed & operator/=(base_type val) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN packed & operator/=(base_type val) noexcept {
 		set(get() / val);
 		return *this;
 	}
-	MPT_CONSTEXPR20_FUN packed & operator%=(base_type val) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN packed & operator%=(base_type val) noexcept {
 		set(get() % val);
 		return *this;
 	}
-	MPT_CONSTEXPR20_FUN packed & operator++() noexcept { // prefix
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN packed & operator++() noexcept { // prefix
 		set(get() + 1);
 		return *this;
 	}
-	MPT_CONSTEXPR20_FUN packed & operator--() noexcept { // prefix
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN packed & operator--() noexcept { // prefix
 		set(get() - 1);
 		return *this;
 	}
-	MPT_CONSTEXPR20_FUN base_type operator++(int) noexcept { // postfix
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN base_type operator++(int) noexcept { // postfix
 		base_type old = get();
 		set(old + 1);
 		return old;
 	}
-	MPT_CONSTEXPR20_FUN base_type operator--(int) noexcept { // postfix
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN base_type operator--(int) noexcept { // postfix
 		base_type old = get();
 		set(old - 1);
 		return old;
@@ -315,7 +315,7 @@
 
 
 template <typename T>
-MPT_CONSTEXPR20_FUN auto as_le(T v) noexcept -> typename mpt::make_le<typename std::remove_const<T>::type>::type {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN auto as_le(T v) noexcept -> typename mpt::make_le<typename std::remove_const<T>::type>::type {
 	typename mpt::make_le<typename std::remove_const<T>::type>::type res{};
 	res = v;
 	return res;
@@ -322,7 +322,7 @@
 }
 
 template <typename T>
-MPT_CONSTEXPR20_FUN auto as_be(T v) noexcept -> typename mpt::make_be<typename std::remove_const<T>::type>::type {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN auto as_be(T v) noexcept -> typename mpt::make_be<typename std::remove_const<T>::type>::type {
 	typename mpt::make_be<typename std::remove_const<T>::type>::type res{};
 	res = v;
 	return res;
@@ -331,7 +331,7 @@
 
 
 template <typename Tpacked>
-MPT_CONSTEXPR20_FUN Tpacked as_endian(typename Tpacked::base_type v) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN Tpacked as_endian(typename Tpacked::base_type v) noexcept {
 	Tpacked res{};
 	res = v;
 	return res;
Index: src/mpt/endian/tests/tests_endian_integer.hpp
===================================================================
--- src/mpt/endian/tests/tests_endian_integer.hpp	(revision 23566)
+++ src/mpt/endian/tests/tests_endian_integer.hpp	(working copy)
@@ -62,7 +62,7 @@
 	static_assert(std::numeric_limits<uint64le>::max() == std::numeric_limits<uint64>::max());
 
 	struct test_endian_constexpr {
-		static MPT_CONSTEXPR20_FUN int32le test(uint32 x) {
+		MPT_ATTR_ALWAYSINLINE MPT_CONSTEXPR20_FUN static int32le test(uint32 x) {
 			int32le foo{};
 			foo = x;
 			return foo;
Index: src/mpt/format/message.hpp
===================================================================
--- src/mpt/format/message.hpp	(revision 23566)
+++ src/mpt/format/message.hpp	(working copy)
@@ -43,7 +43,7 @@
 	Tstring format;
 
 private:
-	MPT_NOINLINE Tstring do_format(const mpt::span<const Tstring> vals) const {
+	MPT_ATTR_NOINLINE MPT_DECL_NOINLINE Tstring do_format(const mpt::span<const Tstring> vals) const {
 		using traits = typename mpt::string_traits<Tstring>;
 		using char_type = typename traits::char_type;
 		using size_type = typename traits::size_type;
@@ -161,13 +161,13 @@
 	}
 
 public:
-	MPT_FORCEINLINE message_formatter(Tstring format_)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE message_formatter(Tstring format_)
 		: format(std::move(format_)) {
 	}
 
 public:
 	template <typename... Ts>
-	MPT_NOINLINE Tstring operator()(Ts &&... xs) const {
+	MPT_ATTR_NOINLINE MPT_DECL_NOINLINE Tstring operator()(Ts &&... xs) const {
 		const std::array<Tstring, sizeof...(xs)> vals{{Tformatter::template format<Tstring>(std::forward<Ts>(xs))...}};
 		return do_format(mpt::as_span(vals));
 	}
@@ -202,7 +202,7 @@
 
 
 template <typename Tchar>
-MPT_CONSTEXPRINLINE std::ptrdiff_t parse_format_string_argument_count_impl(const Tchar * const format, const std::size_t len) {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr std::ptrdiff_t parse_format_string_argument_count_impl(const Tchar * const format, const std::size_t len) {
 	std::size_t max_arg = 0;
 	std::size_t args = 0;
 	bool success = true;
@@ -309,7 +309,7 @@
 
 
 template <typename Tchar, std::size_t literal_length>
-MPT_CONSTEXPRINLINE std::ptrdiff_t parse_format_string_argument_count(const Tchar (&format)[literal_length]) {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr std::ptrdiff_t parse_format_string_argument_count(const Tchar (&format)[literal_length]) {
 	return parse_format_string_argument_count_impl(format, literal_length - 1);
 }
 
Index: src/mpt/format/simple_spec.hpp
===================================================================
--- src/mpt/format/simple_spec.hpp	(revision 23566)
+++ src/mpt/format/simple_spec.hpp	(working copy)
@@ -49,169 +49,169 @@
 	unsigned int group; // int
 	Tstring group_sep;  // int
 public:
-	MPT_CONSTEXPRINLINE format_simple_spec() noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec() noexcept
 		: flags(0)
 		, width(0)
 		, precision(-1)
 		, group(0)
 		, group_sep() { }
-	MPT_CONSTEXPRINLINE format_simple_flags GetFlags() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_flags GetFlags() const noexcept {
 		return flags;
 	}
-	MPT_CONSTEXPRINLINE std::size_t GetWidth() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr std::size_t GetWidth() const noexcept {
 		return width;
 	}
-	MPT_CONSTEXPRINLINE int GetPrecision() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr int GetPrecision() const noexcept {
 		return precision;
 	}
-	MPT_CONSTEXPRINLINE unsigned int GetGroup() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr unsigned int GetGroup() const noexcept {
 		return group;
 	}
-	MPT_CONSTEXPRINLINE Tstring GetGroupSep() const {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr Tstring GetGroupSep() const {
 		return group_sep;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & SetFlags(format_simple_flags f) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & SetFlags(format_simple_flags f) noexcept {
 		flags = f;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & SetWidth(std::size_t w) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & SetWidth(std::size_t w) noexcept {
 		width = w;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & SetPrecision(int p) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & SetPrecision(int p) noexcept {
 		precision = p;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & SetGroup(unsigned int g) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & SetGroup(unsigned int g) noexcept {
 		group = g;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & SetGroupSep(Tstring s) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & SetGroupSep(Tstring s) {
 		group_sep = std::move(s);
 		return *this;
 	}
 
 public:
-	MPT_CONSTEXPRINLINE format_simple_spec & BaseDec() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & BaseDec() noexcept {
 		flags &= ~(format_simple_base::BaseDec | format_simple_base::BaseHex);
 		flags |= format_simple_base::BaseDec;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & BaseHex() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & BaseHex() noexcept {
 		flags &= ~(format_simple_base::BaseDec | format_simple_base::BaseHex);
 		flags |= format_simple_base::BaseHex;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & CaseLow() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & CaseLow() noexcept {
 		flags &= ~(format_simple_base::CaseLow | format_simple_base::CaseUpp);
 		flags |= format_simple_base::CaseLow;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & CaseUpp() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & CaseUpp() noexcept {
 		flags &= ~(format_simple_base::CaseLow | format_simple_base::CaseUpp);
 		flags |= format_simple_base::CaseUpp;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & FillOff() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & FillOff() noexcept {
 		flags &= ~(format_simple_base::FillOff | format_simple_base::FillNul);
 		flags |= format_simple_base::FillOff;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & FillNul() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & FillNul() noexcept {
 		flags &= ~(format_simple_base::FillOff | format_simple_base::FillNul);
 		flags |= format_simple_base::FillNul;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & NotaNrm() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & NotaNrm() noexcept {
 		flags &= ~(format_simple_base::NotaNrm | format_simple_base::NotaFix | format_simple_base::NotaSci);
 		flags |= format_simple_base::NotaNrm;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & NotaFix() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & NotaFix() noexcept {
 		flags &= ~(format_simple_base::NotaNrm | format_simple_base::NotaFix | format_simple_base::NotaSci);
 		flags |= format_simple_base::NotaFix;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & NotaSci() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & NotaSci() noexcept {
 		flags &= ~(format_simple_base::NotaNrm | format_simple_base::NotaFix | format_simple_base::NotaSci);
 		flags |= format_simple_base::NotaSci;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & Width(std::size_t w) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Width(std::size_t w) noexcept {
 		width = w;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & Prec(int p) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Prec(int p) noexcept {
 		precision = p;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & Group(unsigned int g) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Group(unsigned int g) noexcept {
 		group = g;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & GroupSep(Tstring s) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & GroupSep(Tstring s) {
 		group_sep = std::move(s);
 		return *this;
 	}
 
 public:
-	MPT_CONSTEXPRINLINE format_simple_spec & Dec() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Dec() noexcept {
 		return BaseDec();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & Hex() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Hex() noexcept {
 		return BaseHex();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & Low() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Low() noexcept {
 		return CaseLow();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & Upp() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Upp() noexcept {
 		return CaseUpp();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & Off() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Off() noexcept {
 		return FillOff();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & Nul() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Nul() noexcept {
 		return FillNul();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & Nrm() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Nrm() noexcept {
 		return NotaNrm();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & Fix() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Fix() noexcept {
 		return NotaFix();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & Sci() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Sci() noexcept {
 		return NotaSci();
 	}
 
 public:
-	MPT_CONSTEXPRINLINE format_simple_spec & Decimal() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Decimal() noexcept {
 		return BaseDec();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & Hexadecimal() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Hexadecimal() noexcept {
 		return BaseHex();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & Lower() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Lower() noexcept {
 		return CaseLow();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & Upper() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Upper() noexcept {
 		return CaseUpp();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & FillNone() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & FillNone() noexcept {
 		return FillOff();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & FillZero() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & FillZero() noexcept {
 		return FillNul();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & FloatNormal() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & FloatNormal() noexcept {
 		return NotaNrm();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & FloatFixed() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & FloatFixed() noexcept {
 		return NotaFix();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & FloatScientific() noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & FloatScientific() noexcept {
 		return NotaSci();
 	}
-	MPT_CONSTEXPRINLINE format_simple_spec & Precision(int p) noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr format_simple_spec & Precision(int p) noexcept {
 		return Prec(p);
 	}
 };
Index: src/mpt/path/basic_path.hpp
===================================================================
--- src/mpt/path/basic_path.hpp	(revision 23566)
+++ src/mpt/path/basic_path.hpp	(working copy)
@@ -32,12 +32,12 @@
 struct literals;
 
 template <typename Tchar>
-MPT_CONSTEVAL Tchar L(char x) {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL Tchar L(char x) {
 	return path_literals::literals<Tchar>::L(x);
 }
 
 template <typename Tchar, std::size_t N>
-MPT_CONSTEVAL const Tchar * L(const char (&x)[N]) {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL const Tchar * L(const char (&x)[N]) {
 	return path_literals::literals<Tchar>::L(x);
 }
 
@@ -44,7 +44,7 @@
 template <>
 struct literals<char> {
 	using char_type = char;
-	static MPT_CONSTEVAL char_type L(char c) {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL static char_type L(char c) {
 		if (c == '\0')
 			return '\0';
 		if (c == '\\')
@@ -77,7 +77,7 @@
 #endif
 	}
 	template <std::size_t N>
-	static MPT_CONSTEVAL const char_type * L(const char (&s)[N]) {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL static const char_type * L(const char (&s)[N]) {
 		if (std::string_view(s) == std::string_view(""))
 			return "";
 		if (std::string_view(s) == std::string_view("/"))
@@ -119,7 +119,7 @@
 template <>
 struct literals<wchar_t> {
 	using char_type = wchar_t;
-	static MPT_CONSTEVAL char_type L(char c) {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL static char_type L(char c) {
 		if (c == '\0')
 			return L'\0';
 		if (c == '\\')
@@ -152,7 +152,7 @@
 #endif
 	}
 	template <std::size_t N>
-	static MPT_CONSTEVAL const char_type * L(const char (&s)[N]) {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL static const char_type * L(const char (&s)[N]) {
 		if (std::string_view(s) == std::string_view(""))
 			return L"";
 		if (std::string_view(s) == std::string_view("/"))
@@ -195,7 +195,7 @@
 template <>
 struct literals<char8_t> {
 	using char_type = char8_t;
-	static MPT_CONSTEVAL char_type L(char c) {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL static char_type L(char c) {
 		if (c == '\0')
 			return u8'\0';
 		if (c == '\\')
@@ -228,7 +228,7 @@
 #endif
 	}
 	template <std::size_t N>
-	static MPT_CONSTEVAL const char_type * L(const char (&s)[N]) {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL static const char_type * L(const char (&s)[N]) {
 		if (std::string_view(s) == std::string_view(""))
 			return u8"";
 		if (std::string_view(s) == std::string_view("/"))
@@ -270,7 +270,7 @@
 template <>
 struct literals<char16_t> {
 	using char_type = char16_t;
-	static MPT_CONSTEVAL char_type L(char c) {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL static char_type L(char c) {
 		if (c == '\0')
 			return u'\0';
 		if (c == '\\')
@@ -303,7 +303,7 @@
 #endif
 	}
 	template <std::size_t N>
-	static MPT_CONSTEVAL const char_type * L(const char (&s)[N]) {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL static const char_type * L(const char (&s)[N]) {
 		if (std::string_view(s) == std::string_view(""))
 			return u"";
 		if (std::string_view(s) == std::string_view("/"))
@@ -344,7 +344,7 @@
 template <>
 struct literals<char32_t> {
 	using char_type = char32_t;
-	static MPT_CONSTEVAL char_type L(char c) {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL static char_type L(char c) {
 		if (c == '\0')
 			return U'\0';
 		if (c == '\\')
@@ -377,7 +377,7 @@
 #endif
 	}
 	template <std::size_t N>
-	static MPT_CONSTEVAL const char_type * L(const char (&s)[N]) {
+	MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL static const char_type * L(const char (&s)[N]) {
 		if (std::string_view(s) == std::string_view(""))
 			return U"";
 		if (std::string_view(s) == std::string_view("/"))
Index: src/mpt/random/any_engine.hpp
===================================================================
--- src/mpt/random/any_engine.hpp	(revision 23566)
+++ src/mpt/random/any_engine.hpp	(working copy)
@@ -26,13 +26,13 @@
 protected:
 	any_engine() = default;
 public:
-	static MPT_CONSTEXPRINLINE result_type min() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static result_type min() {
 		return static_cast<result_type>(std::numeric_limits<result_type>::min());
 	}
-	static MPT_CONSTEXPRINLINE result_type max() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static result_type max() {
 		return static_cast<result_type>(std::numeric_limits<result_type>::max());
 	}
-	static MPT_CONSTEXPRINLINE int result_bits() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static int result_bits() {
 		return static_cast<int>(sizeof(result_type) * 8);
 	}
 public:
Index: src/mpt/random/crand.hpp
===================================================================
--- src/mpt/random/crand.hpp	(revision 23566)
+++ src/mpt/random/crand.hpp	(working copy)
@@ -41,13 +41,13 @@
 	}
 
 public:
-	static MPT_CONSTEXPRINLINE result_type min() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static result_type min() {
 		return 0;
 	}
-	static MPT_CONSTEXPRINLINE result_type max() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static result_type max() {
 		return RAND_MAX;
 	}
-	static MPT_CONSTEXPRINLINE int result_bits() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static int result_bits() {
 		return mpt::lower_bound_entropy_bits(RAND_MAX);
 	}
 	result_type operator()() {
Index: src/mpt/random/device.hpp
===================================================================
--- src/mpt/random/device.hpp	(revision 23566)
+++ src/mpt/random/device.hpp	(working copy)
@@ -193,13 +193,13 @@
 		init_fallback();
 #endif // !MPT_COMPILER_QUIRK_RANDOM_NO_RANDOM_DEVICE
 	}
-	static MPT_CONSTEXPRINLINE result_type min() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static result_type min() {
 		return std::numeric_limits<result_type>::min();
 	}
-	static MPT_CONSTEXPRINLINE result_type max() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static result_type max() {
 		return std::numeric_limits<result_type>::max();
 	}
-	static MPT_CONSTEXPRINLINE int result_bits() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static int result_bits() {
 		return sizeof(result_type) * 8;
 	}
 	result_type operator()() {
@@ -287,13 +287,13 @@
 		: rng(seeder::template generate_seed<typename Trng::state_type>()) {
 		return;
 	}
-	static MPT_CONSTEXPRINLINE result_type min() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static result_type min() {
 		return std::numeric_limits<unsigned int>::min();
 	}
-	static MPT_CONSTEXPRINLINE result_type max() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static result_type max() {
 		return std::numeric_limits<unsigned int>::max();
 	}
-	static MPT_CONSTEXPRINLINE int result_bits() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static int result_bits() {
 		return sizeof(unsigned int) * 8;
 	}
 	result_type operator()() {
Index: src/mpt/random/engine.hpp
===================================================================
--- src/mpt/random/engine.hpp	(revision 23566)
+++ src/mpt/random/engine.hpp	(working copy)
@@ -25,7 +25,7 @@
 template <typename Trng>
 struct engine_traits {
 	using result_type = typename Trng::result_type;
-	static MPT_CONSTEXPRINLINE int result_bits() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static int result_bits() {
 		return Trng::result_bits();
 	}
 };
@@ -43,7 +43,7 @@
 struct engine_traits<std::mt19937> {
 	using rng_type = std::mt19937;
 	using result_type = rng_type::result_type;
-	static MPT_CONSTEXPRINLINE int result_bits() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static int result_bits() {
 		return rng_type::word_size;
 	}
 };
@@ -57,7 +57,7 @@
 struct engine_traits<std::mt19937_64> {
 	using rng_type = std::mt19937_64;
 	using result_type = rng_type::result_type;
-	static MPT_CONSTEXPRINLINE int result_bits() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static int result_bits() {
 		return rng_type::word_size;
 	}
 };
@@ -71,7 +71,7 @@
 struct engine_traits<std::ranlux24_base> {
 	using rng_type = std::ranlux24_base;
 	using result_type = rng_type::result_type;
-	static MPT_CONSTEXPRINLINE int result_bits() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static int result_bits() {
 		return rng_type::word_size;
 	}
 };
@@ -85,7 +85,7 @@
 struct engine_traits<std::ranlux48_base> {
 	using rng_type = std::ranlux48_base;
 	using result_type = rng_type::result_type;
-	static MPT_CONSTEXPRINLINE int result_bits() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static int result_bits() {
 		return rng_type::word_size;
 	}
 };
@@ -99,7 +99,7 @@
 struct engine_traits<std::ranlux24> {
 	using rng_type = std::ranlux24;
 	using result_type = rng_type::result_type;
-	static MPT_CONSTEXPRINLINE int result_bits() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static int result_bits() {
 		return std::ranlux24_base::word_size;
 	}
 };
@@ -113,7 +113,7 @@
 struct engine_traits<std::ranlux48> {
 	using rng_type = std::ranlux48;
 	using result_type = rng_type::result_type;
-	static MPT_CONSTEXPRINLINE int result_bits() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static int result_bits() {
 		return std::ranlux48_base::word_size;
 	}
 };
Index: src/mpt/random/engine_lcg.hpp
===================================================================
--- src/mpt/random/engine_lcg.hpp	(revision 23566)
+++ src/mpt/random/engine_lcg.hpp	(working copy)
@@ -61,14 +61,14 @@
 	}
 
 public:
-	static MPT_CONSTEXPRINLINE result_type min() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static result_type min() {
 		return static_cast<result_type>(0);
 	}
-	static MPT_CONSTEXPRINLINE result_type max() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static result_type max() {
 		static_assert(((result_mask >> result_shift) << result_shift) == result_mask);
 		return static_cast<result_type>(result_mask >> result_shift);
 	}
-	static MPT_CONSTEXPRINLINE int result_bits() {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static int result_bits() {
 		static_assert(((static_cast<Tstate>(1) << result_bits_) - 1) == (result_mask >> result_shift));
 		return result_bits_;
 	}
Index: src/mpt/string/types.hpp
===================================================================
--- src/mpt/string/types.hpp	(revision 23566)
+++ src/mpt/string/types.hpp	(working copy)
@@ -107,7 +107,7 @@
 
 
 template <typename T, typename std::enable_if<mpt::is_character<T>::value, bool>::type = true>
-MPT_CONSTEXPRINLINE typename std::make_unsigned<T>::type char_value(T x) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr typename std::make_unsigned<T>::type char_value(T x) noexcept {
 	return static_cast<typename std::make_unsigned<T>::type>(x);
 }
 
Index: src/mpt/uuid/uuid.hpp
===================================================================
--- src/mpt/uuid/uuid.hpp	(revision 23566)
+++ src/mpt/uuid/uuid.hpp	(working copy)
@@ -66,24 +66,24 @@
 	uint64 Data4;
 
 public:
-	MPT_CONSTEXPRINLINE uint32 GetData1() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint32 GetData1() const noexcept {
 		return Data1;
 	}
-	MPT_CONSTEXPRINLINE uint16 GetData2() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint16 GetData2() const noexcept {
 		return Data2;
 	}
-	MPT_CONSTEXPRINLINE uint16 GetData3() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint16 GetData3() const noexcept {
 		return Data3;
 	}
-	MPT_CONSTEXPRINLINE uint64 GetData4() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint64 GetData4() const noexcept {
 		return Data4;
 	}
 
 public:
-	MPT_CONSTEXPRINLINE uint64 GetData64_1() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint64 GetData64_1() const noexcept {
 		return (static_cast<uint64>(Data1) << 32) | (static_cast<uint64>(Data2) << 16) | (static_cast<uint64>(Data3) << 0);
 	}
-	MPT_CONSTEXPRINLINE uint64 GetData64_2() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint64 GetData64_2() const noexcept {
 		return Data4;
 	}
 
@@ -90,27 +90,27 @@
 public:
 	// xxxxxxxx-xxxx-Mmxx-Nnxx-xxxxxxxxxxxx
 	// <--32-->-<16>-<16>-<-------64------>
-	MPT_CONSTEXPRINLINE bool IsNil() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool IsNil() const noexcept {
 		return (Data1 == 0) && (Data2 == 0) && (Data3 == 0) && (Data4 == 0);
 	}
-	MPT_CONSTEXPRINLINE bool IsValid() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool IsValid() const noexcept {
 		return (Data1 != 0) || (Data2 != 0) || (Data3 != 0) || (Data4 != 0);
 	}
-	MPT_CONSTEXPRINLINE uint8 Variant() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint8 Variant() const noexcept {
 		return Nn() >> 4u;
 	}
-	MPT_CONSTEXPRINLINE uint8 Version() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint8 Version() const noexcept {
 		return Mm() >> 4u;
 	}
-	MPT_CONSTEXPRINLINE bool IsRFC4122() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool IsRFC4122() const noexcept {
 		return (Variant() & 0xcu) == 0x8u;
 	}
 
 private:
-	MPT_CONSTEXPRINLINE uint8 Mm() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint8 Mm() const noexcept {
 		return static_cast<uint8>((Data3 >> 8) & 0xffu);
 	}
-	MPT_CONSTEXPRINLINE uint8 Nn() const noexcept {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint8 Nn() const noexcept {
 		return static_cast<uint8>((Data4 >> 56) & 0xffu);
 	}
 #if MPT_COMPILER_GCC
@@ -165,23 +165,23 @@
 	}
 #endif // MPT_OS_WINDOWS
 private:
-	static MPT_CONSTEXPRINLINE uint8 NibbleFromChar(char x) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static uint8 NibbleFromChar(char x) {
 		return ('0' <= x && x <= '9') ? static_cast<uint8>(x - '0' + 0) : ('a' <= x && x <= 'z') ? static_cast<uint8>(x - 'a' + 10)
 																	: ('A' <= x && x <= 'Z')     ? static_cast<uint8>(x - 'A' + 10)
 																								 : mpt::constexpr_throw<uint8>(std::domain_error(""));
 	}
-	static MPT_CONSTEXPRINLINE uint8 ByteFromHex(char x, char y) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static uint8 ByteFromHex(char x, char y) {
 		return static_cast<uint8>(uint8(0) | (NibbleFromChar(x) << 4) | (NibbleFromChar(y) << 0));
 	}
-	static MPT_CONSTEXPRINLINE uint16 ParseHex16(const char * str) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static uint16 ParseHex16(const char * str) {
 		return static_cast<uint16>(uint16(0) | (static_cast<uint16>(ByteFromHex(str[0], str[1])) << 8) | (static_cast<uint16>(ByteFromHex(str[2], str[3])) << 0));
 	}
-	static MPT_CONSTEXPRINLINE uint32 ParseHex32(const char * str) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static uint32 ParseHex32(const char * str) {
 		return static_cast<uint32>(uint32(0) | (static_cast<uint32>(ByteFromHex(str[0], str[1])) << 24) | (static_cast<uint32>(ByteFromHex(str[2], str[3])) << 16) | (static_cast<uint32>(ByteFromHex(str[4], str[5])) << 8) | (static_cast<uint32>(ByteFromHex(str[6], str[7])) << 0));
 	}
 
 public:
-	static MPT_CONSTEXPRINLINE UUID ParseLiteral(const char * str, std::size_t len) {
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static UUID ParseLiteral(const char * str, std::size_t len) {
 		return (len == 36 && str[8] == '-' && str[13] == '-' && str[18] == '-' && str[23] == '-') ? mpt::UUID(
 				   ParseHex32(str + 0),
 				   ParseHex16(str + 9),
@@ -194,7 +194,7 @@
 	}
 
 public:
-	MPT_CONSTEXPRINLINE UUID() noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr UUID() noexcept
 		: Data1(0)
 		, Data2(0)
 		, Data3(0)
@@ -201,7 +201,7 @@
 		, Data4(0) {
 		return;
 	}
-	MPT_CONSTEXPRINLINE explicit UUID(uint32 Data1, uint16 Data2, uint16 Data3, uint64 Data4) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr explicit UUID(uint32 Data1, uint16 Data2, uint16 Data3, uint64 Data4) noexcept
 		: Data1(Data1)
 		, Data2(Data2)
 		, Data3(Data3)
@@ -365,11 +365,11 @@
 	}
 };
 
-MPT_CONSTEXPRINLINE bool operator==(const mpt::UUID & a, const mpt::UUID & b) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator==(const mpt::UUID & a, const mpt::UUID & b) noexcept {
 	return (a.GetData1() == b.GetData1()) && (a.GetData2() == b.GetData2()) && (a.GetData3() == b.GetData3()) && (a.GetData4() == b.GetData4());
 }
 
-MPT_CONSTEXPRINLINE bool operator!=(const mpt::UUID & a, const mpt::UUID & b) noexcept {
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator!=(const mpt::UUID & a, const mpt::UUID & b) noexcept {
 	return (a.GetData1() != b.GetData1()) || (a.GetData2() != b.GetData2()) || (a.GetData3() != b.GetData3()) || (a.GetData4() != b.GetData4());
 }
 
@@ -376,7 +376,7 @@
 
 namespace uuid_literals {
 
-MPT_CONSTEVAL mpt::UUID operator""_uuid(const char * str, std::size_t len) {
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL mpt::UUID operator""_uuid(const char * str, std::size_t len) {
 	return mpt::UUID::ParseLiteral(str, len);
 }
 
Index: src/openmpt/base/FlagSet.hpp
===================================================================
--- src/openmpt/base/FlagSet.hpp	(revision 23566)
+++ src/openmpt/base/FlagSet.hpp	(working copy)
@@ -36,84 +36,84 @@
 	store_type bits;
 
 public:
-	MPT_CONSTEXPRINLINE enum_value_type() noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr enum_value_type() noexcept
 		: bits(0)
 	{
 	}
-	MPT_CONSTEXPRINLINE enum_value_type(const enum_value_type &x) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr enum_value_type(const enum_value_type &x) noexcept
 		: bits(x.bits)
 	{
 	}
-	MPT_CONSTEXPRINLINE enum_value_type(enum_type x) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr enum_value_type(enum_type x) noexcept
 		: bits(static_cast<store_type>(x))
 	{
 	}
 
 private:
-	explicit MPT_CONSTEXPRINLINE enum_value_type(store_type x) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr explicit enum_value_type(store_type x) noexcept
 		: bits(x)
 	{
 	}                                                                          // private in order to prevent accidental conversions. use from_bits.
-	MPT_CONSTEXPRINLINE operator store_type() const noexcept { return bits; }  // private in order to prevent accidental conversions. use as_bits.
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr operator store_type() const noexcept { return bits; }  // private in order to prevent accidental conversions. use as_bits.
 public:
-	static MPT_CONSTEXPRINLINE enum_value_type from_bits(store_type bits) noexcept { return value_type(bits); }
-	MPT_CONSTEXPRINLINE enum_type as_enum() const noexcept { return static_cast<enum_t>(bits); }
-	MPT_CONSTEXPRINLINE store_type as_bits() const noexcept { return bits; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static enum_value_type from_bits(store_type bits) noexcept { return value_type(bits); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr enum_type as_enum() const noexcept { return static_cast<enum_t>(bits); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr store_type as_bits() const noexcept { return bits; }
 
 public:
-	MPT_CONSTEXPRINLINE operator bool() const noexcept { return bits != store_type(); }
-	MPT_CONSTEXPRINLINE bool operator!() const noexcept { return bits == store_type(); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr operator bool() const noexcept { return bits != store_type(); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator!() const noexcept { return bits == store_type(); }
 
-	MPT_CONSTEXPRINLINE const enum_value_type operator~() const noexcept { return enum_value_type(~bits); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr const enum_value_type operator~() const noexcept { return enum_value_type(~bits); }
 
-	friend MPT_CONSTEXPRINLINE bool operator==(enum_value_type a, enum_value_type b) noexcept { return a.bits == b.bits; }
-	friend MPT_CONSTEXPRINLINE bool operator!=(enum_value_type a, enum_value_type b) noexcept { return a.bits != b.bits; }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(enum_value_type a, enum_value_type b) noexcept { return a.bits == b.bits; }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(enum_value_type a, enum_value_type b) noexcept { return a.bits != b.bits; }
 
-	friend MPT_CONSTEXPRINLINE bool operator==(enum_value_type a, enum_t b) noexcept { return a == enum_value_type(b); }
-	friend MPT_CONSTEXPRINLINE bool operator!=(enum_value_type a, enum_t b) noexcept { return a != enum_value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(enum_value_type a, enum_t b) noexcept { return a == enum_value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(enum_value_type a, enum_t b) noexcept { return a != enum_value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE bool operator==(enum_t a, enum_value_type b) noexcept { return enum_value_type(a) == b; }
-	friend MPT_CONSTEXPRINLINE bool operator!=(enum_t a, enum_value_type b) noexcept { return enum_value_type(a) != b; }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(enum_t a, enum_value_type b) noexcept { return enum_value_type(a) == b; }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(enum_t a, enum_value_type b) noexcept { return enum_value_type(a) != b; }
 
-	friend MPT_CONSTEXPRINLINE const enum_value_type operator|(enum_value_type a, enum_value_type b) noexcept { return enum_value_type(a.bits | b.bits); }
-	friend MPT_CONSTEXPRINLINE const enum_value_type operator&(enum_value_type a, enum_value_type b) noexcept { return enum_value_type(a.bits & b.bits); }
-	friend MPT_CONSTEXPRINLINE const enum_value_type operator^(enum_value_type a, enum_value_type b) noexcept { return enum_value_type(a.bits ^ b.bits); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const enum_value_type operator|(enum_value_type a, enum_value_type b) noexcept { return enum_value_type(a.bits | b.bits); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const enum_value_type operator&(enum_value_type a, enum_value_type b) noexcept { return enum_value_type(a.bits & b.bits); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const enum_value_type operator^(enum_value_type a, enum_value_type b) noexcept { return enum_value_type(a.bits ^ b.bits); }
 
-	friend MPT_CONSTEXPRINLINE const enum_value_type operator|(enum_value_type a, enum_t b) noexcept { return a | enum_value_type(b); }
-	friend MPT_CONSTEXPRINLINE const enum_value_type operator&(enum_value_type a, enum_t b) noexcept { return a & enum_value_type(b); }
-	friend MPT_CONSTEXPRINLINE const enum_value_type operator^(enum_value_type a, enum_t b) noexcept { return a ^ enum_value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const enum_value_type operator|(enum_value_type a, enum_t b) noexcept { return a | enum_value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const enum_value_type operator&(enum_value_type a, enum_t b) noexcept { return a & enum_value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const enum_value_type operator^(enum_value_type a, enum_t b) noexcept { return a ^ enum_value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE const enum_value_type operator|(enum_t a, enum_value_type b) noexcept { return enum_value_type(a) | b; }
-	friend MPT_CONSTEXPRINLINE const enum_value_type operator&(enum_t a, enum_value_type b) noexcept { return enum_value_type(a) & b; }
-	friend MPT_CONSTEXPRINLINE const enum_value_type operator^(enum_t a, enum_value_type b) noexcept { return enum_value_type(a) ^ b; }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const enum_value_type operator|(enum_t a, enum_value_type b) noexcept { return enum_value_type(a) | b; }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const enum_value_type operator&(enum_t a, enum_value_type b) noexcept { return enum_value_type(a) & b; }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const enum_value_type operator^(enum_t a, enum_value_type b) noexcept { return enum_value_type(a) ^ b; }
 
-	MPT_CONSTEXPRINLINE enum_value_type &operator|=(enum_value_type b) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr enum_value_type &operator|=(enum_value_type b) noexcept
 	{
 		*this = *this | b;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE enum_value_type &operator&=(enum_value_type b) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr enum_value_type &operator&=(enum_value_type b) noexcept
 	{
 		*this = *this & b;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE enum_value_type &operator^=(enum_value_type b) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr enum_value_type &operator^=(enum_value_type b) noexcept
 	{
 		*this = *this ^ b;
 		return *this;
 	}
 
-	MPT_CONSTEXPRINLINE enum_value_type &operator|=(enum_t b) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr enum_value_type &operator|=(enum_t b) noexcept
 	{
 		*this = *this | b;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE enum_value_type &operator&=(enum_t b) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr enum_value_type &operator&=(enum_t b) noexcept
 	{
 		*this = *this & b;
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE enum_value_type &operator^=(enum_t b) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr enum_value_type &operator^=(enum_t b) noexcept
 	{
 		*this = *this ^ b;
 		return *this;
@@ -135,12 +135,12 @@
 	enum_type value;
 
 public:
-	explicit MPT_CONSTEXPRINLINE Enum(enum_type val) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr explicit Enum(enum_type val) noexcept
 		: value(val)
 	{
 	}
-	MPT_CONSTEXPRINLINE operator enum_type() const noexcept { return value; }
-	MPT_CONSTEXPRINLINE Enum &operator=(enum_type val) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr operator enum_type() const noexcept { return value; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr Enum &operator=(enum_type val) noexcept
 	{
 		value = val;
 		return *this;
@@ -147,42 +147,42 @@
 	}
 
 public:
-	MPT_CONSTEXPRINLINE const value_type operator~() const { return ~value_type(value); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr const value_type operator~() const { return ~value_type(value); }
 
-	friend MPT_CONSTEXPRINLINE bool operator==(self_type a, self_type b) noexcept { return value_type(a) == value_type(b); }
-	friend MPT_CONSTEXPRINLINE bool operator!=(self_type a, self_type b) noexcept { return value_type(a) != value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(self_type a, self_type b) noexcept { return value_type(a) == value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(self_type a, self_type b) noexcept { return value_type(a) != value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE bool operator==(self_type a, value_type b) noexcept { return value_type(a) == value_type(b); }
-	friend MPT_CONSTEXPRINLINE bool operator!=(self_type a, value_type b) noexcept { return value_type(a) != value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(self_type a, value_type b) noexcept { return value_type(a) == value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(self_type a, value_type b) noexcept { return value_type(a) != value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE bool operator==(value_type a, self_type b) noexcept { return value_type(a) == value_type(b); }
-	friend MPT_CONSTEXPRINLINE bool operator!=(value_type a, self_type b) noexcept { return value_type(a) != value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(value_type a, self_type b) noexcept { return value_type(a) == value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(value_type a, self_type b) noexcept { return value_type(a) != value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE bool operator==(self_type a, enum_type b) noexcept { return value_type(a) == value_type(b); }
-	friend MPT_CONSTEXPRINLINE bool operator!=(self_type a, enum_type b) noexcept { return value_type(a) != value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(self_type a, enum_type b) noexcept { return value_type(a) == value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(self_type a, enum_type b) noexcept { return value_type(a) != value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE bool operator==(enum_type a, self_type b) noexcept { return value_type(a) == value_type(b); }
-	friend MPT_CONSTEXPRINLINE bool operator!=(enum_type a, self_type b) noexcept { return value_type(a) != value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(enum_type a, self_type b) noexcept { return value_type(a) == value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(enum_type a, self_type b) noexcept { return value_type(a) != value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE const value_type operator|(self_type a, self_type b) noexcept { return value_type(a) | value_type(b); }
-	friend MPT_CONSTEXPRINLINE const value_type operator&(self_type a, self_type b) noexcept { return value_type(a) & value_type(b); }
-	friend MPT_CONSTEXPRINLINE const value_type operator^(self_type a, self_type b) noexcept { return value_type(a) ^ value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator|(self_type a, self_type b) noexcept { return value_type(a) | value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator&(self_type a, self_type b) noexcept { return value_type(a) & value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator^(self_type a, self_type b) noexcept { return value_type(a) ^ value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE const value_type operator|(self_type a, value_type b) noexcept { return value_type(a) | value_type(b); }
-	friend MPT_CONSTEXPRINLINE const value_type operator&(self_type a, value_type b) noexcept { return value_type(a) & value_type(b); }
-	friend MPT_CONSTEXPRINLINE const value_type operator^(self_type a, value_type b) noexcept { return value_type(a) ^ value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator|(self_type a, value_type b) noexcept { return value_type(a) | value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator&(self_type a, value_type b) noexcept { return value_type(a) & value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator^(self_type a, value_type b) noexcept { return value_type(a) ^ value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE const value_type operator|(value_type a, self_type b) noexcept { return value_type(a) | value_type(b); }
-	friend MPT_CONSTEXPRINLINE const value_type operator&(value_type a, self_type b) noexcept { return value_type(a) & value_type(b); }
-	friend MPT_CONSTEXPRINLINE const value_type operator^(value_type a, self_type b) noexcept { return value_type(a) ^ value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator|(value_type a, self_type b) noexcept { return value_type(a) | value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator&(value_type a, self_type b) noexcept { return value_type(a) & value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator^(value_type a, self_type b) noexcept { return value_type(a) ^ value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE const value_type operator|(self_type a, enum_type b) noexcept { return value_type(a) | value_type(b); }
-	friend MPT_CONSTEXPRINLINE const value_type operator&(self_type a, enum_type b) noexcept { return value_type(a) & value_type(b); }
-	friend MPT_CONSTEXPRINLINE const value_type operator^(self_type a, enum_type b) noexcept { return value_type(a) ^ value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator|(self_type a, enum_type b) noexcept { return value_type(a) | value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator&(self_type a, enum_type b) noexcept { return value_type(a) & value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator^(self_type a, enum_type b) noexcept { return value_type(a) ^ value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE const value_type operator|(enum_type a, self_type b) noexcept { return value_type(a) | value_type(b); }
-	friend MPT_CONSTEXPRINLINE const value_type operator&(enum_type a, self_type b) noexcept { return value_type(a) & value_type(b); }
-	friend MPT_CONSTEXPRINLINE const value_type operator^(enum_type a, self_type b) noexcept { return value_type(a) ^ value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator|(enum_type a, self_type b) noexcept { return value_type(a) | value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator&(enum_type a, self_type b) noexcept { return value_type(a) & value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator^(enum_type a, self_type b) noexcept { return value_type(a) ^ value_type(b); }
 };
 
 
@@ -199,255 +199,255 @@
 private:
 	// support truncated store_type ... :
 	store_type bits_;
-	static MPT_CONSTEXPRINLINE store_type store_from_value(value_type bits) noexcept { return static_cast<store_type>(bits.as_bits()); }
-	static MPT_CONSTEXPRINLINE value_type value_from_store(store_type bits) noexcept { return value_type::from_bits(static_cast<typename value_type::store_type>(bits)); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static store_type store_from_value(value_type bits) noexcept { return static_cast<store_type>(bits.as_bits()); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static value_type value_from_store(store_type bits) noexcept { return value_type::from_bits(static_cast<typename value_type::store_type>(bits)); }
 
-	MPT_CONSTEXPRINLINE FlagSet &store(value_type bits) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet &store(value_type bits) noexcept
 	{
 		bits_ = store_from_value(bits);
 		return *this;
 	}
-	MPT_CONSTEXPRINLINE value_type load() const noexcept { return value_from_store(bits_); }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr value_type load() const noexcept { return value_from_store(bits_); }
 
 public:
 	// Default constructor (no flags set)
-	MPT_CONSTEXPRINLINE FlagSet() noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet() noexcept
 		: bits_(store_from_value(value_type()))
 	{
 	}
 
 	// Copy constructor
-	MPT_CONSTEXPRINLINE FlagSet(const FlagSet &flags) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet(const FlagSet &flags) noexcept
 		: bits_(flags.bits_)
 	{
 	}
 
 	// Value constructor
-	MPT_CONSTEXPRINLINE FlagSet(value_type flags) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet(value_type flags) noexcept
 		: bits_(store_from_value(value_type(flags)))
 	{
 	}
 
-	MPT_CONSTEXPRINLINE FlagSet(enum_type flag) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet(enum_type flag) noexcept
 		: bits_(store_from_value(value_type(flag)))
 	{
 	}
 
-	explicit MPT_CONSTEXPRINLINE FlagSet(store_type flags) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr explicit FlagSet(store_type flags) noexcept
 		: bits_(store_from_value(value_type::from_bits(flags)))
 	{
 	}
 
-	MPT_CONSTEXPRINLINE explicit operator bool() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr explicit operator bool() const noexcept
 	{
 		return load();
 	}
-	MPT_CONSTEXPRINLINE explicit operator store_type() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr explicit operator store_type() const noexcept
 	{
 		return load().as_bits();
 	}
 
-	MPT_CONSTEXPRINLINE value_type value() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr value_type value() const noexcept
 	{
 		return load();
 	}
 
-	MPT_CONSTEXPRINLINE operator value_type() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr operator value_type() const noexcept
 	{
 		return load();
 	}
 
 	// Test if one or more flags are set. Returns true if at least one of the given flags is set.
-	MPT_CONSTEXPRINLINE bool operator[](value_type flags) const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool operator[](value_type flags) const noexcept
 	{
 		return test(flags);
 	}
 
 	// Set one or more flags.
-	MPT_CONSTEXPRINLINE FlagSet &set(value_type flags) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet &set(value_type flags) noexcept
 	{
 		return store(load() | flags);
 	}
 
 	// Set or clear one or more flags.
-	MPT_CONSTEXPRINLINE FlagSet &set(value_type flags, bool val) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet &set(value_type flags, bool val) noexcept
 	{
 		return store((val ? (load() | flags) : (load() & ~flags)));
 	}
 
 	// Clear or flags.
-	MPT_CONSTEXPRINLINE FlagSet &reset() noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet &reset() noexcept
 	{
 		return store(value_type());
 	}
 
 	// Clear one or more flags.
-	MPT_CONSTEXPRINLINE FlagSet &reset(value_type flags) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet &reset(value_type flags) noexcept
 	{
 		return store(load() & ~flags);
 	}
 
 	// Toggle all flags.
-	MPT_CONSTEXPRINLINE FlagSet &flip() noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet &flip() noexcept
 	{
 		return store(~load());
 	}
 
 	// Toggle one or more flags.
-	MPT_CONSTEXPRINLINE FlagSet &flip(value_type flags) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet &flip(value_type flags) noexcept
 	{
 		return store(load() ^ flags);
 	}
 
 	// Returns the size of the flag set in bytes
-	MPT_CONSTEXPRINLINE std::size_t size() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr std::size_t size() const noexcept
 	{
 		return sizeof(store_type);
 	}
 
 	// Returns the size of the flag set in bits
-	MPT_CONSTEXPRINLINE std::size_t size_bits() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr std::size_t size_bits() const noexcept
 	{
 		return size() * 8;
 	}
 
 	// Test if one or more flags are set. Returns true if at least one of the given flags is set.
-	MPT_CONSTEXPRINLINE bool test(value_type flags) const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool test(value_type flags) const noexcept
 	{
 		return (load() & flags);
 	}
 
 	// Test if all specified flags are set.
-	MPT_CONSTEXPRINLINE bool test_all(value_type flags) const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool test_all(value_type flags) const noexcept
 	{
 		return (load() & flags) == flags;
 	}
 
 	// Test if any but the specified flags are set.
-	MPT_CONSTEXPRINLINE bool test_any_except(value_type flags) const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool test_any_except(value_type flags) const noexcept
 	{
 		return (load() & ~flags);
 	}
 
 	// Test if any flag is set.
-	MPT_CONSTEXPRINLINE bool any() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool any() const noexcept
 	{
 		return load();
 	}
 
 	// Test if no flags are set.
-	MPT_CONSTEXPRINLINE bool none() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool none() const noexcept
 	{
 		return !load();
 	}
 
-	MPT_CONSTEXPRINLINE store_type GetRaw() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr store_type GetRaw() const noexcept
 	{
 		return bits_;
 	}
 
-	MPT_CONSTEXPRINLINE FlagSet &SetRaw(store_type flags) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet &SetRaw(store_type flags) noexcept
 	{
 		bits_ = flags;
 		return *this;
 	}
 
-	MPT_CONSTEXPRINLINE FlagSet &operator=(value_type flags) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet &operator=(value_type flags) noexcept
 	{
 		return store(flags);
 	}
 
-	MPT_CONSTEXPRINLINE FlagSet &operator=(enum_type flag) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet &operator=(enum_type flag) noexcept
 	{
 		return store(flag);
 	}
 
-	MPT_CONSTEXPRINLINE FlagSet &operator=(FlagSet flags) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet &operator=(FlagSet flags) noexcept
 	{
 		return store(flags.load());
 	}
 
-	MPT_CONSTEXPRINLINE FlagSet &operator&=(value_type flags) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet &operator&=(value_type flags) noexcept
 	{
 		return store(load() & flags);
 	}
 
-	MPT_CONSTEXPRINLINE FlagSet &operator|=(value_type flags) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet &operator|=(value_type flags) noexcept
 	{
 		return store(load() | flags);
 	}
 
-	MPT_CONSTEXPRINLINE FlagSet &operator^=(value_type flags) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr FlagSet &operator^=(value_type flags) noexcept
 	{
 		return store(load() ^ flags);
 	}
 
-	friend MPT_CONSTEXPRINLINE bool operator==(self_type a, self_type b) noexcept { return a.load() == b.load(); }
-	friend MPT_CONSTEXPRINLINE bool operator!=(self_type a, self_type b) noexcept { return a.load() != b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(self_type a, self_type b) noexcept { return a.load() == b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(self_type a, self_type b) noexcept { return a.load() != b.load(); }
 
-	friend MPT_CONSTEXPRINLINE bool operator==(self_type a, value_type b) noexcept { return a.load() == value_type(b); }
-	friend MPT_CONSTEXPRINLINE bool operator!=(self_type a, value_type b) noexcept { return a.load() != value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(self_type a, value_type b) noexcept { return a.load() == value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(self_type a, value_type b) noexcept { return a.load() != value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE bool operator==(value_type a, self_type b) noexcept { return value_type(a) == b.load(); }
-	friend MPT_CONSTEXPRINLINE bool operator!=(value_type a, self_type b) noexcept { return value_type(a) != b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(value_type a, self_type b) noexcept { return value_type(a) == b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(value_type a, self_type b) noexcept { return value_type(a) != b.load(); }
 
-	friend MPT_CONSTEXPRINLINE bool operator==(self_type a, enum_type b) noexcept { return a.load() == value_type(b); }
-	friend MPT_CONSTEXPRINLINE bool operator!=(self_type a, enum_type b) noexcept { return a.load() != value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(self_type a, enum_type b) noexcept { return a.load() == value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(self_type a, enum_type b) noexcept { return a.load() != value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE bool operator==(enum_type a, self_type b) noexcept { return value_type(a) == b.load(); }
-	friend MPT_CONSTEXPRINLINE bool operator!=(enum_type a, self_type b) noexcept { return value_type(a) != b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(enum_type a, self_type b) noexcept { return value_type(a) == b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(enum_type a, self_type b) noexcept { return value_type(a) != b.load(); }
 
-	friend MPT_CONSTEXPRINLINE bool operator==(self_type a, Enum<enum_type> b) noexcept { return a.load() == value_type(b); }
-	friend MPT_CONSTEXPRINLINE bool operator!=(self_type a, Enum<enum_type> b) noexcept { return a.load() != value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(self_type a, Enum<enum_type> b) noexcept { return a.load() == value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(self_type a, Enum<enum_type> b) noexcept { return a.load() != value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE bool operator==(Enum<enum_type> a, self_type b) noexcept { return value_type(a) == b.load(); }
-	friend MPT_CONSTEXPRINLINE bool operator!=(Enum<enum_type> a, self_type b) noexcept { return value_type(a) != b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(Enum<enum_type> a, self_type b) noexcept { return value_type(a) == b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(Enum<enum_type> a, self_type b) noexcept { return value_type(a) != b.load(); }
 
-	friend MPT_CONSTEXPRINLINE const value_type operator|(self_type a, self_type b) noexcept { return a.load() | b.load(); }
-	friend MPT_CONSTEXPRINLINE const value_type operator&(self_type a, self_type b) noexcept { return a.load() & b.load(); }
-	friend MPT_CONSTEXPRINLINE const value_type operator^(self_type a, self_type b) noexcept { return a.load() ^ b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator|(self_type a, self_type b) noexcept { return a.load() | b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator&(self_type a, self_type b) noexcept { return a.load() & b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator^(self_type a, self_type b) noexcept { return a.load() ^ b.load(); }
 
-	friend MPT_CONSTEXPRINLINE const value_type operator|(self_type a, value_type b) noexcept { return a.load() | value_type(b); }
-	friend MPT_CONSTEXPRINLINE const value_type operator&(self_type a, value_type b) noexcept { return a.load() & value_type(b); }
-	friend MPT_CONSTEXPRINLINE const value_type operator^(self_type a, value_type b) noexcept { return a.load() ^ value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator|(self_type a, value_type b) noexcept { return a.load() | value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator&(self_type a, value_type b) noexcept { return a.load() & value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator^(self_type a, value_type b) noexcept { return a.load() ^ value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE const value_type operator|(value_type a, self_type b) noexcept { return value_type(a) | b.load(); }
-	friend MPT_CONSTEXPRINLINE const value_type operator&(value_type a, self_type b) noexcept { return value_type(a) & b.load(); }
-	friend MPT_CONSTEXPRINLINE const value_type operator^(value_type a, self_type b) noexcept { return value_type(a) ^ b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator|(value_type a, self_type b) noexcept { return value_type(a) | b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator&(value_type a, self_type b) noexcept { return value_type(a) & b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator^(value_type a, self_type b) noexcept { return value_type(a) ^ b.load(); }
 
-	friend MPT_CONSTEXPRINLINE const value_type operator|(self_type a, enum_type b) noexcept { return a.load() | value_type(b); }
-	friend MPT_CONSTEXPRINLINE const value_type operator&(self_type a, enum_type b) noexcept { return a.load() & value_type(b); }
-	friend MPT_CONSTEXPRINLINE const value_type operator^(self_type a, enum_type b) noexcept { return a.load() ^ value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator|(self_type a, enum_type b) noexcept { return a.load() | value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator&(self_type a, enum_type b) noexcept { return a.load() & value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator^(self_type a, enum_type b) noexcept { return a.load() ^ value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE const value_type operator|(enum_type a, self_type b) noexcept { return value_type(a) | b.load(); }
-	friend MPT_CONSTEXPRINLINE const value_type operator&(enum_type a, self_type b) noexcept { return value_type(a) & b.load(); }
-	friend MPT_CONSTEXPRINLINE const value_type operator^(enum_type a, self_type b) noexcept { return value_type(a) ^ b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator|(enum_type a, self_type b) noexcept { return value_type(a) | b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator&(enum_type a, self_type b) noexcept { return value_type(a) & b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator^(enum_type a, self_type b) noexcept { return value_type(a) ^ b.load(); }
 
-	friend MPT_CONSTEXPRINLINE const value_type operator|(self_type a, Enum<enum_type> b) noexcept { return a.load() | value_type(b); }
-	friend MPT_CONSTEXPRINLINE const value_type operator&(self_type a, Enum<enum_type> b) noexcept { return a.load() & value_type(b); }
-	friend MPT_CONSTEXPRINLINE const value_type operator^(self_type a, Enum<enum_type> b) noexcept { return a.load() ^ value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator|(self_type a, Enum<enum_type> b) noexcept { return a.load() | value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator&(self_type a, Enum<enum_type> b) noexcept { return a.load() & value_type(b); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator^(self_type a, Enum<enum_type> b) noexcept { return a.load() ^ value_type(b); }
 
-	friend MPT_CONSTEXPRINLINE const value_type operator|(Enum<enum_type> a, self_type b) noexcept { return value_type(a) | b.load(); }
-	friend MPT_CONSTEXPRINLINE const value_type operator&(Enum<enum_type> a, self_type b) noexcept { return value_type(a) & b.load(); }
-	friend MPT_CONSTEXPRINLINE const value_type operator^(Enum<enum_type> a, self_type b) noexcept { return value_type(a) ^ b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator|(Enum<enum_type> a, self_type b) noexcept { return value_type(a) | b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator&(Enum<enum_type> a, self_type b) noexcept { return value_type(a) & b.load(); }
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr const value_type operator^(Enum<enum_type> a, self_type b) noexcept { return value_type(a) ^ b.load(); }
 };
 
 
 // Declare typesafe logical operators for enum_t
 #define MPT_DECLARE_ENUM(enum_t) \
-	MPT_CONSTEXPRINLINE enum_value_type<enum_t> operator|(enum_t a, enum_t b) noexcept \
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr enum_value_type<enum_t> operator|(enum_t a, enum_t b) noexcept \
 	{ \
 		return enum_value_type<enum_t>(a) | enum_value_type<enum_t>(b); \
 	} \
-	MPT_CONSTEXPRINLINE enum_value_type<enum_t> operator&(enum_t a, enum_t b) noexcept \
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr enum_value_type<enum_t> operator&(enum_t a, enum_t b) noexcept \
 	{ \
 		return enum_value_type<enum_t>(a) & enum_value_type<enum_t>(b); \
 	} \
-	MPT_CONSTEXPRINLINE enum_value_type<enum_t> operator^(enum_t a, enum_t b) noexcept \
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr enum_value_type<enum_t> operator^(enum_t a, enum_t b) noexcept \
 	{ \
 		return enum_value_type<enum_t>(a) ^ enum_value_type<enum_t>(b); \
 	} \
-	MPT_CONSTEXPRINLINE enum_value_type<enum_t> operator~(enum_t a) noexcept \
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr enum_value_type<enum_t> operator~(enum_t a) noexcept \
 	{ \
 		return ~enum_value_type<enum_t>(a); \
 	} \
Index: src/openmpt/fileformat_base/magic.hpp
===================================================================
--- src/openmpt/fileformat_base/magic.hpp	(revision 23566)
+++ src/openmpt/fileformat_base/magic.hpp	(working copy)
@@ -17,11 +17,11 @@
 
 // Functions to create 4-byte and 2-byte magic byte identifiers in little-endian format
 // Use this together with uint32le/uint16le file members.
-MPT_CONSTEVAL uint32 MagicLE(const char (&id)[5])
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL uint32 MagicLE(const char (&id)[5])
 {
 	return static_cast<uint32>((static_cast<uint8>(id[3]) << 24) | (static_cast<uint8>(id[2]) << 16) | (static_cast<uint8>(id[1]) << 8) | static_cast<uint8>(id[0]));
 }
-MPT_CONSTEVAL uint16 MagicLE(const char (&id)[3])
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL uint16 MagicLE(const char (&id)[3])
 {
 	return static_cast<uint16>((static_cast<uint8>(id[1]) << 8) | static_cast<uint8>(id[0]));
 }
@@ -30,11 +30,11 @@
 // Use this together with uint32be/uint16be file members.
 // Note: Historically, some magic bytes in MPT-specific fields are reversed (due to the use of multi-char literals).
 // Such fields turned up reversed in files, so MagicBE is used to keep them readable in the code.
-MPT_CONSTEVAL uint32 MagicBE(const char (&id)[5])
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL uint32 MagicBE(const char (&id)[5])
 {
 	return static_cast<uint32>((static_cast<uint8>(id[0]) << 24) | (static_cast<uint8>(id[1]) << 16) | (static_cast<uint8>(id[2]) << 8) | static_cast<uint8>(id[3]));
 }
-MPT_CONSTEVAL uint16 MagicBE(const char (&id)[3])
+MPT_ATTR_ALWAYSINLINE MPT_CONSTEVAL uint16 MagicBE(const char (&id)[3])
 {
 	return static_cast<uint16>((static_cast<uint8>(id[0]) << 8) | static_cast<uint8>(id[1]));
 }
Index: src/openmpt/random/ModPlug.hpp
===================================================================
--- src/openmpt/random/ModPlug.hpp	(revision 23566)
+++ src/openmpt/random/ModPlug.hpp	(working copy)
@@ -50,15 +50,15 @@
 	}
 
 public:
-	static MPT_CONSTEXPRINLINE result_type min()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static result_type min()
 	{
 		return static_cast<result_type>(0);
 	}
-	static MPT_CONSTEXPRINLINE result_type max()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static result_type max()
 	{
 		return std::numeric_limits<result_type>::max();
 	}
-	static MPT_CONSTEXPRINLINE int result_bits()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static int result_bits()
 	{
 		static_assert(std::is_integral<result_type>::value);
 		static_assert(std::is_unsigned<result_type>::value);
Index: src/openmpt/soundbase/Dither.hpp
===================================================================
--- src/openmpt/soundbase/Dither.hpp	(revision 23566)
+++ src/openmpt/soundbase/Dither.hpp	(working copy)
@@ -48,12 +48,12 @@
 		return DitherChannels.size();
 	}
 	template <uint32 targetbits>
-	MPT_FORCEINLINE MixSampleInt process(std::size_t channel, MixSampleInt sample)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE MixSampleInt process(std::size_t channel, MixSampleInt sample)
 	{
 		return DitherChannels[channel].template process<targetbits>(sample, prng);
 	}
 	template <uint32 targetbits>
-	MPT_FORCEINLINE MixSampleFloat process(std::size_t channel, MixSampleFloat sample)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE MixSampleFloat process(std::size_t channel, MixSampleFloat sample)
 	{
 		return DitherChannels[channel].template process<targetbits>(sample, prng);
 	}
Index: src/openmpt/soundbase/DitherModPlug.hpp
===================================================================
--- src/openmpt/soundbase/DitherModPlug.hpp	(revision 23566)
+++ src/openmpt/soundbase/DitherModPlug.hpp	(working copy)
@@ -31,7 +31,7 @@
 
 public:
 	template <uint32 targetbits, typename Trng>
-	MPT_FORCEINLINE MixSampleInt process(MixSampleInt sample, Trng &rng)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE MixSampleInt process(MixSampleInt sample, Trng &rng)
 	{
 		if constexpr(targetbits == 0)
 		{
@@ -48,7 +48,7 @@
 		}
 	}
 	template <uint32 targetbits, typename Trng>
-	MPT_FORCEINLINE MixSampleFloat process(MixSampleFloat sample, Trng &prng)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE MixSampleFloat process(MixSampleFloat sample, Trng &prng)
 	{
 		return mix_sample_cast<MixSampleFloat>(process<targetbits>(mix_sample_cast<MixSampleInt>(sample), prng));
 	}
Index: src/openmpt/soundbase/DitherNone.hpp
===================================================================
--- src/openmpt/soundbase/DitherNone.hpp	(revision 23566)
+++ src/openmpt/soundbase/DitherNone.hpp	(working copy)
@@ -28,12 +28,12 @@
 
 public:
 	template <uint32 targetbits, typename Trng>
-	MPT_FORCEINLINE MixSampleInt process(MixSampleInt sample, Trng &)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE MixSampleInt process(MixSampleInt sample, Trng &)
 	{
 		return sample;
 	}
 	template <uint32 targetbits, typename Trng>
-	MPT_FORCEINLINE MixSampleFloat process(MixSampleFloat sample, Trng &)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE MixSampleFloat process(MixSampleFloat sample, Trng &)
 	{
 		return sample;
 	}
Index: src/openmpt/soundbase/DitherSimple.hpp
===================================================================
--- src/openmpt/soundbase/DitherSimple.hpp	(revision 23566)
+++ src/openmpt/soundbase/DitherSimple.hpp	(working copy)
@@ -35,7 +35,7 @@
 
 public:
 	template <uint32 targetbits, typename Trng>
-	MPT_FORCEINLINE MixSampleInt process(MixSampleInt sample, Trng &prng)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE MixSampleInt process(MixSampleInt sample, Trng &prng)
 	{
 		if constexpr(targetbits == 0)
 		{
@@ -81,7 +81,7 @@
 		}
 	}
 	template <uint32 targetbits, typename Trng>
-	MPT_FORCEINLINE MixSampleFloat process(MixSampleFloat sample, Trng &prng)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE MixSampleFloat process(MixSampleFloat sample, Trng &prng)
 	{
 		return mix_sample_cast<MixSampleFloat>(process<targetbits>(mix_sample_cast<MixSampleInt>(sample), prng));
 	}
Index: src/openmpt/soundbase/MixSampleConvert.hpp
===================================================================
--- src/openmpt/soundbase/MixSampleConvert.hpp	(revision 23566)
+++ src/openmpt/soundbase/MixSampleConvert.hpp	(working copy)
@@ -21,7 +21,7 @@
 template <>
 struct ConvertMixSample<MixSampleInt, MixSampleInt>
 {
-	MPT_FORCEINLINE MixSampleInt conv(MixSampleInt src)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE MixSampleInt conv(MixSampleInt src)
 	{
 		return src;
 	}
@@ -30,7 +30,7 @@
 template <>
 struct ConvertMixSample<MixSampleFloat, MixSampleFloat>
 {
-	MPT_FORCEINLINE MixSampleFloat conv(MixSampleFloat src)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE MixSampleFloat conv(MixSampleFloat src)
 	{
 		return src;
 	}
@@ -39,7 +39,7 @@
 template <typename Tsrc>
 struct ConvertMixSample<MixSampleInt, Tsrc>
 {
-	MPT_FORCEINLINE MixSampleInt conv(Tsrc src)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE MixSampleInt conv(Tsrc src)
 	{
 		return SC::ConvertToFixedPoint<MixSampleInt, Tsrc, MixSampleIntTraits::mix_fractional_bits>{}(src);
 	}
@@ -48,7 +48,7 @@
 template <typename Tdst>
 struct ConvertMixSample<Tdst, MixSampleInt>
 {
-	MPT_FORCEINLINE Tdst conv(MixSampleInt src)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE Tdst conv(MixSampleInt src)
 	{
 		return SC::ConvertFixedPoint<Tdst, MixSampleInt, MixSampleIntTraits::mix_fractional_bits>{}(src);
 	}
@@ -57,7 +57,7 @@
 template <typename Tsrc>
 struct ConvertMixSample<MixSampleFloat, Tsrc>
 {
-	MPT_FORCEINLINE MixSampleFloat conv(Tsrc src)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE MixSampleFloat conv(Tsrc src)
 	{
 		return SC::Convert<MixSampleFloat, Tsrc>{}(src);
 	}
@@ -66,7 +66,7 @@
 template <typename Tdst>
 struct ConvertMixSample<Tdst, MixSampleFloat>
 {
-	MPT_FORCEINLINE Tdst conv(MixSampleFloat src)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE Tdst conv(MixSampleFloat src)
 	{
 		return SC::Convert<Tdst, MixSampleFloat>{}(src);
 	}
@@ -75,7 +75,7 @@
 template <>
 struct ConvertMixSample<MixSampleInt, MixSampleFloat>
 {
-	MPT_FORCEINLINE MixSampleInt conv(MixSampleFloat src)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE MixSampleInt conv(MixSampleFloat src)
 	{
 		return SC::ConvertToFixedPoint<MixSampleInt, MixSampleFloat, MixSampleIntTraits::mix_fractional_bits>{}(src);
 	}
@@ -84,7 +84,7 @@
 template <>
 struct ConvertMixSample<MixSampleFloat, MixSampleInt>
 {
-	MPT_FORCEINLINE MixSampleFloat conv(MixSampleInt src)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE MixSampleFloat conv(MixSampleInt src)
 	{
 		return SC::ConvertFixedPoint<MixSampleFloat, MixSampleInt, MixSampleIntTraits::mix_fractional_bits>{}(src);
 	}
@@ -92,7 +92,7 @@
 
 
 template <typename Tdst, typename Tsrc>
-MPT_FORCEINLINE Tdst mix_sample_cast(Tsrc src)
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE Tdst mix_sample_cast(Tsrc src)
 {
 	return ConvertMixSample<Tdst, Tsrc>{}.conv(src);
 }
Index: src/openmpt/soundbase/SampleClip.hpp
===================================================================
--- src/openmpt/soundbase/SampleClip.hpp	(revision 23566)
+++ src/openmpt/soundbase/SampleClip.hpp	(working copy)
@@ -26,7 +26,7 @@
 {
 	using input_t = uint8;
 	using output_t = uint8;
-	MPT_FORCEINLINE uint8 operator()(uint8 val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE uint8 operator()(uint8 val)
 	{
 		return val;
 	}
@@ -37,7 +37,7 @@
 {
 	using input_t = int8;
 	using output_t = int8;
-	MPT_FORCEINLINE int8 operator()(int8 val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE int8 operator()(int8 val)
 	{
 		return val;
 	}
@@ -48,7 +48,7 @@
 {
 	using input_t = int16;
 	using output_t = int16;
-	MPT_FORCEINLINE int16 operator()(int16 val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE int16 operator()(int16 val)
 	{
 		return val;
 	}
@@ -59,7 +59,7 @@
 {
 	using input_t = int24;
 	using output_t = int24;
-	MPT_FORCEINLINE int24 operator()(int24 val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE int24 operator()(int24 val)
 	{
 		return val;
 	}
@@ -70,7 +70,7 @@
 {
 	using input_t = int32;
 	using output_t = int32;
-	MPT_FORCEINLINE int32 operator()(int32 val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE int32 operator()(int32 val)
 	{
 		return val;
 	}
@@ -81,7 +81,7 @@
 {
 	using input_t = int64;
 	using output_t = int64;
-	MPT_FORCEINLINE int64 operator()(int64 val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE int64 operator()(int64 val)
 	{
 		return val;
 	}
@@ -92,7 +92,7 @@
 {
 	using input_t = float;
 	using output_t = float;
-	MPT_FORCEINLINE float operator()(float val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE float operator()(float val)
 	{
 		if constexpr(clipOutput)
 		{
@@ -111,7 +111,7 @@
 {
 	using input_t = double;
 	using output_t = double;
-	MPT_FORCEINLINE double operator()(double val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE double operator()(double val)
 	{
 		if constexpr(clipOutput)
 		{
Index: src/openmpt/soundbase/SampleClipFixedPoint.hpp
===================================================================
--- src/openmpt/soundbase/SampleClipFixedPoint.hpp	(revision 23566)
+++ src/openmpt/soundbase/SampleClipFixedPoint.hpp	(working copy)
@@ -21,7 +21,7 @@
 {
 	using input_t = Tfixed;
 	using output_t = Tfixed;
-	MPT_FORCEINLINE Tfixed operator()(Tfixed val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE Tfixed operator()(Tfixed val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t) * 8 - 1);
 		if constexpr(clipOutput)
Index: src/openmpt/soundbase/SampleConvert.hpp
===================================================================
--- src/openmpt/soundbase/SampleConvert.hpp	(revision 23566)
+++ src/openmpt/soundbase/SampleConvert.hpp	(working copy)
@@ -34,7 +34,7 @@
 
 #if MPT_COMPILER_MSVC
 template <typename Tfloat>
-MPT_FORCEINLINE Tfloat fastround(Tfloat x)
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE Tfloat fastround(Tfloat x)
 {
 	static_assert(std::is_floating_point<Tfloat>::value);
 	return std::floor(x + static_cast<Tfloat>(0.5));
@@ -41,7 +41,7 @@
 }
 #else
 template <typename Tfloat>
-MPT_FORCEINLINE Tfloat fastround(Tfloat x)
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE Tfloat fastround(Tfloat x)
 {
 	static_assert(std::is_floating_point<Tfloat>::value);
 	return mpt::round(x);
@@ -56,7 +56,7 @@
 {
 	using input_t = Tsrc;
 	using output_t = Tdst;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return mpt::saturate_cast<output_t>(mpt::rshift_signed(val, shift));
 	}
@@ -70,7 +70,7 @@
 {
 	using input_t = Tsrc;
 	using output_t = Tdst;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return mpt::saturate_cast<output_t>(mpt::lshift_signed(val, shift));
 	}
@@ -92,7 +92,7 @@
 {
 	using input_t = Tid;
 	using output_t = Tid;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return val;
 	}
@@ -103,7 +103,7 @@
 {
 	using input_t = int8;
 	using output_t = uint8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<uint8>(val + 0x80);
 	}
@@ -114,7 +114,7 @@
 {
 	using input_t = int16;
 	using output_t = uint8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<uint8>(static_cast<int8>(mpt::rshift_signed(val, 8)) + 0x80);
 	}
@@ -125,7 +125,7 @@
 {
 	using input_t = int24;
 	using output_t = uint8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<uint8>(static_cast<int8>(mpt::rshift_signed(static_cast<int>(val), 16)) + 0x80);
 	}
@@ -136,7 +136,7 @@
 {
 	using input_t = int32;
 	using output_t = uint8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<uint8>(static_cast<int8>(mpt::rshift_signed(val, 24)) + 0x80);
 	}
@@ -147,7 +147,7 @@
 {
 	using input_t = int64;
 	using output_t = uint8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<uint8>(static_cast<int8>(mpt::rshift_signed(val, 56)) + 0x80);
 	}
@@ -158,7 +158,7 @@
 {
 	using input_t = somefloat32;
 	using output_t = uint8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		val = mpt::safe_clamp(val, -1.0f, 1.0f);
 		val *= 128.0f;
@@ -171,7 +171,7 @@
 {
 	using input_t = double;
 	using output_t = uint8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		val = std::clamp(val, -1.0, 1.0);
 		val *= 128.0;
@@ -184,7 +184,7 @@
 {
 	using input_t = uint8;
 	using output_t = int8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int8>(static_cast<int>(val) - 0x80);
 	}
@@ -195,7 +195,7 @@
 {
 	using input_t = int16;
 	using output_t = int8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int8>(mpt::rshift_signed(val, 8));
 	}
@@ -206,7 +206,7 @@
 {
 	using input_t = int24;
 	using output_t = int8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int8>(mpt::rshift_signed(static_cast<int>(val), 16));
 	}
@@ -217,7 +217,7 @@
 {
 	using input_t = int32;
 	using output_t = int8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int8>(mpt::rshift_signed(val, 24));
 	}
@@ -228,7 +228,7 @@
 {
 	using input_t = int64;
 	using output_t = int8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int8>(mpt::rshift_signed(val, 56));
 	}
@@ -239,7 +239,7 @@
 {
 	using input_t = somefloat32;
 	using output_t = int8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		val = mpt::safe_clamp(val, -1.0f, 1.0f);
 		val *= 128.0f;
@@ -252,7 +252,7 @@
 {
 	using input_t = double;
 	using output_t = int8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		val = std::clamp(val, -1.0, 1.0);
 		val *= 128.0;
@@ -265,7 +265,7 @@
 {
 	using input_t = uint8;
 	using output_t = int16;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int16>(mpt::lshift_signed(static_cast<int>(val) - 0x80, 8));
 	}
@@ -276,7 +276,7 @@
 {
 	using input_t = int8;
 	using output_t = int16;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int16>(mpt::lshift_signed(val, 8));
 	}
@@ -287,7 +287,7 @@
 {
 	using input_t = int24;
 	using output_t = int16;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int16>(mpt::rshift_signed(static_cast<int>(val), 8));
 	}
@@ -298,7 +298,7 @@
 {
 	using input_t = int32;
 	using output_t = int16;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int16>(mpt::rshift_signed(val, 16));
 	}
@@ -309,7 +309,7 @@
 {
 	using input_t = int64;
 	using output_t = int16;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int16>(mpt::rshift_signed(val, 48));
 	}
@@ -320,7 +320,7 @@
 {
 	using input_t = somefloat32;
 	using output_t = int16;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		val = mpt::safe_clamp(val, -1.0f, 1.0f);
 		val *= 32768.0f;
@@ -333,7 +333,7 @@
 {
 	using input_t = double;
 	using output_t = int16;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		val = std::clamp(val, -1.0, 1.0);
 		val *= 32768.0;
@@ -346,7 +346,7 @@
 {
 	using input_t = uint8;
 	using output_t = int24;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int24>(mpt::lshift_signed(static_cast<int>(val) - 0x80, 16));
 	}
@@ -357,7 +357,7 @@
 {
 	using input_t = int8;
 	using output_t = int24;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int24>(mpt::lshift_signed(val, 16));
 	}
@@ -368,7 +368,7 @@
 {
 	using input_t = int16;
 	using output_t = int24;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int24>(mpt::lshift_signed(val, 8));
 	}
@@ -379,7 +379,7 @@
 {
 	using input_t = int32;
 	using output_t = int24;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int24>(mpt::rshift_signed(val, 8));
 	}
@@ -390,7 +390,7 @@
 {
 	using input_t = int64;
 	using output_t = int24;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int24>(mpt::rshift_signed(val, 40));
 	}
@@ -401,7 +401,7 @@
 {
 	using input_t = somefloat32;
 	using output_t = int24;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		val = mpt::safe_clamp(val, -1.0f, 1.0f);
 		val *= 2147483648.0f;
@@ -414,7 +414,7 @@
 {
 	using input_t = double;
 	using output_t = int24;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		val = std::clamp(val, -1.0, 1.0);
 		val *= 2147483648.0;
@@ -427,7 +427,7 @@
 {
 	using input_t = uint8;
 	using output_t = int32;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int32>(mpt::lshift_signed(static_cast<int>(val) - 0x80, 24));
 	}
@@ -438,7 +438,7 @@
 {
 	using input_t = int8;
 	using output_t = int32;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int32>(mpt::lshift_signed(val, 24));
 	}
@@ -449,7 +449,7 @@
 {
 	using input_t = int16;
 	using output_t = int32;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int32>(mpt::lshift_signed(val, 16));
 	}
@@ -460,7 +460,7 @@
 {
 	using input_t = int24;
 	using output_t = int32;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int32>(mpt::lshift_signed(static_cast<int>(val), 8));
 	}
@@ -471,7 +471,7 @@
 {
 	using input_t = int64;
 	using output_t = int32;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<int32>(mpt::rshift_signed(val, 32));
 	}
@@ -482,7 +482,7 @@
 {
 	using input_t = somefloat32;
 	using output_t = int32;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		val = mpt::safe_clamp(val, -1.0f, 1.0f);
 		val *= 2147483648.0f;
@@ -495,7 +495,7 @@
 {
 	using input_t = double;
 	using output_t = int32;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		val = std::clamp(val, -1.0, 1.0);
 		val *= 2147483648.0;
@@ -508,7 +508,7 @@
 {
 	using input_t = uint8;
 	using output_t = int64;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return mpt::lshift_signed(static_cast<int64>(val) - 0x80, 56);
 	}
@@ -519,7 +519,7 @@
 {
 	using input_t = int8;
 	using output_t = int64;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return mpt::lshift_signed(static_cast<int64>(val), 56);
 	}
@@ -530,7 +530,7 @@
 {
 	using input_t = int16;
 	using output_t = int64;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return mpt::lshift_signed(static_cast<int64>(val), 48);
 	}
@@ -541,7 +541,7 @@
 {
 	using input_t = int24;
 	using output_t = int64;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return mpt::lshift_signed(static_cast<int64>(val), 40);
 	}
@@ -552,7 +552,7 @@
 {
 	using input_t = int32;
 	using output_t = int64;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return mpt::lshift_signed(static_cast<int64>(val), 32);
 	}
@@ -563,7 +563,7 @@
 {
 	using input_t = somefloat32;
 	using output_t = int64;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		val = mpt::safe_clamp(val, -1.0f, 1.0f);
 		val *= static_cast<float>(uint64(1) << 63);
@@ -576,7 +576,7 @@
 {
 	using input_t = double;
 	using output_t = int64;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		val = std::clamp(val, -1.0, 1.0);
 		val *= static_cast<double>(uint64(1) << 63);
@@ -589,7 +589,7 @@
 {
 	using input_t = uint8;
 	using output_t = somefloat32;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<somefloat32>(static_cast<int>(val) - 0x80) * (1.0f / static_cast<somefloat32>(static_cast<uint8>(1) << 7));
 	}
@@ -600,7 +600,7 @@
 {
 	using input_t = int8;
 	using output_t = somefloat32;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<somefloat32>(val) * (1.0f / static_cast<float>(static_cast<uint8>(1) << 7));
 	}
@@ -611,7 +611,7 @@
 {
 	using input_t = int16;
 	using output_t = somefloat32;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<somefloat32>(val) * (1.0f / static_cast<float>(static_cast<uint16>(1) << 15));
 	}
@@ -622,7 +622,7 @@
 {
 	using input_t = int24;
 	using output_t = somefloat32;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<somefloat32>(val) * (1.0f / static_cast<float>(static_cast<uint32>(1) << 23));
 	}
@@ -633,7 +633,7 @@
 {
 	using input_t = int32;
 	using output_t = somefloat32;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<somefloat32>(val) * (1.0f / static_cast<float>(static_cast<uint32>(1) << 31));
 	}
@@ -644,7 +644,7 @@
 {
 	using input_t = int64;
 	using output_t = somefloat32;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<somefloat32>(val) * (1.0f / static_cast<float>(static_cast<uint64>(1) << 63));
 	}
@@ -655,7 +655,7 @@
 {
 	using input_t = uint8;
 	using output_t = double;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<double>(static_cast<int>(val) - 0x80) * (1.0 / static_cast<double>(static_cast<uint8>(1) << 7));
 	}
@@ -666,7 +666,7 @@
 {
 	using input_t = int8;
 	using output_t = double;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<double>(val) * (1.0 / static_cast<double>(static_cast<uint8>(1) << 7));
 	}
@@ -677,7 +677,7 @@
 {
 	using input_t = int16;
 	using output_t = double;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<double>(val) * (1.0 / static_cast<double>(static_cast<uint16>(1) << 15));
 	}
@@ -688,7 +688,7 @@
 {
 	using input_t = int24;
 	using output_t = double;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<double>(val) * (1.0 / static_cast<double>(static_cast<uint32>(1) << 23));
 	}
@@ -699,7 +699,7 @@
 {
 	using input_t = int32;
 	using output_t = double;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<double>(val) * (1.0 / static_cast<double>(static_cast<uint32>(1) << 31));
 	}
@@ -710,7 +710,7 @@
 {
 	using input_t = int64;
 	using output_t = double;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<double>(val) * (1.0 / static_cast<double>(static_cast<uint64>(1) << 63));
 	}
@@ -721,7 +721,7 @@
 {
 	using input_t = float;
 	using output_t = double;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<double>(val);
 	}
@@ -732,7 +732,7 @@
 {
 	using input_t = double;
 	using output_t = float;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		return static_cast<float>(val);
 	}
@@ -741,7 +741,7 @@
 
 
 template <typename Tdst, typename Tsrc>
-MPT_FORCEINLINE Tdst sample_cast(Tsrc src)
+MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE Tdst sample_cast(Tsrc src)
 {
 	return SC::Convert<Tdst, Tsrc>{}(src);
 }
Index: src/openmpt/soundbase/SampleConvertFixedPoint.hpp
===================================================================
--- src/openmpt/soundbase/SampleConvertFixedPoint.hpp	(revision 23566)
+++ src/openmpt/soundbase/SampleConvertFixedPoint.hpp	(working copy)
@@ -35,7 +35,7 @@
 	using input_t = int32;
 	using output_t = uint8;
 	static constexpr int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t) * 8 - 1);
 		static_assert(shiftBits >= 1);
@@ -52,7 +52,7 @@
 	using input_t = int32;
 	using output_t = int8;
 	static constexpr int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t) * 8 - 1);
 		static_assert(shiftBits >= 1);
@@ -69,7 +69,7 @@
 	using input_t = int32;
 	using output_t = int16;
 	static constexpr int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t) * 8 - 1);
 		static_assert(shiftBits >= 1);
@@ -86,7 +86,7 @@
 	using input_t = int32;
 	using output_t = int24;
 	static constexpr int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t) * 8 - 1);
 		static_assert(shiftBits >= 1);
@@ -102,7 +102,7 @@
 {
 	using input_t = int32;
 	using output_t = int32;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t) * 8 - 1);
 		return static_cast<int32>(std::clamp(val, static_cast<int32>(-((1 << fractionalBits) - 1)), static_cast<int32>(1 << fractionalBits) - 1)) << (sizeof(input_t) * 8 - 1 - fractionalBits);
@@ -115,12 +115,12 @@
 	using input_t = int32;
 	using output_t = somefloat32;
 	const float factor;
-	MPT_FORCEINLINE ConvertFixedPoint()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE ConvertFixedPoint()
 		: factor(1.0f / static_cast<float>(1 << fractionalBits))
 	{
 		return;
 	}
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t) * 8 - 1);
 		return static_cast<somefloat32>(val) * factor;
@@ -133,12 +133,12 @@
 	using input_t = int32;
 	using output_t = somefloat64;
 	const double factor;
-	MPT_FORCEINLINE ConvertFixedPoint()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE ConvertFixedPoint()
 		: factor(1.0 / static_cast<double>(1 << fractionalBits))
 	{
 		return;
 	}
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t) * 8 - 1);
 		return static_cast<somefloat64>(val) * factor;
@@ -155,7 +155,7 @@
 	using input_t = uint8;
 	using output_t = int32;
 	static constexpr int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t) * 8 - 1);
 		static_assert(shiftBits >= 1);
@@ -169,7 +169,7 @@
 	using input_t = int8;
 	using output_t = int32;
 	static constexpr int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t) * 8 - 1);
 		static_assert(shiftBits >= 1);
@@ -183,7 +183,7 @@
 	using input_t = int16;
 	using output_t = int32;
 	static constexpr int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t) * 8 - 1);
 		static_assert(shiftBits >= 1);
@@ -197,7 +197,7 @@
 	using input_t = int24;
 	using output_t = int32;
 	static constexpr int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t) * 8 - 1);
 		static_assert(shiftBits >= 1);
@@ -210,7 +210,7 @@
 {
 	using input_t = int32;
 	using output_t = int32;
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t) * 8 - 1);
 		return mpt::rshift_signed(static_cast<output_t>(val), (sizeof(input_t) * 8 - 1 - fractionalBits));
@@ -223,12 +223,12 @@
 	using input_t = somefloat32;
 	using output_t = int32;
 	const float factor;
-	MPT_FORCEINLINE ConvertToFixedPoint()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE ConvertToFixedPoint()
 		: factor(static_cast<float>(1 << fractionalBits))
 	{
 		return;
 	}
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t) * 8 - 1);
 		val = mpt::sanitize_nan(val);
@@ -242,12 +242,12 @@
 	using input_t = somefloat64;
 	using output_t = int32;
 	const double factor;
-	MPT_FORCEINLINE ConvertToFixedPoint()
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE ConvertToFixedPoint()
 		: factor(static_cast<double>(1 << fractionalBits))
 	{
 		return;
 	}
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t) * 8 - 1);
 		val = mpt::sanitize_nan(val);
Index: src/openmpt/soundbase/SampleDecode.hpp
===================================================================
--- src/openmpt/soundbase/SampleDecode.hpp	(revision 23566)
+++ src/openmpt/soundbase/SampleDecode.hpp	(working copy)
@@ -49,7 +49,7 @@
 	using input_t = std::byte;
 	using output_t = int8;
 	static constexpr std::size_t input_inc = 1;
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		return mpt::byte_cast<int8>(*inBuf);
 	}
@@ -60,7 +60,7 @@
 	using input_t = std::byte;
 	using output_t = int8;
 	static constexpr std::size_t input_inc = 1;
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		return static_cast<int8>(static_cast<int>(mpt::byte_cast<uint8>(*inBuf)) - 128);
 	}
@@ -76,7 +76,7 @@
 		: delta(0)
 	{
 	}
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		delta += mpt::byte_cast<uint8>(*inBuf);
 		return static_cast<int8>(delta);
@@ -125,7 +125,7 @@
 		    56,    48,    40,    32,    24,    16,     8,     0
 	};
 	// clang-format on
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		return uLawTable[mpt::byte_cast<uint8>(*inBuf)];
 	}
@@ -173,7 +173,7 @@
 		   944,   912,  1008,   976,   816,   784,   880,   848
 	};
 	// clang-format on
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		return ALawTable[mpt::byte_cast<uint8>(*inBuf)];
 	}
@@ -185,7 +185,7 @@
 	using input_t = std::byte;
 	using output_t = int16;
 	static constexpr std::size_t input_inc = 2;
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		return static_cast<int16>((mpt::byte_cast<uint8>(inBuf[loByteIndex]) | (mpt::byte_cast<uint8>(inBuf[hiByteIndex]) << 8)) - offset);
 	}
@@ -202,7 +202,7 @@
 		: delta(0)
 	{
 	}
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		delta += static_cast<uint16>(static_cast<uint16>(mpt::byte_cast<uint8>(inBuf[loByteIndex])) | static_cast<uint16>(mpt::byte_cast<uint8>(inBuf[hiByteIndex]) << 8));
 		return static_cast<int16>(delta);
@@ -219,7 +219,7 @@
 		: delta(0)
 	{
 	}
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		delta += mpt::byte_cast<uint8>(inBuf[0]);
 		int16 result = delta & 0xFF;
@@ -235,7 +235,7 @@
 	using input_t = std::byte;
 	using output_t = int32;
 	static constexpr std::size_t input_inc = 3;
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		const uint32 tmp = (uint32(0)
 							| (static_cast<uint32>(mpt::byte_cast<uint8>(inBuf[loByteIndex])) << 8)
@@ -252,7 +252,7 @@
 	using input_t = std::byte;
 	using output_t = int32;
 	static constexpr std::size_t input_inc = 4;
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		const uint32 tmp = (uint32(0)
 							| (static_cast<uint32>(mpt::byte_cast<uint8>(inBuf[loLoByteIndex])) << 0)
@@ -270,7 +270,7 @@
 	using input_t = std::byte;
 	using output_t = int64;
 	static constexpr std::size_t input_inc = 8;
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		const uint64 tmp = (uint64(0)
 							| (static_cast<uint64>(mpt::byte_cast<uint8>(inBuf[b0])) << 0)
@@ -292,7 +292,7 @@
 	using input_t = std::byte;
 	using output_t = somefloat32;
 	static constexpr std::size_t input_inc = 4;
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		somefloat32 val = IEEE754binary32LE(inBuf[loLoByteIndex], inBuf[loHiByteIndex], inBuf[hiLoByteIndex], inBuf[hiHiByteIndex]);
 		val = mpt::sanitize_nan(val);
@@ -317,7 +317,7 @@
 	using output_t = somefloat32;
 	static constexpr std::size_t input_inc = 4;
 	float factor;
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		somefloat32 val = IEEE754binary32LE(inBuf[loLoByteIndex], inBuf[loHiByteIndex], inBuf[hiLoByteIndex], inBuf[hiHiByteIndex]);
 		val = mpt::sanitize_nan(val);
@@ -333,7 +333,7 @@
 		}
 		return factor * val;
 	}
-	MPT_FORCEINLINE DecodeScaledFloat32(float scaleFactor)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE DecodeScaledFloat32(float scaleFactor)
 		: factor(scaleFactor)
 	{
 		return;
@@ -346,7 +346,7 @@
 	using input_t = std::byte;
 	using output_t = somefloat64;
 	static constexpr std::size_t input_inc = 8;
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		somefloat64 val = IEEE754binary64LE(inBuf[b0], inBuf[b1], inBuf[b2], inBuf[b3], inBuf[b4], inBuf[b5], inBuf[b6], inBuf[b7]);
 		val = mpt::sanitize_nan(val);
@@ -370,7 +370,7 @@
 	using input_t = Tsample;
 	using output_t = Tsample;
 	static constexpr std::size_t input_inc = 1;
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		return *inBuf;
 	}
@@ -387,11 +387,11 @@
 	static constexpr std::size_t input_inc = Func1::input_inc;
 	Func1 func1;
 	Func2 func2;
-	MPT_FORCEINLINE output_t operator()(const input_t *inBuf)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(const input_t *inBuf)
 	{
 		return func2(func1(inBuf));
 	}
-	MPT_FORCEINLINE ConversionChain(Func2 f2 = Func2(), Func1 f1 = Func1())
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE ConversionChain(Func2 f2 = Func2(), Func1 f1 = Func1())
 		: func1(f1)
 		, func2(f2)
 	{
Index: src/openmpt/soundbase/SampleEncode.hpp
===================================================================
--- src/openmpt/soundbase/SampleEncode.hpp	(revision 23566)
+++ src/openmpt/soundbase/SampleEncode.hpp	(working copy)
@@ -31,7 +31,7 @@
 	using output_t = std::byte;
 	static constexpr uint8 exp_table[17] = {0, 7 << 4, 6 << 4, 5 << 4, 4 << 4, 3 << 4, 2 << 4, 1 << 4, 0 << 4, 0, 0, 0, 0, 0, 0, 0, 0};
 	static constexpr uint8 mant_table[17] = {0, 10, 9, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3};
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		uint16 x = static_cast<uint16>(val);
 		uint8 out = static_cast<uint8>((x >> 8) & 0x80u);
@@ -57,7 +57,7 @@
 	using output_t = std::byte;
 	static constexpr uint8 exp_table[17] = {0, 7 << 4, 6 << 4, 5 << 4, 4 << 4, 3 << 4, 2 << 4, 1 << 4, 0 << 4, 0, 0, 0, 0, 0, 0, 0, 0};
 	static constexpr uint8 mant_table[17] = {0, 10, 9, 8, 7, 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};
-	MPT_FORCEINLINE output_t operator()(input_t val)
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE output_t operator()(input_t val)
 	{
 		int16 sx = std::clamp(val, static_cast<int16>(-32767), static_cast<int16>(32767));
 		uint16 x = static_cast<uint16>(sx);
Index: src/openmpt/soundbase/SampleFormat.hpp
===================================================================
--- src/openmpt/soundbase/SampleFormat.hpp	(revision 23566)
+++ src/openmpt/soundbase/SampleFormat.hpp	(working copy)
@@ -44,7 +44,7 @@
 	SampleFormat::Enum value;
 
 	template <typename T>
-	static MPT_CONSTEXPRINLINE SampleFormat::Enum Sanitize(T x) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static SampleFormat::Enum Sanitize(T x) noexcept
 	{
 		using uT = typename std::make_unsigned<T>::type;
 		uT val = static_cast<uT>(x);
@@ -181,53 +181,53 @@
 	}
 
 public:
-	MPT_CONSTEXPRINLINE SampleFormat() noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr SampleFormat() noexcept
 		: value(SampleFormat::Default)
 	{
 	}
 
-	MPT_CONSTEXPRINLINE SampleFormat(SampleFormat::Enum v) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr SampleFormat(SampleFormat::Enum v) noexcept
 		: value(Sanitize(v))
 	{
 	}
 
-	friend MPT_CONSTEXPRINLINE bool operator==(const SampleFormat &a, const SampleFormat &b) noexcept
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(const SampleFormat &a, const SampleFormat &b) noexcept
 	{
 		return a.value == b.value;
 	}
-	friend MPT_CONSTEXPRINLINE bool operator!=(const SampleFormat &a, const SampleFormat &b) noexcept
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(const SampleFormat &a, const SampleFormat &b) noexcept
 	{
 		return a.value != b.value;
 	}
-	friend MPT_CONSTEXPRINLINE bool operator==(const SampleFormat::Enum &a, const SampleFormat &b) noexcept
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(const SampleFormat::Enum &a, const SampleFormat &b) noexcept
 	{
 		return a == b.value;
 	}
-	friend MPT_CONSTEXPRINLINE bool operator!=(const SampleFormat::Enum &a, const SampleFormat &b) noexcept
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(const SampleFormat::Enum &a, const SampleFormat &b) noexcept
 	{
 		return a != b.value;
 	}
-	friend MPT_CONSTEXPRINLINE bool operator==(const SampleFormat &a, const SampleFormat::Enum &b) noexcept
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator==(const SampleFormat &a, const SampleFormat::Enum &b) noexcept
 	{
 		return a.value == b;
 	}
-	friend MPT_CONSTEXPRINLINE bool operator!=(const SampleFormat &a, const SampleFormat::Enum &b) noexcept
+	MPT_ATTR_ALWAYSINLINE friend MPT_INLINE_FORCE constexpr bool operator!=(const SampleFormat &a, const SampleFormat::Enum &b) noexcept
 	{
 		return a.value != b;
 	}
 
-	MPT_CONSTEXPRINLINE bool IsUnsigned() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool IsUnsigned() const noexcept
 	{
 		return false
 			|| (value == SampleFormat::Unsigned8);
 	}
-	MPT_CONSTEXPRINLINE bool IsFloat() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool IsFloat() const noexcept
 	{
 		return false
 			|| (value == SampleFormat::Float32)
 			|| (value == SampleFormat::Float64);
 	}
-	MPT_CONSTEXPRINLINE bool IsInt() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr bool IsInt() const noexcept
 	{
 		return false
 			|| (value == SampleFormat::Unsigned8)
@@ -236,7 +236,7 @@
 			|| (value == SampleFormat::Int24)
 			|| (value == SampleFormat::Int32);
 	}
-	MPT_CONSTEXPRINLINE uint8 GetSampleSize() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint8 GetSampleSize() const noexcept
 	{
 		return false                              ? 0
 			 : (value == SampleFormat::Unsigned8) ? 1
@@ -248,7 +248,7 @@
 			 : (value == SampleFormat::Float64)   ? 8
 												  : 0;
 	}
-	MPT_CONSTEXPRINLINE uint8 GetBitsPerSample() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr uint8 GetBitsPerSample() const noexcept
 	{
 		return false                              ? 0
 			 : (value == SampleFormat::Unsigned8) ? 8
@@ -261,17 +261,17 @@
 												  : 0;
 	}
 
-	MPT_CONSTEXPRINLINE operator SampleFormat::Enum() const noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr operator SampleFormat::Enum() const noexcept
 	{
 		return value;
 	}
 
 	// backward compatibility, conversion to/from integers
-	static MPT_CONSTEXPRINLINE SampleFormat FromInt(int x) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static SampleFormat FromInt(int x) noexcept
 	{
 		return SampleFormat(Sanitize(x));
 	}
-	static MPT_CONSTEXPRINLINE int ToInt(SampleFormat x) noexcept
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static int ToInt(SampleFormat x) noexcept
 	{
 		return mpt::to_underlying(x.value);
 	}
@@ -295,37 +295,37 @@
 template <>
 struct SampleFormatTraits<uint8>
 {
-	static MPT_CONSTEXPRINLINE SampleFormat sampleFormat() { return SampleFormat::Unsigned8; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static SampleFormat sampleFormat() { return SampleFormat::Unsigned8; }
 };
 template <>
 struct SampleFormatTraits<int8>
 {
-	static MPT_CONSTEXPRINLINE SampleFormat sampleFormat() { return SampleFormat::Int8; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static SampleFormat sampleFormat() { return SampleFormat::Int8; }
 };
 template <>
 struct SampleFormatTraits<int16>
 {
-	static MPT_CONSTEXPRINLINE SampleFormat sampleFormat() { return SampleFormat::Int16; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static SampleFormat sampleFormat() { return SampleFormat::Int16; }
 };
 template <>
 struct SampleFormatTraits<int24>
 {
-	static MPT_CONSTEXPRINLINE SampleFormat sampleFormat() { return SampleFormat::Int24; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static SampleFormat sampleFormat() { return SampleFormat::Int24; }
 };
 template <>
 struct SampleFormatTraits<int32>
 {
-	static MPT_CONSTEXPRINLINE SampleFormat sampleFormat() { return SampleFormat::Int32; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static SampleFormat sampleFormat() { return SampleFormat::Int32; }
 };
 template <>
 struct SampleFormatTraits<float>
 {
-	static MPT_CONSTEXPRINLINE SampleFormat sampleFormat() { return SampleFormat::Float32; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static SampleFormat sampleFormat() { return SampleFormat::Float32; }
 };
 template <>
 struct SampleFormatTraits<double>
 {
-	static MPT_CONSTEXPRINLINE SampleFormat sampleFormat() { return SampleFormat::Float64; }
+	MPT_ATTR_ALWAYSINLINE MPT_INLINE_FORCE constexpr static SampleFormat sampleFormat() { return SampleFormat::Float64; }
 };
 
 template <SampleFormat::Enum sampleFormat>
Index: test/test.cpp
===================================================================
--- test/test.cpp	(revision 23566)
+++ test/test.cpp	(working copy)
@@ -136,24 +136,24 @@
 
 
 
-static MPT_NOINLINE void TestVersion();
-static MPT_NOINLINE void TestTypes();
-static MPT_NOINLINE void TestMisc1();
-static MPT_NOINLINE void TestMisc2();
-static MPT_NOINLINE void TestRandom();
-static MPT_NOINLINE void TestCharsets();
-static MPT_NOINLINE void TestPathNative();
-static MPT_NOINLINE void TestPathForeign();
-static MPT_NOINLINE void TestStringFormatting();
-static MPT_NOINLINE void TestSettings();
-static MPT_NOINLINE void TestStringIO();
-static MPT_NOINLINE void TestMIDIEvents();
-static MPT_NOINLINE void TestSampleConversion();
-static MPT_NOINLINE void TestITCompression();
-static MPT_NOINLINE void TestPCnoteSerialization();
-static MPT_NOINLINE void TestLoadSaveFile();
-static MPT_NOINLINE void TestEditing();
-static MPT_NOINLINE void TestMIDIMacroParser();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestVersion();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestTypes();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestMisc1();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestMisc2();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestRandom();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestCharsets();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestPathNative();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestPathForeign();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestStringFormatting();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestSettings();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestStringIO();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestMIDIEvents();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestSampleConversion();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestITCompression();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestPCnoteSerialization();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestLoadSaveFile();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestEditing();
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestMIDIMacroParser();
 
 
 
@@ -512,7 +512,7 @@
 
 
 // Test if functions related to program version data work
-static MPT_NOINLINE void TestVersion()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestVersion()
 {
 	//Verify that macros and functions work.
 	{
@@ -666,7 +666,7 @@
 
 
 // Test if data types are interpreted correctly
-static MPT_NOINLINE void TestTypes()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestTypes()
 {
 
 	static_assert(sizeof(std::uintptr_t) == sizeof(void*));
@@ -784,7 +784,7 @@
 
 
 
-static MPT_NOINLINE void TestStringFormatting()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestStringFormatting()
 {
 	VERIFY_EQUAL(mpt::afmt::val(1.5f), "1.5");
 	VERIFY_EQUAL(mpt::afmt::val(true), "1");
@@ -1052,7 +1052,7 @@
 }
 
 
-static MPT_NOINLINE void TestMisc1()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestMisc1()
 {
 
 	VERIFY_EQUAL(ModCommand::IsPcNote(NOTE_MAX), false);
@@ -1173,7 +1173,7 @@
 }
 
 
-static MPT_NOINLINE void TestMisc2()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestMisc2()
 {
 
 	// Check for completeness of supported effect list in mod specifications
@@ -1551,7 +1551,7 @@
 }
 
 
-static MPT_NOINLINE void TestRandom()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestRandom()
 {
 
 	#ifdef FLAKY_TESTS
@@ -1604,7 +1604,7 @@
 }
 
 
-static MPT_NOINLINE void TestPathNative()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestPathNative()
 {
 
 	// Path splitting
@@ -1865,7 +1865,7 @@
 
 #if !defined(MPT_EMSCRIPTEN_TEST_PATH_CRASH)
 
-static MPT_NOINLINE void TestPathForeignWindowsNT()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestPathForeignWindowsNT()
 {
 	{
 		using P = mpt::BasicPathString<mpt::PathTraits<std::string, mpt::PathStyleTag<mpt::PathStyle::WindowsNT>>>;
@@ -2028,7 +2028,7 @@
 	}
 }
 
-static MPT_NOINLINE void TestPathForeignWindows9x()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestPathForeignWindows9x()
 {
 	{
 		using P = mpt::BasicPathString<mpt::PathTraits<std::string, mpt::PathStyleTag<mpt::PathStyle::Windows9x>>>;
@@ -2175,7 +2175,7 @@
 	}
 }
 
-static MPT_NOINLINE void TestPathForeignDOSDJGPP()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestPathForeignDOSDJGPP()
 {
 	{
 		using P = mpt::BasicPathString<mpt::PathTraits<std::string, mpt::PathStyleTag<mpt::PathStyle::DOS_DJGPP>>>;
@@ -2282,7 +2282,7 @@
 	}
 }
 
-static MPT_NOINLINE void TestPathForeignPOSIX()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestPathForeignPOSIX()
 {
 	{
 		using P = mpt::BasicPathString<mpt::PathTraits<std::string, mpt::PathStyleTag<mpt::PathStyle::Posix>>>;
@@ -2343,7 +2343,7 @@
 #endif // !MPT_EMSCRIPTEN_TEST_PATH_CRASH
 
 
-static MPT_NOINLINE void TestPathForeign()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestPathForeign()
 {
 
 #if !defined(MPT_EMSCRIPTEN_TEST_PATH_CRASH)
@@ -2423,7 +2423,7 @@
 
 
 
-static MPT_NOINLINE void TestCharsets()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestCharsets()
 {
 
 	// Path conversions
@@ -2599,7 +2599,7 @@
 #endif // MODPLUG_TRACKER
 
 
-static MPT_NOINLINE void TestSettings()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestSettings()
 {
 
 #ifdef MODPLUG_TRACKER
@@ -2679,7 +2679,7 @@
 
 
 // Test MIDI Event generating / reading
-static MPT_NOINLINE void TestMIDIEvents()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestMIDIEvents()
 {
 	uint32 midiEvent;
 
@@ -3690,7 +3690,7 @@
 
 
 // Test file loading and saving
-static MPT_NOINLINE void TestLoadSaveFile()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestLoadSaveFile()
 {
 	if(!ShouldRunTests())
 	{
@@ -3925,7 +3925,7 @@
 
 
 // Test various editing features
-static MPT_NOINLINE void TestEditing()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestEditing()
 {
 #ifdef MODPLUG_TRACKER
 	auto modDoc = static_cast<CModDoc *>(theApp.GetModDocTemplate()->CreateNewDocument());
@@ -4025,7 +4025,7 @@
 }
 
 
-static MPT_NOINLINE void TestITCompression()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestITCompression()
 {
 	// Test loading / saving of IT-compressed samples
 	constexpr int sampleDataSize = 131072;
@@ -4132,7 +4132,7 @@
 
 
 // Test PC note serialization
-static MPT_NOINLINE void TestPCnoteSerialization()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestPCnoteSerialization()
 {
 	FileReader file;
 	mpt::heap_value<CSoundFile> pSndFile;
@@ -4195,7 +4195,7 @@
 
 // Test String I/O functionality
 
-static MPT_NOINLINE void TestStringIO1()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestStringIO1()
 {
 
 #if MPT_COMPILER_MSVC
@@ -4453,7 +4453,7 @@
 	}
 }
 
-static MPT_NOINLINE void TestStringIO2()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestStringIO2()
 {
 	{
 	
@@ -4567,13 +4567,13 @@
 	}
 }
 
-static MPT_NOINLINE void TestStringIO()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestStringIO()
 {
 	TestStringIO1();
 	TestStringIO2();
 }
 
-static MPT_NOINLINE void TestSampleConversion()
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE static void TestSampleConversion()
 {
 	// Signed 8-Bit Integer PCM
 	// Unsigned 8-Bit Integer PCM
Index: test/TestToolsLib.cpp
===================================================================
--- test/TestToolsLib.cpp	(revision 23566)
+++ test/TestToolsLib.cpp	(working copy)
@@ -240,7 +240,7 @@
 
 #if defined(MPT_ASSERT_HANDLER_NEEDED)
 
-MPT_NOINLINE void AssertHandler(const mpt::source_location &loc, const char *expr, const char *msg)
+MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void AssertHandler(const mpt::source_location &loc, const char *expr, const char *msg)
 {
 	Test::fail_count++;
 	if(msg)
Index: test/TestToolsLib.h
===================================================================
--- test/TestToolsLib.h	(revision 23566)
+++ test/TestToolsLib.h	(working copy)
@@ -219,7 +219,7 @@
 private:
 
 	template <typename Tx, typename Ty>
-	MPT_NOINLINE void TypeCompareHelper(const Tx &x, const Ty &y)
+	MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void TypeCompareHelper(const Tx &x, const Ty &y)
 	{
 		if(!IsEqual(x, y, std::is_integral<Tx>(), std::is_integral<Ty>()))
 		{
@@ -229,7 +229,7 @@
 	}
 
 	template <typename Tx, typename Ty, typename Teps>
-	MPT_NOINLINE void TypeCompareHelper(const Tx &x, const Ty &y, const Teps &eps)
+	MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void TypeCompareHelper(const Tx &x, const Ty &y, const Teps &eps)
 	{
 		if(!IsEqualEpsilon(x, y, eps))
 		{
@@ -241,7 +241,7 @@
 public:
 
 	template <typename Tfx, typename Tfy>
-	MPT_NOINLINE void operator () (const Tfx &fx, const Tfy &fy)
+	MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void operator () (const Tfx &fx, const Tfy &fy)
 	{
 		ShowStart();
 		try
@@ -260,7 +260,7 @@
 	}
 
 	template <typename Tfx, typename Tfy, typename Teps>
-	MPT_NOINLINE void operator () (const Tfx &fx, const Tfy &fy, const Teps &eps)
+	MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void operator () (const Tfx &fx, const Tfy &fy, const Teps &eps)
 	{
 		ShowStart();
 		try
@@ -289,7 +289,7 @@
 public:
 
 	template <typename Tx, typename Ty>
-	MPT_NOINLINE void operator () (const Tx &x, const Ty &y)
+	MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void operator () (const Tx &x, const Ty &y)
 	{
 		ShowStart();
 		try
@@ -307,7 +307,7 @@
 	}
 
 	template <typename Tx, typename Ty, typename Teps>
-	MPT_NOINLINE void operator () (const Tx &x, const Ty &y, const Teps &eps)
+	MPT_ATTR_NOINLINE MPT_DECL_NOINLINE void operator () (const Tx &x, const Ty &y, const Teps &eps)
 	{
 		ShowStart();
 		try
