Skip to content

Commit

Permalink
ctpop
Browse files Browse the repository at this point in the history
  • Loading branch information
c8ef committed Nov 10, 2024
1 parent b0d6abb commit 69fba99
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 37 deletions.
135 changes: 98 additions & 37 deletions gcc/rust/backend/rust-compile-intrinsic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ static tree
move_val_init_handler (Context *ctx, TyTy::FnType *fntype);
static tree
assume_handler (Context *ctx, TyTy::FnType *fntype);
static tree ctpop_hander(Context *ctx, TyTy::FnType *fntype);

enum class Prefetch
{
Expand Down Expand Up @@ -204,43 +205,44 @@ sorry_handler (Context *ctx, TyTy::FnType *fntype)
}

static const std::map<std::string,
std::function<tree (Context *, TyTy::FnType *)>>
generic_intrinsics = {
{"offset", offset_handler},
{"size_of", sizeof_handler},
{"transmute", transmute_handler},
{"rotate_left", rotate_left_handler},
{"rotate_right", rotate_right_handler},
{"wrapping_add", wrapping_op_handler (PLUS_EXPR)},
{"wrapping_sub", wrapping_op_handler (MINUS_EXPR)},
{"wrapping_mul", wrapping_op_handler (MULT_EXPR)},
{"add_with_overflow", op_with_overflow (PLUS_EXPR)},
{"sub_with_overflow", op_with_overflow (MINUS_EXPR)},
{"mul_with_overflow", op_with_overflow (MULT_EXPR)},
{"copy", copy_handler (true)},
{"copy_nonoverlapping", copy_handler (false)},
{"prefetch_read_data", prefetch_read_data},
{"prefetch_write_data", prefetch_write_data},
{"atomic_store_seqcst", atomic_store_handler (__ATOMIC_SEQ_CST)},
{"atomic_store_release", atomic_store_handler (__ATOMIC_RELEASE)},
{"atomic_store_relaxed", atomic_store_handler (__ATOMIC_RELAXED)},
{"atomic_store_unordered", atomic_store_handler (__ATOMIC_RELAXED)},
{"atomic_load_seqcst", atomic_load_handler (__ATOMIC_SEQ_CST)},
{"atomic_load_acquire", atomic_load_handler (__ATOMIC_ACQUIRE)},
{"atomic_load_relaxed", atomic_load_handler (__ATOMIC_RELAXED)},
{"atomic_load_unordered", atomic_load_handler (__ATOMIC_RELAXED)},
{"unchecked_add", unchecked_op_handler (PLUS_EXPR)},
{"unchecked_sub", unchecked_op_handler (MINUS_EXPR)},
{"unchecked_mul", unchecked_op_handler (MULT_EXPR)},
{"unchecked_div", unchecked_op_handler (TRUNC_DIV_EXPR)},
{"unchecked_rem", unchecked_op_handler (TRUNC_MOD_EXPR)},
{"unchecked_shl", unchecked_op_handler (LSHIFT_EXPR)},
{"unchecked_shr", unchecked_op_handler (RSHIFT_EXPR)},
{"uninit", uninit_handler},
{"move_val_init", move_val_init_handler},
{"likely", expect_handler (true)},
{"unlikely", expect_handler (false)},
{"assume", assume_handler},
std::function<tree(Context *, TyTy::FnType *)>>
generic_intrinsics = {
{"offset", offset_handler},
{"size_of", sizeof_handler},
{"transmute", transmute_handler},
{"rotate_left", rotate_left_handler},
{"rotate_right", rotate_right_handler},
{"wrapping_add", wrapping_op_handler(PLUS_EXPR)},
{"wrapping_sub", wrapping_op_handler(MINUS_EXPR)},
{"wrapping_mul", wrapping_op_handler(MULT_EXPR)},
{"add_with_overflow", op_with_overflow(PLUS_EXPR)},
{"sub_with_overflow", op_with_overflow(MINUS_EXPR)},
{"mul_with_overflow", op_with_overflow(MULT_EXPR)},
{"copy", copy_handler(true)},
{"copy_nonoverlapping", copy_handler(false)},
{"prefetch_read_data", prefetch_read_data},
{"prefetch_write_data", prefetch_write_data},
{"atomic_store_seqcst", atomic_store_handler(__ATOMIC_SEQ_CST)},
{"atomic_store_release", atomic_store_handler(__ATOMIC_RELEASE)},
{"atomic_store_relaxed", atomic_store_handler(__ATOMIC_RELAXED)},
{"atomic_store_unordered", atomic_store_handler(__ATOMIC_RELAXED)},
{"atomic_load_seqcst", atomic_load_handler(__ATOMIC_SEQ_CST)},
{"atomic_load_acquire", atomic_load_handler(__ATOMIC_ACQUIRE)},
{"atomic_load_relaxed", atomic_load_handler(__ATOMIC_RELAXED)},
{"atomic_load_unordered", atomic_load_handler(__ATOMIC_RELAXED)},
{"unchecked_add", unchecked_op_handler(PLUS_EXPR)},
{"unchecked_sub", unchecked_op_handler(MINUS_EXPR)},
{"unchecked_mul", unchecked_op_handler(MULT_EXPR)},
{"unchecked_div", unchecked_op_handler(TRUNC_DIV_EXPR)},
{"unchecked_rem", unchecked_op_handler(TRUNC_MOD_EXPR)},
{"unchecked_shl", unchecked_op_handler(LSHIFT_EXPR)},
{"unchecked_shr", unchecked_op_handler(RSHIFT_EXPR)},
{"uninit", uninit_handler},
{"move_val_init", move_val_init_handler},
{"likely", expect_handler(true)},
{"unlikely", expect_handler(false)},
{"assume", assume_handler},
{"ctpop", ctpop_hander},
};

Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
Expand Down Expand Up @@ -611,6 +613,65 @@ wrapping_op_handler_inner (Context *ctx, TyTy::FnType *fntype, tree_code op)
return fndecl;
}

static tree ctpop_hander(Context *ctx, TyTy::FnType *fntype) {
rust_assert(fntype->get_params().size() == 1);

tree lookup = NULL_TREE;
if (check_for_cached_intrinsic(ctx, fntype, &lookup))
return lookup;

auto fndecl = compile_intrinsic_function(ctx, fntype);

// setup the params
std::vector<Bvariable *> param_vars;
compile_fn_params(ctx, fntype, fndecl, &param_vars);

auto &x_param = param_vars.at(0);

if (!Backend::function_set_parameters(fndecl, param_vars))
return error_mark_node;

rust_assert(fntype->get_num_substitutions() == 1);
auto &param_mapping = fntype->get_substs().at(0);
const TyTy::ParamType *param_tyty = param_mapping.get_param_ty();
TyTy::BaseType *resolved_tyty = param_tyty->resolve();
tree template_parameter_type =
TyTyResolveCompile::compile(ctx, resolved_tyty);

tree tmp_stmt = error_mark_node;
Bvariable *result_variable = Backend::temporary_variable(
fndecl, NULL_TREE, template_parameter_type, NULL_TREE,
true /*address_is_taken*/, UNDEF_LOCATION, &tmp_stmt);

enter_intrinsic_block(ctx, fndecl, {result_variable});

// BUILTIN popcount FN BODY BEGIN
auto x = Backend::var_expression(x_param, UNDEF_LOCATION);

tree popcount_builtin = error_mark_node;

BuiltinsContext::get().lookup_simple_builtin("__builtin_popcountg",
&popcount_builtin);
rust_assert(popcount_builtin != error_mark_node);

tree result_decl = result_variable->get_tree(BUILTINS_LOCATION);
tree result_ref = build_fold_addr_expr_loc(BUILTINS_LOCATION, result_decl);

tree builtin_call = build_call_expr_loc(BUILTINS_LOCATION, popcount_builtin,
2, x, result_ref);

auto return_statement = Backend::return_statement(
fndecl, build1(CONVERT_EXPR, unsigned_type_node, builtin_call),
UNDEF_LOCATION);
ctx->add_statement(return_statement);

// BUILTIN popcount FN BODY END

finalize_intrinsic_block(ctx, fndecl);

return fndecl;
}

/**
* pub fn add_with_overflow<T>(x: T, y: T) -> (T, bool);
*/
Expand Down
7 changes: 7 additions & 0 deletions gcc/testsuite/rust/compile/torture/intrinsics-6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ extern "rust-intrinsic" {
pub fn unchecked_rem<T>(x: T, y: T) -> T;
pub fn unchecked_shl<T>(x: T, y: T) -> T;
pub fn unchecked_shr<T>(x: T, y: T) -> T;

pub fn ctpop<T>(x: T) -> u32;
}

fn main() -> i32 {
Expand All @@ -22,5 +24,10 @@ fn main() -> i32 {
let zero5 = unsafe { (1 << 5) - unchecked_shl(1, 5) };
let zero6 = unsafe { (1 >> 5) - unchecked_shr(1, 5) };

let _pop1 = ctpop(42i32);
let _pop2 = ctpop(42u32);
let _pop3 = ctpop(42i128);
let _pop4 = ctpop(42u128);

zero0 + zero1 + zero2 + zero3 + zero4 + zero5 + zero6
}

0 comments on commit 69fba99

Please sign in to comment.