r374263 - [CUDA][HIP] Fix host/device check with -fopenmp
Yaxun Liu via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 9 16:54:10 PDT 2019
Author: yaxunl
Date: Wed Oct 9 16:54:10 2019
New Revision: 374263
URL: http://llvm.org/viewvc/llvm-project?rev=374263&view=rev
Log:
[CUDA][HIP] Fix host/device check with -fopenmp
CUDA/HIP program may be compiled with -fopenmp. In this case, -fopenmp is only passed to host compilation
to take advantages of multi-threads computation.
CUDA/HIP and OpenMP both use Sema::DeviceCallGraph to store functions to be analyzed and remove them
once they decide the function is sure to be emitted. CUDA/HIP and OpenMP have different functions to determine
if a function is sure to be emitted.
To check host/device correctly for CUDA/HIP when -fopenmp is enabled, there needs a unified logic to determine
whether a function is to be emitted. The logic needs to be aware of both CUDA and OpenMP logic.
Differential Revision: https://reviews.llvm.org/D67837
Added:
cfe/trunk/test/CodeGenCUDA/openmp-target.cu
cfe/trunk/test/SemaCUDA/openmp-static-func.cu
cfe/trunk/test/SemaCUDA/openmp-target.cu
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaCUDA.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaOpenMP.cpp
cfe/trunk/test/OpenMP/declare_target_messages.cpp
cfe/trunk/test/SemaCUDA/call-device-fn-from-host.cu
cfe/trunk/test/SemaCUDA/host-device-constexpr.cu
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=374263&r1=374262&r2=374263&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Oct 9 16:54:10 2019
@@ -3451,6 +3451,19 @@ public:
bool DiagnoseMissing);
bool isKnownName(StringRef name);
+ /// Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
+ enum class FunctionEmissionStatus {
+ Emitted,
+ CUDADiscarded, // Discarded due to CUDA/HIP hostness
+ OMPDiscarded, // Discarded due to OpenMP hostness
+ TemplateDiscarded, // Discarded due to uninstantiated templates
+ Unknown,
+ };
+ FunctionEmissionStatus getEmissionStatus(FunctionDecl *Decl);
+
+ // Whether the callee should be ignored in CUDA/HIP/OpenMP host/device check.
+ bool shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee);
+
void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
ArrayRef<Expr *> Args, ADLResult &Functions);
Modified: cfe/trunk/lib/Sema/SemaCUDA.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCUDA.cpp?rev=374263&r1=374262&r2=374263&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCUDA.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCUDA.cpp Wed Oct 9 16:54:10 2019
@@ -600,40 +600,6 @@ void Sema::maybeAddCUDAHostDeviceAttrs(F
NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context));
}
-// Do we know that we will eventually codegen the given function?
-static bool IsKnownEmitted(Sema &S, FunctionDecl *FD) {
- // Templates are emitted when they're instantiated.
- if (FD->isDependentContext())
- return false;
-
- // When compiling for device, host functions are never emitted. Similarly,
- // when compiling for host, device and global functions are never emitted.
- // (Technically, we do emit a host-side stub for global functions, but this
- // doesn't count for our purposes here.)
- Sema::CUDAFunctionTarget T = S.IdentifyCUDATarget(FD);
- if (S.getLangOpts().CUDAIsDevice && T == Sema::CFT_Host)
- return false;
- if (!S.getLangOpts().CUDAIsDevice &&
- (T == Sema::CFT_Device || T == Sema::CFT_Global))
- return false;
-
- // Check whether this function is externally visible -- if so, it's
- // known-emitted.
- //
- // We have to check the GVA linkage of the function's *definition* -- if we
- // only have a declaration, we don't know whether or not the function will be
- // emitted, because (say) the definition could include "inline".
- FunctionDecl *Def = FD->getDefinition();
-
- if (Def &&
- !isDiscardableGVALinkage(S.getASTContext().GetGVALinkageForFunction(Def)))
- return true;
-
- // Otherwise, the function is known-emitted if it's in our set of
- // known-emitted functions.
- return S.DeviceKnownEmittedFns.count(FD) > 0;
-}
-
Sema::DeviceDiagBuilder Sema::CUDADiagIfDeviceCode(SourceLocation Loc,
unsigned DiagID) {
assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
@@ -647,7 +613,8 @@ Sema::DeviceDiagBuilder Sema::CUDADiagIf
// device code if we're compiling for device. Defer any errors in device
// mode until the function is known-emitted.
if (getLangOpts().CUDAIsDevice) {
- return IsKnownEmitted(*this, dyn_cast<FunctionDecl>(CurContext))
+ return (getEmissionStatus(cast<FunctionDecl>(CurContext)) ==
+ FunctionEmissionStatus::Emitted)
? DeviceDiagBuilder::K_ImmediateWithCallStack
: DeviceDiagBuilder::K_Deferred;
}
@@ -675,7 +642,8 @@ Sema::DeviceDiagBuilder Sema::CUDADiagIf
if (getLangOpts().CUDAIsDevice)
return DeviceDiagBuilder::K_Nop;
- return IsKnownEmitted(*this, dyn_cast<FunctionDecl>(CurContext))
+ return (getEmissionStatus(cast<FunctionDecl>(CurContext)) ==
+ FunctionEmissionStatus::Emitted)
? DeviceDiagBuilder::K_ImmediateWithCallStack
: DeviceDiagBuilder::K_Deferred;
default:
@@ -702,12 +670,16 @@ bool Sema::CheckCUDACall(SourceLocation
// If the caller is known-emitted, mark the callee as known-emitted.
// Otherwise, mark the call in our call graph so we can traverse it later.
- bool CallerKnownEmitted = IsKnownEmitted(*this, Caller);
+ bool CallerKnownEmitted =
+ getEmissionStatus(Caller) == FunctionEmissionStatus::Emitted;
if (CallerKnownEmitted) {
// Host-side references to a __global__ function refer to the stub, so the
// function itself is never emitted and therefore should not be marked.
- if (getLangOpts().CUDAIsDevice || IdentifyCUDATarget(Callee) != CFT_Global)
- markKnownEmitted(*this, Caller, Callee, Loc, IsKnownEmitted);
+ if (!shouldIgnoreInHostDeviceCheck(Callee))
+ markKnownEmitted(
+ *this, Caller, Callee, Loc, [](Sema &S, FunctionDecl *FD) {
+ return S.getEmissionStatus(FD) == FunctionEmissionStatus::Emitted;
+ });
} else {
// If we have
// host fn calls kernel fn calls host+device,
@@ -715,7 +687,7 @@ bool Sema::CheckCUDACall(SourceLocation
// omitting at the call to the kernel from the callgraph. This ensures
// that, when compiling for host, only HD functions actually called from the
// host get marked as known-emitted.
- if (getLangOpts().CUDAIsDevice || IdentifyCUDATarget(Callee) != CFT_Global)
+ if (!shouldIgnoreInHostDeviceCheck(Callee))
DeviceCallGraph[Caller].insert({Callee, Loc});
}
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=374263&r1=374262&r2=374263&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Oct 9 16:54:10 2019
@@ -17614,3 +17614,87 @@ void Sema::ActOnPragmaWeakAlias(Identifi
Decl *Sema::getObjCDeclContext() const {
return (dyn_cast_or_null<ObjCContainerDecl>(CurContext));
}
+
+Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD) {
+ // Templates are emitted when they're instantiated.
+ if (FD->isDependentContext())
+ return FunctionEmissionStatus::TemplateDiscarded;
+
+ FunctionEmissionStatus OMPES = FunctionEmissionStatus::Unknown;
+ if (LangOpts.OpenMPIsDevice) {
+ Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
+ OMPDeclareTargetDeclAttr::getDeviceType(FD->getCanonicalDecl());
+ if (DevTy.hasValue()) {
+ if (*DevTy == OMPDeclareTargetDeclAttr::DT_Host)
+ OMPES = FunctionEmissionStatus::OMPDiscarded;
+ else if (DeviceKnownEmittedFns.count(FD) > 0)
+ OMPES = FunctionEmissionStatus::Emitted;
+ }
+ } else if (LangOpts.OpenMP) {
+ // In OpenMP 4.5 all the functions are host functions.
+ if (LangOpts.OpenMP <= 45) {
+ OMPES = FunctionEmissionStatus::Emitted;
+ } else {
+ Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
+ OMPDeclareTargetDeclAttr::getDeviceType(FD->getCanonicalDecl());
+ // In OpenMP 5.0 or above, DevTy may be changed later by
+ // #pragma omp declare target to(*) device_type(*). Therefore DevTy
+ // having no value does not imply host. The emission status will be
+ // checked again at the end of compilation unit.
+ if (DevTy.hasValue()) {
+ if (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
+ OMPES = FunctionEmissionStatus::OMPDiscarded;
+ } else if (DeviceKnownEmittedFns.count(FD) > 0) {
+ OMPES = FunctionEmissionStatus::Emitted;
+ }
+ }
+ }
+ }
+ if (OMPES == FunctionEmissionStatus::OMPDiscarded ||
+ (OMPES == FunctionEmissionStatus::Emitted && !LangOpts.CUDA))
+ return OMPES;
+
+ if (LangOpts.CUDA) {
+ // When compiling for device, host functions are never emitted. Similarly,
+ // when compiling for host, device and global functions are never emitted.
+ // (Technically, we do emit a host-side stub for global functions, but this
+ // doesn't count for our purposes here.)
+ Sema::CUDAFunctionTarget T = IdentifyCUDATarget(FD);
+ if (LangOpts.CUDAIsDevice && T == Sema::CFT_Host)
+ return FunctionEmissionStatus::CUDADiscarded;
+ if (!LangOpts.CUDAIsDevice &&
+ (T == Sema::CFT_Device || T == Sema::CFT_Global))
+ return FunctionEmissionStatus::CUDADiscarded;
+
+ // Check whether this function is externally visible -- if so, it's
+ // known-emitted.
+ //
+ // We have to check the GVA linkage of the function's *definition* -- if we
+ // only have a declaration, we don't know whether or not the function will
+ // be emitted, because (say) the definition could include "inline".
+ FunctionDecl *Def = FD->getDefinition();
+
+ if (Def &&
+ !isDiscardableGVALinkage(getASTContext().GetGVALinkageForFunction(Def))
+ && (!LangOpts.OpenMP || OMPES == FunctionEmissionStatus::Emitted))
+ return FunctionEmissionStatus::Emitted;
+ }
+
+ // Otherwise, the function is known-emitted if it's in our set of
+ // known-emitted functions.
+ return (DeviceKnownEmittedFns.count(FD) > 0)
+ ? FunctionEmissionStatus::Emitted
+ : FunctionEmissionStatus::Unknown;
+}
+
+bool Sema::shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee) {
+ // Host-side references to a __global__ function refer to the stub, so the
+ // function itself is never emitted and therefore should not be marked.
+ // If we have host fn calls kernel fn calls host+device, the HD function
+ // does not get instantiated on the host. We model this by omitting at the
+ // call to the kernel from the callgraph. This ensures that, when compiling
+ // for host, only HD functions actually called from the host get marked as
+ // known-emitted.
+ return LangOpts.CUDA && !LangOpts.CUDAIsDevice &&
+ IdentifyCUDATarget(Callee) == CFT_Global;
+}
Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=374263&r1=374262&r2=374263&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Wed Oct 9 16:54:10 2019
@@ -1565,34 +1565,11 @@ enum class FunctionEmissionStatus {
};
} // anonymous namespace
-/// Do we know that we will eventually codegen the given function?
-static FunctionEmissionStatus isKnownDeviceEmitted(Sema &S, FunctionDecl *FD) {
- assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsDevice &&
- "Expected OpenMP device compilation.");
- // Templates are emitted when they're instantiated.
- if (FD->isDependentContext())
- return FunctionEmissionStatus::Discarded;
-
- Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
- OMPDeclareTargetDeclAttr::getDeviceType(FD->getCanonicalDecl());
- if (DevTy.hasValue())
- return (*DevTy == OMPDeclareTargetDeclAttr::DT_Host)
- ? FunctionEmissionStatus::Discarded
- : FunctionEmissionStatus::Emitted;
-
- // Otherwise, the function is known-emitted if it's in our set of
- // known-emitted functions.
- return (S.DeviceKnownEmittedFns.count(FD) > 0)
- ? FunctionEmissionStatus::Emitted
- : FunctionEmissionStatus::Unknown;
-}
-
Sema::DeviceDiagBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc,
unsigned DiagID) {
assert(LangOpts.OpenMP && LangOpts.OpenMPIsDevice &&
"Expected OpenMP device compilation.");
- FunctionEmissionStatus FES =
- isKnownDeviceEmitted(*this, getCurFunctionDecl());
+ FunctionEmissionStatus FES = getEmissionStatus(getCurFunctionDecl());
DeviceDiagBuilder::Kind Kind = DeviceDiagBuilder::K_Nop;
switch (FES) {
case FunctionEmissionStatus::Emitted:
@@ -1602,42 +1579,23 @@ Sema::DeviceDiagBuilder Sema::diagIfOpen
Kind = isOpenMPDeviceDelayedContext(*this) ? DeviceDiagBuilder::K_Deferred
: DeviceDiagBuilder::K_Immediate;
break;
- case FunctionEmissionStatus::Discarded:
+ case FunctionEmissionStatus::TemplateDiscarded:
+ case FunctionEmissionStatus::OMPDiscarded:
Kind = DeviceDiagBuilder::K_Nop;
break;
+ case FunctionEmissionStatus::CUDADiscarded:
+ llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
+ break;
}
return DeviceDiagBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this);
}
-/// Do we know that we will eventually codegen the given function?
-static FunctionEmissionStatus isKnownHostEmitted(Sema &S, FunctionDecl *FD) {
- assert(S.LangOpts.OpenMP && !S.LangOpts.OpenMPIsDevice &&
- "Expected OpenMP host compilation.");
- // In OpenMP 4.5 all the functions are host functions.
- if (S.LangOpts.OpenMP <= 45)
- return FunctionEmissionStatus::Emitted;
-
- Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
- OMPDeclareTargetDeclAttr::getDeviceType(FD->getCanonicalDecl());
- if (DevTy.hasValue())
- return (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
- ? FunctionEmissionStatus::Discarded
- : FunctionEmissionStatus::Emitted;
-
- // Otherwise, the function is known-emitted if it's in our set of
- // known-emitted functions.
- return (S.DeviceKnownEmittedFns.count(FD) > 0)
- ? FunctionEmissionStatus::Emitted
- : FunctionEmissionStatus::Unknown;
-}
-
Sema::DeviceDiagBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc,
unsigned DiagID) {
assert(LangOpts.OpenMP && !LangOpts.OpenMPIsDevice &&
"Expected OpenMP host compilation.");
- FunctionEmissionStatus FES =
- isKnownHostEmitted(*this, getCurFunctionDecl());
+ FunctionEmissionStatus FES = getEmissionStatus(getCurFunctionDecl());
DeviceDiagBuilder::Kind Kind = DeviceDiagBuilder::K_Nop;
switch (FES) {
case FunctionEmissionStatus::Emitted:
@@ -1646,7 +1604,9 @@ Sema::DeviceDiagBuilder Sema::diagIfOpen
case FunctionEmissionStatus::Unknown:
Kind = DeviceDiagBuilder::K_Deferred;
break;
- case FunctionEmissionStatus::Discarded:
+ case FunctionEmissionStatus::TemplateDiscarded:
+ case FunctionEmissionStatus::OMPDiscarded:
+ case FunctionEmissionStatus::CUDADiscarded:
Kind = DeviceDiagBuilder::K_Nop;
break;
}
@@ -1663,31 +1623,34 @@ void Sema::checkOpenMPDeviceFunction(Sou
FunctionDecl *Caller = getCurFunctionDecl();
// host only function are not available on the device.
- if (Caller &&
- (isKnownDeviceEmitted(*this, Caller) == FunctionEmissionStatus::Emitted ||
- (!isOpenMPDeviceDelayedContext(*this) &&
- isKnownDeviceEmitted(*this, Caller) ==
- FunctionEmissionStatus::Unknown)) &&
- isKnownDeviceEmitted(*this, Callee) ==
- FunctionEmissionStatus::Discarded) {
- StringRef HostDevTy =
- getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
- Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
- Diag(Callee->getAttr<OMPDeclareTargetDeclAttr>()->getLocation(),
- diag::note_omp_marked_device_type_here)
- << HostDevTy;
- return;
+ if (Caller) {
+ FunctionEmissionStatus CallerS = getEmissionStatus(Caller);
+ FunctionEmissionStatus CalleeS = getEmissionStatus(Callee);
+ assert(CallerS != FunctionEmissionStatus::CUDADiscarded &&
+ CalleeS != FunctionEmissionStatus::CUDADiscarded &&
+ "CUDADiscarded unexpected in OpenMP device function check");
+ if ((CallerS == FunctionEmissionStatus::Emitted ||
+ (!isOpenMPDeviceDelayedContext(*this) &&
+ CallerS == FunctionEmissionStatus::Unknown)) &&
+ CalleeS == FunctionEmissionStatus::OMPDiscarded) {
+ StringRef HostDevTy = getOpenMPSimpleClauseTypeName(
+ OMPC_device_type, OMPC_DEVICE_TYPE_host);
+ Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
+ Diag(Callee->getAttr<OMPDeclareTargetDeclAttr>()->getLocation(),
+ diag::note_omp_marked_device_type_here)
+ << HostDevTy;
+ return;
+ }
}
// If the caller is known-emitted, mark the callee as known-emitted.
// Otherwise, mark the call in our call graph so we can traverse it later.
if ((CheckForDelayedContext && !isOpenMPDeviceDelayedContext(*this)) ||
(!Caller && !CheckForDelayedContext) ||
- (Caller &&
- isKnownDeviceEmitted(*this, Caller) == FunctionEmissionStatus::Emitted))
+ (Caller && getEmissionStatus(Caller) == FunctionEmissionStatus::Emitted))
markKnownEmitted(*this, Caller, Callee, Loc,
[CheckForDelayedContext](Sema &S, FunctionDecl *FD) {
return CheckForDelayedContext &&
- isKnownDeviceEmitted(S, FD) ==
+ S.getEmissionStatus(FD) ==
FunctionEmissionStatus::Emitted;
});
else if (Caller)
@@ -1703,29 +1666,38 @@ void Sema::checkOpenMPHostFunction(Sourc
FunctionDecl *Caller = getCurFunctionDecl();
// device only function are not available on the host.
- if (Caller &&
- isKnownHostEmitted(*this, Caller) == FunctionEmissionStatus::Emitted &&
- isKnownHostEmitted(*this, Callee) == FunctionEmissionStatus::Discarded) {
- StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
- OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
- Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
- Diag(Callee->getAttr<OMPDeclareTargetDeclAttr>()->getLocation(),
- diag::note_omp_marked_device_type_here)
- << NoHostDevTy;
- return;
+ if (Caller) {
+ FunctionEmissionStatus CallerS = getEmissionStatus(Caller);
+ FunctionEmissionStatus CalleeS = getEmissionStatus(Callee);
+ assert(
+ (LangOpts.CUDA || (CallerS != FunctionEmissionStatus::CUDADiscarded &&
+ CalleeS != FunctionEmissionStatus::CUDADiscarded)) &&
+ "CUDADiscarded unexpected in OpenMP host function check");
+ if (CallerS == FunctionEmissionStatus::Emitted &&
+ CalleeS == FunctionEmissionStatus::OMPDiscarded) {
+ StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
+ OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
+ Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
+ Diag(Callee->getAttr<OMPDeclareTargetDeclAttr>()->getLocation(),
+ diag::note_omp_marked_device_type_here)
+ << NoHostDevTy;
+ return;
+ }
}
// If the caller is known-emitted, mark the callee as known-emitted.
// Otherwise, mark the call in our call graph so we can traverse it later.
- if ((!CheckCaller && !Caller) ||
- (Caller &&
- isKnownHostEmitted(*this, Caller) == FunctionEmissionStatus::Emitted))
- markKnownEmitted(
- *this, Caller, Callee, Loc, [CheckCaller](Sema &S, FunctionDecl *FD) {
- return CheckCaller &&
- isKnownHostEmitted(S, FD) == FunctionEmissionStatus::Emitted;
- });
- else if (Caller)
- DeviceCallGraph[Caller].insert({Callee, Loc});
+ if (!shouldIgnoreInHostDeviceCheck(Callee)) {
+ if ((!CheckCaller && !Caller) ||
+ (Caller &&
+ getEmissionStatus(Caller) == FunctionEmissionStatus::Emitted))
+ markKnownEmitted(
+ *this, Caller, Callee, Loc, [CheckCaller](Sema &S, FunctionDecl *FD) {
+ return CheckCaller &&
+ S.getEmissionStatus(FD) == FunctionEmissionStatus::Emitted;
+ });
+ else if (Caller)
+ DeviceCallGraph[Caller].insert({Callee, Loc});
+ }
}
void Sema::checkOpenMPDeviceExpr(const Expr *E) {
Added: cfe/trunk/test/CodeGenCUDA/openmp-target.cu
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCUDA/openmp-target.cu?rev=374263&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCUDA/openmp-target.cu (added)
+++ cfe/trunk/test/CodeGenCUDA/openmp-target.cu Wed Oct 9 16:54:10 2019
@@ -0,0 +1,20 @@
+// REQUIRES: x86-registered-target
+// REQUIRES: nvptx-registered-target
+
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm \
+// RUN: -fopenmp -fopenmp-version=50 -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm \
+// RUN: -fopenmp -fopenmp-version=50 -o - -x c++ %s | FileCheck %s
+// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fcuda-is-device \
+// RUN: -emit-llvm -o - %s | FileCheck -check-prefixes=DEV %s
+
+// CHECK: declare{{.*}}@_Z7nohost1v()
+// DEV-NOT: _Z7nohost1v
+void nohost1() {}
+#pragma omp declare target to(nohost1) device_type(nohost)
+
+// CHECK: declare{{.*}}@_Z7nohost2v()
+// DEV-NOT: _Z7nohost2v
+void nohost2() {nohost1();}
+#pragma omp declare target to(nohost2) device_type(nohost)
+
Modified: cfe/trunk/test/OpenMP/declare_target_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_target_messages.cpp?rev=374263&r1=374262&r2=374263&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/declare_target_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/declare_target_messages.cpp Wed Oct 9 16:54:10 2019
@@ -162,10 +162,10 @@ namespace {
#pragma omp declare target link(x) // expected-error {{'x' must not appear in both clauses 'to' and 'link'}}
void bazz() {}
-#pragma omp declare target to(bazz) device_type(nohost) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}}
+#pragma omp declare target to(bazz) device_type(nohost) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} host5-note {{marked as 'device_type(nohost)' here}}
void bazzz() {bazz();}
#pragma omp declare target to(bazzz) device_type(nohost) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}}
-void any() {bazz();}
+void any() {bazz();} // host5-error {{function with 'device_type(nohost)' is not available on host}}
void host1() {bazz();}
#pragma omp declare target to(host1) device_type(host) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} dev5-note 2 {{marked as 'device_type(host)' here}}
void host2() {bazz();}
Modified: cfe/trunk/test/SemaCUDA/call-device-fn-from-host.cu
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCUDA/call-device-fn-from-host.cu?rev=374263&r1=374262&r2=374263&view=diff
==============================================================================
--- cfe/trunk/test/SemaCUDA/call-device-fn-from-host.cu (original)
+++ cfe/trunk/test/SemaCUDA/call-device-fn-from-host.cu Wed Oct 9 16:54:10 2019
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 %s --std=c++11 -triple x86_64-unknown-linux -emit-llvm -o - \
// RUN: -verify -verify-ignore-unexpected=note
+// RUN: %clang_cc1 %s --std=c++11 -triple x86_64-unknown-linux -emit-llvm -o - \
+// RUN: -verify -verify-ignore-unexpected=note -fopenmp
// Note: This test won't work with -fsyntax-only, because some of these errors
// are emitted during codegen.
Modified: cfe/trunk/test/SemaCUDA/host-device-constexpr.cu
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCUDA/host-device-constexpr.cu?rev=374263&r1=374262&r2=374263&view=diff
==============================================================================
--- cfe/trunk/test/SemaCUDA/host-device-constexpr.cu (original)
+++ cfe/trunk/test/SemaCUDA/host-device-constexpr.cu Wed Oct 9 16:54:10 2019
@@ -1,5 +1,10 @@
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -isystem %S/Inputs %s
-// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -isystem %S/Inputs %s -fcuda-is-device
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -isystem %S/Inputs %s \
+// RUN: -fcuda-is-device
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -isystem %S/Inputs \
+// RUN: -fopenmp %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -isystem %S/Inputs \
+// RUN: -fopenmp %s -fcuda-is-device
#include "Inputs/cuda.h"
Added: cfe/trunk/test/SemaCUDA/openmp-static-func.cu
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCUDA/openmp-static-func.cu?rev=374263&view=auto
==============================================================================
--- cfe/trunk/test/SemaCUDA/openmp-static-func.cu (added)
+++ cfe/trunk/test/SemaCUDA/openmp-static-func.cu Wed Oct 9 16:54:10 2019
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only \
+// RUN: -verify -fopenmp %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only \
+// RUN: -verify -fopenmp -x hip %s
+// expected-no-diagnostics
+
+// Tests there is no assertion in Sema::markKnownEmitted when fopenmp is used
+// with CUDA/HIP host compilation.
+
+static void f() {}
+
+static void g() { f(); }
+
+static void h() { g(); }
Added: cfe/trunk/test/SemaCUDA/openmp-target.cu
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCUDA/openmp-target.cu?rev=374263&view=auto
==============================================================================
--- cfe/trunk/test/SemaCUDA/openmp-target.cu (added)
+++ cfe/trunk/test/SemaCUDA/openmp-target.cu Wed Oct 9 16:54:10 2019
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -triple x86_64 -verify=expected,dev \
+// RUN: -verify-ignore-unexpected=note \
+// RUN: -fopenmp -fopenmp-version=50 -o - %s
+// RUN: %clang_cc1 -triple x86_64 -verify -verify-ignore-unexpected=note\
+// RUN: -fopenmp -fopenmp-version=50 -o - -x c++ %s
+// RUN: %clang_cc1 -triple x86_64 -verify=dev -verify-ignore-unexpected=note\
+// RUN: -fcuda-is-device -o - %s
+
+#if __CUDA__
+#include "Inputs/cuda.h"
+__device__ void cu_devf();
+#endif
+
+void bazz() {}
+#pragma omp declare target to(bazz) device_type(nohost)
+void bazzz() {bazz();}
+#pragma omp declare target to(bazzz) device_type(nohost)
+void any() {bazz();} // expected-error {{function with 'device_type(nohost)' is not available on host}}
+void host1() {bazz();}
+#pragma omp declare target to(host1) device_type(host)
+void host2() {bazz();}
+#pragma omp declare target to(host2)
+void device() {host1();}
+#pragma omp declare target to(device) device_type(nohost)
+void host3() {host1();}
+#pragma omp declare target to(host3)
+
+#pragma omp declare target
+void any1() {any();}
+void any2() {host1();}
+void any3() {device();} // expected-error {{function with 'device_type(nohost)' is not available on host}}
+void any4() {any2();}
+#pragma omp end declare target
+
+void any5() {any();}
+void any6() {host1();}
+void any7() {device();} // expected-error {{function with 'device_type(nohost)' is not available on host}}
+void any8() {any2();}
+
+#if __CUDA__
+void cu_hostf() { cu_devf(); } // dev-error {{no matching function for call to 'cu_devf'}}
+__device__ void cu_devf2() { cu_hostf(); } // dev-error{{no matching function for call to 'cu_hostf'}}
+#endif
More information about the cfe-commits
mailing list