[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