[llvm-commits] [llvm] r154822 - in /llvm/trunk: docs/LangRef.html docs/ReleaseNotes.html include/llvm/Operator.h include/llvm/Support/IRBuilder.h include/llvm/Support/MDBuilder.h lib/VMCore/Instructions.cpp lib/VMCore/Verifier.cpp test/Verifier/fpmath.ll unittests/Support/MDBuilderTest.cpp unittests/VMCore/InstructionsTest.cpp

Duncan Sands baldrick at free.fr
Mon Apr 16 09:29:00 PDT 2012


Author: baldrick
Date: Mon Apr 16 11:28:59 2012
New Revision: 154822

URL: http://llvm.org/viewvc/llvm-project?rev=154822&view=rev
Log:
Make it possible to indicate relaxed floating point requirements at the IR level
through the use of 'fpmath' metadata.  Currently this only provides a 'fpaccuracy'
value, which may be a number in ULPs or the keyword 'fast', however the intent is
that this will be extended with additional information about NaN's, infinities
etc later.  No optimizations have been hooked up to this so far.

Modified:
    llvm/trunk/docs/LangRef.html
    llvm/trunk/docs/ReleaseNotes.html
    llvm/trunk/include/llvm/Operator.h
    llvm/trunk/include/llvm/Support/IRBuilder.h
    llvm/trunk/include/llvm/Support/MDBuilder.h
    llvm/trunk/lib/VMCore/Instructions.cpp
    llvm/trunk/lib/VMCore/Verifier.cpp
    llvm/trunk/test/Verifier/fpmath.ll
    llvm/trunk/unittests/Support/MDBuilderTest.cpp
    llvm/trunk/unittests/VMCore/InstructionsTest.cpp

Modified: llvm/trunk/docs/LangRef.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=154822&r1=154821&r2=154822&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.html (original)
+++ llvm/trunk/docs/LangRef.html Mon Apr 16 11:28:59 2012
@@ -3006,10 +3006,12 @@
 <div>
 
 <p><tt>fpmath</tt> metadata may be attached to any instruction of floating point
-   type.  It can be used to express the maximum acceptable relative error in the
-   result of that instruction, in ULPs, thus potentially allowing the compiler
-   to use a more efficient but less accurate method of computing it.
-   ULP is defined as follows:</p>
+  type.  It can be used to express the maximum acceptable error in the result of
+  that instruction, in ULPs, thus potentially allowing the compiler to use a
+  more efficient but less accurate method of computing it.  The number of ULPs
+  may also be the string <tt>"fast"</tt>, which tells the compiler that speed
+  matters more than accuracy, so any fairly accurate method of computation is
+  fine as long as it is quick.  ULP is defined as follows:</p>
 
 <blockquote>
 
@@ -3021,13 +3023,14 @@
 
 </blockquote>
 
-<p>The metadata node shall consist of a single non-negative floating
-   point number representing the maximum relative error.  For example,
-   2.5 ULP:</p>
+<p>The metadata node shall consist of a single positive floating point number
+   representing the maximum relative error, or the string <tt>"fast"</tt>.
+   For example:</p>
 
 <div class="doc_code">
 <pre>
-!0 = metadata !{ float 2.5 }
+!0 = metadata !{ float 2.5 } ; maximum acceptable inaccuracy is 2.5 ULPs
+!1 = metadata !{ !metadata !"fast" } ; potentially unbounded inaccuracy
 </pre>
 </div>
 

Modified: llvm/trunk/docs/ReleaseNotes.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/ReleaseNotes.html?rev=154822&r1=154821&r2=154822&view=diff
==============================================================================
--- llvm/trunk/docs/ReleaseNotes.html (original)
+++ llvm/trunk/docs/ReleaseNotes.html Mon Apr 16 11:28:59 2012
@@ -489,6 +489,9 @@
   <li>The <tt>unwind</tt> instruction is now gone. With the introduction of the
       new exception handling system in LLVM 3.0, the <tt>unwind</tt> instruction
       became obsolete.</li>
+  <li>Floating point instructions can be annotated with <tt>fpmath</tt> metadata
+      to indicate relaxed precision requirements, such as those corresponding to
+      "fast math".</li>
   <li>....</li>
 </ul>
 

Modified: llvm/trunk/include/llvm/Operator.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Operator.h?rev=154822&r1=154821&r2=154822&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Operator.h (original)
+++ llvm/trunk/include/llvm/Operator.h Mon Apr 16 11:28:59 2012
@@ -15,8 +15,9 @@
 #ifndef LLVM_OPERATOR_H
 #define LLVM_OPERATOR_H
 
-#include "llvm/Instruction.h"
 #include "llvm/Constants.h"
+#include "llvm/Instruction.h"
+#include "llvm/Type.h"
 
 namespace llvm {
 
@@ -162,7 +163,32 @@
            (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
   }
 };
-  
+
+/// FPMathOperator - Utility class for floating point operations which can have
+/// information about relaxed accuracy requirements attached to them.
+class FPMathOperator : public Operator {
+private:
+  ~FPMathOperator(); // do not implement
+
+public:
+
+  /// \brief Get the maximum error permitted by this operation in ULPs.  An
+  /// accuracy of 0.0 means that the operation should be performed with the
+  /// default precision.  A huge value is returned if the accuracy is 'fast'.
+  float getFPAccuracy() const;
+
+  /// \brief Return true if the accuracy is 'fast'.  This indicates that speed
+  /// is more important than accuracy.
+  bool isFastFPAccuracy() const;
+
+  static inline bool classof(const FPMathOperator *) { return true; }
+  static inline bool classof(const Instruction *I) {
+    return I->getType()->isFPOrFPVectorTy();
+  }
+  static inline bool classof(const Value *V) {
+    return isa<Instruction>(V) && classof(cast<Instruction>(V));
+  }
+};
 
   
 /// ConcreteOperator - A helper template for defining operators for individual

Modified: llvm/trunk/include/llvm/Support/IRBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/IRBuilder.h?rev=154822&r1=154821&r2=154822&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/IRBuilder.h (original)
+++ llvm/trunk/include/llvm/Support/IRBuilder.h Mon Apr 16 11:28:59 2012
@@ -17,6 +17,7 @@
 
 #include "llvm/Instructions.h"
 #include "llvm/BasicBlock.h"
+#include "llvm/LLVMContext.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -331,49 +332,63 @@
          typename Inserter = IRBuilderDefaultInserter<preserveNames> >
 class IRBuilder : public IRBuilderBase, public Inserter {
   T Folder;
+  MDNode *DefaultFPMathTag;
 public:
-  IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter())
-    : IRBuilderBase(C), Inserter(I), Folder(F) {
+  IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter(),
+            MDNode *FPMathTag = 0)
+    : IRBuilderBase(C), Inserter(I), Folder(F), DefaultFPMathTag(FPMathTag) {
   }
 
-  explicit IRBuilder(LLVMContext &C) : IRBuilderBase(C), Folder() {
+  explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = 0) : IRBuilderBase(C),
+    Folder(), DefaultFPMathTag(FPMathTag) {
   }
 
-  explicit IRBuilder(BasicBlock *TheBB, const T &F)
-    : IRBuilderBase(TheBB->getContext()), Folder(F) {
+  explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = 0)
+    : IRBuilderBase(TheBB->getContext()), Folder(F),
+      DefaultFPMathTag(FPMathTag) {
     SetInsertPoint(TheBB);
   }
 
-  explicit IRBuilder(BasicBlock *TheBB)
-    : IRBuilderBase(TheBB->getContext()), Folder() {
+  explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = 0)
+    : IRBuilderBase(TheBB->getContext()), Folder(),
+      DefaultFPMathTag(FPMathTag) {
     SetInsertPoint(TheBB);
   }
 
-  explicit IRBuilder(Instruction *IP)
-    : IRBuilderBase(IP->getContext()), Folder() {
+  explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = 0)
+    : IRBuilderBase(IP->getContext()), Folder(), DefaultFPMathTag(FPMathTag) {
     SetInsertPoint(IP);
     SetCurrentDebugLocation(IP->getDebugLoc());
   }
 
-  explicit IRBuilder(Use &U)
-    : IRBuilderBase(U->getContext()), Folder() {
+  explicit IRBuilder(Use &U, MDNode *FPMathTag = 0)
+    : IRBuilderBase(U->getContext()), Folder(), DefaultFPMathTag(FPMathTag) {
     SetInsertPoint(U);
     SetCurrentDebugLocation(cast<Instruction>(U.getUser())->getDebugLoc());
   }
 
-  IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F)
-    : IRBuilderBase(TheBB->getContext()), Folder(F) {
+  IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F,
+            MDNode *FPMathTag = 0)
+    : IRBuilderBase(TheBB->getContext()), Folder(F),
+      DefaultFPMathTag(FPMathTag) {
     SetInsertPoint(TheBB, IP);
   }
 
-  IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP)
-    : IRBuilderBase(TheBB->getContext()), Folder() {
+  IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, MDNode *FPMathTag = 0)
+    : IRBuilderBase(TheBB->getContext()), Folder(),
+      DefaultFPMathTag(FPMathTag) {
     SetInsertPoint(TheBB, IP);
   }
 
   /// getFolder - Get the constant folder being used.
   const T &getFolder() { return Folder; }
 
+  /// getDefaultFPMathTag - Get the floating point math metadata being used.
+  MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; }
+
+  /// SetDefaultFPMathTag - Set the floating point math metadata to be used.
+  void SetDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; }
+
   /// isNamePreserving - Return true if this builder is configured to actually
   /// add the requested names to IR created through it.
   bool isNamePreserving() const { return preserveNames; }
@@ -496,6 +511,14 @@
     if (HasNSW) BO->setHasNoSignedWrap();
     return BO;
   }
+
+  Instruction *AddFPMathTag(Instruction *I, MDNode *FPMathTag) const {
+    if (!FPMathTag)
+      FPMathTag = DefaultFPMathTag;
+    if (FPMathTag)
+      I->setMetadata(LLVMContext::MD_fpmath, FPMathTag);
+    return I;
+  }
 public:
   Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "",
                    bool HasNUW = false, bool HasNSW = false) {
@@ -511,11 +534,13 @@
   Value *CreateNUWAdd(Value *LHS, Value *RHS, const Twine &Name = "") {
     return CreateAdd(LHS, RHS, Name, true, false);
   }
-  Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "") {
+  Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "",
+                    MDNode *FPMathTag = 0) {
     if (Constant *LC = dyn_cast<Constant>(LHS))
       if (Constant *RC = dyn_cast<Constant>(RHS))
         return Insert(Folder.CreateFAdd(LC, RC), Name);
-    return Insert(BinaryOperator::CreateFAdd(LHS, RHS), Name);
+    return Insert(AddFPMathTag(BinaryOperator::CreateFAdd(LHS, RHS),
+                               FPMathTag), Name);
   }
   Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "",
                    bool HasNUW = false, bool HasNSW = false) {
@@ -531,11 +556,13 @@
   Value *CreateNUWSub(Value *LHS, Value *RHS, const Twine &Name = "") {
     return CreateSub(LHS, RHS, Name, true, false);
   }
-  Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "") {
+  Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "",
+                    MDNode *FPMathTag = 0) {
     if (Constant *LC = dyn_cast<Constant>(LHS))
       if (Constant *RC = dyn_cast<Constant>(RHS))
         return Insert(Folder.CreateFSub(LC, RC), Name);
-    return Insert(BinaryOperator::CreateFSub(LHS, RHS), Name);
+    return Insert(AddFPMathTag(BinaryOperator::CreateFSub(LHS, RHS),
+                               FPMathTag), Name);
   }
   Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "",
                    bool HasNUW = false, bool HasNSW = false) {
@@ -551,11 +578,13 @@
   Value *CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name = "") {
     return CreateMul(LHS, RHS, Name, true, false);
   }
-  Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "") {
+  Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "",
+                    MDNode *FPMathTag = 0) {
     if (Constant *LC = dyn_cast<Constant>(LHS))
       if (Constant *RC = dyn_cast<Constant>(RHS))
         return Insert(Folder.CreateFMul(LC, RC), Name);
-    return Insert(BinaryOperator::CreateFMul(LHS, RHS), Name);
+    return Insert(AddFPMathTag(BinaryOperator::CreateFMul(LHS, RHS),
+                               FPMathTag), Name);
   }
   Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "",
                     bool isExact = false) {
@@ -581,11 +610,13 @@
   Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
     return CreateSDiv(LHS, RHS, Name, true);
   }
-  Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
+  Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "",
+                    MDNode *FPMathTag = 0) {
     if (Constant *LC = dyn_cast<Constant>(LHS))
       if (Constant *RC = dyn_cast<Constant>(RHS))
         return Insert(Folder.CreateFDiv(LC, RC), Name);
-    return Insert(BinaryOperator::CreateFDiv(LHS, RHS), Name);
+    return Insert(AddFPMathTag(BinaryOperator::CreateFDiv(LHS, RHS),
+                               FPMathTag), Name);
   }
   Value *CreateURem(Value *LHS, Value *RHS, const Twine &Name = "") {
     if (Constant *LC = dyn_cast<Constant>(LHS))
@@ -599,11 +630,13 @@
         return Insert(Folder.CreateSRem(LC, RC), Name);
     return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name);
   }
-  Value *CreateFRem(Value *LHS, Value *RHS, const Twine &Name = "") {
+  Value *CreateFRem(Value *LHS, Value *RHS, const Twine &Name = "",
+                    MDNode *FPMathTag = 0) {
     if (Constant *LC = dyn_cast<Constant>(LHS))
       if (Constant *RC = dyn_cast<Constant>(RHS))
         return Insert(Folder.CreateFRem(LC, RC), Name);
-    return Insert(BinaryOperator::CreateFRem(LHS, RHS), Name);
+    return Insert(AddFPMathTag(BinaryOperator::CreateFRem(LHS, RHS),
+                               FPMathTag), Name);
   }
 
   Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "",
@@ -729,10 +762,10 @@
   Value *CreateNUWNeg(Value *V, const Twine &Name = "") {
     return CreateNeg(V, Name, true, false);
   }
-  Value *CreateFNeg(Value *V, const Twine &Name = "") {
+  Value *CreateFNeg(Value *V, const Twine &Name = "", MDNode *FPMathTag = 0) {
     if (Constant *VC = dyn_cast<Constant>(V))
       return Insert(Folder.CreateFNeg(VC), Name);
-    return Insert(BinaryOperator::CreateFNeg(V), Name);
+    return Insert(AddFPMathTag(BinaryOperator::CreateFNeg(V), FPMathTag), Name);
   }
   Value *CreateNot(Value *V, const Twine &Name = "") {
     if (Constant *VC = dyn_cast<Constant>(V))

Modified: llvm/trunk/include/llvm/Support/MDBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/MDBuilder.h?rev=154822&r1=154821&r2=154822&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/MDBuilder.h (original)
+++ llvm/trunk/include/llvm/Support/MDBuilder.h Mon Apr 16 11:28:59 2012
@@ -26,20 +26,46 @@
   class MDBuilder {
     LLVMContext &Context;
 
+    MDString *getFastString() {
+      return createString("fast");
+    }
   public:
     MDBuilder(LLVMContext &context) : Context(context) {}
 
-    /// CreateString - Return the given string as metadata.
-    MDString *CreateString(StringRef Str) {
+    /// \brief Return the given string as metadata.
+    MDString *createString(StringRef Str) {
       return MDString::get(Context, Str);
     }
 
     //===------------------------------------------------------------------===//
+    // FPMath metadata.
+    //===------------------------------------------------------------------===//
+
+    /// \brief Return metadata with appropriate settings for 'fast math'.
+    MDNode *createFastFPMath() {
+      return MDNode::get(Context, getFastString());
+    }
+
+    /// \brief Return metadata with the given settings.  Special values for the
+    /// Accuracy parameter are 0.0, which means the default (maximal precision)
+    /// setting; and negative values which all mean 'fast'.
+    MDNode *createFPMath(float Accuracy) {
+      if (Accuracy == 0.0)
+        return 0;
+      if (Accuracy < 0.0)
+        return MDNode::get(Context, getFastString());
+      assert(Accuracy > 0.0 && "Invalid fpmath accuracy!");
+      Value *Op = ConstantFP::get(Type::getFloatTy(Context), Accuracy);
+      return MDNode::get(Context, Op);
+    }
+
+
+    //===------------------------------------------------------------------===//
     // Range metadata.
     //===------------------------------------------------------------------===//
 
-    /// CreateRange - Return metadata describing the range [Lo, Hi).
-    MDNode *CreateRange(const APInt &Lo, const APInt &Hi) {
+    /// \brief Return metadata describing the range [Lo, Hi).
+    MDNode *createRange(const APInt &Lo, const APInt &Hi) {
       assert(Lo.getBitWidth() == Hi.getBitWidth() && "Mismatched bitwidths!");
       // If the range is everything then it is useless.
       if (Hi == Lo)
@@ -56,10 +82,10 @@
     // TBAA metadata.
     //===------------------------------------------------------------------===//
 
-    /// CreateAnonymousTBAARoot - Return metadata appropriate for a TBAA root
-    /// node.  Each returned node is distinct from all other metadata and will
-    /// never be identified (uniqued) with anything else.
-    MDNode *CreateAnonymousTBAARoot() {
+    /// \brief Return metadata appropriate for a TBAA root node.  Each returned
+    /// node is distinct from all other metadata and will never be identified
+    /// (uniqued) with anything else.
+    MDNode *createAnonymousTBAARoot() {
       // To ensure uniqueness the root node is self-referential.
       MDNode *Dummy = MDNode::getTemporary(Context, ArrayRef<Value*>());
       MDNode *Root = MDNode::get(Context, Dummy);
@@ -74,23 +100,23 @@
       return Root;
     }
 
-    /// CreateTBAARoot - Return metadata appropriate for a TBAA root node with
-    /// the given name.  This may be identified (uniqued) with other roots with
-    /// the same name.
-    MDNode *CreateTBAARoot(StringRef Name) {
-      return MDNode::get(Context, CreateString(Name));
+    /// \brief Return metadata appropriate for a TBAA root node with the given
+    /// name.  This may be identified (uniqued) with other roots with the same
+    /// name.
+    MDNode *createTBAARoot(StringRef Name) {
+      return MDNode::get(Context, createString(Name));
     }
 
-    /// CreateTBAANode - Return metadata for a non-root TBAA node with the given
-    /// name, parent in the TBAA tree, and value for 'pointsToConstantMemory'.
-    MDNode *CreateTBAANode(StringRef Name, MDNode *Parent,
+    /// \brief Return metadata for a non-root TBAA node with the given name,
+    /// parent in the TBAA tree, and value for 'pointsToConstantMemory'.
+    MDNode *createTBAANode(StringRef Name, MDNode *Parent,
                            bool isConstant = false) {
       if (isConstant) {
         Constant *Flags = ConstantInt::get(Type::getInt64Ty(Context), 1);
-        Value *Ops[3] = { CreateString(Name), Parent, Flags };
+        Value *Ops[3] = { createString(Name), Parent, Flags };
         return MDNode::get(Context, Ops);
       } else {
-        Value *Ops[2] = { CreateString(Name), Parent };
+        Value *Ops[2] = { createString(Name), Parent };
         return MDNode::get(Context, Ops);
       }
     }

Modified: llvm/trunk/lib/VMCore/Instructions.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Instructions.cpp?rev=154822&r1=154821&r2=154822&view=diff
==============================================================================
--- llvm/trunk/lib/VMCore/Instructions.cpp (original)
+++ llvm/trunk/lib/VMCore/Instructions.cpp Mon Apr 16 11:28:59 2012
@@ -2003,6 +2003,44 @@
 }
 
 //===----------------------------------------------------------------------===//
+//                             FPMathOperator Class
+//===----------------------------------------------------------------------===//
+
+/// getFPAccuracy - Get the maximum error permitted by this operation in ULPs.
+/// An accuracy of 0.0 means that the operation should be performed with the
+/// default precision.  A huge value is returned if the accuracy is 'fast'.
+float FPMathOperator::getFPAccuracy() const {
+  const MDNode *MD =
+    cast<Instruction>(this)->getMetadata(LLVMContext::MD_fpmath);
+  if (!MD)
+    return 0.0;
+  Value *Op = MD->getOperand(0);
+  if (const ConstantFP *Accuracy = dyn_cast<ConstantFP>(Op))
+    return Accuracy->getValueAPF().convertToFloat();
+  // If it's not a floating point number then it must be 'fast'.
+  assert(isa<MDString>(Op) && cast<MDString>(Op)->getString() == "fast" &&
+         "Expected the 'fast' keyword!");
+  return HUGE_VALF;
+}
+
+/// isFastFPAccuracy - Return true if the accuracy is 'fast'.  This says that
+/// speed is more important than accuracy.
+bool FPMathOperator::isFastFPAccuracy() const {
+  const MDNode *MD =
+    cast<Instruction>(this)->getMetadata(LLVMContext::MD_fpmath);
+  if (!MD)
+    return false;
+  Value *Op = MD->getOperand(0);
+  if (isa<ConstantFP>(Op))
+    return false;
+  // If it's not a floating point number then it must be 'fast'.
+  assert(isa<MDString>(Op) && cast<MDString>(Op)->getString() == "fast" &&
+         "Expected the 'fast' keyword!");
+  return true;
+}
+
+
+//===----------------------------------------------------------------------===//
 //                                CastInst Class
 //===----------------------------------------------------------------------===//
 

Modified: llvm/trunk/lib/VMCore/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Verifier.cpp?rev=154822&r1=154821&r2=154822&view=diff
==============================================================================
--- llvm/trunk/lib/VMCore/Verifier.cpp (original)
+++ llvm/trunk/lib/VMCore/Verifier.cpp Mon Apr 16 11:28:59 2012
@@ -1657,12 +1657,16 @@
     Assert1(I.getType()->isFPOrFPVectorTy(),
             "fpmath requires a floating point result!", &I);
     Assert1(MD->getNumOperands() == 1, "fpmath takes one operand!", &I);
-    ConstantFP *Op = dyn_cast_or_null<ConstantFP>(MD->getOperand(0));
-    Assert1(Op, "fpmath ULPs not a floating point number!", &I);
-    APFloat ULPs = Op->getValueAPF();
-    Assert1(ULPs.isNormal() || ULPs.isZero(),
-            "fpmath ULPs not a normal number!", &I);
-    Assert1(!ULPs.isNegative(), "fpmath ULPs is negative!", &I);
+    Value *Op0 = MD->getOperand(0);
+    if (ConstantFP *CFP0 = dyn_cast_or_null<ConstantFP>(Op0)) {
+      APFloat Accuracy = CFP0->getValueAPF();
+      Assert1(Accuracy.isNormal() && !Accuracy.isNegative(),
+              "fpmath accuracy not a positive number!", &I);
+    } else if (MDString *S0 = dyn_cast_or_null<MDString>(Op0)) {
+      Assert1(S0->getString() == "fast", "wrong fpmath accuracy keyword!", &I);
+    } else {
+      Assert1(false, "invalid fpmath accuracy!", &I);
+    }
   }
 
   MDNode *MD = I.getMetadata(LLVMContext::MD_range);

Modified: llvm/trunk/test/Verifier/fpmath.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/fpmath.ll?rev=154822&r1=154821&r2=154822&view=diff
==============================================================================
--- llvm/trunk/test/Verifier/fpmath.ll (original)
+++ llvm/trunk/test/Verifier/fpmath.ll Mon Apr 16 11:28:59 2012
@@ -1,6 +1,6 @@
 ; RUN: not llvm-as < %s |& FileCheck %s
 
-define void @foo(i32 %i, float %f, <2 x float> %g) {
+define void @fpmath1(i32 %i, float %f, <2 x float> %g) {
   %s = add i32 %i, %i, !fpmath !0
 ; CHECK: fpmath requires a floating point result!
   %t = fadd float %f, %f, !fpmath !1
@@ -8,17 +8,27 @@
   %u = fadd float %f, %f, !fpmath !2
 ; CHECK: fpmath takes one operand!
   %v = fadd float %f, %f, !fpmath !3
-; CHECK: fpmath ULPs not a floating point number!
+; CHECK: invalid fpmath accuracy!
   %w = fadd float %f, %f, !fpmath !0
 ; Above line is correct.
   %w2 = fadd <2 x float> %g, %g, !fpmath !0
 ; Above line is correct.
   %x = fadd float %f, %f, !fpmath !4
-; CHECK: fpmath ULPs is negative!
+; CHECK: fpmath accuracy not a positive number!
   %y = fadd float %f, %f, !fpmath !5
-; CHECK: fpmath ULPs is negative!
+; CHECK: fpmath accuracy not a positive number!
   %z = fadd float %f, %f, !fpmath !6
-; CHECK: fpmath ULPs not a normal number!
+; CHECK: fpmath accuracy not a positive number!
+  ret void
+}
+
+define void @fpmath2(float %f, <2 x float> %g) {
+  %w = fadd float %f, %f, !fpmath !7
+; Above line is correct.
+  %w2 = fadd <2 x float> %g, %g, !fpmath !7
+; Above line is correct.
+  %x = fadd float %f, %f, !fpmath !8
+; CHECK: wrong fpmath accuracy keyword!
   ret void
 }
 
@@ -27,5 +37,7 @@
 !2 = metadata !{ float 1.0, float 1.0 }
 !3 = metadata !{ i32 1 }
 !4 = metadata !{ float -1.0 }
-!5 = metadata !{ float -0.0 }
+!5 = metadata !{ float 0.0 }
 !6 = metadata !{ float 0x7FFFFFFF00000000 }
+!7 = metadata !{ metadata !"fast" }
+!8 = metadata !{ metadata !"slow" }

Modified: llvm/trunk/unittests/Support/MDBuilderTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/MDBuilderTest.cpp?rev=154822&r1=154821&r2=154822&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/MDBuilderTest.cpp (original)
+++ llvm/trunk/unittests/Support/MDBuilderTest.cpp Mon Apr 16 11:28:59 2012
@@ -8,6 +8,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "gtest/gtest.h"
+#include "llvm/Operator.h"
+#include "llvm/Support/IRBuilder.h"
 #include "llvm/Support/MDBuilder.h"
 using namespace llvm;
 
@@ -18,19 +20,43 @@
   LLVMContext Context;
 };
 
-TEST_F(MDBuilderTest, CreateString) {
+TEST_F(MDBuilderTest, createString) {
   MDBuilder MDHelper(Context);
-  MDString *Str0 = MDHelper.CreateString("");
-  MDString *Str1 = MDHelper.CreateString("string");
+  MDString *Str0 = MDHelper.createString("");
+  MDString *Str1 = MDHelper.createString("string");
   EXPECT_EQ(Str0->getString(), StringRef(""));
   EXPECT_EQ(Str1->getString(), StringRef("string"));
 }
-
-TEST_F(MDBuilderTest, CreateRangeMetadata) {
+TEST_F(MDBuilderTest, createFastFPMath) {
+  MDBuilder MDHelper(Context);
+  MDNode *MD = MDHelper.createFastFPMath();
+  EXPECT_NE(MD, (MDNode *)0);
+  EXPECT_EQ(MD->getNumOperands(), 1U);
+  Value *Op = MD->getOperand(0);
+  EXPECT_TRUE(isa<MDString>(Op));
+  EXPECT_EQ(cast<MDString>(Op)->getString(), "fast");
+}
+TEST_F(MDBuilderTest, createFPMath) {
+  MDBuilder MDHelper(Context);
+  MDNode *MD0 = MDHelper.createFPMath(0.0);
+  MDNode *MD1 = MDHelper.createFPMath(1.0);
+  MDNode *MDF = MDHelper.createFPMath(-1.0);
+  MDNode *MDF2 = MDHelper.createFastFPMath();
+  EXPECT_EQ(MD0, (MDNode *)0);
+  EXPECT_NE(MD1, (MDNode *)0);
+  EXPECT_EQ(MDF, MDF2);
+  EXPECT_EQ(MD1->getNumOperands(), 1U);
+  Value *Op = MD1->getOperand(0);
+  EXPECT_TRUE(isa<ConstantFP>(Op));
+  EXPECT_TRUE(Op->getType()->isFloatingPointTy());
+  ConstantFP *Val = cast<ConstantFP>(Op);
+  EXPECT_TRUE(Val->isExactlyValue(1.0));
+}
+TEST_F(MDBuilderTest, createRangeMetadata) {
   MDBuilder MDHelper(Context);
   APInt A(8, 1), B(8, 2);
-  MDNode *R0 = MDHelper.CreateRange(A, A);
-  MDNode *R1 = MDHelper.CreateRange(A, B);
+  MDNode *R0 = MDHelper.createRange(A, A);
+  MDNode *R1 = MDHelper.createRange(A, B);
   EXPECT_EQ(R0, (MDNode *)0);
   EXPECT_NE(R1, (MDNode *)0);
   EXPECT_EQ(R1->getNumOperands(), 2U);
@@ -41,10 +67,10 @@
   EXPECT_EQ(C0->getValue(), A);
   EXPECT_EQ(C1->getValue(), B);
 }
-TEST_F(MDBuilderTest, CreateAnonymousTBAARoot) {
+TEST_F(MDBuilderTest, createAnonymousTBAARoot) {
   MDBuilder MDHelper(Context);
-  MDNode *R0 = MDHelper.CreateAnonymousTBAARoot();
-  MDNode *R1 = MDHelper.CreateAnonymousTBAARoot();
+  MDNode *R0 = MDHelper.createAnonymousTBAARoot();
+  MDNode *R1 = MDHelper.createAnonymousTBAARoot();
   EXPECT_NE(R0, R1);
   EXPECT_GE(R0->getNumOperands(), 1U);
   EXPECT_GE(R1->getNumOperands(), 1U);
@@ -53,23 +79,23 @@
   EXPECT_TRUE(R0->getNumOperands() == 1 || R0->getOperand(1) == 0);
   EXPECT_TRUE(R1->getNumOperands() == 1 || R1->getOperand(1) == 0);
 }
-TEST_F(MDBuilderTest, CreateTBAARoot) {
+TEST_F(MDBuilderTest, createTBAARoot) {
   MDBuilder MDHelper(Context);
-  MDNode *R0 = MDHelper.CreateTBAARoot("Root");
-  MDNode *R1 = MDHelper.CreateTBAARoot("Root");
+  MDNode *R0 = MDHelper.createTBAARoot("Root");
+  MDNode *R1 = MDHelper.createTBAARoot("Root");
   EXPECT_EQ(R0, R1);
   EXPECT_GE(R0->getNumOperands(), 1U);
   EXPECT_TRUE(isa<MDString>(R0->getOperand(0)));
   EXPECT_EQ(cast<MDString>(R0->getOperand(0))->getString(), "Root");
   EXPECT_TRUE(R0->getNumOperands() == 1 || R0->getOperand(1) == 0);
 }
-TEST_F(MDBuilderTest, CreateTBAANode) {
+TEST_F(MDBuilderTest, createTBAANode) {
   MDBuilder MDHelper(Context);
-  MDNode *R = MDHelper.CreateTBAARoot("Root");
-  MDNode *N0 = MDHelper.CreateTBAANode("Node", R);
-  MDNode *N1 = MDHelper.CreateTBAANode("edoN", R);
-  MDNode *N2 = MDHelper.CreateTBAANode("Node", R, true);
-  MDNode *N3 = MDHelper.CreateTBAANode("Node", R);
+  MDNode *R = MDHelper.createTBAARoot("Root");
+  MDNode *N0 = MDHelper.createTBAANode("Node", R);
+  MDNode *N1 = MDHelper.createTBAANode("edoN", R);
+  MDNode *N2 = MDHelper.createTBAANode("Node", R, true);
+  MDNode *N3 = MDHelper.createTBAANode("Node", R);
   EXPECT_EQ(N0, N3);
   EXPECT_NE(N0, N1);
   EXPECT_NE(N0, N2);

Modified: llvm/trunk/unittests/VMCore/InstructionsTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/VMCore/InstructionsTest.cpp?rev=154822&r1=154821&r2=154822&view=diff
==============================================================================
--- llvm/trunk/unittests/VMCore/InstructionsTest.cpp (original)
+++ llvm/trunk/unittests/VMCore/InstructionsTest.cpp Mon Apr 16 11:28:59 2012
@@ -12,8 +12,11 @@
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/LLVMContext.h"
+#include "llvm/Operator.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Analysis/ValueTracking.h"
+#include "llvm/Support/MDBuilder.h"
+#include "llvm/Support/IRBuilder.h"
 #include "llvm/Target/TargetData.h"
 #include "gtest/gtest.h"
 
@@ -226,5 +229,27 @@
   delete PtrVecB;
 }
 
+TEST(InstructionsTest, FPMathOperator) {
+  LLVMContext &Context = getGlobalContext();
+  IRBuilder<> Builder(Context);
+  MDBuilder MDHelper(Context);
+  Instruction *I = Builder.CreatePHI(Builder.getDoubleTy(), 0);
+  MDNode *MD1 = MDHelper.createFPMath(1.0);
+  MDNode *MDF = MDHelper.createFastFPMath();
+  Value *V1 = Builder.CreateFAdd(I, I, "", MD1);
+  Value *VF = Builder.CreateFAdd(I, I, "", MDF);
+  EXPECT_TRUE(isa<FPMathOperator>(V1));
+  EXPECT_TRUE(isa<FPMathOperator>(VF));
+  FPMathOperator *O1 = cast<FPMathOperator>(V1);
+  FPMathOperator *OF = cast<FPMathOperator>(VF);
+  EXPECT_FALSE(O1->isFastFPAccuracy());
+  EXPECT_TRUE(OF->isFastFPAccuracy());
+  EXPECT_EQ(O1->getFPAccuracy(), 1.0);
+  EXPECT_GT(OF->getFPAccuracy(), 999.0);
+  delete V1;
+  delete VF;
+  delete I;
+}
+
 }  // end anonymous namespace
 }  // end namespace llvm





More information about the llvm-commits mailing list