// 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 fake { #define DECLARE_FUNCTION(TGT) \ namespace N_##TGT { \ uint32_t FakeFunction(int) { return HWY_##TGT; } \ } DECLARE_FUNCTION(AVX3_DL) DECLARE_FUNCTION(AVX3) DECLARE_FUNCTION(AVX2) DECLARE_FUNCTION(SSE4) DECLARE_FUNCTION(SSSE3) DECLARE_FUNCTION(NEON) DECLARE_FUNCTION(SVE) DECLARE_FUNCTION(SVE2) DECLARE_FUNCTION(PPC8) DECLARE_FUNCTION(WASM) DECLARE_FUNCTION(RVV) DECLARE_FUNCTION(SCALAR) HWY_EXPORT(FakeFunction); void CheckFakeFunction() { #define CHECK_ARRAY_ENTRY(TGT) \ if ((HWY_TARGETS & HWY_##TGT) != 0) { \ hwy::SetSupportedTargetsForTest(HWY_##TGT); \ /* Calling Update() first to make &HWY_DYNAMIC_DISPATCH() return */ \ /* the pointer to the already cached function. */ \ hwy::GetChosenTarget().Update(); \ EXPECT_EQ(uint32_t(HWY_##TGT), HWY_DYNAMIC_DISPATCH(FakeFunction)(42)); \ /* Calling DeInit() will test that the initializer function */ \ /* also calls the right function. */ \ hwy::GetChosenTarget().DeInit(); \ EXPECT_EQ(uint32_t(HWY_##TGT), HWY_DYNAMIC_DISPATCH(FakeFunction)(42)); \ /* Second call uses the cached value from the previous call. */ \ EXPECT_EQ(uint32_t(HWY_##TGT), HWY_DYNAMIC_DISPATCH(FakeFunction)(42)); \ } CHECK_ARRAY_ENTRY(AVX3_DL) CHECK_ARRAY_ENTRY(AVX3) CHECK_ARRAY_ENTRY(AVX2) CHECK_ARRAY_ENTRY(SSE4) CHECK_ARRAY_ENTRY(SSSE3) CHECK_ARRAY_ENTRY(NEON) CHECK_ARRAY_ENTRY(SVE) CHECK_ARRAY_ENTRY(SVE2) CHECK_ARRAY_ENTRY(PPC8) CHECK_ARRAY_ENTRY(WASM) CHECK_ARRAY_ENTRY(RVV) CHECK_ARRAY_ENTRY(SCALAR) #undef CHECK_ARRAY_ENTRY } } // namespace fake namespace hwy { class HwyTargetsTest : public testing::Test { protected: void TearDown() override { SetSupportedTargetsForTest(0); DisableTargets(0); // Reset the mask. } }; // 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) { fake::CheckFakeFunction(); } 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 & ~uint32_t(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 & ~uint32_t(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 // Ought not to be necessary, but without this, no tests run on RVV. int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }