summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorMelanie Blower <melanie.blower@intel.com>2019-12-04 12:23:46 -0800
committerMelanie Blower <melanie.blower@intel.com>2019-12-05 03:48:04 -0800
commit7f9b5138470db1dc58f3bc05631284c653c9ed7a (patch)
tree6df6dcd5ce5f7d56fcef6e72ab2c3f287bce860e /clang/lib
parentc16f0b18c13e88fedaa510bc2442bb693a6230c8 (diff)
downloadbcm5719-llvm-7f9b5138470db1dc58f3bc05631284c653c9ed7a.tar.gz
bcm5719-llvm-7f9b5138470db1dc58f3bc05631284c653c9ed7a.zip
Reapply af57dbf12e54 "Add support for options -frounding-math, ftrapping-math, -ffp-model=, and -ffp-exception-behavior="
Patch was reverted because https://bugs.llvm.org/show_bug.cgi?id=44048 The original patch is modified to set the strictfp IR attribute explicitly in CodeGen instead of as a side effect of IRBuilder. In the 2nd attempt to reapply there was a windows lit test fail, the tests were fixed to use wildcard matching. Differential Revision: https://reviews.llvm.org/D62731
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Decl.cpp1
-rw-r--r--clang/lib/CodeGen/CGCall.cpp14
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp52
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h3
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp205
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp28
-rw-r--r--clang/lib/Sema/SemaExpr.cpp10
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp1
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp1
9 files changed, 306 insertions, 9 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index bfcf7926861..0301110b706 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2793,6 +2793,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
FunctionDeclBits.ConstexprKind = ConstexprKind;
FunctionDeclBits.InstantiationIsPending = false;
FunctionDeclBits.UsesSEHTry = false;
+ FunctionDeclBits.UsesFPIntrin = false;
FunctionDeclBits.HasSkippedBody = false;
FunctionDeclBits.WillHaveBody = false;
FunctionDeclBits.IsMultiVersion = false;
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index ca6b1d409c2..657c9260e6e 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -4336,6 +4336,13 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Callee.getAbstractInfo(), Attrs, CallingConv,
/*AttrOnCallSite=*/true);
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl))
+ if (FD->usesFPIntrin())
+ // All calls within a strictfp function are marked strictfp
+ Attrs =
+ Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex,
+ llvm::Attribute::StrictFP);
+
// Apply some call-site-specific attributes.
// TODO: work this into building the attribute set.
@@ -4385,6 +4392,13 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
SmallVector<llvm::OperandBundleDef, 1> BundleList =
getBundlesForFunclet(CalleePtr);
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl))
+ if (FD->usesFPIntrin())
+ // All calls within a strictfp function are marked strictfp
+ Attrs =
+ Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex,
+ llvm::Attribute::StrictFP);
+
// Emit the actual call/invoke instruction.
llvm::CallBase *CI;
if (!InvokeDest) {
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 7f3be896a7b..fd3020835a4 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -33,6 +33,8 @@
#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
+#include "llvm/IR/FPEnv.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Operator.h"
@@ -87,6 +89,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
FMF.setAllowReassoc();
}
Builder.setFastMathFlags(FMF);
+ SetFPModel();
}
CodeGenFunction::~CodeGenFunction() {
@@ -102,6 +105,51 @@ CodeGenFunction::~CodeGenFunction() {
CGM.getOpenMPRuntime().functionFinished(*this);
}
+// Map the LangOption for rounding mode into
+// the corresponding enum in the IR.
+static llvm::fp::RoundingMode ToConstrainedRoundingMD(
+ LangOptions::FPRoundingModeKind Kind) {
+
+ switch (Kind) {
+ case LangOptions::FPR_ToNearest: return llvm::fp::rmToNearest;
+ case LangOptions::FPR_Downward: return llvm::fp::rmDownward;
+ case LangOptions::FPR_Upward: return llvm::fp::rmUpward;
+ case LangOptions::FPR_TowardZero: return llvm::fp::rmTowardZero;
+ case LangOptions::FPR_Dynamic: return llvm::fp::rmDynamic;
+ }
+ llvm_unreachable("Unsupported FP RoundingMode");
+}
+
+// Map the LangOption for exception behavior into
+// the corresponding enum in the IR.
+static llvm::fp::ExceptionBehavior ToConstrainedExceptMD(
+ LangOptions::FPExceptionModeKind Kind) {
+
+ switch (Kind) {
+ case LangOptions::FPE_Ignore: return llvm::fp::ebIgnore;
+ case LangOptions::FPE_MayTrap: return llvm::fp::ebMayTrap;
+ case LangOptions::FPE_Strict: return llvm::fp::ebStrict;
+ }
+ llvm_unreachable("Unsupported FP Exception Behavior");
+}
+
+void CodeGenFunction::SetFPModel() {
+ auto fpRoundingMode = ToConstrainedRoundingMD(
+ getLangOpts().getFPRoundingMode());
+ auto fpExceptionBehavior = ToConstrainedExceptMD(
+ getLangOpts().getFPExceptionMode());
+
+ if (fpExceptionBehavior == llvm::fp::ebIgnore &&
+ fpRoundingMode == llvm::fp::rmToNearest)
+ // Constrained intrinsics are not used.
+ ;
+ else {
+ Builder.setIsFPConstrained(true);
+ Builder.setDefaultConstrainedRounding(fpRoundingMode);
+ Builder.setDefaultConstrainedExcept(fpExceptionBehavior);
+ }
+}
+
CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T,
LValueBaseInfo *BaseInfo,
TBAAAccessInfo *TBAAInfo) {
@@ -823,6 +871,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
if (FD->isMain())
Fn->addFnAttr(llvm::Attribute::NoRecurse);
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
+ if (FD->usesFPIntrin())
+ Fn->addFnAttr(llvm::Attribute::StrictFP);
+
// If a custom alignment is used, force realigning to this alignment on
// any main function which certainly will need it.
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 7a2627ccf58..8f99b090b81 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4169,6 +4169,9 @@ public:
/// point operation, expressed as the maximum relative error in ulp.
void SetFPAccuracy(llvm::Value *Val, float Accuracy);
+ /// SetFPModel - Control floating point behavior via fp-model settings.
+ void SetFPModel();
+
private:
llvm::MDNode *getRangeForLoadFromType(QualType Ty);
void EmitReturnOfRValue(RValue RV, QualType Ty);
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 03a6de81204..5f8c0cb8a2c 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -2302,9 +2302,18 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
bool AssociativeMath = false;
bool ReciprocalMath = false;
bool SignedZeros = true;
- bool TrappingMath = true;
+ bool TrappingMath = false; // Implemented via -ffp-exception-behavior
+ bool TrappingMathPresent = false; // Is trapping-math in args, and not
+ // overriden by ffp-exception-behavior?
+ bool RoundingFPMath = false;
+ bool RoundingMathPresent = false; // Is rounding-math in args?
+ // -ffp-model values: strict, fast, precise
+ StringRef FPModel = "";
+ // -ffp-exception-behavior options: strict, maytrap, ignore
+ StringRef FPExceptionBehavior = "";
StringRef DenormalFPMath = "";
StringRef FPContract = "";
+ bool StrictFPModel = false;
if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
CmdArgs.push_back("-mlimit-float-precision");
@@ -2312,7 +2321,73 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
}
for (const Arg *A : Args) {
- switch (A->getOption().getID()) {
+ auto optID = A->getOption().getID();
+ bool PreciseFPModel = false;
+ switch (optID) {
+ default:
+ break;
+ case options::OPT_frounding_math:
+ case options::OPT_ftrapping_math:
+ case options::OPT_ffp_exception_behavior_EQ:
+ D.Diag(clang::diag::warn_drv_experimental_fp_control_incomplete_opt)
+ << A->getOption().getName();
+ break;
+ case options::OPT_ffp_model_EQ: {
+ D.Diag(clang::diag::warn_drv_experimental_fp_control_incomplete_opt)
+ << A->getOption().getName();
+ // If -ffp-model= is seen, reset to fno-fast-math
+ HonorINFs = true;
+ HonorNaNs = true;
+ // Turning *off* -ffast-math restores the toolchain default.
+ MathErrno = TC.IsMathErrnoDefault();
+ AssociativeMath = false;
+ ReciprocalMath = false;
+ SignedZeros = true;
+ // -fno_fast_math restores default denormal and fpcontract handling
+ DenormalFPMath = "";
+ FPContract = "";
+ StringRef Val = A->getValue();
+ if (OFastEnabled && !Val.equals("fast")) {
+ // Only -ffp-model=fast is compatible with OFast, ignore.
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << Args.MakeArgString("-ffp-model=" + Val)
+ << "-Ofast";
+ break;
+ }
+ StrictFPModel = false;
+ PreciseFPModel = true;
+ // ffp-model= is a Driver option, it is entirely rewritten into more
+ // granular options before being passed into cc1.
+ // Use the gcc option in the switch below.
+ if (!FPModel.empty() && !FPModel.equals(Val)) {
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << Args.MakeArgString("-ffp-model=" + FPModel)
+ << Args.MakeArgString("-ffp-model=" + Val);
+ FPContract = "";
+ }
+ if (Val.equals("fast")) {
+ optID = options::OPT_ffast_math;
+ FPModel = Val;
+ FPContract = "fast";
+ } else if (Val.equals("precise")) {
+ optID = options::OPT_ffp_contract;
+ FPModel = Val;
+ FPContract = "fast";
+ PreciseFPModel = true;
+ } else if (Val.equals("strict")) {
+ StrictFPModel = true;
+ optID = options::OPT_frounding_math;
+ FPExceptionBehavior = "strict";
+ FPModel = Val;
+ TrappingMath = true;
+ } else
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ break;
+ }
+ }
+
+ switch (optID) {
// If this isn't an FP option skip the claim below
default: continue;
@@ -2329,20 +2404,83 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
case options::OPT_fno_reciprocal_math: ReciprocalMath = false; break;
case options::OPT_fsigned_zeros: SignedZeros = true; break;
case options::OPT_fno_signed_zeros: SignedZeros = false; break;
- case options::OPT_ftrapping_math: TrappingMath = true; break;
- case options::OPT_fno_trapping_math: TrappingMath = false; break;
+ case options::OPT_ftrapping_math:
+ if (!TrappingMathPresent && !FPExceptionBehavior.empty() &&
+ !FPExceptionBehavior.equals("strict"))
+ // Warn that previous value of option is overridden.
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << Args.MakeArgString("-ffp-exception-behavior=" + FPExceptionBehavior)
+ << "-ftrapping-math";
+ TrappingMath = true;
+ TrappingMathPresent = true;
+ FPExceptionBehavior = "strict";
+ break;
+ case options::OPT_fno_trapping_math:
+ if (!TrappingMathPresent && !FPExceptionBehavior.empty() &&
+ !FPExceptionBehavior.equals("ignore"))
+ // Warn that previous value of option is overridden.
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << Args.MakeArgString("-ffp-exception-behavior=" + FPExceptionBehavior)
+ << "-fno-trapping-math";
+ TrappingMath = false;
+ TrappingMathPresent = true;
+ FPExceptionBehavior = "ignore";
+ break;
+
+ case options::OPT_frounding_math:
+ RoundingFPMath = true;
+ RoundingMathPresent = true;
+ break;
+
+ case options::OPT_fno_rounding_math:
+ RoundingFPMath = false;
+ RoundingMathPresent = false;
+ break;
case options::OPT_fdenormal_fp_math_EQ:
DenormalFPMath = A->getValue();
break;
- // Validate and pass through -fp-contract option.
+ // Validate and pass through -ffp-contract option.
case options::OPT_ffp_contract: {
StringRef Val = A->getValue();
- if (Val == "fast" || Val == "on" || Val == "off")
+ if (PreciseFPModel) {
+ // -ffp-model=precise enables ffp-contract=fast as a side effect
+ // the FPContract value has already been set to a string literal
+ // and the Val string isn't a pertinent value.
+ ;
+ } else if (Val.equals("fast") || Val.equals("on") || Val.equals("off"))
FPContract = Val;
else
D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ break;
+ }
+
+ // Validate and pass through -ffp-model option.
+ case options::OPT_ffp_model_EQ:
+ // This should only occur in the error case
+ // since the optID has been replaced by a more granular
+ // floating point option.
+ break;
+
+ // Validate and pass through -ffp-exception-behavior option.
+ case options::OPT_ffp_exception_behavior_EQ: {
+ StringRef Val = A->getValue();
+ if (!TrappingMathPresent && !FPExceptionBehavior.empty() &&
+ !FPExceptionBehavior.equals(Val))
+ // Warn that previous value of option is overridden.
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << Args.MakeArgString("-ffp-exception-behavior=" + FPExceptionBehavior)
+ << Args.MakeArgString("-ffp-exception-behavior=" + Val);
+ TrappingMath = TrappingMathPresent = false;
+ if (Val.equals("ignore") || Val.equals("maytrap"))
+ FPExceptionBehavior = Val;
+ else if (Val.equals("strict")) {
+ FPExceptionBehavior = Val;
+ TrappingMath = TrappingMathPresent = true;
+ } else
+ D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Val;
break;
}
@@ -2361,12 +2499,14 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
ReciprocalMath = true;
SignedZeros = false;
TrappingMath = false;
+ FPExceptionBehavior = "";
break;
case options::OPT_fno_unsafe_math_optimizations:
AssociativeMath = false;
ReciprocalMath = false;
SignedZeros = true;
TrappingMath = true;
+ FPExceptionBehavior = "strict";
// -fno_unsafe_math_optimizations restores default denormal handling
DenormalFPMath = "";
break;
@@ -2384,6 +2524,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
ReciprocalMath = true;
SignedZeros = false;
TrappingMath = false;
+ RoundingFPMath = false;
// If fast-math is set then set the fp-contract mode to fast.
FPContract = "fast";
break;
@@ -2397,12 +2538,31 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
AssociativeMath = false;
ReciprocalMath = false;
SignedZeros = true;
- TrappingMath = true;
+ TrappingMath = false;
+ RoundingFPMath = false;
// -fno_fast_math restores default denormal and fpcontract handling
DenormalFPMath = "";
FPContract = "";
break;
}
+ if (StrictFPModel) {
+ // If -ffp-model=strict has been specified on command line but
+ // subsequent options conflict then emit warning diagnostic.
+ if (HonorINFs && HonorNaNs &&
+ !AssociativeMath && !ReciprocalMath &&
+ SignedZeros && TrappingMath && RoundingFPMath &&
+ DenormalFPMath.empty() && FPContract.empty())
+ // OK: Current Arg doesn't conflict with -ffp-model=strict
+ ;
+ else {
+ StrictFPModel = false;
+ FPModel = "";
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << "-ffp-model=strict" <<
+ ((A->getNumValues() == 0) ? A->getSpelling()
+ : Args.MakeArgString(A->getSpelling() + A->getValue()));
+ }
+ }
// If we handled this option claim it
A->claim();
@@ -2430,7 +2590,11 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
if (ReciprocalMath)
CmdArgs.push_back("-freciprocal-math");
- if (!TrappingMath)
+ if (TrappingMath) {
+ // FP Exception Behavior is also set to strict
+ assert(FPExceptionBehavior.equals("strict"));
+ CmdArgs.push_back("-ftrapping-math");
+ } else if (TrappingMathPresent)
CmdArgs.push_back("-fno-trapping-math");
if (!DenormalFPMath.empty())
@@ -2440,14 +2604,37 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
if (!FPContract.empty())
CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + FPContract));
+ if (!RoundingFPMath)
+ CmdArgs.push_back(Args.MakeArgString("-fno-rounding-math"));
+
+ if (RoundingFPMath && RoundingMathPresent)
+ CmdArgs.push_back(Args.MakeArgString("-frounding-math"));
+
+ if (!FPExceptionBehavior.empty())
+ CmdArgs.push_back(Args.MakeArgString("-ffp-exception-behavior=" +
+ FPExceptionBehavior));
+
ParseMRecip(D, Args, CmdArgs);
// -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for the
// individual features enabled by -ffast-math instead of the option itself as
// that's consistent with gcc's behaviour.
if (!HonorINFs && !HonorNaNs && !MathErrno && AssociativeMath &&
- ReciprocalMath && !SignedZeros && !TrappingMath)
+ ReciprocalMath && !SignedZeros && !TrappingMath && !RoundingFPMath) {
CmdArgs.push_back("-ffast-math");
+ if (FPModel.equals("fast")) {
+ if (FPContract.equals("fast"))
+ // All set, do nothing.
+ ;
+ else if (FPContract.empty())
+ // Enable -ffp-contract=fast
+ CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
+ else
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << "-ffp-model=fast"
+ << Args.MakeArgString("-ffp-contract=" + FPContract);
+ }
+ }
// Handle __FINITE_MATH_ONLY__ similarly.
if (!HonorINFs && !HonorNaNs)
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 74831e78d8c..198ae69b765 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3145,6 +3145,34 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
}
+ LangOptions::FPRoundingModeKind FPRM = LangOptions::FPR_ToNearest;
+ if (Args.hasArg(OPT_frounding_math)) {
+ FPRM = LangOptions::FPR_Dynamic;
+ }
+ Opts.setFPRoundingMode(FPRM);
+
+ if (Args.hasArg(OPT_ftrapping_math)) {
+ Opts.setFPExceptionMode(LangOptions::FPE_Strict);
+ }
+
+ if (Args.hasArg(OPT_fno_trapping_math)) {
+ Opts.setFPExceptionMode(LangOptions::FPE_Ignore);
+ }
+
+ LangOptions::FPExceptionModeKind FPEB = LangOptions::FPE_Ignore;
+ if (Arg *A = Args.getLastArg(OPT_ffp_exception_behavior_EQ)) {
+ StringRef Val = A->getValue();
+ if (Val.equals("ignore"))
+ FPEB = LangOptions::FPE_Ignore;
+ else if (Val.equals("maytrap"))
+ FPEB = LangOptions::FPE_MayTrap;
+ else if (Val.equals("strict"))
+ FPEB = LangOptions::FPE_Strict;
+ else
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
+ }
+ Opts.setFPExceptionMode(FPEB);
+
Opts.RetainCommentsFromSystemHeaders =
Args.hasArg(OPT_fretain_comments_from_system_headers);
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 7bbda127a54..c53a4b789be 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -13037,6 +13037,16 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
if (ResultTy.isNull() || LHS.isInvalid() || RHS.isInvalid())
return ExprError();
+ if (ResultTy->isRealFloatingType() &&
+ (getLangOpts().getFPRoundingMode() != LangOptions::FPR_ToNearest ||
+ getLangOpts().getFPExceptionMode() != LangOptions::FPE_Ignore))
+ // Mark the current function as usng floating point constrained intrinsics
+ if (FunctionDecl *F = dyn_cast<FunctionDecl>(CurContext))
+{
+ F->setUsesFPIntrin(true);
+ printf("Enclosing function uses fp intrinsics\n");
+}
+
// Some of the binary operations require promoting operands of half vector to
// float vectors and truncating the result back to half vector. For now, we do
// this only when HalfArgsAndReturn is set (that is, when the target is arm or
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 3f7a1ed7fd5..d989f46c4ab 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -886,6 +886,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FD->ODRHash = Record.readInt();
FD->setHasODRHash(true);
+ FD->setUsesFPIntrin(Record.readInt());
switch ((FunctionDecl::TemplatedKind)Record.readInt()) {
case FunctionDecl::TK_NonTemplate:
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 51902a607ca..38eb64e52e4 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -559,6 +559,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
Record.AddSourceLocation(D->getEndLoc());
Record.push_back(D->getODRHash());
+ Record.push_back(D->usesFPIntrin());
Record.push_back(D->getTemplatedKind());
switch (D->getTemplatedKind()) {
OpenPOWER on IntegriCloud