diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h index 799f684349f1..7ef245cbc46e 100644 --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -358,7 +358,7 @@ public: /// isExact - Determine whether the exact flag is set. bool isExact() const; - /// Convenience method to copy wrapping, exact, and fast-math flag values + /// Convenience method to copy supported wrapping, exact, and fast-math flags /// from V to this instruction. void copyFlags(const Value *V); diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h index 7665033ac125..8dd2bbc1b140 100644 --- a/llvm/include/llvm/IR/Instruction.h +++ b/llvm/include/llvm/IR/Instruction.h @@ -230,11 +230,16 @@ public: /// this flag. void setHasAllowReciprocal(bool B); - /// Convenience function for setting all the fast-math flags on this + /// Convenience function for setting multiple fast-math flags on this /// instruction, which must be an operator which supports these flags. See /// LangRef.html for the meaning of these flags. void setFastMathFlags(FastMathFlags FMF); + /// Convenience function for transferring all fast-math flag values to this + /// instruction, which must be an operator which supports these flags. See + /// LangRef.html for the meaning of these flags. + void copyFastMathFlags(FastMathFlags FMF); + /// Determine whether the unsafe-algebra flag is set. bool hasUnsafeAlgebra() const; diff --git a/llvm/include/llvm/IR/Operator.h b/llvm/include/llvm/IR/Operator.h index 762f4a75c315..c25937c97ab0 100644 --- a/llvm/include/llvm/IR/Operator.h +++ b/llvm/include/llvm/IR/Operator.h @@ -257,11 +257,18 @@ private: (B * FastMathFlags::AllowReciprocal); } - /// Convenience function for setting all the fast-math flags + /// Convenience function for setting multiple fast-math flags. + /// FMF is a mask of the bits to set. void setFastMathFlags(FastMathFlags FMF) { SubclassOptionalData |= FMF.Flags; } + /// Convenience function for copying all fast-math flags. + /// All values in FMF are transferred to this operator. + void copyFastMathFlags(FastMathFlags FMF) { + SubclassOptionalData = FMF.Flags; + } + public: /// Test whether this operation is permitted to be /// algebraically transformed, aka the 'A' fast-math property. diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp index 86421c4ae9ff..50b1f04d41e1 100644 --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -143,6 +143,11 @@ void Instruction::setFastMathFlags(FastMathFlags FMF) { cast(this)->setFastMathFlags(FMF); } +void Instruction::copyFastMathFlags(FastMathFlags FMF) { + assert(isa(this) && "copying fast-math flag on invalid op"); + cast(this)->copyFastMathFlags(FMF); +} + /// Determine whether the unsafe-algebra flag is set. bool Instruction::hasUnsafeAlgebra() const { assert(isa(this) && "getting fast-math flag on invalid op"); @@ -183,7 +188,7 @@ FastMathFlags Instruction::getFastMathFlags() const { /// Copy I's fast-math flags void Instruction::copyFastMathFlags(const Instruction *I) { - setFastMathFlags(I->getFastMathFlags()); + copyFastMathFlags(I->getFastMathFlags()); } diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index 16993f1bba54..b113d51d4168 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -2043,7 +2043,7 @@ void BinaryOperator::copyFlags(const Value *V) { // Copy the fast-math flags. if (auto *FP = dyn_cast(V)) - setFastMathFlags(FP->getFastMathFlags()); + copyFastMathFlags(FP->getFastMathFlags()); } //===----------------------------------------------------------------------===// diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp index 21085755fbad..df5c84064779 100644 --- a/llvm/unittests/IR/IRBuilderTest.cpp +++ b/llvm/unittests/IR/IRBuilderTest.cpp @@ -189,12 +189,16 @@ TEST_F(IRBuilderTest, FastMathFlags) { Builder.clearFastMathFlags(); + // To test a copy, make sure that a '0' and a '1' change state. F = Builder.CreateFDiv(F, F); ASSERT_TRUE(isa(F)); FDiv = cast(F); EXPECT_FALSE(FDiv->getFastMathFlags().any()); + FDiv->setHasAllowReciprocal(true); + FAdd->setHasAllowReciprocal(false); FDiv->copyFastMathFlags(FAdd); EXPECT_TRUE(FDiv->hasNoNaNs()); + EXPECT_FALSE(FDiv->hasAllowReciprocal()); }