Skip to content

Commit baa4379

Browse files
committed
Merge pull request #4245 from JensNockert/bit-intrinsics
Add support for bitcount intrinsics Issue #2777
2 parents 9152463 + 82641d4 commit baa4379

File tree

5 files changed

+270
-1
lines changed

5 files changed

+270
-1
lines changed

src/librustc/middle/trans/base.rs

+36
Original file line numberDiff line numberDiff line change
@@ -2396,6 +2396,30 @@ fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> {
23962396
T_fn(~[T_f32()], T_f32()));
23972397
let truncf64 = decl_cdecl_fn(llmod, ~"llvm.trunc.f64",
23982398
T_fn(~[T_f64()], T_f64()));
2399+
let ctpop8 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i8",
2400+
T_fn(~[T_i8()], T_i8()));
2401+
let ctpop16 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i16",
2402+
T_fn(~[T_i16()], T_i16()));
2403+
let ctpop32 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i32",
2404+
T_fn(~[T_i32()], T_i32()));
2405+
let ctpop64 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i64",
2406+
T_fn(~[T_i64()], T_i64()));
2407+
let ctlz8 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i8",
2408+
T_fn(~[T_i8(), T_i1()], T_i8()));
2409+
let ctlz16 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i16",
2410+
T_fn(~[T_i16(), T_i1()], T_i16()));
2411+
let ctlz32 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i32",
2412+
T_fn(~[T_i32(), T_i1()], T_i32()));
2413+
let ctlz64 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i64",
2414+
T_fn(~[T_i64(), T_i1()], T_i64()));
2415+
let cttz8 = decl_cdecl_fn(llmod, ~"llvm.cttz.i8",
2416+
T_fn(~[T_i8(), T_i1()], T_i8()));
2417+
let cttz16 = decl_cdecl_fn(llmod, ~"llvm.cttz.i16",
2418+
T_fn(~[T_i16(), T_i1()], T_i16()));
2419+
let cttz32 = decl_cdecl_fn(llmod, ~"llvm.cttz.i32",
2420+
T_fn(~[T_i32(), T_i1()], T_i32()));
2421+
let cttz64 = decl_cdecl_fn(llmod, ~"llvm.cttz.i64",
2422+
T_fn(~[T_i64(), T_i1()], T_i64()));
23992423

24002424
let intrinsics = HashMap();
24012425
intrinsics.insert(~"llvm.gcroot", gcroot);
@@ -2436,6 +2460,18 @@ fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> {
24362460
intrinsics.insert(~"llvm.ceil.f64", ceilf64);
24372461
intrinsics.insert(~"llvm.trunc.f32", truncf32);
24382462
intrinsics.insert(~"llvm.trunc.f64", truncf64);
2463+
intrinsics.insert(~"llvm.ctpop.i8", ctpop8);
2464+
intrinsics.insert(~"llvm.ctpop.i16", ctpop16);
2465+
intrinsics.insert(~"llvm.ctpop.i32", ctpop32);
2466+
intrinsics.insert(~"llvm.ctpop.i64", ctpop64);
2467+
intrinsics.insert(~"llvm.ctlz.i8", ctlz8);
2468+
intrinsics.insert(~"llvm.ctlz.i16", ctlz16);
2469+
intrinsics.insert(~"llvm.ctlz.i32", ctlz32);
2470+
intrinsics.insert(~"llvm.ctlz.i64", ctlz64);
2471+
intrinsics.insert(~"llvm.cttz.i8", cttz8);
2472+
intrinsics.insert(~"llvm.cttz.i16", cttz16);
2473+
intrinsics.insert(~"llvm.cttz.i32", cttz32);
2474+
intrinsics.insert(~"llvm.cttz.i64", cttz64);
24392475

24402476
return intrinsics;
24412477
}

src/librustc/middle/trans/foreign.rs

+68
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,74 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
11941194
let truncf = ccx.intrinsics.get(~"llvm.trunc.f64");
11951195
Store(bcx, Call(bcx, truncf, ~[x]), fcx.llretptr);
11961196
}
1197+
~"ctpop8" => {
1198+
let x = get_param(decl, first_real_arg);
1199+
let ctpop = ccx.intrinsics.get(~"llvm.ctpop.i8");
1200+
Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr)
1201+
}
1202+
~"ctpop16" => {
1203+
let x = get_param(decl, first_real_arg);
1204+
let ctpop = ccx.intrinsics.get(~"llvm.ctpop.i16");
1205+
Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr)
1206+
}
1207+
~"ctpop32" => {
1208+
let x = get_param(decl, first_real_arg);
1209+
let ctpop = ccx.intrinsics.get(~"llvm.ctpop.i32");
1210+
Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr)
1211+
}
1212+
~"ctpop64" => {
1213+
let x = get_param(decl, first_real_arg);
1214+
let ctpop = ccx.intrinsics.get(~"llvm.ctpop.i64");
1215+
Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr)
1216+
}
1217+
~"ctlz8" => {
1218+
let x = get_param(decl, first_real_arg);
1219+
let y = C_bool(false);
1220+
let ctlz = ccx.intrinsics.get(~"llvm.ctlz.i8");
1221+
Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr)
1222+
}
1223+
~"ctlz16" => {
1224+
let x = get_param(decl, first_real_arg);
1225+
let y = C_bool(false);
1226+
let ctlz = ccx.intrinsics.get(~"llvm.ctlz.i16");
1227+
Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr)
1228+
}
1229+
~"ctlz32" => {
1230+
let x = get_param(decl, first_real_arg);
1231+
let y = C_bool(false);
1232+
let ctlz = ccx.intrinsics.get(~"llvm.ctlz.i32");
1233+
Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr)
1234+
}
1235+
~"ctlz64" => {
1236+
let x = get_param(decl, first_real_arg);
1237+
let y = C_bool(false);
1238+
let ctlz = ccx.intrinsics.get(~"llvm.ctlz.i64");
1239+
Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr)
1240+
}
1241+
~"cttz8" => {
1242+
let x = get_param(decl, first_real_arg);
1243+
let y = C_bool(false);
1244+
let cttz = ccx.intrinsics.get(~"llvm.cttz.i8");
1245+
Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr)
1246+
}
1247+
~"cttz16" => {
1248+
let x = get_param(decl, first_real_arg);
1249+
let y = C_bool(false);
1250+
let cttz = ccx.intrinsics.get(~"llvm.cttz.i16");
1251+
Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr)
1252+
}
1253+
~"cttz32" => {
1254+
let x = get_param(decl, first_real_arg);
1255+
let y = C_bool(false);
1256+
let cttz = ccx.intrinsics.get(~"llvm.cttz.i32");
1257+
Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr)
1258+
}
1259+
~"cttz64" => {
1260+
let x = get_param(decl, first_real_arg);
1261+
let y = C_bool(false);
1262+
let cttz = ccx.intrinsics.get(~"llvm.cttz.i64");
1263+
Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr)
1264+
}
11971265
_ => {
11981266
// Could we make this an enum rather than a string? does it get
11991267
// checked earlier?

src/librustc/middle/trans/type_use.rs

+5
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
130130
~"floorf32"| ~"floorf64"| ~"ceilf32" | ~"ceilf64" |
131131
~"truncf32"| ~"truncf64" => 0,
132132

133+
~"ctpop8" | ~"ctpop16" | ~"ctpop32" | ~"ctpop64" => 0,
134+
135+
~"ctlz8" | ~"ctlz16" | ~"ctlz32" | ~"ctlz64" => 0,
136+
~"cttz8" | ~"cttz16" | ~"cttz32" | ~"cttz64" => 0,
137+
133138
// would be cool to make these an enum instead of strings!
134139
_ => fail ~"unknown intrinsic in type_use"
135140
};

src/librustc/middle/typeck/check/mod.rs

+49-1
Original file line numberDiff line numberDiff line change
@@ -3156,7 +3156,55 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
31563156
(0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))],
31573157
ty::mk_f64(tcx))
31583158
}
3159-
ref other => {
3159+
~"ctpop8" => {
3160+
(0u, ~[arg(ast::by_copy, ty::mk_i8(tcx))],
3161+
ty::mk_i8(tcx))
3162+
}
3163+
~"ctpop16" => {
3164+
(0u, ~[arg(ast::by_copy, ty::mk_i16(tcx))],
3165+
ty::mk_i16(tcx))
3166+
}
3167+
~"ctpop32" => {
3168+
(0u, ~[arg(ast::by_copy, ty::mk_i32(tcx))],
3169+
ty::mk_i32(tcx))
3170+
}
3171+
~"ctpop64" => {
3172+
(0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))],
3173+
ty::mk_i64(tcx))
3174+
}
3175+
~"ctlz8" => {
3176+
(0u, ~[arg(ast::by_copy, ty::mk_i8(tcx))],
3177+
ty::mk_i8(tcx))
3178+
}
3179+
~"ctlz16" => {
3180+
(0u, ~[arg(ast::by_copy, ty::mk_i16(tcx))],
3181+
ty::mk_i16(tcx))
3182+
}
3183+
~"ctlz32" => {
3184+
(0u, ~[arg(ast::by_copy, ty::mk_i32(tcx))],
3185+
ty::mk_i32(tcx))
3186+
}
3187+
~"ctlz64" => {
3188+
(0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))],
3189+
ty::mk_i64(tcx))
3190+
}
3191+
~"cttz8" => {
3192+
(0u, ~[arg(ast::by_copy, ty::mk_i8(tcx))],
3193+
ty::mk_i8(tcx))
3194+
}
3195+
~"cttz16" => {
3196+
(0u, ~[arg(ast::by_copy, ty::mk_i16(tcx))],
3197+
ty::mk_i16(tcx))
3198+
}
3199+
~"cttz32" => {
3200+
(0u, ~[arg(ast::by_copy, ty::mk_i32(tcx))],
3201+
ty::mk_i32(tcx))
3202+
}
3203+
~"cttz64" => {
3204+
(0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))],
3205+
ty::mk_i64(tcx))
3206+
}
3207+
ref other => {
31603208
tcx.sess.span_err(it.span, ~"unrecognized intrinsic function: `" +
31613209
(*other) + ~"`");
31623210
return;
+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// xfail-fast
2+
3+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
4+
// file at the top-level directory of this distribution and at
5+
// http://rust-lang.org/COPYRIGHT.
6+
//
7+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
8+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
9+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
10+
// option. This file may not be copied, modified, or distributed
11+
// except according to those terms.
12+
13+
extern mod std;
14+
15+
#[abi = "rust-intrinsic"]
16+
extern mod rusti {
17+
fn ctpop8(x: i8) -> i8;
18+
fn ctpop16(x: i16) -> i16;
19+
fn ctpop32(x: i32) -> i32;
20+
fn ctpop64(x: i64) -> i64;
21+
22+
fn ctlz8(x: i8) -> i8;
23+
fn ctlz16(x: i16) -> i16;
24+
fn ctlz32(x: i32) -> i32;
25+
fn ctlz64(x: i64) -> i64;
26+
27+
fn cttz8(x: i8) -> i8;
28+
fn cttz16(x: i16) -> i16;
29+
fn cttz32(x: i32) -> i32;
30+
fn cttz64(x: i64) -> i64;
31+
}
32+
33+
fn main() {
34+
35+
use rusti::*;
36+
37+
assert(ctpop8(0i8) == 0i8);
38+
assert(ctpop16(0i16) == 0i16);
39+
assert(ctpop32(0i32) == 0i32);
40+
assert(ctpop64(0i64) == 0i64);
41+
42+
assert(ctpop8(1i8) == 1i8);
43+
assert(ctpop16(1i16) == 1i16);
44+
assert(ctpop32(1i32) == 1i32);
45+
assert(ctpop64(1i64) == 1i64);
46+
47+
assert(ctpop8(10i8) == 2i8);
48+
assert(ctpop16(10i16) == 2i16);
49+
assert(ctpop32(10i32) == 2i32);
50+
assert(ctpop64(10i64) == 2i64);
51+
52+
assert(ctpop8(100i8) == 3i8);
53+
assert(ctpop16(100i16) == 3i16);
54+
assert(ctpop32(100i32) == 3i32);
55+
assert(ctpop64(100i64) == 3i64);
56+
57+
assert(ctpop8(-1i8) == 8i8);
58+
assert(ctpop16(-1i16) == 16i16);
59+
assert(ctpop32(-1i32) == 32i32);
60+
assert(ctpop64(-1i64) == 64i64);
61+
62+
assert(ctlz8(0i8) == 8i8);
63+
assert(ctlz16(0i16) == 16i16);
64+
assert(ctlz32(0i32) == 32i32);
65+
assert(ctlz64(0i64) == 64i64);
66+
67+
assert(ctlz8(1i8) == 7i8);
68+
assert(ctlz16(1i16) == 15i16);
69+
assert(ctlz32(1i32) == 31i32);
70+
assert(ctlz64(1i64) == 63i64);
71+
72+
assert(ctlz8(10i8) == 4i8);
73+
assert(ctlz16(10i16) == 12i16);
74+
assert(ctlz32(10i32) == 28i32);
75+
assert(ctlz64(10i64) == 60i64);
76+
77+
assert(ctlz8(100i8) == 1i8);
78+
assert(ctlz16(100i16) == 9i16);
79+
assert(ctlz32(100i32) == 25i32);
80+
assert(ctlz64(100i64) == 57i64);
81+
82+
assert(cttz8(-1i8) == 0i8);
83+
assert(cttz16(-1i16) == 0i16);
84+
assert(cttz32(-1i32) == 0i32);
85+
assert(cttz64(-1i64) == 0i64);
86+
87+
assert(cttz8(0i8) == 8i8);
88+
assert(cttz16(0i16) == 16i16);
89+
assert(cttz32(0i32) == 32i32);
90+
assert(cttz64(0i64) == 64i64);
91+
92+
assert(cttz8(1i8) == 0i8);
93+
assert(cttz16(1i16) == 0i16);
94+
assert(cttz32(1i32) == 0i32);
95+
assert(cttz64(1i64) == 0i64);
96+
97+
assert(cttz8(10i8) == 1i8);
98+
assert(cttz16(10i16) == 1i16);
99+
assert(cttz32(10i32) == 1i32);
100+
assert(cttz64(10i64) == 1i64);
101+
102+
assert(cttz8(100i8) == 2i8);
103+
assert(cttz16(100i16) == 2i16);
104+
assert(cttz32(100i32) == 2i32);
105+
assert(cttz64(100i64) == 2i64);
106+
107+
assert(cttz8(-1i8) == 0i8);
108+
assert(cttz16(-1i16) == 0i16);
109+
assert(cttz32(-1i32) == 0i32);
110+
assert(cttz64(-1i64) == 0i64);
111+
112+
}

0 commit comments

Comments
 (0)