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
This commit is contained in:
Shuxin Yang 2013-01-09 00:13:41 +00:00
parent b6714227ed
commit 935e35d2b9
7 changed files with 35 additions and 9 deletions

View File

@ -61,6 +61,9 @@ public:
/// 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;

View File

@ -309,7 +309,7 @@ public:
/// 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

View File

@ -51,6 +51,15 @@ bool Constant::isNegativeZeroValue() const {
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))

View File

@ -1926,11 +1926,14 @@ bool BinaryOperator::isNeg(const Value *V) {
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;
}

View File

@ -211,7 +211,7 @@ public:
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);

View File

@ -516,8 +516,8 @@ Value *InstCombiner::dyn_castNegVal(Value *V) const {
// 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.

View File

@ -243,5 +243,16 @@ define float @fmul5(float %f1, float %f2) {
; 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
}