Skip to content

Commit 1fc62ff

Browse files
committed
Replace whole-TU arch flags with function-targeted
1 parent e5f2c15 commit 1fc62ff

7 files changed

Lines changed: 35 additions & 45 deletions

File tree

CMakeLists.txt

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,6 @@ option(LIBHAT_EXAMPLES "Include example targets" ${PROJECT_IS_TOP_LEVEL})
2929

3030
option(LIBHAT_HINT_X86_64 "Enables support for the x86_64 scan hint, requires a small (2KB) data table" ON)
3131

32-
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
33-
# Just assume that the compiler accepts the required x86/x64 options if it'll accept -mmmx
34-
# CMake architecture detection SUCKS!!!
35-
check_cxx_compiler_flag("-mmmx" LIBHAT_COMPILER_X86_OPTIONS)
36-
37-
if(LIBHAT_COMPILER_X86_OPTIONS)
38-
set_source_files_properties(src/arch/x86/SSE.cpp PROPERTIES COMPILE_FLAGS "-msse4.1")
39-
set_source_files_properties(src/arch/x86/AVX2.cpp PROPERTIES COMPILE_FLAGS "-mavx -mavx2 -mbmi")
40-
set_source_files_properties(src/arch/x86/AVX512.cpp PROPERTIES COMPILE_FLAGS "-mavx512f -mavx512bw -mbmi")
41-
set_source_files_properties(src/arch/x86/System.cpp PROPERTIES COMPILE_FLAGS "-mxsave")
42-
endif()
43-
endif()
44-
4532
if(LIBHAT_TESTING AND LIBHAT_TESTING_SANITIZE)
4633
if(MSVC)
4734
add_compile_options($<$<AND:$<CONFIG:Debug>,$<CXX_COMPILER_ID:MSVC>>:/fsanitize=address>)

include/libhat/defines.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@
7676
#define LIBHAT_FORCEINLINE inline
7777
#endif
7878

79+
#if defined(__GNUC__) || defined(__clang__)
80+
#define LIBHAT_TARGET(arch) __attribute__((target(arch)))
81+
#else
82+
#define LIBHAT_TARGET(arch)
83+
#endif
84+
7985
#if __has_cpp_attribute(no_unique_address)
8086
#define LIBHAT_NO_UNIQUE_ADDRESS [[no_unique_address]]
8187
#elif __has_cpp_attribute(msvc::no_unique_address)

include/libhat/scanner.hpp

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -192,42 +192,29 @@ namespace hat::detail {
192192
return mask;
193193
}
194194

195-
template<scan_alignment alignment>
196-
LIBHAT_FORCEINLINE const std::byte* next_boundary_align(const std::byte* ptr) {
197-
constexpr auto stride = alignment_stride<alignment>;
198-
if constexpr (stride == 1) {
199-
return ptr;
200-
}
201-
uintptr_t mod = reinterpret_cast<uintptr_t>(ptr) % stride;
202-
ptr += mod ? stride - mod : 0;
203-
return std::assume_aligned<stride>(ptr);
204-
}
205-
206-
template<scan_alignment alignment>
207-
LIBHAT_FORCEINLINE const std::byte* prev_boundary_align(const std::byte* ptr) {
208-
constexpr auto stride = alignment_stride<alignment>;
209-
if constexpr (stride == 1) {
210-
return ptr;
211-
}
212-
const uintptr_t mod = reinterpret_cast<uintptr_t>(ptr) % stride;
213-
return std::assume_aligned<stride>(ptr - mod);
214-
}
215-
216-
template<typename Type>
217-
LIBHAT_FORCEINLINE const std::byte* align_pointer_as(const std::byte* ptr) {
218-
constexpr size_t alignment = alignof(Type);
195+
template<size_t alignment>
196+
LIBHAT_FORCEINLINE const std::byte* align_up(const std::byte* ptr) {
219197
const uintptr_t mod = reinterpret_cast<uintptr_t>(ptr) % alignment;
220198
ptr += mod ? alignment - mod : 0;
221199
return std::assume_aligned<alignment>(ptr);
222200
}
223201

224-
template<typename Vector, bool veccmp>
202+
template<scan_alignment alignment>
203+
LIBHAT_FORCEINLINE const std::byte* align_up(const std::byte* ptr) {
204+
return align_up<alignment_stride<alignment>>(ptr);
205+
}
206+
207+
template<typename Vector, size_t alignment, bool veccmp>
225208
LIBHAT_FORCEINLINE auto segment_scan(
226209
const std::byte* begin,
227210
const std::byte* end,
228211
const size_t signatureSize,
229212
const size_t cmpOffset
230213
) -> std::tuple<std::span<const std::byte>, std::span<const Vector>, std::span<const std::byte>> {
214+
// Alignment may not match due to function-targeted architecture flags
215+
// The size should though...
216+
static_assert(sizeof(Vector) == alignment);
217+
231218
auto validateRange = [signatureSize](const std::byte* b, const std::byte* e) -> std::span<const std::byte> {
232219
if (b <= e && static_cast<size_t>(e - b) >= signatureSize) {
233220
return {b, e};
@@ -236,7 +223,7 @@ namespace hat::detail {
236223
};
237224

238225
const auto preBegin = begin;
239-
const auto vecBegin = reinterpret_cast<const Vector*>(align_pointer_as<Vector>(preBegin + cmpOffset));
226+
const auto vecBegin = reinterpret_cast<const Vector*>(align_up<alignment>(preBegin + cmpOffset));
240227
if (reinterpret_cast<const std::byte*>(vecBegin) > end) LIBHAT_UNLIKELY {
241228
return {validateRange(begin, end), {}, {}};
242229
}
@@ -308,8 +295,8 @@ namespace hat::detail {
308295
const auto signature = context.signature;
309296
const auto cmpByte = *signature[context.cmpIndex];
310297

311-
const auto scanBegin = next_boundary_align<scan_alignment::X16>(begin) + context.cmpIndex;
312-
const auto scanEnd = next_boundary_align<scan_alignment::X16>(end - signature.size() + 1) + context.cmpIndex;
298+
const auto scanBegin = align_up<scan_alignment::X16>(begin) + context.cmpIndex;
299+
const auto scanEnd = align_up<scan_alignment::X16>(end - signature.size() + 1) + context.cmpIndex;
313300

314301
if (scanBegin >= scanEnd) {
315302
return nullptr;

src/arch/x86/AVX2.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
namespace hat::detail {
1010

11+
LIBHAT_TARGET("avx")
1112
inline void load_signature_256(const signature_view signature, __m256i& bytes, __m256i& mask) {
1213
std::byte byteBuffer[32]{}; // The remaining signature bytes
1314
std::byte maskBuffer[32]{}; // A bitmask for the signature bytes we care about
@@ -20,6 +21,7 @@ namespace hat::detail {
2021
}
2122

2223
template<scan_alignment alignment, bool cmpeq2, bool veccmp>
24+
LIBHAT_TARGET("avx,avx2,bmi")
2325
const_scan_result find_pattern_avx2(const std::byte* begin, const std::byte* end, const scan_context& context) {
2426
const auto signature = context.signature;
2527
const auto cmpIndex = cmpeq2 ? *context.pairIndex : context.cmpIndex;
@@ -37,7 +39,7 @@ namespace hat::detail {
3739
load_signature_256(signature, signatureBytes, signatureMask);
3840
}
3941

40-
auto [pre, vec, post] = segment_scan<__m256i, veccmp>(begin, end, signature.size(), cmpIndex);
42+
auto [pre, vec, post] = segment_scan<__m256i, 32, veccmp>(begin, end, signature.size(), cmpIndex);
4143

4244
if (!pre.empty()) {
4345
const auto result = find_pattern_single<alignment>(pre.data(), pre.data() + pre.size(), context);

src/arch/x86/AVX512.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
namespace hat::detail {
1010

11+
LIBHAT_TARGET("avx512f")
1112
inline void load_signature_512(const signature_view signature, __m512i& bytes, __m512i& mask) {
1213
alignas(64) std::byte byteBuffer[64]{}; // The remaining signature bytes
1314
alignas(64) std::byte maskBuffer[64]{}; // A bitmask for the signature bytes we care about
@@ -20,6 +21,7 @@ namespace hat::detail {
2021
}
2122

2223
template<scan_alignment alignment, bool cmpeq2, bool veccmp>
24+
LIBHAT_TARGET("avx512f,avx512bw,bmi")
2325
const_scan_result find_pattern_avx512(const std::byte* begin, const std::byte* end, const scan_context& context) {
2426
const auto signature = context.signature;
2527
const auto cmpIndex = cmpeq2 ? *context.pairIndex : context.cmpIndex;
@@ -38,7 +40,7 @@ namespace hat::detail {
3840
load_signature_512(signature, signatureBytes, signatureMask);
3941
}
4042

41-
auto [pre, vec, post] = segment_scan<__m512i, veccmp>(begin, end, signature.size(), cmpIndex);
43+
auto [pre, vec, post] = segment_scan<__m512i, 64, veccmp>(begin, end, signature.size(), cmpIndex);
4244

4345
if (!pre.empty()) {
4446
const auto result = find_pattern_single<alignment>(pre.data(), pre.data() + pre.size(), context);

src/arch/x86/SSE.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ namespace hat::detail {
3636
}
3737

3838
template<scan_alignment alignment, bool cmpeq2, bool veccmp>
39+
LIBHAT_TARGET("sse4.1")
3940
const_scan_result find_pattern_sse(const std::byte* begin, const std::byte* end, const scan_context& context) {
4041
const auto signature = context.signature;
4142
const auto cmpIndex = cmpeq2 ? *context.pairIndex : context.cmpIndex;
@@ -53,7 +54,7 @@ namespace hat::detail {
5354
load_signature_128(signature, signatureBytes, signatureMask);
5455
}
5556

56-
auto [pre, vec, post] = segment_scan<__m128i, veccmp>(begin, end, signature.size(), cmpIndex);
57+
auto [pre, vec, post] = segment_scan<__m128i, 16, veccmp>(begin, end, signature.size(), cmpIndex);
5758

5859
if (!pre.empty()) {
5960
const auto result = find_pattern_single<alignment>(pre.data(), pre.data() + pre.size(), context);

src/arch/x86/System.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ namespace hat {
4646
}
4747
#endif
4848

49+
LIBHAT_TARGET("xsave")
50+
static auto xgetbv_impl(unsigned int a) {
51+
return _xgetbv(a);
52+
}
53+
4954
system_info_x86::system_info_x86() {
5055
std::array<int, 4> info{};
5156
std::vector<std::array<int, 4>> data{};
@@ -99,7 +104,7 @@ namespace hat {
99104
bool osxsave = f_1_ECX_[27];
100105
if (xsave && osxsave) {
101106
// https://cdrdv2-public.intel.com/671190/253668-sdm-vol-3a.pdf (Page 2-20)
102-
const std::bitset<64> xcr = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
107+
const std::bitset<64> xcr = xgetbv_impl(_XCR_XFEATURE_ENABLED_MASK);
103108
avxsupport = xcr[1] && xcr[2]; // xmm and ymm
104109
avx512support = avxsupport && xcr[5] && xcr[6] && xcr[7]; // opmask and zmm
105110
}

0 commit comments

Comments
 (0)