[llvm-branch-commits] [llvm] [LICM] Do not strip invariant AA tags (PR #222686)
Nikita Popov via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat Sep 12 11:14:08 PDT 2026
nikic wrote:
AI flagged a possible miscompile introduced in this change. Consider a case like this:
```llvm
define i32 @f(i32 %v) {
entry:
%p = alloca i32, align 4
store i32 0, ptr %p, align 4
br label %loop
loop:
%i = phi i32 [ 0, %entry ], [ %i.next, %loop.latch ]
call void @llvm.experimental.noalias.scope.decl(metadata !2)
%c = icmp eq i32 %i, 0
br i1 %c, label %if, label %else
if:
call void @llvm.memset.p0.i64(ptr align 4 %p, i8 1, i64 4, i1 false), !alias.scope !2
br label %loop.latch
else:
%ld = load i32, ptr %p, align 4, !noalias !2
%new = add i32 %ld, %v
store i32 %new, ptr %p, align 4, !noalias !2
%e = icmp ugt i32 %i, 2
br i1 %e, label %exit, label %loop.latch
loop.latch:
%i.next = add i32 %i, 1
br label %loop
exit:
%r = load i32, ptr %p, align 4
ret i32 %r
}
!0 = !{!0}
!1 = !{!1, !0}
!2 = !{!1}
```
Notably, we have a noalias.scope.decl inside the loop, which means that the noalias metadata only holds within one loop iteration. As the if/else code paths are disjoint, the alias scope metadata is correct and there is no UB.
However, we now preserve the noalias metadata in `else`, which is is an exiting block, so we do know that it must hold on the last iteration. But we use it to prove noalias with the memset on a different iteration.
(After seeing this, I suspect that we have some other places that may not handle per-iteration scoped alias metadata correctly. Any place using the AA cross iteration mode is suspect. LAA has explicit handling for this, but DA probably gets it wrong, and MSSA translation across phis likely as well...)
https://github.com/llvm/llvm-project/pull/222686
More information about the llvm-branch-commits
mailing list