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 +} _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
