Skip to content

Commit f9200ff

Browse files
committed
intrinsic: add ctpop.
This patch adds support for the `ctpop` intrinsic. gcc/rust/ChangeLog: * backend/rust-compile-intrinsic.cc (ctpop_hander): Add `ctpop`. gcc/testsuite/ChangeLog: * rust/execute/torture/ctpop.rs: New test. Signed-off-by: Yuao Ma <[email protected]>
1 parent b0d6abb commit f9200ff

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

gcc/rust/backend/rust-compile-intrinsic.cc

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ static tree
9292
move_val_init_handler (Context *ctx, TyTy::FnType *fntype);
9393
static tree
9494
assume_handler (Context *ctx, TyTy::FnType *fntype);
95+
static tree
96+
ctpop_hander (Context *ctx, TyTy::FnType *fntype);
9597

9698
enum class Prefetch
9799
{
@@ -241,6 +243,7 @@ static const std::map<std::string,
241243
{"likely", expect_handler (true)},
242244
{"unlikely", expect_handler (false)},
243245
{"assume", assume_handler},
246+
{"ctpop", ctpop_hander},
244247
};
245248

246249
Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
@@ -611,6 +614,67 @@ wrapping_op_handler_inner (Context *ctx, TyTy::FnType *fntype, tree_code op)
611614
return fndecl;
612615
}
613616

617+
static tree
618+
ctpop_hander (Context *ctx, TyTy::FnType *fntype)
619+
{
620+
rust_assert (fntype->get_params ().size () == 1);
621+
622+
tree lookup = NULL_TREE;
623+
if (check_for_cached_intrinsic (ctx, fntype, &lookup))
624+
return lookup;
625+
626+
auto fndecl = compile_intrinsic_function (ctx, fntype);
627+
628+
// setup the params
629+
std::vector<Bvariable *> param_vars;
630+
compile_fn_params (ctx, fntype, fndecl, &param_vars);
631+
632+
auto &x_param = param_vars.at (0);
633+
634+
if (!Backend::function_set_parameters (fndecl, param_vars))
635+
return error_mark_node;
636+
637+
rust_assert (fntype->get_num_substitutions () == 1);
638+
auto &param_mapping = fntype->get_substs ().at (0);
639+
const TyTy::ParamType *param_tyty = param_mapping.get_param_ty ();
640+
TyTy::BaseType *resolved_tyty = param_tyty->resolve ();
641+
tree template_parameter_type
642+
= TyTyResolveCompile::compile (ctx, resolved_tyty);
643+
644+
tree tmp_stmt = error_mark_node;
645+
Bvariable *result_variable
646+
= Backend::temporary_variable (fndecl, NULL_TREE, template_parameter_type,
647+
NULL_TREE, true /*address_is_taken*/,
648+
UNDEF_LOCATION, &tmp_stmt);
649+
650+
enter_intrinsic_block (ctx, fndecl, {result_variable});
651+
652+
// BUILTIN popcount FN BODY BEGIN
653+
auto x = Backend::var_expression (x_param, UNDEF_LOCATION);
654+
655+
tree popcount_builtin = error_mark_node;
656+
657+
BuiltinsContext::get ().lookup_simple_builtin ("__builtin_popcountg",
658+
&popcount_builtin);
659+
rust_assert (popcount_builtin != error_mark_node);
660+
661+
tree builtin_call
662+
= build_call_expr_loc (BUILTINS_LOCATION, popcount_builtin, 1, x);
663+
664+
auto return_statement
665+
= Backend::return_statement (fndecl,
666+
build1 (CONVERT_EXPR, unsigned_type_node,
667+
builtin_call),
668+
UNDEF_LOCATION);
669+
ctx->add_statement (return_statement);
670+
671+
// BUILTIN popcount FN BODY END
672+
673+
finalize_intrinsic_block (ctx, fndecl);
674+
675+
return fndecl;
676+
}
677+
614678
/**
615679
* pub fn add_with_overflow<T>(x: T, y: T) -> (T, bool);
616680
*/
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#![feature(intrinsics)]
2+
3+
#[lang = "sized"]
4+
pub trait Sized {}
5+
6+
extern "rust-intrinsic" {
7+
pub fn ctpop<T>(x: T) -> u32;
8+
}
9+
10+
fn main() -> i32 {
11+
let pop1 = ctpop(42i32) - 3;
12+
let pop2 = ctpop(42u32) - 3;
13+
let pop3 = ctpop(42i128) - 3;
14+
let pop4 = ctpop(42u128) - 3;
15+
let pop5 = ctpop(-42i32) - 29;
16+
let pop6 = ctpop(0x1234567812345678i64) - 26;
17+
18+
(pop1 + pop2 + pop3 + pop4 + pop5 + pop6) as i32
19+
}

0 commit comments

Comments
 (0)