diff --git a/vpr/src/place/place_delay_model.h b/vpr/src/place/place_delay_model.h index b1fe5ac305e..db22db238ec 100644 --- a/vpr/src/place/place_delay_model.h +++ b/vpr/src/place/place_delay_model.h @@ -6,6 +6,20 @@ #include "vpr_types.h" #include "router_delay_profiling.h" +#ifndef __has_attribute +# define __has_attribute(x) 0 // Compatibility with non-clang compilers. +#endif + +#if defined(COMPILER_GCC) && defined(NDEBUG) +# define ALWAYS_INLINE inline __attribute__((__always_inline__)) +#elif defined(COMPILER_MSVC) && defined(NDEBUG) +# define ALWAYS_INLINE __forceinline +#elif __has_attribute(always_inline) +# define ALWAYS_INLINE __attribute__((always_inline)) // clang +#else +# define ALWAYS_INLINE inline +#endif + //Abstract interface to a placement delay model class PlaceDelayModel { public: @@ -95,13 +109,29 @@ class OverrideDelayModel : public PlaceDelayModel { short delta_x; short delta_y; - friend bool operator<(const t_override& lhs, const t_override& rhs) { - return std::tie(lhs.from_type, lhs.to_type, lhs.from_class, lhs.to_class, lhs.delta_x, lhs.delta_y) - < std::tie(rhs.from_type, rhs.to_type, rhs.from_class, rhs.to_class, rhs.delta_x, rhs.delta_y); + //A combination of ALWAYS_INLINE attribute and std::lexicographical_compare + //is required for operator< to be inlined by compiler. + //Proper inlining of the function reduces place time by around 5%. + //For more information: https://github.com/verilog-to-routing/vtr-verilog-to-routing/issues/1225 + friend ALWAYS_INLINE bool operator<(const t_override& lhs, const t_override& rhs) { + const short* left = reinterpret_cast(&lhs); + const short* right = reinterpret_cast(&rhs); + constexpr size_t NUM_T_OVERRIDE_MEMBERS = sizeof(t_override) / sizeof(short); + return std::lexicographical_compare(left, left + NUM_T_OVERRIDE_MEMBERS, right, right + NUM_T_OVERRIDE_MEMBERS); } }; vtr::flat_map2 delay_overrides_; + + //operator< treats memory layout of t_override as an array of short + //this requires all members of t_override are shorts and there is no padding between members of t_override + static_assert(sizeof(t_override) == sizeof(t_override::from_type) + sizeof(t_override::to_type) + sizeof(t_override::from_class) + sizeof(t_override::to_class) + sizeof(t_override::delta_x) + sizeof(t_override::delta_y), "Expect t_override to have a memory layout equivalent to an array of short (no padding)"); + static_assert(sizeof(t_override::from_type) == sizeof(short), "Expect all t_override data members to be shorts"); + static_assert(sizeof(t_override::to_type) == sizeof(short), "Expect all t_override data members to be shorts"); + static_assert(sizeof(t_override::from_class) == sizeof(short), "Expect all t_override data members to be shorts"); + static_assert(sizeof(t_override::to_class) == sizeof(short), "Expect all t_override data members to be shorts"); + static_assert(sizeof(t_override::delta_x) == sizeof(short), "Expect all t_override data members to be shorts"); + static_assert(sizeof(t_override::delta_y) == sizeof(short), "Expect all t_override data members to be shorts"); }; #endif