// Copyright 2022 The Tint Authors. // // 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 #include "benchmark/benchmark.h" #include "src/tint/switch.h" namespace tint { namespace { struct Base : public tint::utils::Castable {}; struct A : public tint::utils::Castable {}; struct AA : public tint::utils::Castable {}; struct AAA : public tint::utils::Castable {}; struct AAB : public tint::utils::Castable {}; struct AAC : public tint::utils::Castable {}; struct AB : public tint::utils::Castable {}; struct ABA : public tint::utils::Castable {}; struct ABB : public tint::utils::Castable {}; struct ABC : public tint::utils::Castable {}; struct AC : public tint::utils::Castable {}; struct ACA : public tint::utils::Castable {}; struct ACB : public tint::utils::Castable {}; struct ACC : public tint::utils::Castable {}; struct B : public tint::utils::Castable {}; struct BA : public tint::utils::Castable {}; struct BAA : public tint::utils::Castable {}; struct BAB : public tint::utils::Castable {}; struct BAC : public tint::utils::Castable {}; struct BB : public tint::utils::Castable {}; struct BBA : public tint::utils::Castable {}; struct BBB : public tint::utils::Castable {}; struct BBC : public tint::utils::Castable {}; struct BC : public tint::utils::Castable {}; struct BCA : public tint::utils::Castable {}; struct BCB : public tint::utils::Castable {}; struct BCC : public tint::utils::Castable {}; struct C : public tint::utils::Castable {}; struct CA : public tint::utils::Castable {}; struct CAA : public tint::utils::Castable {}; struct CAB : public tint::utils::Castable {}; struct CAC : public tint::utils::Castable {}; struct CB : public tint::utils::Castable {}; struct CBA : public tint::utils::Castable {}; struct CBB : public tint::utils::Castable {}; struct CBC : public tint::utils::Castable {}; struct CC : public tint::utils::Castable {}; struct CCA : public tint::utils::Castable {}; struct CCB : public tint::utils::Castable {}; struct CCC : public tint::utils::Castable {}; using AllTypes = std::tuple; std::vector> MakeObjects() { std::vector> out; out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); out.emplace_back(std::make_unique()); return out; } void CastableLargeSwitch(::benchmark::State& state) { auto objects = MakeObjects(); size_t i = 0; for (auto _ : state) { auto* object = objects[i % objects.size()].get(); Switch( object, // [&](const AAA*) { ::benchmark::DoNotOptimize(i += 40); }, [&](const AAB*) { ::benchmark::DoNotOptimize(i += 50); }, [&](const AAC*) { ::benchmark::DoNotOptimize(i += 60); }, [&](const ABA*) { ::benchmark::DoNotOptimize(i += 80); }, [&](const ABB*) { ::benchmark::DoNotOptimize(i += 90); }, [&](const ABC*) { ::benchmark::DoNotOptimize(i += 100); }, [&](const ACA*) { ::benchmark::DoNotOptimize(i += 120); }, [&](const ACB*) { ::benchmark::DoNotOptimize(i += 130); }, [&](const ACC*) { ::benchmark::DoNotOptimize(i += 140); }, [&](const BAA*) { ::benchmark::DoNotOptimize(i += 170); }, [&](const BAB*) { ::benchmark::DoNotOptimize(i += 180); }, [&](const BAC*) { ::benchmark::DoNotOptimize(i += 190); }, [&](const BBA*) { ::benchmark::DoNotOptimize(i += 210); }, [&](const BBB*) { ::benchmark::DoNotOptimize(i += 220); }, [&](const BBC*) { ::benchmark::DoNotOptimize(i += 230); }, [&](const BCA*) { ::benchmark::DoNotOptimize(i += 250); }, [&](const BCB*) { ::benchmark::DoNotOptimize(i += 260); }, [&](const BCC*) { ::benchmark::DoNotOptimize(i += 270); }, [&](const CA*) { ::benchmark::DoNotOptimize(i += 290); }, [&](const CAA*) { ::benchmark::DoNotOptimize(i += 300); }, [&](const CAB*) { ::benchmark::DoNotOptimize(i += 310); }, [&](const CAC*) { ::benchmark::DoNotOptimize(i += 320); }, [&](const CBA*) { ::benchmark::DoNotOptimize(i += 340); }, [&](const CBB*) { ::benchmark::DoNotOptimize(i += 350); }, [&](const CBC*) { ::benchmark::DoNotOptimize(i += 360); }, [&](const CCA*) { ::benchmark::DoNotOptimize(i += 380); }, [&](const CCB*) { ::benchmark::DoNotOptimize(i += 390); }, [&](const CCC*) { ::benchmark::DoNotOptimize(i += 400); }, [&](Default) { ::benchmark::DoNotOptimize(i += 123); }); i = (i * 31) ^ (i << 5); } } BENCHMARK(CastableLargeSwitch); void CastableMediumSwitch(::benchmark::State& state) { auto objects = MakeObjects(); size_t i = 0; for (auto _ : state) { auto* object = objects[i % objects.size()].get(); Switch( object, // [&](const ACB*) { ::benchmark::DoNotOptimize(i += 130); }, [&](const BAA*) { ::benchmark::DoNotOptimize(i += 170); }, [&](const BAB*) { ::benchmark::DoNotOptimize(i += 180); }, [&](const BBA*) { ::benchmark::DoNotOptimize(i += 210); }, [&](const BBB*) { ::benchmark::DoNotOptimize(i += 220); }, [&](const CAA*) { ::benchmark::DoNotOptimize(i += 300); }, [&](const CCA*) { ::benchmark::DoNotOptimize(i += 380); }, [&](const CCB*) { ::benchmark::DoNotOptimize(i += 390); }, [&](const CCC*) { ::benchmark::DoNotOptimize(i += 400); }, [&](Default) { ::benchmark::DoNotOptimize(i += 123); }); i = (i * 31) ^ (i << 5); } } BENCHMARK(CastableMediumSwitch); void CastableSmallSwitch(::benchmark::State& state) { auto objects = MakeObjects(); size_t i = 0; for (auto _ : state) { auto* object = objects[i % objects.size()].get(); Switch( object, // [&](const AAB*) { ::benchmark::DoNotOptimize(i += 30); }, [&](const CAC*) { ::benchmark::DoNotOptimize(i += 290); }, [&](const CAA*) { ::benchmark::DoNotOptimize(i += 300); }); i = (i * 31) ^ (i << 5); } } BENCHMARK(CastableSmallSwitch); } // namespace } // namespace tint TINT_INSTANTIATE_TYPEINFO(tint::Base); TINT_INSTANTIATE_TYPEINFO(tint::A); TINT_INSTANTIATE_TYPEINFO(tint::AA); TINT_INSTANTIATE_TYPEINFO(tint::AAA); TINT_INSTANTIATE_TYPEINFO(tint::AAB); TINT_INSTANTIATE_TYPEINFO(tint::AAC); TINT_INSTANTIATE_TYPEINFO(tint::AB); TINT_INSTANTIATE_TYPEINFO(tint::ABA); TINT_INSTANTIATE_TYPEINFO(tint::ABB); TINT_INSTANTIATE_TYPEINFO(tint::ABC); TINT_INSTANTIATE_TYPEINFO(tint::AC); TINT_INSTANTIATE_TYPEINFO(tint::ACA); TINT_INSTANTIATE_TYPEINFO(tint::ACB); TINT_INSTANTIATE_TYPEINFO(tint::ACC); TINT_INSTANTIATE_TYPEINFO(tint::B); TINT_INSTANTIATE_TYPEINFO(tint::BA); TINT_INSTANTIATE_TYPEINFO(tint::BAA); TINT_INSTANTIATE_TYPEINFO(tint::BAB); TINT_INSTANTIATE_TYPEINFO(tint::BAC); TINT_INSTANTIATE_TYPEINFO(tint::BB); TINT_INSTANTIATE_TYPEINFO(tint::BBA); TINT_INSTANTIATE_TYPEINFO(tint::BBB); TINT_INSTANTIATE_TYPEINFO(tint::BBC); TINT_INSTANTIATE_TYPEINFO(tint::BC); TINT_INSTANTIATE_TYPEINFO(tint::BCA); TINT_INSTANTIATE_TYPEINFO(tint::BCB); TINT_INSTANTIATE_TYPEINFO(tint::BCC); TINT_INSTANTIATE_TYPEINFO(tint::C); TINT_INSTANTIATE_TYPEINFO(tint::CA); TINT_INSTANTIATE_TYPEINFO(tint::CAA); TINT_INSTANTIATE_TYPEINFO(tint::CAB); TINT_INSTANTIATE_TYPEINFO(tint::CAC); TINT_INSTANTIATE_TYPEINFO(tint::CB); TINT_INSTANTIATE_TYPEINFO(tint::CBA); TINT_INSTANTIATE_TYPEINFO(tint::CBB); TINT_INSTANTIATE_TYPEINFO(tint::CBC); TINT_INSTANTIATE_TYPEINFO(tint::CC); TINT_INSTANTIATE_TYPEINFO(tint::CCA); TINT_INSTANTIATE_TYPEINFO(tint::CCB); TINT_INSTANTIATE_TYPEINFO(tint::CCC);