[PATCH] Flag to enable IEEE-754 friendly FP optimizations
Sergey Dmitrouk
sdmitrouk at accesssoftek.com
Fri Oct 31 09:19:40 PDT 2014
Ping. Rebased patches with a fix for a typo (in code, not in comments) are
attached.
Hal, do I get it right that what you suggest can be implemented in
Instruction::mayReadFromMemory() and Instruction::mayWriteToMemory() to
get desired behaviour in wider range of usages?
Thanks,
Sergey
On Fri, Oct 24, 2014 at 09:24:48AM -0700, Stephen Canon wrote:
> On Oct 24, 2014, at 12:23 PM, Hal Finkel <hfinkel at anl.gov> wrote:
>
> ----- Original Message -----
>
> From: "Stephen Canon" <scanon at apple.com>
> To: "Hal Finkel" <hfinkel at anl.gov>
> Cc: "Sergey Dmitrouk" <sdmitrouk at accesssoftek.com>, "llvm-commits"
> <llvm-commits at cs.uiuc.edu>, "Owen Anderson"
> <owen at apple.com>
> Sent: Friday, October 24, 2014 11:13:10 AM
> Subject: Re: [PATCH] Flag to enable IEEE-754 friendly FP optimizations
>
> As a necessary piece of building support for FENV_ACCESS, yes, I
> think this is worth pursuing. Note, however, that actually
> providing full FENV_ACCESS support is likely to be a significant
> undertaking, and I expect that the pieces that go into it are
> basically useless until all of them are in place. Thata**s not to say
> that it isna**t worth doing, just that ita**s a big thankless job.
>
> Steve, so long as you're willing to serve as the expert reviewer here,
> I'm happy to help move this forward as well. We should, however,
> probably have a plan for the rest of it. Maybe this is as simple as:
> when FP exceptions are enabled, we treat all FP operations as if they
> might write to memory (except that AA confirms that they don't actually
> alias with any address in particular, but we say nothing about function
> calls). What do you think?
>
> From a numerical point of view, something along those lines could be
> workable, yes.
> a** Steve
-------------- next part --------------
>From 2caf27cfa48029dd315bcd51e95d53515992e9b4 Mon Sep 17 00:00:00 2001
From: Sergey Dmitrouk <sdmitrouk at accesssoftek.com>
Date: Thu, 25 Sep 2014 11:38:14 +0300
Subject: [PATCH 01/11] Add HonorFPExceptions flag to TargetOptions
---
include/llvm/Target/TargetOptions.h | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h
index f7df921..e20fc36 100644
--- a/include/llvm/Target/TargetOptions.h
+++ b/include/llvm/Target/TargetOptions.h
@@ -62,7 +62,7 @@ namespace llvm {
TargetOptions()
: PrintMachineCode(false), NoFramePointerElim(false),
LessPreciseFPMADOption(false), UnsafeFPMath(false),
- NoInfsFPMath(false), NoNaNsFPMath(false),
+ NoInfsFPMath(false), NoNaNsFPMath(false), HonorFPExceptions(false),
HonorSignDependentRoundingFPMathOption(false), UseSoftFloat(false),
NoZerosInBSS(false), JITEmitDebugInfo(false),
JITEmitDebugInfoToDisk(false), GuaranteedTailCallOpt(false),
@@ -117,6 +117,11 @@ namespace llvm {
/// assume the FP arithmetic arguments and results are never NaNs.
unsigned NoNaNsFPMath : 1;
+ /// HonorFPExceptions - This flag is enabled when code relies on
+ /// availability of floating point exceptions at run-time, thus such
+ /// operations should not be replaced with their results at compile-time.
+ unsigned HonorFPExceptions : 1;
+
/// HonorSignDependentRoundingFPMath - This returns true when the
/// -enable-sign-dependent-rounding-fp-math is specified. If this returns
/// false (the default), the code generator is allowed to assume that the
--
1.8.4
-------------- next part --------------
>From afec5b48cc94866ad4fe9315034c8e6e5d4fa6d0 Mon Sep 17 00:00:00 2001
From: Sergey Dmitrouk <sdmitrouk at accesssoftek.com>
Date: Thu, 25 Sep 2014 11:40:10 +0300
Subject: [PATCH 02/11] Consider HonorFPExceptions flag in SelectionDAG
---
include/llvm/CodeGen/SelectionDAG.h | 5 +++++
lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 28 ++++++++++++++++++++--------
2 files changed, 25 insertions(+), 8 deletions(-)
diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h
index ade7e56..008f90e 100644
--- a/include/llvm/CodeGen/SelectionDAG.h
+++ b/include/llvm/CodeGen/SelectionDAG.h
@@ -1248,6 +1248,11 @@ private:
SDValue N1, SDValue N2, bool nuw, bool nsw,
bool exact);
+ /// Checks whether it's safe to replace floating point operation with it's
+ /// result. UnsafeOps is bit mask of unacceptable exceptions.
+ bool isSafeToOptimizeFPOp(APFloat::opStatus s,
+ APFloat::opStatus UnsafeOps) const;
+
/// VTList - List of non-single value types.
FoldingSet<SDVTListNode> VTListMap;
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 7fb7aba..990f52c 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -3381,7 +3381,6 @@ SDValue SelectionDAG::getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1,
}
// Constant fold FP operations.
- bool HasFPExceptions = TLI->hasFloatingPointExceptions();
ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1.getNode());
ConstantFPSDNode *N2CFP = dyn_cast<ConstantFPSDNode>(N2.getNode());
if (N1CFP) {
@@ -3395,30 +3394,32 @@ SDValue SelectionDAG::getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1,
switch (Opcode) {
case ISD::FADD:
s = V1.add(V2, APFloat::rmNearestTiesToEven);
- if (!HasFPExceptions || s != APFloat::opInvalidOp)
+ if (isSafeToOptimizeFPOp(s, APFloat::opInvalidOp))
return getConstantFP(V1, VT);
break;
case ISD::FSUB:
s = V1.subtract(V2, APFloat::rmNearestTiesToEven);
- if (!HasFPExceptions || s!=APFloat::opInvalidOp)
+ if (isSafeToOptimizeFPOp(s, APFloat::opInvalidOp))
return getConstantFP(V1, VT);
break;
case ISD::FMUL:
s = V1.multiply(V2, APFloat::rmNearestTiesToEven);
- if (!HasFPExceptions || s!=APFloat::opInvalidOp)
+ if (isSafeToOptimizeFPOp(s, APFloat::opInvalidOp))
return getConstantFP(V1, VT);
break;
case ISD::FDIV:
s = V1.divide(V2, APFloat::rmNearestTiesToEven);
- if (!HasFPExceptions || (s!=APFloat::opInvalidOp &&
- s!=APFloat::opDivByZero)) {
+ if (isSafeToOptimizeFPOp(s,
+ (APFloat::opStatus)(APFloat::opInvalidOp |
+ APFloat::opDivByZero))) {
return getConstantFP(V1, VT);
}
break;
case ISD::FREM :
s = V1.mod(V2, APFloat::rmNearestTiesToEven);
- if (!HasFPExceptions || (s!=APFloat::opInvalidOp &&
- s!=APFloat::opDivByZero)) {
+ if (isSafeToOptimizeFPOp(s,
+ (APFloat::opStatus)(APFloat::opInvalidOp |
+ APFloat::opDivByZero))) {
return getConstantFP(V1, VT);
}
break;
@@ -3541,6 +3542,17 @@ SDValue SelectionDAG::getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1,
return SDValue(N, 0);
}
+bool SelectionDAG::isSafeToOptimizeFPOp(APFloat::opStatus s,
+ APFloat::opStatus UnsafeOps) const {
+ if (!TLI->hasFloatingPointExceptions()) {
+ return true;
+ }
+ if (getTarget().Options.HonorFPExceptions) {
+ return s == APFloat::opOK;
+ }
+ return (s & UnsafeOps) == APFloat::opOK;
+}
+
SDValue SelectionDAG::getNode(unsigned Opcode, SDLoc DL, EVT VT,
SDValue N1, SDValue N2, SDValue N3) {
// Perform various simplifications.
--
1.8.4
-------------- next part --------------
>From 2b2200c97fe25600b542e6ab9ca6d3cccef70805 Mon Sep 17 00:00:00 2001
From: Sergey Dmitrouk <sdmitrouk at accesssoftek.com>
Date: Thu, 25 Sep 2014 11:44:51 +0300
Subject: [PATCH 03/11] Skip constant folding to preserve FP exceptions
---
include/llvm/Analysis/ValueTracking.h | 3 +-
include/llvm/IR/Constant.h | 2 +-
include/llvm/IR/Constants.h | 4 ++
lib/Analysis/ValueTracking.cpp | 13 +++++-
lib/IR/ConstantFold.cpp | 44 ++++++++++++++------
lib/IR/ConstantFold.h | 2 +-
lib/IR/Constants.cpp | 78 ++++++++++++++++++++++++++++++++---
7 files changed, 123 insertions(+), 23 deletions(-)
diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h
index 6bbf4f4..2afb912 100644
--- a/include/llvm/Analysis/ValueTracking.h
+++ b/include/llvm/Analysis/ValueTracking.h
@@ -203,7 +203,8 @@ namespace llvm {
/// However, this method can return true for instructions that read memory;
/// for such instructions, moving them may change the resulting value.
bool isSafeToSpeculativelyExecute(const Value *V,
- const DataLayout *TD = nullptr);
+ const DataLayout *TD = nullptr,
+ bool HonorFPExceptions = false);
/// isKnownNonNull - Return true if this pointer couldn't possibly be null by
/// its definition. This returns true for allocas, non-extern-weak globals
diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h
index d26991e..fa7e4e5 100644
--- a/include/llvm/IR/Constant.h
+++ b/include/llvm/IR/Constant.h
@@ -77,7 +77,7 @@ public:
/// canTrap - Return true if evaluation of this constant could trap. This is
/// true for things like constant expressions that could divide by zero.
- bool canTrap() const;
+ bool canTrap(bool HonorFPExceptions = false) const;
/// isThreadDependent - Return true if the value can vary between threads.
bool isThreadDependent() const;
diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h
index 4823be0..825998e 100644
--- a/include/llvm/IR/Constants.h
+++ b/include/llvm/IR/Constants.h
@@ -1139,6 +1139,10 @@ public:
return V->getValueID() == ConstantExprVal;
}
+ /// Checks that floating point operation is safe with regard to exceptions.
+ /// Returns false for unsupported types of Value.
+ static bool isExceptionSafeFPOp(const Value *V);
+
private:
// Shadow Value::setValueSubclassData with a private forwarding method so that
// subclasses cannot accidentally use it.
diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp
index da5ba0b..e7911e3 100644
--- a/lib/Analysis/ValueTracking.cpp
+++ b/lib/Analysis/ValueTracking.cpp
@@ -2538,19 +2538,28 @@ bool llvm::onlyUsedByLifetimeMarkers(const Value *V) {
}
bool llvm::isSafeToSpeculativelyExecute(const Value *V,
- const DataLayout *TD) {
+ const DataLayout *TD,
+ bool HonorFPExceptions) {
const Operator *Inst = dyn_cast<Operator>(V);
if (!Inst)
return false;
for (unsigned i = 0, e = Inst->getNumOperands(); i != e; ++i)
if (Constant *C = dyn_cast<Constant>(Inst->getOperand(i)))
- if (C->canTrap())
+ if (C->canTrap(HonorFPExceptions))
return false;
switch (Inst->getOpcode()) {
default:
return true;
+ case Instruction::FMul:
+ case Instruction::FAdd:
+ case Instruction::FSub:
+ case Instruction::FDiv:
+ if (HonorFPExceptions) {
+ return ConstantExpr::isExceptionSafeFPOp(Inst);
+ }
+ return true;
case Instruction::UDiv:
case Instruction::URem:
// x / y is undefined if y == 0, but calculations like x / 3 are safe.
diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp
index cdfb41f..542fe72 100644
--- a/lib/IR/ConstantFold.cpp
+++ b/lib/IR/ConstantFold.cpp
@@ -895,7 +895,8 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg,
Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
- Constant *C1, Constant *C2) {
+ Constant *C1, Constant *C2,
+ bool HonorFPExceptions) {
// Handle UndefValue up front.
if (isa<UndefValue>(C1) || isa<UndefValue>(C2)) {
switch (Opcode) {
@@ -1058,7 +1059,7 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
} else if (isa<ConstantInt>(C1)) {
// If C1 is a ConstantInt and C2 is not, swap the operands.
if (Instruction::isCommutative(Opcode))
- return ConstantExpr::get(Opcode, C2, C1);
+ return ConstantExpr::get(Opcode, C2, C1, 0, nullptr, HonorFPExceptions);
}
// At this point we know neither constant is an UndefValue.
@@ -1139,23 +1140,39 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
APFloat C1V = CFP1->getValueAPF();
APFloat C2V = CFP2->getValueAPF();
APFloat C3V = C1V; // copy for modification
+ APFloat::opStatus s;
switch (Opcode) {
- default:
+ default:
break;
case Instruction::FAdd:
- (void)C3V.add(C2V, APFloat::rmNearestTiesToEven);
+ s = C3V.add(C2V, APFloat::rmNearestTiesToEven);
+ if (HonorFPExceptions && s != APFloat::opOK) {
+ break;
+ }
return ConstantFP::get(C1->getContext(), C3V);
case Instruction::FSub:
- (void)C3V.subtract(C2V, APFloat::rmNearestTiesToEven);
+ s = C3V.subtract(C2V, APFloat::rmNearestTiesToEven);
+ if (HonorFPExceptions && s != APFloat::opOK) {
+ break;
+ }
return ConstantFP::get(C1->getContext(), C3V);
case Instruction::FMul:
- (void)C3V.multiply(C2V, APFloat::rmNearestTiesToEven);
+ s = C3V.multiply(C2V, APFloat::rmNearestTiesToEven);
+ if (HonorFPExceptions && s != APFloat::opOK) {
+ break;
+ }
return ConstantFP::get(C1->getContext(), C3V);
case Instruction::FDiv:
- (void)C3V.divide(C2V, APFloat::rmNearestTiesToEven);
+ s = C3V.divide(C2V, APFloat::rmNearestTiesToEven);
+ if (HonorFPExceptions && s != APFloat::opOK) {
+ break;
+ }
return ConstantFP::get(C1->getContext(), C3V);
case Instruction::FRem:
- (void)C3V.mod(C2V, APFloat::rmNearestTiesToEven);
+ s = C3V.mod(C2V, APFloat::rmNearestTiesToEven);
+ if (HonorFPExceptions && s != APFloat::opOK) {
+ break;
+ }
return ConstantFP::get(C1->getContext(), C3V);
}
}
@@ -1169,7 +1186,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
Constant *RHS =
ConstantExpr::getExtractElement(C2, ConstantInt::get(Ty, i));
- Result.push_back(ConstantExpr::get(Opcode, LHS, RHS));
+ Result.push_back(ConstantExpr::get(Opcode, LHS, RHS, 0, nullptr,
+ HonorFPExceptions));
}
return ConstantVector::get(Result);
@@ -1183,15 +1201,17 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
// Given ((a + b) + c), if (b + c) folds to something interesting, return
// (a + (b + c)).
if (Instruction::isAssociative(Opcode) && CE1->getOpcode() == Opcode) {
- Constant *T = ConstantExpr::get(Opcode, CE1->getOperand(1), C2);
+ Constant *T = ConstantExpr::get(Opcode, CE1->getOperand(1), C2, 0,
+ nullptr, HonorFPExceptions);
if (!isa<ConstantExpr>(T) || cast<ConstantExpr>(T)->getOpcode() != Opcode)
- return ConstantExpr::get(Opcode, CE1->getOperand(0), T);
+ return ConstantExpr::get(Opcode, CE1->getOperand(0), T, 0, nullptr,
+ HonorFPExceptions);
}
} else if (isa<ConstantExpr>(C2)) {
// If C2 is a constant expr and C1 isn't, flop them around and fold the
// other way if possible.
if (Instruction::isCommutative(Opcode))
- return ConstantFoldBinaryInstruction(Opcode, C2, C1);
+ return ConstantFoldBinaryInstruction(Opcode, C2, C1, HonorFPExceptions);
}
// i1 can be simplified in many cases.
diff --git a/lib/IR/ConstantFold.h b/lib/IR/ConstantFold.h
index a516abe..1a6d82e 100644
--- a/lib/IR/ConstantFold.h
+++ b/lib/IR/ConstantFold.h
@@ -44,7 +44,7 @@ namespace llvm {
Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val,
ArrayRef<unsigned> Idxs);
Constant *ConstantFoldBinaryInstruction(unsigned Opcode, Constant *V1,
- Constant *V2);
+ Constant *V2, bool HonorFPExceptions);
Constant *ConstantFoldCompareInstruction(unsigned short predicate,
Constant *C1, Constant *C2);
Constant *ConstantFoldGetElementPtr(Constant *C, bool inBounds,
diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp
index 21dbacc..779c02f 100644
--- a/lib/IR/Constants.cpp
+++ b/lib/IR/Constants.cpp
@@ -306,7 +306,8 @@ void Constant::destroyConstantImpl() {
}
static bool canTrapImpl(const Constant *C,
- SmallPtrSetImpl<const ConstantExpr *> &NonTrappingOps) {
+ SmallPtrSetImpl<const ConstantExpr *> &NonTrappingOps,
+ bool HonorFPExceptions) {
assert(C->getType()->isFirstClassType() && "Cannot evaluate aggregate vals!");
// The only thing that could possibly trap are constant exprs.
const ConstantExpr *CE = dyn_cast<ConstantExpr>(C);
@@ -316,13 +317,27 @@ static bool canTrapImpl(const Constant *C,
// ConstantExpr traps if any operands can trap.
for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) {
if (ConstantExpr *Op = dyn_cast<ConstantExpr>(CE->getOperand(i))) {
- if (NonTrappingOps.insert(Op) && canTrapImpl(Op, NonTrappingOps))
+ if (NonTrappingOps.insert(Op) && canTrapImpl(Op, NonTrappingOps,
+ HonorFPExceptions)) {
return true;
+ }
}
}
// Otherwise, only specific operations can trap.
- switch (CE->getOpcode()) {
+ unsigned Opcode = CE->getOpcode();
+ if (HonorFPExceptions) {
+ switch (Opcode) {
+ default:
+ break;
+ case Instruction::FMul:
+ case Instruction::FAdd:
+ case Instruction::FSub:
+ case Instruction::FDiv:
+ return !ConstantExpr::isExceptionSafeFPOp(CE);
+ }
+ }
+ switch (Opcode) {
default:
return false;
case Instruction::UDiv:
@@ -340,9 +355,9 @@ static bool canTrapImpl(const Constant *C,
/// canTrap - Return true if evaluation of this constant could trap. This is
/// true for things like constant expressions that could divide by zero.
-bool Constant::canTrap() const {
+bool Constant::canTrap(bool HonorFPExceptions) const {
SmallPtrSet<const ConstantExpr *, 4> NonTrappingOps;
- return canTrapImpl(this, NonTrappingOps);
+ return canTrapImpl(this, NonTrappingOps, HonorFPExceptions);
}
/// Check if C contains a GlobalValue for which Predicate is true.
@@ -1892,7 +1907,7 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
}
#endif
- if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2))
+ if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2, false))
return FC; // Fold a few common cases.
if (OnlyIfReducedTy == C1->getType())
@@ -2965,3 +2980,54 @@ Instruction *ConstantExpr::getAsInstruction() {
return BO;
}
}
+
+bool ConstantExpr::isExceptionSafeFPOp(const Value *V) {
+ unsigned Opcode;
+ const User *U;
+ if (const Operator *Op = dyn_cast<Operator>(V)) {
+ U = Op;
+ Opcode = Op->getOpcode();
+ } if (const ConstantExpr *C = dyn_cast<ConstantExpr>(V)) {
+ U = C;
+ Opcode = C->getOpcode();
+ } else {
+ return false;
+ }
+
+ switch (Opcode) {
+ default:
+ return true;
+ case Instruction::FMul:
+ case Instruction::FAdd:
+ case Instruction::FSub:
+ case Instruction::FDiv: {
+ ConstantFP *LHSC = dyn_cast<ConstantFP>(U->getOperand(0));
+ ConstantFP *RHSC = dyn_cast<ConstantFP>(U->getOperand(1));
+
+ if (!LHSC || !RHSC) {
+ return false;
+ }
+
+ APFloat LHS = LHSC->getValueAPF();
+ APFloat RHS = LHSC->getValueAPF();
+ APFloat::opStatus status;
+
+ switch (Opcode) {
+ case Instruction::FMul:
+ status = LHS.multiply(RHS, APFloat::rmNearestTiesToEven);
+ break;
+ case Instruction::FAdd:
+ status = LHS.add(RHS, APFloat::rmNearestTiesToEven);
+ break;
+ case Instruction::FSub:
+ status = LHS.subtract(RHS, APFloat::rmNearestTiesToEven);
+ break;
+ case Instruction::FDiv:
+ status = LHS.divide(RHS, APFloat::rmNearestTiesToEven);
+ break;
+ }
+
+ return (status == APFloat::opOK);
+ }
+ }
+}
--
1.8.4
-------------- next part --------------
>From 342de27ad5e8173a84b8618fb21fc0e701d2db09 Mon Sep 17 00:00:00 2001
From: Sergey Dmitrouk <sdmitrouk at accesssoftek.com>
Date: Thu, 25 Sep 2014 11:46:24 +0300
Subject: [PATCH 04/11] Pass HonorFPExceptions flag around
---
include/llvm/Analysis/ConstantFolding.h | 9 ++++++---
include/llvm/Analysis/TargetFolder.h | 26 ++++++++++++++----------
include/llvm/IR/ConstantFolder.h | 30 +++++++++++++++++-----------
include/llvm/IR/Constants.h | 18 +++++++++++------
include/llvm/IR/IRBuilder.h | 20 +++++++++++--------
lib/Analysis/ConstantFolding.cpp | 35 ++++++++++++++++++++++-----------
lib/IR/Constants.cpp | 32 +++++++++++++++++++-----------
7 files changed, 107 insertions(+), 63 deletions(-)
diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h
index 09d45ca..8f013ec 100644
--- a/include/llvm/Analysis/ConstantFolding.h
+++ b/include/llvm/Analysis/ConstantFolding.h
@@ -38,14 +38,16 @@ namespace llvm {
/// and stores, which have no constant expression form.
Constant *ConstantFoldInstruction(Instruction *I,
const DataLayout *TD = nullptr,
- const TargetLibraryInfo *TLI = nullptr);
+ const TargetLibraryInfo *TLI = nullptr,
+ bool HonorFPExceptions = false);
/// ConstantFoldConstantExpression - Attempt to fold the constant expression
/// using the specified DataLayout. If successful, the constant result is
/// result is returned, if not, null is returned.
Constant *ConstantFoldConstantExpression(const ConstantExpr *CE,
const DataLayout *TD = nullptr,
- const TargetLibraryInfo *TLI =nullptr);
+ const TargetLibraryInfo *TLI = nullptr,
+ bool HonorFPExceptions = false);
/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
/// specified operands. If successful, the constant result is returned, if not,
@@ -56,7 +58,8 @@ Constant *ConstantFoldConstantExpression(const ConstantExpr *CE,
Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
ArrayRef<Constant *> Ops,
const DataLayout *TD = nullptr,
- const TargetLibraryInfo *TLI = nullptr);
+ const TargetLibraryInfo *TLI = nullptr,
+ bool HonorFPExceptions = false);
/// ConstantFoldCompareInstOperands - Attempt to constant fold a compare
/// instruction (icmp/fcmp) with the specified operands. If it fails, it
diff --git a/include/llvm/Analysis/TargetFolder.h b/include/llvm/Analysis/TargetFolder.h
index 587a7ef..a04a186 100644
--- a/include/llvm/Analysis/TargetFolder.h
+++ b/include/llvm/Analysis/TargetFolder.h
@@ -51,22 +51,27 @@ public:
bool HasNUW = false, bool HasNSW = false) const {
return Fold(ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW));
}
- Constant *CreateFAdd(Constant *LHS, Constant *RHS) const {
- return Fold(ConstantExpr::getFAdd(LHS, RHS));
+ Constant *CreateFAdd(Constant *LHS, Constant *RHS,
+ bool HonorFPExceptions = false) const {
+ return Fold(ConstantExpr::getFAdd(LHS, RHS, HonorFPExceptions));
}
Constant *CreateSub(Constant *LHS, Constant *RHS,
bool HasNUW = false, bool HasNSW = false) const {
return Fold(ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW));
}
- Constant *CreateFSub(Constant *LHS, Constant *RHS) const {
- return Fold(ConstantExpr::getFSub(LHS, RHS));
+ Constant *CreateFSub(Constant *LHS, Constant *RHS,
+ bool HonorFPExceptions = false) const {
+ return Fold(ConstantExpr::getFSub(LHS, RHS, HonorFPExceptions));
}
Constant *CreateMul(Constant *LHS, Constant *RHS,
- bool HasNUW = false, bool HasNSW = false) const {
- return Fold(ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW));
+ bool HasNUW = false, bool HasNSW = false,
+ bool HonorFPExceptions = false) const {
+ return Fold(ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW,
+ HonorFPExceptions));
}
- Constant *CreateFMul(Constant *LHS, Constant *RHS) const {
- return Fold(ConstantExpr::getFMul(LHS, RHS));
+ Constant *CreateFMul(Constant *LHS, Constant *RHS,
+ bool HonorFPExceptions = false) const {
+ return Fold(ConstantExpr::getFMul(LHS, RHS, HonorFPExceptions));
}
Constant *CreateUDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{
return Fold(ConstantExpr::getUDiv(LHS, RHS, isExact));
@@ -74,8 +79,9 @@ public:
Constant *CreateSDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{
return Fold(ConstantExpr::getSDiv(LHS, RHS, isExact));
}
- Constant *CreateFDiv(Constant *LHS, Constant *RHS) const {
- return Fold(ConstantExpr::getFDiv(LHS, RHS));
+ Constant *CreateFDiv(Constant *LHS, Constant *RHS,
+ bool HonorFPExceptions = false) const {
+ return Fold(ConstantExpr::getFDiv(LHS, RHS, HonorFPExceptions));
}
Constant *CreateURem(Constant *LHS, Constant *RHS) const {
return Fold(ConstantExpr::getURem(LHS, RHS));
diff --git a/include/llvm/IR/ConstantFolder.h b/include/llvm/IR/ConstantFolder.h
index e271a14..fd753ad 100644
--- a/include/llvm/IR/ConstantFolder.h
+++ b/include/llvm/IR/ConstantFolder.h
@@ -35,22 +35,26 @@ public:
bool HasNUW = false, bool HasNSW = false) const {
return ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW);
}
- Constant *CreateFAdd(Constant *LHS, Constant *RHS) const {
- return ConstantExpr::getFAdd(LHS, RHS);
+ Constant *CreateFAdd(Constant *LHS, Constant *RHS,
+ bool HonorFPExceptions = false) const {
+ return ConstantExpr::getFAdd(LHS, RHS, HonorFPExceptions);
}
Constant *CreateSub(Constant *LHS, Constant *RHS,
bool HasNUW = false, bool HasNSW = false) const {
return ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW);
}
- Constant *CreateFSub(Constant *LHS, Constant *RHS) const {
- return ConstantExpr::getFSub(LHS, RHS);
+ Constant *CreateFSub(Constant *LHS, Constant *RHS,
+ bool HonorFPExceptions = false) const {
+ return ConstantExpr::getFSub(LHS, RHS, HonorFPExceptions);
}
Constant *CreateMul(Constant *LHS, Constant *RHS,
- bool HasNUW = false, bool HasNSW = false) const {
- return ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW);
+ bool HasNUW = false, bool HasNSW = false,
+ bool HonorFPExceptions = false) const {
+ return ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW, HonorFPExceptions);
}
- Constant *CreateFMul(Constant *LHS, Constant *RHS) const {
- return ConstantExpr::getFMul(LHS, RHS);
+ Constant *CreateFMul(Constant *LHS, Constant *RHS,
+ bool HonorFPExceptions = false) const {
+ return ConstantExpr::getFMul(LHS, RHS, HonorFPExceptions);
}
Constant *CreateUDiv(Constant *LHS, Constant *RHS,
bool isExact = false) const {
@@ -60,8 +64,9 @@ public:
bool isExact = false) const {
return ConstantExpr::getSDiv(LHS, RHS, isExact);
}
- Constant *CreateFDiv(Constant *LHS, Constant *RHS) const {
- return ConstantExpr::getFDiv(LHS, RHS);
+ Constant *CreateFDiv(Constant *LHS, Constant *RHS,
+ bool HonorFPExceptions = false) const {
+ return ConstantExpr::getFDiv(LHS, RHS, HonorFPExceptions);
}
Constant *CreateURem(Constant *LHS, Constant *RHS) const {
return ConstantExpr::getURem(LHS, RHS);
@@ -95,8 +100,9 @@ public:
}
Constant *CreateBinOp(Instruction::BinaryOps Opc,
- Constant *LHS, Constant *RHS) const {
- return ConstantExpr::get(Opc, LHS, RHS);
+ Constant *LHS, Constant *RHS,
+ bool HonorFPExceptions = false) const {
+ return ConstantExpr::get(Opc, LHS, RHS, 0, nullptr, HonorFPExceptions);
}
//===--------------------------------------------------------------------===//
diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h
index 825998e..cc12bbf 100644
--- a/include/llvm/IR/Constants.h
+++ b/include/llvm/IR/Constants.h
@@ -841,16 +841,21 @@ public:
static Constant *getNot(Constant *C);
static Constant *getAdd(Constant *C1, Constant *C2,
bool HasNUW = false, bool HasNSW = false);
- static Constant *getFAdd(Constant *C1, Constant *C2);
+ static Constant *getFAdd(Constant *C1, Constant *C2,
+ bool HonorFPExceptions = false);
static Constant *getSub(Constant *C1, Constant *C2,
bool HasNUW = false, bool HasNSW = false);
- static Constant *getFSub(Constant *C1, Constant *C2);
+ static Constant *getFSub(Constant *C1, Constant *C2,
+ bool HonorFPExceptions = false);
static Constant *getMul(Constant *C1, Constant *C2,
- bool HasNUW = false, bool HasNSW = false);
- static Constant *getFMul(Constant *C1, Constant *C2);
+ bool HasNUW = false, bool HasNSW = false,
+ bool HonorFPExceptions = false);
+ static Constant *getFMul(Constant *C1, Constant *C2,
+ bool HonorFPExceptions = false);
static Constant *getUDiv(Constant *C1, Constant *C2, bool isExact = false);
static Constant *getSDiv(Constant *C1, Constant *C2, bool isExact = false);
- static Constant *getFDiv(Constant *C1, Constant *C2);
+ static Constant *getFDiv(Constant *C1, Constant *C2,
+ bool HonorFPExceptions = false);
static Constant *getURem(Constant *C1, Constant *C2);
static Constant *getSRem(Constant *C1, Constant *C2);
static Constant *getFRem(Constant *C1, Constant *C2);
@@ -1016,7 +1021,8 @@ public:
///
/// \param OnlyIfReducedTy see \a getWithOperands() docs.
static Constant *get(unsigned Opcode, Constant *C1, Constant *C2,
- unsigned Flags = 0, Type *OnlyIfReducedTy = nullptr);
+ unsigned Flags = 0, Type *OnlyIfReducedTy = nullptr,
+ bool HonorFPExceptions = false);
/// \brief Return an ICmp or FCmp comparison operator constant expression.
///
diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h
index d803bf4..8908c0e 100644
--- a/include/llvm/IR/IRBuilder.h
+++ b/include/llvm/IR/IRBuilder.h
@@ -664,10 +664,11 @@ public:
return CreateAdd(LHS, RHS, Name, true, false);
}
Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "",
- MDNode *FPMathTag = nullptr) {
+ MDNode *FPMathTag = nullptr,
+ bool HonorFPExceptions = false) {
if (Constant *LC = dyn_cast<Constant>(LHS))
if (Constant *RC = dyn_cast<Constant>(RHS))
- return Insert(Folder.CreateFAdd(LC, RC), Name);
+ return Insert(Folder.CreateFAdd(LC, RC, HonorFPExceptions), Name);
return Insert(AddFPMathAttributes(BinaryOperator::CreateFAdd(LHS, RHS),
FPMathTag, FMF), Name);
}
@@ -686,10 +687,11 @@ public:
return CreateSub(LHS, RHS, Name, true, false);
}
Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "",
- MDNode *FPMathTag = nullptr) {
+ MDNode *FPMathTag = nullptr,
+ bool HonorFPExceptions = false) {
if (Constant *LC = dyn_cast<Constant>(LHS))
if (Constant *RC = dyn_cast<Constant>(RHS))
- return Insert(Folder.CreateFSub(LC, RC), Name);
+ return Insert(Folder.CreateFSub(LC, RC, HonorFPExceptions), Name);
return Insert(AddFPMathAttributes(BinaryOperator::CreateFSub(LHS, RHS),
FPMathTag, FMF), Name);
}
@@ -708,10 +710,11 @@ public:
return CreateMul(LHS, RHS, Name, true, false);
}
Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "",
- MDNode *FPMathTag = nullptr) {
+ MDNode *FPMathTag = nullptr,
+ bool HonorFPExceptions = false) {
if (Constant *LC = dyn_cast<Constant>(LHS))
if (Constant *RC = dyn_cast<Constant>(RHS))
- return Insert(Folder.CreateFMul(LC, RC), Name);
+ return Insert(Folder.CreateFMul(LC, RC, HonorFPExceptions), Name);
return Insert(AddFPMathAttributes(BinaryOperator::CreateFMul(LHS, RHS),
FPMathTag, FMF), Name);
}
@@ -740,10 +743,11 @@ public:
return CreateSDiv(LHS, RHS, Name, true);
}
Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "",
- MDNode *FPMathTag = nullptr) {
+ MDNode *FPMathTag = nullptr,
+ bool HonorFPExceptions = false) {
if (Constant *LC = dyn_cast<Constant>(LHS))
if (Constant *RC = dyn_cast<Constant>(RHS))
- return Insert(Folder.CreateFDiv(LC, RC), Name);
+ return Insert(Folder.CreateFDiv(LC, RC, HonorFPExceptions), Name);
return Insert(AddFPMathAttributes(BinaryOperator::CreateFDiv(LHS, RHS),
FPMathTag, FMF), Name);
}
diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp
index cd25acb..0fb5bb0 100644
--- a/lib/Analysis/ConstantFolding.cpp
+++ b/lib/Analysis/ConstantFolding.cpp
@@ -623,7 +623,8 @@ static Constant *ConstantFoldLoadInst(const LoadInst *LI, const DataLayout *TD){
/// these together. If target data info is available, it is provided as DL,
/// otherwise DL is null.
static Constant *SymbolicallyEvaluateBinop(unsigned Opc, Constant *Op0,
- Constant *Op1, const DataLayout *DL){
+ Constant *Op1, const DataLayout *DL,
+ bool HonorFPExceptions) {
// SROA
// Fold (and 0xffffffff00000000, (shl x, 32)) -> shl.
@@ -900,7 +901,8 @@ static Constant *SymbolicallyEvaluateGEP(ArrayRef<Constant *> Ops,
/// and stores, which have no constant expression form.
Constant *llvm::ConstantFoldInstruction(Instruction *I,
const DataLayout *TD,
- const TargetLibraryInfo *TLI) {
+ const TargetLibraryInfo *TLI,
+ bool HonorFPExceptions) {
// Handle PHI nodes quickly here...
if (PHINode *PN = dyn_cast<PHINode>(I)) {
Constant *CommonValue = nullptr;
@@ -919,7 +921,7 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I,
return nullptr;
// Fold the PHI's operands.
if (ConstantExpr *NewC = dyn_cast<ConstantExpr>(C))
- C = ConstantFoldConstantExpression(NewC, TD, TLI);
+ C = ConstantFoldConstantExpression(NewC, TD, TLI, HonorFPExceptions);
// If the incoming value is a different constant to
// the one we saw previously, then give up.
if (CommonValue && C != CommonValue)
@@ -967,13 +969,15 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I,
EVI->getIndices());
}
- return ConstantFoldInstOperands(I->getOpcode(), I->getType(), Ops, TD, TLI);
+ return ConstantFoldInstOperands(I->getOpcode(), I->getType(), Ops, TD, TLI,
+ HonorFPExceptions);
}
static Constant *
ConstantFoldConstantExpressionImpl(const ConstantExpr *CE, const DataLayout *TD,
const TargetLibraryInfo *TLI,
- SmallPtrSetImpl<ConstantExpr *> &FoldedOps) {
+ SmallPtrSetImpl<ConstantExpr *> &FoldedOps,
+ bool HonorFPExceptions) {
SmallVector<Constant *, 8> Ops;
for (User::const_op_iterator i = CE->op_begin(), e = CE->op_end(); i != e;
++i) {
@@ -982,7 +986,8 @@ ConstantFoldConstantExpressionImpl(const ConstantExpr *CE, const DataLayout *TD,
// a ConstantExpr, we don't have to process it again.
if (ConstantExpr *NewCE = dyn_cast<ConstantExpr>(NewC)) {
if (FoldedOps.insert(NewCE))
- NewC = ConstantFoldConstantExpressionImpl(NewCE, TD, TLI, FoldedOps);
+ NewC = ConstantFoldConstantExpressionImpl(NewCE, TD, TLI, FoldedOps,
+ HonorFPExceptions);
}
Ops.push_back(NewC);
}
@@ -990,7 +995,8 @@ ConstantFoldConstantExpressionImpl(const ConstantExpr *CE, const DataLayout *TD,
if (CE->isCompare())
return ConstantFoldCompareInstOperands(CE->getPredicate(), Ops[0], Ops[1],
TD, TLI);
- return ConstantFoldInstOperands(CE->getOpcode(), CE->getType(), Ops, TD, TLI);
+ return ConstantFoldInstOperands(CE->getOpcode(), CE->getType(), Ops, TD, TLI,
+ HonorFPExceptions);
}
/// Attempt to fold the constant expression
@@ -998,9 +1004,11 @@ ConstantFoldConstantExpressionImpl(const ConstantExpr *CE, const DataLayout *TD,
/// result is returned, if not, null is returned.
Constant *llvm::ConstantFoldConstantExpression(const ConstantExpr *CE,
const DataLayout *TD,
- const TargetLibraryInfo *TLI) {
+ const TargetLibraryInfo *TLI,
+ bool HonorFPExceptions) {
SmallPtrSet<ConstantExpr *, 4> FoldedOps;
- return ConstantFoldConstantExpressionImpl(CE, TD, TLI, FoldedOps);
+ return ConstantFoldConstantExpressionImpl(CE, TD, TLI, FoldedOps,
+ HonorFPExceptions);
}
/// Attempt to constant fold an instruction with the
@@ -1016,15 +1024,18 @@ Constant *llvm::ConstantFoldConstantExpression(const ConstantExpr *CE,
Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
ArrayRef<Constant *> Ops,
const DataLayout *TD,
- const TargetLibraryInfo *TLI) {
+ const TargetLibraryInfo *TLI,
+ bool HonorFPExceptions) {
// Handle easy binops first.
if (Instruction::isBinaryOp(Opcode)) {
if (isa<ConstantExpr>(Ops[0]) || isa<ConstantExpr>(Ops[1])) {
- if (Constant *C = SymbolicallyEvaluateBinop(Opcode, Ops[0], Ops[1], TD))
+ if (Constant *C = SymbolicallyEvaluateBinop(Opcode, Ops[0], Ops[1], TD,
+ HonorFPExceptions))
return C;
}
- return ConstantExpr::get(Opcode, Ops[0], Ops[1]);
+ return ConstantExpr::get(Opcode, Ops[0], Ops[1], 0, nullptr,
+ HonorFPExceptions);
}
switch (Opcode) {
diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp
index 779c02f..5ce91b1 100644
--- a/lib/IR/Constants.cpp
+++ b/lib/IR/Constants.cpp
@@ -1841,7 +1841,8 @@ Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy,
}
Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
- unsigned Flags, Type *OnlyIfReducedTy) {
+ unsigned Flags, Type *OnlyIfReducedTy,
+ bool HonorFPExceptions) {
// Check the operands for consistency first.
assert(Opcode >= Instruction::BinaryOpsBegin &&
Opcode < Instruction::BinaryOpsEnd &&
@@ -1907,8 +1908,10 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
}
#endif
- if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2, false))
+ if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2,
+ HonorFPExceptions)) {
return FC; // Fold a few common cases.
+ }
if (OnlyIfReducedTy == C1->getType())
return nullptr;
@@ -2231,8 +2234,9 @@ Constant *ConstantExpr::getAdd(Constant *C1, Constant *C2,
return get(Instruction::Add, C1, C2, Flags);
}
-Constant *ConstantExpr::getFAdd(Constant *C1, Constant *C2) {
- return get(Instruction::FAdd, C1, C2);
+Constant *ConstantExpr::getFAdd(Constant *C1, Constant *C2,
+ bool HonorFPExceptions) {
+ return get(Instruction::FAdd, C1, C2, 0, nullptr, HonorFPExceptions);
}
Constant *ConstantExpr::getSub(Constant *C1, Constant *C2,
@@ -2242,19 +2246,22 @@ Constant *ConstantExpr::getSub(Constant *C1, Constant *C2,
return get(Instruction::Sub, C1, C2, Flags);
}
-Constant *ConstantExpr::getFSub(Constant *C1, Constant *C2) {
- return get(Instruction::FSub, C1, C2);
+Constant *ConstantExpr::getFSub(Constant *C1, Constant *C2,
+ bool HonorFPExceptions) {
+ return get(Instruction::FSub, C1, C2, 0, nullptr, HonorFPExceptions);
}
Constant *ConstantExpr::getMul(Constant *C1, Constant *C2,
- bool HasNUW, bool HasNSW) {
+ bool HasNUW, bool HasNSW,
+ bool HonorFPExceptions) {
unsigned Flags = (HasNUW ? OverflowingBinaryOperator::NoUnsignedWrap : 0) |
(HasNSW ? OverflowingBinaryOperator::NoSignedWrap : 0);
- return get(Instruction::Mul, C1, C2, Flags);
+ return get(Instruction::Mul, C1, C2, Flags, nullptr, HonorFPExceptions);
}
-Constant *ConstantExpr::getFMul(Constant *C1, Constant *C2) {
- return get(Instruction::FMul, C1, C2);
+Constant *ConstantExpr::getFMul(Constant *C1, Constant *C2,
+ bool HonorFPExceptions) {
+ return get(Instruction::FMul, C1, C2, 0, nullptr, HonorFPExceptions);
}
Constant *ConstantExpr::getUDiv(Constant *C1, Constant *C2, bool isExact) {
@@ -2267,8 +2274,9 @@ Constant *ConstantExpr::getSDiv(Constant *C1, Constant *C2, bool isExact) {
isExact ? PossiblyExactOperator::IsExact : 0);
}
-Constant *ConstantExpr::getFDiv(Constant *C1, Constant *C2) {
- return get(Instruction::FDiv, C1, C2);
+Constant *ConstantExpr::getFDiv(Constant *C1, Constant *C2,
+ bool HonorFPExceptions) {
+ return get(Instruction::FDiv, C1, C2, 0, nullptr, HonorFPExceptions);
}
Constant *ConstantExpr::getURem(Constant *C1, Constant *C2) {
--
1.8.4
-------------- next part --------------
>From b849aaa0c13b64e5a5ffc1874c1f47a8a468a233 Mon Sep 17 00:00:00 2001
From: Sergey Dmitrouk <sdmitrouk at accesssoftek.com>
Date: Thu, 25 Sep 2014 11:47:00 +0300
Subject: [PATCH 05/11] 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 309e1bf..0250552 100644
--- a/lib/Target/TargetMachine.cpp
+++ b/lib/Target/TargetMachine.cpp
@@ -64,6 +64,7 @@ void TargetMachine::resetTargetOptions(const Function &F) 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");
Options.MCOptions.SanitizeAddress = F.hasFnAttribute(Attribute::SanitizeAddress);
}
diff --git a/lib/Transforms/InstCombine/InstCombine.h b/lib/Transforms/InstCombine/InstCombine.h
index d4b252b..d7b604c 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 c32294f..7ad2bb3 100644
--- a/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2660,7 +2660,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);
@@ -2687,7 +2688,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);
@@ -2704,10 +2706,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;
@@ -2773,7 +2778,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
@@ -2968,6 +2973,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 0e4d779..9009241 100644
--- a/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -1088,6 +1088,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();
@@ -1103,10 +1108,14 @@ HoistTerminator:
passingValueIsAlwaysUndefined(BB2V, PN))
return Changed;
- 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
-------------- next part --------------
>From e3bb752a4bca84e6f4711f24fe5cf70574f0443b Mon Sep 17 00:00:00 2001
From: Sergey Dmitrouk <sdmitrouk at accesssoftek.com>
Date: Fri, 26 Sep 2014 15:33:02 +0300
Subject: [PATCH 06/11] Add -honor-fp-exceptions option to LLVM
---
include/llvm/CodeGen/CommandFlags.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h
index 95579f8..60baf67 100644
--- a/include/llvm/CodeGen/CommandFlags.h
+++ b/include/llvm/CodeGen/CommandFlags.h
@@ -133,6 +133,11 @@ GenerateSoftFloatCalls("soft-float",
cl::desc("Generate software floating point library calls"),
cl::init(false));
+cl::opt<bool>
+HonorFPExceptions("honor-fp-exceptions",
+ cl::desc("Preserve exceptions raising floating operations"),
+ cl::init(false));
+
cl::opt<llvm::FloatABI::ABIType>
FloatABIForCalls("float-abi",
cl::desc("Choose float ABI type"),
@@ -237,6 +242,7 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
Options.UnsafeFPMath = EnableUnsafeFPMath;
Options.NoInfsFPMath = EnableNoInfsFPMath;
Options.NoNaNsFPMath = EnableNoNaNsFPMath;
+ Options.HonorFPExceptions = HonorFPExceptions;
Options.HonorSignDependentRoundingFPMathOption =
EnableHonorSignDependentRoundingFPMath;
Options.UseSoftFloat = GenerateSoftFloatCalls;
--
1.8.4
-------------- next part --------------
>From 74029ba361eba8ef237a975a5a6dfd5ed7193ad8 Mon Sep 17 00:00:00 2001
From: Sergey Dmitrouk <sdmitrouk at accesssoftek.com>
Date: Fri, 26 Sep 2014 15:33:25 +0300
Subject: [PATCH 07/11] Do not fold constants on reading in IR assembly
---
lib/AsmParser/LLParser.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index b7818bb..0aea438 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -2776,7 +2776,7 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
if (NUW) Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
if (NSW) Flags |= OverflowingBinaryOperator::NoSignedWrap;
if (Exact) Flags |= PossiblyExactOperator::IsExact;
- Constant *C = ConstantExpr::get(Opc, Val0, Val1, Flags);
+ Constant *C = ConstantExpr::get(Opc, Val0, Val1, Flags, nullptr, true);
ID.ConstantVal = C;
ID.Kind = ValID::t_Constant;
return false;
--
1.8.4
-------------- next part --------------
>From 723d7cff2ea0a4c8cf13dc3ada0bad3b437df3c5 Mon Sep 17 00:00:00 2001
From: Sergey Dmitrouk <sdmitrouk at accesssoftek.com>
Date: Fri, 26 Sep 2014 18:41:17 +0300
Subject: [PATCH 08/11] Consider HonorFPExceptions flag in SimplifyCFG
---
lib/Transforms/Utils/SimplifyCFG.cpp | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp
index 9009241..593056d 100644
--- a/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -278,9 +278,15 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB,
if (!I) {
// Non-instructions all dominate instructions, but not all constantexprs
// can be executed unconditionally.
- if (ConstantExpr *C = dyn_cast<ConstantExpr>(V))
- if (C->canTrap())
+ if (ConstantExpr *C = dyn_cast<ConstantExpr>(V)) {
+ Function *F = BB->getParent();
+ bool HonorFPExceptions = F->hasFnAttribute("honor-fp-exceptions") &&
+ (F->getFnAttribute("honor-fp-exceptions")
+ .getValueAsString() == "true");
+
+ if (C->canTrap(HonorFPExceptions))
return false;
+ }
return true;
}
BasicBlock *PBB = I->getParent();
--
1.8.4
-------------- next part --------------
>From 578cc30b79bdafa864cb3481e425783fa951a1cb Mon Sep 17 00:00:00 2001
From: Sergey Dmitrouk <sdmitrouk at accesssoftek.com>
Date: Fri, 3 Oct 2014 17:30:13 +0300
Subject: [PATCH 09/11] Add LLVM test for HonorFPExceptions
---
.../SimplifyCFG/do-not-hoist-fp-that-can-trap.ll | 28 ++++++++++++++++++++++
1 file changed, 28 insertions(+)
create mode 100644 test/Transforms/SimplifyCFG/do-not-hoist-fp-that-can-trap.ll
diff --git a/test/Transforms/SimplifyCFG/do-not-hoist-fp-that-can-trap.ll b/test/Transforms/SimplifyCFG/do-not-hoist-fp-that-can-trap.ll
new file mode 100644
index 0000000..351c6d7
--- /dev/null
+++ b/test/Transforms/SimplifyCFG/do-not-hoist-fp-that-can-trap.ll
@@ -0,0 +1,28 @@
+; The phi should not be replaced with select because operation raises exception.
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+define double @do-not-hoist-fp-that-can-trap(double %x, double %y) #0 {
+; CHECK-NOT: select
+; CHECK-NOT: double 0x7FF0000000000000
+; CHECK-NOT: double 0.000000e+00
+entry:
+ %x.addr = alloca double, align 8
+ %y.addr = alloca double, align 8
+ store double %x, double* %x.addr, align 8
+ store double %y, double* %y.addr, align 8
+ %0 = load double* %x.addr, align 8
+ %cmp = fcmp oeq double %0, 0.000000e+00
+ br i1 %cmp, label %cond.true, label %cond.false
+
+cond.true: ; preds = %entry
+ br label %cond.end
+
+cond.false: ; preds = %entry
+ br label %cond.end
+
+cond.end: ; preds = %cond.false, %cond.true
+ %cond = phi double [ fmul (double 1.000000e+300, double 1.000000e+300), %cond.true ], [ fmul (double 1.000000e-300, double 1.000000e-300), %cond.false ]
+ ret double %cond
+}
+
+attributes #0 = { "honor-fp-exceptions"="true" }
--
1.8.4
More information about the llvm-commits
mailing list