diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp --- a/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -1207,7 +1207,8 @@ // Otherwise, if we have a single return value case, and if the function is // a declaration, maybe we can constant fold it. - if (F && F->isDeclaration() && canConstantFoldCallTo(&CB, F)) { + if (F && (F->isDeclaration() || F->hasOptNone()) && + canConstantFoldCallTo(&CB, F)) { SmallVector Operands; for (auto AI = CB.arg_begin(), E = CB.arg_end(); AI != E; ++AI) { if (AI->get()->getType()->isStructTy()) @@ -1380,7 +1381,7 @@ // The common case is that we aren't tracking the callee, either because we // are not doing interprocedural analysis or the callee is indirect, or is // external. Handle these cases first. - if (!F || F->isDeclaration()) + if (!F || F->isDeclaration() || F->hasOptNone()) return handleCallOverdefined(CB); // If this is a single/zero retval case, see if we're tracking the function. @@ -1940,6 +1941,10 @@ for (Function &F : M) { if (F.isDeclaration()) continue; + if (F.hasOptNone()) { + Solver.MarkBlockExecutable(&F.front()); + continue; + } Solver.addAnalysis(F, getAnalysis(F)); @@ -1992,7 +1997,7 @@ // constants if we have found them to be of constant values. for (Function &F : M) { - if (F.isDeclaration()) + if (F.isDeclaration() || F.hasOptNone()) continue; SmallVector BlocksToErase; diff --git a/llvm/test/Transforms/SCCP/optnone.ll b/llvm/test/Transforms/SCCP/optnone.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/SCCP/optnone.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -ipsccp -instcombine -S | FileCheck %s + +attributes #0 = { noinline optnone } + +define i32 @callee() #0 { + ret i32 52 +} + +define i32 @caller() { + ; CHECK: define i32 @caller() + ; CHECK: ret i32 %X + %X = call i32 @callee() + ret i32 %X +} +