Index: llvm/include/llvm/IR/IRBuilder.h =================================================================== --- llvm/include/llvm/IR/IRBuilder.h +++ llvm/include/llvm/IR/IRBuilder.h @@ -1372,6 +1372,17 @@ return Insert(BinaryOperator::CreateNot(V), Name); } + /// Copy fast-math-flags from an instruction rather than using the builder's + /// default FMF. + Value *CreateFNegFMF(Value *V, Instruction *FMFSource, + const Twine &Name = "") { + if (auto *VC = dyn_cast(V)) + return Insert(Folder.CreateFNeg(VC), Name); + return Insert(setFPAttrs(UnaryOperator::CreateFNeg(V), nullptr, + FMFSource->getFastMathFlags()), + Name); + } + Value *CreateUnOp(Instruction::UnaryOps Opc, Value *V, const Twine &Name = "", MDNode *FPMathTag = nullptr) { Index: llvm/unittests/IR/IRBuilderTest.cpp =================================================================== --- llvm/unittests/IR/IRBuilderTest.cpp +++ llvm/unittests/IR/IRBuilderTest.cpp @@ -206,12 +206,22 @@ IRBuilder Builder(BB); Value *V = Builder.CreateLoad(GV->getValueType(), GV); - // Test CreateUnOp + // Test CreateUnOp(X) Value *U = Builder.CreateUnOp(Instruction::FNeg, V); ASSERT_TRUE(isa(U)); ASSERT_TRUE(isa(U)); ASSERT_TRUE(isa(U)); ASSERT_FALSE(isa(U)); + + // Test CreateFNegFMF(X) + Instruction *I = cast(V); + I->setHasNoSignedZeros(true); + I->setHasNoNaNs(true); + Value *VFMF = Builder.CreateFNegFMF(V, I); + Instruction *IFMF = cast(VFMF); + EXPECT_TRUE(IFMF->hasNoSignedZeros()); + EXPECT_TRUE(IFMF->hasNoNaNs()); + EXPECT_FALSE(IFMF->hasAllowReassoc()); } TEST_F(IRBuilderTest, FastMathFlags) {