Subject: [PATCH 7/7] Use "honor-fp-exceptions" function attribute

---
 lib/Target/TargetMachine.cpp                       |  1 +
 lib/Transforms/InstCombine/InstCombine.h           |  2 ++
 .../InstCombine/InstructionCombining.cpp           | 22 ++++++++++++++++------
 lib/Transforms/Utils/SimplifyCFG.cpp               | 13 +++++++++++--
 4 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp
index dcb8338..44fb521 100644
--- a/lib/Target/TargetMachine.cpp
+++ b/lib/Target/TargetMachine.cpp
@@ -68,6 +68,7 @@ void TargetMachine::resetTargetOptions(const MachineFunction *MF) const {
   RESET_OPTION(NoNaNsFPMath, "no-nans-fp-math");
   RESET_OPTION(UseSoftFloat, "use-soft-float");
   RESET_OPTION(DisableTailCalls, "disable-tail-calls");
+  RESET_OPTION(HonorFPExceptions, "honor-fp-exceptions");
 
   TO.MCOptions.SanitizeAddress = F->hasFnAttribute(Attribute::SanitizeAddress);
 }
diff --git a/lib/Transforms/InstCombine/InstCombine.h b/lib/Transforms/InstCombine/InstCombine.h
index 6c0d4e7..d18309d 100644
--- a/lib/Transforms/InstCombine/InstCombine.h
+++ b/lib/Transforms/InstCombine/InstCombine.h
@@ -102,6 +102,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner
   bool MadeIRChange;
   LibCallSimplifier *Simplifier;
   bool MinimizeSize;
+  bool HonorFPExceptions;
 
 public:
   /// Worklist - All of the instructions that need to be simplified.
@@ -115,6 +116,7 @@ public:
   static char ID; // Pass identification, replacement for typeid
   InstCombiner() : FunctionPass(ID), DL(nullptr), Builder(nullptr) {
     MinimizeSize = false;
+    HonorFPExceptions = false;
     initializeInstCombinerPass(*PassRegistry::getPassRegistry());
   }
 
diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp
index ac0c01e..270e086 100644
--- a/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2635,7 +2635,8 @@ static bool AddReachableCodeToWorklist(BasicBlock *BB,
                                        SmallPtrSetImpl<BasicBlock*> &Visited,
                                        InstCombiner &IC,
                                        const DataLayout *DL,
-                                       const TargetLibraryInfo *TLI) {
+                                       const TargetLibraryInfo *TLI,
+                                       bool HonorFPExceptions) {
   bool MadeIRChange = false;
   SmallVector<BasicBlock*, 256> Worklist;
   Worklist.push_back(BB);
@@ -2662,7 +2663,8 @@ static bool AddReachableCodeToWorklist(BasicBlock *BB,
 
       // ConstantProp instruction if trivially constant.
       if (!Inst->use_empty() && isa<Constant>(Inst->getOperand(0)))
-        if (Constant *C = ConstantFoldInstruction(Inst, DL, TLI)) {
+        if (Constant *C = ConstantFoldInstruction(Inst, DL, TLI,
+                                                  HonorFPExceptions)) {
           DEBUG(dbgs() << "IC: ConstFold to: " << *C << " from: "
                        << *Inst << '\n');
           Inst->replaceAllUsesWith(C);
@@ -2679,10 +2681,13 @@ static bool AddReachableCodeToWorklist(BasicBlock *BB,
           if (CE == nullptr) continue;
 
           Constant*& FoldRes = FoldedConstants[CE];
-          if (!FoldRes)
-            FoldRes = ConstantFoldConstantExpression(CE, DL, TLI);
-          if (!FoldRes)
+          if (!FoldRes) {
+            FoldRes = ConstantFoldConstantExpression(CE, DL, TLI,
+                                                     HonorFPExceptions);
+          }
+          if (!FoldRes) {
             FoldRes = CE;
+          }
 
           if (FoldRes != CE) {
             *i = FoldRes;
@@ -2748,7 +2753,7 @@ bool InstCombiner::DoOneIteration(Function &F, unsigned Iteration) {
     // track of which blocks we visit.
     SmallPtrSet<BasicBlock*, 64> Visited;
     MadeIRChange |= AddReachableCodeToWorklist(F.begin(), Visited, *this, DL,
-                                               TLI);
+                                               TLI, HonorFPExceptions);
 
     // Do a quick scan over the function.  If we find any blocks that are
     // unreachable, remove any instructions inside of them.  This prevents
@@ -2943,6 +2948,11 @@ bool InstCombiner::runOnFunction(Function &F) {
   MinimizeSize = F.getAttributes().hasAttribute(AttributeSet::FunctionIndex,
                                                 Attribute::MinSize);
 
+  // Target cares about IEEE754 conformant FP exceptions at run-time?
+  HonorFPExceptions = F.hasFnAttribute("honor-fp-exceptions") &&
+                      (F.getFnAttribute("honor-fp-exceptions")
+                        .getValueAsString() == "true");
+
   /// Builder - This is an IRBuilder that automatically inserts new
   /// instructions into the worklist when they are created.
   IRBuilder<true, TargetFolder, InstCombineIRInserter>
diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp
index c5205ce..d341afd 100644
--- a/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -1073,6 +1073,11 @@ HoistTerminator:
   if (isa<InvokeInst>(I1) && !isSafeToHoistInvoke(BB1, BB2, I1, I2))
     return Changed;
 
+  Function *F = BIParent->getParent();
+  bool HonorFPExceptions = F->hasFnAttribute("honor-fp-exceptions") &&
+                           (F->getFnAttribute("honor-fp-exceptions")
+                              .getValueAsString() == "true");
+
   for (succ_iterator SI = succ_begin(BB1), E = succ_end(BB1); SI != E; ++SI) {
     PHINode *PN;
     for (BasicBlock::iterator BBI = SI->begin();
@@ -1082,10 +1087,14 @@ HoistTerminator:
       if (BB1V == BB2V)
         continue;
 
-      if (isa<ConstantExpr>(BB1V) && !isSafeToSpeculativelyExecute(BB1V, DL))
+      if (isa<ConstantExpr>(BB1V) &&
+          !isSafeToSpeculativelyExecute(BB1V, DL, HonorFPExceptions)) {
         return Changed;
-      if (isa<ConstantExpr>(BB2V) && !isSafeToSpeculativelyExecute(BB2V, DL))
+      }
+      if (isa<ConstantExpr>(BB2V) &&
+          !isSafeToSpeculativelyExecute(BB2V, DL, HonorFPExceptions)) {
         return Changed;
+      }
     }
   }
 
-- 
1.8.4

