mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-27 13:40:43 +00:00
[IR] Add AllowContract to FastMathFlags
-ffp-contract=fast does not currently work with LTO because it's passed as a TargetOption to the backend rather than in the IR. This adds it to FastMathFlags. This is toward fixing PR25721 Differential Revision: https://reviews.llvm.org/D31164 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298939 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d707b92e85
commit
5c57c1108e
@ -2194,6 +2194,10 @@ otherwise unsafe floating point transformations.
|
||||
Allow Reciprocal - Allow optimizations to use the reciprocal of an
|
||||
argument rather than perform division.
|
||||
|
||||
``contract``
|
||||
Allow floating-point contraction (e.g. fusing a multiply followed by an
|
||||
addition into a fused multiply-and-add).
|
||||
|
||||
``fast``
|
||||
Fast - Allow algebraically equivalent transformations that may
|
||||
dramatically change results in floating point (e.g. reassociate). This
|
||||
|
@ -345,6 +345,9 @@ public:
|
||||
/// Determine whether the allow-reciprocal flag is set.
|
||||
bool hasAllowReciprocal() const;
|
||||
|
||||
/// Determine whether the allow-contract flag is set.
|
||||
bool hasAllowContract() 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.
|
||||
|
@ -172,12 +172,15 @@ private:
|
||||
FastMathFlags(unsigned F) : Flags(F) { }
|
||||
|
||||
public:
|
||||
/// This is how the bits are used in Value::SubclassOptionalData so they
|
||||
/// should fit there too.
|
||||
enum {
|
||||
UnsafeAlgebra = (1 << 0),
|
||||
NoNaNs = (1 << 1),
|
||||
NoInfs = (1 << 2),
|
||||
NoSignedZeros = (1 << 3),
|
||||
AllowReciprocal = (1 << 4)
|
||||
AllowReciprocal = (1 << 4),
|
||||
AllowContract = (1 << 5)
|
||||
};
|
||||
|
||||
FastMathFlags() = default;
|
||||
@ -193,6 +196,7 @@ public:
|
||||
bool noInfs() const { return 0 != (Flags & NoInfs); }
|
||||
bool noSignedZeros() const { return 0 != (Flags & NoSignedZeros); }
|
||||
bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); }
|
||||
bool allowContract() const { return 0 != (Flags & AllowContract); }
|
||||
bool unsafeAlgebra() const { return 0 != (Flags & UnsafeAlgebra); }
|
||||
|
||||
/// Flag setters
|
||||
@ -200,12 +204,16 @@ public:
|
||||
void setNoInfs() { Flags |= NoInfs; }
|
||||
void setNoSignedZeros() { Flags |= NoSignedZeros; }
|
||||
void setAllowReciprocal() { Flags |= AllowReciprocal; }
|
||||
void setAllowContract(bool B) {
|
||||
Flags = (Flags & ~AllowContract) | B * AllowContract;
|
||||
}
|
||||
void setUnsafeAlgebra() {
|
||||
Flags |= UnsafeAlgebra;
|
||||
setNoNaNs();
|
||||
setNoInfs();
|
||||
setNoSignedZeros();
|
||||
setAllowReciprocal();
|
||||
setAllowContract(true);
|
||||
}
|
||||
|
||||
void operator&=(const FastMathFlags &OtherFlags) {
|
||||
@ -257,6 +265,12 @@ private:
|
||||
(B * FastMathFlags::AllowReciprocal);
|
||||
}
|
||||
|
||||
void setHasAllowContract(bool B) {
|
||||
SubclassOptionalData =
|
||||
(SubclassOptionalData & ~FastMathFlags::AllowContract) |
|
||||
(B * FastMathFlags::AllowContract);
|
||||
}
|
||||
|
||||
/// Convenience function for setting multiple fast-math flags.
|
||||
/// FMF is a mask of the bits to set.
|
||||
void setFastMathFlags(FastMathFlags FMF) {
|
||||
@ -300,6 +314,12 @@ public:
|
||||
return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0;
|
||||
}
|
||||
|
||||
/// Test whether this operation is permitted to
|
||||
/// be floating-point contracted.
|
||||
bool hasAllowContract() const {
|
||||
return (SubclassOptionalData & FastMathFlags::AllowContract) != 0;
|
||||
}
|
||||
|
||||
/// Convenience function for getting all the fast-math flags
|
||||
FastMathFlags getFastMathFlags() const {
|
||||
return FastMathFlags(SubclassOptionalData);
|
||||
|
@ -548,6 +548,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(ninf);
|
||||
KEYWORD(nsz);
|
||||
KEYWORD(arcp);
|
||||
KEYWORD(contract);
|
||||
KEYWORD(fast);
|
||||
KEYWORD(nuw);
|
||||
KEYWORD(nsw);
|
||||
|
@ -193,6 +193,10 @@ namespace llvm {
|
||||
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_contract:
|
||||
FMF.setAllowContract(true);
|
||||
Lex.Lex();
|
||||
continue;
|
||||
default: return FMF;
|
||||
}
|
||||
return FMF;
|
||||
|
@ -98,6 +98,7 @@ enum Kind {
|
||||
kw_ninf,
|
||||
kw_nsz,
|
||||
kw_arcp,
|
||||
kw_contract,
|
||||
kw_fast,
|
||||
kw_nuw,
|
||||
kw_nsw,
|
||||
|
@ -971,6 +971,8 @@ static FastMathFlags getDecodedFastMathFlags(unsigned Val) {
|
||||
FMF.setNoSignedZeros();
|
||||
if (0 != (Val & FastMathFlags::AllowReciprocal))
|
||||
FMF.setAllowReciprocal();
|
||||
if (0 != (Val & FastMathFlags::AllowContract))
|
||||
FMF.setAllowContract(true);
|
||||
return FMF;
|
||||
}
|
||||
|
||||
|
@ -1336,6 +1336,8 @@ static uint64_t getOptimizationFlags(const Value *V) {
|
||||
Flags |= FastMathFlags::NoSignedZeros;
|
||||
if (FPMO->hasAllowReciprocal())
|
||||
Flags |= FastMathFlags::AllowReciprocal;
|
||||
if (FPMO->hasAllowContract())
|
||||
Flags |= FastMathFlags::AllowContract;
|
||||
}
|
||||
|
||||
return Flags;
|
||||
|
@ -1073,6 +1073,8 @@ static void WriteOptimizationInfo(raw_ostream &Out, const User *U) {
|
||||
Out << " nsz";
|
||||
if (FPO->hasAllowReciprocal())
|
||||
Out << " arcp";
|
||||
if (FPO->hasAllowContract())
|
||||
Out << " contract";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,6 +204,11 @@ bool Instruction::hasAllowReciprocal() const {
|
||||
return cast<FPMathOperator>(this)->hasAllowReciprocal();
|
||||
}
|
||||
|
||||
bool Instruction::hasAllowContract() const {
|
||||
assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op");
|
||||
return cast<FPMathOperator>(this)->hasAllowContract();
|
||||
}
|
||||
|
||||
FastMathFlags Instruction::getFastMathFlags() const {
|
||||
assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op");
|
||||
return cast<FPMathOperator>(this)->getFastMathFlags();
|
||||
|
@ -74,6 +74,18 @@ entry:
|
||||
ret float %e
|
||||
}
|
||||
|
||||
; CHECK: @contract(
|
||||
define float @contract(float %x, float %y) {
|
||||
entry:
|
||||
; CHECK: %a = fsub contract float %x, %y
|
||||
%a = fsub contract float %x, %y
|
||||
; CHECK: %b = fadd contract float %x, %y
|
||||
%b = fadd contract float %x, %y
|
||||
; CHECK: %c = fmul contract float %a, %b
|
||||
%c = fmul contract float %a, %b
|
||||
ret float %c
|
||||
}
|
||||
|
||||
; CHECK: no_nan_inf
|
||||
define float @no_nan_inf(float %x, float %y) {
|
||||
entry:
|
||||
|
@ -760,6 +760,8 @@ define void @fastmathflags(float %op1, float %op2) {
|
||||
; CHECK: %f.nsz = fadd nsz float %op1, %op2
|
||||
%f.arcp = fadd arcp float %op1, %op2
|
||||
; CHECK: %f.arcp = fadd arcp float %op1, %op2
|
||||
%f.contract = fadd contract float %op1, %op2
|
||||
; CHECK: %f.contract = fadd contract float %op1, %op2
|
||||
%f.fast = fadd fast float %op1, %op2
|
||||
; CHECK: %f.fast = fadd fast float %op1, %op2
|
||||
ret void
|
||||
|
@ -207,7 +207,26 @@ TEST_F(IRBuilderTest, FastMathFlags) {
|
||||
EXPECT_TRUE(FCmp->hasAllowReciprocal());
|
||||
|
||||
Builder.clearFastMathFlags();
|
||||
|
||||
|
||||
// Test FP-contract
|
||||
FC = Builder.CreateFAdd(F, F);
|
||||
ASSERT_TRUE(isa<Instruction>(FC));
|
||||
FAdd = cast<Instruction>(FC);
|
||||
EXPECT_FALSE(FAdd->hasAllowContract());
|
||||
|
||||
FMF.clear();
|
||||
FMF.setAllowContract(true);
|
||||
Builder.setFastMathFlags(FMF);
|
||||
|
||||
FC = Builder.CreateFAdd(F, F);
|
||||
EXPECT_TRUE(Builder.getFastMathFlags().any());
|
||||
EXPECT_TRUE(Builder.getFastMathFlags().AllowContract);
|
||||
ASSERT_TRUE(isa<Instruction>(FC));
|
||||
FAdd = cast<Instruction>(FC);
|
||||
EXPECT_TRUE(FAdd->hasAllowContract());
|
||||
|
||||
Builder.clearFastMathFlags();
|
||||
|
||||
// Test a call with FMF.
|
||||
auto CalleeTy = FunctionType::get(Type::getFloatTy(Ctx),
|
||||
/*isVarArg=*/false);
|
||||
|
Loading…
Reference in New Issue
Block a user