[clang] cefac9d - Remove implicit conversion that promotes half to other larger precision types for fp classification builtins

Jim Lin via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 9 21:26:24 PST 2019


Author: Jim Lin
Date: 2019-12-10T13:24:21+08:00
New Revision: cefac9dfaac9c806433ad88cca85bd2f3ba1edad

URL: https://github.com/llvm/llvm-project/commit/cefac9dfaac9c806433ad88cca85bd2f3ba1edad
DIFF: https://github.com/llvm/llvm-project/commit/cefac9dfaac9c806433ad88cca85bd2f3ba1edad.diff

LOG: Remove implicit conversion that promotes half to other larger precision types for fp classification builtins

Summary:
It shouldn't promote half to double or any larger precision types for fp classification builtins.
Because fp classification builtins would get incorrect result with promoted argument.
For example, __builtin_isnormal with a subnormal half value should return false, but it is not.
That the subnormal half value is promoted to a normal double value.

Reviewers: aaron.ballman

Reviewed By: aaron.ballman

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D71049

Added: 
    

Modified: 
    clang/lib/Sema/SemaChecking.cpp
    clang/test/CodeGen/builtins.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 825e0faa3037..2be9effffcec 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5808,10 +5808,11 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
            << OrigArg->getType() << OrigArg->getSourceRange();
 
   // If this is an implicit conversion from float -> float, double, or
-  // long double, remove it.
+  // long double, or half -> half, float, double, or long double, remove it.
   if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(OrigArg)) {
     // Only remove standard FloatCasts, leaving other casts inplace
     if (Cast->getCastKind() == CK_FloatingCast) {
+      bool IgnoreCast = false;
       Expr *CastArg = Cast->getSubExpr();
       if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) {
         assert(
@@ -5820,6 +5821,19 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
              Cast->getType()->isSpecificBuiltinType(BuiltinType::LongDouble)) &&
             "promotion from float to either float, double, or long double is "
             "the only expected cast here");
+        IgnoreCast = true;
+      } else if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Half)) {
+        assert(
+            (Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) ||
+             Cast->getType()->isSpecificBuiltinType(BuiltinType::Float) ||
+             Cast->getType()->isSpecificBuiltinType(BuiltinType::Half) ||
+             Cast->getType()->isSpecificBuiltinType(BuiltinType::LongDouble)) &&
+            "promotion from half to either half, float, double, or long double "
+            "is the only expected cast here");
+        IgnoreCast = true;
+      }
+
+      if (IgnoreCast) {
         Cast->setSubExpr(nullptr);
         TheCall->setArg(NumArgs-1, CastArg);
       }

diff  --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index 5b482543d2d0..591416d00cc7 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -193,8 +193,12 @@ void test_conditional_bzero() {
 }
 
 // CHECK-LABEL: define void @test_float_builtins
-void test_float_builtins(float F, double D, long double LD) {
+void test_float_builtins(__fp16 *H, float F, double D, long double LD) {
   volatile int res;
+  res = __builtin_isinf(*H);
+  // CHECK:  call half @llvm.fabs.f16(half
+  // CHECK:  fcmp oeq half {{.*}}, 0xH7C00
+
   res = __builtin_isinf(F);
   // CHECK:  call float @llvm.fabs.f32(float
   // CHECK:  fcmp oeq float {{.*}}, 0x7FF0000000000000
@@ -207,6 +211,14 @@ void test_float_builtins(float F, double D, long double LD) {
   // CHECK:  call x86_fp80 @llvm.fabs.f80(x86_fp80
   // CHECK:  fcmp oeq x86_fp80 {{.*}}, 0xK7FFF8000000000000000
 
+  res = __builtin_isinf_sign(*H);
+  // CHECK:  %[[ABS:.*]] = call half @llvm.fabs.f16(half %[[ARG:.*]])
+  // CHECK:  %[[ISINF:.*]] = fcmp oeq half %[[ABS]], 0xH7C00
+  // CHECK:  %[[BITCAST:.*]] = bitcast half %[[ARG]] to i16
+  // CHECK:  %[[ISNEG:.*]] = icmp slt i16 %[[BITCAST]], 0
+  // CHECK:  %[[SIGN:.*]] = select i1 %[[ISNEG]], i32 -1, i32 1
+  // CHECK:  select i1 %[[ISINF]], i32 %[[SIGN]], i32 0
+
   res = __builtin_isinf_sign(F);
   // CHECK:  %[[ABS:.*]] = call float @llvm.fabs.f32(float %[[ARG:.*]])
   // CHECK:  %[[ISINF:.*]] = fcmp oeq float %[[ABS]], 0x7FF0000000000000
@@ -231,6 +243,10 @@ void test_float_builtins(float F, double D, long double LD) {
   // CHECK:  %[[SIGN:.*]] = select i1 %[[ISNEG]], i32 -1, i32 1
   // CHECK:  select i1 %[[ISINF]], i32 %[[SIGN]], i32 0
 
+  res = __builtin_isfinite(*H);
+  // CHECK: call half @llvm.fabs.f16(half
+  // CHECK: fcmp one half {{.*}}, 0xH7C00
+
   res = __builtin_isfinite(F);
   // CHECK: call float @llvm.fabs.f32(float
   // CHECK: fcmp one float {{.*}}, 0x7FF0000000000000
@@ -239,6 +255,14 @@ void test_float_builtins(float F, double D, long double LD) {
   // CHECK: call double @llvm.fabs.f64(double
   // CHECK: fcmp one double {{.*}}, 0x7FF0000000000000
 
+  res = __builtin_isnormal(*H);
+  // CHECK: fcmp oeq half
+  // CHECK: call half @llvm.fabs.f16(half
+  // CHECK: fcmp ult half {{.*}}, 0xH7C00
+  // CHECK: fcmp uge half {{.*}}, 0xH0400
+  // CHECK: and i1
+  // CHECK: and i1
+
   res = __builtin_isnormal(F);
   // CHECK: fcmp oeq float
   // CHECK: call float @llvm.fabs.f32(float


        


More information about the cfe-commits mailing list