Fix a bug in fast-math fadd/fsub simplification.

The problem is that the code mistakenly took for granted that following constructor 
is able to create an APFloat from a *SIGNED* integer:
   
  APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value)

rdar://13486998


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177906 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Shuxin Yang 2013-03-25 20:43:41 +00:00
parent dceaf4ac8d
commit c76067b774
2 changed files with 53 additions and 10 deletions

View File

@ -44,7 +44,7 @@ namespace {
}
void set(const APFloat& C);
void negate();
bool isZero() const { return isInt() ? !IntVal : getFpVal().isZero(); }
@ -79,6 +79,14 @@ namespace {
bool isInt() const { return !IsFp; }
// If the coefficient is represented by an integer, promote it to a
// floating point.
void convertToFpType(const fltSemantics &Sem);
// Construct an APFloat from a signed integer.
// TODO: We should get rid of this function when APFloat can be constructed
// from an *SIGNED* integer.
APFloat createAPFloatFromInt(const fltSemantics &Sem, int Val);
private:
bool IsFp;
@ -206,7 +214,31 @@ void FAddendCoef::set(const APFloat& C) {
IsFp = BufHasFpVal = true;
}
void FAddendCoef::operator=(const FAddendCoef& That) {
void FAddendCoef::convertToFpType(const fltSemantics &Sem) {
if (!isInt())
return;
APFloat *P = getFpValPtr();
if (IntVal > 0)
new(P) APFloat(Sem, IntVal);
else {
new(P) APFloat(Sem, 0 - IntVal);
P->changeSign();
}
IsFp = BufHasFpVal = true;
}
APFloat FAddendCoef::createAPFloatFromInt(const fltSemantics &Sem, int Val) {
if (Val >= 0)
return APFloat(Sem, Val);
APFloat T(Sem, 0 - Val);
T.changeSign();
return T;
}
void FAddendCoef::operator=(const FAddendCoef &That) {
if (That.isInt())
set(That.IntVal);
else
@ -225,13 +257,13 @@ void FAddendCoef::operator+=(const FAddendCoef &That) {
if (isInt()) {
const APFloat &T = That.getFpVal();
set(T);
getFpVal().add(APFloat(T.getSemantics(), IntVal), RndMode);
convertToFpType(T.getSemantics());
getFpVal().add(T, RndMode);
return;
}
APFloat &T = getFpVal();
T.add(APFloat(T.getSemantics(), That.IntVal), RndMode);
T.add(createAPFloatFromInt(T.getSemantics(), That.IntVal), RndMode);
}
void FAddendCoef::operator-=(const FAddendCoef &That) {
@ -246,13 +278,13 @@ void FAddendCoef::operator-=(const FAddendCoef &That) {
if (isInt()) {
const APFloat &T = That.getFpVal();
set(T);
getFpVal().subtract(APFloat(T.getSemantics(), IntVal), RndMode);
convertToFpType(T.getSemantics());
getFpVal().subtract(T, RndMode);
return;
}
APFloat &T = getFpVal();
T.subtract(APFloat(T.getSemantics(), IntVal), RndMode);
T.subtract(createAPFloatFromInt(T.getSemantics(), IntVal), RndMode);
}
void FAddendCoef::operator*=(const FAddendCoef &That) {
@ -275,11 +307,12 @@ void FAddendCoef::operator*=(const FAddendCoef &That) {
isInt() ? That.getFpVal().getSemantics() : getFpVal().getSemantics();
if (isInt())
set(APFloat(Semantic, IntVal));
convertToFpType(Semantic);
APFloat &F0 = getFpVal();
if (That.isInt())
F0.multiply(APFloat(Semantic, That.IntVal), APFloat::rmNearestTiesToEven);
F0.multiply(createAPFloatFromInt(Semantic, That.IntVal),
APFloat::rmNearestTiesToEven);
else
F0.multiply(That.getFpVal(), APFloat::rmNearestTiesToEven);

View File

@ -130,6 +130,16 @@ define double @fail2(double %f1, double %f2) {
; CHECK: ret
}
; c1 * x - x => (c1 - 1.0) * x
define float @fold13(float %x) {
%mul = fmul fast float %x, 7.000000e+00
%sub = fsub fast float %mul, %x
ret float %sub
; CHECK: fold13
; CHECK: fmul fast float %x, 6.000000e+00
; CHECK: ret
}
; =========================================================================
;
; Testing-cases about fmul begin