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

[DSE] dereferenceable attribute should be updated after shortening memset at the beginning #115976

Closed
dtcxzyw opened this issue Nov 13, 2024 · 0 comments · Fixed by #125073
Closed

Comments

@dtcxzyw
Copy link
Member

dtcxzyw commented Nov 13, 2024

; bin/opt -passes=dse test.ll -S
define void @test(ptr %p) {
  call void @llvm.memset.p0.i64(ptr noundef nonnull align 4 dereferenceable(100) %p, i8 0, i64 100, i1 false)
  store i32 5, ptr %p, align 4
  %4 = getelementptr inbounds i8, ptr %p, i64 4
  store i32 8, ptr %4, align 4
  %5 = getelementptr inbounds i8, ptr %p, i64 8
  store i32 5, ptr %5, align 4
  %6 = getelementptr inbounds i8, ptr %p, i64 12
  store i32 8, ptr %6, align 4
  ret void
}
define void @test(ptr %p) {
  %1 = getelementptr inbounds i8, ptr %p, i64 16
  call void @llvm.memset.p0.i64(ptr noundef nonnull align 4 dereferenceable(100) %1, i8 0, i64 84, i1 false)
  store i32 5, ptr %p, align 4
  %2 = getelementptr inbounds i8, ptr %p, i64 4
  store i32 8, ptr %2, align 4
  %3 = getelementptr inbounds i8, ptr %p, i64 8
  store i32 5, ptr %3, align 4
  %4 = getelementptr inbounds i8, ptr %p, i64 12
  store i32 8, ptr %4, align 4
  ret void
}

Found with https://github.com/dtcxzyw/llvm-ub-aware-interpreter.

@dtcxzyw dtcxzyw self-assigned this Nov 13, 2024
@bjope bjope closed this as completed in 7401672 Feb 18, 2025
wldfngrs pushed a commit to wldfngrs/llvm-project that referenced this issue Feb 19, 2025
…tr (llvm#125073)

Consider IR like this
call void @llvm.memset.p0.i64(ptr dereferenceable(28) %p, i8 0, i64 28,
i1 false)
  store i32 1, ptr %p

In the past it has been optimized like this:
  %p2 = getelementptr inbounds i8, ptr %p, i64 4
call void @llvm.memset.p0.i64(ptr dereferenceable(28) %p2, i8 0, i64 24,
i1 false)
  store i32 1, ptr %p

As the input IR doesn't guarantee that it is OK to deref 28 bytes
starting at the adjusted pointer %p2 the transformation has been a bit
flawed.

With this patch we make sure to drop any
dereferenceable/dereferenceable_or_null attributes when doing such
transforms. An alternative would have been to adjust the amount of
dereferenceable bytes, but since a memset with a constant length already
implies dereferenceability by itself it is simpler to just drop the
attributes.

The new filtering of attributes is done using a helper that only keep
attributes that we explicitly handle. For the adjusted mem instrinsic
pointers that currently involve "NonNull", "NoUndef" and "Alignment"
(when the alignment is known to be fulfilled also after offsetting the
pointer).

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

Successfully merging a pull request may close this issue.

1 participant