From c7a7d682bcfafe48ef14d49a6535610c95491f9f Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 26 Oct 2019 15:41:43 +1000 Subject: [PATCH] Common: Force inlining of BitField/SignExtend/ZeroExtend functions --- src/common/bitfield.h | 42 ++++++++++++------------ src/common/types.h | 74 ++++++++++++++++++++----------------------- 2 files changed, 56 insertions(+), 60 deletions(-) diff --git a/src/common/bitfield.h b/src/common/bitfield.h index 0f4137f8c..86dd8f7c2 100644 --- a/src/common/bitfield.h +++ b/src/common/bitfield.h @@ -1,4 +1,5 @@ #pragma once +#include "types.h" #include // Disable MSVC warnings that we actually handle @@ -10,105 +11,107 @@ template struct BitField { + static_assert(!std::is_same_v || BitCount == 1, "Boolean bitfields should only be 1 bit"); + // We have to delete the copy assignment operator otherwise we can't use this class in anonymous structs/unions. BitField& operator=(const BitField& rhs) = delete; - constexpr BackingDataType GetMask() const + ALWAYS_INLINE constexpr BackingDataType GetMask() const { return ((static_cast(~0)) >> (8 * sizeof(BackingDataType) - BitCount)) << BitIndex; } - operator DataType() const { return GetValue(); } + ALWAYS_INLINE operator DataType() const { return GetValue(); } - BitField& operator=(DataType value) + ALWAYS_INLINE BitField& operator=(DataType value) { SetValue(value); return *this; } - DataType operator++() + ALWAYS_INLINE DataType operator++() { DataType value = GetValue() + 1; SetValue(value); return GetValue(); } - DataType operator++(int) + ALWAYS_INLINE DataType operator++(int) { DataType value = GetValue(); SetValue(value + 1); return value; } - DataType operator--() + ALWAYS_INLINE DataType operator--() { DataType value = GetValue() - 1; SetValue(value); return GetValue(); } - DataType operator--(int) + ALWAYS_INLINE DataType operator--(int) { DataType value = GetValue(); SetValue(value - 1); return value; } - BitField& operator+=(DataType rhs) + ALWAYS_INLINE BitField& operator+=(DataType rhs) { SetValue(GetValue() + rhs); return *this; } - BitField& operator-=(DataType rhs) + ALWAYS_INLINE BitField& operator-=(DataType rhs) { SetValue(GetValue() - rhs); return *this; } - BitField& operator*=(DataType rhs) + ALWAYS_INLINE BitField& operator*=(DataType rhs) { SetValue(GetValue() * rhs); return *this; } - BitField& operator/=(DataType rhs) + ALWAYS_INLINE BitField& operator/=(DataType rhs) { SetValue(GetValue() / rhs); return *this; } - BitField& operator&=(DataType rhs) + ALWAYS_INLINE BitField& operator&=(DataType rhs) { SetValue(GetValue() & rhs); return *this; } - BitField& operator|=(DataType rhs) + ALWAYS_INLINE BitField& operator|=(DataType rhs) { SetValue(GetValue() | rhs); return *this; } - BitField& operator^=(DataType rhs) + ALWAYS_INLINE BitField& operator^=(DataType rhs) { SetValue(GetValue() ^ rhs); return *this; } - BitField& operator<<=(DataType rhs) + ALWAYS_INLINE BitField& operator<<=(DataType rhs) { SetValue(GetValue() << rhs); return *this; } - BitField& operator>>=(DataType rhs) + ALWAYS_INLINE BitField& operator>>=(DataType rhs) { SetValue(GetValue() >> rhs); return *this; } - DataType GetValue() const + ALWAYS_INLINE DataType GetValue() const { if constexpr (std::is_same_v) { @@ -125,10 +128,9 @@ struct BitField } } - void SetValue(DataType value) + ALWAYS_INLINE void SetValue(DataType value) { - data &= ~GetMask(); - data |= (static_cast(value) << BitIndex) & GetMask(); + data = (data & ~GetMask()) | (static_cast(value) << BitIndex) & GetMask(); } BackingDataType data; diff --git a/src/common/types.h b/src/common/types.h index 9f3aa9138..a5b33c021 100644 --- a/src/common/types.h +++ b/src/common/types.h @@ -42,33 +42,33 @@ using CycleCount = int64_t; using SimulationTime = int64_t; // Helpers for simulation time. -constexpr SimulationTime SecondsToSimulationTime(SimulationTime s) +ALWAYS_INLINE constexpr SimulationTime SecondsToSimulationTime(SimulationTime s) { return s * INT64_C(1000000000); } -constexpr SimulationTime MillisecondsToSimulationTime(SimulationTime ms) +ALWAYS_INLINE constexpr SimulationTime MillisecondsToSimulationTime(SimulationTime ms) { return ms * INT64_C(1000000); } -constexpr SimulationTime MicrosecondsToSimulationTime(SimulationTime us) +ALWAYS_INLINE constexpr SimulationTime MicrosecondsToSimulationTime(SimulationTime us) { return us * INT64_C(1000); } -constexpr SimulationTime SimulationTimeToSeconds(SimulationTime s) +ALWAYS_INLINE constexpr SimulationTime SimulationTimeToSeconds(SimulationTime s) { return s / INT64_C(1000000000); } -constexpr SimulationTime SimulationTimeToMilliseconds(SimulationTime ms) +ALWAYS_INLINE constexpr SimulationTime SimulationTimeToMilliseconds(SimulationTime ms) { return ms / INT64_C(1000000); } -constexpr SimulationTime SimulationTimeToMicroseconds(SimulationTime us) +ALWAYS_INLINE constexpr SimulationTime SimulationTimeToMicroseconds(SimulationTime us) { return us / INT64_C(1000); } // Calculates the difference between the specified timestamps, accounting for signed overflow. -constexpr SimulationTime GetSimulationTimeDifference(SimulationTime prev, SimulationTime now) +ALWAYS_INLINE constexpr SimulationTime GetSimulationTimeDifference(SimulationTime prev, SimulationTime now) { if (prev <= now) return now - prev; @@ -78,111 +78,105 @@ constexpr SimulationTime GetSimulationTimeDifference(SimulationTime prev, Simula // Zero-extending helper template -constexpr TReturn ZeroExtend(TValue value) +ALWAYS_INLINE constexpr TReturn ZeroExtend(TValue value) { - // auto unsigned_val = static_cast::type>(value); - // auto extended_val = static_cast::type>(unsigned_val); - // return static_cast(extended_val); return static_cast(static_cast::type>( static_cast::type>(value))); } // Sign-extending helper template -constexpr TReturn SignExtend(TValue value) +ALWAYS_INLINE constexpr TReturn SignExtend(TValue value) { - // auto signed_val = static_cast::type>(value); - // auto extended_val = static_cast::type>(signed_val); - // return static_cast(extended_val); return static_cast( static_cast::type>(static_cast::type>(value))); } // Type-specific helpers template -constexpr u16 ZeroExtend16(TValue value) +ALWAYS_INLINE constexpr u16 ZeroExtend16(TValue value) { return ZeroExtend(value); } template -constexpr u32 ZeroExtend32(TValue value) +ALWAYS_INLINE constexpr u32 ZeroExtend32(TValue value) { return ZeroExtend(value); } template -constexpr u64 ZeroExtend64(TValue value) +ALWAYS_INLINE constexpr u64 ZeroExtend64(TValue value) { return ZeroExtend(value); } template -constexpr u16 SignExtend16(TValue value) +ALWAYS_INLINE constexpr u16 SignExtend16(TValue value) { return SignExtend(value); } template -constexpr u32 SignExtend32(TValue value) +ALWAYS_INLINE constexpr u32 SignExtend32(TValue value) { return SignExtend(value); } template -constexpr u64 SignExtend64(TValue value) +ALWAYS_INLINE constexpr u64 SignExtend64(TValue value) { return SignExtend(value); } template -constexpr u8 Truncate8(TValue value) +ALWAYS_INLINE constexpr u8 Truncate8(TValue value) { return static_cast(static_cast::type>(value)); } template -constexpr u16 Truncate16(TValue value) +ALWAYS_INLINE constexpr u16 Truncate16(TValue value) { return static_cast(static_cast::type>(value)); } template -constexpr u32 Truncate32(TValue value) +ALWAYS_INLINE constexpr u32 Truncate32(TValue value) { return static_cast(static_cast::type>(value)); } // BCD helpers -constexpr u8 DecimalToBCD(u8 value) +ALWAYS_INLINE constexpr u8 DecimalToBCD(u8 value) { return ((value / 10) << 4) + (value % 10); } -constexpr u8 BCDToDecimal(u8 value) +ALWAYS_INLINE constexpr u8 BCDToDecimal(u8 value) { return ((value >> 4) * 10) + (value % 16); } // Boolean to integer -constexpr u8 BoolToUInt8(bool value) +ALWAYS_INLINE constexpr u8 BoolToUInt8(bool value) { return static_cast(value); } -constexpr u16 BoolToUInt16(bool value) +ALWAYS_INLINE constexpr u16 BoolToUInt16(bool value) { return static_cast(value); } -constexpr u32 BoolToUInt32(bool value) +ALWAYS_INLINE constexpr u32 BoolToUInt32(bool value) { return static_cast(value); } -constexpr u64 BoolToUInt64(bool value) +ALWAYS_INLINE constexpr u64 BoolToUInt64(bool value) { return static_cast(value); } // Integer to boolean template -constexpr bool ConvertToBool(TValue value) +ALWAYS_INLINE constexpr bool ConvertToBool(TValue value) { return static_cast(value); } // Unsafe integer to boolean template -constexpr bool ConvertToBoolUnchecked(TValue value) +ALWAYS_INLINE constexpr bool ConvertToBoolUnchecked(TValue value) { // static_assert(sizeof(uint8) == sizeof(bool)); bool ret; @@ -192,7 +186,7 @@ constexpr bool ConvertToBoolUnchecked(TValue value) // Generic sign extension template -constexpr T SignExtendN(T value) +ALWAYS_INLINE constexpr T SignExtendN(T value) { // http://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend constexpr int shift = 8 * sizeof(T) - NBITS; @@ -201,38 +195,38 @@ constexpr T SignExtendN(T value) // Enum class bitwise operators #define IMPLEMENT_ENUM_CLASS_BITWISE_OPERATORS(type_) \ - inline constexpr type_ operator&(type_ lhs, type_ rhs) \ + ALWAYS_INLINE constexpr type_ operator&(type_ lhs, type_ rhs) \ { \ return static_cast(static_cast::type>(lhs) & \ static_cast::type>(rhs)); \ } \ - inline constexpr type_ operator|(type_ lhs, type_ rhs) \ + ALWAYS_INLINE constexpr type_ operator|(type_ lhs, type_ rhs) \ { \ return static_cast(static_cast::type>(lhs) | \ static_cast::type>(rhs)); \ } \ - inline constexpr type_ operator^(type_ lhs, type_ rhs) \ + ALWAYS_INLINE constexpr type_ operator^(type_ lhs, type_ rhs) \ { \ return static_cast(static_cast::type>(lhs) ^ \ static_cast::type>(rhs)); \ } \ - inline constexpr type_ operator~(type_ val) \ + ALWAYS_INLINE constexpr type_ operator~(type_ val) \ { \ return static_cast(~static_cast::type>(val)); \ } \ - inline constexpr type_& operator&=(type_& lhs, type_ rhs) \ + ALWAYS_INLINE constexpr type_& operator&=(type_& lhs, type_ rhs) \ { \ lhs = static_cast(static_cast::type>(lhs) & \ static_cast::type>(rhs)); \ return lhs; \ } \ - inline constexpr type_& operator|=(type_& lhs, type_ rhs) \ + ALWAYS_INLINE constexpr type_& operator|=(type_& lhs, type_ rhs) \ { \ lhs = static_cast(static_cast::type>(lhs) | \ static_cast::type>(rhs)); \ return lhs; \ } \ - inline constexpr type_& operator^=(type_& lhs, type_ rhs) \ + ALWAYS_INLINE constexpr type_& operator^=(type_& lhs, type_ rhs) \ { \ lhs = static_cast(static_cast::type>(lhs) ^ \ static_cast::type>(rhs)); \