New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

noalias on all parameters by default (with debug safety); ability to specify mayalias #1108

Open
andrewrk opened this Issue Jun 13, 2018 · 2 comments

Comments

Projects
None yet
2 participants
@andrewrk
Member

andrewrk commented Jun 13, 2018

I'm extracting this (flawed) proposal out of #733.

  • Add mayalias keyword
  • Remove noalias keyword
  • mayalias valid only on a pointer parameter. It means "may be aliased by global variables or other arguments to this function which are mutable pointers"
  • Debug safety
    • At the beginning of each function, verify that no mutable pointers with known sizes (*T, *[N]T, and []T) overlap with each other, or with any const pointers with known sizes
  • In Zig IR, pointer values track the set of noalias parameters and global variables possibly referenced
    • slice and getelementptr instructions that include a noalias var of
      unknown len ptr in the set do a safety check to find overlap
  • When generating LLVM,
    • load instructions based on const ptr noalias variables !alias.scope
      a scope unique to the function but shared by each other (the function's
      const ptr alias scope)
    • load instructions based on mut ptr noalias variables !alias.scope
      a unique scope per var
    • Store instructions based on noalias variables !noalias all the
      function's noalias var scopes they are not based on, and the function's
      const ptr alias scope
  • Verify that LLVM can take advantage of these annotations

Depends on #561 so we can put llvm parameter attributes on slice pointers

This proposal needs work. Consider this example:

const Context = struct {
    // some useful fields, and then
    preallocated_point: Point,
};

const Point = struct {
    x: i32,
    y: i32,
}

fn incrementXAndPrint(self: *Context, pt: *Point) {
    pt.x += 1;
    self.log("point: {v}\n", pt);
}

test "aoeu" {
    var c = Context {
        .preallocated_point = Point { .x = 0, .y = 0 },
    };
    incrementXAndPrint(&c, &c.preallocated_point);
}

This would trigger the proposed debug safety but it does not actually represent problematic behavior, since the value is never accessed via the other pointer.

One proposal adjustment could be to do all the runtime safety only at store instructions for everything. I fear this would be too slow in practice, however it is worth experimenting with before shutting the idea down. I'll first verify that LLVM would be able to take advantage of these annotations though.

@andrewrk

This comment has been minimized.

Member

andrewrk commented Sep 26, 2018

Related: #476

@andrewrk andrewrk modified the milestones: 0.4.0, 0.5.0 Nov 21, 2018

@daurnimator

This comment has been minimized.

Contributor

daurnimator commented Nov 28, 2018

I'll first verify that LLVM would be able to take advantage of these annotations though.

It is, but there have been some issues. It looks like rust currently has related optimizations disabled due to rust-lang/rust#54878

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment