From 68fb712245390fc74a16e3072d37f3403a032040 Mon Sep 17 00:00:00 2001 From: JF Bastien Date: Fri, 6 Sep 2019 16:26:59 +0000 Subject: [PATCH] [InstCombine] pow(x, +/- 0.0) -> 1.0 Summary: This isn't an important optimization at all... We're already doing: pow(x, 0.0) -> 1.0 My patch merely teaches instcombine that -0.0 does the same. However, doing this fixes an AMAZING bug! Compile this program: extern "C" double pow(double, double); double boom(double base) { return pow(base, -0.0); } With: clang++ ~/Desktop/fast-math.cpp -ffast-math -O2 -S And clang will crash with a signal. Wow, fast math is so fast it ICEs the compiler! Arguably, the generated math is infinitely fast. What's actually happening is that we recurse infinitely in getPow. In debug we hit its assertion: assert(Exp != 0 && "Incorrect exponent 0 not handled"); We avoid this entire mess if we instead recognize that an exponent of positive and negative zero yield 1.0. A separate commit, r371221, fixed the same problem. This only contains the added tests. Reviewers: scanon Subscribers: hiraditya, jkorous, dexonsmith, ributzka, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D67248 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@371224 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Transforms/InstCombine/pow-0.ll | 60 ++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 test/Transforms/InstCombine/pow-0.ll diff --git a/test/Transforms/InstCombine/pow-0.ll b/test/Transforms/InstCombine/pow-0.ll new file mode 100644 index 00000000000..8de8e12a2d1 --- /dev/null +++ b/test/Transforms/InstCombine/pow-0.ll @@ -0,0 +1,60 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; CHECK-LABEL: @zero( +; CHECK-NEXT: ret double 1.000000e+00 +define double @zero(double %value) { + %res = call double @llvm.pow.f64(double %value, double 0.000000e+00) + ret double %res +} + +; CHECK-LABEL: @minus_zero( +; CHECK-NEXT: ret double 1.000000e+00 +define double @minus_zero(double %value) { + %res = call double @llvm.pow.f64(double %value, double -0.000000e+00) + ret double %res +} + +; CHECK-LABEL: @fast_zero( +; CHECK-NEXT: ret double 1.000000e+00 +define double @fast_zero(double %value) { + %res = call fast double @llvm.pow.f64(double %value, double 0.000000e+00) + ret double %res +} + +; CHECK-LABEL: @fast_minus_zero( +; CHECK-NEXT: ret double 1.000000e+00 +define double @fast_minus_zero(double %value) { + %res = call fast double @llvm.pow.f64(double %value, double -0.000000e+00) + ret double %res +} + +; CHECK-LABEL: @vec_zero( +; CHECK-NEXT: ret <2 x double> +define <2 x double> @vec_zero(<2 x double> %value) { + %res = call <2 x double> @llvm.pow.v2f64(<2 x double> %value, <2 x double> ) + ret <2 x double> %res +} + +; CHECK-LABEL: @vec_minus_zero( +; CHECK-NEXT: ret <2 x double> +define <2 x double> @vec_minus_zero(<2 x double> %value) { + %res = call <2 x double> @llvm.pow.v2f64(<2 x double> %value, <2 x double> ) + ret <2 x double> %res +} + +; CHECK-LABEL: @vec_fast_zero( +; CHECK-NEXT: ret <2 x double> +define <2 x double> @vec_fast_zero(<2 x double> %value) { + %res = call fast <2 x double> @llvm.pow.v2f64(<2 x double> %value, <2 x double> ) + ret <2 x double> %res +} + +; CHECK-LABEL: @vec_fast_minus_zero( +; CHECK-NEXT: ret <2 x double> +define <2 x double> @vec_fast_minus_zero(<2 x double> %value) { + %res = call fast <2 x double> @llvm.pow.v2f64(<2 x double> %value, <2 x double> ) + ret <2 x double> %res +} + +declare double @llvm.pow.f64(double, double) +declare <2 x double> @llvm.pow.v2f64(<2 x double>, <2 x double>) -- 2.40.0