Consider expression "0.0 - X" as the negation of X if
- this expression is explicitly marked no-signed-zero, or
- no-signed-zero of this expression can be derived from some context.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171922 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h
index 36a4538..5a3ba28 100644
--- a/include/llvm/IR/Constant.h
+++ b/include/llvm/IR/Constant.h
@@ -61,6 +61,9 @@
/// by getZeroValueForNegation.
bool isNegativeZeroValue() const;
+ /// Return true if the value is negative zero or null value.
+ bool isZeroValue() const;
+
/// 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;
diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h
index 66bf8dd..7ee5cdb 100644
--- a/include/llvm/IR/InstrTypes.h
+++ b/include/llvm/IR/InstrTypes.h
@@ -309,7 +309,7 @@
/// NEG, FNeg, or NOT instruction.
///
static bool isNeg(const Value *V);
- static bool isFNeg(const Value *V);
+ static bool isFNeg(const Value *V, bool IgnoreZeroSign=false);
static bool isNot(const Value *V);
/// getNegArgument, getNotArgument - Helper functions to extract the
diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp
index 4b58599..812692f 100644
--- a/lib/IR/Constants.cpp
+++ b/lib/IR/Constants.cpp
@@ -51,6 +51,15 @@
return isNullValue();
}
+bool Constant::isZeroValue() const {
+ // Floating point values have an explicit -0.0 value.
+ if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
+ return CFP->isZero();
+
+ // Otherwise, just use +0.0.
+ return isNullValue();
+}
+
bool Constant::isNullValue() const {
// 0 is null.
if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp
index 1b5d004..f2e9813 100644
--- a/lib/IR/Instructions.cpp
+++ b/lib/IR/Instructions.cpp
@@ -1926,11 +1926,14 @@
return false;
}
-bool BinaryOperator::isFNeg(const Value *V) {
+bool BinaryOperator::isFNeg(const Value *V, bool IgnoreZeroSign) {
if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V))
if (Bop->getOpcode() == Instruction::FSub)
- if (Constant* C = dyn_cast<Constant>(Bop->getOperand(0)))
- return C->isNegativeZeroValue();
+ if (Constant* C = dyn_cast<Constant>(Bop->getOperand(0))) {
+ if (!IgnoreZeroSign)
+ IgnoreZeroSign = cast<Instruction>(V)->hasNoSignedZeros();
+ return !IgnoreZeroSign ? C->isNegativeZeroValue() : C->isZeroValue();
+ }
return false;
}
diff --git a/lib/Transforms/InstCombine/InstCombine.h b/lib/Transforms/InstCombine/InstCombine.h
index 959daa2..a36b1e6 100644
--- a/lib/Transforms/InstCombine/InstCombine.h
+++ b/lib/Transforms/InstCombine/InstCombine.h
@@ -211,7 +211,7 @@
private:
bool ShouldChangeType(Type *From, Type *To) const;
Value *dyn_castNegVal(Value *V) const;
- Value *dyn_castFNegVal(Value *V) const;
+ Value *dyn_castFNegVal(Value *V, bool NoSignedZero=false) const;
Type *FindElementAtOffset(Type *Ty, int64_t Offset,
SmallVectorImpl<Value*> &NewIndices);
Instruction *FoldOpIntoSelect(Instruction &Op, SelectInst *SI);
diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp
index 6f24cdd..dc7fe5c 100644
--- a/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -516,8 +516,8 @@
// instruction if the LHS is a constant negative zero (which is the 'negate'
// form).
//
-Value *InstCombiner::dyn_castFNegVal(Value *V) const {
- if (BinaryOperator::isFNeg(V))
+Value *InstCombiner::dyn_castFNegVal(Value *V, bool IgnoreZeroSign) const {
+ if (BinaryOperator::isFNeg(V, IgnoreZeroSign))
return BinaryOperator::getFNegArgument(V);
// Constants can be considered to be negated values if they can be folded.
diff --git a/test/Transforms/InstCombine/fast-math.ll b/test/Transforms/InstCombine/fast-math.ll
index 5d40d71..df0455a 100644
--- a/test/Transforms/InstCombine/fast-math.ll
+++ b/test/Transforms/InstCombine/fast-math.ll
@@ -243,5 +243,16 @@
; CHECK: fdiv fast float %f1, 0x47E8000000000000
}
-
-
+; =========================================================================
+;
+; Testing-cases about negation
+;
+; =========================================================================
+define float @fneg1(float %f1, float %f2) {
+ %sub = fsub float -0.000000e+00, %f1
+ %sub1 = fsub nsz float 0.000000e+00, %f2
+ %mul = fmul float %sub, %sub1
+ ret float %mul
+; CHECK: @fneg1
+; CHECK: fmul float %f1, %f2
+}