Skip to content

Commit

Permalink
intrinsic: add ctpop.
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
c8ef committed Nov 14, 2024
1 parent b0d6abb commit f9200ff
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
64 changes: 64 additions & 0 deletions gcc/rust/backend/rust-compile-intrinsic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ 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 @@ -241,6 +243,7 @@ static const std::map<std::string,
{"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 +614,67 @@ 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 builtin_call
= build_call_expr_loc (BUILTINS_LOCATION, popcount_builtin, 1, x);

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
19 changes: 19 additions & 0 deletions gcc/testsuite/rust/execute/torture/ctpop.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#![feature(intrinsics)]

Check failure on line 1 in gcc/testsuite/rust/execute/torture/ctpop.rs

View workflow job for this annotation

GitHub Actions / build-alpine-32bit-and-check-alpine-32bit

Test failure (FAIL)

-O0 (internal compiler error: in expand_fn_using_insn, at internal-fn.cc:209)

Check failure on line 1 in gcc/testsuite/rust/execute/torture/ctpop.rs

View workflow job for this annotation

GitHub Actions / build-alpine-32bit-and-check-alpine-32bit

Test failure (FAIL)

-O0 (test for excess errors)

Check failure on line 1 in gcc/testsuite/rust/execute/torture/ctpop.rs

View workflow job for this annotation

GitHub Actions / build-alpine-32bit-and-check-alpine-32bit

Test failure (FAIL)

-O1 execution test

Check failure on line 1 in gcc/testsuite/rust/execute/torture/ctpop.rs

View workflow job for this annotation

GitHub Actions / build-alpine-32bit-and-check-alpine-32bit

Test failure (FAIL)

-O2 execution test

Check failure on line 1 in gcc/testsuite/rust/execute/torture/ctpop.rs

View workflow job for this annotation

GitHub Actions / build-alpine-32bit-and-check-alpine-32bit

Test failure (FAIL)

-O3 -g execution test

Check failure on line 1 in gcc/testsuite/rust/execute/torture/ctpop.rs

View workflow job for this annotation

GitHub Actions / build-alpine-32bit-and-check-alpine-32bit

Test failure (FAIL)

-Os execution test

Check failure on line 1 in gcc/testsuite/rust/execute/torture/ctpop.rs

View workflow job for this annotation

GitHub Actions / build-alpine-32bit-and-check-alpine-32bit

Test failure (FAIL)

-O2 -flto -fno-use-linker-plugin -flto-partition=none execution test

Check failure on line 1 in gcc/testsuite/rust/execute/torture/ctpop.rs

View workflow job for this annotation

GitHub Actions / build-alpine-32bit-and-check-alpine-32bit

Test failure (FAIL)

-O2 -flto -fuse-linker-plugin -fno-fat-lto-objects execution test

Check failure on line 1 in gcc/testsuite/rust/execute/torture/ctpop.rs

View workflow job for this annotation

GitHub Actions / build-and-check-ubuntu-32bit

Test failure (FAIL)

-O0 (internal compiler error: in expand_fn_using_insn, at internal-fn.cc:209)

Check failure on line 1 in gcc/testsuite/rust/execute/torture/ctpop.rs

View workflow job for this annotation

GitHub Actions / build-and-check-ubuntu-32bit

Test failure (FAIL)

-O0 (test for excess errors)

#[lang = "sized"]
pub trait Sized {}

extern "rust-intrinsic" {
pub fn ctpop<T>(x: T) -> u32;
}

fn main() -> i32 {
let pop1 = ctpop(42i32) - 3;
let pop2 = ctpop(42u32) - 3;
let pop3 = ctpop(42i128) - 3;
let pop4 = ctpop(42u128) - 3;
let pop5 = ctpop(-42i32) - 29;
let pop6 = ctpop(0x1234567812345678i64) - 26;

(pop1 + pop2 + pop3 + pop4 + pop5 + pop6) as i32
}

0 comments on commit f9200ff

Please sign in to comment.