[clang-tools-extra] r325272 - [clang-tidy] Add `readability-simd-intrinsics` check.
Fangrui Song via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 15 09:56:43 PST 2018
Author: maskray
Date: Thu Feb 15 09:56:43 2018
New Revision: 325272
URL: http://llvm.org/viewvc/llvm-project?rev=325272&view=rev
Log:
[clang-tidy] Add `readability-simd-intrinsics` check.
Summary:
Many architectures provide SIMD operations (e.g. x86 SSE/AVX, Power AltiVec/VSX,
ARM NEON). It is common that SIMD code implementing the same algorithm, is
written in multiple target-dispatching pieces to optimize for different
architectures or micro-architectures.
The C++ standard proposal P0214 and its extensions cover many common SIMD
operations. By migrating from target-dependent intrinsics to P0214 operations,
the SIMD code can be simplified and pieces for different targets can be unified.
Refer to http://wg21.link/p0214 for introduction and motivation for the
data-parallel standard library.
Subscribers: klimek, aemerson, mgorny, xazax.hun, kristof.beyls, hintonda, cfe-commits
Differential Revision: https://reviews.llvm.org/D42983
Added:
clang-tools-extra/trunk/clang-tidy/readability/SIMDIntrinsicsCheck.cpp
clang-tools-extra/trunk/clang-tidy/readability/SIMDIntrinsicsCheck.h
clang-tools-extra/trunk/docs/clang-tidy/checks/readability-simd-intrinsics.rst
clang-tools-extra/trunk/test/clang-tidy/readability-simd-intrinsics-ppc.cpp
clang-tools-extra/trunk/test/clang-tidy/readability-simd-intrinsics-x86.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt
clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp
clang-tools-extra/trunk/docs/ReleaseNotes.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
Modified: clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt?rev=325272&r1=325271&r2=325272&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt Thu Feb 15 09:56:43 2018
@@ -24,6 +24,7 @@ add_clang_library(clangTidyReadabilityMo
RedundantStringCStrCheck.cpp
RedundantSmartptrGetCheck.cpp
RedundantStringInitCheck.cpp
+ SIMDIntrinsicsCheck.cpp
SimplifyBooleanExprCheck.cpp
StaticAccessedThroughInstanceCheck.cpp
StaticDefinitionInAnonymousNamespaceCheck.cpp
Modified: clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp?rev=325272&r1=325271&r2=325272&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp Thu Feb 15 09:56:43 2018
@@ -31,6 +31,7 @@
#include "RedundantSmartptrGetCheck.h"
#include "RedundantStringCStrCheck.h"
#include "RedundantStringInitCheck.h"
+#include "SIMDIntrinsicsCheck.h"
#include "SimplifyBooleanExprCheck.h"
#include "StaticAccessedThroughInstanceCheck.h"
#include "StaticDefinitionInAnonymousNamespaceCheck.h"
@@ -92,6 +93,8 @@ public:
"readability-redundant-string-cstr");
CheckFactories.registerCheck<RedundantStringInitCheck>(
"readability-redundant-string-init");
+ CheckFactories.registerCheck<SIMDIntrinsicsCheck>(
+ "readability-simd-intrinsics");
CheckFactories.registerCheck<SimplifyBooleanExprCheck>(
"readability-simplify-boolean-expr");
CheckFactories.registerCheck<UniqueptrDeleteReleaseCheck>(
Added: clang-tools-extra/trunk/clang-tidy/readability/SIMDIntrinsicsCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/SIMDIntrinsicsCheck.cpp?rev=325272&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/SIMDIntrinsicsCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/readability/SIMDIntrinsicsCheck.cpp Thu Feb 15 09:56:43 2018
@@ -0,0 +1,152 @@
+//===--- SIMDIntrinsicsCheck.cpp - clang-tidy------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SIMDIntrinsicsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Regex.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+namespace {
+
+// If the callee has parameter of VectorType or pointer to VectorType,
+// or the return type is VectorType, we consider it a vector function
+// and a candidate for checking.
+AST_MATCHER(FunctionDecl, isVectorFunction) {
+ bool IsVector = Node.getReturnType()->isVectorType();
+ for (const ParmVarDecl *Parm : Node.parameters()) {
+ QualType Type = Parm->getType();
+ if (Type->isPointerType())
+ Type = Type->getPointeeType();
+ if (Type->isVectorType())
+ IsVector = true;
+ }
+ return IsVector;
+}
+
+} // namespace
+
+static StringRef TrySuggestPPC(StringRef Name) {
+ if (!Name.consume_front("vec_"))
+ return {};
+
+ static const llvm::StringMap<StringRef> Mapping{
+ // [simd.alg]
+ {"max", "$std::max"},
+ {"min", "$std::min"},
+
+ // [simd.binary]
+ {"add", "operator+ on $simd objects"},
+ {"sub", "operator- on $simd objects"},
+ {"mul", "operator* on $simd objects"},
+ };
+
+ auto It = Mapping.find(Name);
+ if (It != Mapping.end())
+ return It->second;
+ return {};
+}
+
+static StringRef TrySuggestX86(StringRef Name) {
+ if (!(Name.consume_front("_mm_") || Name.consume_front("_mm256_") ||
+ Name.consume_front("_mm512_")))
+ return {};
+
+ // [simd.alg]
+ if (Name.startswith("max_"))
+ return "$simd::max";
+ if (Name.startswith("min_"))
+ return "$simd::min";
+
+ // [simd.binary]
+ if (Name.startswith("add_"))
+ return "operator+ on $simd objects";
+ if (Name.startswith("sub_"))
+ return "operator- on $simd objects";
+ if (Name.startswith("mul_"))
+ return "operator* on $simd objects";
+
+ return {};
+}
+
+SIMDIntrinsicsCheck::SIMDIntrinsicsCheck(StringRef Name,
+ ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context), Suggest(Options.get("Suggest", 0) != 0) {}
+
+void SIMDIntrinsicsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "Suggest", 0);
+}
+
+void SIMDIntrinsicsCheck::registerMatchers(MatchFinder *Finder) {
+ if (!getLangOpts().CPlusPlus11)
+ return;
+ // libcxx implementation backports it to C++11 std::experimental::simd.
+ Std = getLangOpts().CPlusPlus2a ? "std" : "std::experimental";
+
+ Finder->addMatcher(callExpr(callee(functionDecl(allOf(
+ matchesName("^::(_mm_|_mm256_|_mm512_|vec_)"),
+ isVectorFunction()))),
+ unless(isExpansionInSystemHeader()))
+ .bind("call"),
+ this);
+}
+
+void SIMDIntrinsicsCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call");
+ assert(Call != nullptr);
+ const FunctionDecl *Callee = Call->getDirectCallee();
+ if (!Callee)
+ return;
+
+ StringRef Old = Callee->getName();
+ StringRef New;
+ llvm::Triple::ArchType Arch =
+ Result.Context->getTargetInfo().getTriple().getArch();
+
+ switch (Arch) {
+ default:
+ break;
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ New = TrySuggestPPC(Old);
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ New = TrySuggestX86(Old);
+ break;
+ }
+
+ if (!New.empty()) {
+ std::string Message;
+ // If Suggest is true, give a P0214 alternative, otherwise point it out it
+ // is non-portable.
+ if (Suggest) {
+ Message = (Twine("'") + Old + "' can be replaced by " + New).str();
+ Message = llvm::Regex("\\$std").sub(Std, Message);
+ Message = llvm::Regex("\\$simd").sub(Std.str() + "::simd", Message);
+ } else {
+ Message = (Twine("'") + Old + "' is a non-portable " +
+ llvm::Triple::getArchTypeName(Arch) + " intrinsic function")
+ .str();
+ }
+ diag(Call->getExprLoc(), Message);
+ }
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
Added: clang-tools-extra/trunk/clang-tidy/readability/SIMDIntrinsicsCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/SIMDIntrinsicsCheck.h?rev=325272&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/SIMDIntrinsicsCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/readability/SIMDIntrinsicsCheck.h Thu Feb 15 09:56:43 2018
@@ -0,0 +1,40 @@
+//===--- SIMDIntrinsicsCheck.h - clang-tidy----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_SIMD_INTRINSICS_CHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_SIMD_INTRINSICS_CHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Find SIMD intrinsics calls and suggest std::experimental::simd alternatives.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-simd-intrinsics.html
+class SIMDIntrinsicsCheck : public ClangTidyCheck {
+public:
+ SIMDIntrinsicsCheck(StringRef Name, ClangTidyContext *Context);
+
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+ private:
+ const bool Suggest;
+ StringRef Std;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_SIMD_INTRINSICS_CHECK_H
Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=325272&r1=325271&r2=325272&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Thu Feb 15 09:56:43 2018
@@ -88,6 +88,12 @@ Improvements to clang-tidy
Functions that have trailing returns are disallowed, except for those
using decltype specifiers and lambda with otherwise unutterable
return types.
+
+- New `readability-simd-intrinsics
+ <http://clang.llvm.org/extra/clang-tidy/checks/readability-simd-intrinsics.html>`_ check
+
+ Warns if SIMD intrinsics are used which can be replaced by
+ ``std::experimental::simd`` operations.
- New alias `hicpp-avoid-goto
<http://clang.llvm.org/extra/clang-tidy/checks/hicpp-avoid-goto.html>`_ to
Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=325272&r1=325271&r2=325272&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Thu Feb 15 09:56:43 2018
@@ -217,6 +217,7 @@ Clang-Tidy Checks
readability-redundant-smartptr-get
readability-redundant-string-cstr
readability-redundant-string-init
+ readability-simd-intrinsics
readability-simplify-boolean-expr
readability-static-accessed-through-instance
readability-static-definition-in-anonymous-namespace
Added: clang-tools-extra/trunk/docs/clang-tidy/checks/readability-simd-intrinsics.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/readability-simd-intrinsics.rst?rev=325272&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/readability-simd-intrinsics.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/readability-simd-intrinsics.rst Thu Feb 15 09:56:43 2018
@@ -0,0 +1,42 @@
+.. title:: clang-tidy - readability-simd-intrinsics
+
+readability-simd-intrinsics
+===========================
+
+Finds SIMD intrinsics calls and suggests ``std::experimental::simd`` (`P0214`_) alternatives.
+
+If the option ``Suggest`` is set to non-zero, for
+
+.. code-block:: c++
+
+ _mm_add_epi32(a, b); // x86
+ vec_add(a, b); // Power
+
+the check suggests an alternative:
+
+.. code-block::
+
+ operator+ on std::experimental::simd objects
+
+Otherwise, it just complains the intrinsics are non-portable (and there are `P0214`_ alternatives).
+
+Many architectures provide SIMD operations (e.g. x86 SSE/AVX, Power AltiVec/VSX,
+ARM NEON). It is common that SIMD code implementing the same algorithm, is
+written in multiple target-dispatching pieces to optimize for different
+architectures or micro-architectures.
+
+The C++ standard proposal `P0214`_ and its extensions cover many common SIMD
+operations. By migrating from target-dependent intrinsics to `P0214` operations,
+the SIMD code can be simplified and pieces for different targets can be unified.
+
+Refer to `P0214`_ for introduction and motivation for the data-parallel standard
+library.
+
+Options
+-------
+
+.. option:: Suggest
+
+ If this option is set to non-zero (default is `0`), the check will suggest P0214 alternatives, otherwise it only points out the intrinsic function is non-portable.
+
+.. _P0214: http://wg21.link/p0214
Added: clang-tools-extra/trunk/test/clang-tidy/readability-simd-intrinsics-ppc.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/readability-simd-intrinsics-ppc.cpp?rev=325272&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/readability-simd-intrinsics-ppc.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/readability-simd-intrinsics-ppc.cpp Thu Feb 15 09:56:43 2018
@@ -0,0 +1,13 @@
+// RUN: %check_clang_tidy %s readability-simd-intrinsics %t -- \
+// RUN: -config='{CheckOptions: [ \
+// RUN: {key: readability-simd-intrinsics.Suggest, value: 1} \
+// RUN: ]}' -- -target ppc64le -maltivec -std=c++11
+
+vector int vec_add(vector int, vector int);
+
+void PPC() {
+ vector int i0, i1;
+
+ vec_add(i0, i1);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'vec_add' can be replaced by operator+ on std::experimental::simd objects [readability-simd-intrinsics]
+}
Added: clang-tools-extra/trunk/test/clang-tidy/readability-simd-intrinsics-x86.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/readability-simd-intrinsics-x86.cpp?rev=325272&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/readability-simd-intrinsics-x86.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/readability-simd-intrinsics-x86.cpp Thu Feb 15 09:56:43 2018
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s readability-simd-intrinsics %t -- \
+// RUN: -config='{CheckOptions: [ \
+// RUN: {key: readability-simd-intrinsics.Suggest, value: 1} \
+// RUN: ]}' -- -target x86_64 -std=c++11
+
+typedef long long __m128i __attribute__((vector_size(16)));
+typedef double __m256 __attribute__((vector_size(32)));
+
+__m128i _mm_add_epi32(__m128i, __m128i);
+__m256 _mm256_load_pd(double const *);
+void _mm256_store_pd(double *, __m256);
+
+int _mm_add_fake(int, int);
+
+void X86() {
+ __m128i i0, i1;
+ __m256 d0;
+
+ _mm_add_epi32(i0, i1);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: '_mm_add_epi32' can be replaced by operator+ on std::experimental::simd objects [readability-simd-intrinsics]
+ d0 = _mm256_load_pd(0);
+ _mm256_store_pd(0, d0);
+
+ _mm_add_fake(0, 1);
+}
More information about the cfe-commits
mailing list