Skip to content
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

Assume alignment when loading from pointer #3562

Open
JohanEngelen opened this issue Sep 15, 2020 · 5 comments · May be fixed by #3580
Open

Assume alignment when loading from pointer #3562

JohanEngelen opened this issue Sep 15, 2020 · 5 comments · May be fixed by #3580

Comments

@JohanEngelen
Copy link
Member

As far as I know, unaligned memory access is UB in D. We don't yet make use of this in all cases.

align(64)
struct int64 {
    int i;
    alias i this;
}

int64* g();

int foo() {
    auto t = g();
    return *t;
}

int f(int64* i) { return *i;}

creates the IR:

define i32 @_D7example3fooFZi() local_unnamed_addr #1 {
  %1 = tail call %example.int64* @_D7example1gFZPSQo5int64() #0
  %2 = getelementptr inbounds %example.int64, %example.int64* %1, i64 0, i32 0
  %3 = load i32, i32* %2, align 4
  ret i32 %3
}

define i32 @_D7example1fFPSQn5int64Zi(%example.int64* nocapture readonly %i_arg) local_unnamed_addr #2 {
  %1 = getelementptr inbounds %example.int64, %example.int64* %i_arg, i64 0, i32 0
  %2 = load i32, i32* %1, align 4
  ret i32 %2
}

Note that align 4 instead of align 64. (The align 4 is actually deduced by LLVM (loading an i32), and not emitted by LDC.)

I think we can be aggressive here and emit align 64.
Clang does that too.

@p0nce
Copy link
Contributor

p0nce commented Jan 1, 2021

Related: https://forum.dlang.org/thread/xntxnthytvnxdmhkerrj@forum.dlang.org would greatly appreciate your input!

@JohanEngelen
Copy link
Member Author

My interpretation is that a pointer of type T does not always have to be aligned. But when you dereference the pointer (e.g. read or write), then it has to be aligned.

@p0nce
Copy link
Contributor

p0nce commented Jan 2, 2021

Is there a transition path though?
That means *cast(int*)(any pointer to valid memory) would become UB because it needs an alignement of 4 bytes, but I think this kind of things happens lots of time in code in the wild ; it would have to be converted to ubyte* everytime?
(OTOH, if that leads to speed-up it will be very cool)

@JohanEngelen
Copy link
Member Author

Is there a transition path though?
That means *cast(int*)(any pointer to valid memory) would become UB because it needs an alignement of 4 bytes, but I think this kind of things happens lots of time in code in the wild ; it would have to be converted to ubyte* everytime?
(OTOH, if that leads to speed-up it will be very cool)

Yes, this is already UB. In practice, the code will just crash on, say, some ARM architectures that do not support unaligned access in general.
It doesn't happen so often in practice, but indeed I believe it is one of the common problems when porting code from x86 to another architecture.

@JohanEngelen
Copy link
Member Author

related: #4236

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants