mkql_builtins_countbits.cpp 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. #include "mkql_builtins_impl.h" // Y_IGNORE // Y_IGNORE
  2. #include <bit>
  3. #include <type_traits>
  4. namespace NKikimr {
  5. namespace NMiniKQL {
  6. namespace {
  7. template<typename TInput, typename TOutput>
  8. struct TCountBits : public TSimpleArithmeticUnary<TInput, TOutput, TCountBits<TInput, TOutput>> {
  9. static TOutput Do(TInput val)
  10. {
  11. if constexpr (std::is_signed_v<TInput>) {
  12. return std::popcount(static_cast<std::make_unsigned_t<TInput>>(val));
  13. } else {
  14. return std::popcount(val);
  15. }
  16. }
  17. #ifndef MKQL_DISABLE_CODEGEN
  18. static Value* Gen(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  19. {
  20. auto& context = ctx.Codegen.GetContext();
  21. auto& module = ctx.Codegen.GetModule();
  22. const auto fnType = FunctionType::get(arg->getType(), {arg->getType()}, false);
  23. const auto& name = GetFuncNameForType<TInput>("llvm.ctpop");
  24. const auto func = module.getOrInsertFunction(name, fnType).getCallee();
  25. const auto result = CallInst::Create(fnType, func, {arg}, "popcount", block);
  26. return StaticCast<TInput, TOutput>(result, context, block);
  27. }
  28. #endif
  29. };
  30. }
  31. void RegisterCountBits(IBuiltinFunctionRegistry& registry) {
  32. RegisterUnaryIntegralFunctionOpt<TCountBits, TUnaryArgsOpt>(registry, "CountBits");
  33. }
  34. } // namespace NMiniKQL
  35. } // namespace NKikimr