[PATCH] D150967: [MemCpyOpt] precommit test for memcpy removal for immutable arguments from attributes (NFC)

Nikita Popov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun May 21 10:08:39 PDT 2023


nikic added inline comments.


================
Comment at: llvm/test/Transforms/MemCpyOpt/memcpy.ll:398
+declare void @fnr(ptr noalias readonly)
+define noundef i32 @noalias_readonly_i8(ptr align 4 noalias readonly %val) {
+; CHECK-LABEL: @noalias_readonly_i8(
----------------
khei4 wrote:
> nikic wrote:
> > Drop noundef, it's not relevant. Can also change return type to void. I also don't think `noalias readonly` on the function argument matter, only `align 4`. The `noalias readonly` are relevant on the call only.
> > Drop noundef, it's not relevant. Can also change return type to void. 
> 
> Thanks! They seemed correct!
> 
> > I also don't think noalias readonly on the function argument matter, only align 4. The noalias readonly are relevant on the call only.
> 
> I worry about the case like
> 
> ```
> #include <thread>
> 
> void ro(int &d) { d; }
> 
> void w(int &d) { d = 13; }
> 
> int main() {
>   int *src, *dest1, *dest2;
>   *src = 42;
>   std::memcpy(dest1, src, sizeof dest1);
>   std::thread ro_t1(ro, dest1);
>   std::memcpy(dest2, src, sizeof dest2);
>   std::thread w_t(w, dest2);
>   std::thread ro_t2(ro, dest2);
> }
> ```
> (although I'm not sure `noalias` can be actually attributed for this specific case)
> 
> It seems like the transformation would break the `noalias` property of the callee parameter, because memcpy might be used to introduce the actual `noalias` property.  
Yes, I think you're right. Basically, in terms of clobbers, the things we have to ensure are:

* The memcpy dst is not modified by the call. (The noalias readonly ensures this.)
* The memcpy dst is not modified between the memcpy and the call. (Needs MSSA clobber check.)
* The memcpy src is not modified between the memcpy and the call. (Needs MSSA clobber check.)
* The memcpy src is not modified by the call. Needs a ModRef check. This is the bit that could be ensured by noalias readonly the function parameter. (But also through other means, e.g. if the source is an unescaped alloca.)


================
Comment at: llvm/test/Transforms/MemCpyOpt/memcpy.ll:409
+  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
+  %0 = call noundef i32 @fnr(ptr align 4 noalias readonly %val1)
+  ret i32 %0
----------------
khei4 wrote:
> khei4 wrote:
> > nikic wrote:
> > > Also needs `nocapture`, otherwise the address may be significant.
> > Thanks! Yeah, removing memcpy by only `noalias` and `readonly` might broke capturing behavior! 
> > Also I noticed `readnone` doesn't need `nocapture`, so I'll add a test for that case :)
> > 
> > Also I noticed readnone doesn't need nocapture, so I'll add a test for that case :)
> 
> Sorry, that's not. Maybe `readnone` only guarantee no-deref, so capturing with `readnone` seems valid. 
Yes, a readnone argument can still be captured. Even if the function itself is `memory(none)` it can still be captured via return value or via unwind/divergence side effects.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D150967/new/

https://reviews.llvm.org/D150967



More information about the llvm-commits mailing list