llvm.org GIT mirror llvm / 2867c85
Remove support for the special 'fast' value for fpmath accuracy for the moment. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154850 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan Sands 8 years ago
8 changed file(s) with 10 addition(s) and 83 deletion(s). Raw diff Collapse all Expand all
30073007

fpmath metadata may be attached to any instruction of floating point

30083008 type. It can be used to express the maximum acceptable error in the result of
30093009 that instruction, in ULPs, thus potentially allowing the compiler to use a
3010 more efficient but less accurate method of computing it. The number of ULPs
3011 may also be the string "fast", which tells the compiler that speed
3012 matters more than accuracy, so any fairly accurate method of computation is
3013 fine as long as it is quick. ULP is defined as follows:

3010 more efficient but less accurate method of computing it. ULP is defined as
3011 follows:

30143012
30153013
30163014
30233021
30243022
30253023

The metadata node shall consist of a single positive floating point number

3026 representing the maximum relative error, or the string "fast".
3027 For example:

3024 representing the maximum relative error, for example:

30283025
30293026
30303027

                  
                
30313028 !0 = metadata !{ float 2.5 } ; maximum acceptable inaccuracy is 2.5 ULPs
3032 !1 = metadata !{ !metadata !"fast" } ; potentially unbounded inaccuracy
30333029
30343030
30353031
173173
174174 /// \brief Get the maximum error permitted by this operation in ULPs. An
175175 /// accuracy of 0.0 means that the operation should be performed with the
176 /// default precision. A huge value is returned if the accuracy is 'fast'.
176 /// default precision.
177177 float getFPAccuracy() const;
178
179 /// \brief Return true if the accuracy is 'fast'. This indicates that speed
180 /// is more important than accuracy.
181 bool isFastFPAccuracy() const;
182178
183179 static inline bool classof(const FPMathOperator *) { return true; }
184180 static inline bool classof(const Instruction *I) {
2525 class MDBuilder {
2626 LLVMContext &Context;
2727
28 MDString *getFastString() {
29 return createString("fast");
30 }
3128 public:
3229 MDBuilder(LLVMContext &context) : Context(context) {}
3330
4037 // FPMath metadata.
4138 //===------------------------------------------------------------------===//
4239
43 /// \brief Return metadata with appropriate settings for 'fast math'.
44 MDNode *createFastFPMath() {
45 return MDNode::get(Context, getFastString());
46 }
47
48 /// \brief Return metadata with the given settings. Special values for the
49 /// Accuracy parameter are 0.0, which means the default (maximal precision)
50 /// setting; and negative values which all mean 'fast'.
40 /// \brief Return metadata with the given settings. The special value 0.0
41 /// for the Accuracy parameter indicates the default (maximal precision)
42 /// setting.
5143 MDNode *createFPMath(float Accuracy) {
5244 if (Accuracy == 0.0)
5345 return 0;
54 if (Accuracy < 0.0)
55 return MDNode::get(Context, getFastString());
5646 assert(Accuracy > 0.0 && "Invalid fpmath accuracy!");
5747 Value *Op = ConstantFP::get(Type::getFloatTy(Context), Accuracy);
5848 return MDNode::get(Context, Op);
20072007
20082008 /// getFPAccuracy - Get the maximum error permitted by this operation in ULPs.
20092009 /// An accuracy of 0.0 means that the operation should be performed with the
2010 /// default precision. A huge value is returned if the accuracy is 'fast'.
2010 /// default precision.
20112011 float FPMathOperator::getFPAccuracy() const {
20122012 const MDNode *MD =
20132013 cast(this)->getMetadata(LLVMContext::MD_fpmath);
20142014 if (!MD)
20152015 return 0.0;
2016 Value *Op = MD->getOperand(0);
2017 if (const ConstantFP *Accuracy = dyn_cast(Op))
2018 return Accuracy->getValueAPF().convertToFloat();
2019 // If it's not a floating point number then it must be 'fast'.
2020 assert(isa(Op) && cast(Op)->getString() == "fast" &&
2021 "Expected the 'fast' keyword!");
2022 return HUGE_VALF;
2023 }
2024
2025 /// isFastFPAccuracy - Return true if the accuracy is 'fast'. This says that
2026 /// speed is more important than accuracy.
2027 bool FPMathOperator::isFastFPAccuracy() const {
2028 const MDNode *MD =
2029 cast(this)->getMetadata(LLVMContext::MD_fpmath);
2030 if (!MD)
2031 return false;
2032 Value *Op = MD->getOperand(0);
2033 if (isa(Op))
2034 return false;
2035 // If it's not a floating point number then it must be 'fast'.
2036 assert(isa(Op) && cast(Op)->getString() == "fast" &&
2037 "Expected the 'fast' keyword!");
2038 return true;
2016 ConstantFP *Accuracy = cast(MD->getOperand(0));
2017 return Accuracy->getValueAPF().convertToFloat();
20392018 }
20402019
20412020
16611661 APFloat Accuracy = CFP0->getValueAPF();
16621662 Assert1(Accuracy.isNormal() && !Accuracy.isNegative(),
16631663 "fpmath accuracy not a positive number!", &I);
1664 } else if (MDString *S0 = dyn_cast_or_null(Op0)) {
1665 Assert1(S0->getString() == "fast", "wrong fpmath accuracy keyword!", &I);
16661664 } else {
16671665 Assert1(false, "invalid fpmath accuracy!", &I);
16681666 }
2121 ret void
2222 }
2323
24 define void @fpmath2(float %f, <2 x float> %g) {
25 %w = fadd float %f, %f, !fpmath !7
26 ; Above line is correct.
27 %w2 = fadd <2 x float> %g, %g, !fpmath !7
28 ; Above line is correct.
29 %x = fadd float %f, %f, !fpmath !8
30 ; CHECK: wrong fpmath accuracy keyword!
31 ret void
32 }
33
3424 !0 = metadata !{ float 1.0 }
3525 !1 = metadata !{ }
3626 !2 = metadata !{ float 1.0, float 1.0 }
3828 !4 = metadata !{ float -1.0 }
3929 !5 = metadata !{ float 0.0 }
4030 !6 = metadata !{ float 0x7FFFFFFF00000000 }
41 !7 = metadata !{ metadata !"fast" }
42 !8 = metadata !{ metadata !"slow" }
2626 EXPECT_EQ(Str0->getString(), StringRef(""));
2727 EXPECT_EQ(Str1->getString(), StringRef("string"));
2828 }
29 TEST_F(MDBuilderTest, createFastFPMath) {
30 MDBuilder MDHelper(Context);
31 MDNode *MD = MDHelper.createFastFPMath();
32 EXPECT_NE(MD, (MDNode *)0);
33 EXPECT_EQ(MD->getNumOperands(), 1U);
34 Value *Op = MD->getOperand(0);
35 EXPECT_TRUE(isa(Op));
36 EXPECT_EQ(cast(Op)->getString(), "fast");
37 }
3829 TEST_F(MDBuilderTest, createFPMath) {
3930 MDBuilder MDHelper(Context);
4031 MDNode *MD0 = MDHelper.createFPMath(0.0);
4132 MDNode *MD1 = MDHelper.createFPMath(1.0);
42 MDNode *MDF = MDHelper.createFPMath(-1.0);
43 MDNode *MDF2 = MDHelper.createFastFPMath();
4433 EXPECT_EQ(MD0, (MDNode *)0);
4534 EXPECT_NE(MD1, (MDNode *)0);
46 EXPECT_EQ(MDF, MDF2);
4735 EXPECT_EQ(MD1->getNumOperands(), 1U);
4836 Value *Op = MD1->getOperand(0);
4937 EXPECT_TRUE(isa(Op));
234234 MDBuilder MDHelper(Context);
235235 Instruction *I = Builder.CreatePHI(Builder.getDoubleTy(), 0);
236236 MDNode *MD1 = MDHelper.createFPMath(1.0);
237 MDNode *MDF = MDHelper.createFastFPMath();
238237 Value *V1 = Builder.CreateFAdd(I, I, "", MD1);
239 Value *VF = Builder.CreateFAdd(I, I, "", MDF);
240238 EXPECT_TRUE(isa(V1));
241 EXPECT_TRUE(isa(VF));
242239 FPMathOperator *O1 = cast(V1);
243 FPMathOperator *OF = cast(VF);
244 EXPECT_FALSE(O1->isFastFPAccuracy());
245 EXPECT_TRUE(OF->isFastFPAccuracy());
246240 EXPECT_EQ(O1->getFPAccuracy(), 1.0);
247 EXPECT_GT(OF->getFPAccuracy(), 999.0);
248241 delete V1;
249 delete VF;
250242 delete I;
251243 }
252244