<div dir="ltr">Hi all,<br><br>I think I've managed to trick the legacy MemCpyOpt (MCO) into an incorrect<br>transform, but I would like to confirm the validity of my counterexample before<br>working on the fix. Suppose the following IR:<br><br>    %T = type { i32, i32 }<br><br>    define void @f(%T* %a, %T* %b, %T* %c, %T* %d) {<br>        %val = load %T, %T* %a, !alias.scope !{!10}<br><br>        ; store1<br>        ; Aliases the load<br>        store %T { i32 22, i32 22 }, %T* %b, !alias.scope !{!11}<br><br>        ; store2<br>        ; Aliases the store below and the load. No-alias with above store<br>        store %T { i32 44, i32 44 }, %T* %c, !alias.scope !{!12},<br>              !noalias !{!11}<br><br>        ; store3<br>        ; MCO wants to combine this store with the load into a memcpy<br>        store %T %val, %T* %d, !alias.scope !{!13}, !noalias !{!10, !11}<br>        ret void<br>    }<br><br>!0 = !{!0}<br>!1 = !{!1}<br>!2 = !{!2}<br>!3 = !{!3}<br><br>!10 = !{ !10, !0 }<br>!11 = !{ !11, !1 }<br>!12 = !{ !12, !2 }<br>!13 = !{ !13, !3 }<br><br>Have I used the metadata nodes correctly? The goal is to make:<br><br>- load may-alias store1<br>- load may-alias store2<br>- store2 may-alias store3<br><br>`-print-may-aliases` seems confirm this:<br><br>    opt -disable-output -basicaa -scoped-noalias -aa-eval -evaluate-aa-metadata -print-may-aliases ohgod.ll <br>    Function: f: 4 pointers, 0 call sites<br>      MayAlias:     %T* %a, %T* %b<br>      MayAlias:     %T* %a, %T* %c<br>      MayAlias:     %T* %b, %T* %c<br>      MayAlias:     %T* %a, %T* %d<br>      MayAlias:     %T* %b, %T* %d<br>      MayAlias:     %T* %c, %T* %d<br>      MayAlias:   %val = load %T, %T* %a, !alias.scope !0 <->   store %T { i32 23, i32 23 }, %T* %b, !alias.scope !3<br>      MayAlias:   %val = load %T, %T* %a, !alias.scope !0 <->   store %T { i32 44, i32 44 }, %T* %c, !alias.scope !6, !noalias !3<br>      MayAlias:   store %T %val, %T* %d, !alias.scope !9, !noalias !12 <->   store %T { i32 44, i32 44 }, %T* %c, !alias.scope !6, !noalias !3<br><br>The problem is that MCO happily moves store2 + store3 above store1 (this is<br>fine) and then the load below store2 (this is not fine) in order to combine<br>load + store3 into a memcpy:<br><br>    opt -S -basicaa -scoped-noalias -aa-eval -evaluate-aa-metadata -memcpyopt<br><br>    %T = type { i32, i32 }<br><br>    define void @f(%T* %a, %T* %b, %T* %c, %T* %d) {<br>      ; store2<br>      store %T { i32 44, i32 44 }, %T* %c, !alias.scope !0, !noalias !3<br><br>      ; combined from load + store3<br>      call void @llvm.memcpy.p0i8.p0i8.i64(i8* (bitcast %T* %d to i8*),<br>                                           i8* (bitcast %T* %a to i8*),<br>                                           i64 8, i32 4, i1 false)<br><br>      ; store1<br>      store %T { i32 23, i32 23 }, %T* %b, !alias.scope !3<br>      ret void<br>    }<br><br></div>