ISL's high-level rust binding

27 views
Skip to first unread message

Schrodinger ZHU Yifan

unread,
May 7, 2025, 1:02:42 PMMay 7
to isl-dev...@googlegroups.com
Dear all,

We are working on a new high-level rust bindings for ISL/Barvinok. We use high-level abstractions such as invariant lifetimes to automatically safeguard the isl context and provide rusty-style memory management in comparison to previous attempts. Currently, the binding is under development at https://github.com/Roc-Locality/barvinok-rs.

I have built a macro system to map directly based on the take/keep/give annotations:

isl_flag!(set_is_strict_subset => strict_subset, [ref] other : &Set<'a>);
isl_flag!(set_has_equal_space => has_equal_space, [ref] other : &Set<'a>);
isl_transform!(sum, isl_set_sum, [managed] other : Set<'a>);
isl_transform!(checked_neg, isl_set_neg);
isl_transform!(make_disjoint, isl_set_make_disjoint);
isl_transform!(compute_divs, isl_set_compute_divs);
isl_flag!(set_dim_is_bounded => dim_is_bounded, [cast(u32)] ty : DimType, [trivial] pos : u32);
isl_flag!(set_dim_has_lower_bound => dim_has_lower_bound, [cast(u32)] ty : DimType, [trivial] pos : u32);
isl_flag!(set_dim_has_upper_bound => dim_has_upper_bound, [cast(u32)] ty : DimType, [trivial] pos : u32);
isl_flag!(set_dim_has_any_lower_bound => dim_has_any_lower_bound, [cast(u32)] ty : DimType, [trivial] pos : u32);
isl_flag!(set_dim_has_any_upper_bound => dim_has_any_upper_bound, [cast(u32)] ty : DimType, [trivial] pos : u32);
isl_project!([into(Value)] plain_get_val_if_fixed, isl_set_plain_get_val_if_fixed, [cast(u32)] ty : DimType, [trivial] pos : u32);
isl_transform!(gist, isl_set_gist, [managed] context : Set<'a>);


It is already capable of counting reuse interval values for loop nests:

#[test]
    fn test_construct_triangular_iteration_space() -> anyhow::Result<()> {
        // for i in 0 .. n
        //     for j in 0 .. i
        //         for k in 0 .. j
        let ctx = Context::new();
        ctx.scope(|ctx| {
            let space = Space::new_set(ctx, 1, 3);
            let local_space = LocalSpace::from(space.clone());
            let i_ge_0 = Constraint::new_inequality(local_space.clone())
                .set_coefficient_si(DimType::Out, 0, 1)?
                .set_constant_si(0)?;
            let i_lt_n = Constraint::new_inequality(local_space.clone())
                .set_coefficient_si(DimType::Param, 0, 1)?
                .set_coefficient_si(DimType::Out, 0, -1)?
                .set_constant_si(-1)?;
            let j_ge_0 = Constraint::new_inequality(local_space.clone())
                .set_coefficient_si(DimType::Out, 1, 1)?
                .set_constant_si(0)?;
            let j_lt_i = Constraint::new_inequality(local_space.clone())
                .set_coefficient_si(DimType::Out, 0, 1)?
                .set_coefficient_si(DimType::Out, 1, -1)?
                .set_constant_si(-1)?;
            let k_ge_0 = Constraint::new_inequality(local_space.clone())
                .set_coefficient_si(DimType::Out, 2, 1)?
                .set_constant_si(0)?;
            let k_lt_j = Constraint::new_inequality(local_space.clone())
                .set_coefficient_si(DimType::Out, 1, 1)?
                .set_coefficient_si(DimType::Out, 2, -1)?
                .set_constant_si(-1)?;
            let set = Set::universe(space.clone())?
                .add_constraint(i_ge_0)?
                .add_constraint(i_lt_n)?
                .add_constraint(j_ge_0)?
                .add_constraint(j_lt_i)?
                .add_constraint(k_ge_0)?
                .add_constraint(k_lt_j)?
                .set_dim_name(DimType::Param, 0, "n")?
                .set_dim_name(DimType::Out, 0, "i")?
                .set_dim_name(DimType::Out, 1, "j")?
                .set_dim_name(DimType::Out, 2, "k")?;
            println!("iteration space {:?}", set);
            let card = set.cardinality()?;
            println!("cardinality {:?}", card);
            Ok(())
        })
    }


We welcome any feedback and contribution. The porting work is quite heavy and I may not be able to finish it on myself. If anyone is interested in this project, please feel free to reach out!

Yifan

image
Schrodinger ZHU Yifan, Ph.D. Student
Computer Science Department, University of Rochester

Personal Email: i...@zhuyi.fan
Github: SchrodingerZhu
GPG Fingerprint: BA02CBEB8CB5D8181E9368304D2CC545A78DBCC3
publickey - i@zhuyi.fan - 0xA98A3EAE.asc
signature.asc

Sven Verdoolaege

unread,
May 7, 2025, 2:19:56 PMMay 7
to Schrodinger ZHU Yifan, isl-dev...@googlegroups.com
On Wed, May 07, 2025 at 01:34:49PM +0000, 'Schrodinger ZHU Yifan' via isl Development wrote:
> Dear all,
>
> We are working on a new high-level rust bindings for ISL/Barvinok. We use high-level abstractions such as invariant lifetimes to automatically safeguard the isl context and provide rusty-style memory management in comparison to previous attempts. Currently, the binding is under development at https://github.com/Roc-Locality/barvinok-rs.
>
> I have built a macro system to map directly based on the take/keep/give annotations:

Have you considered generating the interface using the isl_export
annotations like interface/extract_interface does for C++ and Python bindings?

> #[test]    fn test_construct_triangular_iteration_space() -> anyhow::Result<()> {
>         // for i in 0 .. n
>         //     for j in 0 .. i
>         //         for k in 0 .. j
>         let ctx = Context::new();
>         ctx.scope(|ctx| {
>             let space = Space::new_set(ctx, 1, 3);
>             let local_space = LocalSpace::from(space.clone());
>             let i_ge_0 = Constraint::new_inequality(local_space.clone())
>                 .set_coefficient_si(DimType::Out, 0, 1)?

The generated interface don't have any type corresponding to isl_dim_type
because in hindsight I figured out it wasn't a good idea to introduce
that type in the C interface.

skimo
Reply all
Reply to author
Forward
0 new messages