diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index ce083979afc63a..7ebf265e17ba1f 100644 --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -1296,6 +1296,12 @@ static void addNoUndefAttrs(const SCCNodeSet &SCCNodes, if (!F->hasExactDefinition()) return; + // MemorySanitizer assumes that the definition and declaration of a + // function will be consistent. A function with sanitize_memory attribute + // should be skipped from inference. + if (F->hasFnAttribute(Attribute::SanitizeMemory)) + continue; + if (F->getReturnType()->isVoidTy()) continue; diff --git a/llvm/test/Transforms/FunctionAttrs/noundef.ll b/llvm/test/Transforms/FunctionAttrs/noundef.ll index b357587cc12394..946b562f39553e 100644 --- a/llvm/test/Transforms/FunctionAttrs/noundef.ll +++ b/llvm/test/Transforms/FunctionAttrs/noundef.ll @@ -143,3 +143,12 @@ define i32 @test_noundef_prop() { %ret = call i32 @test_ret_constant() ret i32 %ret } + +; Don't deduce noundef for functions with sanitize_memory. +define i32 @test_ret_constant_msan() sanitize_memory { +; CHECK-LABEL: define i32 @test_ret_constant_msan( +; CHECK-SAME: ) #[[ATTR1:[0-9]+]] { +; CHECK-NEXT: ret i32 0 +; + ret i32 0 +}