diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -111,12 +111,14 @@ if (!MI) return false; + // If the transfer is volatile, reject it. + if (MI->isVolatile()) + return false; + // If the transfer is using the alloca as a source of the transfer, then // ignore it since it is a load (unless the transfer is volatile). - if (U.getOperandNo() == 1) { - if (MI->isVolatile()) return false; + if (U.getOperandNo() == 1) continue; - } // If we already have seen a copy, reject the second one. if (TheCopy) return false; diff --git a/llvm/test/Transforms/InstCombine/memcpy-from-global.ll b/llvm/test/Transforms/InstCombine/memcpy-from-global.ll --- a/llvm/test/Transforms/InstCombine/memcpy-from-global.ll +++ b/llvm/test/Transforms/InstCombine/memcpy-from-global.ll @@ -366,10 +366,12 @@ ret void } -; FIXME: Test that we incorrectly elide a volatile memcpy. +; Test that we don't elide a volatile memcpy. define void @volatile_memcpy() { ; CHECK-LABEL: @volatile_memcpy( -; CHECK-NEXT: call void @bar(ptr nonnull @H) #[[ATTR3]] +; CHECK-NEXT: [[A:%.*]] = alloca [[U:%.*]], align 16 +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[A]], ptr align 4 @H, i64 20, i1 true) +; CHECK-NEXT: call void @bar(ptr nonnull [[A]]) #[[ATTR3]] ; CHECK-NEXT: ret void ; %A = alloca %U, align 16