jonpa updated this revision to Diff 324376.
jonpa added a comment.

> Sounds good to me. Hopefully I'll get round to __builtin_isinf soon and a 
> single hook will make the patch slightly smaller.

Patch updated to call the new hook testFPKind() and make it take a BuiltinID as 
argument (that seems to work at least for the moment - maybe an enum type will 
become necessary at some point per your suggestion..?)

I am not sure if this is "only" or "typically" used in constrained FP mode, or 
if the mode should be independent of calling this hook. The patch as it is 
asserts that it is called for an FP type but leaves it to the target to decide 
based on the FP mode, where SystemZ opts out unless it is constrained (which I 
think is what is wanted...).


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D96568/new/

https://reviews.llvm.org/D96568

Files:
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/CodeGen/TargetInfo.cpp
  clang/lib/CodeGen/TargetInfo.h
  clang/test/CodeGen/SystemZ/strictfp_builtins.c

Index: clang/test/CodeGen/SystemZ/strictfp_builtins.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/SystemZ/strictfp_builtins.c
@@ -0,0 +1,43 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: systemz-registered-target
+// RUN: %clang_cc1 %s -emit-llvm -ffp-exception-behavior=maytrap -o - -triple s390x-linux-gnu | FileCheck %s
+
+#pragma float_control(except, on)
+
+// CHECK-LABEL: @test_isnan_float(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[F_ADDR:%.*]] = alloca float, align 4
+// CHECK-NEXT:    store float [[F:%.*]], float* [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load float, float* [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.s390.tdc.f32(float [[TMP0]], i64 15) [[ATTR2:#.*]]
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+int test_isnan_float(float f) {
+  return __builtin_isnan(f);
+}
+
+// CHECK-LABEL: @test_isnan_double(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[D_ADDR:%.*]] = alloca double, align 8
+// CHECK-NEXT:    store double [[D:%.*]], double* [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load double, double* [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.s390.tdc.f64(double [[TMP0]], i64 15) [[ATTR2]]
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+int test_isnan_double(double d) {
+  return __builtin_isnan(d);
+}
+
+// CHECK-LABEL: @test_isnan_long_double(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[LD_ADDR:%.*]] = alloca fp128, align 8
+// CHECK-NEXT:    [[LD:%.*]] = load fp128, fp128* [[TMP0:%.*]], align 8
+// CHECK-NEXT:    store fp128 [[LD]], fp128* [[LD_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = load fp128, fp128* [[LD_ADDR]], align 8
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.s390.tdc.f128(fp128 [[TMP1]], i64 15) [[ATTR2]]
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int test_isnan_long_double(long double ld) {
+  return __builtin_isnan(ld);
+}
+
Index: clang/lib/CodeGen/TargetInfo.h
===================================================================
--- clang/lib/CodeGen/TargetInfo.h
+++ clang/lib/CodeGen/TargetInfo.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_LIB_CODEGEN_TARGETINFO_H
 #define LLVM_CLANG_LIB_CODEGEN_TARGETINFO_H
 
+#include "CGBuilder.h"
 #include "CodeGenModule.h"
 #include "CGValue.h"
 #include "clang/AST/Type.h"
@@ -126,6 +127,16 @@
     return Address;
   }
 
+  /// Performs a target specific test of a floating point value for things
+  /// like IsNaN, Infinity, ... Nullptr is returned if no implementation
+  /// exists.
+  virtual llvm::Value *
+  testFPKind(llvm::Value *V, unsigned BuiltinID, CGBuilderTy &Builder,
+             CodeGenModule &CGM) const {
+    assert(V->getType()->isFloatingPointTy() && "V should have an FP type.");
+    return nullptr;
+  }
+
   /// Corrects the low-level LLVM type for a given constraint and "usual"
   /// type.
   ///
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -21,6 +21,7 @@
 #include "clang/AST/RecordLayout.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
 #include "clang/CodeGen/SwiftCallingConv.h"
 #include "llvm/ADT/SmallBitVector.h"
@@ -30,6 +31,7 @@
 #include "llvm/ADT/Twine.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/IntrinsicsNVPTX.h"
+#include "llvm/IR/IntrinsicsS390.h"
 #include "llvm/IR/Type.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm> // std::sort
@@ -7200,8 +7202,37 @@
   SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector, bool SoftFloatABI)
       : TargetCodeGenInfo(
             std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)) {}
-};
 
+  llvm::Value *testFPKind(llvm::Value *V, unsigned BuiltinID,
+                          CGBuilderTy &Builder,
+                          CodeGenModule &CGM) const override {
+    assert(V->getType()->isFloatingPointTy() && "V should have an FP type.");
+    // Only use TDC in constrained FP mode.
+    if (!Builder.getIsFPConstrained())
+      return nullptr;
+
+    llvm::Type *Ty = V->getType();
+    if (Ty->isFloatTy() || Ty->isDoubleTy() || Ty->isFP128Ty()) {
+      llvm::Module &M = CGM.getModule();
+      auto &Ctx = M.getContext();
+      llvm::Function *TDCFunc =
+          llvm::Intrinsic::getDeclaration(&M, llvm::Intrinsic::s390_tdc, Ty);
+      unsigned TDCBits = 0;
+      switch (BuiltinID) {
+      case Builtin::BI__builtin_isnan:
+        TDCBits = 0xf;
+        break;
+      default:
+        break;
+      }
+      if (TDCBits)
+        return Builder.CreateCall(
+            TDCFunc,
+            {V, llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), TDCBits)});
+    }
+    return nullptr;
+  }
+};
 }
 
 bool SystemZABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const {
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -2997,6 +2997,9 @@
       return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType())));
     }
 
+    if (Value *Result = getTargetHooks().testFPKind(V, BuiltinID, Builder, CGM))
+      return RValue::get(Result);
+
     // NaN has all exp bits set and a non zero significand. Therefore:
     // isnan(V) == ((exp mask - (abs(V) & exp mask)) < 0)
     unsigned bitsize = Ty->getScalarSizeInBits();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to