Add support for bitcount intrinsics
Adds support for the llvm.ctpop, llvm.ctlz and llvm.cttz intrinsics.
This commit is contained in:
parent
76a2891feb
commit
82641d4c39
@ -2396,6 +2396,30 @@ fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> {
|
||||
T_fn(~[T_f32()], T_f32()));
|
||||
let truncf64 = decl_cdecl_fn(llmod, ~"llvm.trunc.f64",
|
||||
T_fn(~[T_f64()], T_f64()));
|
||||
let ctpop8 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i8",
|
||||
T_fn(~[T_i8()], T_i8()));
|
||||
let ctpop16 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i16",
|
||||
T_fn(~[T_i16()], T_i16()));
|
||||
let ctpop32 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i32",
|
||||
T_fn(~[T_i32()], T_i32()));
|
||||
let ctpop64 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i64",
|
||||
T_fn(~[T_i64()], T_i64()));
|
||||
let ctlz8 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i8",
|
||||
T_fn(~[T_i8(), T_i1()], T_i8()));
|
||||
let ctlz16 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i16",
|
||||
T_fn(~[T_i16(), T_i1()], T_i16()));
|
||||
let ctlz32 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i32",
|
||||
T_fn(~[T_i32(), T_i1()], T_i32()));
|
||||
let ctlz64 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i64",
|
||||
T_fn(~[T_i64(), T_i1()], T_i64()));
|
||||
let cttz8 = decl_cdecl_fn(llmod, ~"llvm.cttz.i8",
|
||||
T_fn(~[T_i8(), T_i1()], T_i8()));
|
||||
let cttz16 = decl_cdecl_fn(llmod, ~"llvm.cttz.i16",
|
||||
T_fn(~[T_i16(), T_i1()], T_i16()));
|
||||
let cttz32 = decl_cdecl_fn(llmod, ~"llvm.cttz.i32",
|
||||
T_fn(~[T_i32(), T_i1()], T_i32()));
|
||||
let cttz64 = decl_cdecl_fn(llmod, ~"llvm.cttz.i64",
|
||||
T_fn(~[T_i64(), T_i1()], T_i64()));
|
||||
|
||||
let intrinsics = HashMap();
|
||||
intrinsics.insert(~"llvm.gcroot", gcroot);
|
||||
@ -2436,6 +2460,18 @@ fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> {
|
||||
intrinsics.insert(~"llvm.ceil.f64", ceilf64);
|
||||
intrinsics.insert(~"llvm.trunc.f32", truncf32);
|
||||
intrinsics.insert(~"llvm.trunc.f64", truncf64);
|
||||
intrinsics.insert(~"llvm.ctpop.i8", ctpop8);
|
||||
intrinsics.insert(~"llvm.ctpop.i16", ctpop16);
|
||||
intrinsics.insert(~"llvm.ctpop.i32", ctpop32);
|
||||
intrinsics.insert(~"llvm.ctpop.i64", ctpop64);
|
||||
intrinsics.insert(~"llvm.ctlz.i8", ctlz8);
|
||||
intrinsics.insert(~"llvm.ctlz.i16", ctlz16);
|
||||
intrinsics.insert(~"llvm.ctlz.i32", ctlz32);
|
||||
intrinsics.insert(~"llvm.ctlz.i64", ctlz64);
|
||||
intrinsics.insert(~"llvm.cttz.i8", cttz8);
|
||||
intrinsics.insert(~"llvm.cttz.i16", cttz16);
|
||||
intrinsics.insert(~"llvm.cttz.i32", cttz32);
|
||||
intrinsics.insert(~"llvm.cttz.i64", cttz64);
|
||||
|
||||
return intrinsics;
|
||||
}
|
||||
|
@ -1194,6 +1194,74 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
|
||||
let truncf = ccx.intrinsics.get(~"llvm.trunc.f64");
|
||||
Store(bcx, Call(bcx, truncf, ~[x]), fcx.llretptr);
|
||||
}
|
||||
~"ctpop8" => {
|
||||
let x = get_param(decl, first_real_arg);
|
||||
let ctpop = ccx.intrinsics.get(~"llvm.ctpop.i8");
|
||||
Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr)
|
||||
}
|
||||
~"ctpop16" => {
|
||||
let x = get_param(decl, first_real_arg);
|
||||
let ctpop = ccx.intrinsics.get(~"llvm.ctpop.i16");
|
||||
Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr)
|
||||
}
|
||||
~"ctpop32" => {
|
||||
let x = get_param(decl, first_real_arg);
|
||||
let ctpop = ccx.intrinsics.get(~"llvm.ctpop.i32");
|
||||
Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr)
|
||||
}
|
||||
~"ctpop64" => {
|
||||
let x = get_param(decl, first_real_arg);
|
||||
let ctpop = ccx.intrinsics.get(~"llvm.ctpop.i64");
|
||||
Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr)
|
||||
}
|
||||
~"ctlz8" => {
|
||||
let x = get_param(decl, first_real_arg);
|
||||
let y = C_bool(false);
|
||||
let ctlz = ccx.intrinsics.get(~"llvm.ctlz.i8");
|
||||
Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr)
|
||||
}
|
||||
~"ctlz16" => {
|
||||
let x = get_param(decl, first_real_arg);
|
||||
let y = C_bool(false);
|
||||
let ctlz = ccx.intrinsics.get(~"llvm.ctlz.i16");
|
||||
Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr)
|
||||
}
|
||||
~"ctlz32" => {
|
||||
let x = get_param(decl, first_real_arg);
|
||||
let y = C_bool(false);
|
||||
let ctlz = ccx.intrinsics.get(~"llvm.ctlz.i32");
|
||||
Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr)
|
||||
}
|
||||
~"ctlz64" => {
|
||||
let x = get_param(decl, first_real_arg);
|
||||
let y = C_bool(false);
|
||||
let ctlz = ccx.intrinsics.get(~"llvm.ctlz.i64");
|
||||
Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr)
|
||||
}
|
||||
~"cttz8" => {
|
||||
let x = get_param(decl, first_real_arg);
|
||||
let y = C_bool(false);
|
||||
let cttz = ccx.intrinsics.get(~"llvm.cttz.i8");
|
||||
Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr)
|
||||
}
|
||||
~"cttz16" => {
|
||||
let x = get_param(decl, first_real_arg);
|
||||
let y = C_bool(false);
|
||||
let cttz = ccx.intrinsics.get(~"llvm.cttz.i16");
|
||||
Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr)
|
||||
}
|
||||
~"cttz32" => {
|
||||
let x = get_param(decl, first_real_arg);
|
||||
let y = C_bool(false);
|
||||
let cttz = ccx.intrinsics.get(~"llvm.cttz.i32");
|
||||
Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr)
|
||||
}
|
||||
~"cttz64" => {
|
||||
let x = get_param(decl, first_real_arg);
|
||||
let y = C_bool(false);
|
||||
let cttz = ccx.intrinsics.get(~"llvm.cttz.i64");
|
||||
Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr)
|
||||
}
|
||||
_ => {
|
||||
// Could we make this an enum rather than a string? does it get
|
||||
// checked earlier?
|
||||
|
@ -130,6 +130,11 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
|
||||
~"floorf32"| ~"floorf64"| ~"ceilf32" | ~"ceilf64" |
|
||||
~"truncf32"| ~"truncf64" => 0,
|
||||
|
||||
~"ctpop8" | ~"ctpop16" | ~"ctpop32" | ~"ctpop64" => 0,
|
||||
|
||||
~"ctlz8" | ~"ctlz16" | ~"ctlz32" | ~"ctlz64" => 0,
|
||||
~"cttz8" | ~"cttz16" | ~"cttz32" | ~"cttz64" => 0,
|
||||
|
||||
// would be cool to make these an enum instead of strings!
|
||||
_ => fail ~"unknown intrinsic in type_use"
|
||||
};
|
||||
|
@ -3156,6 +3156,54 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))],
|
||||
ty::mk_f64(tcx))
|
||||
}
|
||||
~"ctpop8" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i8(tcx))],
|
||||
ty::mk_i8(tcx))
|
||||
}
|
||||
~"ctpop16" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i16(tcx))],
|
||||
ty::mk_i16(tcx))
|
||||
}
|
||||
~"ctpop32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i32(tcx))],
|
||||
ty::mk_i32(tcx))
|
||||
}
|
||||
~"ctpop64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))],
|
||||
ty::mk_i64(tcx))
|
||||
}
|
||||
~"ctlz8" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i8(tcx))],
|
||||
ty::mk_i8(tcx))
|
||||
}
|
||||
~"ctlz16" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i16(tcx))],
|
||||
ty::mk_i16(tcx))
|
||||
}
|
||||
~"ctlz32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i32(tcx))],
|
||||
ty::mk_i32(tcx))
|
||||
}
|
||||
~"ctlz64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))],
|
||||
ty::mk_i64(tcx))
|
||||
}
|
||||
~"cttz8" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i8(tcx))],
|
||||
ty::mk_i8(tcx))
|
||||
}
|
||||
~"cttz16" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i16(tcx))],
|
||||
ty::mk_i16(tcx))
|
||||
}
|
||||
~"cttz32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i32(tcx))],
|
||||
ty::mk_i32(tcx))
|
||||
}
|
||||
~"cttz64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))],
|
||||
ty::mk_i64(tcx))
|
||||
}
|
||||
ref other => {
|
||||
tcx.sess.span_err(it.span, ~"unrecognized intrinsic function: `" +
|
||||
(*other) + ~"`");
|
||||
|
112
src/test/run-pass/intrinsics-integer.rs
Normal file
112
src/test/run-pass/intrinsics-integer.rs
Normal file
@ -0,0 +1,112 @@
|
||||
// xfail-fast
|
||||
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
extern mod std;
|
||||
|
||||
#[abi = "rust-intrinsic"]
|
||||
extern mod rusti {
|
||||
fn ctpop8(x: i8) -> i8;
|
||||
fn ctpop16(x: i16) -> i16;
|
||||
fn ctpop32(x: i32) -> i32;
|
||||
fn ctpop64(x: i64) -> i64;
|
||||
|
||||
fn ctlz8(x: i8) -> i8;
|
||||
fn ctlz16(x: i16) -> i16;
|
||||
fn ctlz32(x: i32) -> i32;
|
||||
fn ctlz64(x: i64) -> i64;
|
||||
|
||||
fn cttz8(x: i8) -> i8;
|
||||
fn cttz16(x: i16) -> i16;
|
||||
fn cttz32(x: i32) -> i32;
|
||||
fn cttz64(x: i64) -> i64;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
use rusti::*;
|
||||
|
||||
assert(ctpop8(0i8) == 0i8);
|
||||
assert(ctpop16(0i16) == 0i16);
|
||||
assert(ctpop32(0i32) == 0i32);
|
||||
assert(ctpop64(0i64) == 0i64);
|
||||
|
||||
assert(ctpop8(1i8) == 1i8);
|
||||
assert(ctpop16(1i16) == 1i16);
|
||||
assert(ctpop32(1i32) == 1i32);
|
||||
assert(ctpop64(1i64) == 1i64);
|
||||
|
||||
assert(ctpop8(10i8) == 2i8);
|
||||
assert(ctpop16(10i16) == 2i16);
|
||||
assert(ctpop32(10i32) == 2i32);
|
||||
assert(ctpop64(10i64) == 2i64);
|
||||
|
||||
assert(ctpop8(100i8) == 3i8);
|
||||
assert(ctpop16(100i16) == 3i16);
|
||||
assert(ctpop32(100i32) == 3i32);
|
||||
assert(ctpop64(100i64) == 3i64);
|
||||
|
||||
assert(ctpop8(-1i8) == 8i8);
|
||||
assert(ctpop16(-1i16) == 16i16);
|
||||
assert(ctpop32(-1i32) == 32i32);
|
||||
assert(ctpop64(-1i64) == 64i64);
|
||||
|
||||
assert(ctlz8(0i8) == 8i8);
|
||||
assert(ctlz16(0i16) == 16i16);
|
||||
assert(ctlz32(0i32) == 32i32);
|
||||
assert(ctlz64(0i64) == 64i64);
|
||||
|
||||
assert(ctlz8(1i8) == 7i8);
|
||||
assert(ctlz16(1i16) == 15i16);
|
||||
assert(ctlz32(1i32) == 31i32);
|
||||
assert(ctlz64(1i64) == 63i64);
|
||||
|
||||
assert(ctlz8(10i8) == 4i8);
|
||||
assert(ctlz16(10i16) == 12i16);
|
||||
assert(ctlz32(10i32) == 28i32);
|
||||
assert(ctlz64(10i64) == 60i64);
|
||||
|
||||
assert(ctlz8(100i8) == 1i8);
|
||||
assert(ctlz16(100i16) == 9i16);
|
||||
assert(ctlz32(100i32) == 25i32);
|
||||
assert(ctlz64(100i64) == 57i64);
|
||||
|
||||
assert(cttz8(-1i8) == 0i8);
|
||||
assert(cttz16(-1i16) == 0i16);
|
||||
assert(cttz32(-1i32) == 0i32);
|
||||
assert(cttz64(-1i64) == 0i64);
|
||||
|
||||
assert(cttz8(0i8) == 8i8);
|
||||
assert(cttz16(0i16) == 16i16);
|
||||
assert(cttz32(0i32) == 32i32);
|
||||
assert(cttz64(0i64) == 64i64);
|
||||
|
||||
assert(cttz8(1i8) == 0i8);
|
||||
assert(cttz16(1i16) == 0i16);
|
||||
assert(cttz32(1i32) == 0i32);
|
||||
assert(cttz64(1i64) == 0i64);
|
||||
|
||||
assert(cttz8(10i8) == 1i8);
|
||||
assert(cttz16(10i16) == 1i16);
|
||||
assert(cttz32(10i32) == 1i32);
|
||||
assert(cttz64(10i64) == 1i64);
|
||||
|
||||
assert(cttz8(100i8) == 2i8);
|
||||
assert(cttz16(100i16) == 2i16);
|
||||
assert(cttz32(100i32) == 2i32);
|
||||
assert(cttz64(100i64) == 2i64);
|
||||
|
||||
assert(cttz8(-1i8) == 0i8);
|
||||
assert(cttz16(-1i16) == 0i16);
|
||||
assert(cttz32(-1i32) == 0i32);
|
||||
assert(cttz64(-1i64) == 0i64);
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user