blob: ba6541327843a1747a1ca34ff35969b7d2992d36 [file] [log] [blame]
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "hwy/targets.h"
#include "hwy/tests/test_util-inl.h"
namespace hwy {
class HwyTargetsTest : public testing::Test {
protected:
void TearDown() override {
SetSupportedTargetsForTest(0);
DisableTargets(0); // Reset the mask.
}
};
namespace fake {
#define DECLARE_FUNCTION(TGT) \
namespace N_##TGT { \
uint32_t FakeFunction(int) { return HWY_##TGT; } \
}
DECLARE_FUNCTION(AVX3)
DECLARE_FUNCTION(AVX2)
DECLARE_FUNCTION(SSE4)
DECLARE_FUNCTION(NEON)
DECLARE_FUNCTION(PPC8)
DECLARE_FUNCTION(WASM)
DECLARE_FUNCTION(SCALAR)
HWY_EXPORT(FakeFunction);
} // namespace fake
// Test that the order in the HWY_EXPORT static array matches the expected
// value of the target bits. This is only checked for the targets that are
// enabled in the current compilation.
TEST_F(HwyTargetsTest, ChosenTargetOrderTest) {
#define CHECK_ARRAY_ENTRY(TGT) \
if ((HWY_TARGETS & HWY_##TGT) != 0) { \
SetSupportedTargetsForTest(HWY_##TGT); \
/* Calling Update() first to make &HWY_DYNAMIC_DISPATCH() return */ \
/* the pointer to the already cached function. */ \
chosen_target.Update(); \
ASSERT_NE(nullptr, &HWY_DYNAMIC_DISPATCH(fake::FakeFunction)); \
EXPECT_EQ(HWY_##TGT, HWY_DYNAMIC_DISPATCH(fake::FakeFunction)(42)); \
/* Calling DeInit() will test that the initializer function */ \
/* also calls the right function. */ \
chosen_target.DeInit(); \
EXPECT_EQ(HWY_##TGT, HWY_DYNAMIC_DISPATCH(fake::FakeFunction)(42)); \
/* Second call uses the cached value from the previous call. */ \
EXPECT_EQ(HWY_##TGT, HWY_DYNAMIC_DISPATCH(fake::FakeFunction)(42)); \
}
CHECK_ARRAY_ENTRY(AVX3)
CHECK_ARRAY_ENTRY(AVX2)
CHECK_ARRAY_ENTRY(SSE4)
CHECK_ARRAY_ENTRY(NEON)
CHECK_ARRAY_ENTRY(PPC8)
CHECK_ARRAY_ENTRY(WASM)
CHECK_ARRAY_ENTRY(SCALAR)
}
TEST_F(HwyTargetsTest, DisabledTargetsTest) {
DisableTargets(~0u);
// Check that the baseline can't be disabled.
HWY_ASSERT(HWY_ENABLED_BASELINE == SupportedTargets());
DisableTargets(0); // Reset the mask.
uint32_t current_targets = SupportedTargets();
if ((current_targets & ~HWY_ENABLED_BASELINE) == 0) {
// We can't test anything else if the only compiled target is the baseline.
return;
}
// Get the lowest bit in the mask (the best target) and disable that one.
uint32_t lowest_target = current_targets & (~current_targets + 1);
// The lowest target shouldn't be one in the baseline.
HWY_ASSERT((lowest_target & ~HWY_ENABLED_BASELINE) != 0);
DisableTargets(lowest_target);
// Check that the other targets are still enabled.
HWY_ASSERT((lowest_target ^ current_targets) == SupportedTargets());
DisableTargets(0); // Reset the mask.
}
} // namespace hwy