diff --git a/compiler/AST/primitive.cpp b/compiler/AST/primitive.cpp index 4334596771ab..cfdc11b6610f 100644 --- a/compiler/AST/primitive.cpp +++ b/compiler/AST/primitive.cpp @@ -972,6 +972,7 @@ initPrimitive() { // Generates call that produces runtime error when not run by a GPU prim_def(PRIM_ASSERT_ON_GPU, "chpl_assert_on_gpu", returnInfoVoid, true, true); + prim_def(PRIM_ASSERT_GPU_ELIGIBLE, "assert gpu eligible", returnInfoVoid, true, true); prim_def(PRIM_GPU_ELIGIBLE, "gpu eligible", returnInfoVoid, true, true); prim_def(PRIM_GPU_REDUCE_WRAPPER, "gpu reduce wrapper", returnInfoVoid, true); diff --git a/compiler/optimizations/gpuTransforms.cpp b/compiler/optimizations/gpuTransforms.cpp index cc5a04f4b9bc..0ab1bc4ab981 100644 --- a/compiler/optimizations/gpuTransforms.cpp +++ b/compiler/optimizations/gpuTransforms.cpp @@ -410,11 +410,17 @@ class GpuAssertionReporter { void printNonGpuizableError(CallExpr* assertion, Expr* loc) const { debuggerBreakHere(); - const char* reason = "contains assertOnGpu()"; - auto isAttributeSym = toSymExpr(assertion->get(1)); - INT_ASSERT(isAttributeSym); - if (isAttributeSym->symbol() == gTrue) { - reason = "is marked with @assertOnGpu"; + const char* reason = nullptr; + if (assertion->isPrimitive(PRIM_ASSERT_GPU_ELIGIBLE)) { + reason = "is marked with @gpu.assertEligible"; + } else { + INT_ASSERT(assertion->isPrimitive(PRIM_ASSERT_ON_GPU)); + reason = "contains assertOnGpu()"; + auto isAttributeSym = toSymExpr(assertion->get(1)); + INT_ASSERT(isAttributeSym); + if (isAttributeSym->symbol() == gTrue) { + reason = "is marked with @assertOnGpu"; + } } USR_FATAL_CONT(loc, "Loop %s but is not eligible for execution on a GPU", reason); } @@ -617,6 +623,16 @@ bool GpuizableLoop::isReportWorthy() { return true; } +static CallExpr* toCallToGpuEligibilityPrimitive(Expr* expr) { + CallExpr *call = toCallExpr(expr); + if (call && + (call->isPrimitive(PRIM_ASSERT_ON_GPU) || + call->isPrimitive(PRIM_ASSERT_GPU_ELIGIBLE))) { + return call; + } + return nullptr; +} + CallExpr* GpuizableLoop::findCompileTimeGpuAssertions() { CForLoop *cfl = this->loop_; INT_ASSERT(cfl); @@ -629,8 +645,7 @@ CallExpr* GpuizableLoop::findCompileTimeGpuAssertions() { // assign to the loop iteration variable if we're iterating // over values rather than indices) for_alist(expr, cfl->body) { - CallExpr *call = toCallExpr(expr); - if (call && call->isPrimitive(PRIM_ASSERT_ON_GPU)) { + if (auto call = toCallToGpuEligibilityPrimitive(expr)) { return call; } @@ -639,8 +654,7 @@ CallExpr* GpuizableLoop::findCompileTimeGpuAssertions() { BlockStmt *blk = toBlockStmt(expr); if (blk && blk->isGpuPrimitivesBlock()) { for_alist(expr, blk->body) { - CallExpr *call = toCallExpr(expr); - if (call && call->isPrimitive(PRIM_ASSERT_ON_GPU)) { + if (auto call = toCallToGpuEligibilityPrimitive(expr)) { return call; } } @@ -1576,6 +1590,7 @@ bool isCallToPrimitiveWeShouldNotCopyIntoKernel(CallExpr *call) { if (!call) return false; return call->isPrimitive(PRIM_ASSERT_ON_GPU) || + call->isPrimitive(PRIM_ASSERT_GPU_ELIGIBLE) || call->isPrimitive(PRIM_GPU_SET_BLOCKSIZE) || call->isPrimitive(PRIM_GPU_PRIMITIVE_BLOCK); } @@ -2144,8 +2159,13 @@ static void cleanupPrimitives() { // uses of the primitive, which we process by removing the primitive but keeping // the copy. cleanupTaskIndependentCapturePrimitive(callExpr); - } - else if(callExpr->isPrimitive(PRIM_GPU_SET_BLOCKSIZE)) { + } else if (callExpr->isPrimitive(PRIM_GPU_SET_BLOCKSIZE) || + callExpr->isPrimitive(PRIM_ASSERT_GPU_ELIGIBLE)) { + callExpr->remove(); + } else if(callExpr->isPrimitive(PRIM_GPU_PRIMITIVE_BLOCK)) { + auto parentBlock = toBlockStmt(callExpr->parentExpr); + INT_ASSERT(parentBlock); + parentBlock->flattenAndRemove(); callExpr->remove(); } } diff --git a/compiler/passes/convert-uast.cpp b/compiler/passes/convert-uast.cpp index c7914df9a4b8..928e1f5a3b00 100644 --- a/compiler/passes/convert-uast.cpp +++ b/compiler/passes/convert-uast.cpp @@ -126,6 +126,9 @@ struct LoopAttributeInfo { LLVMMetadataList llvmMetadata; // The @assertOnGpu attribute, if one is provided by the user. const uast::Attribute* assertOnGpuAttr = nullptr; + // The @gpu.assertEligible attribute, which asserts GPU eligibility, + // if one is provided by the user. + const uast::Attribute* assertEligibleAttr = nullptr; // The @gpu.blockSize attribute, if one is provided by the user. const uast::Attribute* blockSizeAttr = nullptr; @@ -207,6 +210,7 @@ struct LoopAttributeInfo { void readNativeGpuAttributes(const uast::AttributeGroup* attrs) { this->assertOnGpuAttr = attrs->getAttributeNamed(USTR("assertOnGpu")); + this->assertEligibleAttr = attrs->getAttributeNamed(USTR("gpu.assertEligible")); this->blockSizeAttr = attrs->getAttributeNamed(USTR("gpu.blockSize")); } @@ -238,6 +242,7 @@ struct LoopAttributeInfo { bool empty() const { return llvmMetadata.size() == 0 && assertOnGpuAttr == nullptr && + assertEligibleAttr == nullptr && blockSizeAttr == nullptr; } @@ -462,12 +467,6 @@ struct Converter { return nullptr; } - void readNativeGpuAttributes(LoopAttributeInfo& into, - const uast::AttributeGroup* attrs) { - into.assertOnGpuAttr = attrs->getAttributeNamed(USTR("assertOnGpu")); - into.blockSizeAttr = attrs->getAttributeNamed(USTR("gpu.blockSize")); - } - Expr* visit(const uast::AttributeGroup* node) { INT_FATAL("Should not be called directly!"); return nullptr; @@ -1760,6 +1759,9 @@ struct Converter { if (loopAttributes.assertOnGpuAttr != nullptr) { CHPL_REPORT(context, InvalidGpuAssertion, node, loopAttributes.assertOnGpuAttr); + } else if (loopAttributes.assertEligibleAttr != nullptr) { + CHPL_REPORT(context, InvalidGpuAssertion, node, + loopAttributes.assertEligibleAttr); } return std::move(loopAttributes.llvmMetadata); } @@ -4366,12 +4368,16 @@ struct Converter { }; bool LoopAttributeInfo::insertGpuEligibilityAssertion(BlockStmt* body) { + bool inserted = false; if (assertOnGpuAttr) { - body->insertAtTail(new CallExpr(PRIM_ASSERT_ON_GPU, - new SymExpr(gTrue))); - return true; + body->insertAtTail(new CallExpr("chpl__assertOnGpuAttr")); + inserted = true; } - return false; + if (assertEligibleAttr) { + body->insertAtTail(new CallExpr("chpl__gpuAssertEligibleAttr")); + inserted = true; + } + return inserted; } bool LoopAttributeInfo::insertBlockSizeCall(Converter& converter, BlockStmt* body) { @@ -4384,16 +4390,11 @@ bool LoopAttributeInfo::insertBlockSizeCall(Converter& converter, BlockStmt* bod static int counter = 0; if (blockSizeAttr) { - if (blockSizeAttr->numActuals() != 1) { - USR_FATAL(blockSizeAttr->id(), - "'@gpu.blockSize' attribute must have exactly one argument: " - "the block size"); + auto newCall = new CallExpr("chpl__gpuBlockSizeAttr", new_IntSymbol(counter++)); + for (auto actual : blockSizeAttr->actuals()) { + newCall->insertAtTail(converter.convertAST(actual)); } - - Expr* blockSize = converter.convertAST(blockSizeAttr->actual(0)); - body->insertAtTail(new CallExpr(PRIM_GPU_SET_BLOCKSIZE, - blockSize, - new_IntSymbol(counter++))); + body->insertAtTail(newCall); return true; } return false; diff --git a/frontend/include/chpl/framework/all-global-strings.h b/frontend/include/chpl/framework/all-global-strings.h index 9a85315af775..19254db72b5e 100644 --- a/frontend/include/chpl/framework/all-global-strings.h +++ b/frontend/include/chpl/framework/all-global-strings.h @@ -57,6 +57,7 @@ X(forall , "forall") X(foreach , "foreach") X(functionStatic , "functionStatic") X(generate , "generate") +X(gpuAssertEligible , "gpu.assertEligible") X(gpuBlockSize , "gpu.blockSize") X(hash_ , "hash") X(imag_ , "imag") diff --git a/frontend/include/chpl/uast/prim-ops-list.h b/frontend/include/chpl/uast/prim-ops-list.h index d70c40fca814..49c69db3ff1d 100644 --- a/frontend/include/chpl/uast/prim-ops-list.h +++ b/frontend/include/chpl/uast/prim-ops-list.h @@ -173,6 +173,7 @@ PRIMITIVE_G(GPU_ALLOC_SHARED, "gpu allocShared") PRIMITIVE_G(GPU_SYNC_THREADS, "gpu syncThreads") PRIMITIVE_R(GPU_SET_BLOCKSIZE, "gpu set blockSize") PRIMITIVE_G(ASSERT_ON_GPU, "chpl_assert_on_gpu") +PRIMITIVE_R(ASSERT_GPU_ELIGIBLE, "assert gpu eligible") PRIMITIVE_R(GPU_ELIGIBLE, "gpu eligible") PRIMITIVE_G(GPU_INIT_KERNEL_CFG, "gpu init kernel cfg") PRIMITIVE_G(GPU_INIT_KERNEL_CFG_3D, "gpu init kernel cfg 3d") diff --git a/frontend/lib/resolution/prims.cpp b/frontend/lib/resolution/prims.cpp index 20bf5dff2eee..23219f40cd49 100644 --- a/frontend/lib/resolution/prims.cpp +++ b/frontend/lib/resolution/prims.cpp @@ -1636,6 +1636,10 @@ CallResolutionResult resolvePrimCall(Context* context, type = primAssertOnGpu(context, ci); break; + case PRIM_ASSERT_GPU_ELIGIBLE: + type = QualifiedType(QualifiedType::CONST_VAR, VoidType::get(context)); + break; + case PRIM_GPU_INIT_KERNEL_CFG: case PRIM_GPU_INIT_KERNEL_CFG_3D: type = QualifiedType(QualifiedType::CONST_VAR, CPtrType::getCVoidPtrType(context)); diff --git a/frontend/lib/uast/post-parse-checks.cpp b/frontend/lib/uast/post-parse-checks.cpp index 8c894f4f47d8..cfa7eed17f82 100644 --- a/frontend/lib/uast/post-parse-checks.cpp +++ b/frontend/lib/uast/post-parse-checks.cpp @@ -1620,6 +1620,7 @@ void Visitor::checkAttributeNameRecognizedOrToolSpaced(const Attribute* node) { node->name() == USTR("stable") || node->name() == USTR("functionStatic") || node->name() == USTR("assertOnGpu") || + node->name() == USTR("gpu.assertEligible") || node->name() == USTR("gpu.blockSize") || node->name().startsWith(USTR("chpldoc.")) || node->name().startsWith(USTR("chplcheck.")) || @@ -1653,13 +1654,15 @@ void Visitor::checkAttributeAppliedToCorrectNode(const Attribute* attr) { auto attributeGroup = parents_[parents_.size() - 1]; CHPL_ASSERT(attributeGroup->isAttributeGroup()); auto node = parents_[parents_.size() - 2]; - if (attr->name() == USTR("assertOnGpu") || attr->name() == USTR("gpu.blockSize")) { + if (attr->name() == USTR("assertOnGpu") || + attr->name() == USTR("gpu.blockSize") || + attr->name() == USTR("gpu.assertEligible")) { if (node->isForall() || node->isForeach()) return; if (auto var = node->toVariable()) { if (!var->isField()) return; } - if (attr->name() == USTR("assertOnGpu")) { + if (attr->name() == USTR("assertOnGpu") || attr->name() == USTR("gpu.assertEligible")) { CHPL_REPORT(context_, InvalidGpuAssertion, node, attr); } else { CHPL_ASSERT(attr->name() == USTR("gpu.blockSize")); diff --git a/modules/internal/ChapelStandard.chpl b/modules/internal/ChapelStandard.chpl index 662acb8dd374..a334dd7ac8ce 100644 --- a/modules/internal/ChapelStandard.chpl +++ b/modules/internal/ChapelStandard.chpl @@ -81,6 +81,7 @@ module ChapelStandard { // Standard modules. public use Types as Types; public use AutoMath as AutoMath; + public use AutoGpu as AutoGpu; use stopInitCommDiags; // Internal, but uses standard/CommDiagnostics } diff --git a/modules/standard/AutoGpu.chpl b/modules/standard/AutoGpu.chpl new file mode 100644 index 000000000000..0649ad47b149 --- /dev/null +++ b/modules/standard/AutoGpu.chpl @@ -0,0 +1,64 @@ +/* + * Copyright 2024 Hewlett Packard Enterprise Development LP + * Other additional copyright holders may be indicated within. + * + * The entirety of this work is licensed under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma "module included by default" +@unstable("The module name 'AutoGpu' is unstable.") +module AutoGpu { + // This module supports GPU-specific attributes like @gpu.assertEligible + // @assertOnGpu. These attributes are translated into calls to procedures + // in this module as part of the loop body, which insert various GPU + // primitives. The primitives are used to configure the GPU execution. + + use ChplConfig; + use Errors; + + inline proc chpl__gpuAssertEligibleAttr() { + if CHPL_LOCALE_MODEL == "gpu" then + __primitive("assert gpu eligible"); + } + + config param silenceAssertOnGpuWarning = false; + + inline proc chpl__assertOnGpuAttr() { + if CHPL_LOCALE_MODEL != "gpu" && !silenceAssertOnGpuWarning { + compilerWarning("@assertOnGpu encountered in non-GPU compilation"); + compilerWarning("this attribute has a runtime component, and will ", + "always halt execution in a non-GPU context."); + compilerWarning("consider using '@gpu.assertEligible' to ensure ", + "that the code can be executed on the GPU without ", + "runtime checks."); + } + __primitive("chpl_assert_on_gpu", true); + } + + inline proc chpl__gpuBlockSizeAttr(param counter: int, arg: integral) { + if CHPL_LOCALE_MODEL == "gpu" then + __primitive("gpu set blockSize", arg, counter); + } + + pragma "last resort" + inline proc chpl__gpuBlockSizeAttr(param counter: int, rest ...) { + compilerError("'@gpu.blockSize' attribute must have exactly one argument: an integral value for the block size"); + } + + pragma "last resort" + inline proc chpl__gpuBlockSizeAttr(param counter: int) { + compilerError("'@gpu.blockSize' attribute must have exactly one argument: an integral value for the block size"); + } +} diff --git a/runtime/include/chpl-gpu.h b/runtime/include/chpl-gpu.h index 9115c42755f2..68becf511105 100644 --- a/runtime/include/chpl-gpu.h +++ b/runtime/include/chpl-gpu.h @@ -201,6 +201,15 @@ GPU_CUB_WRAP(DECL_ONE_SORT, keys); #undef DECL_ONE_SORT +#else // HAS_GPU_LOCALE + +// Provide a fallback for the chpl_assert_on_gpu function for non-GPU locales. +// This works exactly the same as the standard one. + +static inline void chpl_assert_on_gpu(int32_t ln, int32_t fn) { + chpl_error("assertOnGpu() failed", ln, fn); +} + #endif // HAS_GPU_LOCALE #ifdef __cplusplus diff --git a/test/compflags/ferguson/print-module-resolution.good b/test/compflags/ferguson/print-module-resolution.good index 6e204c91df7b..91e27f4fc983 100644 --- a/test/compflags/ferguson/print-module-resolution.good +++ b/test/compflags/ferguson/print-module-resolution.good @@ -210,6 +210,8 @@ ChapelStaticVars from print-module-resolution.ChapelStandard.ChapelStaticVars ChapelRemoteVars from print-module-resolution.ChapelStandard.ChapelRemoteVars +AutoGpu + from print-module-resolution.ChapelStandard.AutoGpu stopInitCommDiags from print-module-resolution.ChapelStandard.stopInitCommDiags ChapelStandard diff --git a/test/gpu/native/assertEligibleNoRuntime.chpl b/test/gpu/native/assertEligibleNoRuntime.chpl new file mode 100644 index 000000000000..af53ab7716ea --- /dev/null +++ b/test/gpu/native/assertEligibleNoRuntime.chpl @@ -0,0 +1,4 @@ +@gpu.assertEligible +var A = foreach i in 1..100 do i; + +writeln("all is good; '@gpu.assertEligible' doesn't require GPU execution."); diff --git a/test/gpu/native/assertEligibleNoRuntime.good b/test/gpu/native/assertEligibleNoRuntime.good new file mode 100644 index 000000000000..e66075a53ab8 --- /dev/null +++ b/test/gpu/native/assertEligibleNoRuntime.good @@ -0,0 +1 @@ +all is good; '@gpu.assertEligible' doesn't require GPU execution. diff --git a/test/gpu/native/assertOnNotGpuEligible.1.good b/test/gpu/native/assertOnNotGpuEligible.1.good new file mode 100644 index 000000000000..ef2b9fccbfed --- /dev/null +++ b/test/gpu/native/assertOnNotGpuEligible.1.good @@ -0,0 +1,3 @@ +assertOnNotGpuEligible.chpl:15: In function 'funcMarkedNotGpuizableThatTriesToGpuize': +assertOnNotGpuEligible.chpl:17: error: Loop is marked with @gpu.assertEligible but is not eligible for execution on a GPU +assertOnNotGpuEligible.chpl:15: note: parent function disallows execution on a GPU diff --git a/test/gpu/native/assertOnNotGpuEligible.2.good b/test/gpu/native/assertOnNotGpuEligible.2.good new file mode 100644 index 000000000000..8fce325aac46 --- /dev/null +++ b/test/gpu/native/assertOnNotGpuEligible.2.good @@ -0,0 +1,3 @@ +assertOnNotGpuEligible.chpl:32: error: Loop is marked with @gpu.assertEligible but is not eligible for execution on a GPU +assertOnNotGpuEligible.chpl:23: note: function is marked as not eligible for GPU execution +assertOnNotGpuEligible.chpl:33: note: reached via call to 'funcMarkedNotGpuizable' in loop body here diff --git a/test/gpu/native/assertOnNotGpuEligible.3.good b/test/gpu/native/assertOnNotGpuEligible.3.good new file mode 100644 index 000000000000..c87765749d27 --- /dev/null +++ b/test/gpu/native/assertOnNotGpuEligible.3.good @@ -0,0 +1,3 @@ +assertOnNotGpuEligible.chpl:39: error: Loop is marked with @gpu.assertEligible but is not eligible for execution on a GPU +assertOnNotGpuEligible.chpl:12: note: called function has outer var access +assertOnNotGpuEligible.chpl:40: note: reached via call to 'usesOutsideVar' in loop body here diff --git a/test/gpu/native/assertOnNotGpuEligible.4.good b/test/gpu/native/assertOnNotGpuEligible.4.good new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/gpu/native/assertOnNotGpuEligible.chpl b/test/gpu/native/assertOnNotGpuEligible.chpl new file mode 100644 index 000000000000..d604b35ae412 --- /dev/null +++ b/test/gpu/native/assertOnNotGpuEligible.chpl @@ -0,0 +1,82 @@ +// This test and assertOnFailToGpuize are siblings; this one tests +// @gpu.assertEligible, which does not have a runtime component. + +use GPU; + +config param failureMode = 8; +var globalVar = 0; + +proc directlyRecursiveFunc(i:int) { if i > 0 then directlyRecursiveFunc(i-1); } +proc indirectlyRecursiveFunc(i:int) { if i > 0 then indirectlyRecursiveFunc2(i-1); } +proc indirectlyRecursiveFunc2(i:int) { if i > 0 then indirectlyRecursiveFunc(i-1); } +proc usesOutsideVar() { return globalVar; } + +pragma "no gpu codegen" +proc funcMarkedNotGpuizableThatTriesToGpuize() { + @gpu.assertEligible + foreach i in 0..10 { + + } +} + +pragma "no gpu codegen" +proc funcMarkedNotGpuizable() { } + +on here.gpus[0] { + if failureMode == 1 { + funcMarkedNotGpuizableThatTriesToGpuize(); + } + + if failureMode == 2 { + @gpu.assertEligible + foreach i in 0..10 { + funcMarkedNotGpuizable(); + } + } + + if failureMode == 3 { + @gpu.assertEligible + foreach i in 0..10 { + usesOutsideVar(); + } + } + + // Also ensure that gpu.assertEligible does not fail + // for the following (use failureMode >= 4 + // to run these tests): + + // calling a recursive function is allowed now + @gpu.assertEligible + foreach i in 0..10 { + directlyRecursiveFunc(i); + } + + @gpu.assertEligible + foreach i in 0..10 { + indirectlyRecursiveFunc(i); + } + + // I want to ensure this works + // with forall loops as well: + @gpu.assertEligible + forall i in 0..10 { + directlyRecursiveFunc(i); + } + + // And loops of a multidimensional array: + { + var A: [1..10, 1..10] int; + @gpu.assertEligible + foreach a in A { + directlyRecursiveFunc(5); + } + } + + @gpu.assertEligible foreach i in 0..10 { } + @gpu.assertEligible forall i in 0..10 { } + var A: [1..10, 1..10] int; + @gpu.assertEligible foreach a in A { } + @gpu.assertEligible foreach idx in {0..10, 0..10} { } + @gpu.assertEligible forall a in A { } + @gpu.assertEligible forall idx in {0..10, 0..10} { } +} diff --git a/test/gpu/native/assertOnNotGpuEligible.compopts b/test/gpu/native/assertOnNotGpuEligible.compopts new file mode 100755 index 000000000000..3bd8209478e3 --- /dev/null +++ b/test/gpu/native/assertOnNotGpuEligible.compopts @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 + +import os + +for i in range(1, 5): + # We currently skip configuration 3 when CHPL_COMM is not none see + # https://github.com/chapel-lang/chapel/issues/20641. TODO: re-enable this + # once this works in our gasnet configuration. + if i == 3 and os.getenv('CHPL_COMM') != 'none': + continue + print('-sfailureMode={} # assertOnNotGpuEligible.{}.good'.format(i, i)) diff --git a/test/gpu/native/basics/blockSizeNotEnough.chpl b/test/gpu/native/basics/blockSizeNotEnough.chpl new file mode 100644 index 000000000000..0a17cf083dec --- /dev/null +++ b/test/gpu/native/basics/blockSizeNotEnough.chpl @@ -0,0 +1,6 @@ +on here.gpus[0] { + @gpu.blockSize + foreach 1..128 { + + } +} diff --git a/test/gpu/native/basics/blockSizeNotEnough.good b/test/gpu/native/basics/blockSizeNotEnough.good new file mode 100644 index 000000000000..fe99b20409d2 --- /dev/null +++ b/test/gpu/native/basics/blockSizeNotEnough.good @@ -0,0 +1 @@ +blockSizeNotEnough.chpl:3: error: '@gpu.blockSize' attribute must have exactly one argument: an integral value for the block size diff --git a/test/gpu/native/basics/blockSizeNotIntegral.chpl b/test/gpu/native/basics/blockSizeNotIntegral.chpl new file mode 100644 index 000000000000..016a23267518 --- /dev/null +++ b/test/gpu/native/basics/blockSizeNotIntegral.chpl @@ -0,0 +1,6 @@ +on here.gpus[0] { + @gpu.blockSize(128.1) + foreach 1..128 { + + } +} diff --git a/test/gpu/native/basics/blockSizeNotIntegral.good b/test/gpu/native/basics/blockSizeNotIntegral.good new file mode 100644 index 000000000000..16f81a4c23fa --- /dev/null +++ b/test/gpu/native/basics/blockSizeNotIntegral.good @@ -0,0 +1 @@ +blockSizeNotIntegral.chpl:3: error: '@gpu.blockSize' attribute must have exactly one argument: an integral value for the block size diff --git a/test/gpu/native/basics/blockSizeTooMany.chpl b/test/gpu/native/basics/blockSizeTooMany.chpl new file mode 100644 index 000000000000..728448dd2f3c --- /dev/null +++ b/test/gpu/native/basics/blockSizeTooMany.chpl @@ -0,0 +1,6 @@ +on here.gpus[0] { + @gpu.blockSize(128, 128) + foreach 1..128 { + + } +} diff --git a/test/gpu/native/basics/blockSizeTooMany.good b/test/gpu/native/basics/blockSizeTooMany.good new file mode 100644 index 000000000000..44ede9189402 --- /dev/null +++ b/test/gpu/native/basics/blockSizeTooMany.good @@ -0,0 +1 @@ +blockSizeTooMany.chpl:3: error: '@gpu.blockSize' attribute must have exactly one argument: an integral value for the block size diff --git a/test/gpu/nongpu.skipif b/test/gpu/nongpu.skipif new file mode 100644 index 000000000000..92209123becc --- /dev/null +++ b/test/gpu/nongpu.skipif @@ -0,0 +1 @@ +CHPL_LOCALE_MODEL==gpu diff --git a/test/gpu/nongpu/assertEligible.chpl b/test/gpu/nongpu/assertEligible.chpl new file mode 100644 index 000000000000..3faf7c4329e6 --- /dev/null +++ b/test/gpu/nongpu/assertEligible.chpl @@ -0,0 +1,16 @@ +config param case = 0; + +const loc = if here.gpus.size > 0 then here.gpus[0] else here; + +on loc { + if case == 0 { + var A: [1..10] int; + @gpu.assertEligible + foreach i in 1..10 { + A[i] = i*i; + } + } else if case == 1 { + @gpu.assertEligible + var A = foreach i in 1..10 do i*i; + } +} diff --git a/test/gpu/nongpu/assertEligible.compopts b/test/gpu/nongpu/assertEligible.compopts new file mode 100644 index 000000000000..6a49889c1bc5 --- /dev/null +++ b/test/gpu/nongpu/assertEligible.compopts @@ -0,0 +1,2 @@ +-scase=0 # assertEligible.stmt.good +-scase=1 # assertEligible.var.good diff --git a/test/gpu/nongpu/assertEligible.stmt.good b/test/gpu/nongpu/assertEligible.stmt.good new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/gpu/nongpu/assertEligible.var.good b/test/gpu/nongpu/assertEligible.var.good new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/gpu/nongpu/assertOnGpu.chpl b/test/gpu/nongpu/assertOnGpu.chpl new file mode 100644 index 000000000000..f15800a1fc8d --- /dev/null +++ b/test/gpu/nongpu/assertOnGpu.chpl @@ -0,0 +1,16 @@ +config param case = 0; + +const loc = if here.gpus.size > 0 then here.gpus[0] else here; + +on loc { + if case == 0 { + var A: [1..10] int; + @assertOnGpu + foreach i in 1..10 { + A[i] = i*i; + } + } else if case == 1 { + @assertOnGpu + var A = foreach i in 1..10 do i*i; + } +} diff --git a/test/gpu/nongpu/assertOnGpu.compopts b/test/gpu/nongpu/assertOnGpu.compopts new file mode 100644 index 000000000000..9968b7d0da4d --- /dev/null +++ b/test/gpu/nongpu/assertOnGpu.compopts @@ -0,0 +1,2 @@ +-scase=0 # assertOnGpu.stmt.good +-scase=1 # assertOnGpu.var.good diff --git a/test/gpu/nongpu/assertOnGpu.stmt.good b/test/gpu/nongpu/assertOnGpu.stmt.good new file mode 100644 index 000000000000..777d47fa819a --- /dev/null +++ b/test/gpu/nongpu/assertOnGpu.stmt.good @@ -0,0 +1,4 @@ +assertOnGpu.chpl:9: warning: @assertOnGpu encountered in non-GPU compilation +assertOnGpu.chpl:9: warning: this attribute has a runtime component, and will always halt execution in a non-GPU context. +assertOnGpu.chpl:9: warning: consider using '@gpu.assertEligible' to ensure that the code can be executed on the GPU without runtime checks. +assertOnGpu.chpl:9: error: assertOnGpu() failed diff --git a/test/gpu/nongpu/assertOnGpu.var.good b/test/gpu/nongpu/assertOnGpu.var.good new file mode 100644 index 000000000000..00c3e745f540 --- /dev/null +++ b/test/gpu/nongpu/assertOnGpu.var.good @@ -0,0 +1,5 @@ +assertOnGpu.chpl:14: warning: @assertOnGpu encountered in non-GPU compilation +assertOnGpu.chpl:14: warning: this attribute has a runtime component, and will always halt execution in a non-GPU context. +assertOnGpu.chpl:14: warning: consider using '@gpu.assertEligible' to ensure that the code can be executed on the GPU without runtime checks. +assertOnGpu.chpl:14: warning: consider using '@gpu.assertEligible' to ensure that the code can be executed on the GPU without runtime checks. +assertOnGpu.chpl:14: error: assertOnGpu() failed diff --git a/test/gpu/nongpu/blockSize.chpl b/test/gpu/nongpu/blockSize.chpl new file mode 100644 index 000000000000..8656381fbce2 --- /dev/null +++ b/test/gpu/nongpu/blockSize.chpl @@ -0,0 +1,16 @@ +config param case = 0; + +const loc = if here.gpus.size > 0 then here.gpus[0] else here; + +on loc { + if case == 0 { + var A: [1..10] int; + @gpu.blockSize(128) + foreach i in 1..10 { + A[i] = i*i; + } + } else if case == 1 { + @gpu.blockSize(128) + var A = foreach i in 1..10 do i*i; + } +} diff --git a/test/gpu/nongpu/blockSize.compopts b/test/gpu/nongpu/blockSize.compopts new file mode 100644 index 000000000000..dfe9186ccf80 --- /dev/null +++ b/test/gpu/nongpu/blockSize.compopts @@ -0,0 +1,2 @@ +-scase=0 # blockSize.stmt.good +-scase=1 # blockSize.var.good diff --git a/test/gpu/nongpu/blockSize.stmt.good b/test/gpu/nongpu/blockSize.stmt.good new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/gpu/nongpu/blockSize.var.good b/test/gpu/nongpu/blockSize.var.good new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/modules/bradc/printModStuff/foo.good b/test/modules/bradc/printModStuff/foo.good index 5f3caa7dc416..8ef1f117ef2e 100644 --- a/test/modules/bradc/printModStuff/foo.good +++ b/test/modules/bradc/printModStuff/foo.good @@ -39,6 +39,7 @@ Parsing module files: $CHPL_HOME/modules/packages/Search.chpl $CHPL_HOME/modules/standard/Allocators.chpl $CHPL_HOME/modules/packages/CopyAggregation.chpl + $CHPL_HOME/modules/standard/AutoGpu.chpl subdir/bar.chpl subdir/baz.chpl subdir1/bak.chpl