diff options
-rw-r--r-- | docs/LangRef.html | 19 | ||||
-rw-r--r-- | docs/ReleaseNotes.html | 3 | ||||
-rw-r--r-- | include/llvm/Operator.h | 30 | ||||
-rw-r--r-- | include/llvm/Support/IRBuilder.h | 87 | ||||
-rw-r--r-- | include/llvm/Support/MDBuilder.h | 62 | ||||
-rw-r--r-- | lib/VMCore/Instructions.cpp | 38 | ||||
-rw-r--r-- | lib/VMCore/Verifier.cpp | 16 | ||||
-rw-r--r-- | test/Verifier/fpmath.ll | 24 | ||||
-rw-r--r-- | unittests/Support/MDBuilderTest.cpp | 64 | ||||
-rw-r--r-- | unittests/VMCore/InstructionsTest.cpp | 25 |
10 files changed, 282 insertions, 86 deletions
diff --git a/docs/LangRef.html b/docs/LangRef.html index c148211..3a474a5 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -3006,10 +3006,12 @@ call void @llvm.dbg.value(metadata !24, i64 0, metadata !25) <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 @@ call void @llvm.dbg.value(metadata !24, i64 0, metadata !25) </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> diff --git a/docs/ReleaseNotes.html b/docs/ReleaseNotes.html index aa85e15..5af15eb 100644 --- a/docs/ReleaseNotes.html +++ b/docs/ReleaseNotes.html @@ -489,6 +489,9 @@ syntax, there are still significant gaps in that support.</p> <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> diff --git a/include/llvm/Operator.h b/include/llvm/Operator.h index 9268d98..6bd7e56 100644 --- a/include/llvm/Operator.h +++ b/include/llvm/Operator.h @@ -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 @@ public: (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 diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/Support/IRBuilder.h index 7828001..ef00e8e 100644 --- a/include/llvm/Support/IRBuilder.h +++ b/include/llvm/Support/IRBuilder.h @@ -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 @@ template<bool preserveNames = true, typename T = ConstantFolder, 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 @@ private: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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)) diff --git a/include/llvm/Support/MDBuilder.h b/include/llvm/Support/MDBuilder.h index 022e8e3..f6d8452 100644 --- a/include/llvm/Support/MDBuilder.h +++ b/include/llvm/Support/MDBuilder.h @@ -26,20 +26,46 @@ namespace llvm { 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 @@ namespace llvm { // 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 @@ namespace llvm { 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); } } diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 8db6ac9..185cd05 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -2003,6 +2003,44 @@ bool BinaryOperator::isExact() const { } //===----------------------------------------------------------------------===// +// 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 //===----------------------------------------------------------------------===// diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index ab79d8c..2576766 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -1657,12 +1657,16 @@ void Verifier::visitInstruction(Instruction &I) { 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); diff --git a/test/Verifier/fpmath.ll b/test/Verifier/fpmath.ll index 4cfed2a..a7d3ea8 100644 --- a/test/Verifier/fpmath.ll +++ b/test/Verifier/fpmath.ll @@ -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 @@ define void @foo(i32 %i, float %f, <2 x float> %g) { %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 @@ define void @foo(i32 %i, float %f, <2 x float> %g) { !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" } diff --git a/unittests/Support/MDBuilderTest.cpp b/unittests/Support/MDBuilderTest.cpp index 44218d3..e8e0386 100644 --- a/unittests/Support/MDBuilderTest.cpp +++ b/unittests/Support/MDBuilderTest.cpp @@ -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 @@ protected: 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 @@ TEST_F(MDBuilderTest, CreateRangeMetadata) { 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 @@ TEST_F(MDBuilderTest, CreateAnonymousTBAARoot) { 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); diff --git a/unittests/VMCore/InstructionsTest.cpp b/unittests/VMCore/InstructionsTest.cpp index 218a9a0..9c0cb44 100644 --- a/unittests/VMCore/InstructionsTest.cpp +++ b/unittests/VMCore/InstructionsTest.cpp @@ -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 @@ TEST(InstructionsTest, VectorGep) { 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 |