[PATCH] D39642: [ValueTracking] readnone is a requirement for converting sqrt to llvm.sqrt; nnan is not

Sanjay Patel via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 5 08:53:27 PST 2017


spatel created this revision.
Herald added a subscriber: mcrosier.

As discussed in https://reviews.llvm.org/D39204, this is effectively a revert of https://reviews.llvm.org/rL265521 which required nnan to vectorize sqrt libcalls based on the old LangRef definition of llvm.sqrt.

We have the right check to know that errno is not set:

  if (!ICS.onlyReadsMemory())

...ahead of the switch.

But after reviewing the C standard text, I'm not sure the previous behavior was correct in the first place. If "implementation-defined" is actually defined by the platform, then a compiler can't assume that value (is nan) as we were doing?

This will solve https://bugs.llvm.org/show_bug.cgi?id=27435 although I'm still planning to make clang changes for intrinsics after https://reviews.llvm.org/D39611. That would create the sqrt intrinsic before we ever reach this place in LLVM.


https://reviews.llvm.org/D39642

Files:
  lib/Analysis/ValueTracking.cpp
  test/Transforms/SLPVectorizer/X86/call.ll


Index: test/Transforms/SLPVectorizer/X86/call.ll
===================================================================
--- test/Transforms/SLPVectorizer/X86/call.ll
+++ test/Transforms/SLPVectorizer/X86/call.ll
@@ -91,20 +91,51 @@
   ret void
 }
 
-define void @sqrt_libm(double* %a, double* %b) {
-; CHECK-LABEL: @sqrt_libm(
+; No fast-math-flags are required to convert sqrt library calls to an intrinsic. 
+; We just need to know that errno is not set (readnone).
+
+define void @sqrt_libm_no_errno(double* %a, double* %b) {
+; CHECK-LABEL: @sqrt_libm_no_errno(
 ; CHECK-NEXT:    [[TMP1:%.*]] = bitcast double* %a to <2 x double>*
 ; CHECK-NEXT:    [[TMP2:%.*]] = load <2 x double>, <2 x double>* [[TMP1]], align 8
-; CHECK-NEXT:    [[TMP3:%.*]] = call nnan <2 x double> @llvm.sqrt.v2f64(<2 x double> [[TMP2]])
+; CHECK-NEXT:    [[TMP3:%.*]] = call <2 x double> @llvm.sqrt.v2f64(<2 x double> [[TMP2]])
 ; CHECK-NEXT:    [[TMP4:%.*]] = bitcast double* %b to <2 x double>*
 ; CHECK-NEXT:    store <2 x double> [[TMP3]], <2 x double>* [[TMP4]], align 8
 ; CHECK-NEXT:    ret void
 ;
   %a0 = load double, double* %a, align 8
   %idx1 = getelementptr inbounds double, double* %a, i64 1
   %a1 = load double, double* %idx1, align 8
-  %sqrt1 = tail call nnan double @sqrt(double %a0) nounwind readnone
-  %sqrt2 = tail call nnan double @sqrt(double %a1) nounwind readnone
+  %sqrt1 = tail call double @sqrt(double %a0) nounwind readnone
+  %sqrt2 = tail call double @sqrt(double %a1) nounwind readnone
+  store double %sqrt1, double* %b, align 8
+  %idx2 = getelementptr inbounds double, double* %b, i64 1
+  store double %sqrt2, double* %idx2, align 8
+  ret void
+}
+
+; The sqrt intrinsic does not set errno, but a non-constant sqrt call might, so this can't vectorize.
+; The nnan on the call does not matter because there's no guarantee in the C standard that a negative
+; input would result in a nan output ("On a domain error, the function returns an 
+; implementation-defined value.")
+
+define void @sqrt_libm_errno(double* %a, double* %b) {
+; CHECK-LABEL: @sqrt_libm_errno(
+; CHECK-NEXT:    [[A0:%.*]] = load double, double* %a, align 8
+; CHECK-NEXT:    [[IDX1:%.*]] = getelementptr inbounds double, double* %a, i64 1
+; CHECK-NEXT:    [[A1:%.*]] = load double, double* [[IDX1]], align 8
+; CHECK-NEXT:    [[SQRT1:%.*]] = tail call nnan double @sqrt(double [[A0]]) #2
+; CHECK-NEXT:    [[SQRT2:%.*]] = tail call nnan double @sqrt(double [[A1]]) #2
+; CHECK-NEXT:    store double [[SQRT1]], double* %b, align 8
+; CHECK-NEXT:    [[IDX2:%.*]] = getelementptr inbounds double, double* %b, i64 1
+; CHECK-NEXT:    store double [[SQRT2]], double* [[IDX2]], align 8
+; CHECK-NEXT:    ret void
+;
+  %a0 = load double, double* %a, align 8
+  %idx1 = getelementptr inbounds double, double* %a, i64 1
+  %a1 = load double, double* %idx1, align 8
+  %sqrt1 = tail call nnan double @sqrt(double %a0) nounwind
+  %sqrt2 = tail call nnan double @sqrt(double %a1) nounwind
   store double %sqrt1, double* %b, align 8
   %idx2 = getelementptr inbounds double, double* %b, i64 1
   store double %sqrt2, double* %idx2, align 8
@@ -117,8 +148,8 @@
 ; CHECK-NEXT:    [[A0:%.*]] = load i64, i64* %a, align 8
 ; CHECK-NEXT:    [[IDX1:%.*]] = getelementptr inbounds i64, i64* %a, i64 1
 ; CHECK-NEXT:    [[A1:%.*]] = load i64, i64* [[IDX1]], align 8
-; CHECK-NEXT:    [[ROUND1:%.*]] = tail call i64 @round(i64 [[A0]]) #2
-; CHECK-NEXT:    [[ROUND2:%.*]] = tail call i64 @round(i64 [[A1]]) #2
+; CHECK-NEXT:    [[ROUND1:%.*]] = tail call i64 @round(i64 [[A0]]) #3
+; CHECK-NEXT:    [[ROUND2:%.*]] = tail call i64 @round(i64 [[A1]]) #3
 ; CHECK-NEXT:    store i64 [[ROUND1]], i64* %b, align 8
 ; CHECK-NEXT:    [[IDX2:%.*]] = getelementptr inbounds i64, i64* %b, i64 1
 ; CHECK-NEXT:    store i64 [[ROUND2]], i64* [[IDX2]], align 8
Index: lib/Analysis/ValueTracking.cpp
===================================================================
--- lib/Analysis/ValueTracking.cpp
+++ lib/Analysis/ValueTracking.cpp
@@ -2579,9 +2579,7 @@
   case LibFunc_sqrt:
   case LibFunc_sqrtf:
   case LibFunc_sqrtl:
-    if (ICS->hasNoNaNs())
-      return Intrinsic::sqrt;
-    return Intrinsic::not_intrinsic;
+    return Intrinsic::sqrt;
   }
 
   return Intrinsic::not_intrinsic;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D39642.121628.patch
Type: text/x-patch
Size: 4253 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20171105/878d621d/attachment.bin>


More information about the llvm-commits mailing list