[PATCH] D52839: Inform AST's UnaryOperator of FENV_ACCESS

2019-09-20 Thread Kevin P. Neal via Phabricator via cfe-commits
kpn abandoned this revision.
kpn added a comment.

I believe Serge Pavlov has demonstrated a better way to do this.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D52839/new/

https://reviews.llvm.org/D52839



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D52839: Inform AST's UnaryOperator of FENV_ACCESS

2019-01-25 Thread Kevin P. Neal via Phabricator via cfe-commits
kpn added a comment.

In D52839#1263794 , @rsmith wrote:

>




> 2. Track the FP environment somewhere more transient, probably on the `Scope` 
> object. When parsing an operator, store the environment on the expression, 
> and when performing a `TreeTransform`, inherit the state onto the new node.
> 
>   I think option 2 seems cleaner.

In D53157  it looks like an API where the 
IRBuilder has a constrained FP switch is preferred. This way calls to the 
IRBuilder can remain as one liners.

Going that route, would it make more sense to store the FP environment mode in 
some place like CompoundStmt so it gets set correctly when traversing the AST 
emitting IR? I'm not sure how TreeTransform would fit in here, though. The AST 
is supposed to be immutable once created, right? Can we set bits in a node 
after the node is created and before construction of the AST is completed?

Another wrinkle is that LLVM needs all FP in a function to be either 
constrained or non-constrained. This is to prevent code motion between the two 
modes. So clang would need to set the constrained mode someplace at function 
scope. I don't know the best place for that. And I'm not 100% sure that this 
requirement is set in stone yet. But where in the AST would be the proper place 
for that?

How does that change things?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D52839/new/

https://reviews.llvm.org/D52839



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D52839: Inform AST's UnaryOperator of FENV_ACCESS

2018-10-12 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith added a comment.

In https://reviews.llvm.org/D52839#1262449, @kpn wrote:

> I forgot to address the template question. I've spend the past 18 years doing 
> SystemZ backend work on multiple {,JIT} compilers. I'm not really in a 
> position to answer your question about how to handle getting these FP bits 
> down into C++ templates. I hope that won't hold up getting FENV_ACCESS 
> working for C compilations.


Actually, I think it should. If your approach doesn't extend to C++, then you 
have the wrong approach, and we should redesign it now rather than spend more 
time on it. (Also, we use TreeTransforms in C sometimes, too, so this actually 
isn't even a C++-specific design problem.)

I think there are two possible approaches to take here:

1. Treat the FP environment flags as a part of the global Sema state. Whenever 
Clang switches its current context, figure out the right FP environment for the 
new context, and switch the FP environment too. This'd necessitate storing the 
FP environment data on DeclContexts, which would likely otherwise be 
unnecessary.


https://reviews.llvm.org/D52839



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D52839: Inform AST's UnaryOperator of FENV_ACCESS

2018-10-12 Thread Kevin P. Neal via Phabricator via cfe-commits
kpn updated this revision to Diff 169464.
kpn added a comment.

Upload the correct diff this time. Sorry about the confusion!


https://reviews.llvm.org/D52839

Files:
  include/clang/AST/Expr.h
  lib/AST/ASTImporter.cpp
  lib/Analysis/BodyFarm.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/CodeGen/CGObjC.cpp
  lib/CodeGen/CGStmtOpenMP.cpp
  lib/Frontend/Rewrite/RewriteModernObjC.cpp
  lib/Frontend/Rewrite/RewriteObjC.cpp
  lib/Sema/SemaDeclCXX.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprObjC.cpp
  lib/Sema/SemaOverload.cpp
  lib/Sema/SemaPseudoObject.cpp
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  test/CodeGen/unary-con-fadd.c

Index: test/CodeGen/unary-con-fadd.c
===
--- test/CodeGen/unary-con-fadd.c
+++ test/CodeGen/unary-con-fadd.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+
+#pragma STDC FENV_ACCESS ON
+
+// Is FENV_ACCESS honored in a simple case?
+double test_1(double x) {
+// CHECK: test_1
+// CHECK: call double @llvm.experimental.constrained.fadd.f64
+  x++;
+  return x;
+}
Index: lib/Serialization/ASTWriterStmt.cpp
===
--- lib/Serialization/ASTWriterStmt.cpp
+++ lib/Serialization/ASTWriterStmt.cpp
@@ -517,6 +517,7 @@
   Record.push_back(E->getOpcode()); // FIXME: stable encoding
   Record.AddSourceLocation(E->getOperatorLoc());
   Record.push_back(E->canOverflow());
+  Record.push_back(E->getFPFeatures().getInt());
   Code = serialization::EXPR_UNARY_OPERATOR;
 }
 
Index: lib/Serialization/ASTReaderStmt.cpp
===
--- lib/Serialization/ASTReaderStmt.cpp
+++ lib/Serialization/ASTReaderStmt.cpp
@@ -603,6 +603,8 @@
   E->setOpcode((UnaryOperator::Opcode)Record.readInt());
   E->setOperatorLoc(ReadSourceLocation());
   E->setCanOverflow(Record.readInt());
+  FPOptions FPFeatures(Record.readInt());
+  E->setFPFeatures(FPFeatures);
 }
 
 void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
Index: lib/Sema/SemaPseudoObject.cpp
===
--- lib/Sema/SemaPseudoObject.cpp
+++ lib/Sema/SemaPseudoObject.cpp
@@ -133,7 +133,8 @@
  uop->getValueKind(),
  uop->getObjectKind(),
  uop->getOperatorLoc(),
- uop->canOverflow());
+ uop->canOverflow(),
+ FPOptions());
   }
 
   if (GenericSelectionExpr *gse = dyn_cast(e)) {
@@ -543,7 +544,7 @@
   !resultType->isDependentType()
   ? S.Context.getTypeSize(resultType) >=
 S.Context.getTypeSize(S.Context.IntTy)
-  : false);
+  : false, FPOptions());
   return complete(syntactic);
 }
 
@@ -1564,7 +1565,8 @@
   // Do nothing if the operand is dependent.
   if (op->isTypeDependent())
 return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
-   VK_RValue, OK_Ordinary, opcLoc, false);
+   VK_RValue, OK_Ordinary, opcLoc, false,
+   FPOptions());
 
   assert(UnaryOperator::isIncrementDecrementOp(opcode));
   Expr *opaqueRef = op->IgnoreParens();
@@ -1650,7 +1652,8 @@
 Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr());
 return new (Context) UnaryOperator(
 op, uop->getOpcode(), uop->getType(), uop->getValueKind(),
-uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow());
+uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow(),
+FPOptions());
   } else if (CompoundAssignOperator *cop
= dyn_cast(syntax)) {
 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
Index: lib/Sema/SemaOverload.cpp
===
--- lib/Sema/SemaOverload.cpp
+++ lib/Sema/SemaOverload.cpp
@@ -12146,7 +12146,8 @@
   if (Input->isTypeDependent()) {
 if (Fns.empty())
   return new (Context) UnaryOperator(Input, Opc, Context.DependentTy,
- VK_RValue, OK_Ordinary, OpLoc, false);
+ VK_RValue, OK_Ordinary, OpLoc, false,
+ FPFeatures);
 
 CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
 UnresolvedLookupExpr *Fn
@@ -13671,7 +13672,8 @@
 
 return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType,
VK_RValue, OK_Ordinary,
-   UnOp->getOperatorLoc(), false);
+   UnOp->getOperatorLoc(), false,
+ 

[PATCH] D52839: Inform AST's UnaryOperator of FENV_ACCESS

2018-10-12 Thread Roman Lebedev via Phabricator via cfe-commits
lebedev.ri added a comment.

I think you have uploaded the wrong patch here.


https://reviews.llvm.org/D52839



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D52839: Inform AST's UnaryOperator of FENV_ACCESS

2018-10-12 Thread Kevin P. Neal via Phabricator via cfe-commits
kpn updated this revision to Diff 169463.
kpn added a comment.

Address review comments.


https://reviews.llvm.org/D52839

Files:
  include/llvm/IR/IRBuilder.h

Index: include/llvm/IR/IRBuilder.h
===
--- include/llvm/IR/IRBuilder.h
+++ include/llvm/IR/IRBuilder.h
@@ -960,6 +960,30 @@
 return (LC && RC) ? Insert(Folder.CreateBinOp(Opc, LC, RC), Name) : nullptr;
   }
 
+  Value *getConstrainedRounding(MDNode *RoundingMD) {
+MDString *Rounding = nullptr;
+
+if (RoundingMD)
+  Rounding = cast(RoundingMD->getOperand(0));
+
+if (!Rounding)
+  Rounding = MDString::get(Context, "round.dynamic");
+
+return MetadataAsValue::get(Context, Rounding);
+  }
+
+  Value *getConstrainedExcept(MDNode *ExceptMD) {
+MDString *Except = nullptr;
+
+if (ExceptMD)
+  Except = cast(ExceptMD->getOperand(0));
+
+if (!Except)
+  Except = MDString::get(Context, "fpexcept.strict");
+
+return MetadataAsValue::get(Context, Except);
+  }
+
 public:
   Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "",
bool HasNUW = false, bool HasNSW = false) {
@@ -1177,6 +1201,19 @@
 return Insert(I, Name);
   }
 
+  Value *CreateConstrainedFAdd(Value *L, Value *R, const Twine &Name = "",
+MDNode *RoundingMD = nullptr, MDNode *ExceptMD = nullptr) {
+
+Value *Rounding = getConstrainedRounding(RoundingMD);
+Value *Except = getConstrainedExcept(ExceptMD);
+
+Value *F = Intrinsic::getDeclaration(
+BB->getModule(), Intrinsic::experimental_constrained_fadd,
+{L->getType()});
+
+return CreateCall(F, { L, R, Rounding, Except }, Name);
+  }
+
   Value *CreateFSub(Value *L, Value *R, const Twine &Name = "",
 MDNode *FPMD = nullptr) {
 if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V;
@@ -1194,6 +1231,19 @@
 return Insert(I, Name);
   }
 
+  Value *CreateConstrainedFSub(Value *L, Value *R, const Twine &Name = "",
+MDNode *RoundingMD = nullptr, MDNode *ExceptMD = nullptr) {
+ 
+Value *Rounding = getConstrainedRounding(RoundingMD);
+Value *Except = getConstrainedExcept(ExceptMD);
+
+Value *F = Intrinsic::getDeclaration(
+BB->getModule(), Intrinsic::experimental_constrained_fsub,
+{L->getType()});
+
+return CreateCall(F, { L, R, Rounding, Except });
+  }
+
   Value *CreateFMul(Value *L, Value *R, const Twine &Name = "",
 MDNode *FPMD = nullptr) {
 if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V;
@@ -1211,6 +1261,19 @@
 return Insert(I, Name);
   }
 
+  Value *CreateConstrainedFMul(Value *L, Value *R, const Twine &Name = "",
+MDNode *RoundingMD = nullptr, MDNode *ExceptMD = nullptr) {
+ 
+Value *Rounding = getConstrainedRounding(RoundingMD);
+Value *Except = getConstrainedExcept(ExceptMD);
+
+Value *F = Intrinsic::getDeclaration(
+BB->getModule(), Intrinsic::experimental_constrained_fmul,
+{L->getType()});
+
+return CreateCall(F, { L, R, Rounding, Except });
+  }
+
   Value *CreateFDiv(Value *L, Value *R, const Twine &Name = "",
 MDNode *FPMD = nullptr) {
 if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V;
@@ -1228,6 +1291,19 @@
 return Insert(I, Name);
   }
 
+  Value *CreateConstrainedFDiv(Value *L, Value *R, const Twine &Name = "",
+MDNode *RoundingMD = nullptr, MDNode *ExceptMD = nullptr) {
+ 
+Value *Rounding = getConstrainedRounding(RoundingMD);
+Value *Except = getConstrainedExcept(ExceptMD);
+
+Value *F = Intrinsic::getDeclaration(
+BB->getModule(), Intrinsic::experimental_constrained_fdiv,
+{L->getType()});
+
+return CreateCall(F, { L, R, Rounding, Except });
+  }
+
   Value *CreateFRem(Value *L, Value *R, const Twine &Name = "",
 MDNode *FPMD = nullptr) {
 if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V;
@@ -1245,6 +1321,19 @@
 return Insert(I, Name);
   }
 
+  Value *CreateConstrainedFRem(Value *L, Value *R, const Twine &Name = "",
+MDNode *RoundingMD = nullptr, MDNode *ExceptMD = nullptr) {
+ 
+Value *Rounding = getConstrainedRounding(RoundingMD);
+Value *Except = getConstrainedExcept(ExceptMD);
+
+Value *F = Intrinsic::getDeclaration(
+BB->getModule(), Intrinsic::experimental_constrained_frem,
+{L->getType()});
+
+return CreateCall(F, { L, R, Rounding, Except });
+  }
+
   Value *CreateBinOp(Instruction::BinaryOps Opc,
  Value *LHS, Value *RHS, const Twine &Name = "",
  MDNode *FPMathTag = nullptr) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D52839: Inform AST's UnaryOperator of FENV_ACCESS

2018-10-11 Thread Kevin P. Neal via Phabricator via cfe-commits
kpn added a comment.

I forgot to address the template question. I've spend the past 18 years doing 
SystemZ backend work on multiple {,JIT} compilers. I'm not really in a position 
to answer your question about how to handle getting these FP bits down into C++ 
templates. I hope that won't hold up getting FENV_ACCESS working for C 
compilations.


https://reviews.llvm.org/D52839



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D52839: Inform AST's UnaryOperator of FENV_ACCESS

2018-10-11 Thread Roman Lebedev via Phabricator via cfe-commits
lebedev.ri added inline comments.



Comment at: include/clang/AST/Expr.h:1791
+  // otherwise.
+  unsigned FPFeatures : 3;
+

Why as the first one, and not after `CanOverflow` ...



Comment at: include/clang/AST/Expr.h:1809
+Opc(opc), CanOverflow(CanOverflow), Loc(l), Val(input)
+{ FPFeatures = FPF.getInt(); }
 

.. then you should be able to init it in ctor initializer, not in the body.


https://reviews.llvm.org/D52839



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D52839: Inform AST's UnaryOperator of FENV_ACCESS

2018-10-11 Thread Kevin P. Neal via Phabricator via cfe-commits
kpn updated this revision to Diff 169266.
kpn added a comment.

Address review comments.

Add a test case. The test depends on https://reviews.llvm.org/D53157, but it 
reads easily enough. Richard, does this work for you?


https://reviews.llvm.org/D52839

Files:
  include/clang/AST/Expr.h
  lib/AST/ASTImporter.cpp
  lib/Analysis/BodyFarm.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/CodeGen/CGObjC.cpp
  lib/CodeGen/CGStmtOpenMP.cpp
  lib/Frontend/Rewrite/RewriteModernObjC.cpp
  lib/Frontend/Rewrite/RewriteObjC.cpp
  lib/Sema/SemaDeclCXX.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprObjC.cpp
  lib/Sema/SemaOverload.cpp
  lib/Sema/SemaPseudoObject.cpp
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  test/CodeGen/unary-con-fadd.c

Index: test/CodeGen/unary-con-fadd.c
===
--- test/CodeGen/unary-con-fadd.c
+++ test/CodeGen/unary-con-fadd.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+
+#pragma STDC FENV_ACCESS ON
+
+// Is FENV_ACCESS honored in a simple case?
+double test_1(double x) {
+// CHECK: test_1
+// CHECK: call double @llvm.experimental.constrained.fadd.f64
+  x++;
+  return x;
+}
Index: lib/Serialization/ASTWriterStmt.cpp
===
--- lib/Serialization/ASTWriterStmt.cpp
+++ lib/Serialization/ASTWriterStmt.cpp
@@ -517,6 +517,7 @@
   Record.push_back(E->getOpcode()); // FIXME: stable encoding
   Record.AddSourceLocation(E->getOperatorLoc());
   Record.push_back(E->canOverflow());
+  Record.push_back(E->getFPFeatures().getInt());
   Code = serialization::EXPR_UNARY_OPERATOR;
 }
 
Index: lib/Serialization/ASTReaderStmt.cpp
===
--- lib/Serialization/ASTReaderStmt.cpp
+++ lib/Serialization/ASTReaderStmt.cpp
@@ -603,6 +603,8 @@
   E->setOpcode((UnaryOperator::Opcode)Record.readInt());
   E->setOperatorLoc(ReadSourceLocation());
   E->setCanOverflow(Record.readInt());
+  FPOptions FPFeatures(Record.readInt());
+  E->setFPFeatures(FPFeatures);
 }
 
 void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
Index: lib/Sema/SemaPseudoObject.cpp
===
--- lib/Sema/SemaPseudoObject.cpp
+++ lib/Sema/SemaPseudoObject.cpp
@@ -133,7 +133,8 @@
  uop->getValueKind(),
  uop->getObjectKind(),
  uop->getOperatorLoc(),
- uop->canOverflow());
+ uop->canOverflow(),
+ FPOptions());
   }
 
   if (GenericSelectionExpr *gse = dyn_cast(e)) {
@@ -543,7 +544,7 @@
   !resultType->isDependentType()
   ? S.Context.getTypeSize(resultType) >=
 S.Context.getTypeSize(S.Context.IntTy)
-  : false);
+  : false, FPOptions());
   return complete(syntactic);
 }
 
@@ -1564,7 +1565,8 @@
   // Do nothing if the operand is dependent.
   if (op->isTypeDependent())
 return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
-   VK_RValue, OK_Ordinary, opcLoc, false);
+   VK_RValue, OK_Ordinary, opcLoc, false,
+   FPOptions());
 
   assert(UnaryOperator::isIncrementDecrementOp(opcode));
   Expr *opaqueRef = op->IgnoreParens();
@@ -1650,7 +1652,8 @@
 Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr());
 return new (Context) UnaryOperator(
 op, uop->getOpcode(), uop->getType(), uop->getValueKind(),
-uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow());
+uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow(),
+FPOptions());
   } else if (CompoundAssignOperator *cop
= dyn_cast(syntax)) {
 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
Index: lib/Sema/SemaOverload.cpp
===
--- lib/Sema/SemaOverload.cpp
+++ lib/Sema/SemaOverload.cpp
@@ -12146,7 +12146,8 @@
   if (Input->isTypeDependent()) {
 if (Fns.empty())
   return new (Context) UnaryOperator(Input, Opc, Context.DependentTy,
- VK_RValue, OK_Ordinary, OpLoc, false);
+ VK_RValue, OK_Ordinary, OpLoc, false,
+ FPFeatures);
 
 CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
 UnresolvedLookupExpr *Fn
@@ -13671,7 +13672,8 @@
 
 return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType,
VK_RValue, OK_Ordinary,
-   UnOp->getOperatorLoc(), false);
+

[PATCH] D52839: Inform AST's UnaryOperator of FENV_ACCESS

2018-10-03 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith added a comment.

Maybe take this very slightly further so it becomes testable: change the 
expression evaluator (lib/AST/ExprConstant.cpp) so it treats floating-point 
operations as non-constant if they're potentially-overflowing.

You also need to update lib/Serialization/AST{Reader,Writer}Stmt.cpp to 
round-trip this information through AST files.

How do you intend for this to work in template instantiation? Do we record the 
pragmas in the AST (and likewise for the state on entry to each function) so 
that we can rebuild the `FPOptions` during instantiation, or should we be 
inheriting the `FPOptions` from the expression in the template onto the 
expression in the instantiation? In the latter case, it would make more sense 
to me to track `FPOptions` on the `Scope` rather than as a `Sema` member, so 
that the state is more-obviously unavailable during template instantiation.




Comment at: include/clang/AST/Expr.h:1794-1796
+  // This is only meaningful for operations on floating point types and 0
+  // otherwise.
+  unsigned FPFeatures : 3;

Move this adjacent to the other bitfields so we don't spend 32 / 64 bits on it.


Repository:
  rC Clang

https://reviews.llvm.org/D52839



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D52839: Inform AST's UnaryOperator of FENV_ACCESS

2018-10-03 Thread Kevin P. Neal via Phabricator via cfe-commits
kpn created this revision.
kpn added a reviewer: rsmith.
Herald added a reviewer: javed.absar.
Herald added a subscriber: cfe-commits.

The UnaryOperator needs to know about #pragma FENV_ACCESS to eventually 
properly emit the constrained math intrinsics. This diff just gets the 
information about the pragma into that part of the AST.

The visible behavior of clang is unaffected and so this cannot yet be tested.


Repository:
  rC Clang

https://reviews.llvm.org/D52839

Files:
  include/clang/AST/Expr.h
  lib/AST/ASTImporter.cpp
  lib/Analysis/BodyFarm.cpp
  lib/CodeGen/CGObjC.cpp
  lib/CodeGen/CGStmtOpenMP.cpp
  lib/Frontend/Rewrite/RewriteModernObjC.cpp
  lib/Frontend/Rewrite/RewriteObjC.cpp
  lib/Sema/SemaDeclCXX.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprObjC.cpp
  lib/Sema/SemaOverload.cpp
  lib/Sema/SemaPseudoObject.cpp

Index: lib/Sema/SemaPseudoObject.cpp
===
--- lib/Sema/SemaPseudoObject.cpp
+++ lib/Sema/SemaPseudoObject.cpp
@@ -133,7 +133,8 @@
  uop->getValueKind(),
  uop->getObjectKind(),
  uop->getOperatorLoc(),
- uop->canOverflow());
+ uop->canOverflow(),
+ FPOptions());
   }
 
   if (GenericSelectionExpr *gse = dyn_cast(e)) {
@@ -543,7 +544,7 @@
   !resultType->isDependentType()
   ? S.Context.getTypeSize(resultType) >=
 S.Context.getTypeSize(S.Context.IntTy)
-  : false);
+  : false, FPOptions());
   return complete(syntactic);
 }
 
@@ -1564,7 +1565,8 @@
   // Do nothing if the operand is dependent.
   if (op->isTypeDependent())
 return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
-   VK_RValue, OK_Ordinary, opcLoc, false);
+   VK_RValue, OK_Ordinary, opcLoc, false,
+   FPOptions());
 
   assert(UnaryOperator::isIncrementDecrementOp(opcode));
   Expr *opaqueRef = op->IgnoreParens();
@@ -1650,7 +1652,8 @@
 Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr());
 return new (Context) UnaryOperator(
 op, uop->getOpcode(), uop->getType(), uop->getValueKind(),
-uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow());
+uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow(),
+FPOptions());
   } else if (CompoundAssignOperator *cop
= dyn_cast(syntax)) {
 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
Index: lib/Sema/SemaOverload.cpp
===
--- lib/Sema/SemaOverload.cpp
+++ lib/Sema/SemaOverload.cpp
@@ -12146,7 +12146,8 @@
   if (Input->isTypeDependent()) {
 if (Fns.empty())
   return new (Context) UnaryOperator(Input, Opc, Context.DependentTy,
- VK_RValue, OK_Ordinary, OpLoc, false);
+ VK_RValue, OK_Ordinary, OpLoc, false,
+ FPFeatures);
 
 CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
 UnresolvedLookupExpr *Fn
@@ -13671,7 +13672,8 @@
 
 return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType,
VK_RValue, OK_Ordinary,
-   UnOp->getOperatorLoc(), false);
+   UnOp->getOperatorLoc(), false,
+   FPFeatures);
   }
 }
 Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
@@ -13682,7 +13684,8 @@
 return new (Context) UnaryOperator(SubExpr, UO_AddrOf,
  Context.getPointerType(SubExpr->getType()),
VK_RValue, OK_Ordinary,
-   UnOp->getOperatorLoc(), false);
+   UnOp->getOperatorLoc(), false,
+   FPFeatures);
   }
 
   // C++ [except.spec]p17:
Index: lib/Sema/SemaExprObjC.cpp
===
--- lib/Sema/SemaExprObjC.cpp
+++ lib/Sema/SemaExprObjC.cpp
@@ -4307,7 +4307,8 @@
 Expr *sub = stripARCUnbridgedCast(uo->getSubExpr());
 return new (Context)
 UnaryOperator(sub, UO_Extension, sub->getType(), sub->getValueKind(),
-  sub->getObjectKind(), uo->getOperatorLoc(), false);
+  sub->getObjectKind(), uo->getOperatorLoc(), false,
+  FPFeatures);
   } else if (GenericSelectionExpr *gse = dyn_cast(e)) {
 assert(!gse->isResultDependent());
 
Index: lib/Sema/SemaE