Add FP_CONTRACT support for clang.
Clang will now honor the FP_CONTRACT pragma and emit LLVM
fmuladd intrinsics for expressions of the form A * B + C (when they occur in a
single statement).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164989 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index dccce6e..b3836a2 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -7504,7 +7504,7 @@
= new (S.Context) BinaryOperator(IterationVarRefRVal,
IntegerLiteral::Create(S.Context, Upper, SizeType, Loc),
BO_NE, S.Context.BoolTy,
- VK_RValue, OK_Ordinary, Loc);
+ VK_RValue, OK_Ordinary, Loc, false);
// Create the pre-increment of the iteration variable.
Expr *Increment
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 0570dd3..75bc865 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -8416,7 +8416,8 @@
if (CompResultTy.isNull())
return Owned(new (Context) BinaryOperator(LHS.take(), RHS.take(), Opc,
- ResultTy, VK, OK, OpLoc));
+ ResultTy, VK, OK, OpLoc,
+ FPFeatures.fp_contract));
if (getLangOpts().CPlusPlus && LHS.get()->getObjectKind() !=
OK_ObjCProperty) {
VK = VK_LValue;
@@ -8424,7 +8425,8 @@
}
return Owned(new (Context) CompoundAssignOperator(LHS.take(), RHS.take(), Opc,
ResultTy, VK, OK, CompLHSTy,
- CompResultTy, OpLoc));
+ CompResultTy, OpLoc,
+ FPFeatures.fp_contract));
}
/// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 763ef28..ad4a17f 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -4833,7 +4833,8 @@
BO_Comma, BO->getType(),
BO->getValueKind(),
BO->getObjectKind(),
- BO->getOperatorLoc()));
+ BO->getOperatorLoc(),
+ BO->isFPContractable()));
}
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index e9c2c6c..10b96c9 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -9981,7 +9981,7 @@
llvm::makeArrayRef(Args, NumArgs),
Context.DependentTy,
VK_RValue,
- OpLoc));
+ OpLoc, false));
}
// Build an empty overload set.
@@ -10058,7 +10058,7 @@
CallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(),
llvm::makeArrayRef(Args, NumArgs),
- ResultTy, VK, OpLoc);
+ ResultTy, VK, OpLoc, false);
if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
FnDecl))
@@ -10159,7 +10159,8 @@
return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
Context.DependentTy,
VK_RValue, OK_Ordinary,
- OpLoc));
+ OpLoc,
+ FPFeatures.fp_contract));
return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc,
Context.DependentTy,
@@ -10167,7 +10168,8 @@
OK_Ordinary,
Context.DependentTy,
Context.DependentTy,
- OpLoc));
+ OpLoc,
+ FPFeatures.fp_contract));
}
// FIXME: save results of ADL from here?
@@ -10179,11 +10181,9 @@
NestedNameSpecifierLoc(), OpNameInfo,
/*ADL*/ true, IsOverloaded(Fns),
Fns.begin(), Fns.end());
- return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
- Args,
- Context.DependentTy,
- VK_RValue,
- OpLoc));
+ return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, Args,
+ Context.DependentTy, VK_RValue,
+ OpLoc, FPFeatures.fp_contract));
}
// Always do placeholder-like conversions on the RHS.
@@ -10298,7 +10298,8 @@
CXXOperatorCallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(),
- Args, ResultTy, VK, OpLoc);
+ Args, ResultTy, VK, OpLoc,
+ FPFeatures.fp_contract);
if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
FnDecl))
@@ -10430,7 +10431,7 @@
Args,
Context.DependentTy,
VK_RValue,
- RLoc));
+ RLoc, false));
}
// Handle placeholders on both operands.
@@ -10507,7 +10508,8 @@
CXXOperatorCallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
FnExpr.take(), Args,
- ResultTy, VK, RLoc);
+ ResultTy, VK, RLoc,
+ false);
if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall,
FnDecl))
@@ -11035,7 +11037,7 @@
CXXOperatorCallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn.take(),
llvm::makeArrayRef(MethodArgs, NumArgs+1),
- ResultTy, VK, RParenLoc);
+ ResultTy, VK, RParenLoc, false);
delete [] MethodArgs;
if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall,
@@ -11208,7 +11210,7 @@
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.take(),
- Base, ResultTy, VK, OpLoc);
+ Base, ResultTy, VK, OpLoc, false);
if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall,
Method))
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp
index 501fa11..22a24a9 100644
--- a/lib/Sema/SemaPseudoObject.cpp
+++ b/lib/Sema/SemaPseudoObject.cpp
@@ -356,7 +356,7 @@
syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS,
opcode, capturedRHS->getType(),
capturedRHS->getValueKind(),
- OK_Ordinary, opcLoc);
+ OK_Ordinary, opcLoc, false);
} else {
ExprResult opLHS = buildGet();
if (opLHS.isInvalid()) return ExprError();
@@ -375,7 +375,7 @@
OK_Ordinary,
opLHS.get()->getType(),
result.get()->getType(),
- opcLoc);
+ opcLoc, false);
}
// The result of the assignment, if not void, is the value set into
@@ -1366,7 +1366,7 @@
// Do nothing if either argument is dependent.
if (LHS->isTypeDependent() || RHS->isTypeDependent())
return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,
- VK_RValue, OK_Ordinary, opcLoc);
+ VK_RValue, OK_Ordinary, opcLoc, false);
// Filter out non-overload placeholder types in the RHS.
if (RHS->getType()->isNonOverloadPlaceholderType()) {
@@ -1437,14 +1437,14 @@
cop->getObjectKind(),
cop->getComputationLHSType(),
cop->getComputationResultType(),
- cop->getOperatorLoc());
+ cop->getOperatorLoc(), false);
} else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {
Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS());
Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr();
return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(),
bop->getType(), bop->getValueKind(),
bop->getObjectKind(),
- bop->getOperatorLoc());
+ bop->getOperatorLoc(), false);
} else {
assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject));
return stripOpaqueValuesFromPseudoObjectRef(*this, syntax);
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index e0451c4..f76c947 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -6429,6 +6429,9 @@
RHS.get() == E->getRHS())
return SemaRef.Owned(E);
+ Sema::FPContractStateRAII FPContractState(getSema());
+ getSema().FPFeatures.fp_contract = E->isFPContractable();
+
return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(),
LHS.get(), RHS.get());
}
@@ -6852,6 +6855,9 @@
(E->getNumArgs() != 2 || Second.get() == E->getArg(1)))
return SemaRef.MaybeBindToTemporary(E);
+ Sema::FPContractStateRAII FPContractState(getSema());
+ getSema().FPFeatures.fp_contract = E->isFPContractable();
+
return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(),
E->getOperatorLoc(),
Callee.get(),