Index: lib/Analysis/ConstantFolding.cpp =================================================================== --- lib/Analysis/ConstantFolding.cpp +++ lib/Analysis/ConstantFolding.cpp @@ -1015,6 +1015,8 @@ case Instruction::ICmp: case Instruction::FCmp: llvm_unreachable("Invalid for compares"); case Instruction::Call: + if (cast(InstOrCE)->isNoBuiltin()) + return nullptr; if (auto *F = dyn_cast(Ops.back())) if (canConstantFoldCallTo(F)) return ConstantFoldCall(F, Ops.slice(0, Ops.size() - 1), TLI); @@ -2063,6 +2065,9 @@ bool llvm::isMathLibCallNoop(CallSite CS, const TargetLibraryInfo *TLI) { // FIXME: Refactor this code; this duplicates logic in LibCallsShrinkWrap // (and to some extent ConstantFoldScalarCall). + if (CS.isNoBuiltin()) + return false; + Function *F = CS.getCalledFunction(); if (!F) return false; Index: lib/Analysis/InlineCost.cpp =================================================================== --- lib/Analysis/InlineCost.cpp +++ lib/Analysis/InlineCost.cpp @@ -874,7 +874,7 @@ // because we have to continually rebuild the argument list even when no // simplifications can be performed. Until that is fixed with remapping // inside of instsimplify, directly constant fold calls here. - if (!canConstantFoldCallTo(F)) + if (CS.isNoBuiltin() || !canConstantFoldCallTo(F)) return false; // Try to re-map the arguments to constants. Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -4659,7 +4659,12 @@ break; case Instruction::Call: { CallSite CS(cast(I)); - Result = SimplifyCall(CS.getCalledValue(), CS.arg_begin(), CS.arg_end(), Q); + // Calls to nobuiltin functions can't be simplified. + if (CS.isNoBuiltin()) + Result = nullptr; + else + Result = SimplifyCall(CS.getCalledValue(), CS.arg_begin(), CS.arg_end(), + Q); break; } #define HANDLE_CAST_INST(num, opc, clas) case Instruction::opc: Index: lib/Analysis/ScalarEvolution.cpp =================================================================== --- lib/Analysis/ScalarEvolution.cpp +++ lib/Analysis/ScalarEvolution.cpp @@ -6791,9 +6791,12 @@ isa(I)) return true; - if (const CallInst *CI = dyn_cast(I)) + if (const CallInst *CI = dyn_cast(I)) { + if (CI->isNoBuiltin()) + return false; if (const Function *F = CI->getCalledFunction()) return canConstantFoldCallTo(F); + } return false; } Index: lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCalls.cpp +++ lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1818,9 +1818,10 @@ /// lifting. Instruction *InstCombiner::visitCallInst(CallInst &CI) { auto Args = CI.arg_operands(); - if (Value *V = - SimplifyCall(CI.getCalledValue(), Args.begin(), Args.end(), SQ)) - return replaceInstUsesWith(CI, V); + if (!CI.isNoBuiltin()) + if (Value *V = + SimplifyCall(CI.getCalledValue(), Args.begin(), Args.end(), SQ)) + return replaceInstUsesWith(CI, V); if (isFreeCall(&CI, &TLI)) return visitFree(CI); Index: lib/Transforms/Scalar/SCCP.cpp =================================================================== --- lib/Transforms/Scalar/SCCP.cpp +++ lib/Transforms/Scalar/SCCP.cpp @@ -1116,8 +1116,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() && !I->getType()->isStructTy() && - canConstantFoldCallTo(F)) { + if (!CS.isNoBuiltin() && F && F->isDeclaration() && + !I->getType()->isStructTy() && canConstantFoldCallTo(F)) { SmallVector Operands; for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end(); Index: lib/Transforms/Utils/Evaluator.cpp =================================================================== --- lib/Transforms/Utils/Evaluator.cpp +++ lib/Transforms/Utils/Evaluator.cpp @@ -359,6 +359,12 @@ continue; } + // Cannot evaluate nobuiltin functions. + if (CS.isNoBuiltin()) { + DEBUG(dbgs() << "Can not evaluate nobuiltin call\n"); + return false; + } + // Cannot handle inline asm. if (isa(CS.getCalledValue())) { DEBUG(dbgs() << "Found inline asm, can not evaluate.\n"); Index: test/Transforms/DCE/calls-errno.ll =================================================================== --- test/Transforms/DCE/calls-errno.ll +++ test/Transforms/DCE/calls-errno.ll @@ -72,6 +72,10 @@ ; CHECK-NEXT: %cos2 = call double @cos(double 0x7FF0000000000000) %cos2 = call double @cos(double 0x7FF0000000000000) +; cos(0) nobuiltin may have side effects +; CHECK-NEXT: %cos3 = call double @cos(double 0.000000e+00) + %cos3 = call double @cos(double 0.000000e+00) nobuiltin + ; pow(0, 1) is 0 %pow1 = call double @pow(double 0x7FF0000000000000, double 1.000000e+00) Index: test/Transforms/InstCombine/constant-fold-libfunc.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/constant-fold-libfunc.ll @@ -0,0 +1,20 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +declare double @acos(double) + +; Check that functions without any function attributes are simplified. + +define double @test_simplify_acos() { +; CHECK-LABEL: @test_simplify_acos + %pi = call double @acos(double -1.000000e+00) +; CHECK-NOT: call double @acos +; CHECK: ret double 0x400921FB54442D18 + ret double %pi +} + +define double @test_acos_nobuiltin() { +; CHECK-LABEL: @test_acos_nobuiltin + %pi = call double @acos(double -1.000000e+00) nobuiltin +; CHECK: call double @acos(double -1.000000e+00) + ret double %pi +}