[llvm] r218803 - Make the sqrt intrinsic return undef for a negative input.

Sanjay Patel spatel at rotateright.com
Wed Oct 1 13:36:33 PDT 2014

Author: spatel
Date: Wed Oct  1 15:36:33 2014
New Revision: 218803

URL: http://llvm.org/viewvc/llvm-project?rev=218803&view=rev
Make the sqrt intrinsic return undef for a negative input.

As discussed here:

And again here:

The sqrt of a negative number when using the llvm intrinsic is undefined. 
We should return undef rather than 0.0 to match the definition in the LLVM IR lang ref.

This change should not affect any code that isn't using "no-nans-fp-math"; 
ie, no-nans is a requirement for generating the llvm intrinsic in place of a sqrt function call.

Unfortunately, the behavior introduced by this patch will not match current gcc, xlc, icc, and 
possibly other compilers. The current clang/llvm behavior of returning 0.0 doesn't either. 
We knowingly approve of this difference with the other compilers in an attempt to flag code 
that is invoking undefined behavior.

A front-end warning should also try to convince the user that the program will fail:

Differential Revision: http://reviews.llvm.org/D5527


Modified: llvm/trunk/lib/Analysis/ConstantFolding.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ConstantFolding.cpp?rev=218803&r1=218802&r2=218803&view=diff
--- llvm/trunk/lib/Analysis/ConstantFolding.cpp (original)
+++ llvm/trunk/lib/Analysis/ConstantFolding.cpp Wed Oct  1 15:36:33 2014
@@ -1520,8 +1520,14 @@ static Constant *ConstantFoldScalarCall(
                  (Ty->isHalfTy() || Ty->isFloatTy() || Ty->isDoubleTy())) {
           if (V >= -0.0)
             return ConstantFoldFP(sqrt, V, Ty);
-          else // Undefined
-            return Constant::getNullValue(Ty);
+          else {
+            // Unlike the sqrt definitions in C/C++, POSIX, and IEEE-754 - which
+            // all guarantee or favor returning NaN - the square root of a
+            // negative number is not defined for the LLVM sqrt intrinsic.
+            // This is because the intrinsic should only be emitted in place of
+            // libm's sqrt function when using "no-nans-fp-math".
+            return UndefValue::get(Ty);
+          }
       case 's':

Modified: llvm/trunk/test/Transforms/InstCombine/constant-fold-math.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/constant-fold-math.ll?rev=218803&r1=218802&r2=218803&view=diff
--- llvm/trunk/test/Transforms/InstCombine/constant-fold-math.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/constant-fold-math.ll Wed Oct  1 15:36:33 2014
@@ -7,6 +7,7 @@ declare <4 x float> @llvm.fma.v4f32(<4 x
 declare double @llvm.fma.f64(double, double, double) #0
 declare double @llvm.fmuladd.f64(double, double, double) #0
+declare double @llvm.sqrt.f64(double) #0
 ; CHECK-LABEL: @constant_fold_fma_f32
@@ -44,4 +45,12 @@ define double @constant_fold_fmuladd_f64
   ret double %x
+; The sqrt intrinsic is undefined for negative inputs besides -0.0.
+; CHECK-LABEL: @bad_sqrt
+; CHECK-NEXT: ret double undef
+define double @bad_sqrt() {
+  %x = call double @llvm.sqrt.f64(double -2.000000e+00)
+  ret double %x
 attributes #0 = { nounwind readnone }

More information about the llvm-commits mailing list