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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits