diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 31 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 9 |
4 files changed, 42 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index b990c199953..6e59226a6e8 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -36,7 +36,8 @@ static RValue EmitBinaryAtomic(CodeGenFunction& CFG, CFG.EmitScalarExpr(E->getArg(1)))); } -RValue CodeGenFunction::EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { +RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, + unsigned BuiltinID, const CallExpr *E) { // See if we can constant fold this builtin. If so, don't emit it at all. Expr::EvalResult Result; if (E->Evaluate(Result, CGM.getContext())) { @@ -324,6 +325,34 @@ RValue CodeGenFunction::EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { } case Builtin::BI__sync_lock_test_and_set: return EmitBinaryAtomic(*this, Intrinsic::atomic_swap, E); + + + // Library functions with special handling. + + case Builtin::BIsqrt: + case Builtin::BIsqrtf: + case Builtin::BIsqrtl: { + // Rewrite sqrt to intrinsic if allowed. + if (!FD->getAttr<ConstAttr>()) + break; + Value *Arg0 = EmitScalarExpr(E->getArg(0)); + const llvm::Type *ArgType = Arg0->getType(); + Value *F = CGM.getIntrinsic(Intrinsic::sqrt, &ArgType, 1); + return RValue::get(Builder.CreateCall(F, Arg0, "tmp")); + } + + case Builtin::BIpow: + case Builtin::BIpowf: + case Builtin::BIpowl: { + // Rewrite sqrt to intrinsic if allowed. + if (!FD->getAttr<ConstAttr>()) + break; + Value *Base = EmitScalarExpr(E->getArg(0)); + Value *Exponent = EmitScalarExpr(E->getArg(1)); + const llvm::Type *ArgType = Base->getType(); + Value *F = CGM.getIntrinsic(Intrinsic::pow, &ArgType, 1); + return RValue::get(Builder.CreateCall2(F, Base, Exponent, "tmp")); + } } // If this is an alias for a libm function (e.g. __builtin_sin) turn it into diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 4dc8a9e1d4d..b151dd2102c 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -969,7 +969,7 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) { if (const FunctionDecl *FDecl = dyn_cast<const FunctionDecl>(DRExpr->getDecl())) if (unsigned builtinID = FDecl->getBuiltinID(getContext())) - return EmitBuiltinExpr(builtinID, E); + return EmitBuiltinExpr(FDecl, builtinID, E); if (E->getCallee()->getType()->isBlockPointerType()) return EmitBlockCallExpr(E); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 5f42a429e06..7f36c71ab6f 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -631,7 +631,8 @@ public: CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd); - RValue EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E); + RValue EmitBuiltinExpr(const FunctionDecl *FD, + unsigned BuiltinID, const CallExpr *E); RValue EmitBlockCallExpr(const CallExpr *E); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 2692cd99db4..4f8b245ef36 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2956,6 +2956,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { if (!FD->getAttr<FormatAttr>()) FD->addAttr(new FormatAttr("printf", FormatIdx + 1, FormatIdx + 2)); } + + // Mark const if we don't care about errno and that is the only + // thing preventing the function from being const. This allows + // IRgen to use LLVM intrinsics for such functions. + if (!getLangOptions().MathErrno && + Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) { + if (!FD->getAttr<ConstAttr>()) + FD->addAttr(new ConstAttr()); + } } IdentifierInfo *Name = FD->getIdentifier(); |