1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 11:02:59 +02:00

Make special cases (0 inf nan) work for frem.

Besides APFloat, this involved removing code
from two places that thought they knew the
result of frem(0., x) but were wrong.

llvm-svn: 62645
This commit is contained in:
Dale Johannesen 2009-01-21 00:35:19 +00:00
parent 10ad717dc8
commit 6854f86296
5 changed files with 384 additions and 38 deletions

View File

@ -293,6 +293,7 @@ namespace llvm {
opStatus addOrSubtractSpecials(const APFloat &, bool subtract);
opStatus divideSpecials(const APFloat &);
opStatus multiplySpecials(const APFloat &);
opStatus modSpecials(const APFloat &);
/* Miscellany. */
void makeNaN(void);

View File

@ -1405,6 +1405,42 @@ APFloat::divideSpecials(const APFloat &rhs)
}
}
APFloat::opStatus
APFloat::modSpecials(const APFloat &rhs)
{
switch(convolve(category, rhs.category)) {
default:
assert(0);
case convolve(fcNaN, fcZero):
case convolve(fcNaN, fcNormal):
case convolve(fcNaN, fcInfinity):
case convolve(fcNaN, fcNaN):
case convolve(fcZero, fcInfinity):
case convolve(fcZero, fcNormal):
case convolve(fcNormal, fcInfinity):
return opOK;
case convolve(fcZero, fcNaN):
case convolve(fcNormal, fcNaN):
case convolve(fcInfinity, fcNaN):
category = fcNaN;
copySignificand(rhs);
return opOK;
case convolve(fcNormal, fcZero):
case convolve(fcInfinity, fcZero):
case convolve(fcInfinity, fcNormal):
case convolve(fcInfinity, fcInfinity):
case convolve(fcZero, fcZero):
makeNaN();
return opInvalidOp;
case convolve(fcNormal, fcNormal):
return opOK;
}
}
/* Change sign. */
void
APFloat::changeSign()
@ -1557,10 +1593,13 @@ APFloat::opStatus
APFloat::mod(const APFloat &rhs, roundingMode rounding_mode)
{
opStatus fs;
assertArithmeticOK(*semantics);
fs = modSpecials(rhs);
if (category == fcNormal && rhs.category == fcNormal) {
APFloat V = *this;
unsigned int origSign = sign;
assertArithmeticOK(*semantics);
fs = V.divide(rhs, rmNearestTiesToEven);
if (fs == opDivByZero)
return fs;
@ -1586,6 +1625,7 @@ APFloat::mod(const APFloat &rhs, roundingMode rounding_mode)
if (isZero())
sign = origSign; // IEEE754 requires this
delete[] x;
}
return fs;
}

View File

@ -2954,11 +2954,6 @@ Instruction *InstCombiner::visitFDiv(BinaryOperator &I) {
Instruction *InstCombiner::commonRemTransforms(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
// 0 % X == 0 for integer, we don't need to preserve faults!
if (Constant *LHS = dyn_cast<Constant>(Op0))
if (LHS->isNullValue())
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
if (isa<UndefValue>(Op0)) { // undef % X -> 0
if (I.getType()->isFPOrFPVector())
return ReplaceInstUsesWith(I, Op0); // X % undef -> undef (could be SNaN)
@ -2984,6 +2979,11 @@ Instruction *InstCombiner::commonIRemTransforms(BinaryOperator &I) {
if (Instruction *common = commonRemTransforms(I))
return common;
// 0 % X == 0 for integer, we don't need to preserve faults!
if (Constant *LHS = dyn_cast<Constant>(Op0))
if (LHS->isNullValue())
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
// X % 0 == undef, we don't need to preserve faults!
if (RHS->equalsInt(0))

View File

@ -802,16 +802,6 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
(void)C3V.divide(C2V, APFloat::rmNearestTiesToEven);
return ConstantFP::get(C3V);
case Instruction::FRem:
if (C2V.isZero()) {
// IEEE 754, Section 7.1, #5
if (CFP1->getType() == Type::DoubleTy)
return ConstantFP::get(APFloat(std::numeric_limits<double>::
quiet_NaN()));
if (CFP1->getType() == Type::FloatTy)
return ConstantFP::get(APFloat(std::numeric_limits<float>::
quiet_NaN()));
break;
}
(void)C3V.mod(C2V, APFloat::rmNearestTiesToEven);
return ConstantFP::get(C3V);
}

View File

@ -0,0 +1,315 @@
; RUN: llvm-as < %s | opt -simplifycfg -instcombine | llvm-dis | grep 0x7FF8000000000000 | count 7
; RUN: llvm-as < %s | opt -simplifycfg -instcombine | llvm-dis | grep 0x7FF80000FFFFFFFF | count 5
; RUN: llvm-as < %s | opt -simplifycfg -instcombine | llvm-dis | grep {0\\.0} | count 3
; RUN: llvm-as < %s | opt -simplifycfg -instcombine | llvm-dis | grep {3\\.5} | count 1
; ModuleID = 'apf.c'
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
target triple = "i386-apple-darwin9.6"
@"\01LC" = internal constant [4 x i8] c"%f\0A\00" ; <[4 x i8]*> [#uses=1]
define void @foo1() nounwind {
entry:
%y = alloca float ; <float*> [#uses=2]
%x = alloca float ; <float*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store float 0x7FF0000000000000, float* %x, align 4
store float 0x7FF8000000000000, float* %y, align 4
%0 = load float* %y, align 4 ; <float> [#uses=1]
%1 = fpext float %0 to double ; <double> [#uses=1]
%2 = load float* %x, align 4 ; <float> [#uses=1]
%3 = fpext float %2 to double ; <double> [#uses=1]
%4 = frem double %3, %1 ; <double> [#uses=1]
%5 = call i32 (i8*, ...)* @printf(i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), double %4) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %entry
ret void
}
declare i32 @printf(i8*, ...) nounwind
define void @foo2() nounwind {
entry:
%y = alloca float ; <float*> [#uses=2]
%x = alloca float ; <float*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store float 0x7FF0000000000000, float* %x, align 4
store float 0.000000e+00, float* %y, align 4
%0 = load float* %y, align 4 ; <float> [#uses=1]
%1 = fpext float %0 to double ; <double> [#uses=1]
%2 = load float* %x, align 4 ; <float> [#uses=1]
%3 = fpext float %2 to double ; <double> [#uses=1]
%4 = frem double %3, %1 ; <double> [#uses=1]
%5 = call i32 (i8*, ...)* @printf(i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), double %4) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %entry
ret void
}
define void @foo3() nounwind {
entry:
%y = alloca float ; <float*> [#uses=2]
%x = alloca float ; <float*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store float 0x7FF0000000000000, float* %x, align 4
store float 3.500000e+00, float* %y, align 4
%0 = load float* %y, align 4 ; <float> [#uses=1]
%1 = fpext float %0 to double ; <double> [#uses=1]
%2 = load float* %x, align 4 ; <float> [#uses=1]
%3 = fpext float %2 to double ; <double> [#uses=1]
%4 = frem double %3, %1 ; <double> [#uses=1]
%5 = call i32 (i8*, ...)* @printf(i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), double %4) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %entry
ret void
}
define void @foo4() nounwind {
entry:
%y = alloca float ; <float*> [#uses=2]
%x = alloca float ; <float*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store float 0x7FF0000000000000, float* %x, align 4
store float 0x7FF0000000000000, float* %y, align 4
%0 = load float* %y, align 4 ; <float> [#uses=1]
%1 = fpext float %0 to double ; <double> [#uses=1]
%2 = load float* %x, align 4 ; <float> [#uses=1]
%3 = fpext float %2 to double ; <double> [#uses=1]
%4 = frem double %3, %1 ; <double> [#uses=1]
%5 = call i32 (i8*, ...)* @printf(i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), double %4) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %entry
ret void
}
define void @foo5() nounwind {
entry:
%y = alloca float ; <float*> [#uses=2]
%x = alloca float ; <float*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store float 0x7FF8000000000000, float* %x, align 4
store float 0x7FF0000000000000, float* %y, align 4
%0 = load float* %y, align 4 ; <float> [#uses=1]
%1 = fpext float %0 to double ; <double> [#uses=1]
%2 = load float* %x, align 4 ; <float> [#uses=1]
%3 = fpext float %2 to double ; <double> [#uses=1]
%4 = frem double %3, %1 ; <double> [#uses=1]
%5 = call i32 (i8*, ...)* @printf(i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), double %4) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %entry
ret void
}
define void @foo6() nounwind {
entry:
%y = alloca float ; <float*> [#uses=2]
%x = alloca float ; <float*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store float 0x7FF8000000000000, float* %x, align 4
store float 0.000000e+00, float* %y, align 4
%0 = load float* %y, align 4 ; <float> [#uses=1]
%1 = fpext float %0 to double ; <double> [#uses=1]
%2 = load float* %x, align 4 ; <float> [#uses=1]
%3 = fpext float %2 to double ; <double> [#uses=1]
%4 = frem double %3, %1 ; <double> [#uses=1]
%5 = call i32 (i8*, ...)* @printf(i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), double %4) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %entry
ret void
}
define void @foo7() nounwind {
entry:
%y = alloca float ; <float*> [#uses=2]
%x = alloca float ; <float*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store float 0x7FF8000000000000, float* %x, align 4
store float 3.500000e+00, float* %y, align 4
%0 = load float* %y, align 4 ; <float> [#uses=1]
%1 = fpext float %0 to double ; <double> [#uses=1]
%2 = load float* %x, align 4 ; <float> [#uses=1]
%3 = fpext float %2 to double ; <double> [#uses=1]
%4 = frem double %3, %1 ; <double> [#uses=1]
%5 = call i32 (i8*, ...)* @printf(i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), double %4) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %entry
ret void
}
define void @foo8() nounwind {
entry:
%y = alloca float ; <float*> [#uses=2]
%x = alloca float ; <float*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store float 0x7FF8000000000000, float* %x, align 4
store float 0x7FF8000000000000, float* %y, align 4
%0 = load float* %y, align 4 ; <float> [#uses=1]
%1 = fpext float %0 to double ; <double> [#uses=1]
%2 = load float* %x, align 4 ; <float> [#uses=1]
%3 = fpext float %2 to double ; <double> [#uses=1]
%4 = frem double %3, %1 ; <double> [#uses=1]
%5 = call i32 (i8*, ...)* @printf(i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), double %4) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %entry
ret void
}
define void @foo9() nounwind {
entry:
%y = alloca float ; <float*> [#uses=2]
%x = alloca float ; <float*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store float 0.000000e+00, float* %x, align 4
store float 0x7FF8000000000000, float* %y, align 4
%0 = load float* %y, align 4 ; <float> [#uses=1]
%1 = fpext float %0 to double ; <double> [#uses=1]
%2 = load float* %x, align 4 ; <float> [#uses=1]
%3 = fpext float %2 to double ; <double> [#uses=1]
%4 = frem double %3, %1 ; <double> [#uses=1]
%5 = call i32 (i8*, ...)* @printf(i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), double %4) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %entry
ret void
}
define void @foo10() nounwind {
entry:
%y = alloca float ; <float*> [#uses=2]
%x = alloca float ; <float*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store float 0.000000e+00, float* %x, align 4
store float 0x7FF0000000000000, float* %y, align 4
%0 = load float* %y, align 4 ; <float> [#uses=1]
%1 = fpext float %0 to double ; <double> [#uses=1]
%2 = load float* %x, align 4 ; <float> [#uses=1]
%3 = fpext float %2 to double ; <double> [#uses=1]
%4 = frem double %3, %1 ; <double> [#uses=1]
%5 = call i32 (i8*, ...)* @printf(i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), double %4) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %entry
ret void
}
define void @foo11() nounwind {
entry:
%y = alloca float ; <float*> [#uses=2]
%x = alloca float ; <float*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store float 0.000000e+00, float* %x, align 4
store float 0.000000e+00, float* %y, align 4
%0 = load float* %y, align 4 ; <float> [#uses=1]
%1 = fpext float %0 to double ; <double> [#uses=1]
%2 = load float* %x, align 4 ; <float> [#uses=1]
%3 = fpext float %2 to double ; <double> [#uses=1]
%4 = frem double %3, %1 ; <double> [#uses=1]
%5 = call i32 (i8*, ...)* @printf(i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), double %4) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %entry
ret void
}
define void @foo12() nounwind {
entry:
%y = alloca float ; <float*> [#uses=2]
%x = alloca float ; <float*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store float 0.000000e+00, float* %x, align 4
store float 3.500000e+00, float* %y, align 4
%0 = load float* %y, align 4 ; <float> [#uses=1]
%1 = fpext float %0 to double ; <double> [#uses=1]
%2 = load float* %x, align 4 ; <float> [#uses=1]
%3 = fpext float %2 to double ; <double> [#uses=1]
%4 = frem double %3, %1 ; <double> [#uses=1]
%5 = call i32 (i8*, ...)* @printf(i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), double %4) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %entry
ret void
}
define void @foo13() nounwind {
entry:
%y = alloca float ; <float*> [#uses=2]
%x = alloca float ; <float*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store float 3.500000e+00, float* %x, align 4
store float 0x7FF8000000000000, float* %y, align 4
%0 = load float* %y, align 4 ; <float> [#uses=1]
%1 = fpext float %0 to double ; <double> [#uses=1]
%2 = load float* %x, align 4 ; <float> [#uses=1]
%3 = fpext float %2 to double ; <double> [#uses=1]
%4 = frem double %3, %1 ; <double> [#uses=1]
%5 = call i32 (i8*, ...)* @printf(i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), double %4) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %entry
ret void
}
define void @foo14() nounwind {
entry:
%y = alloca float ; <float*> [#uses=2]
%x = alloca float ; <float*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store float 3.500000e+00, float* %x, align 4
store float 0x7FF0000000000000, float* %y, align 4
%0 = load float* %y, align 4 ; <float> [#uses=1]
%1 = fpext float %0 to double ; <double> [#uses=1]
%2 = load float* %x, align 4 ; <float> [#uses=1]
%3 = fpext float %2 to double ; <double> [#uses=1]
%4 = frem double %3, %1 ; <double> [#uses=1]
%5 = call i32 (i8*, ...)* @printf(i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), double %4) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %entry
ret void
}
define void @foo15() nounwind {
entry:
%y = alloca float ; <float*> [#uses=2]
%x = alloca float ; <float*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store float 3.500000e+00, float* %x, align 4
store float 0.000000e+00, float* %y, align 4
%0 = load float* %y, align 4 ; <float> [#uses=1]
%1 = fpext float %0 to double ; <double> [#uses=1]
%2 = load float* %x, align 4 ; <float> [#uses=1]
%3 = fpext float %2 to double ; <double> [#uses=1]
%4 = frem double %3, %1 ; <double> [#uses=1]
%5 = call i32 (i8*, ...)* @printf(i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), double %4) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %entry
ret void
}
define void @foo16() nounwind {
entry:
%y = alloca float ; <float*> [#uses=2]
%x = alloca float ; <float*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store float 3.500000e+00, float* %x, align 4
store float 3.500000e+00, float* %y, align 4
%0 = load float* %y, align 4 ; <float> [#uses=1]
%1 = fpext float %0 to double ; <double> [#uses=1]
%2 = load float* %x, align 4 ; <float> [#uses=1]
%3 = fpext float %2 to double ; <double> [#uses=1]
%4 = frem double %3, %1 ; <double> [#uses=1]
%5 = call i32 (i8*, ...)* @printf(i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), double %4) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %entry
ret void
}