[cfe-commits] r64689 - in /cfe/trunk: Driver/clang.cpp include/clang/AST/Builtins.def include/clang/AST/Builtins.h include/clang/Basic/LangOptions.h lib/CodeGen/CGBuiltin.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CodeGenFunction.h lib/Sema/SemaDecl.cpp test/CodeGen/libcalls.c
Daniel Dunbar
daniel at zuster.org
Mon Feb 16 14:43:43 PST 2009
Author: ddunbar
Date: Mon Feb 16 16:43:43 2009
New Revision: 64689
URL: http://llvm.org/viewvc/llvm-project?rev=64689&view=rev
Log:
Support IRgen of sqrt -> llvm.sqrt, pow -> llvm.pow.
- Define pow[lf]?, sqrt[lf]? as builtins.
- Add -fmath-errno option which binds to LangOptions.MathErrno
- Add new builtin flag Builtin::Context::isConstWithoutErrno for
functions which can be marked as const if errno isn't respected for
math functions. Sema automatically marks these functions as const
when they are defined, if MathErrno=0.
- IRgen uses const attribute on sqrt and pow library functions to
decide if it can use the llvm intrinsic.
Added:
cfe/trunk/test/CodeGen/libcalls.c
Modified:
cfe/trunk/Driver/clang.cpp
cfe/trunk/include/clang/AST/Builtins.def
cfe/trunk/include/clang/AST/Builtins.h
cfe/trunk/include/clang/Basic/LangOptions.h
cfe/trunk/lib/CodeGen/CGBuiltin.cpp
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
cfe/trunk/lib/Sema/SemaDecl.cpp
Modified: cfe/trunk/Driver/clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/clang.cpp?rev=64689&r1=64688&r2=64689&view=diff
==============================================================================
--- cfe/trunk/Driver/clang.cpp (original)
+++ cfe/trunk/Driver/clang.cpp Mon Feb 16 16:43:43 2009
@@ -213,9 +213,14 @@
//===----------------------------------------------------------------------===//
static llvm::cl::opt<bool>
Freestanding("ffreestanding",
- llvm::cl::desc("Assert that the compiler takes place in a "
+ llvm::cl::desc("Assert that the compilation takes place in a "
"freestanding environment"));
+static llvm::cl::opt<bool>
+MathErrno("fmath-errno",
+ llvm::cl::desc("Require math functions to respect errno."),
+ llvm::cl::init(true));
+
//===----------------------------------------------------------------------===//
// Analyzer Options.
//===----------------------------------------------------------------------===//
@@ -647,6 +652,8 @@
if (Freestanding)
Options.Freestanding = 1;
+ Options.MathErrno = MathErrno;
+
// Override the default runtime if the user requested it.
if (NeXTRuntime)
Options.NeXTRuntime = 1;
@@ -1238,8 +1245,7 @@
//===----------------------------------------------------------------------===//
static llvm::cl::opt<bool>
-OptSize("Os",
- llvm::cl::desc("Optimize for size"));
+OptSize("Os", llvm::cl::desc("Optimize for size"));
// It might be nice to add bounds to the CommandLine library directly.
struct OptLevelParser : public llvm::cl::parser<unsigned> {
Modified: cfe/trunk/include/clang/AST/Builtins.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Builtins.def?rev=64689&r1=64688&r2=64689&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Builtins.def (original)
+++ cfe/trunk/include/clang/AST/Builtins.def Mon Feb 16 16:43:43 2009
@@ -63,6 +63,7 @@
// P:N: -> similar to the p:N: attribute, but the function is like vprintf
// in that it accepts its arguments as a va_list rather than
// through an ellipsis
+// e -> const, but only when -fmath-errno=0
// FIXME: gcc has nonnull
#if defined(BUILTIN) && !defined(LIBBUILTIN)
@@ -176,7 +177,7 @@
BUILTIN(__sync_fetch_and_max,"ii*i", "n")
BUILTIN(__sync_fetch_and_umin,"UiUi*Ui", "n")
BUILTIN(__sync_fetch_and_umax,"UiUi*Ui", "n")
-BUILTIN(__sync_fetch_and_and,"ii*i", "n")
+BUILTIN(__sync_fetch_and_and,"ii*i", "n")
BUILTIN(__sync_fetch_and_or,"ii*i", "n")
BUILTIN(__sync_fetch_and_xor,"ii*i", "n")
BUILTIN(__sync_lock_test_and_set,"ii*i", "n")
@@ -216,5 +217,14 @@
// FIXME: asprintf and vasprintf aren't C99 functions. Should they be
// target-specific builtins, perhaps?
+// Builtin math library functions
+LIBBUILTIN(pow, "ddd", "fe", "math.h")
+LIBBUILTIN(powl, "LdLdLd", "fe", "math.h")
+LIBBUILTIN(powf, "fff", "fe", "math.h")
+
+LIBBUILTIN(sqrt, "dd", "fe", "math.h")
+LIBBUILTIN(sqrtl, "LdLd", "fe", "math.h")
+LIBBUILTIN(sqrtf, "ff", "fe", "math.h")
+
#undef BUILTIN
#undef LIBBUILTIN
Modified: cfe/trunk/include/clang/AST/Builtins.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Builtins.h?rev=64689&r1=64688&r2=64689&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Builtins.h (original)
+++ cfe/trunk/include/clang/AST/Builtins.h Mon Feb 16 16:43:43 2009
@@ -105,6 +105,14 @@
return strpbrk(GetRecord(ID).Type, "Aa") != 0;
}
+ /// isConstWithoutErrno - Return true if this function has no side
+ /// effects and doesn't read memory, except for possibly errno. Such
+ /// functions can be const when the MathErrno lang option is
+ /// disabled.
+ bool isConstWithoutErrno(unsigned ID) const {
+ return strchr(GetRecord(ID).Attributes, 'e') != 0;
+ }
+
/// GetBuiltinType - Return the type for the specified builtin.
enum GetBuiltinTypeError {
GE_None, //< No error
Modified: cfe/trunk/include/clang/Basic/LangOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.h?rev=64689&r1=64688&r2=64689&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/LangOptions.h (original)
+++ cfe/trunk/include/clang/Basic/LangOptions.h Mon Feb 16 16:43:43 2009
@@ -54,6 +54,9 @@
unsigned Blocks : 1; // block extension to C
unsigned EmitAllDecls : 1; // Emit all declarations, even if
// they are unused.
+ unsigned MathErrno : 1; // Math functions must respect errno
+ // (modulo the platform support).
+
private:
unsigned GC : 2; // Objective-C Garbage Collection modes. We declare
// this enum as unsigned because MSVC insists on making enums
@@ -76,6 +79,7 @@
ThreadsafeStatics = 0;
Blocks = 0;
EmitAllDecls = 0;
+ MathErrno = 1;
}
GCMode getGCMode() const { return (GCMode) GC; }
Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=64689&r1=64688&r2=64689&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Mon Feb 16 16:43:43 2009
@@ -36,7 +36,8 @@
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 @@
}
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
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=64689&r1=64688&r2=64689&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Mon Feb 16 16:43:43 2009
@@ -969,7 +969,7 @@
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);
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=64689&r1=64688&r2=64689&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon Feb 16 16:43:43 2009
@@ -631,7 +631,8 @@
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);
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=64689&r1=64688&r2=64689&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Feb 16 16:43:43 2009
@@ -2956,6 +2956,15 @@
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();
Added: cfe/trunk/test/CodeGen/libcalls.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/libcalls.c?rev=64689&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/libcalls.c (added)
+++ cfe/trunk/test/CodeGen/libcalls.c Mon Feb 16 16:43:43 2009
@@ -0,0 +1,22 @@
+// RUN: clang -fmath-errno=1 -emit-llvm -o %t %s &&
+// RUN: grep "declare " %t | count 6 &&
+// RUN: grep "declare " %t | grep "@llvm." | count 1 &&
+// RUN: clang -fmath-errno=0 -emit-llvm -o %t %s &&
+// RUN: grep "declare " %t | count 6 &&
+// RUN: grep "declare " %t | grep -v "@llvm." | count 0
+
+// IRgen only pays attention to const; it should always call llvm for
+// this.
+float sqrtf(float) __attribute__((const));
+
+void test_sqrt(float a0, double a1, long double a2) {
+ float l0 = sqrtf(a0);
+ double l1 = sqrt(a1);
+ long double l2 = sqrtl(a2);
+}
+
+void test_pow(float a0, double a1, long double a2) {
+ float l0 = powf(a0, a0);
+ double l1 = pow(a1, a1);
+ long double l2 = powl(a2, a2);
+}
More information about the cfe-commits
mailing list