[llvm-branch-commits] [llvm] b93a9d0 - [MemCpyOpt] Don't perform stack-move opt for out-of-bounds copy (#217607)

Douglas Yung via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Aug 24 05:28:44 PDT 2026


Author: Nikita Popov
Date: 2026-08-24T12:28:28Z
New Revision: b93a9d0a873ef43973e33ea4c9a66fae7281a253

URL: https://github.com/llvm/llvm-project/commit/b93a9d0a873ef43973e33ea4c9a66fae7281a253
DIFF: https://github.com/llvm/llvm-project/commit/b93a9d0a873ef43973e33ea4c9a66fae7281a253.diff

LOG: [MemCpyOpt] Don't perform stack-move opt for out-of-bounds copy (#217607)

There can be a copy with an out of bounds offset in dead code. If the
perform the stack-move optimization based on that, we'll end up merging
an alloca into an out-of-bounds offset of another alloca, which will
result in UB (when used in non-dead code).

Fixes https://github.com/llvm/llvm-project/issues/216566.

(cherry picked from commit 8ab2745ce76041a0404c36aea5c37160f10d8840)

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
    llvm/test/Transforms/MemCpyOpt/stack-move-offset.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 92e1d9cf21240..a8b6bc7b275b2 100644
--- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -1572,6 +1572,13 @@ bool MemCpyOptPass::performStackMoveOptzn(Instruction *Load, Instruction *Store,
     return false;
   }
 
+  if (*SrcOffset) {
+    // Make sure that the copied offset is actually part of the alloca. There
+    // might be an out-of-bounds copy in dead code.
+    if (!Size.isFixed() || *SrcOffset + Size > *SrcSize)
+      return false;
+  }
+
   // Check if it will be legal to combine allocas without breaking dominator.
   bool MoveSrc = !DT->dominates(SrcAlloca, DestAlloca);
   if (MoveSrc) {

diff  --git a/llvm/test/Transforms/MemCpyOpt/stack-move-offset.ll b/llvm/test/Transforms/MemCpyOpt/stack-move-offset.ll
index ee15babdd3896..80cb21dee3d1e 100644
--- a/llvm/test/Transforms/MemCpyOpt/stack-move-offset.ll
+++ b/llvm/test/Transforms/MemCpyOpt/stack-move-offset.ll
@@ -282,3 +282,37 @@ define void @no_optimize_clobbering_store_to_src_offset(ptr noalias %dst) {
 
   ret void
 }
+
+; https://github.com/llvm/llvm-project/issues/216566
+; There could be a copy using an out of bounds offset in dead code. Don't
+; optimize such cases.
+define i32 @out_of_bounds_offset() {
+; CHECK-LABEL: define i32 @out_of_bounds_offset() {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[A2:%.*]] = alloca i8, align 1
+; CHECK-NEXT:    [[A3:%.*]] = alloca i8, align 1
+; CHECK-NEXT:    br i1 true, label [[IF_THEN1:%.*]], label [[IF_THEN2:%.*]]
+; CHECK:       if.then1:
+; CHECK-NEXT:    store i8 0, ptr [[A2]], align 1
+; CHECK-NEXT:    ret i32 0
+; CHECK:       if.then2:
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[A3]], i64 123
+; CHECK-NEXT:    [[V:%.*]] = load i8, ptr [[GEP]], align 1
+; CHECK-NEXT:    store i8 [[V]], ptr [[A2]], align 1
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %a1 = alloca i8, align 1
+  %a2 = alloca i8, align 1
+  br i1 true, label %if.then1, label %if.then2
+
+if.then1:
+  store i8 0, ptr %a1
+  ret i32 0
+
+if.then2:
+  %gep = getelementptr i8, ptr %a2, i64 123
+  %v = load i8, ptr %gep
+  store i8 %v, ptr %a1
+  ret i32 0
+}


        


More information about the llvm-branch-commits mailing list