Skip to content

Commit e69e551

Browse files
ffrankiesAaronBallman
authored andcommitted
new altera single work item barrier check
This lint check is a part of the FLOCL (FPGA Linters for OpenCL) project out of the Synergy Lab at Virginia Tech. FLOCL is a set of lint checks aimed at FPGA developers who write code in OpenCL. The altera single work item barrier check finds OpenCL kernel functions that call a barrier function but do not call an ID function. These kernel functions will be treated as single work-item kernels, which could be inefficient or lead to errors. Based on the "Altera SDK for OpenCL: Best Practices Guide."
1 parent e35f922 commit e69e551

File tree

8 files changed

+493
-0
lines changed

8 files changed

+493
-0
lines changed

clang-tools-extra/clang-tidy/altera/AlteraTidyModule.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "../ClangTidyModule.h"
1111
#include "../ClangTidyModuleRegistry.h"
1212
#include "KernelNameRestrictionCheck.h"
13+
#include "SingleWorkItemBarrierCheck.h"
1314
#include "StructPackAlignCheck.h"
1415

1516
using namespace clang::ast_matchers;
@@ -23,6 +24,8 @@ class AlteraModule : public ClangTidyModule {
2324
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
2425
CheckFactories.registerCheck<KernelNameRestrictionCheck>(
2526
"altera-kernel-name-restriction");
27+
CheckFactories.registerCheck<SingleWorkItemBarrierCheck>(
28+
"altera-single-work-item-barrier");
2629
CheckFactories.registerCheck<StructPackAlignCheck>(
2730
"altera-struct-pack-align");
2831
}

clang-tools-extra/clang-tidy/altera/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS
66
add_clang_library(clangTidyAlteraModule
77
AlteraTidyModule.cpp
88
KernelNameRestrictionCheck.cpp
9+
SingleWorkItemBarrierCheck.cpp
910
StructPackAlignCheck.cpp
1011

1112
LINK_LIBS
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//===--- SingleWorkItemBarrierCheck.cpp - clang-tidy-----------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "SingleWorkItemBarrierCheck.h"
10+
#include "clang/AST/ASTContext.h"
11+
#include "clang/ASTMatchers/ASTMatchFinder.h"
12+
13+
using namespace clang::ast_matchers;
14+
15+
namespace clang {
16+
namespace tidy {
17+
namespace altera {
18+
19+
void SingleWorkItemBarrierCheck::registerMatchers(MatchFinder *Finder) {
20+
// Find any function that calls barrier but does not call an ID function.
21+
// hasAttr(attr::Kind::OpenCLKernel) restricts it to only kernel functions.
22+
// FIXME: Have it accept all functions but check for a parameter that gets an
23+
// ID from one of the four ID functions.
24+
Finder->addMatcher(
25+
// Find function declarations...
26+
functionDecl(
27+
allOf(
28+
// That are OpenCL kernels...
29+
hasAttr(attr::Kind::OpenCLKernel),
30+
// And call a barrier function (either 1.x or 2.x version)...
31+
forEachDescendant(callExpr(callee(functionDecl(hasAnyName(
32+
"barrier", "work_group_barrier"))))
33+
.bind("barrier")),
34+
// But do not call an ID function.
35+
unless(hasDescendant(callExpr(callee(functionDecl(
36+
hasAnyName("get_global_id", "get_local_id", "get_group_id",
37+
"get_local_linear_id"))))))))
38+
.bind("function"),
39+
this);
40+
}
41+
42+
void SingleWorkItemBarrierCheck::check(const MatchFinder::MatchResult &Result) {
43+
const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>("function");
44+
const auto *MatchedBarrier = Result.Nodes.getNodeAs<CallExpr>("barrier");
45+
if (AOCVersion < 1701) {
46+
// get_group_id and get_local_linear_id were added at/after v17.01
47+
diag(MatchedDecl->getLocation(),
48+
"kernel function %0 does not call 'get_global_id' or 'get_local_id' "
49+
"and will be treated as a single work-item")
50+
<< MatchedDecl;
51+
diag(MatchedBarrier->getBeginLoc(),
52+
"barrier call is in a single work-item and may error out",
53+
DiagnosticIDs::Note);
54+
} else {
55+
// If reqd_work_group_size is anything other than (1,1,1), it will be
56+
// interpreted as an NDRange in AOC version >= 17.1.
57+
bool IsNDRange = false;
58+
if (MatchedDecl->hasAttr<ReqdWorkGroupSizeAttr>()) {
59+
const auto *Attribute = MatchedDecl->getAttr<ReqdWorkGroupSizeAttr>();
60+
if (Attribute->getXDim() > 1 || Attribute->getYDim() > 1 ||
61+
Attribute->getZDim() > 1)
62+
IsNDRange = true;
63+
}
64+
if (IsNDRange) // No warning if kernel is treated as an NDRange.
65+
return;
66+
diag(MatchedDecl->getLocation(),
67+
"kernel function %0 does not call an ID function and may be a viable "
68+
"single work-item, but will be forced to execute as an NDRange")
69+
<< MatchedDecl;
70+
diag(MatchedBarrier->getBeginLoc(),
71+
"barrier call will force NDRange execution; if single work-item "
72+
"semantics are desired a mem_fence may be more efficient",
73+
DiagnosticIDs::Note);
74+
}
75+
}
76+
77+
void SingleWorkItemBarrierCheck::storeOptions(
78+
ClangTidyOptions::OptionMap &Opts) {
79+
Options.store(Opts, "AOCVersion", AOCVersion);
80+
}
81+
82+
} // namespace altera
83+
} // namespace tidy
84+
} // namespace clang
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===--- SingleWorkItemBarrierCheck.h - clang-tidy---------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALTERA_SINGLE_WORK_ITEM_BARRIER_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALTERA_SINGLE_WORK_ITEM_BARRIER_H
11+
12+
#include "../ClangTidyCheck.h"
13+
14+
namespace clang {
15+
namespace tidy {
16+
namespace altera {
17+
18+
/// Detects OpenCL kernel functions that call a barrier but do not call an
19+
/// ID-function function. These functions will be treated as single work-item
20+
/// kernels, which may be inefficient or cause an error.
21+
///
22+
/// For the user-facing documentation see:
23+
/// http://clang.llvm.org/extra/clang-tidy/checks/opencl-single-work-item-barrier.html
24+
class SingleWorkItemBarrierCheck : public ClangTidyCheck {
25+
const unsigned AOCVersion;
26+
27+
public:
28+
SingleWorkItemBarrierCheck(StringRef Name, ClangTidyContext *Context)
29+
: ClangTidyCheck(Name, Context),
30+
AOCVersion(Options.get("AOCVersion", 1600U)) {}
31+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
32+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
33+
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
34+
};
35+
36+
} // namespace altera
37+
} // namespace tidy
38+
} // namespace clang
39+
40+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALTERA_SINGLE_WORK_ITEM_BARRIER_H

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ New checks
9999
Finds kernel files and include directives whose filename is `kernel.cl`,
100100
`Verilog.cl`, or `VHDL.cl`.
101101

102+
- New :doc:`altera-single-work-item-barrier
103+
<clang-tidy/checks/altera-single-work-item-barrier>` check.
104+
105+
Finds OpenCL kernel functions that call a barrier function but do not call
106+
an ID function.
107+
102108
- New :doc:`altera-struct-pack-align
103109
<clang-tidy/checks/altera-struct-pack-align>` check.
104110

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
.. title:: clang-tidy - altera-single-work-item-barrier
2+
3+
altera-single-work-item-barrier
4+
===============================
5+
6+
Finds OpenCL kernel functions that call a barrier function but do not call
7+
an ID function (``get_local_id``, ``get_local_id``, ``get_group_id``, or
8+
``get_local_linear_id``).
9+
10+
These kernels may be viable single work-item kernels, but will be forced to
11+
execute as NDRange kernels if using a newer version of the Altera Offline
12+
Compiler (>= v17.01).
13+
14+
If using an older version of the Altera Offline Compiler, these kernel
15+
functions will be treated as single work-item kernels, which could be
16+
inefficient or lead to errors if NDRange semantics were intended.
17+
18+
Based on the `Altera SDK for OpenCL: Best Practices Guide
19+
<https://www.altera.com/en_US/pdfs/literature/hb/opencl-sdk/aocl_optimization_guide.pdf>`_.
20+
21+
Examples:
22+
23+
.. code-block:: c++
24+
25+
// error: function calls barrier but does not call an ID function.
26+
void __kernel barrier_no_id(__global int * foo, int size) {
27+
for (int i = 0; i < 100; i++) {
28+
foo[i] += 5;
29+
}
30+
barrier(CLK_GLOBAL_MEM_FENCE);
31+
}
32+
33+
// ok: function calls barrier and an ID function.
34+
void __kernel barrier_with_id(__global int * foo, int size) {
35+
for (int i = 0; i < 100; i++) {
36+
int tid = get_global_id(0);
37+
foo[tid] += 5;
38+
}
39+
barrier(CLK_GLOBAL_MEM_FENCE);
40+
}
41+
42+
// ok with AOC Version 17.01: the reqd_work_group_size turns this into
43+
// an NDRange.
44+
__attribute__((reqd_work_group_size(2,2,2)))
45+
void __kernel barrier_with_id(__global int * foo, int size) {
46+
for (int i = 0; i < 100; i++) {
47+
foo[tid] += 5;
48+
}
49+
barrier(CLK_GLOBAL_MEM_FENCE);
50+
}
51+
52+
Options
53+
-------
54+
55+
.. option:: AOCVersion
56+
57+
Defines the version of the Altera Offline Compiler. Defaults to ``1600``
58+
(corresponding to version 16.00).

clang-tools-extra/docs/clang-tidy/checks/list.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Clang-Tidy Checks
3131
`abseil-time-subtraction <abseil-time-subtraction.html>`_, "Yes"
3232
`abseil-upgrade-duration-conversions <abseil-upgrade-duration-conversions.html>`_, "Yes"
3333
`altera-kernel-name-restriction <altera-kernel-name-restriction.html>`_,
34+
`altera-single-work-item-barrier <altera-single-work-item-barrier.html>`_, "Yes"
3435
`altera-struct-pack-align <altera-struct-pack-align.html>`_,
3536
`android-cloexec-accept <android-cloexec-accept.html>`_, "Yes"
3637
`android-cloexec-accept4 <android-cloexec-accept4.html>`_,

0 commit comments

Comments
 (0)