Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -1916,10 +1916,18 @@ Allow Reciprocal - Allow optimizations to use the reciprocal of an argument rather than perform division. +``kexc`` + Keep Exceptions - Forbid optimizations to affect floating-point exceptions + that can be thrown at runtime. + +``kround`` + Keep Rounding - Optimizations may assume round-to-nearest (ties even) + rounding mode unless this flag is specified. + ``fast`` Fast - Allow algebraically equivalent transformations that may dramatically change results in floating point (e.g. reassociate). This - flag implies all the others. + flag implies all the others except for the last two. .. _uselistorder: Index: include/llvm/IR/Instruction.h =================================================================== --- include/llvm/IR/Instruction.h +++ include/llvm/IR/Instruction.h @@ -241,6 +241,16 @@ /// this flag. void setHasAllowReciprocal(bool B); + /// Set or clear the keep-exceptions flag on this instruction, which must be + /// an operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasKeepExceptions(bool B); + + /// Set or clear the keep-rounding flag on this instruction, which must be an + /// operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasKeepRounding(bool B); + /// 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. @@ -266,6 +276,12 @@ /// Determine whether the allow-reciprocal flag is set. bool hasAllowReciprocal() const; + /// Determine whether the keep-exceptions flag is set. + bool hasKeepExceptions() const; + + /// Determine whether the keep-rounding flag is set. + bool hasKeepRounding() const; + /// Convenience function for getting all the fast-math flags, which must be an /// operator which supports these flags. See LangRef.html for the meaning of /// these flags. Index: include/llvm/IR/Operator.h =================================================================== --- include/llvm/IR/Operator.h +++ include/llvm/IR/Operator.h @@ -173,7 +173,9 @@ NoNaNs = (1 << 1), NoInfs = (1 << 2), NoSignedZeros = (1 << 3), - AllowReciprocal = (1 << 4) + AllowReciprocal = (1 << 4), + KeepExceptions = (1 << 5), + KeepRounding = (1 << 6) }; FastMathFlags() : Flags(0) @@ -191,6 +193,8 @@ bool noSignedZeros() const { return 0 != (Flags & NoSignedZeros); } bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); } bool unsafeAlgebra() const { return 0 != (Flags & UnsafeAlgebra); } + bool keepExceptions() const { return 0 != (Flags & KeepExceptions); } + bool keepRounding()const { return 0 != (Flags & KeepRounding); } /// Flag setters void setNoNaNs() { Flags |= NoNaNs; } @@ -204,6 +208,8 @@ setNoSignedZeros(); setAllowReciprocal(); } + void setKeepExceptions() { Flags |= KeepExceptions; } + void setKeepRounding() { Flags |= KeepRounding; } void operator&=(const FastMathFlags &OtherFlags) { Flags &= OtherFlags.Flags; @@ -250,6 +256,16 @@ (SubclassOptionalData & ~FastMathFlags::AllowReciprocal) | (B * FastMathFlags::AllowReciprocal); } + void setHasKeepExceptions(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~FastMathFlags::KeepExceptions) | + (B * FastMathFlags::KeepExceptions); + } + void setHasKeepRounding(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~FastMathFlags::KeepRounding) | + (B * FastMathFlags::KeepRounding); + } /// Convenience function for setting multiple fast-math flags. /// FMF is a mask of the bits to set. @@ -294,6 +310,18 @@ return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0; } + /// Test whether this operation should not be optimized if its runtime + /// semantics regarding floating-point exceptions can't be preserved. + bool hasKeepExceptions() const { + return (SubclassOptionalData & FastMathFlags::KeepExceptions) != 0; + } + + /// Test whether this operation should not be optimized if its runtime + /// semantics regarding floating-point rounding modes can't be preserved. + bool hasKeepRounding() const { + return (SubclassOptionalData & FastMathFlags::KeepRounding) != 0; + } + /// Convenience function for getting all the fast-math flags FastMathFlags getFastMathFlags() const { return FastMathFlags(SubclassOptionalData); Index: lib/AsmParser/LLLexer.cpp =================================================================== --- lib/AsmParser/LLLexer.cpp +++ lib/AsmParser/LLLexer.cpp @@ -546,6 +546,8 @@ KEYWORD(ninf); KEYWORD(nsz); KEYWORD(arcp); + KEYWORD(kexc); + KEYWORD(kround); KEYWORD(fast); KEYWORD(nuw); KEYWORD(nsw); Index: lib/AsmParser/LLParser.h =================================================================== --- lib/AsmParser/LLParser.h +++ lib/AsmParser/LLParser.h @@ -193,11 +193,13 @@ FastMathFlags FMF; while (true) switch (Lex.getKind()) { - case lltok::kw_fast: FMF.setUnsafeAlgebra(); Lex.Lex(); continue; - case lltok::kw_nnan: FMF.setNoNaNs(); Lex.Lex(); continue; - case lltok::kw_ninf: FMF.setNoInfs(); Lex.Lex(); continue; - case lltok::kw_nsz: FMF.setNoSignedZeros(); Lex.Lex(); continue; - case lltok::kw_arcp: FMF.setAllowReciprocal(); Lex.Lex(); continue; + case lltok::kw_fast: FMF.setUnsafeAlgebra(); Lex.Lex(); continue; + case lltok::kw_nnan: FMF.setNoNaNs(); Lex.Lex(); continue; + case lltok::kw_ninf: FMF.setNoInfs(); Lex.Lex(); continue; + case lltok::kw_nsz: FMF.setNoSignedZeros(); Lex.Lex(); continue; + case lltok::kw_arcp: FMF.setAllowReciprocal(); Lex.Lex(); continue; + case lltok::kw_kexc: FMF.setKeepExceptions(); Lex.Lex(); continue; + case lltok::kw_kround: FMF.setKeepRounding(); Lex.Lex(); continue; default: return FMF; } return FMF; Index: lib/AsmParser/LLToken.h =================================================================== --- lib/AsmParser/LLToken.h +++ lib/AsmParser/LLToken.h @@ -67,6 +67,8 @@ kw_ninf, kw_nsz, kw_arcp, + kw_kexc, + kw_kround, kw_fast, kw_nuw, kw_nsw, Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -823,6 +823,10 @@ FMF.setNoSignedZeros(); if (0 != (Val & FastMathFlags::AllowReciprocal)) FMF.setAllowReciprocal(); + if (0 != (Val & FastMathFlags::KeepExceptions)) + FMF.setKeepExceptions(); + if (0 != (Val & FastMathFlags::KeepRounding)) + FMF.setKeepRounding(); return FMF; } Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -800,6 +800,10 @@ Flags |= FastMathFlags::NoSignedZeros; if (FPMO->hasAllowReciprocal()) Flags |= FastMathFlags::AllowReciprocal; + if (FPMO->hasKeepExceptions()) + Flags |= FastMathFlags::KeepExceptions; + if (FPMO->hasKeepRounding()) + Flags |= FastMathFlags::KeepRounding; } return Flags; Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -1067,6 +1067,10 @@ Out << " nsz"; if (FPO->hasAllowReciprocal()) Out << " arcp"; + if (FPO->hasKeepExceptions()) + Out << " kexc"; + if (FPO->hasKeepRounding()) + Out << " kround"; } } Index: lib/IR/Instruction.cpp =================================================================== --- lib/IR/Instruction.cpp +++ lib/IR/Instruction.cpp @@ -130,6 +130,22 @@ cast(this)->setHasAllowReciprocal(B); } +/// Set or clear the keep-exceptions flag on this instruction, which must be an +/// operator which supports this flag. See LangRef.html for the meaning of this +/// flag. +void Instruction::setHasKeepExceptions(bool B) { + assert(isa(this) && "setting fast-math flag on invalid op"); + cast(this)->setHasKeepExceptions(B); +} + +/// Set or clear the keep-rounding flag on this instruction, which must be an +/// operator which supports this flag. See LangRef.html for the meaning of this +/// flag. +void Instruction::setHasKeepRounding(bool B) { + assert(isa(this) && "setting fast-math flag on invalid op"); + cast(this)->setHasKeepRounding(B); +} + /// Convenience function for setting all the fast-math flags on this /// instruction, which must be an operator which supports these flags. See /// LangRef.html for the meaning of these flats. @@ -173,6 +189,18 @@ return cast(this)->hasAllowReciprocal(); } +/// Determine whether the keep-exceptions flag is set. +bool Instruction::hasKeepExceptions() const { + assert(isa(this) && "getting fast-math flag on invalid op"); + return cast(this)->hasKeepExceptions(); +} + +/// Determine whether the keep-rounding flag is set. +bool Instruction::hasKeepRounding() const { + assert(isa(this) && "getting fast-math flag on invalid op"); + return cast(this)->hasKeepRounding(); +} + /// Convenience function for getting all the fast-math flags, which must be an /// operator which supports these flags. See LangRef.html for the meaning of /// these flags. Index: test/Assembler/fast-math-flags.ll =================================================================== --- test/Assembler/fast-math-flags.ll +++ test/Assembler/fast-math-flags.ll @@ -138,6 +138,14 @@ %e = frem nnan nsz float %x, %y ; CHECK: %e_vec = frem nnan <3 x float> %vec, %vec %e_vec = frem nnan <3 x float> %vec, %vec +; CHECK: %f = fmul fast float %x, %y + %f = fmul kexc kround fast float %x, %y +; CHECK: %f_vec = frem fast <3 x float> %vec, %vec + %f_vec = frem kexc kround fast <3 x float> %vec, %vec +; CHECK: %g = fmul kexc kround float %x, %y + %g = fmul kexc kround float %x, %y +; CHECK: %g_vec = frem kexc kround <3 x float> %vec, %vec + %g_vec = frem kexc kround <3 x float> %vec, %vec ; CHECK: ret float %e ret float %e }