r355027 - [OPENMP]Delay emission of the error for unsupported types.

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 27 12:29:45 PST 2019


Author: abataev
Date: Wed Feb 27 12:29:45 2019
New Revision: 355027

URL: http://llvm.org/viewvc/llvm-project?rev=355027&view=rev
Log:
[OPENMP]Delay emission of the error for unsupported types.

If the type is unsupported on the device side, it still must be emitted,
but we should emit errors for operations with such types.

Added:
    cfe/trunk/test/OpenMP/nvptx_unsupported_type_codegen.cpp
    cfe/trunk/test/OpenMP/nvptx_unsupported_type_messages.cpp
Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/CodeGen/TargetInfo.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaOpenMP.cpp
    cfe/trunk/lib/Sema/SemaType.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=355027&r1=355026&r2=355027&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Feb 27 12:29:45 2019
@@ -8805,6 +8805,10 @@ private:
   /// Check whether we're allowed to call Callee from the current function.
   void checkOpenMPDeviceFunction(SourceLocation Loc, FunctionDecl *Callee);
 
+  /// Check if the expression is allowed to be used in expressions for the
+  /// OpenMP devices.
+  void checkOpenMPDeviceExpr(const Expr *E);
+
   /// Checks if a type or a declaration is disabled due to the owning extension
   /// being disabled, and emits diagnostic messages if it is disabled.
   /// \param D type or declaration to be checked.

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=355027&r1=355026&r2=355027&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed Feb 27 12:29:45 2019
@@ -1902,8 +1902,16 @@ TypeInfo ASTContext::getTypeInfoImpl(con
       break;
     case BuiltinType::Float16:
     case BuiltinType::Half:
-      Width = Target->getHalfWidth();
-      Align = Target->getHalfAlign();
+      if (Target->hasFloat16Type() || !getLangOpts().OpenMP ||
+          !getLangOpts().OpenMPIsDevice) {
+        Width = Target->getHalfWidth();
+        Align = Target->getHalfAlign();
+      } else {
+        assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice &&
+               "Expected OpenMP device compilation.");
+        Width = AuxTarget->getHalfWidth();
+        Align = AuxTarget->getHalfAlign();
+      }
       break;
     case BuiltinType::Float:
       Width = Target->getFloatWidth();
@@ -1918,8 +1926,16 @@ TypeInfo ASTContext::getTypeInfoImpl(con
       Align = Target->getLongDoubleAlign();
       break;
     case BuiltinType::Float128:
-      Width = Target->getFloat128Width();
-      Align = Target->getFloat128Align();
+      if (Target->hasFloat128Type() || !getLangOpts().OpenMP ||
+          !getLangOpts().OpenMPIsDevice) {
+        Width = Target->getFloat128Width();
+        Align = Target->getFloat128Align();
+      } else {
+        assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice &&
+               "Expected OpenMP device compilation.");
+        Width = AuxTarget->getFloat128Width();
+        Align = AuxTarget->getFloat128Align();
+      }
       break;
     case BuiltinType::NullPtr:
       Width = Target->getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t)

Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=355027&r1=355026&r2=355027&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Wed Feb 27 12:29:45 2019
@@ -6268,10 +6268,56 @@ private:
   static void addNVVMMetadata(llvm::Function *F, StringRef Name, int Operand);
 };
 
+/// Checks if the type is unsupported directly by the current target.
+static bool isUnsupportedType(ASTContext &Context, QualType T) {
+  if (!Context.getTargetInfo().hasFloat16Type() && T->isFloat16Type())
+    return true;
+  if (!Context.getTargetInfo().hasFloat128Type() && T->isFloat128Type())
+    return true;
+  if (!Context.getTargetInfo().hasInt128Type() && T->isIntegerType() &&
+      Context.getTypeSize(T) > 64)
+    return true;
+  if (const auto *AT = T->getAsArrayTypeUnsafe())
+    return isUnsupportedType(Context, AT->getElementType());
+  const auto *RT = T->getAs<RecordType>();
+  if (!RT)
+    return false;
+  const RecordDecl *RD = RT->getDecl();
+
+  // If this is a C++ record, check the bases first.
+  if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
+    for (const CXXBaseSpecifier &I : CXXRD->bases())
+      if (isUnsupportedType(Context, I.getType()))
+        return true;
+
+  for (const FieldDecl *I : RD->fields())
+    if (isUnsupportedType(Context, I->getType()))
+      return true;
+  return false;
+}
+
+/// Coerce the given type into an array with maximum allowed size of elements.
+static ABIArgInfo coerceToIntArrayWithLimit(QualType Ty, ASTContext &Context,
+                                            llvm::LLVMContext &LLVMContext,
+                                            unsigned MaxSize) {
+  // Alignment and Size are measured in bits.
+  const uint64_t Size = Context.getTypeSize(Ty);
+  const uint64_t Alignment = Context.getTypeAlign(Ty);
+  const unsigned Div = std::min<unsigned>(MaxSize, Alignment);
+  llvm::Type *IntType = llvm::Type::getIntNTy(LLVMContext, Div);
+  const uint64_t NumElements = (Size + Div - 1) / Div;
+  return ABIArgInfo::getDirect(llvm::ArrayType::get(IntType, NumElements));
+}
+
 ABIArgInfo NVPTXABIInfo::classifyReturnType(QualType RetTy) const {
   if (RetTy->isVoidType())
     return ABIArgInfo::getIgnore();
 
+  if (getContext().getLangOpts().OpenMP &&
+      getContext().getLangOpts().OpenMPIsDevice &&
+      isUnsupportedType(getContext(), RetTy))
+    return coerceToIntArrayWithLimit(RetTy, getContext(), getVMContext(), 64);
+
   // note: this is different from default ABI
   if (!RetTy->isScalarType())
     return ABIArgInfo::getDirect();

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=355027&r1=355026&r2=355027&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Feb 27 12:29:45 2019
@@ -12432,6 +12432,14 @@ ExprResult Sema::CreateBuiltinBinOp(Sour
     }
   }
 
+  // Diagnose operations on the unsupported types for OpenMP device compilation.
+  if (getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice) {
+    if (Opc != BO_Assign && Opc != BO_Comma) {
+      checkOpenMPDeviceExpr(LHSExpr);
+      checkOpenMPDeviceExpr(RHSExpr);
+    }
+  }
+
   switch (Opc) {
   case BO_Assign:
     ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType());
@@ -13027,6 +13035,13 @@ ExprResult Sema::CreateBuiltinUnaryOp(So
                        << Input.get()->getSourceRange());
     }
   }
+  // Diagnose operations on the unsupported types for OpenMP device compilation.
+  if (getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice) {
+    if (UnaryOperator::isIncrementDecrementOp(Opc) ||
+        UnaryOperator::isArithmeticOp(Opc))
+      checkOpenMPDeviceExpr(InputExpr);
+  }
+
   switch (Opc) {
   case UO_PreInc:
   case UO_PreDec:

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=355027&r1=355026&r2=355027&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Wed Feb 27 12:29:45 2019
@@ -1443,6 +1443,18 @@ void Sema::checkOpenMPDeviceFunction(Sou
     DeviceCallGraph[Caller].insert({Callee, Loc});
 }
 
+void Sema::checkOpenMPDeviceExpr(const Expr *E) {
+  assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice &&
+         "OpenMP device compilation mode is expected.");
+  QualType Ty = E->getType();
+  if ((Ty->isFloat16Type() && !Context.getTargetInfo().hasFloat16Type()) ||
+      (Ty->isFloat128Type() && !Context.getTargetInfo().hasFloat128Type()) ||
+      (Ty->isIntegerType() && Context.getTypeSize(Ty) == 128 &&
+       !Context.getTargetInfo().hasInt128Type()))
+    targetDiag(E->getExprLoc(), diag::err_type_unsupported)
+        << Ty << E->getSourceRange();
+}
+
 bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const {
   assert(LangOpts.OpenMP && "OpenMP is not allowed");
 

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=355027&r1=355026&r2=355027&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed Feb 27 12:29:45 2019
@@ -1433,7 +1433,8 @@ static QualType ConvertDeclSpecToType(Ty
     break;
   }
   case DeclSpec::TST_int128:
-    if (!S.Context.getTargetInfo().hasInt128Type())
+    if (!S.Context.getTargetInfo().hasInt128Type() &&
+        !(S.getLangOpts().OpenMP && S.getLangOpts().OpenMPIsDevice))
       S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
         << "__int128";
     if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
@@ -1445,7 +1446,8 @@ static QualType ConvertDeclSpecToType(Ty
     // CUDA host and device may have different _Float16 support, therefore
     // do not diagnose _Float16 usage to avoid false alarm.
     // ToDo: more precise diagnostics for CUDA.
-    if (!S.Context.getTargetInfo().hasFloat16Type() && !S.getLangOpts().CUDA)
+    if (!S.Context.getTargetInfo().hasFloat16Type() && !S.getLangOpts().CUDA &&
+        !(S.getLangOpts().OpenMP && S.getLangOpts().OpenMPIsDevice))
       S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
         << "_Float16";
     Result = Context.Float16Ty;
@@ -1459,7 +1461,8 @@ static QualType ConvertDeclSpecToType(Ty
       Result = Context.DoubleTy;
     break;
   case DeclSpec::TST_float128:
-    if (!S.Context.getTargetInfo().hasFloat128Type())
+    if (!S.Context.getTargetInfo().hasFloat128Type() &&
+        !(S.getLangOpts().OpenMP && S.getLangOpts().OpenMPIsDevice))
       S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
         << "__float128";
     Result = Context.Float128Ty;

Added: cfe/trunk/test/OpenMP/nvptx_unsupported_type_codegen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/nvptx_unsupported_type_codegen.cpp?rev=355027&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/nvptx_unsupported_type_codegen.cpp (added)
+++ cfe/trunk/test/OpenMP/nvptx_unsupported_type_codegen.cpp Wed Feb 27 12:29:45 2019
@@ -0,0 +1,64 @@
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-linux -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -aux-triple x86_64-unknown-linux -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-host.bc -o - | FileCheck %s
+// expected-no-diagnostics
+
+// CHECK-DAG: [[T:%.+]] = type {{.+}}, fp128,
+// CHECK-DAG: [[T1:%.+]] = type {{.+}}, i128, i128,
+
+struct T {
+  char a;
+  __float128 f;
+  char c;
+  T() : a(12), f(15) {}
+  T &operator+(T &b) { f += b.a; return *this;}
+};
+
+struct T1 {
+  char a;
+  __int128 f;
+  __int128 f1;
+  char c;
+  T1() : a(12), f(15) {}
+  T1 &operator+(T1 &b) { f += b.a; return *this;}
+};
+
+#pragma omp declare target
+T a = T();
+T f = a;
+// CHECK: define void @{{.+}}foo{{.+}}([[T]]* byval align {{.+}})
+void foo(T a = T()) {
+  return;
+}
+// CHECK: define [6 x i64] @{{.+}}bar{{.+}}()
+T bar() {
+// CHECK:      bitcast [[T]]* %{{.+}} to [6 x i64]*
+// CHECK-NEXT: load [6 x i64], [6 x i64]* %{{.+}},
+// CHECK-NEXT: ret [6 x i64]
+  return T();
+}
+// CHECK: define void @{{.+}}baz{{.+}}()
+void baz() {
+// CHECK:      call [6 x i64] @{{.+}}bar{{.+}}()
+// CHECK-NEXT: bitcast [[T]]* %{{.+}} to [6 x i64]*
+// CHECK-NEXT: store [6 x i64] %{{.+}}, [6 x i64]* %{{.+}},
+  T t = bar();
+}
+T1 a1 = T1();
+T1 f1 = a1;
+// CHECK: define void @{{.+}}foo1{{.+}}([[T1]]* byval align {{.+}})
+void foo1(T1 a = T1()) {
+  return;
+}
+// CHECK: define [[T1]] @{{.+}}bar1{{.+}}()
+T1 bar1() {
+// CHECK:      load [[T1]], [[T1]]*
+// CHECK-NEXT: ret [[T1]]
+  return T1();
+}
+// CHECK: define void @{{.+}}baz1{{.+}}()
+void baz1() {
+// CHECK: call [[T1]] @{{.+}}bar1{{.+}}()
+  T1 t = bar1();
+}
+#pragma omp end declare target

Added: cfe/trunk/test/OpenMP/nvptx_unsupported_type_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/nvptx_unsupported_type_messages.cpp?rev=355027&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/nvptx_unsupported_type_messages.cpp (added)
+++ cfe/trunk/test/OpenMP/nvptx_unsupported_type_messages.cpp Wed Feb 27 12:29:45 2019
@@ -0,0 +1,47 @@
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-linux -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-host.bc -fsyntax-only
+
+struct T {
+  char a;
+  __float128 f;
+  char c;
+  T() : a(12), f(15) {}
+  T &operator+(T &b) { f += b.a; return *this;} // expected-error {{'__float128' is not supported on this target}}
+};
+
+struct T1 {
+  char a;
+  __int128 f;
+  __int128 f1;
+  char c;
+  T1() : a(12), f(15) {}
+  T1 &operator/(T1 &b) { f /= b.a; return *this;}
+};
+
+#pragma omp declare target
+T a = T();
+T f = a;
+void foo(T a = T()) {
+  a = a + f; // expected-note {{called by 'foo'}}
+  return;
+}
+T bar() {
+  return T();
+}
+void baz() {
+  T t = bar();
+}
+T1 a1 = T1();
+T1 f1 = a1;
+void foo1(T1 a = T1()) {
+  a = a / f1;
+  return;
+}
+T1 bar1() {
+  return T1();
+}
+void baz1() {
+  T1 t = bar1();
+}
+#pragma omp end declare target




More information about the cfe-commits mailing list