Index: llvm/lib/Analysis/ConstantFolding.cpp =================================================================== --- llvm/lib/Analysis/ConstantFolding.cpp +++ llvm/lib/Analysis/ConstantFolding.cpp @@ -3183,6 +3183,12 @@ break; } + case LibFunc_atan: + case LibFunc_atanf: + case LibFunc_atanl: + return !Op.isDenormal(); + + case LibFunc_asinl: case LibFunc_asin: case LibFunc_asinf: @@ -3248,6 +3254,21 @@ return Op0.isNaN() || Op1.isNaN() || (!Op0.isInfinity() && !Op1.isZero()); + case LibFunc_atan2: + case LibFunc_atan2f: + case LibFunc_atan2l: { + // atan2 can fail if the result underflows. Notice the magnitude of + // result is atan(Op0/Op1) and atan(x) approaches x at 0. + // Op0/Op1/2 is a conservative lowerbound for the result magnitue-wise + // If this bound is denormalized or rounds to 0, we return false. + auto Two = APFloat(2.0); + bool ignore; + Two.convert(Op0.getSemantics(), APFloat::rmNearestTiesToEven, &ignore); + auto ResLowerBound = Op0 / Op1 / Two; + return !ResLowerBound.isDenormal() && + !(!Op0.isZero() && ResLowerBound.isZero()); + } + default: break; } Index: llvm/test/Transforms/EarlyCSE/atan.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/EarlyCSE/atan.ll @@ -0,0 +1,112 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -early-cse -S < %s | FileCheck %s + +define float @callatan0() { +; CHECK-LABEL: @callatan0( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret float -0.000000e+00 +; +entry: + %call = call float @atanf(float -0.0) + ret float %call +} + +define float @callatanInf() { +; CHECK-LABEL: @callatanInf( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CALL:%.*]] = call float @atanf(float 0x7FF0000000000000) +; CHECK-NEXT: ret float [[CALL]] +; +entry: + %call = call float @atanf(float 0x7FF0000000000000) + ret float %call +} + +define float @callatanNaN() { +; CHECK-LABEL: @callatanNaN( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CALL:%.*]] = call float @atanf(float 0x7FF8000000000000) +; CHECK-NEXT: ret float [[CALL]] +; +entry: + %call = call float @atanf(float 0x7FF8000000000000) + ret float %call +} + +define float @callatanDenorm() { +; CHECK-LABEL: @callatanDenorm( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CALL:%.*]] = call float @atanf(float 0x37A16C2000000000) +; CHECK-NEXT: ret float 0x37A16C2000000000 +; +entry: + %call = call float @atanf(float 0x37A16C2000000000) + ret float %call +} + +define float @callatan2_00() { +; CHECK-LABEL: @callatan2_00( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret float -0.000000e+00 +; +entry: + %call = call float @atan2f(float -0.0, float 0.0) + ret float %call +} + +define float @callatan2_x0() { +; CHECK-LABEL: @callatan2_x0( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret float 0x3FF921FB60000000 +; +entry: + %call = call float @atan2f(float 1.0, float -0.000000e+00) + ret float %call +} + +define float @callatan2_0x() { +; CHECK-LABEL: @callatan2_0x( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret float -0.000000e+00 +; +entry: + %call = call float @atan2f(float -0.0, float 1.0) + ret float %call +} + +define float @callatan2_xx() { +; CHECK-LABEL: @callatan2_xx( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret float 0xBFE921FB60000000 +; +entry: + %call = call float @atan2f(float -1.0, float 1.0) + ret float %call +} + +define float @callatan2_denorm() { +; CHECK-LABEL: @callatan2_denorm( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CALL:%.*]] = call float @atan2f(float 0x39B4484C00000000, float 1.000000e+10) +; CHECK-NEXT: ret float 0x37A16C2000000000 +; +entry: + %call = call float @atan2f(float 0x39B4484C00000000, float 1.0e+10) + ret float %call +} + +define float @callatan2_flush_to_zero() { +; CHECK-LABEL: @callatan2_flush_to_zero( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CALL:%.*]] = call float @atan2f(float 0x39B4484C00000000, float 0x4415AF1D80000000) +; CHECK-NEXT: ret float 0.000000e+00 +; +entry: + %call = call float @atan2f(float 0x39B4484C00000000, float 0x4415AF1D80000000) + ret float %call +} + +declare dso_local float @atanf(float) #0 +declare dso_local float @atan2f(float, float) #0 + +attributes #0 = { nofree nounwind willreturn } \ No newline at end of file Index: llvm/test/Transforms/InstSimplify/ConstProp/math-1.ll =================================================================== --- llvm/test/Transforms/InstSimplify/ConstProp/math-1.ll +++ llvm/test/Transforms/InstSimplify/ConstProp/math-1.ll @@ -22,7 +22,6 @@ declare double @atan(double) #0 define double @f_atan() { ; CHECK-LABEL: @f_atan( -; CHECK-NEXT: [[RES:%.*]] = tail call fast double @atan(double 1.000000e+00) ; CHECK-NEXT: ret double 0x3FE921FB ; %res = tail call fast double @atan(double 1.0) Index: llvm/test/Transforms/InstSimplify/ConstProp/math-2.ll =================================================================== --- llvm/test/Transforms/InstSimplify/ConstProp/math-2.ll +++ llvm/test/Transforms/InstSimplify/ConstProp/math-2.ll @@ -4,7 +4,6 @@ declare double @atan2(double, double) #0 define double @f_atan2() { ; CHECK-LABEL: @f_atan2( -; CHECK-NEXT: [[RES:%.*]] = tail call fast double @atan2(double 1.000000e+00, double 2.000000e+00) ; CHECK-NEXT: ret double 0x3FDDAC6{{.+}} ; %res = tail call fast double @atan2(double 1.0, double 2.0)