Index: include/llvm/Intrinsics.h
===================================================================
RCS file: /var/cvs/llvm/llvm/include/llvm/Intrinsics.h,v
retrieving revision 1.30
diff -u -r1.30 Intrinsics.h
--- include/llvm/Intrinsics.h	21 Apr 2005 20:11:51 -0000	1.30
+++ include/llvm/Intrinsics.h	29 Apr 2005 10:28:18 -0000
@@ -63,6 +63,7 @@
 
     // libm related functions.
     isunordered,    // Return true if either argument is a NaN
+    sqrt,
 
     // Input/Output intrinsics.
     readport,
Index: include/llvm/Target/TargetOptions.h
===================================================================
RCS file: /var/cvs/llvm/llvm/include/llvm/Target/TargetOptions.h,v
retrieving revision 1.4
diff -u -r1.4 TargetOptions.h
--- include/llvm/Target/TargetOptions.h	21 Apr 2005 20:53:44 -0000	1.4
+++ include/llvm/Target/TargetOptions.h	29 Apr 2005 11:23:21 -0000
@@ -41,6 +41,12 @@
   /// pattern ISel if available.
   extern int PatternISelTriState;
 
+  /// UnsafeFPMath - This flag is enabled when the
+  /// -enable-unsafe-fp-math flag is specified on the command line.  When
+  /// this flag is off (the default), the code generator is not allowed to
+  /// produce results that are "less precise" than IEEE allows.  This includes
+  /// use of X86 instructions like FSIN and FCOS instead of libcalls.
+  extern bool UnsafeFPMath;
 } // End llvm namespace
 
 #endif
Index: lib/Analysis/BasicAliasAnalysis.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/Analysis/BasicAliasAnalysis.cpp,v
retrieving revision 1.67
diff -u -r1.67 BasicAliasAnalysis.cpp
--- lib/Analysis/BasicAliasAnalysis.cpp	28 Apr 2005 21:52:31 -0000	1.67
+++ lib/Analysis/BasicAliasAnalysis.cpp	29 Apr 2005 10:28:18 -0000
@@ -702,7 +702,7 @@
 static const char *DoesntAccessMemoryTable[] = {
   // LLVM intrinsics:
   "llvm.frameaddress", "llvm.returnaddress", "llvm.readport",
-  "llvm.isunordered",
+  "llvm.isunordered", "llvm.sqrt",
 
   "abs", "labs", "llabs", "imaxabs", "fabs", "fabsf", "fabsl",
   "trunc", "truncf", "truncl", "ldexp",
Index: lib/CodeGen/IntrinsicLowering.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/CodeGen/IntrinsicLowering.cpp,v
retrieving revision 1.26
diff -u -r1.26 IntrinsicLowering.cpp
--- lib/CodeGen/IntrinsicLowering.cpp	21 Apr 2005 22:33:33 -0000	1.26
+++ lib/CodeGen/IntrinsicLowering.cpp	29 Apr 2005 10:32:02 -0000
@@ -110,8 +110,13 @@
       case Intrinsic::isunordered:
         EnsureFunctionExists(M, "isunordered", I->arg_begin(), I->arg_end(), Type::BoolTy);
         break;
+      case Intrinsic::sqrt:
+        if(I->abegin()->getType() == Type::FloatTy)
+          EnsureFunctionExists(M, "sqrtf", I->arg_begin(), I->arg_end(), Type::FloatTy);
+        else
+          EnsureFunctionExists(M, "sqrt", I->arg_begin(), I->arg_end(), Type::DoubleTy);
+        break;
       }
-
 }
 
 void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
@@ -219,6 +224,17 @@
                              "isunordered", CI));
     break;
   }
+  case Intrinsic::sqrt: {
+    static Function *sqrtFCache = 0;
+    static Function *sqrtfFCache = 0;
+    if(CI->getType() == Type::FloatTy)
+      ReplaceCallWith("sqrtf", CI, CI->op_begin()+1, CI->op_end(),
+                      Type::FloatTy, sqrtfFCache);
+    else
+      ReplaceCallWith("sqrt", CI, CI->op_begin()+1, CI->op_end(),
+                      Type::DoubleTy, sqrtFCache);
+    break;
+  }
   }
 
   assert(CI->use_empty() &&
Index: lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp,v
retrieving revision 1.92
diff -u -r1.92 LegalizeDAG.cpp
--- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp	28 Apr 2005 21:44:33 -0000	1.92
+++ lib/CodeGen/SelectionDAG/LegalizeDAG.cpp	29 Apr 2005 11:05:19 -0000
@@ -1003,12 +1003,15 @@
     case TargetLowering::Custom:
       assert(0 && "Cannot promote/custom handle this yet!");
     case TargetLowering::Expand:
-      if (Node->getOpcode() == ISD::FNEG) {
+      switch(Node->getOpcode()) {
+      case ISD::FNEG: {
         // Expand Y = FNEG(X) ->  Y = SUB -0.0, X
         Tmp2 = DAG.getConstantFP(-0.0, Node->getValueType(0));
         Result = LegalizeOp(DAG.getNode(ISD::SUB, Node->getValueType(0),
                                         Tmp2, Tmp1));
-      } else if (Node->getOpcode() == ISD::FABS) {
+        break;
+      }
+      case ISD::FABS: {
         // Expand Y = FABS(X) -> Y = (X >u 0.0) ? X : fneg(X).
         MVT::ValueType VT = Node->getValueType(0);
         Tmp2 = DAG.getConstantFP(0.0, VT);
@@ -1016,7 +1019,29 @@
         Tmp3 = DAG.getNode(ISD::FNEG, VT, Tmp1);
         Result = DAG.getNode(ISD::SELECT, VT, Tmp2, Tmp1, Tmp3);
         Result = LegalizeOp(Result);
-      } else {
+        break;
+      }
+      case ISD::FSQRT:
+      case ISD::FSIN:
+      case ISD::FCOS: {
+        MVT::ValueType VT = Node->getValueType(0);
+        Type *T = MVT::f32 ? Type::FloatTy : Type::DoubleTy;
+        const char *FnName = 0;
+        switch(Node->getOpcode()) {
+        case ISD::FSQRT: FnName = VT == MVT::f32 ? "sqrtf" : "sqrt"; break;
+        case ISD::FSIN:  FnName = VT == MVT::f32 ? "sinf"  : "sin"; break;
+        case ISD::FCOS:  FnName = VT == MVT::f32 ? "cosf"  : "cos"; break;
+        default: assert(0 && "Unreachable!");
+        }
+        std::vector<std::pair<SDOperand, const Type*> > Args;
+        Args.push_back(std::make_pair(Tmp1, T));
+        std::pair<SDOperand,SDOperand> CallResult =
+          TLI.LowerCallTo(DAG.getEntryNode(), T, false,
+                          DAG.getExternalSymbol(FnName, VT), Args, DAG);
+        Result = LegalizeOp(CallResult.second);
+        break;
+      }
+      default:
         assert(0 && "Unreachable!");
       }
       break;
Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp,v
retrieving revision 1.44
diff -u -r1.44 SelectionDAGISel.cpp
--- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp	27 Apr 2005 20:10:01 -0000	1.44
+++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp	29 Apr 2005 11:37:33 -0000
@@ -656,6 +656,24 @@
             return;
           }
         }
+        else if (F->getName() == "sin" || F->getName() == "sinf") {
+          if (I.getNumOperands() == 2 &&   // Basic sanity checks.
+              I.getOperand(1)->getType()->isFloatingPoint() &&
+              I.getType() == I.getOperand(1)->getType()) {
+            SDOperand Tmp = getValue(I.getOperand(1));
+            setValue(&I, DAG.getNode(ISD::FSIN, Tmp.getValueType(), Tmp));
+            return;
+          }
+        }
+        else if (F->getName() == "cos" || F->getName() == "cosf") {
+          if (I.getNumOperands() == 2 &&   // Basic sanity checks.
+              I.getOperand(1)->getType()->isFloatingPoint() &&
+              I.getType() == I.getOperand(1)->getType()) {
+            SDOperand Tmp = getValue(I.getOperand(1));
+            setValue(&I, DAG.getNode(ISD::FCOS, Tmp.getValueType(), Tmp));
+            return;
+          }
+        }
         break;
       case Intrinsic::vastart:  visitVAStart(I); return;
       case Intrinsic::vaend:    visitVAEnd(I); return;
@@ -677,6 +695,13 @@
         setValue(&I, DAG.getSetCC(ISD::SETUO, MVT::i1,getValue(I.getOperand(1)),
                                   getValue(I.getOperand(2))));
         return;
+
+      case Intrinsic::sqrt:
+        setValue(&I, DAG.getNode(ISD::FSQRT,
+                                 getValue(I.getOperand(1)).getValueType(),
+                                 getValue(I.getOperand(1))));
+        return;
+
       case Intrinsic::pcmarker: {
         SDOperand Num = getValue(I.getOperand(1));
         DAG.setRoot(DAG.getNode(ISD::PCMARKER, MVT::Other, getRoot(), Num));
Index: lib/Target/TargetMachine.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/Target/TargetMachine.cpp,v
retrieving revision 1.37
diff -u -r1.37 TargetMachine.cpp
--- lib/Target/TargetMachine.cpp	21 Apr 2005 22:55:34 -0000	1.37
+++ lib/Target/TargetMachine.cpp	29 Apr 2005 11:32:28 -0000
@@ -26,6 +26,7 @@
   bool NoFramePointerElim;
   bool NoExcessFPPrecision;
   int  PatternISelTriState;
+  bool UnsafeFPMath;
 };
 namespace {
   cl::opt<bool, true> PrintCode("print-machineinstrs",
@@ -46,6 +47,11 @@
                     cl::desc("sets the pattern ISel off(0), on(1), default(2)"),
                     cl::location(PatternISelTriState),
                     cl::init(2));
+  cl::opt<bool, true>
+  EnableUnsafeFPMath("enable-unsafe-fp-math",
+               cl::desc("Enable optimizations that may decrease FP precision"),
+               cl::location(UnsafeFPMath),
+               cl::init(false));
 };
 
 //---------------------------------------------------------------------------
Index: lib/Target/X86/X86ISelPattern.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/Target/X86/X86ISelPattern.cpp,v
retrieving revision 1.109
diff -u -r1.109 X86ISelPattern.cpp
--- lib/Target/X86/X86ISelPattern.cpp	28 Apr 2005 22:07:18 -0000	1.109
+++ lib/Target/X86/X86ISelPattern.cpp	29 Apr 2005 11:28:30 -0000
@@ -24,6 +24,7 @@
 #include "llvm/CodeGen/SSARegMap.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetLowering.h"
+#include "llvm/Target/TargetOptions.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/ADT/Statistic.h"
 #include <set>
@@ -64,6 +65,11 @@
       setOperationAction(ISD::SEXTLOAD         , MVT::i1   , Expand);
       setOperationAction(ISD::SREM             , MVT::f64  , Expand);
 
+      if(!UnsafeFPMath) {
+        setOperationAction(ISD::FSIN             , MVT::f64  , Expand);
+        setOperationAction(ISD::FCOS             , MVT::f64  , Expand);
+      }
+
       // These should be promoted to a larger select which is supported.
 /**/  setOperationAction(ISD::SELECT           , MVT::i1   , Promote);
       setOperationAction(ISD::SELECT           , MVT::i8   , Promote);
Index: lib/Target/X86/X86ISelSimple.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/Target/X86/X86ISelSimple.cpp,v
retrieving revision 1.315
diff -u -r1.315 X86ISelSimple.cpp
--- lib/Target/X86/X86ISelSimple.cpp	28 Apr 2005 21:48:42 -0000	1.315
+++ lib/Target/X86/X86ISelSimple.cpp	29 Apr 2005 11:30:28 -0000
@@ -26,6 +26,7 @@
 #include "llvm/CodeGen/SSARegMap.h"
 #include "llvm/Target/MRegisterInfo.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
 #include "llvm/Support/GetElementPtrTypeIterator.h"
 #include "llvm/Support/InstVisitor.h"
 #include "llvm/ADT/Statistic.h"
@@ -1746,6 +1747,37 @@
       }
     }
 
+    if (F->getName() == "fabs" || F->getName() == "fabsf") {
+      if (CI.getNumOperands() == 2 &&   // Basic sanity checks.
+          CI.getOperand(1)->getType()->isFloatingPoint() &&
+          CI.getType() == CI.getOperand(1)->getType()) {
+        unsigned op1Reg = getReg(CI.getOperand(1));
+        unsigned DestReg = getReg(CI);
+        BuildMI(BB, X86::FABS, 1, DestReg).addReg(op1Reg);
+        return;
+      }
+    }
+    else if (F->getName() == "sin" && UnsafeFPMath || F->getName() == "sinf") {
+      if (CI.getNumOperands() == 2 &&   // Basic sanity checks.
+          CI.getOperand(1)->getType()->isFloatingPoint() &&
+          CI.getType() == CI.getOperand(1)->getType()) {
+        unsigned op1Reg = getReg(CI.getOperand(1));
+        unsigned DestReg = getReg(CI);
+        BuildMI(BB, X86::FSIN, 1, DestReg).addReg(op1Reg);
+        return;
+      }
+    }
+    else if (F->getName() == "cos" && UnsafeFPMath || F->getName() == "cosf") {
+      if (CI.getNumOperands() == 2 &&   // Basic sanity checks.
+          CI.getOperand(1)->getType()->isFloatingPoint() &&
+          CI.getType() == CI.getOperand(1)->getType()) {
+        unsigned op1Reg = getReg(CI.getOperand(1));
+        unsigned DestReg = getReg(CI);
+        BuildMI(BB, X86::FCOS, 1, DestReg).addReg(op1Reg);
+        return;
+      }
+    }
+
     // Emit a CALL instruction with PC-relative displacement.
     TheCall = BuildMI(X86::CALLpcrel32, 1).addGlobalAddress(F, true);
   } else {  // Emit an indirect call...
@@ -1780,6 +1812,7 @@
           case Intrinsic::memcpy:
           case Intrinsic::memset:
           case Intrinsic::isunordered:
+          case Intrinsic::sqrt:
           case Intrinsic::readport:
           case Intrinsic::writeport:
             // We directly implement these intrinsics
@@ -1860,6 +1893,12 @@
     BuildMI(BB, X86::SETPr, 0, TmpReg2);
     return;
 
+  case Intrinsic::sqrt:
+    TmpReg1 = getReg(CI.getOperand(1));
+    TmpReg2 = getReg(CI);
+    BuildMI(BB, X86::FSQRT, 1, TmpReg2).addReg(TmpReg1);
+    return;
+
   case Intrinsic::memcpy: {
     assert(CI.getNumOperands() == 5 && "Illegal llvm.memcpy call!");
     unsigned Align = 1;
Index: lib/VMCore/Function.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/VMCore/Function.cpp,v
retrieving revision 1.92
diff -u -r1.92 Function.cpp
--- lib/VMCore/Function.cpp	21 Apr 2005 23:46:51 -0000	1.92
+++ lib/VMCore/Function.cpp	29 Apr 2005 10:28:18 -0000
@@ -245,6 +245,7 @@
     if (getName() == "llvm.setjmp")     return Intrinsic::setjmp;
     if (getName() == "llvm.sigsetjmp")  return Intrinsic::sigsetjmp;
     if (getName() == "llvm.siglongjmp") return Intrinsic::siglongjmp;
+    if (getName() == "llvm.sqrt")       return Intrinsic::sqrt;
     break;
   case 'v':
     if (getName() == "llvm.va_copy")  return Intrinsic::vacopy;
Index: lib/VMCore/Verifier.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/VMCore/Verifier.cpp,v
retrieving revision 1.130
diff -u -r1.130 Verifier.cpp
--- lib/VMCore/Verifier.cpp	21 Apr 2005 23:46:51 -0000	1.130
+++ lib/VMCore/Verifier.cpp	29 Apr 2005 10:28:18 -0000
@@ -723,6 +723,16 @@
     NumArgs = 2;
     break;
 
+  case Intrinsic::sqrt:
+    Assert1(FT->getNumParams() == 1,
+            "Illegal # arguments for intrinsic function!", IF);
+    Assert1(FT->getParamType(0)->isFloatingPoint(),
+            "Argument is not a floating point type!", IF);
+    Assert1(FT->getReturnType() == FT->getParamType(0),
+            "Return type is not the same as argument type!", IF);
+    NumArgs = 1;
+    break;
+
   case Intrinsic::setjmp:          NumArgs = 1; break;
   case Intrinsic::longjmp:         NumArgs = 2; break;
   case Intrinsic::sigsetjmp:       NumArgs = 2; break;
