[𝘀𝗽𝗿] changes introduced through rebase
Created using spr 1.3.6 [skip ci]
This commit is contained in:
commit
95edd82041
@ -2517,7 +2517,7 @@ BinaryContext::calculateEmittedSize(BinaryFunction &BF, bool FixBranches) {
|
||||
// Clean-up the effect of the code emission.
|
||||
for (const MCSymbol &Symbol : Assembler.symbols()) {
|
||||
MCSymbol *MutableSymbol = const_cast<MCSymbol *>(&Symbol);
|
||||
MutableSymbol->setUndefined();
|
||||
MutableSymbol->setFragment(nullptr);
|
||||
MutableSymbol->setIsRegistered(false);
|
||||
}
|
||||
|
||||
|
@ -662,7 +662,7 @@ Error CleanMCState::runOnFunctions(BinaryContext &BC) {
|
||||
if (S->isDefined()) {
|
||||
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: Symbol \"" << S->getName()
|
||||
<< "\" is already defined\n");
|
||||
const_cast<MCSymbol *>(S)->setUndefined();
|
||||
const_cast<MCSymbol *>(S)->setFragment(nullptr);
|
||||
}
|
||||
if (S->isRegistered()) {
|
||||
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: Symbol \"" << S->getName()
|
||||
|
@ -424,6 +424,10 @@ ClangTidyASTConsumerFactory::createASTConsumer(
|
||||
FinderOptions.CheckProfiling.emplace(Profiling->Records);
|
||||
}
|
||||
|
||||
// Avoid processing system headers, unless the user explicitly requests it
|
||||
if (!Context.getOptions().SystemHeaders.value_or(false))
|
||||
FinderOptions.IgnoreSystemHeaders = true;
|
||||
|
||||
std::unique_ptr<ast_matchers::MatchFinder> Finder(
|
||||
new ast_matchers::MatchFinder(std::move(FinderOptions)));
|
||||
|
||||
|
@ -191,6 +191,9 @@ void PreferMemberInitializerCheck::check(
|
||||
if (!AssignmentToMember)
|
||||
continue;
|
||||
const FieldDecl *Field = AssignmentToMember->Field;
|
||||
// Skip if the field is inherited from a base class.
|
||||
if (Field->getParent() != Class)
|
||||
continue;
|
||||
const Expr *InitValue = AssignmentToMember->Init;
|
||||
updateAssignmentLevel(Field, InitValue, Ctor, AssignedFields);
|
||||
if (!canAdvanceAssignment(AssignedFields[Field]))
|
||||
|
@ -32,6 +32,7 @@ add_clang_library(clangTidyMiscModule STATIC
|
||||
NoRecursionCheck.cpp
|
||||
NonCopyableObjects.cpp
|
||||
NonPrivateMemberVariablesInClassesCheck.cpp
|
||||
OverrideWithDifferentVisibilityCheck.cpp
|
||||
RedundantExpressionCheck.cpp
|
||||
StaticAssertCheck.cpp
|
||||
ThrowByValueCatchByReferenceCheck.cpp
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "NoRecursionCheck.h"
|
||||
#include "NonCopyableObjects.h"
|
||||
#include "NonPrivateMemberVariablesInClassesCheck.h"
|
||||
#include "OverrideWithDifferentVisibilityCheck.h"
|
||||
#include "RedundantExpressionCheck.h"
|
||||
#include "StaticAssertCheck.h"
|
||||
#include "ThrowByValueCatchByReferenceCheck.h"
|
||||
@ -81,6 +82,8 @@ public:
|
||||
"misc-use-anonymous-namespace");
|
||||
CheckFactories.registerCheck<UseInternalLinkageCheck>(
|
||||
"misc-use-internal-linkage");
|
||||
CheckFactories.registerCheck<OverrideWithDifferentVisibilityCheck>(
|
||||
"misc-override-with-different-visibility");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,150 @@
|
||||
//===--- OverrideWithDifferentVisibilityCheck.cpp - clang-tidy ------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "OverrideWithDifferentVisibilityCheck.h"
|
||||
#include "../utils/Matchers.h"
|
||||
#include "../utils/OptionsUtils.h"
|
||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||
|
||||
using namespace clang::ast_matchers;
|
||||
using namespace clang;
|
||||
|
||||
namespace {
|
||||
|
||||
AST_MATCHER(NamedDecl, isOperatorDecl) {
|
||||
DeclarationName::NameKind const NK = Node.getDeclName().getNameKind();
|
||||
return NK != DeclarationName::Identifier &&
|
||||
NK != DeclarationName::CXXConstructorName &&
|
||||
NK != DeclarationName::CXXDestructorName;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace clang::tidy {
|
||||
|
||||
template <>
|
||||
struct OptionEnumMapping<
|
||||
misc::OverrideWithDifferentVisibilityCheck::ChangeKind> {
|
||||
static llvm::ArrayRef<std::pair<
|
||||
misc::OverrideWithDifferentVisibilityCheck::ChangeKind, StringRef>>
|
||||
getEnumMapping() {
|
||||
static constexpr std::pair<
|
||||
misc::OverrideWithDifferentVisibilityCheck::ChangeKind, StringRef>
|
||||
Mapping[] = {
|
||||
{misc::OverrideWithDifferentVisibilityCheck::ChangeKind::Any,
|
||||
"any"},
|
||||
{misc::OverrideWithDifferentVisibilityCheck::ChangeKind::Widening,
|
||||
"widening"},
|
||||
{misc::OverrideWithDifferentVisibilityCheck::ChangeKind::Narrowing,
|
||||
"narrowing"},
|
||||
};
|
||||
return {Mapping};
|
||||
}
|
||||
};
|
||||
|
||||
namespace misc {
|
||||
|
||||
OverrideWithDifferentVisibilityCheck::OverrideWithDifferentVisibilityCheck(
|
||||
StringRef Name, ClangTidyContext *Context)
|
||||
: ClangTidyCheck(Name, Context),
|
||||
DetectVisibilityChange(
|
||||
Options.get("DisallowedVisibilityChange", ChangeKind::Any)),
|
||||
CheckDestructors(Options.get("CheckDestructors", false)),
|
||||
CheckOperators(Options.get("CheckOperators", false)),
|
||||
IgnoredFunctions(utils::options::parseStringList(
|
||||
Options.get("IgnoredFunctions", ""))) {}
|
||||
|
||||
void OverrideWithDifferentVisibilityCheck::storeOptions(
|
||||
ClangTidyOptions::OptionMap &Opts) {
|
||||
Options.store(Opts, "DisallowedVisibilityChange", DetectVisibilityChange);
|
||||
Options.store(Opts, "CheckDestructors", CheckDestructors);
|
||||
Options.store(Opts, "CheckOperators", CheckOperators);
|
||||
Options.store(Opts, "IgnoredFunctions",
|
||||
utils::options::serializeStringList(IgnoredFunctions));
|
||||
}
|
||||
|
||||
void OverrideWithDifferentVisibilityCheck::registerMatchers(
|
||||
MatchFinder *Finder) {
|
||||
const auto IgnoredDecl =
|
||||
namedDecl(matchers::matchesAnyListedName(IgnoredFunctions));
|
||||
const auto FilterDestructors =
|
||||
CheckDestructors ? decl() : decl(unless(cxxDestructorDecl()));
|
||||
const auto FilterOperators =
|
||||
CheckOperators ? namedDecl() : namedDecl(unless(isOperatorDecl()));
|
||||
Finder->addMatcher(
|
||||
cxxMethodDecl(
|
||||
isVirtual(), FilterDestructors, FilterOperators,
|
||||
ofClass(
|
||||
cxxRecordDecl(unless(isExpansionInSystemHeader())).bind("class")),
|
||||
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")),
|
||||
unless(IgnoredDecl))
|
||||
.bind("base_func")))
|
||||
.bind("func"),
|
||||
this);
|
||||
}
|
||||
|
||||
void OverrideWithDifferentVisibilityCheck::check(
|
||||
const MatchFinder::MatchResult &Result) {
|
||||
const auto *const MatchedFunction =
|
||||
Result.Nodes.getNodeAs<FunctionDecl>("func");
|
||||
if (!MatchedFunction->isCanonicalDecl())
|
||||
return;
|
||||
|
||||
const auto *const ParentClass =
|
||||
Result.Nodes.getNodeAs<CXXRecordDecl>("class");
|
||||
const auto *const BaseClass = Result.Nodes.getNodeAs<CXXRecordDecl>("base");
|
||||
CXXBasePaths Paths;
|
||||
if (!ParentClass->isDerivedFrom(BaseClass, Paths))
|
||||
return;
|
||||
|
||||
const auto *const OverriddenFunction =
|
||||
Result.Nodes.getNodeAs<FunctionDecl>("base_func");
|
||||
AccessSpecifier const ActualAccess = MatchedFunction->getAccess();
|
||||
AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
|
||||
|
||||
const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
|
||||
for (const CXXBasePath &Path : Paths) {
|
||||
for (const CXXBasePathElement &Elem : Path) {
|
||||
if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
|
||||
OverriddenAccess = Elem.Base->getAccessSpecifier();
|
||||
InheritanceWithStrictVisibility = Elem.Base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ActualAccess != OverriddenAccess) {
|
||||
if (DetectVisibilityChange == ChangeKind::Widening &&
|
||||
ActualAccess > OverriddenAccess)
|
||||
return;
|
||||
if (DetectVisibilityChange == ChangeKind::Narrowing &&
|
||||
ActualAccess < OverriddenAccess)
|
||||
return;
|
||||
|
||||
if (InheritanceWithStrictVisibility) {
|
||||
diag(MatchedFunction->getLocation(),
|
||||
"visibility of function %0 is changed from %1 (through %1 "
|
||||
"inheritance of class %2) to %3")
|
||||
<< MatchedFunction << OverriddenAccess
|
||||
<< InheritanceWithStrictVisibility->getType() << ActualAccess;
|
||||
diag(InheritanceWithStrictVisibility->getBeginLoc(),
|
||||
"%0 is inherited as %1 here", DiagnosticIDs::Note)
|
||||
<< InheritanceWithStrictVisibility->getType() << OverriddenAccess;
|
||||
} else {
|
||||
diag(MatchedFunction->getLocation(),
|
||||
"visibility of function %0 is changed from %1 in class %2 to %3")
|
||||
<< MatchedFunction << OverriddenAccess << BaseClass << ActualAccess;
|
||||
}
|
||||
diag(OverriddenFunction->getLocation(), "function declared here as %0",
|
||||
DiagnosticIDs::Note)
|
||||
<< OverriddenFunction->getAccess();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace misc
|
||||
|
||||
} // namespace clang::tidy
|
@ -0,0 +1,43 @@
|
||||
//===--- OverrideWithDifferentVisibilityCheck.h - clang-tidy --*- C++ -*---===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_OVERRIDEWITHDIFFERENTVISIBILITYCHECK_H
|
||||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_OVERRIDEWITHDIFFERENTVISIBILITYCHECK_H
|
||||
|
||||
#include "../ClangTidyCheck.h"
|
||||
|
||||
namespace clang::tidy::misc {
|
||||
|
||||
/// Finds virtual function overrides with different visibility than the function
|
||||
/// in the base class.
|
||||
///
|
||||
/// For the user-facing documentation see:
|
||||
/// http://clang.llvm.org/extra/clang-tidy/checks/misc/override-with-different-visibility.html
|
||||
class OverrideWithDifferentVisibilityCheck : public ClangTidyCheck {
|
||||
public:
|
||||
enum class ChangeKind { Any, Widening, Narrowing };
|
||||
|
||||
OverrideWithDifferentVisibilityCheck(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;
|
||||
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
|
||||
return LangOpts.CPlusPlus;
|
||||
}
|
||||
|
||||
private:
|
||||
ChangeKind DetectVisibilityChange;
|
||||
bool CheckDestructors;
|
||||
bool CheckOperators;
|
||||
std::vector<llvm::StringRef> IgnoredFunctions;
|
||||
};
|
||||
|
||||
} // namespace clang::tidy::misc
|
||||
|
||||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_OVERRIDEWITHDIFFERENTVISIBILITYCHECK_H
|
@ -28,6 +28,7 @@ import glob
|
||||
import json
|
||||
import multiprocessing
|
||||
import os
|
||||
import queue
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
@ -42,13 +43,6 @@ try:
|
||||
except ImportError:
|
||||
yaml = None
|
||||
|
||||
is_py2 = sys.version[0] == "2"
|
||||
|
||||
if is_py2:
|
||||
import Queue as queue
|
||||
else:
|
||||
import queue as queue
|
||||
|
||||
|
||||
def run_tidy(task_queue, lock, timeout, failed_files):
|
||||
watchdog = None
|
||||
|
@ -104,6 +104,10 @@ Improvements to clang-query
|
||||
Improvements to clang-tidy
|
||||
--------------------------
|
||||
|
||||
- :program:`clang-tidy` no longer attemps to analyze code from system headers
|
||||
by default, greatly improving performance. This behavior is disabled if the
|
||||
`SystemHeaders` option is enabled.
|
||||
|
||||
- The :program:`run-clang-tidy.py` and :program:`clang-tidy-diff.py` scripts
|
||||
now run checks in parallel by default using all available hardware threads.
|
||||
Both scripts display the number of threads being used in their output.
|
||||
@ -130,6 +134,12 @@ New checks
|
||||
Checks for uses of MLIR's old/to be deprecated ``OpBuilder::create<T>`` form
|
||||
and suggests using ``T::create`` instead.
|
||||
|
||||
- New :doc:`misc-override-with-different-visibility
|
||||
<clang-tidy/checks/misc/override-with-different-visibility>` check.
|
||||
|
||||
Finds virtual function overrides with different visibility than the function
|
||||
in the base class.
|
||||
|
||||
New check aliases
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -163,6 +173,10 @@ Changes in existing checks
|
||||
an additional matcher that generalizes the copy-and-swap idiom pattern
|
||||
detection.
|
||||
|
||||
- Improved :doc:`cppcoreguidelines-prefer-member-initializer
|
||||
<clang-tidy/checks/cppcoreguidelines/prefer-member-initializer>` check to
|
||||
avoid false positives on inherited members in class templates.
|
||||
|
||||
- Improved :doc:`misc-header-include-cycle
|
||||
<clang-tidy/checks/misc/header-include-cycle>` check performance.
|
||||
|
||||
|
@ -271,6 +271,7 @@ Clang-Tidy Checks
|
||||
:doc:`misc-no-recursion <misc/no-recursion>`,
|
||||
:doc:`misc-non-copyable-objects <misc/non-copyable-objects>`,
|
||||
:doc:`misc-non-private-member-variables-in-classes <misc/non-private-member-variables-in-classes>`,
|
||||
:doc:`misc-override-with-different-visibility <misc/override-with-different-visibility>`,
|
||||
:doc:`misc-redundant-expression <misc/redundant-expression>`, "Yes"
|
||||
:doc:`misc-static-assert <misc/static-assert>`, "Yes"
|
||||
:doc:`misc-throw-by-value-catch-by-reference <misc/throw-by-value-catch-by-reference>`,
|
||||
|
@ -0,0 +1,87 @@
|
||||
.. title:: clang-tidy - misc-override-with-different-visibility
|
||||
|
||||
misc-override-with-different-visibility
|
||||
=======================================
|
||||
|
||||
Finds virtual function overrides with different visibility than the function
|
||||
in the base class. This includes for example if a virtual function declared as
|
||||
``private`` is overridden and declared as ``public`` in a subclass. The detected
|
||||
change is the modification of visibility resulting from keywords ``public``,
|
||||
``protected``, ``private`` at overridden virtual functions. The check applies to
|
||||
any normal virtual function and optionally to destructors or operators. Use of
|
||||
the ``using`` keyword is not considered as visibility change by this check.
|
||||
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
class A {
|
||||
public:
|
||||
virtual void f_pub();
|
||||
private:
|
||||
virtual void f_priv();
|
||||
};
|
||||
|
||||
class B: public A {
|
||||
public:
|
||||
void f_priv(); // warning: changed visibility from private to public
|
||||
private:
|
||||
void f_pub(); // warning: changed visibility from public to private
|
||||
};
|
||||
|
||||
class C: private A {
|
||||
// no warning: f_pub becomes private in this case but this is from the
|
||||
// private inheritance
|
||||
};
|
||||
|
||||
class D: private A {
|
||||
public:
|
||||
void f_pub(); // warning: changed visibility from private to public
|
||||
// 'f_pub' would have private access but is forced to be
|
||||
// public
|
||||
};
|
||||
|
||||
If the visibility is changed in this way, it can indicate bad design or
|
||||
programming error.
|
||||
|
||||
If a virtual function is private in a subclass but public in the base class, it
|
||||
can still be accessed from a pointer to the subclass if the pointer is converted
|
||||
to the base type. Probably private inheritance can be used instead.
|
||||
|
||||
A protected virtual function that is made public in a subclass may have valid
|
||||
use cases but similar (not exactly same) effect can be achieved with the
|
||||
``using`` keyword.
|
||||
|
||||
Options
|
||||
-------
|
||||
|
||||
.. option:: DisallowedVisibilityChange
|
||||
|
||||
Controls what kind of change to the visibility will be detected by the check.
|
||||
Possible values are `any`, `widening`, `narrowing`. For example the
|
||||
`widening` option will produce warning only if the visibility is changed
|
||||
from more restrictive (``private``) to less restrictive (``public``).
|
||||
Default value is `any`.
|
||||
|
||||
.. option:: CheckDestructors
|
||||
|
||||
If `true`, the check does apply to destructors too. Otherwise destructors
|
||||
are ignored by the check.
|
||||
Default value is `false`.
|
||||
|
||||
.. option:: CheckOperators
|
||||
|
||||
If `true`, the check does apply to overloaded C++ operators (as virtual
|
||||
member functions) too. This includes other special member functions (like
|
||||
conversions) too. This option is probably useful only in rare cases because
|
||||
operators and conversions are not often virtual functions.
|
||||
Default value is `false`.
|
||||
|
||||
.. option:: IgnoredFunctions
|
||||
|
||||
This option can be used to ignore the check at specific functions.
|
||||
To configure this option, a semicolon-separated list of function names
|
||||
should be provided. The list can contain regular expressions, in this way it
|
||||
is possible to select all functions of a specific class (like `MyClass::.*`)
|
||||
or a specific function of any class (like `my_function` or
|
||||
`::.*::my_function`). The function names are matched at the base class.
|
||||
Default value is empty string.
|
@ -111,6 +111,13 @@ Diagnostics which have a corresponding warning option, are named
|
||||
``-Wliteral-conversion`` will be reported with check name
|
||||
``clang-diagnostic-literal-conversion``.
|
||||
|
||||
Clang compiler errors (such as syntax errors, semantic errors, or other failures
|
||||
that prevent Clang from compiling the code) are reported with the check name
|
||||
``clang-diagnostic-error``. These represent fundamental compilation failures that
|
||||
must be fixed before :program:`clang-tidy` can perform its analysis. Unlike other
|
||||
diagnostics, ``clang-diagnostic-error`` cannot be disabled, as :program:`clang-tidy`
|
||||
requires valid code to function.
|
||||
|
||||
The ``-fix`` flag instructs :program:`clang-tidy` to fix found errors if
|
||||
supported by corresponding checks.
|
||||
|
||||
|
@ -650,3 +650,16 @@ struct InitFromBindingDecl {
|
||||
}
|
||||
};
|
||||
} // namespace GH82970
|
||||
|
||||
struct A {
|
||||
int m;
|
||||
};
|
||||
|
||||
struct B : A {
|
||||
B() { m = 0; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct C : A {
|
||||
C() { m = 0; }
|
||||
};
|
||||
|
@ -0,0 +1,14 @@
|
||||
#pragma clang system_header
|
||||
|
||||
namespace sys {
|
||||
|
||||
struct Base {
|
||||
virtual void publicF();
|
||||
};
|
||||
|
||||
struct Derived: public Base {
|
||||
private:
|
||||
void publicF() override;
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
// RUN: %check_clang_tidy %s misc-override-with-different-visibility %t -- \
|
||||
// RUN: -config="{CheckOptions: {misc-override-with-different-visibility.IgnoredFunctions: 'IgnoreAlways::.*;::a::IgnoreSelected::.*;IgnoreFunctions::f1;ignored_f'}}"
|
||||
|
||||
class IgnoreAlways {
|
||||
virtual void f();
|
||||
};
|
||||
|
||||
class IgnoreSelected {
|
||||
virtual void f();
|
||||
};
|
||||
|
||||
namespace a {
|
||||
class IgnoreAlways {
|
||||
virtual void f();
|
||||
};
|
||||
class IgnoreSelected {
|
||||
virtual void f();
|
||||
};
|
||||
}
|
||||
|
||||
namespace ignore_always {
|
||||
class Test1: public IgnoreAlways {
|
||||
public:
|
||||
void f();
|
||||
void ignored_f(int);
|
||||
};
|
||||
class Test2: public a::IgnoreAlways {
|
||||
public:
|
||||
void f();
|
||||
};
|
||||
}
|
||||
|
||||
namespace ignore_selected {
|
||||
class Test1: public IgnoreSelected {
|
||||
public:
|
||||
void f();
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'f'
|
||||
// CHECK-MESSAGES: :9:16: note: function declared here
|
||||
void ignored_f(int);
|
||||
};
|
||||
class Test2: public a::IgnoreSelected {
|
||||
public:
|
||||
void f();
|
||||
};
|
||||
}
|
||||
|
||||
class IgnoreFunctions {
|
||||
virtual void f1();
|
||||
virtual void f2();
|
||||
virtual void ignored_f();
|
||||
};
|
||||
|
||||
class IgnoreFunctionsTest: public IgnoreFunctions {
|
||||
public:
|
||||
void f1();
|
||||
void f2();
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'f2'
|
||||
// CHECK-MESSAGES: :[[@LINE-9]]:16: note: function declared here
|
||||
void ignored_f();
|
||||
};
|
@ -0,0 +1,75 @@
|
||||
// RUN: %check_clang_tidy -check-suffixes=DTORS,WIDENING,NARROWING %s misc-override-with-different-visibility %t -- \
|
||||
// RUN: -config="{CheckOptions: {misc-override-with-different-visibility.CheckDestructors: true}}"
|
||||
|
||||
// RUN: %check_clang_tidy -check-suffixes=OPS,WIDENING,NARROWING %s misc-override-with-different-visibility %t -- \
|
||||
// RUN: -config="{CheckOptions: {misc-override-with-different-visibility.CheckOperators: true}}"
|
||||
|
||||
// RUN: %check_clang_tidy -check-suffixes=WIDENING %s misc-override-with-different-visibility %t -- \
|
||||
// RUN: -config="{CheckOptions: {misc-override-with-different-visibility.DisallowedVisibilityChange: 'widening'}}"
|
||||
|
||||
// RUN: %check_clang_tidy -check-suffixes=NARROWING %s misc-override-with-different-visibility %t -- \
|
||||
// RUN: -config="{CheckOptions: {misc-override-with-different-visibility.DisallowedVisibilityChange: 'narrowing'}}"
|
||||
|
||||
namespace test_change {
|
||||
|
||||
class A {
|
||||
protected:
|
||||
virtual void f1();
|
||||
virtual void f2();
|
||||
};
|
||||
|
||||
class B: public A {
|
||||
public:
|
||||
void f1();
|
||||
// CHECK-MESSAGES-WIDENING: :[[@LINE-1]]:8: warning: visibility of function 'f1'
|
||||
// CHECK-MESSAGES-WIDENING: :[[@LINE-8]]:16: note: function declared here
|
||||
private:
|
||||
void f2();
|
||||
// CHECK-MESSAGES-NARROWING: :[[@LINE-1]]:8: warning: visibility of function 'f2'
|
||||
// CHECK-MESSAGES-NARROWING: :[[@LINE-11]]:16: note: function declared here
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace test_destructor {
|
||||
|
||||
class A {
|
||||
public:
|
||||
virtual ~A();
|
||||
};
|
||||
|
||||
class B: public A {
|
||||
protected:
|
||||
~B();
|
||||
// CHECK-MESSAGES-DTORS: :[[@LINE-1]]:3: warning: visibility of function '~B'
|
||||
// CHECK-MESSAGES-DTORS: :[[@LINE-7]]:11: note: function declared here
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace test_operator {
|
||||
|
||||
class A {
|
||||
virtual A& operator=(const A&);
|
||||
virtual A& operator++();
|
||||
virtual int operator()(int);
|
||||
virtual operator double() const;
|
||||
};
|
||||
|
||||
class B: public A {
|
||||
protected:
|
||||
A& operator=(const A&);
|
||||
// CHECK-MESSAGES-OPS: :[[@LINE-1]]:6: warning: visibility of function 'operator='
|
||||
// CHECK-MESSAGES-OPS: :[[@LINE-10]]:14: note: function declared here
|
||||
A& operator++();
|
||||
// CHECK-MESSAGES-OPS: :[[@LINE-1]]:6: warning: visibility of function 'operator++'
|
||||
// CHECK-MESSAGES-OPS: :[[@LINE-12]]:14: note: function declared here
|
||||
int operator()(int);
|
||||
// CHECK-MESSAGES-OPS: :[[@LINE-1]]:7: warning: visibility of function 'operator()'
|
||||
// CHECK-MESSAGES-OPS: :[[@LINE-14]]:15: note: function declared here
|
||||
operator double() const;
|
||||
// CHECK-MESSAGES-OPS: :[[@LINE-1]]:3: warning: visibility of function 'operator double'
|
||||
// CHECK-MESSAGES-OPS: :[[@LINE-16]]:11: note: function declared here
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,289 @@
|
||||
// RUN: %check_clang_tidy %s misc-override-with-different-visibility %t -- -config="{CheckOptions: {misc-override-with-different-visibility.CheckDestructors: true,misc-override-with-different-visibility.CheckOperators: true}}" -- -I %S/Inputs/override-with-different-visibility
|
||||
#include <test-system-header.h>
|
||||
class A {
|
||||
public:
|
||||
virtual void pub_foo1() {}
|
||||
virtual void pub_foo2() {}
|
||||
virtual void pub_foo3() {}
|
||||
protected:
|
||||
virtual void prot_foo1();
|
||||
virtual void prot_foo2();
|
||||
virtual void prot_foo3();
|
||||
private:
|
||||
virtual void priv_foo1() {}
|
||||
virtual void priv_foo2() {}
|
||||
virtual void priv_foo3() {}
|
||||
};
|
||||
|
||||
void A::prot_foo1() {}
|
||||
void A::prot_foo2() {}
|
||||
void A::prot_foo3() {}
|
||||
|
||||
namespace test1 {
|
||||
|
||||
class B: public A {
|
||||
public:
|
||||
void pub_foo1() override {}
|
||||
void prot_foo1() override {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'prot_foo1' is changed from protected in class 'A' to public [misc-override-with-different-visibility]
|
||||
// CHECK-MESSAGES: :9:16: note: function declared here as protected
|
||||
void priv_foo1() override {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'priv_foo1' is changed from private in class 'A' to public [misc-override-with-different-visibility]
|
||||
// CHECK-MESSAGES: :13:16: note: function declared here as private
|
||||
protected:
|
||||
void pub_foo2() override {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'pub_foo2' is changed from public in class 'A' to protected [misc-override-with-different-visibility]
|
||||
// CHECK-MESSAGES: :6:16: note: function declared here as public
|
||||
void prot_foo2() override {}
|
||||
void priv_foo2() override {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'priv_foo2' is changed from private in class 'A' to protected [misc-override-with-different-visibility]
|
||||
// CHECK-MESSAGES: :14:16: note: function declared here as private
|
||||
private:
|
||||
void pub_foo3() override {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'pub_foo3' is changed from public in class 'A' to private [misc-override-with-different-visibility]
|
||||
// CHECK-MESSAGES: :7:16: note: function declared here as public
|
||||
void prot_foo3() override {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'prot_foo3' is changed from protected in class 'A' to private [misc-override-with-different-visibility]
|
||||
// CHECK-MESSAGES: :11:16: note: function declared here as protected
|
||||
void priv_foo3() override {}
|
||||
};
|
||||
|
||||
class C: public B {
|
||||
public:
|
||||
void pub_foo1() override;
|
||||
protected:
|
||||
void prot_foo1() override;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'prot_foo1' is changed from public in class 'B' to protected [misc-override-with-different-visibility]
|
||||
// CHECK-MESSAGES: :27:8: note: function declared here as public
|
||||
private:
|
||||
void priv_foo1() override;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'priv_foo1' is changed from public in class 'B' to private [misc-override-with-different-visibility]
|
||||
// CHECK-MESSAGES: :30:8: note: function declared here as public
|
||||
};
|
||||
|
||||
void C::prot_foo1() {}
|
||||
void C::priv_foo1() {}
|
||||
|
||||
}
|
||||
|
||||
namespace test2 {
|
||||
|
||||
class B: public A {
|
||||
public:
|
||||
void pub_foo1() override;
|
||||
protected:
|
||||
void prot_foo1() override;
|
||||
private:
|
||||
void priv_foo1() override;
|
||||
};
|
||||
|
||||
class C: public B {
|
||||
public:
|
||||
void pub_foo1() override;
|
||||
void prot_foo1() override;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'prot_foo1' is changed from protected in class 'B' to public
|
||||
// CHECK-MESSAGES: :75:8: note: function declared here as protected
|
||||
void priv_foo1() override;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'priv_foo1' is changed from private in class 'B' to public
|
||||
// CHECK-MESSAGES: :77:8: note: function declared here as private
|
||||
|
||||
void pub_foo2() override;
|
||||
void prot_foo2() override;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'prot_foo2' is changed from protected in class 'A' to public
|
||||
// CHECK-MESSAGES: :10:16: note: function declared here as protected
|
||||
void priv_foo2() override;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'priv_foo2' is changed from private in class 'A' to public
|
||||
// CHECK-MESSAGES: :14:16: note: function declared here as private
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace test3 {
|
||||
|
||||
class B: private A {
|
||||
public:
|
||||
void pub_foo1() override;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'pub_foo1' is changed from private (through private inheritance of class 'A') to public
|
||||
// CHECK-MESSAGES: :103:10: note: 'A' is inherited as private here
|
||||
// CHECK-MESSAGES: :5:16: note: function declared here as public
|
||||
protected:
|
||||
void prot_foo1() override;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'prot_foo1' is changed from private (through private inheritance of class 'A') to protected
|
||||
// CHECK-MESSAGES: :103:10: note: 'A' is inherited as private here
|
||||
// CHECK-MESSAGES: :9:16: note: function declared here as protected
|
||||
private:
|
||||
void priv_foo1() override;
|
||||
|
||||
public:
|
||||
void prot_foo2() override;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'prot_foo2' is changed from private (through private inheritance of class 'A') to public
|
||||
// CHECK-MESSAGES: :103:10: note: 'A' is inherited as private here
|
||||
// CHECK-MESSAGES: :10:16: note: function declared here as protected
|
||||
void priv_foo2() override;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'priv_foo2' is changed from private in class 'A' to public
|
||||
// CHECK-MESSAGES: :14:16: note: function declared here as private
|
||||
|
||||
private:
|
||||
void pub_foo3() override;
|
||||
void prot_foo3() override;
|
||||
};
|
||||
|
||||
class C: private A {
|
||||
};
|
||||
|
||||
class D: public C {
|
||||
public:
|
||||
void pub_foo1() override;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'pub_foo1' is changed from private (through private inheritance of class 'A') to public
|
||||
// CHECK-MESSAGES: :131:10: note: 'A' is inherited as private here
|
||||
// CHECK-MESSAGES: :5:16: note: function declared here as public
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
namespace test4 {
|
||||
|
||||
struct Base1 {
|
||||
public:
|
||||
virtual void foo1();
|
||||
private:
|
||||
virtual void foo2();
|
||||
};
|
||||
|
||||
struct Base2 {
|
||||
public:
|
||||
virtual void foo2();
|
||||
private:
|
||||
virtual void foo1();
|
||||
};
|
||||
|
||||
struct A : public Base1, public Base2 {
|
||||
protected:
|
||||
void foo1() override;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'foo1' is changed from private in class 'Base2' to protected
|
||||
// CHECK-MESSAGES: :158:16: note: function declared here as private
|
||||
// CHECK-MESSAGES: :[[@LINE-3]]:8: warning: visibility of function 'foo1' is changed from public in class 'Base1' to protected
|
||||
// CHECK-MESSAGES: :149:16: note: function declared here as public
|
||||
private:
|
||||
void foo2() override;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'foo2' is changed from public in class 'Base2' to private
|
||||
// CHECK-MESSAGES: :156:16: note: function declared here as public
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace test5 {
|
||||
|
||||
struct B1: virtual public A {};
|
||||
struct B2: virtual private A {};
|
||||
struct B: public B1, public B2 {
|
||||
public:
|
||||
void pub_foo1() override;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'pub_foo1' is changed from private (through private inheritance of class 'A') to public
|
||||
// CHECK-MESSAGES: :179:12: note: 'A' is inherited as private here
|
||||
// CHECK-MESSAGES: :5:16: note: function declared here as public
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace test_using {
|
||||
|
||||
class A {
|
||||
private:
|
||||
A(int);
|
||||
protected:
|
||||
virtual void f();
|
||||
};
|
||||
|
||||
class B: public A {
|
||||
public:
|
||||
using A::A;
|
||||
using A::f;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace test_template {
|
||||
|
||||
template <typename T>
|
||||
class A {
|
||||
protected:
|
||||
virtual T foo();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class B: public A<T> {
|
||||
private:
|
||||
T foo() override;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: visibility of function 'foo' is changed from protected in class 'A<int>' to private
|
||||
// CHECK-MESSAGES: :[[@LINE-8]]:13: note: function declared here as protected
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class C: private A<T> {
|
||||
public:
|
||||
T foo() override;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: visibility of function 'foo' is changed from private (through private inheritance of class 'A<int>') to public
|
||||
// CHECK-MESSAGES: :[[@LINE-4]]:10: note: 'A<int>' is inherited as private here
|
||||
// CHECK-MESSAGES: :[[@LINE-17]]:13: note: function declared here as protected
|
||||
};
|
||||
|
||||
B<int> fB() {
|
||||
return B<int>{};
|
||||
}
|
||||
|
||||
C<int> fC() {
|
||||
return C<int>{};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_system_header {
|
||||
|
||||
struct SysDerived: public sys::Base {
|
||||
private:
|
||||
void publicF();
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'publicF' is changed from public in class 'Base' to private
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace test_destructor {
|
||||
|
||||
class A {
|
||||
public:
|
||||
virtual ~A();
|
||||
};
|
||||
|
||||
class B: public A {
|
||||
protected:
|
||||
~B();
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: visibility of function '~B'
|
||||
// CHECK-MESSAGES: :[[@LINE-7]]:11: note: function declared here
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace test_operator {
|
||||
|
||||
class A {
|
||||
virtual int operator()(int);
|
||||
virtual A& operator++();
|
||||
virtual operator double() const;
|
||||
};
|
||||
|
||||
class B: public A {
|
||||
protected:
|
||||
int operator()(int);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: visibility of function 'operator()'
|
||||
// CHECK-MESSAGES: :[[@LINE-9]]:15: note: function declared here
|
||||
A& operator++();
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: visibility of function 'operator++'
|
||||
// CHECK-MESSAGES: :[[@LINE-11]]:14: note: function declared here
|
||||
operator double() const;
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: visibility of function 'operator double'
|
||||
// CHECK-MESSAGES: :[[@LINE-13]]:11: note: function declared here
|
||||
};
|
||||
|
||||
}
|
@ -66,19 +66,14 @@ class A { A(int); };
|
||||
// CHECK4-NOT: warning:
|
||||
// CHECK4-QUIET-NOT: warning:
|
||||
|
||||
// CHECK: Suppressed 3 warnings (3 in non-user code)
|
||||
// CHECK: Use -header-filter=.* to display errors from all non-system headers.
|
||||
// CHECK-QUIET-NOT: Suppressed
|
||||
// CHECK2: Suppressed 1 warnings (1 in non-user code)
|
||||
// CHECK2: Use -header-filter=.* {{.*}}
|
||||
// CHECK2-QUIET-NOT: Suppressed
|
||||
// CHECK3: Suppressed 2 warnings (2 in non-user code)
|
||||
// CHECK3: Use -header-filter=.* {{.*}}
|
||||
// CHECK3-QUIET-NOT: Suppressed
|
||||
// CHECK4-NOT: Suppressed {{.*}} warnings
|
||||
// CHECK4-NOT: Use -header-filter=.* {{.*}}
|
||||
// CHECK4-QUIET-NOT: Suppressed
|
||||
// CHECK6: Suppressed 2 warnings (2 in non-user code)
|
||||
// CHECK6: Use -header-filter=.* {{.*}}
|
||||
|
||||
int x = 123;
|
||||
|
@ -11,9 +11,9 @@
|
||||
// RUN: clang-tidy -help | FileCheck -check-prefix=CHECK-OPT-PRESENT %s
|
||||
|
||||
// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers=true %s -- -isystem %S/Inputs/system-headers 2>&1 | FileCheck -check-prefix=CHECK-SYSTEM-HEADERS %s
|
||||
// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers=false %s -- -isystem %S/Inputs/system-headers 2>&1 | FileCheck -check-prefix=CHECK-NO-SYSTEM-HEADERS %s
|
||||
// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers=false %s -- -isystem %S/Inputs/system-headers 2>&1 | FileCheck -check-prefix=CHECK-NO-SYSTEM-HEADERS --allow-empty %s
|
||||
// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -config='SystemHeaders: true' %s -- -isystem %S/Inputs/system-headers 2>&1 | FileCheck -check-prefix=CHECK-SYSTEM-HEADERS %s
|
||||
// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -config='SystemHeaders: false' %s -- -isystem %S/Inputs/system-headers 2>&1 | FileCheck -check-prefix=CHECK-NO-SYSTEM-HEADERS %s
|
||||
// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -config='SystemHeaders: false' %s -- -isystem %S/Inputs/system-headers 2>&1 | FileCheck -check-prefix=CHECK-NO-SYSTEM-HEADERS --allow-empty %s
|
||||
|
||||
#include <system_header.h>
|
||||
// CHECK-SYSTEM-HEADERS: system_header.h:1:13: warning: single-argument constructors must be marked explicit
|
||||
|
@ -126,6 +126,9 @@ clang-format is turned off or back on.
|
||||
// clang-format on
|
||||
void formatted_code_again;
|
||||
|
||||
In addition, the ``OneLineFormatOffRegex`` option gives you a concise way to
|
||||
disable formatting for all of the lines that match the regular expression.
|
||||
|
||||
|
||||
Configuring Style in Code
|
||||
=========================
|
||||
@ -6483,13 +6486,51 @@ the configuration (without a prefix: ``Auto``).
|
||||
.. _SpaceInEmptyBlock:
|
||||
|
||||
**SpaceInEmptyBlock** (``Boolean``) :versionbadge:`clang-format 10` :ref:`¶ <SpaceInEmptyBlock>`
|
||||
If ``true``, spaces will be inserted into ``{}``.
|
||||
This option is **deprecated**. See ``Block`` of ``SpaceInEmptyBraces``.
|
||||
|
||||
.. _SpaceInEmptyBraces:
|
||||
|
||||
**SpaceInEmptyBraces** (``SpaceInEmptyBracesStyle``) :versionbadge:`clang-format 22` :ref:`¶ <SpaceInEmptyBraces>`
|
||||
Specifies when to insert a space in empty braces.
|
||||
|
||||
.. note::
|
||||
|
||||
This option doesn't apply to initializer braces if
|
||||
``Cpp11BracedListStyle`` is set to ``true``.
|
||||
|
||||
Possible values:
|
||||
|
||||
* ``SIEB_Always`` (in configuration: ``Always``)
|
||||
Always insert a space in empty braces.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
void f() { }
|
||||
class Unit { };
|
||||
auto a = [] { };
|
||||
int x{ };
|
||||
|
||||
* ``SIEB_Block`` (in configuration: ``Block``)
|
||||
Only insert a space in empty blocks.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
void f() { }
|
||||
class Unit { };
|
||||
auto a = [] { };
|
||||
int x{};
|
||||
|
||||
* ``SIEB_Never`` (in configuration: ``Never``)
|
||||
Never insert a space in empty braces.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
void f() {}
|
||||
class Unit {};
|
||||
auto a = [] {};
|
||||
int x{};
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
true: false:
|
||||
void f() { } vs. void f() {}
|
||||
while (true) { } while (true) {}
|
||||
|
||||
.. _SpaceInEmptyParentheses:
|
||||
|
||||
|
@ -230,6 +230,7 @@ Bug Fixes to AST Handling
|
||||
- Fix incorrect name qualifiers applied to alias CTAD. (#GH136624)
|
||||
- Fixed ElaboratedTypes appearing within NestedNameSpecifier, which was not a
|
||||
legal representation. This is fixed because ElaboratedTypes don't exist anymore. (#GH43179) (#GH68670) (#GH92757)
|
||||
- Fix unrecognized html tag causing undesirable comment lexing (#GH152944)
|
||||
- Fix comment lexing of special command names (#GH152943)
|
||||
|
||||
Miscellaneous Bug Fixes
|
||||
@ -308,8 +309,12 @@ AST Matchers
|
||||
- Ensure ``hasBitWidth`` doesn't crash on bit widths that are dependent on template
|
||||
parameters.
|
||||
|
||||
- Add a boolean member ``IgnoreSystemHeaders`` to ``MatchFinderOptions``. This
|
||||
allows it to ignore nodes in system headers when traversing the AST.
|
||||
|
||||
clang-format
|
||||
------------
|
||||
- Add ``SpaceInEmptyBraces`` option and set it to ``Always`` for WebKit style.
|
||||
|
||||
libclang
|
||||
--------
|
||||
|
@ -66,17 +66,17 @@ supported. Uninstrumented code simply won't be accounted for in reports.
|
||||
|
||||
To compile code with Modified Condition/Decision Coverage (MC/DC) enabled,
|
||||
pass ``-fcoverage-mcdc`` in addition to the clang options specified above.
|
||||
MC/DC is an advanced form of code coverage most applicable in the embedded
|
||||
MC/DC is an advanced form of code coverage most applicable to the embedded
|
||||
space.
|
||||
|
||||
Running the instrumented program
|
||||
================================
|
||||
|
||||
The next step is to run the instrumented program. When the program exits it
|
||||
The next step is to run the instrumented program. When the program exits, it
|
||||
will write a **raw profile** to the path specified by the ``LLVM_PROFILE_FILE``
|
||||
environment variable. If that variable does not exist, the profile is written
|
||||
to ``default.profraw`` in the current directory of the program. If
|
||||
``LLVM_PROFILE_FILE`` contains a path to a non-existent directory, the missing
|
||||
``LLVM_PROFILE_FILE`` specifies a path to a non-existent directory, the missing
|
||||
directory structure will be created. Additionally, the following special
|
||||
**pattern strings** are rewritten:
|
||||
|
||||
@ -97,7 +97,7 @@ directory structure will be created. Additionally, the following special
|
||||
* "%b" expands out to the binary ID (build ID). It can be used with "%Nm" to
|
||||
avoid binary signature collisions. To use it, the program should be compiled
|
||||
with the build ID linker option (``--build-id`` for GNU ld or LLD,
|
||||
``/build-id`` for lld-link on Windows). Linux, Windows and AIX are supported.
|
||||
``/build-id`` for lld-link on Windows). Linux, Windows, and AIX are supported.
|
||||
|
||||
* "%c" expands out to nothing, but enables a mode in which profile counter
|
||||
updates are continuously synced to a file. This means that if the
|
||||
@ -128,7 +128,7 @@ and set bias to the offset between the original and the new counter location,
|
||||
at which point every subsequent counter access will be to the new location,
|
||||
which allows updating profile directly akin to the continuous mode.
|
||||
|
||||
The advantage of this approach is that doesn't require any special OS support.
|
||||
The advantage of this approach is that it doesn't require any special OS support.
|
||||
The disadvantage is the extra overhead due to additional instructions required
|
||||
for each counter access (overhead both in terms of binary size and performance)
|
||||
plus duplication of counters (i.e. one copy in the binary itself and another
|
||||
@ -137,7 +137,7 @@ other platforms by passing the ``-runtime-counter-relocation`` option to the
|
||||
backend during compilation.
|
||||
|
||||
For a program such as the `Lit <https://llvm.org/docs/CommandGuide/lit.html>`_
|
||||
testing tool which invokes other programs, it may be necessary to set
|
||||
testing tool, which invokes other programs, it may be necessary to set
|
||||
``LLVM_PROFILE_FILE`` for each invocation. The pattern strings "%p" or "%Nm"
|
||||
may help to avoid corruption due to concurrency. Note that "%p" is also a Lit
|
||||
token and needs to be escaped as "%%p".
|
||||
@ -149,7 +149,7 @@ token and needs to be escaped as "%%p".
|
||||
Creating coverage reports
|
||||
=========================
|
||||
|
||||
Raw profiles have to be **indexed** before they can be used to generate
|
||||
Raw profiles must be **indexed** before they can be used to generate
|
||||
coverage reports. This is done using the "merge" tool in ``llvm-profdata``
|
||||
(which can combine multiple raw profiles and index them at the same time):
|
||||
|
||||
@ -240,13 +240,13 @@ line-oriented report, try:
|
||||
TOTAL 13 0 100.00% 3 0 100.00% 13 0 100.00% 12 2 83.33%
|
||||
|
||||
The ``llvm-cov`` tool supports specifying a custom demangler, writing out
|
||||
reports in a directory structure, and generating html reports. For the full
|
||||
reports in a directory structure, and generating HTML reports. For the full
|
||||
list of options, please refer to the `command guide
|
||||
<https://llvm.org/docs/CommandGuide/llvm-cov.html>`_.
|
||||
|
||||
A few final notes:
|
||||
|
||||
* The ``-sparse`` flag is optional but can result in dramatically smaller
|
||||
* The ``-sparse`` flag is optional but can produce dramatically smaller
|
||||
indexed profiles. This option should not be used if the indexed profile will
|
||||
be reused for PGO.
|
||||
|
||||
@ -255,7 +255,7 @@ A few final notes:
|
||||
information directly into an existing raw profile on disk. The details are
|
||||
out of scope.
|
||||
|
||||
* The ``llvm-profdata`` tool can be used to merge together multiple raw or
|
||||
* The ``llvm-profdata`` tool can be used to merge multiple raw or
|
||||
indexed profiles. To combine profiling data from multiple runs of a program,
|
||||
try e.g:
|
||||
|
||||
@ -299,7 +299,7 @@ There are six statistics tracked in a coverage summary:
|
||||
source code that may each evaluate to either "true" or "false". These
|
||||
conditions may comprise larger boolean expressions linked by boolean logical
|
||||
operators. For example, "x = (y == 2) || (z < 10)" is a boolean expression
|
||||
that is comprised of two individual conditions, each of which evaluates to
|
||||
comprised of two individual conditions, each of which evaluates to
|
||||
either true or false, producing four total branch outcomes.
|
||||
|
||||
* Modified Condition/Decision Coverage (MC/DC) is the percentage of individual
|
||||
@ -316,7 +316,7 @@ There are six statistics tracked in a coverage summary:
|
||||
``-show-mcdc-summary`` option as long as code was also compiled using the
|
||||
clang option ``-fcoverage-mcdc``.
|
||||
|
||||
* Boolean expressions that are only comprised of one condition (and therefore
|
||||
* Boolean expressions comprised of only one condition (and therefore
|
||||
have no logical operators) are not included in MC/DC analysis and are
|
||||
trivially deducible using branch coverage.
|
||||
|
||||
@ -366,7 +366,7 @@ By default the compiler runtime uses a static initializer to determine the
|
||||
profile output path and to register a writer function. To collect profiles
|
||||
without using static initializers, do this manually:
|
||||
|
||||
* Export a ``int __llvm_profile_runtime`` symbol from each instrumented shared
|
||||
* Export an ``int __llvm_profile_runtime`` symbol from each instrumented shared
|
||||
library and executable. When the linker finds a definition of this symbol, it
|
||||
knows to skip loading the object which contains the profiling runtime's
|
||||
static initializer.
|
||||
@ -380,7 +380,7 @@ without using static initializers, do this manually:
|
||||
to ``__llvm_profile_write_file``.
|
||||
|
||||
* Forward-declare ``int __llvm_profile_write_file(void)`` and call it to write
|
||||
out a profile. This function returns 0 when it succeeds, and a non-zero value
|
||||
out a profile. This function returns 0 on success, and a non-zero value
|
||||
otherwise. Calling this function multiple times appends profile data to an
|
||||
existing on-disk raw profile.
|
||||
|
||||
@ -418,7 +418,7 @@ Collecting coverage reports for the llvm project
|
||||
================================================
|
||||
|
||||
To prepare a coverage report for llvm (and any of its sub-projects), add
|
||||
``-DLLVM_BUILD_INSTRUMENTED_COVERAGE=On`` to the cmake configuration. Raw
|
||||
``-DLLVM_BUILD_INSTRUMENTED_COVERAGE=On`` to the CMake configuration. Raw
|
||||
profiles will be written to ``$BUILD_DIR/profiles/``. To prepare an html
|
||||
report, run ``llvm/utils/prepare-code-coverage-artifact.py``.
|
||||
|
||||
@ -429,7 +429,7 @@ To specify an alternate directory for raw profiles, use
|
||||
Drawbacks and limitations
|
||||
=========================
|
||||
|
||||
* Prior to version 2.26, the GNU binutils BFD linker is not able link programs
|
||||
* Prior to version 2.26, the GNU binutils BFD linker cannot link programs
|
||||
compiled with ``-fcoverage-mapping`` in its ``--gc-sections`` mode. Possible
|
||||
workarounds include disabling ``--gc-sections``, upgrading to a newer version
|
||||
of BFD, or using the Gold linker.
|
||||
|
@ -51,6 +51,11 @@ def Col : Tag<"col"> { let EndTagForbidden = 1; }
|
||||
def Tr : Tag<"tr"> { let EndTagOptional = 1; }
|
||||
def Th : Tag<"th"> { let EndTagOptional = 1; }
|
||||
def Td : Tag<"td"> { let EndTagOptional = 1; }
|
||||
def Summary : Tag<"summary">;
|
||||
def Details : Tag<"details">;
|
||||
def Mark : Tag<"mark">;
|
||||
def Figure : Tag<"figure">;
|
||||
def FigCaption : Tag<"figcaption">;
|
||||
|
||||
// Define a list of attributes that are not safe to pass through to HTML
|
||||
// output if the input is untrusted.
|
||||
|
@ -135,10 +135,15 @@ public:
|
||||
llvm::StringMap<llvm::TimeRecord> &Records;
|
||||
};
|
||||
|
||||
MatchFinderOptions() {}
|
||||
|
||||
/// Enables per-check timers.
|
||||
///
|
||||
/// It prints a report after match.
|
||||
std::optional<Profiling> CheckProfiling;
|
||||
|
||||
/// Avoids matching declarations in system headers.
|
||||
bool IgnoreSystemHeaders{false};
|
||||
};
|
||||
|
||||
MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
|
||||
|
@ -19,14 +19,35 @@
|
||||
#define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
|
||||
#include "clang/Analysis/AnalysisDeclContext.h"
|
||||
#include "clang/Analysis/CFG.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/DenseMapInfo.h"
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
#include "llvm/ADT/ImmutableSet.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include <memory>
|
||||
|
||||
namespace clang::lifetimes {
|
||||
|
||||
/// Enum to track the confidence level of a potential error.
|
||||
enum class Confidence {
|
||||
None,
|
||||
Maybe, // Reported as a potential error (-Wlifetime-safety-strict)
|
||||
Definite // Reported as a definite error (-Wlifetime-safety-permissive)
|
||||
};
|
||||
|
||||
class LifetimeSafetyReporter {
|
||||
public:
|
||||
LifetimeSafetyReporter() = default;
|
||||
virtual ~LifetimeSafetyReporter() = default;
|
||||
|
||||
virtual void reportUseAfterFree(const Expr *IssueExpr, const Expr *UseExpr,
|
||||
SourceLocation FreeLoc,
|
||||
Confidence Confidence) {}
|
||||
};
|
||||
|
||||
/// The main entry point for the analysis.
|
||||
void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC);
|
||||
void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
|
||||
LifetimeSafetyReporter *Reporter);
|
||||
|
||||
namespace internal {
|
||||
// Forward declarations of internal types.
|
||||
@ -53,6 +74,7 @@ template <typename Tag> struct ID {
|
||||
IDBuilder.AddInteger(Value);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Tag>
|
||||
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID<Tag> ID) {
|
||||
return OS << ID.Value;
|
||||
@ -78,7 +100,8 @@ using ProgramPoint = const Fact *;
|
||||
/// encapsulates the various dataflow analyses.
|
||||
class LifetimeSafetyAnalysis {
|
||||
public:
|
||||
LifetimeSafetyAnalysis(AnalysisDeclContext &AC);
|
||||
LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
|
||||
LifetimeSafetyReporter *Reporter);
|
||||
~LifetimeSafetyAnalysis();
|
||||
|
||||
void run();
|
||||
@ -87,7 +110,7 @@ public:
|
||||
LoanSet getLoansAtPoint(OriginID OID, ProgramPoint PP) const;
|
||||
|
||||
/// Returns the set of loans that have expired at a specific program point.
|
||||
LoanSet getExpiredLoansAtPoint(ProgramPoint PP) const;
|
||||
std::vector<LoanID> getExpiredLoansAtPoint(ProgramPoint PP) const;
|
||||
|
||||
/// Finds the OriginID for a given declaration.
|
||||
/// Returns a null optional if not found.
|
||||
@ -110,6 +133,7 @@ public:
|
||||
|
||||
private:
|
||||
AnalysisDeclContext &AC;
|
||||
LifetimeSafetyReporter *Reporter;
|
||||
std::unique_ptr<LifetimeFactory> Factory;
|
||||
std::unique_ptr<FactManager> FactMgr;
|
||||
std::unique_ptr<LoanPropagationAnalysis> LoanPropagation;
|
||||
@ -118,4 +142,25 @@ private:
|
||||
} // namespace internal
|
||||
} // namespace clang::lifetimes
|
||||
|
||||
namespace llvm {
|
||||
template <typename Tag>
|
||||
struct DenseMapInfo<clang::lifetimes::internal::ID<Tag>> {
|
||||
using ID = clang::lifetimes::internal::ID<Tag>;
|
||||
|
||||
static inline ID getEmptyKey() {
|
||||
return {DenseMapInfo<uint32_t>::getEmptyKey()};
|
||||
}
|
||||
|
||||
static inline ID getTombstoneKey() {
|
||||
return {DenseMapInfo<uint32_t>::getTombstoneKey()};
|
||||
}
|
||||
|
||||
static unsigned getHashValue(const ID &Val) {
|
||||
return DenseMapInfo<uint32_t>::getHashValue(Val.Value);
|
||||
}
|
||||
|
||||
static bool isEqual(const ID &LHS, const ID &RHS) { return LHS == RHS; }
|
||||
};
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
|
||||
|
@ -268,7 +268,6 @@ let Header = "emmintrin.h", Attributes = [NoThrow, RequireDeclaration] in {
|
||||
}
|
||||
|
||||
let Features = "sse2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
|
||||
def pmuludq128 : X86Builtin<"_Vector<2, long long int>(_Vector<4, int>, _Vector<4, int>)">;
|
||||
def psraw128 : X86Builtin<"_Vector<8, short>(_Vector<8, short>, _Vector<8, short>)">;
|
||||
def psrad128 : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">;
|
||||
def psrlw128 : X86Builtin<"_Vector<8, short>(_Vector<8, short>, _Vector<8, short>)">;
|
||||
@ -290,6 +289,10 @@ let Features = "sse2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] i
|
||||
def psrldqi128_byteshift : X86Builtin<"_Vector<2, long long int>(_Vector<2, long long int>, _Constant int)">;
|
||||
}
|
||||
|
||||
let Features = "sse2", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
|
||||
def pmuludq128 : X86Builtin<"_Vector<2, long long int>(_Vector<4, int>, _Vector<4, int>)">;
|
||||
}
|
||||
|
||||
let Features = "sse3", Attributes = [NoThrow] in {
|
||||
def monitor : X86Builtin<"void(void const *, unsigned int, unsigned int)">;
|
||||
def mwait : X86Builtin<"void(unsigned int, unsigned int)">;
|
||||
@ -312,7 +315,6 @@ let Features = "sse4.1", Attributes = [NoThrow, Const, RequiredVectorWidth<128>]
|
||||
def blendvpd : X86Builtin<"_Vector<2, double>(_Vector<2, double>, _Vector<2, double>, _Vector<2, double>)">;
|
||||
def blendvps : X86Builtin<"_Vector<4, float>(_Vector<4, float>, _Vector<4, float>, _Vector<4, float>)">;
|
||||
def packusdw128 : X86Builtin<"_Vector<8, short>(_Vector<4, int>, _Vector<4, int>)">;
|
||||
def pmuldq128 : X86Builtin<"_Vector<2, long long int>(_Vector<4, int>, _Vector<4, int>)">;
|
||||
def roundps : X86Builtin<"_Vector<4, float>(_Vector<4, float>, _Constant int)">;
|
||||
def roundss : X86Builtin<"_Vector<4, float>(_Vector<4, float>, _Vector<4, float>, _Constant int)">;
|
||||
def roundsd : X86Builtin<"_Vector<2, double>(_Vector<2, double>, _Vector<2, double>, _Constant int)">;
|
||||
@ -329,6 +331,10 @@ let Features = "sse4.1", Attributes = [NoThrow, Const, RequiredVectorWidth<128>]
|
||||
def vec_set_v4si : X86Builtin<"_Vector<4, int>(_Vector<4, int>, int, _Constant int)">;
|
||||
}
|
||||
|
||||
let Features = "sse4.1", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
|
||||
def pmuldq128 : X86Builtin<"_Vector<2, long long int>(_Vector<4, int>, _Vector<4, int>)">;
|
||||
}
|
||||
|
||||
let Features = "sse4.2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
|
||||
def pcmpistrm128 : X86Builtin<"_Vector<16, char>(_Vector<16, char>, _Vector<16, char>, _Constant char)">;
|
||||
def pcmpistri128 : X86Builtin<"int(_Vector<16, char>, _Vector<16, char>, _Constant char)">;
|
||||
@ -580,9 +586,7 @@ let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] i
|
||||
def pmaddubsw256 : X86Builtin<"_Vector<16, short>(_Vector<32, char>, _Vector<32, char>)">;
|
||||
def pmaddwd256 : X86Builtin<"_Vector<8, int>(_Vector<16, short>, _Vector<16, short>)">;
|
||||
def pmovmskb256 : X86Builtin<"int(_Vector<32, char>)">;
|
||||
def pmuldq256 : X86Builtin<"_Vector<4, long long int>(_Vector<8, int>, _Vector<8, int>)">;
|
||||
def pmulhrsw256 : X86Builtin<"_Vector<16, short>(_Vector<16, short>, _Vector<16, short>)">;
|
||||
def pmuludq256 : X86Builtin<"_Vector<4, long long int>(_Vector<8, int>, _Vector<8, int>)">;
|
||||
def psadbw256 : X86Builtin<"_Vector<4, long long int>(_Vector<32, char>, _Vector<32, char>)">;
|
||||
def pshufb256 : X86Builtin<"_Vector<32, char>(_Vector<32, char>, _Vector<32, char>)">;
|
||||
def pshufd256 : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Constant int)">;
|
||||
@ -620,6 +624,11 @@ let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] i
|
||||
def insert128i256 : X86Builtin<"_Vector<4, long long int>(_Vector<4, long long int>, _Vector<2, long long int>, _Constant int)">;
|
||||
}
|
||||
|
||||
let Features = "avx2", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
|
||||
def pmuldq256 : X86Builtin<"_Vector<4, long long int>(_Vector<8, int>, _Vector<8, int>)">;
|
||||
def pmuludq256 : X86Builtin<"_Vector<4, long long int>(_Vector<8, int>, _Vector<8, int>)">;
|
||||
}
|
||||
|
||||
let Features = "avx2", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
|
||||
def pmulhuw256 : X86Builtin<"_Vector<16, unsigned short>(_Vector<16, unsigned short>, _Vector<16, unsigned short>)">;
|
||||
def pmulhw256 : X86Builtin<"_Vector<16, short>(_Vector<16, short>, _Vector<16, short>)">;
|
||||
@ -1078,6 +1087,9 @@ let Features = "avx512f,evex512", Attributes = [NoThrow, Const, RequiredVectorWi
|
||||
def cvtpd2ps512_mask : X86Builtin<"_Vector<8, float>(_Vector<8, double>, _Vector<8, float>, unsigned char, _Constant int)">;
|
||||
def vcvtps2ph512_mask : X86Builtin<"_Vector<16, short>(_Vector<16, float>, _Constant int, _Vector<16, short>, unsigned short)">;
|
||||
def vcvtph2ps512_mask : X86Builtin<"_Vector<16, float>(_Vector<16, short>, _Vector<16, float>, unsigned short, _Constant int)">;
|
||||
}
|
||||
|
||||
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
|
||||
def pmuldq512 : X86Builtin<"_Vector<8, long long int>(_Vector<16, int>, _Vector<16, int>)">;
|
||||
def pmuludq512 : X86Builtin<"_Vector<8, long long int>(_Vector<16, int>, _Vector<16, int>)">;
|
||||
}
|
||||
@ -4118,99 +4130,99 @@ let Features = "avx512fp16,evex512", Attributes = [NoThrow, Const, RequiredVecto
|
||||
def vfcmulcph512_mask : X86Builtin<"_Vector<16, float>(_Vector<16, float>, _Vector<16, float>, _Vector<16, float>, unsigned short, _Constant int)">;
|
||||
}
|
||||
|
||||
let Features = "avx512bw,avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
|
||||
let Features = "avx512bw,avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
|
||||
def selectb_128 : X86Builtin<"_Vector<16, char>(unsigned short, _Vector<16, char>, _Vector<16, char>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512bw,avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
|
||||
let Features = "avx512bw,avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
|
||||
def selectb_256 : X86Builtin<"_Vector<32, char>(unsigned int, _Vector<32, char>, _Vector<32, char>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512bw,evex512", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
|
||||
let Features = "avx512bw,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
|
||||
def selectb_512 : X86Builtin<"_Vector<64, char>(unsigned long long int, _Vector<64, char>, _Vector<64, char>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512bw,avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
|
||||
let Features = "avx512bw,avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
|
||||
def selectw_128 : X86Builtin<"_Vector<8, short>(unsigned char, _Vector<8, short>, _Vector<8, short>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512bw,avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
|
||||
let Features = "avx512bw,avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
|
||||
def selectw_256 : X86Builtin<"_Vector<16, short>(unsigned short, _Vector<16, short>, _Vector<16, short>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512bw,evex512", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
|
||||
let Features = "avx512bw,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
|
||||
def selectw_512 : X86Builtin<"_Vector<32, short>(unsigned int, _Vector<32, short>, _Vector<32, short>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
|
||||
let Features = "avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
|
||||
def selectd_128 : X86Builtin<"_Vector<4, int>(unsigned char, _Vector<4, int>, _Vector<4, int>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
|
||||
let Features = "avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
|
||||
def selectd_256 : X86Builtin<"_Vector<8, int>(unsigned char, _Vector<8, int>, _Vector<8, int>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
|
||||
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
|
||||
def selectd_512 : X86Builtin<"_Vector<16, int>(unsigned short, _Vector<16, int>, _Vector<16, int>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512fp16,avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
|
||||
let Features = "avx512fp16,avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
|
||||
def selectph_128 : X86Builtin<"_Vector<8, _Float16>(unsigned char, _Vector<8, _Float16>, _Vector<8, _Float16>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512fp16,avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
|
||||
let Features = "avx512fp16,avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
|
||||
def selectph_256 : X86Builtin<"_Vector<16, _Float16>(unsigned short, _Vector<16, _Float16>, _Vector<16, _Float16>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512fp16,evex512", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
|
||||
let Features = "avx512fp16,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
|
||||
def selectph_512 : X86Builtin<"_Vector<32, _Float16>(unsigned int, _Vector<32, _Float16>, _Vector<32, _Float16>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512bf16,avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
|
||||
let Features = "avx512bf16,avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
|
||||
def selectpbf_128 : X86Builtin<"_Vector<8, __bf16>(unsigned char, _Vector<8, __bf16>, _Vector<8, __bf16>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512bf16,avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
|
||||
let Features = "avx512bf16,avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
|
||||
def selectpbf_256 : X86Builtin<"_Vector<16, __bf16>(unsigned short, _Vector<16, __bf16>, _Vector<16, __bf16>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512bf16,evex512", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
|
||||
let Features = "avx512bf16,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
|
||||
def selectpbf_512 : X86Builtin<"_Vector<32, __bf16>(unsigned int, _Vector<32, __bf16>, _Vector<32, __bf16>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
|
||||
let Features = "avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
|
||||
def selectq_128 : X86Builtin<"_Vector<2, long long int>(unsigned char, _Vector<2, long long int>, _Vector<2, long long int>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
|
||||
let Features = "avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
|
||||
def selectq_256 : X86Builtin<"_Vector<4, long long int>(unsigned char, _Vector<4, long long int>, _Vector<4, long long int>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
|
||||
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
|
||||
def selectq_512 : X86Builtin<"_Vector<8, long long int>(unsigned char, _Vector<8, long long int>, _Vector<8, long long int>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
|
||||
let Features = "avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
|
||||
def selectps_128 : X86Builtin<"_Vector<4, float>(unsigned char, _Vector<4, float>, _Vector<4, float>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
|
||||
let Features = "avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
|
||||
def selectps_256 : X86Builtin<"_Vector<8, float>(unsigned char, _Vector<8, float>, _Vector<8, float>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
|
||||
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
|
||||
def selectps_512 : X86Builtin<"_Vector<16, float>(unsigned short, _Vector<16, float>, _Vector<16, float>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
|
||||
let Features = "avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
|
||||
def selectpd_128 : X86Builtin<"_Vector<2, double>(unsigned char, _Vector<2, double>, _Vector<2, double>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
|
||||
let Features = "avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
|
||||
def selectpd_256 : X86Builtin<"_Vector<4, double>(unsigned char, _Vector<4, double>, _Vector<4, double>)">;
|
||||
}
|
||||
|
||||
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
|
||||
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
|
||||
def selectpd_512 : X86Builtin<"_Vector<8, double>(unsigned char, _Vector<8, double>, _Vector<8, double>)">;
|
||||
}
|
||||
|
||||
|
@ -533,7 +533,14 @@ def Dangling : DiagGroup<"dangling", [DanglingAssignment,
|
||||
DanglingGsl,
|
||||
ReturnStackAddress]>;
|
||||
|
||||
def LifetimeSafety : DiagGroup<"experimental-lifetime-safety">;
|
||||
def LifetimeSafetyPermissive : DiagGroup<"experimental-lifetime-safety-permissive">;
|
||||
def LifetimeSafetyStrict : DiagGroup<"experimental-lifetime-safety-strict">;
|
||||
def LifetimeSafety : DiagGroup<"experimental-lifetime-safety",
|
||||
[LifetimeSafetyPermissive, LifetimeSafetyStrict]> {
|
||||
code Documentation = [{
|
||||
Experimental warnings to detect use-after-free and related temporal safety bugs based on lifetime safety analysis.
|
||||
}];
|
||||
}
|
||||
|
||||
def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
|
||||
def DllexportExplicitInstantiationDecl : DiagGroup<"dllexport-explicit-instantiation-decl">;
|
||||
|
@ -10671,9 +10671,15 @@ def warn_dangling_reference_captured_by_unknown : Warning<
|
||||
"object whose reference is captured will be destroyed at the end of "
|
||||
"the full-expression">, InGroup<DanglingCapture>;
|
||||
|
||||
def warn_experimental_lifetime_safety_dummy_warning : Warning<
|
||||
"todo: remove this warning after we have atleast one warning based on the lifetime analysis">,
|
||||
InGroup<LifetimeSafety>, DefaultIgnore;
|
||||
// Diagnostics based on the Lifetime safety analysis.
|
||||
def warn_lifetime_safety_loan_expires_permissive : Warning<
|
||||
"object whose reference is captured does not live long enough">,
|
||||
InGroup<LifetimeSafetyPermissive>, DefaultIgnore;
|
||||
def warn_lifetime_safety_loan_expires_strict : Warning<
|
||||
"object whose reference is captured may not live long enough">,
|
||||
InGroup<LifetimeSafetyStrict>, DefaultIgnore;
|
||||
def note_lifetime_safety_used_here : Note<"later used here">;
|
||||
def note_lifetime_safety_destroyed_here : Note<"destroyed here">;
|
||||
|
||||
// For non-floating point, expressions of the form x == x or x != x
|
||||
// should result in a warning, since these always evaluate to a constant.
|
||||
|
@ -233,8 +233,9 @@ protected:
|
||||
bool TLSSupported;
|
||||
bool VLASupported;
|
||||
bool NoAsmVariants; // True if {|} are normal characters.
|
||||
bool HasLegalHalfType; // True if the backend supports operations on the half
|
||||
// LLVM IR type.
|
||||
bool HasFastHalfType; // True if the backend has native half float support,
|
||||
// and performing calculations in float instead does
|
||||
// not have a performance advantage.
|
||||
bool HalfArgsAndReturns; // OpenCL 6.1.1.1, NEON (IEEE 754-2008 half) type.
|
||||
bool HasFloat128;
|
||||
bool HasFloat16;
|
||||
@ -700,8 +701,9 @@ public:
|
||||
return 128;
|
||||
}
|
||||
|
||||
/// Determine whether _Float16 is supported on this target.
|
||||
virtual bool hasLegalHalfType() const { return HasLegalHalfType; }
|
||||
/// Determine whether the target has fast native support for operations
|
||||
/// on half types.
|
||||
virtual bool hasFastHalfType() const { return HasFastHalfType; }
|
||||
|
||||
/// Whether half args and returns are supported.
|
||||
virtual bool allowHalfArgsAndReturns() const { return HalfArgsAndReturns; }
|
||||
|
@ -4813,14 +4813,45 @@ struct FormatStyle {
|
||||
/// \version 7
|
||||
bool SpaceBeforeRangeBasedForLoopColon;
|
||||
|
||||
/// If ``true``, spaces will be inserted into ``{}``.
|
||||
/// \code
|
||||
/// true: false:
|
||||
/// void f() { } vs. void f() {}
|
||||
/// while (true) { } while (true) {}
|
||||
/// \endcode
|
||||
/// This option is **deprecated**. See ``Block`` of ``SpaceInEmptyBraces``.
|
||||
/// \version 10
|
||||
bool SpaceInEmptyBlock;
|
||||
// bool SpaceInEmptyBlock;
|
||||
|
||||
/// Style of when to insert a space in empty braces.
|
||||
enum SpaceInEmptyBracesStyle : int8_t {
|
||||
/// Always insert a space in empty braces.
|
||||
/// \code
|
||||
/// void f() { }
|
||||
/// class Unit { };
|
||||
/// auto a = [] { };
|
||||
/// int x{ };
|
||||
/// \endcode
|
||||
SIEB_Always,
|
||||
/// Only insert a space in empty blocks.
|
||||
/// \code
|
||||
/// void f() { }
|
||||
/// class Unit { };
|
||||
/// auto a = [] { };
|
||||
/// int x{};
|
||||
/// \endcode
|
||||
SIEB_Block,
|
||||
/// Never insert a space in empty braces.
|
||||
/// \code
|
||||
/// void f() {}
|
||||
/// class Unit {};
|
||||
/// auto a = [] {};
|
||||
/// int x{};
|
||||
/// \endcode
|
||||
SIEB_Never
|
||||
};
|
||||
|
||||
/// Specifies when to insert a space in empty braces.
|
||||
/// \note
|
||||
/// This option doesn't apply to initializer braces if
|
||||
/// ``Cpp11BracedListStyle`` is set to ``true``.
|
||||
/// \endnote
|
||||
/// \version 22
|
||||
SpaceInEmptyBracesStyle SpaceInEmptyBraces;
|
||||
|
||||
/// If ``true``, spaces may be inserted into ``()``.
|
||||
/// This option is **deprecated**. See ``InEmptyParentheses`` of
|
||||
@ -5494,7 +5525,7 @@ struct FormatStyle {
|
||||
SpaceBeforeRangeBasedForLoopColon ==
|
||||
R.SpaceBeforeRangeBasedForLoopColon &&
|
||||
SpaceBeforeSquareBrackets == R.SpaceBeforeSquareBrackets &&
|
||||
SpaceInEmptyBlock == R.SpaceInEmptyBlock &&
|
||||
SpaceInEmptyBraces == R.SpaceInEmptyBraces &&
|
||||
SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments &&
|
||||
SpacesInAngles == R.SpacesInAngles &&
|
||||
SpacesInContainerLiterals == R.SpacesInContainerLiterals &&
|
||||
|
@ -143,9 +143,6 @@ class Lexer : public PreprocessorLexer {
|
||||
/// True if this is the first time we're lexing the input file.
|
||||
bool IsFirstTimeLexingFile;
|
||||
|
||||
/// True if current lexing token is the first pp-token.
|
||||
bool IsFirstPPToken;
|
||||
|
||||
// NewLinePtr - A pointer to new line character '\n' being lexed. For '\r\n',
|
||||
// it also points to '\n.'
|
||||
const char *NewLinePtr;
|
||||
|
310
clang/include/clang/Lex/NoTrivialPPDirectiveTracer.h
Normal file
310
clang/include/clang/Lex/NoTrivialPPDirectiveTracer.h
Normal file
@ -0,0 +1,310 @@
|
||||
//===--- NoTrivialPPDirectiveTracer.h ---------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the NoTrivialPPDirectiveTracer interface.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H
|
||||
#define LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H
|
||||
|
||||
#include "clang/Lex/PPCallbacks.h"
|
||||
|
||||
namespace clang {
|
||||
class Preprocessor;
|
||||
|
||||
/// Consider the following code:
|
||||
///
|
||||
/// # 1 __FILE__ 1 3
|
||||
/// export module a;
|
||||
///
|
||||
/// According to the wording in
|
||||
/// [P1857R3](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1857r3.html):
|
||||
///
|
||||
/// A module directive may only appear as the first preprocessing tokens in a
|
||||
/// file (excluding the global module fragment.)
|
||||
///
|
||||
/// and the wording in
|
||||
/// [[cpp.pre]](https://eel.is/c++draft/cpp.pre#nt:module-file):
|
||||
/// module-file:
|
||||
/// pp-global-module-fragment[opt] pp-module group[opt]
|
||||
/// pp-private-module-fragment[opt]
|
||||
///
|
||||
/// `#` is the first pp-token in the translation unit, and it was rejected by
|
||||
/// clang, but they really should be exempted from this rule. The goal is to not
|
||||
/// allow any preprocessor conditionals or most state changes, but these don't
|
||||
/// fit that.
|
||||
///
|
||||
/// State change would mean most semantically observable preprocessor state,
|
||||
/// particularly anything that is order dependent. Global flags like being a
|
||||
/// system header/module shouldn't matter.
|
||||
///
|
||||
/// We should exempt a brunch of directives, even though it violates the current
|
||||
/// standard wording.
|
||||
///
|
||||
/// This class used to trace 'no-trivial' pp-directives in main file, which may
|
||||
/// change the preprocessing state.
|
||||
///
|
||||
/// FIXME: Once the wording of the standard is revised, we need to follow the
|
||||
/// wording of the standard. Currently this is just a workaround
|
||||
class NoTrivialPPDirectiveTracer : public PPCallbacks {
|
||||
Preprocessor &PP;
|
||||
|
||||
/// Whether preprocessing main file. We only focus on the main file.
|
||||
bool InMainFile = true;
|
||||
|
||||
/// Whether one or more conditional, include or other 'no-trivial'
|
||||
/// pp-directives has seen before.
|
||||
bool SeenNoTrivialPPDirective = false;
|
||||
|
||||
void setSeenNoTrivialPPDirective();
|
||||
|
||||
public:
|
||||
NoTrivialPPDirectiveTracer(Preprocessor &P) : PP(P) {}
|
||||
|
||||
bool hasSeenNoTrivialPPDirective() const;
|
||||
|
||||
/// Callback invoked whenever the \p Lexer moves to a different file for
|
||||
/// lexing. Unlike \p FileChanged line number directives and other related
|
||||
/// pragmas do not trigger callbacks to \p LexedFileChanged.
|
||||
///
|
||||
/// \param FID The \p FileID that the \p Lexer moved to.
|
||||
///
|
||||
/// \param Reason Whether the \p Lexer entered a new file or exited one.
|
||||
///
|
||||
/// \param FileType The \p CharacteristicKind of the file the \p Lexer moved
|
||||
/// to.
|
||||
///
|
||||
/// \param PrevFID The \p FileID the \p Lexer was using before the change.
|
||||
///
|
||||
/// \param Loc The location where the \p Lexer entered a new file from or the
|
||||
/// location that the \p Lexer moved into after exiting a file.
|
||||
void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
|
||||
SrcMgr::CharacteristicKind FileType, FileID PrevFID,
|
||||
SourceLocation Loc) override;
|
||||
|
||||
/// Callback invoked whenever an embed directive has been processed,
|
||||
/// regardless of whether the embed will actually find a file.
|
||||
///
|
||||
/// \param HashLoc The location of the '#' that starts the embed directive.
|
||||
///
|
||||
/// \param FileName The name of the file being included, as written in the
|
||||
/// source code.
|
||||
///
|
||||
/// \param IsAngled Whether the file name was enclosed in angle brackets;
|
||||
/// otherwise, it was enclosed in quotes.
|
||||
///
|
||||
/// \param File The actual file that may be included by this embed directive.
|
||||
///
|
||||
/// \param Params The parameters used by the directive.
|
||||
void EmbedDirective(SourceLocation HashLoc, StringRef FileName, bool IsAngled,
|
||||
OptionalFileEntryRef File,
|
||||
const LexEmbedParametersResult &Params) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Callback invoked whenever an inclusion directive of
|
||||
/// any kind (\c \#include, \c \#import, etc.) has been processed, regardless
|
||||
/// of whether the inclusion will actually result in an inclusion.
|
||||
///
|
||||
/// \param HashLoc The location of the '#' that starts the inclusion
|
||||
/// directive.
|
||||
///
|
||||
/// \param IncludeTok The token that indicates the kind of inclusion
|
||||
/// directive, e.g., 'include' or 'import'.
|
||||
///
|
||||
/// \param FileName The name of the file being included, as written in the
|
||||
/// source code.
|
||||
///
|
||||
/// \param IsAngled Whether the file name was enclosed in angle brackets;
|
||||
/// otherwise, it was enclosed in quotes.
|
||||
///
|
||||
/// \param FilenameRange The character range of the quotes or angle brackets
|
||||
/// for the written file name.
|
||||
///
|
||||
/// \param File The actual file that may be included by this inclusion
|
||||
/// directive.
|
||||
///
|
||||
/// \param SearchPath Contains the search path which was used to find the file
|
||||
/// in the file system. If the file was found via an absolute include path,
|
||||
/// SearchPath will be empty. For framework includes, the SearchPath and
|
||||
/// RelativePath will be split up. For example, if an include of "Some/Some.h"
|
||||
/// is found via the framework path
|
||||
/// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be
|
||||
/// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be
|
||||
/// "Some.h".
|
||||
///
|
||||
/// \param RelativePath The path relative to SearchPath, at which the include
|
||||
/// file was found. This is equal to FileName except for framework includes.
|
||||
///
|
||||
/// \param SuggestedModule The module suggested for this header, if any.
|
||||
///
|
||||
/// \param ModuleImported Whether this include was translated into import of
|
||||
/// \p SuggestedModule.
|
||||
///
|
||||
/// \param FileType The characteristic kind, indicates whether a file or
|
||||
/// directory holds normal user code, system code, or system code which is
|
||||
/// implicitly 'extern "C"' in C++ mode.
|
||||
///
|
||||
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
|
||||
StringRef FileName, bool IsAngled,
|
||||
CharSourceRange FilenameRange,
|
||||
OptionalFileEntryRef File, StringRef SearchPath,
|
||||
StringRef RelativePath, const Module *SuggestedModule,
|
||||
bool ModuleImported,
|
||||
SrcMgr::CharacteristicKind FileType) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Callback invoked whenever there was an explicit module-import
|
||||
/// syntax.
|
||||
///
|
||||
/// \param ImportLoc The location of import directive token.
|
||||
///
|
||||
/// \param Path The identifiers (and their locations) of the module
|
||||
/// "path", e.g., "std.vector" would be split into "std" and "vector".
|
||||
///
|
||||
/// \param Imported The imported module; can be null if importing failed.
|
||||
///
|
||||
void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
|
||||
const Module *Imported) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Callback invoked when the end of the main file is reached.
|
||||
///
|
||||
/// No subsequent callbacks will be made.
|
||||
void EndOfMainFile() override { setSeenNoTrivialPPDirective(); }
|
||||
|
||||
/// Callback invoked when start reading any pragma directive.
|
||||
void PragmaDirective(SourceLocation Loc,
|
||||
PragmaIntroducerKind Introducer) override {}
|
||||
|
||||
/// Called by Preprocessor::HandleMacroExpandedIdentifier when a
|
||||
/// macro invocation is found.
|
||||
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
|
||||
SourceRange Range, const MacroArgs *Args) override;
|
||||
|
||||
/// Hook called whenever a macro definition is seen.
|
||||
void MacroDefined(const Token &MacroNameTok,
|
||||
const MacroDirective *MD) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever a macro \#undef is seen.
|
||||
/// \param MacroNameTok The active Token
|
||||
/// \param MD A MacroDefinition for the named macro.
|
||||
/// \param Undef New MacroDirective if the macro was defined, null otherwise.
|
||||
///
|
||||
/// MD is released immediately following this callback.
|
||||
void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD,
|
||||
const MacroDirective *Undef) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever the 'defined' operator is seen.
|
||||
/// \param MD The MacroDirective if the name was a macro, null otherwise.
|
||||
void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
|
||||
SourceRange Range) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever an \#if is seen.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param ConditionRange The SourceRange of the expression being tested.
|
||||
/// \param ConditionValue The evaluated value of the condition.
|
||||
///
|
||||
// FIXME: better to pass in a list (or tree!) of Tokens.
|
||||
void If(SourceLocation Loc, SourceRange ConditionRange,
|
||||
ConditionValueKind ConditionValue) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever an \#elif is seen.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param ConditionRange The SourceRange of the expression being tested.
|
||||
/// \param ConditionValue The evaluated value of the condition.
|
||||
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
|
||||
// FIXME: better to pass in a list (or tree!) of Tokens.
|
||||
void Elif(SourceLocation Loc, SourceRange ConditionRange,
|
||||
ConditionValueKind ConditionValue, SourceLocation IfLoc) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever an \#ifdef is seen.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param MacroNameTok Information on the token being tested.
|
||||
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
|
||||
void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
|
||||
const MacroDefinition &MD) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever an \#elifdef branch is taken.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param MacroNameTok Information on the token being tested.
|
||||
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
|
||||
void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
|
||||
const MacroDefinition &MD) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
/// Hook called whenever an \#elifdef is skipped.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param ConditionRange The SourceRange of the expression being tested.
|
||||
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
|
||||
// FIXME: better to pass in a list (or tree!) of Tokens.
|
||||
void Elifdef(SourceLocation Loc, SourceRange ConditionRange,
|
||||
SourceLocation IfLoc) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever an \#ifndef is seen.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param MacroNameTok Information on the token being tested.
|
||||
/// \param MD The MacroDefiniton if the name was a macro, null otherwise.
|
||||
void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
|
||||
const MacroDefinition &MD) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever an \#elifndef branch is taken.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param MacroNameTok Information on the token being tested.
|
||||
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
|
||||
void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
|
||||
const MacroDefinition &MD) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
/// Hook called whenever an \#elifndef is skipped.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param ConditionRange The SourceRange of the expression being tested.
|
||||
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
|
||||
// FIXME: better to pass in a list (or tree!) of Tokens.
|
||||
void Elifndef(SourceLocation Loc, SourceRange ConditionRange,
|
||||
SourceLocation IfLoc) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever an \#else is seen.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
|
||||
void Else(SourceLocation Loc, SourceLocation IfLoc) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever an \#endif is seen.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
|
||||
void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H
|
@ -82,6 +82,7 @@ class PreprocessorLexer;
|
||||
class PreprocessorOptions;
|
||||
class ScratchBuffer;
|
||||
class TargetInfo;
|
||||
class NoTrivialPPDirectiveTracer;
|
||||
|
||||
namespace Builtin {
|
||||
class Context;
|
||||
@ -353,6 +354,11 @@ private:
|
||||
/// First pp-token source location in current translation unit.
|
||||
SourceLocation FirstPPTokenLoc;
|
||||
|
||||
/// A preprocessor directive tracer to trace whether the preprocessing
|
||||
/// state changed. These changes would mean most semantically observable
|
||||
/// preprocessor state, particularly anything that is order dependent.
|
||||
NoTrivialPPDirectiveTracer *DirTracer = nullptr;
|
||||
|
||||
/// A position within a C++20 import-seq.
|
||||
class StdCXXImportSeq {
|
||||
public:
|
||||
@ -609,6 +615,8 @@ private:
|
||||
return State == NamedModuleImplementation && !getName().contains(':');
|
||||
}
|
||||
|
||||
bool isNotAModuleDecl() const { return State == NotAModuleDecl; }
|
||||
|
||||
StringRef getName() const {
|
||||
assert(isNamedModule() && "Can't get name from a non named module");
|
||||
return Name;
|
||||
@ -3091,6 +3099,10 @@ public:
|
||||
bool setDeserializedSafeBufferOptOutMap(
|
||||
const SmallVectorImpl<SourceLocation> &SrcLocSeqs);
|
||||
|
||||
/// Whether we've seen pp-directives which may have changed the preprocessing
|
||||
/// state.
|
||||
bool hasSeenNoTrivialPPDirective() const;
|
||||
|
||||
private:
|
||||
/// Helper functions to forward lexing to the actual lexer. They all share the
|
||||
/// same signature.
|
||||
|
@ -86,12 +86,12 @@ public:
|
||||
// macro stringizing or charizing operator.
|
||||
CommaAfterElided = 0x200, // The comma following this token was elided (MS).
|
||||
IsEditorPlaceholder = 0x400, // This identifier is a placeholder.
|
||||
|
||||
IsReinjected = 0x800, // A phase 4 token that was produced before and
|
||||
// re-added, e.g. via EnterTokenStream. Annotation
|
||||
// tokens are *not* reinjected.
|
||||
FirstPPToken = 0x1000, // This token is the first pp token in the
|
||||
// translation unit.
|
||||
IsReinjected = 0x800, // A phase 4 token that was produced before and
|
||||
// re-added, e.g. via EnterTokenStream. Annotation
|
||||
// tokens are *not* reinjected.
|
||||
HasSeenNoTrivialPPDirective =
|
||||
0x1000, // Whether we've seen any 'no-trivial' pp-directives before
|
||||
// current position.
|
||||
};
|
||||
|
||||
tok::TokenKind getKind() const { return Kind; }
|
||||
@ -321,8 +321,9 @@ public:
|
||||
/// lexer uses identifier tokens to represent placeholders.
|
||||
bool isEditorPlaceholder() const { return getFlag(IsEditorPlaceholder); }
|
||||
|
||||
/// Returns true if this token is the first pp-token.
|
||||
bool isFirstPPToken() const { return getFlag(FirstPPToken); }
|
||||
bool hasSeenNoTrivialPPDirective() const {
|
||||
return getFlag(HasSeenNoTrivialPPDirective);
|
||||
}
|
||||
};
|
||||
|
||||
/// Information about the conditional stack (\#if directives)
|
||||
|
@ -9837,7 +9837,7 @@ public:
|
||||
SourceLocation ModuleLoc, ModuleDeclKind MDK,
|
||||
ModuleIdPath Path, ModuleIdPath Partition,
|
||||
ModuleImportState &ImportState,
|
||||
bool IntroducerIsFirstPPToken);
|
||||
bool SeenNoTrivialPPDirective);
|
||||
|
||||
/// The parser has processed a global-module-fragment declaration that begins
|
||||
/// the definition of the global module fragment of the current module unit.
|
||||
|
@ -60,16 +60,18 @@ template <class Emitter> class OptionScope final {
|
||||
public:
|
||||
/// Root constructor, compiling or discarding primitives.
|
||||
OptionScope(Compiler<Emitter> *Ctx, bool NewDiscardResult,
|
||||
bool NewInitializing)
|
||||
bool NewInitializing, bool NewToLValue)
|
||||
: Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
|
||||
OldInitializing(Ctx->Initializing) {
|
||||
OldInitializing(Ctx->Initializing), OldToLValue(NewToLValue) {
|
||||
Ctx->DiscardResult = NewDiscardResult;
|
||||
Ctx->Initializing = NewInitializing;
|
||||
Ctx->ToLValue = NewToLValue;
|
||||
}
|
||||
|
||||
~OptionScope() {
|
||||
Ctx->DiscardResult = OldDiscardResult;
|
||||
Ctx->Initializing = OldInitializing;
|
||||
Ctx->ToLValue = OldToLValue;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -78,6 +80,7 @@ private:
|
||||
/// Old discard flag to restore.
|
||||
bool OldDiscardResult;
|
||||
bool OldInitializing;
|
||||
bool OldToLValue;
|
||||
};
|
||||
|
||||
template <class Emitter>
|
||||
@ -222,6 +225,9 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
|
||||
|
||||
switch (CE->getCastKind()) {
|
||||
case CK_LValueToRValue: {
|
||||
if (ToLValue && CE->getType()->isPointerType())
|
||||
return this->delegate(SubExpr);
|
||||
|
||||
if (SubExpr->getType().isVolatileQualified())
|
||||
return this->emitInvalidCast(CastKind::Volatile, /*Fatal=*/true, CE);
|
||||
|
||||
@ -4140,13 +4146,13 @@ bool Compiler<Emitter>::VisitStmtExpr(const StmtExpr *E) {
|
||||
|
||||
template <class Emitter> bool Compiler<Emitter>::discard(const Expr *E) {
|
||||
OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true,
|
||||
/*NewInitializing=*/false);
|
||||
/*NewInitializing=*/false, /*ToLValue=*/false);
|
||||
return this->Visit(E);
|
||||
}
|
||||
|
||||
template <class Emitter> bool Compiler<Emitter>::delegate(const Expr *E) {
|
||||
// We're basically doing:
|
||||
// OptionScope<Emitter> Scope(this, DicardResult, Initializing);
|
||||
// OptionScope<Emitter> Scope(this, DicardResult, Initializing, ToLValue);
|
||||
// but that's unnecessary of course.
|
||||
return this->Visit(E);
|
||||
}
|
||||
@ -4174,7 +4180,7 @@ template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {
|
||||
// Otherwise,we have a primitive return value, produce the value directly
|
||||
// and push it on the stack.
|
||||
OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
|
||||
/*NewInitializing=*/false);
|
||||
/*NewInitializing=*/false, /*ToLValue=*/ToLValue);
|
||||
return this->Visit(E);
|
||||
}
|
||||
|
||||
@ -4183,7 +4189,13 @@ bool Compiler<Emitter>::visitInitializer(const Expr *E) {
|
||||
assert(!canClassify(E->getType()));
|
||||
|
||||
OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
|
||||
/*NewInitializing=*/true);
|
||||
/*NewInitializing=*/true, /*ToLValue=*/false);
|
||||
return this->Visit(E);
|
||||
}
|
||||
|
||||
template <class Emitter> bool Compiler<Emitter>::visitAsLValue(const Expr *E) {
|
||||
OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
|
||||
/*NewInitializing=*/false, /*ToLValue=*/true);
|
||||
return this->Visit(E);
|
||||
}
|
||||
|
||||
@ -4944,7 +4956,6 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
|
||||
template <class Emitter>
|
||||
bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
|
||||
unsigned BuiltinID) {
|
||||
|
||||
if (BuiltinID == Builtin::BI__builtin_constant_p) {
|
||||
// Void argument is always invalid and harder to handle later.
|
||||
if (E->getArg(0)->getType()->isVoidType()) {
|
||||
@ -4989,11 +5000,31 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Context::isUnevaluatedBuiltin(BuiltinID)) {
|
||||
// Put arguments on the stack.
|
||||
for (const auto *Arg : E->arguments()) {
|
||||
if (!this->visit(Arg))
|
||||
// Prepare function arguments including special cases.
|
||||
switch (BuiltinID) {
|
||||
case Builtin::BI__builtin_object_size:
|
||||
case Builtin::BI__builtin_dynamic_object_size: {
|
||||
assert(E->getNumArgs() == 2);
|
||||
const Expr *Arg0 = E->getArg(0);
|
||||
if (Arg0->isGLValue()) {
|
||||
if (!this->visit(Arg0))
|
||||
return false;
|
||||
|
||||
} else {
|
||||
if (!this->visitAsLValue(Arg0))
|
||||
return false;
|
||||
}
|
||||
if (!this->visit(E->getArg(1)))
|
||||
return false;
|
||||
|
||||
} break;
|
||||
default:
|
||||
if (!Context::isUnevaluatedBuiltin(BuiltinID)) {
|
||||
// Put arguments on the stack.
|
||||
for (const auto *Arg : E->arguments()) {
|
||||
if (!this->visit(Arg))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5146,7 +5177,8 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
|
||||
if (!this->emitCheckPseudoDtor(E))
|
||||
return false;
|
||||
const Expr *Base = PD->getBase();
|
||||
if (!Base->isGLValue())
|
||||
// E.g. `using T = int; 0.~T();`.
|
||||
if (OptPrimType BaseT = classify(Base); !BaseT || BaseT != PT_Ptr)
|
||||
return this->discard(Base);
|
||||
if (!this->visit(Base))
|
||||
return false;
|
||||
|
@ -282,6 +282,7 @@ protected:
|
||||
/// been created. visitInitializer() then relies on a pointer to this
|
||||
/// variable being on top of the stack.
|
||||
bool visitInitializer(const Expr *E);
|
||||
bool visitAsLValue(const Expr *E);
|
||||
/// Evaluates an expression for side effects and discards the result.
|
||||
bool discard(const Expr *E);
|
||||
/// Just pass evaluation on to \p E. This leaves all the parsing flags
|
||||
@ -426,6 +427,7 @@ protected:
|
||||
bool DiscardResult = false;
|
||||
|
||||
bool InStmtExpr = false;
|
||||
bool ToLValue = false;
|
||||
|
||||
/// Flag inidicating if we're initializing an already created
|
||||
/// variable. This is set in visitInitializer().
|
||||
|
@ -50,9 +50,9 @@ private:
|
||||
|
||||
public:
|
||||
/// Creates a new block.
|
||||
Block(unsigned EvalID, const std::optional<unsigned> &DeclID,
|
||||
const Descriptor *Desc, bool IsStatic = false, bool IsExtern = false,
|
||||
bool IsWeak = false, bool IsDummy = false)
|
||||
Block(unsigned EvalID, UnsignedOrNone DeclID, const Descriptor *Desc,
|
||||
bool IsStatic = false, bool IsExtern = false, bool IsWeak = false,
|
||||
bool IsDummy = false)
|
||||
: Desc(Desc), DeclID(DeclID), EvalID(EvalID), IsStatic(IsStatic) {
|
||||
assert(Desc);
|
||||
AccessFlags |= (ExternFlag * IsExtern);
|
||||
@ -62,8 +62,7 @@ public:
|
||||
|
||||
Block(unsigned EvalID, const Descriptor *Desc, bool IsStatic = false,
|
||||
bool IsExtern = false, bool IsWeak = false, bool IsDummy = false)
|
||||
: Desc(Desc), DeclID((unsigned)-1), EvalID(EvalID), IsStatic(IsStatic),
|
||||
IsDynamic(false) {
|
||||
: Desc(Desc), EvalID(EvalID), IsStatic(IsStatic), IsDynamic(false) {
|
||||
assert(Desc);
|
||||
AccessFlags |= (ExternFlag * IsExtern);
|
||||
AccessFlags |= (WeakFlag * IsWeak);
|
||||
@ -87,7 +86,7 @@ public:
|
||||
/// Returns the size of the block.
|
||||
unsigned getSize() const { return Desc->getAllocSize(); }
|
||||
/// Returns the declaration ID.
|
||||
std::optional<unsigned> getDeclID() const { return DeclID; }
|
||||
UnsignedOrNone getDeclID() const { return DeclID; }
|
||||
/// Returns whether the data of this block has been initialized via
|
||||
/// invoking the Ctor func.
|
||||
bool isInitialized() const { return IsInitialized; }
|
||||
@ -177,7 +176,7 @@ private:
|
||||
/// Start of the chain of pointers.
|
||||
Pointer *Pointers = nullptr;
|
||||
/// Unique identifier of the declaration.
|
||||
std::optional<unsigned> DeclID;
|
||||
UnsignedOrNone DeclID = std::nullopt;
|
||||
const unsigned EvalID = ~0u;
|
||||
/// Flag indicating if the block has static storage duration.
|
||||
bool IsStatic = false;
|
||||
|
@ -2170,29 +2170,32 @@ static bool interp__builtin_memchr(InterpState &S, CodePtr OpPC,
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned computeFullDescSize(const ASTContext &ASTCtx,
|
||||
const Descriptor *Desc) {
|
||||
|
||||
static std::optional<unsigned> computeFullDescSize(const ASTContext &ASTCtx,
|
||||
const Descriptor *Desc) {
|
||||
if (Desc->isPrimitive())
|
||||
return ASTCtx.getTypeSizeInChars(Desc->getType()).getQuantity();
|
||||
|
||||
if (Desc->isArray())
|
||||
return ASTCtx.getTypeSizeInChars(Desc->getElemQualType()).getQuantity() *
|
||||
Desc->getNumElems();
|
||||
if (Desc->isRecord()) {
|
||||
// Can't use Descriptor::getType() as that may return a pointer type. Look
|
||||
// at the decl directly.
|
||||
return ASTCtx
|
||||
.getTypeSizeInChars(
|
||||
ASTCtx.getCanonicalTagType(Desc->ElemRecord->getDecl()))
|
||||
.getQuantity();
|
||||
}
|
||||
|
||||
if (Desc->isRecord())
|
||||
return ASTCtx.getTypeSizeInChars(Desc->getType()).getQuantity();
|
||||
|
||||
llvm_unreachable("Unhandled descriptor type");
|
||||
return 0;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/// Compute the byte offset of \p Ptr in the full declaration.
|
||||
static unsigned computePointerOffset(const ASTContext &ASTCtx,
|
||||
const Pointer &Ptr) {
|
||||
unsigned Result = 0;
|
||||
|
||||
Pointer P = Ptr;
|
||||
while (P.isArrayElement() || P.isField()) {
|
||||
while (P.isField() || P.isArrayElement()) {
|
||||
P = P.expand();
|
||||
const Descriptor *D = P.getFieldDesc();
|
||||
|
||||
@ -2205,7 +2208,6 @@ static unsigned computePointerOffset(const ASTContext &ASTCtx,
|
||||
Result += ElemSize * P.getIndex();
|
||||
P = P.expand().getArray();
|
||||
} else if (P.isBaseClass()) {
|
||||
|
||||
const auto *RD = cast<CXXRecordDecl>(D->asDecl());
|
||||
bool IsVirtual = Ptr.isVirtualBaseClass();
|
||||
P = P.getBase();
|
||||
@ -2234,30 +2236,136 @@ static unsigned computePointerOffset(const ASTContext &ASTCtx,
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// Does Ptr point to the last subobject?
|
||||
static bool pointsToLastObject(const Pointer &Ptr) {
|
||||
Pointer P = Ptr;
|
||||
while (!P.isRoot()) {
|
||||
|
||||
if (P.isArrayElement()) {
|
||||
P = P.expand().getArray();
|
||||
continue;
|
||||
}
|
||||
if (P.isBaseClass()) {
|
||||
if (P.getRecord()->getNumFields() > 0)
|
||||
return false;
|
||||
P = P.getBase();
|
||||
continue;
|
||||
}
|
||||
|
||||
Pointer Base = P.getBase();
|
||||
if (const Record *R = Base.getRecord()) {
|
||||
assert(P.getField());
|
||||
if (P.getField()->getFieldIndex() != R->getNumFields() - 1)
|
||||
return false;
|
||||
}
|
||||
P = Base;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Does Ptr point to the last object AND to a flexible array member?
|
||||
static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const Pointer &Ptr) {
|
||||
auto isFlexibleArrayMember = [&](const Descriptor *FieldDesc) {
|
||||
using FAMKind = LangOptions::StrictFlexArraysLevelKind;
|
||||
FAMKind StrictFlexArraysLevel =
|
||||
Ctx.getLangOpts().getStrictFlexArraysLevel();
|
||||
|
||||
if (StrictFlexArraysLevel == FAMKind::Default)
|
||||
return true;
|
||||
|
||||
unsigned NumElems = FieldDesc->getNumElems();
|
||||
if (NumElems == 0 && StrictFlexArraysLevel != FAMKind::IncompleteOnly)
|
||||
return true;
|
||||
|
||||
if (NumElems == 1 && StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
const Descriptor *FieldDesc = Ptr.getFieldDesc();
|
||||
if (!FieldDesc->isArray())
|
||||
return false;
|
||||
|
||||
return Ptr.isDummy() && pointsToLastObject(Ptr) &&
|
||||
isFlexibleArrayMember(FieldDesc);
|
||||
}
|
||||
|
||||
static bool interp__builtin_object_size(InterpState &S, CodePtr OpPC,
|
||||
const InterpFrame *Frame,
|
||||
const CallExpr *Call) {
|
||||
const ASTContext &ASTCtx = S.getASTContext();
|
||||
PrimType KindT = *S.getContext().classify(Call->getArg(1));
|
||||
[[maybe_unused]] unsigned Kind = popToAPSInt(S.Stk, KindT).getZExtValue();
|
||||
|
||||
// From the GCC docs:
|
||||
// Kind is an integer constant from 0 to 3. If the least significant bit is
|
||||
// clear, objects are whole variables. If it is set, a closest surrounding
|
||||
// subobject is considered the object a pointer points to. The second bit
|
||||
// determines if maximum or minimum of remaining bytes is computed.
|
||||
unsigned Kind = popToAPSInt(S.Stk, KindT).getZExtValue();
|
||||
assert(Kind <= 3 && "unexpected kind");
|
||||
|
||||
bool UseFieldDesc = (Kind & 1u);
|
||||
bool ReportMinimum = (Kind & 2u);
|
||||
const Pointer &Ptr = S.Stk.pop<Pointer>();
|
||||
|
||||
if (Ptr.isZero())
|
||||
if (Call->getArg(0)->HasSideEffects(ASTCtx)) {
|
||||
// "If there are any side effects in them, it returns (size_t) -1
|
||||
// for type 0 or 1 and (size_t) 0 for type 2 or 3."
|
||||
pushInteger(S, Kind <= 1 ? -1 : 0, Call->getType());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Ptr.isZero() || !Ptr.isBlockPointer())
|
||||
return false;
|
||||
|
||||
// We can't load through pointers.
|
||||
if (Ptr.isDummy() && Ptr.getType()->isPointerType())
|
||||
return false;
|
||||
|
||||
bool DetermineForCompleteObject = Ptr.getFieldDesc() == Ptr.getDeclDesc();
|
||||
const Descriptor *DeclDesc = Ptr.getDeclDesc();
|
||||
if (!DeclDesc)
|
||||
assert(DeclDesc);
|
||||
|
||||
if (!UseFieldDesc || DetermineForCompleteObject) {
|
||||
// Lower bound, so we can't fall back to this.
|
||||
if (ReportMinimum && !DetermineForCompleteObject)
|
||||
return false;
|
||||
|
||||
// Can't read beyond the pointer decl desc.
|
||||
if (!UseFieldDesc && !ReportMinimum && DeclDesc->getType()->isPointerType())
|
||||
return false;
|
||||
} else {
|
||||
if (isUserWritingOffTheEnd(ASTCtx, Ptr.expand())) {
|
||||
// If we cannot determine the size of the initial allocation, then we
|
||||
// can't given an accurate upper-bound. However, we are still able to give
|
||||
// conservative lower-bounds for Type=3.
|
||||
if (Kind == 1)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const Descriptor *Desc = UseFieldDesc ? Ptr.getFieldDesc() : DeclDesc;
|
||||
assert(Desc);
|
||||
|
||||
std::optional<unsigned> FullSize = computeFullDescSize(ASTCtx, Desc);
|
||||
if (!FullSize)
|
||||
return false;
|
||||
|
||||
const ASTContext &ASTCtx = S.getASTContext();
|
||||
unsigned ByteOffset;
|
||||
if (UseFieldDesc) {
|
||||
if (Ptr.isBaseClass())
|
||||
ByteOffset = computePointerOffset(ASTCtx, Ptr.getBase()) -
|
||||
computePointerOffset(ASTCtx, Ptr);
|
||||
else
|
||||
ByteOffset =
|
||||
computePointerOffset(ASTCtx, Ptr) -
|
||||
computePointerOffset(ASTCtx, Ptr.expand().atIndex(0).narrow());
|
||||
} else
|
||||
ByteOffset = computePointerOffset(ASTCtx, Ptr);
|
||||
|
||||
unsigned ByteOffset = computePointerOffset(ASTCtx, Ptr);
|
||||
unsigned FullSize = computeFullDescSize(ASTCtx, DeclDesc);
|
||||
|
||||
pushInteger(S, FullSize - ByteOffset, Call->getType());
|
||||
assert(ByteOffset <= *FullSize);
|
||||
unsigned Result = *FullSize - ByteOffset;
|
||||
|
||||
pushInteger(S, Result, Call->getType());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -593,7 +593,7 @@ public:
|
||||
}
|
||||
|
||||
/// Returns the declaration ID.
|
||||
std::optional<unsigned> getDeclID() const {
|
||||
UnsignedOrNone getDeclID() const {
|
||||
if (isBlockPointer()) {
|
||||
assert(asBlockPointer().Pointee);
|
||||
return asBlockPointer().Pointee->getDeclID();
|
||||
|
@ -164,8 +164,8 @@ unsigned Program::getOrCreateDummy(const DeclTy &D) {
|
||||
const auto *VD = cast<ValueDecl>(cast<const Decl *>(D));
|
||||
IsWeak = VD->isWeak();
|
||||
QT = VD->getType();
|
||||
if (const auto *RT = QT->getAs<ReferenceType>())
|
||||
QT = RT->getPointeeType();
|
||||
if (QT->isPointerOrReferenceType())
|
||||
QT = QT->getPointeeType();
|
||||
}
|
||||
assert(!QT.isNull());
|
||||
|
||||
|
@ -152,7 +152,7 @@ public:
|
||||
};
|
||||
|
||||
/// Returns the current declaration ID.
|
||||
std::optional<unsigned> getCurrentDecl() const {
|
||||
UnsignedOrNone getCurrentDecl() const {
|
||||
if (CurrentDeclaration == NoDeclaration)
|
||||
return std::nullopt;
|
||||
return CurrentDeclaration;
|
||||
|
@ -2805,32 +2805,20 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
|
||||
|
||||
case CXXTemporaryObjectExprClass:
|
||||
case CXXConstructExprClass: {
|
||||
if (const CXXRecordDecl *Type = getType()->getAsCXXRecordDecl()) {
|
||||
const auto *WarnURAttr = Type->getAttr<WarnUnusedResultAttr>();
|
||||
if (Type->hasAttr<WarnUnusedAttr>() ||
|
||||
(WarnURAttr && WarnURAttr->IsCXX11NoDiscard())) {
|
||||
WarnE = this;
|
||||
Loc = getBeginLoc();
|
||||
R1 = getSourceRange();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const auto *CE = cast<CXXConstructExpr>(this);
|
||||
if (const CXXConstructorDecl *Ctor = CE->getConstructor()) {
|
||||
const auto *WarnURAttr = Ctor->getAttr<WarnUnusedResultAttr>();
|
||||
if (WarnURAttr && WarnURAttr->IsCXX11NoDiscard()) {
|
||||
WarnE = this;
|
||||
Loc = getBeginLoc();
|
||||
R1 = getSourceRange();
|
||||
const CXXRecordDecl *Type = getType()->getAsCXXRecordDecl();
|
||||
|
||||
if (unsigned NumArgs = CE->getNumArgs())
|
||||
R2 = SourceRange(CE->getArg(0)->getBeginLoc(),
|
||||
CE->getArg(NumArgs - 1)->getEndLoc());
|
||||
return true;
|
||||
}
|
||||
if ((Type && Type->hasAttr<WarnUnusedAttr>()) ||
|
||||
CE->hasUnusedResultAttr(Ctx)) {
|
||||
WarnE = this;
|
||||
Loc = getBeginLoc();
|
||||
R1 = getSourceRange();
|
||||
|
||||
if (unsigned NumArgs = CE->getNumArgs())
|
||||
R2 = SourceRange(CE->getArg(0)->getBeginLoc(),
|
||||
CE->getArg(NumArgs - 1)->getEndLoc());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -11711,6 +11711,43 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
|
||||
|
||||
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
|
||||
}
|
||||
case clang::X86::BI__builtin_ia32_pmuldq128:
|
||||
case clang::X86::BI__builtin_ia32_pmuldq256:
|
||||
case clang::X86::BI__builtin_ia32_pmuldq512:
|
||||
case clang::X86::BI__builtin_ia32_pmuludq128:
|
||||
case clang::X86::BI__builtin_ia32_pmuludq256:
|
||||
case clang::X86::BI__builtin_ia32_pmuludq512: {
|
||||
APValue SourceLHS, SourceRHS;
|
||||
if (!EvaluateAsRValue(Info, E->getArg(0), SourceLHS) ||
|
||||
!EvaluateAsRValue(Info, E->getArg(1), SourceRHS))
|
||||
return false;
|
||||
|
||||
unsigned SourceLen = SourceLHS.getVectorLength();
|
||||
SmallVector<APValue, 4> ResultElements;
|
||||
ResultElements.reserve(SourceLen / 2);
|
||||
|
||||
for (unsigned EltNum = 0; EltNum < SourceLen; EltNum += 2) {
|
||||
APSInt LHS = SourceLHS.getVectorElt(EltNum).getInt();
|
||||
APSInt RHS = SourceRHS.getVectorElt(EltNum).getInt();
|
||||
|
||||
switch (E->getBuiltinCallee()) {
|
||||
case clang::X86::BI__builtin_ia32_pmuludq128:
|
||||
case clang::X86::BI__builtin_ia32_pmuludq256:
|
||||
case clang::X86::BI__builtin_ia32_pmuludq512:
|
||||
ResultElements.push_back(
|
||||
APValue(APSInt(llvm::APIntOps::muluExtended(LHS, RHS), true)));
|
||||
break;
|
||||
case clang::X86::BI__builtin_ia32_pmuldq128:
|
||||
case clang::X86::BI__builtin_ia32_pmuldq256:
|
||||
case clang::X86::BI__builtin_ia32_pmuldq512:
|
||||
ResultElements.push_back(
|
||||
APValue(APSInt(llvm::APIntOps::mulsExtended(LHS, RHS), false)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
|
||||
}
|
||||
case Builtin::BI__builtin_elementwise_max:
|
||||
case Builtin::BI__builtin_elementwise_min: {
|
||||
APValue SourceLHS, SourceRHS;
|
||||
@ -11746,6 +11783,50 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
|
||||
|
||||
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
|
||||
}
|
||||
case X86::BI__builtin_ia32_selectb_128:
|
||||
case X86::BI__builtin_ia32_selectb_256:
|
||||
case X86::BI__builtin_ia32_selectb_512:
|
||||
case X86::BI__builtin_ia32_selectw_128:
|
||||
case X86::BI__builtin_ia32_selectw_256:
|
||||
case X86::BI__builtin_ia32_selectw_512:
|
||||
case X86::BI__builtin_ia32_selectd_128:
|
||||
case X86::BI__builtin_ia32_selectd_256:
|
||||
case X86::BI__builtin_ia32_selectd_512:
|
||||
case X86::BI__builtin_ia32_selectq_128:
|
||||
case X86::BI__builtin_ia32_selectq_256:
|
||||
case X86::BI__builtin_ia32_selectq_512:
|
||||
case X86::BI__builtin_ia32_selectph_128:
|
||||
case X86::BI__builtin_ia32_selectph_256:
|
||||
case X86::BI__builtin_ia32_selectph_512:
|
||||
case X86::BI__builtin_ia32_selectpbf_128:
|
||||
case X86::BI__builtin_ia32_selectpbf_256:
|
||||
case X86::BI__builtin_ia32_selectpbf_512:
|
||||
case X86::BI__builtin_ia32_selectps_128:
|
||||
case X86::BI__builtin_ia32_selectps_256:
|
||||
case X86::BI__builtin_ia32_selectps_512:
|
||||
case X86::BI__builtin_ia32_selectpd_128:
|
||||
case X86::BI__builtin_ia32_selectpd_256:
|
||||
case X86::BI__builtin_ia32_selectpd_512: {
|
||||
// AVX512 predicated move: "Result = Mask[] ? LHS[] : RHS[]".
|
||||
APValue SourceMask, SourceLHS, SourceRHS;
|
||||
if (!EvaluateAsRValue(Info, E->getArg(0), SourceMask) ||
|
||||
!EvaluateAsRValue(Info, E->getArg(1), SourceLHS) ||
|
||||
!EvaluateAsRValue(Info, E->getArg(2), SourceRHS))
|
||||
return false;
|
||||
|
||||
APSInt Mask = SourceMask.getInt();
|
||||
unsigned SourceLen = SourceLHS.getVectorLength();
|
||||
SmallVector<APValue, 4> ResultElements;
|
||||
ResultElements.reserve(SourceLen);
|
||||
|
||||
for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
|
||||
const APValue &LHS = SourceLHS.getVectorElt(EltNum);
|
||||
const APValue &RHS = SourceRHS.getVectorElt(EltNum);
|
||||
ResultElements.push_back(Mask[EltNum] ? LHS : RHS);
|
||||
}
|
||||
|
||||
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -440,37 +440,37 @@ public:
|
||||
#define GEN_CLANG_CLAUSE_CLASS
|
||||
#define CLAUSE_CLASS(Enum, Str, Class) void Visit##Class(const Class *C);
|
||||
#include "llvm/Frontend/OpenMP/OMP.inc"
|
||||
void VistOMPClauseWithPreInit(const OMPClauseWithPreInit *C);
|
||||
void VistOMPClauseWithPostUpdate(const OMPClauseWithPostUpdate *C);
|
||||
void VisitOMPClauseWithPreInit(const OMPClauseWithPreInit *C);
|
||||
void VisitOMPClauseWithPostUpdate(const OMPClauseWithPostUpdate *C);
|
||||
};
|
||||
|
||||
void OMPClauseProfiler::VistOMPClauseWithPreInit(
|
||||
void OMPClauseProfiler::VisitOMPClauseWithPreInit(
|
||||
const OMPClauseWithPreInit *C) {
|
||||
if (auto *S = C->getPreInitStmt())
|
||||
Profiler->VisitStmt(S);
|
||||
}
|
||||
|
||||
void OMPClauseProfiler::VistOMPClauseWithPostUpdate(
|
||||
void OMPClauseProfiler::VisitOMPClauseWithPostUpdate(
|
||||
const OMPClauseWithPostUpdate *C) {
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
if (auto *E = C->getPostUpdateExpr())
|
||||
Profiler->VisitStmt(E);
|
||||
}
|
||||
|
||||
void OMPClauseProfiler::VisitOMPIfClause(const OMPIfClause *C) {
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
if (C->getCondition())
|
||||
Profiler->VisitStmt(C->getCondition());
|
||||
}
|
||||
|
||||
void OMPClauseProfiler::VisitOMPFinalClause(const OMPFinalClause *C) {
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
if (C->getCondition())
|
||||
Profiler->VisitStmt(C->getCondition());
|
||||
}
|
||||
|
||||
void OMPClauseProfiler::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) {
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
if (C->getNumThreads())
|
||||
Profiler->VisitStmt(C->getNumThreads());
|
||||
}
|
||||
@ -526,13 +526,13 @@ void OMPClauseProfiler::VisitOMPDetachClause(const OMPDetachClause *C) {
|
||||
}
|
||||
|
||||
void OMPClauseProfiler::VisitOMPNovariantsClause(const OMPNovariantsClause *C) {
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
if (C->getCondition())
|
||||
Profiler->VisitStmt(C->getCondition());
|
||||
}
|
||||
|
||||
void OMPClauseProfiler::VisitOMPNocontextClause(const OMPNocontextClause *C) {
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
if (C->getCondition())
|
||||
Profiler->VisitStmt(C->getCondition());
|
||||
}
|
||||
@ -568,7 +568,7 @@ void OMPClauseProfiler::VisitOMPMessageClause(const OMPMessageClause *C) {
|
||||
}
|
||||
|
||||
void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) {
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
if (auto *S = C->getChunkSize())
|
||||
Profiler->VisitStmt(S);
|
||||
}
|
||||
@ -646,7 +646,7 @@ void OMPClauseProfiler::VisitOMPDestroyClause(const OMPDestroyClause *C) {
|
||||
}
|
||||
|
||||
void OMPClauseProfiler::VisitOMPFilterClause(const OMPFilterClause *C) {
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
if (C->getThreadID())
|
||||
Profiler->VisitStmt(C->getThreadID());
|
||||
}
|
||||
@ -669,7 +669,7 @@ void OMPClauseProfiler::VisitOMPPrivateClause(const OMPPrivateClause *C) {
|
||||
void
|
||||
OMPClauseProfiler::VisitOMPFirstprivateClause(const OMPFirstprivateClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
for (auto *E : C->private_copies()) {
|
||||
if (E)
|
||||
Profiler->VisitStmt(E);
|
||||
@ -682,7 +682,7 @@ OMPClauseProfiler::VisitOMPFirstprivateClause(const OMPFirstprivateClause *C) {
|
||||
void
|
||||
OMPClauseProfiler::VisitOMPLastprivateClause(const OMPLastprivateClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
VistOMPClauseWithPostUpdate(C);
|
||||
VisitOMPClauseWithPostUpdate(C);
|
||||
for (auto *E : C->source_exprs()) {
|
||||
if (E)
|
||||
Profiler->VisitStmt(E);
|
||||
@ -705,7 +705,7 @@ void OMPClauseProfiler::VisitOMPReductionClause(
|
||||
C->getQualifierLoc().getNestedNameSpecifier());
|
||||
Profiler->VisitName(C->getNameInfo().getName());
|
||||
VisitOMPClauseList(C);
|
||||
VistOMPClauseWithPostUpdate(C);
|
||||
VisitOMPClauseWithPostUpdate(C);
|
||||
for (auto *E : C->privates()) {
|
||||
if (E)
|
||||
Profiler->VisitStmt(E);
|
||||
@ -743,7 +743,7 @@ void OMPClauseProfiler::VisitOMPTaskReductionClause(
|
||||
C->getQualifierLoc().getNestedNameSpecifier());
|
||||
Profiler->VisitName(C->getNameInfo().getName());
|
||||
VisitOMPClauseList(C);
|
||||
VistOMPClauseWithPostUpdate(C);
|
||||
VisitOMPClauseWithPostUpdate(C);
|
||||
for (auto *E : C->privates()) {
|
||||
if (E)
|
||||
Profiler->VisitStmt(E);
|
||||
@ -767,7 +767,7 @@ void OMPClauseProfiler::VisitOMPInReductionClause(
|
||||
C->getQualifierLoc().getNestedNameSpecifier());
|
||||
Profiler->VisitName(C->getNameInfo().getName());
|
||||
VisitOMPClauseList(C);
|
||||
VistOMPClauseWithPostUpdate(C);
|
||||
VisitOMPClauseWithPostUpdate(C);
|
||||
for (auto *E : C->privates()) {
|
||||
if (E)
|
||||
Profiler->VisitStmt(E);
|
||||
@ -791,7 +791,7 @@ void OMPClauseProfiler::VisitOMPInReductionClause(
|
||||
}
|
||||
void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
VistOMPClauseWithPostUpdate(C);
|
||||
VisitOMPClauseWithPostUpdate(C);
|
||||
for (auto *E : C->privates()) {
|
||||
if (E)
|
||||
Profiler->VisitStmt(E);
|
||||
@ -873,25 +873,25 @@ void OMPClauseProfiler::VisitOMPAllocateClause(const OMPAllocateClause *C) {
|
||||
}
|
||||
void OMPClauseProfiler::VisitOMPNumTeamsClause(const OMPNumTeamsClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
}
|
||||
void OMPClauseProfiler::VisitOMPThreadLimitClause(
|
||||
const OMPThreadLimitClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
}
|
||||
void OMPClauseProfiler::VisitOMPPriorityClause(const OMPPriorityClause *C) {
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
if (C->getPriority())
|
||||
Profiler->VisitStmt(C->getPriority());
|
||||
}
|
||||
void OMPClauseProfiler::VisitOMPGrainsizeClause(const OMPGrainsizeClause *C) {
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
if (C->getGrainsize())
|
||||
Profiler->VisitStmt(C->getGrainsize());
|
||||
}
|
||||
void OMPClauseProfiler::VisitOMPNumTasksClause(const OMPNumTasksClause *C) {
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
if (C->getNumTasks())
|
||||
Profiler->VisitStmt(C->getNumTasks());
|
||||
}
|
||||
@ -952,7 +952,7 @@ void OMPClauseProfiler::VisitOMPOrderClause(const OMPOrderClause *C) {}
|
||||
void OMPClauseProfiler::VisitOMPBindClause(const OMPBindClause *C) {}
|
||||
void OMPClauseProfiler::VisitOMPXDynCGroupMemClause(
|
||||
const OMPXDynCGroupMemClause *C) {
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
if (Expr *Size = C->getSize())
|
||||
Profiler->VisitStmt(Size);
|
||||
}
|
||||
@ -1229,7 +1229,7 @@ void StmtProfiler::VisitOMPDistributeDirective(
|
||||
|
||||
void OMPClauseProfiler::VisitOMPDistScheduleClause(
|
||||
const OMPDistScheduleClause *C) {
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
if (auto *S = C->getChunkSize())
|
||||
Profiler->VisitStmt(S);
|
||||
}
|
||||
|
@ -1627,7 +1627,7 @@ bool QualType::UseExcessPrecision(const ASTContext &Ctx) {
|
||||
switch (BT->getKind()) {
|
||||
case BuiltinType::Kind::Float16: {
|
||||
const TargetInfo &TI = Ctx.getTargetInfo();
|
||||
if (TI.hasFloat16Type() && !TI.hasLegalHalfType() &&
|
||||
if (TI.hasFloat16Type() && !TI.hasFastHalfType() &&
|
||||
Ctx.getLangOpts().getFloat16ExcessPrecision() !=
|
||||
Ctx.getLangOpts().ExcessPrecisionKind::FPP_None)
|
||||
return true;
|
||||
|
@ -1344,6 +1344,41 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T> static SourceLocation getNodeLocation(const T &Node) {
|
||||
return Node.getBeginLoc();
|
||||
}
|
||||
|
||||
static SourceLocation getNodeLocation(const CXXCtorInitializer &Node) {
|
||||
return Node.getSourceLocation();
|
||||
}
|
||||
|
||||
static SourceLocation getNodeLocation(const TemplateArgumentLoc &Node) {
|
||||
return Node.getLocation();
|
||||
}
|
||||
|
||||
static SourceLocation getNodeLocation(const Attr &Node) {
|
||||
return Node.getLocation();
|
||||
}
|
||||
|
||||
bool isInSystemHeader(SourceLocation Loc) {
|
||||
const SourceManager &SM = getASTContext().getSourceManager();
|
||||
return SM.isInSystemHeader(Loc);
|
||||
}
|
||||
|
||||
template <typename T> bool shouldSkipNode(T &Node) {
|
||||
if (Options.IgnoreSystemHeaders && isInSystemHeader(getNodeLocation(Node)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T> bool shouldSkipNode(T *Node) {
|
||||
return (Node == nullptr) || shouldSkipNode(*Node);
|
||||
}
|
||||
|
||||
bool shouldSkipNode(QualType &) { return false; }
|
||||
|
||||
bool shouldSkipNode(NestedNameSpecifier &) { return false; }
|
||||
|
||||
/// Bucket to record map.
|
||||
///
|
||||
/// Used to get the appropriate bucket for each matcher.
|
||||
@ -1473,9 +1508,8 @@ bool MatchASTVisitor::objcClassIsDerivedFrom(
|
||||
}
|
||||
|
||||
bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
|
||||
if (!DeclNode) {
|
||||
if (shouldSkipNode(DeclNode))
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScopedTraversal =
|
||||
TraversingASTNodeNotSpelledInSource || DeclNode->isImplicit();
|
||||
@ -1503,9 +1537,9 @@ bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
|
||||
}
|
||||
|
||||
bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
|
||||
if (!StmtNode) {
|
||||
if (shouldSkipNode(StmtNode))
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
|
||||
TraversingASTChildrenNotSpelledInSource;
|
||||
|
||||
@ -1515,6 +1549,9 @@ bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
|
||||
}
|
||||
|
||||
bool MatchASTVisitor::TraverseType(QualType TypeNode, bool TraverseQualifier) {
|
||||
if (shouldSkipNode(TypeNode))
|
||||
return true;
|
||||
|
||||
match(TypeNode);
|
||||
return RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode,
|
||||
TraverseQualifier);
|
||||
@ -1522,6 +1559,8 @@ bool MatchASTVisitor::TraverseType(QualType TypeNode, bool TraverseQualifier) {
|
||||
|
||||
bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode,
|
||||
bool TraverseQualifier) {
|
||||
if (shouldSkipNode(TypeLocNode))
|
||||
return true;
|
||||
// The RecursiveASTVisitor only visits types if they're not within TypeLocs.
|
||||
// We still want to find those types via matchers, so we match them here. Note
|
||||
// that the TypeLocs are structurally a shadow-hierarchy to the expressed
|
||||
@ -1534,6 +1573,9 @@ bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode,
|
||||
}
|
||||
|
||||
bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier NNS) {
|
||||
if (shouldSkipNode(NNS))
|
||||
return true;
|
||||
|
||||
match(NNS);
|
||||
return RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifier(NNS);
|
||||
}
|
||||
@ -1543,6 +1585,9 @@ bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
|
||||
if (!NNS)
|
||||
return true;
|
||||
|
||||
if (shouldSkipNode(NNS))
|
||||
return true;
|
||||
|
||||
match(NNS);
|
||||
|
||||
// We only match the nested name specifier here (as opposed to traversing it)
|
||||
@ -1555,7 +1600,7 @@ bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
|
||||
|
||||
bool MatchASTVisitor::TraverseConstructorInitializer(
|
||||
CXXCtorInitializer *CtorInit) {
|
||||
if (!CtorInit)
|
||||
if (shouldSkipNode(CtorInit))
|
||||
return true;
|
||||
|
||||
bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
|
||||
@ -1573,11 +1618,17 @@ bool MatchASTVisitor::TraverseConstructorInitializer(
|
||||
}
|
||||
|
||||
bool MatchASTVisitor::TraverseTemplateArgumentLoc(TemplateArgumentLoc Loc) {
|
||||
if (shouldSkipNode(Loc))
|
||||
return true;
|
||||
|
||||
match(Loc);
|
||||
return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateArgumentLoc(Loc);
|
||||
}
|
||||
|
||||
bool MatchASTVisitor::TraverseAttr(Attr *AttrNode) {
|
||||
if (shouldSkipNode(AttrNode))
|
||||
return true;
|
||||
|
||||
match(*AttrNode);
|
||||
return RecursiveASTVisitor<MatchASTVisitor>::TraverseAttr(AttrNode);
|
||||
}
|
||||
|
@ -45,10 +45,11 @@ struct Loan {
|
||||
/// is represented as empty LoanSet
|
||||
LoanID ID;
|
||||
AccessPath Path;
|
||||
SourceLocation IssueLoc;
|
||||
/// The expression that creates the loan, e.g., &x.
|
||||
const Expr *IssueExpr;
|
||||
|
||||
Loan(LoanID id, AccessPath path, SourceLocation loc)
|
||||
: ID(id), Path(path), IssueLoc(loc) {}
|
||||
Loan(LoanID id, AccessPath path, const Expr *IssueExpr)
|
||||
: ID(id), Path(path), IssueExpr(IssueExpr) {}
|
||||
};
|
||||
|
||||
/// An Origin is a symbolic identifier that represents the set of possible
|
||||
@ -82,8 +83,8 @@ class LoanManager {
|
||||
public:
|
||||
LoanManager() = default;
|
||||
|
||||
Loan &addLoan(AccessPath Path, SourceLocation Loc) {
|
||||
AllLoans.emplace_back(getNextLoanID(), Path, Loc);
|
||||
Loan &addLoan(AccessPath Path, const Expr *IssueExpr) {
|
||||
AllLoans.emplace_back(getNextLoanID(), Path, IssueExpr);
|
||||
return AllLoans.back();
|
||||
}
|
||||
|
||||
@ -199,6 +200,8 @@ public:
|
||||
AssignOrigin,
|
||||
/// An origin escapes the function by flowing into the return value.
|
||||
ReturnOfOrigin,
|
||||
/// An origin is used (eg. dereferencing a pointer).
|
||||
Use,
|
||||
/// A marker for a specific point in the code, for testing.
|
||||
TestPoint,
|
||||
};
|
||||
@ -242,12 +245,17 @@ public:
|
||||
|
||||
class ExpireFact : public Fact {
|
||||
LoanID LID;
|
||||
SourceLocation ExpiryLoc;
|
||||
|
||||
public:
|
||||
static bool classof(const Fact *F) { return F->getKind() == Kind::Expire; }
|
||||
|
||||
ExpireFact(LoanID LID) : Fact(Kind::Expire), LID(LID) {}
|
||||
ExpireFact(LoanID LID, SourceLocation ExpiryLoc)
|
||||
: Fact(Kind::Expire), LID(LID), ExpiryLoc(ExpiryLoc) {}
|
||||
|
||||
LoanID getLoanID() const { return LID; }
|
||||
SourceLocation getExpiryLoc() const { return ExpiryLoc; }
|
||||
|
||||
void dump(llvm::raw_ostream &OS) const override {
|
||||
OS << "Expire (LoanID: " << getLoanID() << ")\n";
|
||||
}
|
||||
@ -287,6 +295,24 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class UseFact : public Fact {
|
||||
OriginID UsedOrigin;
|
||||
const Expr *UseExpr;
|
||||
|
||||
public:
|
||||
static bool classof(const Fact *F) { return F->getKind() == Kind::Use; }
|
||||
|
||||
UseFact(OriginID UsedOrigin, const Expr *UseExpr)
|
||||
: Fact(Kind::Use), UsedOrigin(UsedOrigin), UseExpr(UseExpr) {}
|
||||
|
||||
OriginID getUsedOrigin() const { return UsedOrigin; }
|
||||
const Expr *getUseExpr() const { return UseExpr; }
|
||||
|
||||
void dump(llvm::raw_ostream &OS) const override {
|
||||
OS << "Use (OriginID: " << UsedOrigin << ")\n";
|
||||
}
|
||||
};
|
||||
|
||||
/// A dummy-fact used to mark a specific point in the code for testing.
|
||||
/// It is generated by recognizing a `void("__lifetime_test_point_...")` cast.
|
||||
class TestPointFact : public Fact {
|
||||
@ -417,13 +443,17 @@ public:
|
||||
if (VD->hasLocalStorage()) {
|
||||
OriginID OID = FactMgr.getOriginMgr().getOrCreate(*UO);
|
||||
AccessPath AddrOfLocalVarPath(VD);
|
||||
const Loan &L = FactMgr.getLoanMgr().addLoan(AddrOfLocalVarPath,
|
||||
UO->getOperatorLoc());
|
||||
const Loan &L =
|
||||
FactMgr.getLoanMgr().addLoan(AddrOfLocalVarPath, UO);
|
||||
CurrentBlockFacts.push_back(
|
||||
FactMgr.createFact<IssueFact>(L.ID, OID));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (UO->getOpcode() == UO_Deref) {
|
||||
// This is a pointer use, like '*p'.
|
||||
OriginID OID = FactMgr.getOriginMgr().get(*UO->getSubExpr());
|
||||
CurrentBlockFacts.push_back(FactMgr.createFact<UseFact>(OID, UO));
|
||||
}
|
||||
}
|
||||
|
||||
@ -492,7 +522,8 @@ private:
|
||||
// Check if the loan is for a stack variable and if that variable
|
||||
// is the one being destructed.
|
||||
if (LoanPath.D == DestructedVD)
|
||||
CurrentBlockFacts.push_back(FactMgr.createFact<ExpireFact>(L.ID));
|
||||
CurrentBlockFacts.push_back(FactMgr.createFact<ExpireFact>(
|
||||
L.ID, DtorOpt.getTriggerStmt()->getEndLoc()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -618,6 +649,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
Lattice getState(ProgramPoint P) const { return PerPointStates.lookup(P); }
|
||||
|
||||
Lattice getInState(const CFGBlock *B) const { return InStates.lookup(B); }
|
||||
@ -665,6 +697,8 @@ private:
|
||||
return D->transfer(In, *F->getAs<AssignOriginFact>());
|
||||
case Fact::Kind::ReturnOfOrigin:
|
||||
return D->transfer(In, *F->getAs<ReturnOfOriginFact>());
|
||||
case Fact::Kind::Use:
|
||||
return D->transfer(In, *F->getAs<UseFact>());
|
||||
case Fact::Kind::TestPoint:
|
||||
return D->transfer(In, *F->getAs<TestPointFact>());
|
||||
}
|
||||
@ -676,6 +710,7 @@ public:
|
||||
Lattice transfer(Lattice In, const ExpireFact &) { return In; }
|
||||
Lattice transfer(Lattice In, const AssignOriginFact &) { return In; }
|
||||
Lattice transfer(Lattice In, const ReturnOfOriginFact &) { return In; }
|
||||
Lattice transfer(Lattice In, const UseFact &) { return In; }
|
||||
Lattice transfer(Lattice In, const TestPointFact &) { return In; }
|
||||
};
|
||||
|
||||
@ -693,6 +728,20 @@ static llvm::ImmutableSet<T> join(llvm::ImmutableSet<T> A,
|
||||
return A;
|
||||
}
|
||||
|
||||
/// Checks if set A is a subset of set B.
|
||||
template <typename T>
|
||||
static bool isSubsetOf(const llvm::ImmutableSet<T> &A,
|
||||
const llvm::ImmutableSet<T> &B) {
|
||||
// Empty set is a subset of all sets.
|
||||
if (A.isEmpty())
|
||||
return true;
|
||||
|
||||
for (const T &Elem : A)
|
||||
if (!B.contains(Elem))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Computes the key-wise union of two ImmutableMaps.
|
||||
// TODO(opt): This key-wise join is a performance bottleneck. A more
|
||||
// efficient merge could be implemented using a Patricia Trie or HAMT
|
||||
@ -700,7 +749,7 @@ static llvm::ImmutableSet<T> join(llvm::ImmutableSet<T> A,
|
||||
template <typename K, typename V, typename Joiner>
|
||||
static llvm::ImmutableMap<K, V>
|
||||
join(llvm::ImmutableMap<K, V> A, llvm::ImmutableMap<K, V> B,
|
||||
typename llvm::ImmutableMap<K, V>::Factory &F, Joiner joinValues) {
|
||||
typename llvm::ImmutableMap<K, V>::Factory &F, Joiner JoinValues) {
|
||||
if (A.getHeight() < B.getHeight())
|
||||
std::swap(A, B);
|
||||
|
||||
@ -710,7 +759,7 @@ join(llvm::ImmutableMap<K, V> A, llvm::ImmutableMap<K, V> B,
|
||||
const K &Key = Entry.first;
|
||||
const V &ValB = Entry.second;
|
||||
if (const V *ValA = A.lookup(Key))
|
||||
A = F.add(A, Key, joinValues(*ValA, ValB));
|
||||
A = F.add(A, Key, JoinValues(*ValA, ValB));
|
||||
else
|
||||
A = F.add(A, Key, ValB);
|
||||
}
|
||||
@ -723,17 +772,14 @@ join(llvm::ImmutableMap<K, V> A, llvm::ImmutableMap<K, V> B,
|
||||
// ========================================================================= //
|
||||
|
||||
using OriginLoanMap = llvm::ImmutableMap<OriginID, LoanSet>;
|
||||
using ExpiredLoanMap = llvm::ImmutableMap<LoanID, const ExpireFact *>;
|
||||
|
||||
/// An object to hold the factories for immutable collections, ensuring
|
||||
/// that all created states share the same underlying memory management.
|
||||
struct LifetimeFactory {
|
||||
OriginLoanMap::Factory OriginMapFactory;
|
||||
LoanSet::Factory LoanSetFactory;
|
||||
|
||||
/// Creates a singleton set containing only the given loan ID.
|
||||
LoanSet createLoanSet(LoanID LID) {
|
||||
return LoanSetFactory.add(LoanSetFactory.getEmptySet(), LID);
|
||||
}
|
||||
ExpiredLoanMap::Factory ExpiredLoanMapFactory;
|
||||
};
|
||||
|
||||
/// Represents the dataflow lattice for loan propagation.
|
||||
@ -774,13 +820,15 @@ struct LoanPropagationLattice {
|
||||
class LoanPropagationAnalysis
|
||||
: public DataflowAnalysis<LoanPropagationAnalysis, LoanPropagationLattice,
|
||||
Direction::Forward> {
|
||||
|
||||
LifetimeFactory &Factory;
|
||||
OriginLoanMap::Factory &OriginLoanMapFactory;
|
||||
LoanSet::Factory &LoanSetFactory;
|
||||
|
||||
public:
|
||||
LoanPropagationAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
|
||||
LifetimeFactory &Factory)
|
||||
: DataflowAnalysis(C, AC, F), Factory(Factory) {}
|
||||
LifetimeFactory &LFactory)
|
||||
: DataflowAnalysis(C, AC, F),
|
||||
OriginLoanMapFactory(LFactory.OriginMapFactory),
|
||||
LoanSetFactory(LFactory.LoanSetFactory) {}
|
||||
|
||||
using Base::transfer;
|
||||
|
||||
@ -792,9 +840,9 @@ public:
|
||||
// TODO(opt): Keep the state small by removing origins which become dead.
|
||||
Lattice join(Lattice A, Lattice B) {
|
||||
OriginLoanMap JoinedOrigins =
|
||||
utils::join(A.Origins, B.Origins, Factory.OriginMapFactory,
|
||||
[this](LoanSet S1, LoanSet S2) {
|
||||
return utils::join(S1, S2, Factory.LoanSetFactory);
|
||||
utils::join(A.Origins, B.Origins, OriginLoanMapFactory,
|
||||
[&](LoanSet S1, LoanSet S2) {
|
||||
return utils::join(S1, S2, LoanSetFactory);
|
||||
});
|
||||
return Lattice(JoinedOrigins);
|
||||
}
|
||||
@ -803,8 +851,9 @@ public:
|
||||
Lattice transfer(Lattice In, const IssueFact &F) {
|
||||
OriginID OID = F.getOriginID();
|
||||
LoanID LID = F.getLoanID();
|
||||
return LoanPropagationLattice(Factory.OriginMapFactory.add(
|
||||
In.Origins, OID, Factory.createLoanSet(LID)));
|
||||
return LoanPropagationLattice(OriginLoanMapFactory.add(
|
||||
In.Origins, OID,
|
||||
LoanSetFactory.add(LoanSetFactory.getEmptySet(), LID)));
|
||||
}
|
||||
|
||||
/// The destination origin's loan set is replaced by the source's.
|
||||
@ -814,7 +863,7 @@ public:
|
||||
OriginID SrcOID = F.getSrcOriginID();
|
||||
LoanSet SrcLoans = getLoans(In, SrcOID);
|
||||
return LoanPropagationLattice(
|
||||
Factory.OriginMapFactory.add(In.Origins, DestOID, SrcLoans));
|
||||
OriginLoanMapFactory.add(In.Origins, DestOID, SrcLoans));
|
||||
}
|
||||
|
||||
LoanSet getLoans(OriginID OID, ProgramPoint P) {
|
||||
@ -825,7 +874,7 @@ private:
|
||||
LoanSet getLoans(Lattice L, OriginID OID) {
|
||||
if (auto *Loans = L.Origins.lookup(OID))
|
||||
return *Loans;
|
||||
return Factory.LoanSetFactory.getEmptySet();
|
||||
return LoanSetFactory.getEmptySet();
|
||||
}
|
||||
};
|
||||
|
||||
@ -835,10 +884,11 @@ private:
|
||||
|
||||
/// The dataflow lattice for tracking the set of expired loans.
|
||||
struct ExpiredLattice {
|
||||
LoanSet Expired;
|
||||
/// Map from an expired `LoanID` to the `ExpireFact` that made it expire.
|
||||
ExpiredLoanMap Expired;
|
||||
|
||||
ExpiredLattice() : Expired(nullptr) {};
|
||||
explicit ExpiredLattice(LoanSet S) : Expired(S) {}
|
||||
explicit ExpiredLattice(ExpiredLoanMap M) : Expired(M) {}
|
||||
|
||||
bool operator==(const ExpiredLattice &Other) const {
|
||||
return Expired == Other.Expired;
|
||||
@ -851,8 +901,8 @@ struct ExpiredLattice {
|
||||
OS << "ExpiredLattice State:\n";
|
||||
if (Expired.isEmpty())
|
||||
OS << " <empty>\n";
|
||||
for (const LoanID &LID : Expired)
|
||||
OS << " Loan " << LID << " is expired\n";
|
||||
for (const auto &[ID, _] : Expired)
|
||||
OS << " Loan " << ID << " is expired\n";
|
||||
}
|
||||
};
|
||||
|
||||
@ -861,26 +911,31 @@ class ExpiredLoansAnalysis
|
||||
: public DataflowAnalysis<ExpiredLoansAnalysis, ExpiredLattice,
|
||||
Direction::Forward> {
|
||||
|
||||
LoanSet::Factory &Factory;
|
||||
ExpiredLoanMap::Factory &Factory;
|
||||
|
||||
public:
|
||||
ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
|
||||
LifetimeFactory &Factory)
|
||||
: DataflowAnalysis(C, AC, F), Factory(Factory.LoanSetFactory) {}
|
||||
: DataflowAnalysis(C, AC, F), Factory(Factory.ExpiredLoanMapFactory) {}
|
||||
|
||||
using Base::transfer;
|
||||
|
||||
StringRef getAnalysisName() const { return "ExpiredLoans"; }
|
||||
|
||||
Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
|
||||
Lattice getInitialState() { return Lattice(Factory.getEmptyMap()); }
|
||||
|
||||
/// Merges two lattices by taking the union of the expired loan sets.
|
||||
Lattice join(Lattice L1, Lattice L2) const {
|
||||
return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
|
||||
/// Merges two lattices by taking the union of the two expired loans.
|
||||
Lattice join(Lattice L1, Lattice L2) {
|
||||
return Lattice(
|
||||
utils::join(L1.Expired, L2.Expired, Factory,
|
||||
// Take the last expiry fact to make this hermetic.
|
||||
[](const ExpireFact *F1, const ExpireFact *F2) {
|
||||
return F1->getExpiryLoc() > F2->getExpiryLoc() ? F1 : F2;
|
||||
}));
|
||||
}
|
||||
|
||||
Lattice transfer(Lattice In, const ExpireFact &F) {
|
||||
return Lattice(Factory.add(In.Expired, F.getLoanID()));
|
||||
return Lattice(Factory.add(In.Expired, F.getLoanID(), &F));
|
||||
}
|
||||
|
||||
// Removes the loan from the set of expired loans.
|
||||
@ -912,15 +967,116 @@ public:
|
||||
Lattice transfer(Lattice In, const IssueFact &F) {
|
||||
return Lattice(Factory.remove(In.Expired, F.getLoanID()));
|
||||
}
|
||||
|
||||
ExpiredLoanMap getExpiredLoans(ProgramPoint P) { return getState(P).Expired; }
|
||||
};
|
||||
|
||||
// ========================================================================= //
|
||||
// TODO:
|
||||
// - Modify loan expiry analysis to answer `bool isExpired(Loan L, Point P)`
|
||||
// - Modify origin liveness analysis to answer `bool isLive(Origin O, Point P)`
|
||||
// - Using the above three to perform the final error reporting.
|
||||
// Lifetime checker and Error reporter
|
||||
// ========================================================================= //
|
||||
|
||||
/// Struct to store the complete context for a potential lifetime violation.
|
||||
struct PendingWarning {
|
||||
SourceLocation ExpiryLoc; // Where the loan expired.
|
||||
const Expr *UseExpr; // Where the origin holding this loan was used.
|
||||
Confidence ConfidenceLevel;
|
||||
};
|
||||
|
||||
class LifetimeChecker {
|
||||
private:
|
||||
llvm::DenseMap<LoanID, PendingWarning> FinalWarningsMap;
|
||||
LoanPropagationAnalysis &LoanPropagation;
|
||||
ExpiredLoansAnalysis &ExpiredLoans;
|
||||
FactManager &FactMgr;
|
||||
AnalysisDeclContext &ADC;
|
||||
LifetimeSafetyReporter *Reporter;
|
||||
|
||||
public:
|
||||
LifetimeChecker(LoanPropagationAnalysis &LPA, ExpiredLoansAnalysis &ELA,
|
||||
FactManager &FM, AnalysisDeclContext &ADC,
|
||||
LifetimeSafetyReporter *Reporter)
|
||||
: LoanPropagation(LPA), ExpiredLoans(ELA), FactMgr(FM), ADC(ADC),
|
||||
Reporter(Reporter) {}
|
||||
|
||||
void run() {
|
||||
llvm::TimeTraceScope TimeProfile("LifetimeChecker");
|
||||
for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>())
|
||||
for (const Fact *F : FactMgr.getFacts(B))
|
||||
if (const auto *UF = F->getAs<UseFact>())
|
||||
checkUse(UF);
|
||||
issuePendingWarnings();
|
||||
}
|
||||
|
||||
/// Checks for use-after-free errors for a given use of an Origin.
|
||||
///
|
||||
/// This method is called for each 'UseFact' identified in the control flow
|
||||
/// graph. It determines if the loans held by the used origin have expired
|
||||
/// at the point of use.
|
||||
void checkUse(const UseFact *UF) {
|
||||
|
||||
OriginID O = UF->getUsedOrigin();
|
||||
|
||||
// Get the set of loans that the origin might hold at this program point.
|
||||
LoanSet HeldLoans = LoanPropagation.getLoans(O, UF);
|
||||
|
||||
// Get the set of all loans that have expired at this program point.
|
||||
ExpiredLoanMap AllExpiredLoans = ExpiredLoans.getExpiredLoans(UF);
|
||||
|
||||
// If the pointer holds no loans or no loans have expired, there's nothing
|
||||
// to check.
|
||||
if (HeldLoans.isEmpty() || AllExpiredLoans.isEmpty())
|
||||
return;
|
||||
|
||||
// Identify loans that which have expired but are held by the pointer. Using
|
||||
// them is a use-after-free.
|
||||
llvm::SmallVector<LoanID> DefaultedLoans;
|
||||
// A definite UaF error occurs if all loans the origin might hold have
|
||||
// expired.
|
||||
bool IsDefiniteError = true;
|
||||
for (LoanID L : HeldLoans) {
|
||||
if (AllExpiredLoans.contains(L))
|
||||
DefaultedLoans.push_back(L);
|
||||
else
|
||||
// If at least one loan is not expired, this use is not a definite UaF.
|
||||
IsDefiniteError = false;
|
||||
}
|
||||
// If there are no defaulted loans, the use is safe.
|
||||
if (DefaultedLoans.empty())
|
||||
return;
|
||||
|
||||
// Determine the confidence level of the error (definite or maybe).
|
||||
Confidence CurrentConfidence =
|
||||
IsDefiniteError ? Confidence::Definite : Confidence::Maybe;
|
||||
|
||||
// For each expired loan, create a pending warning.
|
||||
for (LoanID DefaultedLoan : DefaultedLoans) {
|
||||
// If we already have a warning for this loan with a higher or equal
|
||||
// confidence, skip this one.
|
||||
if (FinalWarningsMap.count(DefaultedLoan) &&
|
||||
CurrentConfidence <= FinalWarningsMap[DefaultedLoan].ConfidenceLevel)
|
||||
continue;
|
||||
|
||||
auto *EF = AllExpiredLoans.lookup(DefaultedLoan);
|
||||
assert(EF && "Could not find ExpireFact for an expired loan.");
|
||||
|
||||
FinalWarningsMap[DefaultedLoan] = {/*ExpiryLoc=*/(*EF)->getExpiryLoc(),
|
||||
/*UseExpr=*/UF->getUseExpr(),
|
||||
/*ConfidenceLevel=*/CurrentConfidence};
|
||||
}
|
||||
}
|
||||
|
||||
void issuePendingWarnings() {
|
||||
if (!Reporter)
|
||||
return;
|
||||
for (const auto &[LID, Warning] : FinalWarningsMap) {
|
||||
const Loan &L = FactMgr.getLoanMgr().getLoan(LID);
|
||||
const Expr *IssueExpr = L.IssueExpr;
|
||||
Reporter->reportUseAfterFree(IssueExpr, Warning.UseExpr,
|
||||
Warning.ExpiryLoc, Warning.ConfidenceLevel);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ========================================================================= //
|
||||
// LifetimeSafetyAnalysis Class Implementation
|
||||
// ========================================================================= //
|
||||
@ -928,8 +1084,9 @@ public:
|
||||
// We need this here for unique_ptr with forward declared class.
|
||||
LifetimeSafetyAnalysis::~LifetimeSafetyAnalysis() = default;
|
||||
|
||||
LifetimeSafetyAnalysis::LifetimeSafetyAnalysis(AnalysisDeclContext &AC)
|
||||
: AC(AC), Factory(std::make_unique<LifetimeFactory>()),
|
||||
LifetimeSafetyAnalysis::LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
|
||||
LifetimeSafetyReporter *Reporter)
|
||||
: AC(AC), Reporter(Reporter), Factory(std::make_unique<LifetimeFactory>()),
|
||||
FactMgr(std::make_unique<FactManager>()) {}
|
||||
|
||||
void LifetimeSafetyAnalysis::run() {
|
||||
@ -952,6 +1109,8 @@ void LifetimeSafetyAnalysis::run() {
|
||||
/// blocks; only Decls are visible. Therefore, loans in a block that
|
||||
/// never reach an Origin associated with a Decl can be safely dropped by
|
||||
/// the analysis.
|
||||
/// 3. Collapse ExpireFacts belonging to same source location into a single
|
||||
/// Fact.
|
||||
LoanPropagation =
|
||||
std::make_unique<LoanPropagationAnalysis>(Cfg, AC, *FactMgr, *Factory);
|
||||
LoanPropagation->run();
|
||||
@ -959,6 +1118,10 @@ void LifetimeSafetyAnalysis::run() {
|
||||
ExpiredLoans =
|
||||
std::make_unique<ExpiredLoansAnalysis>(Cfg, AC, *FactMgr, *Factory);
|
||||
ExpiredLoans->run();
|
||||
|
||||
LifetimeChecker Checker(*LoanPropagation, *ExpiredLoans, *FactMgr, AC,
|
||||
Reporter);
|
||||
Checker.run();
|
||||
}
|
||||
|
||||
LoanSet LifetimeSafetyAnalysis::getLoansAtPoint(OriginID OID,
|
||||
@ -967,9 +1130,13 @@ LoanSet LifetimeSafetyAnalysis::getLoansAtPoint(OriginID OID,
|
||||
return LoanPropagation->getLoans(OID, PP);
|
||||
}
|
||||
|
||||
LoanSet LifetimeSafetyAnalysis::getExpiredLoansAtPoint(ProgramPoint PP) const {
|
||||
std::vector<LoanID>
|
||||
LifetimeSafetyAnalysis::getExpiredLoansAtPoint(ProgramPoint PP) const {
|
||||
assert(ExpiredLoans && "ExpiredLoansAnalysis has not been run.");
|
||||
return ExpiredLoans->getState(PP).Expired;
|
||||
std::vector<LoanID> Result;
|
||||
for (const auto &pair : ExpiredLoans->getExpiredLoans(PP))
|
||||
Result.push_back(pair.first);
|
||||
return Result;
|
||||
}
|
||||
|
||||
std::optional<OriginID>
|
||||
@ -1009,8 +1176,9 @@ llvm::StringMap<ProgramPoint> LifetimeSafetyAnalysis::getTestPoints() const {
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC) {
|
||||
internal::LifetimeSafetyAnalysis Analysis(AC);
|
||||
void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
|
||||
LifetimeSafetyReporter *Reporter) {
|
||||
internal::LifetimeSafetyAnalysis Analysis(AC, Reporter);
|
||||
Analysis.run();
|
||||
}
|
||||
} // namespace clang::lifetimes
|
||||
|
@ -62,7 +62,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
|
||||
TLSSupported = true;
|
||||
VLASupported = true;
|
||||
NoAsmVariants = false;
|
||||
HasLegalHalfType = false;
|
||||
HasFastHalfType = false;
|
||||
HalfArgsAndReturns = false;
|
||||
HasFloat128 = false;
|
||||
HasIbm128 = false;
|
||||
|
@ -142,7 +142,7 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
|
||||
AddrSpaceMap = &ARM64AddrSpaceMap;
|
||||
|
||||
// All AArch64 implementations support ARMv8 FP, which makes half a legal type.
|
||||
HasLegalHalfType = true;
|
||||
HasFastHalfType = true;
|
||||
HalfArgsAndReturns = true;
|
||||
HasFloat16 = true;
|
||||
HasStrictFP = true;
|
||||
|
@ -251,7 +251,7 @@ AMDGPUTargetInfo::AMDGPUTargetInfo(const llvm::Triple &Triple,
|
||||
BFloat16Format = &llvm::APFloat::BFloat();
|
||||
}
|
||||
|
||||
HasLegalHalfType = true;
|
||||
HasFastHalfType = true;
|
||||
HasFloat16 = true;
|
||||
WavefrontSize = (GPUFeatures & llvm::AMDGPU::FEATURE_WAVE32) ? 32 : 64;
|
||||
|
||||
|
@ -585,13 +585,13 @@ bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
|
||||
} else if (Feature == "+fp16") {
|
||||
HW_FP |= HW_FP_HP;
|
||||
} else if (Feature == "+fullfp16") {
|
||||
HasLegalHalfType = true;
|
||||
HasFastHalfType = true;
|
||||
} else if (Feature == "+dotprod") {
|
||||
DotProd = true;
|
||||
} else if (Feature == "+mve") {
|
||||
MVE |= MVE_INT;
|
||||
} else if (Feature == "+mve.fp") {
|
||||
HasLegalHalfType = true;
|
||||
HasFastHalfType = true;
|
||||
FPU |= FPARMV8;
|
||||
MVE |= MVE_INT | MVE_FP;
|
||||
HW_FP |= HW_FP_SP | HW_FP_HP;
|
||||
@ -1014,11 +1014,11 @@ void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
|
||||
Builder.defineMacro("__ARM_FP_FAST", "1");
|
||||
|
||||
// Armv8.2-A FP16 vector intrinsic
|
||||
if ((FPU & NeonFPU) && HasLegalHalfType)
|
||||
if ((FPU & NeonFPU) && HasFastHalfType)
|
||||
Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
|
||||
|
||||
// Armv8.2-A FP16 scalar intrinsics
|
||||
if (HasLegalHalfType)
|
||||
if (HasFastHalfType)
|
||||
Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
|
||||
|
||||
// Armv8.2-A dot product intrinsics
|
||||
|
@ -59,7 +59,7 @@ public:
|
||||
VLASupported = false;
|
||||
AddrSpaceMap = &DirectXAddrSpaceMap;
|
||||
UseAddrSpaceMapMangling = true;
|
||||
HasLegalHalfType = true;
|
||||
HasFastHalfType = true;
|
||||
HasFloat16 = true;
|
||||
NoAsmVariants = true;
|
||||
PlatformMinVersion = Triple.getOSVersion();
|
||||
|
@ -149,7 +149,7 @@ bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
|
||||
HasAudio = true;
|
||||
}
|
||||
if (CPU.compare("hexagonv68") >= 0) {
|
||||
HasLegalHalfType = true;
|
||||
HasFastHalfType = true;
|
||||
HasFloat16 = true;
|
||||
}
|
||||
return true;
|
||||
|
@ -65,7 +65,7 @@ NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple,
|
||||
GPU = OffloadArch::UNUSED;
|
||||
|
||||
// PTX supports f16 as a fundamental type.
|
||||
HasLegalHalfType = true;
|
||||
HasFastHalfType = true;
|
||||
HasFloat16 = true;
|
||||
|
||||
if (TargetPointerWidth == 32)
|
||||
|
@ -427,7 +427,7 @@ bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
|
||||
ABI = ISAInfo->computeDefaultABI().str();
|
||||
|
||||
if (ISAInfo->hasExtension("zfh") || ISAInfo->hasExtension("zhinx"))
|
||||
HasLegalHalfType = true;
|
||||
HasFastHalfType = true;
|
||||
|
||||
FastScalarUnalignedAccess =
|
||||
llvm::is_contained(Features, "+unaligned-scalar-mem");
|
||||
|
@ -106,7 +106,7 @@ protected:
|
||||
LongWidth = LongAlign = 64;
|
||||
AddrSpaceMap = &SPIRDefIsPrivMap;
|
||||
UseAddrSpaceMapMangling = true;
|
||||
HasLegalHalfType = true;
|
||||
HasFastHalfType = true;
|
||||
HasFloat16 = true;
|
||||
// Define available target features
|
||||
// These must be defined in sorted order!
|
||||
@ -427,7 +427,7 @@ public:
|
||||
BFloat16Width = BFloat16Align = 16;
|
||||
BFloat16Format = &llvm::APFloat::BFloat();
|
||||
|
||||
HasLegalHalfType = true;
|
||||
HasFastHalfType = true;
|
||||
HasFloat16 = true;
|
||||
HalfArgsAndReturns = true;
|
||||
|
||||
|
@ -104,7 +104,7 @@ public:
|
||||
// -ffloat16-excess-precision=none is given, no conversions will be made
|
||||
// and instead the backend will promote each half operation to float
|
||||
// individually.
|
||||
HasLegalHalfType = false;
|
||||
HasFastHalfType = false;
|
||||
|
||||
HasStrictFP = true;
|
||||
}
|
||||
|
@ -348,7 +348,7 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
|
||||
HasAVX512BF16 = true;
|
||||
} else if (Feature == "+avx512fp16") {
|
||||
HasAVX512FP16 = true;
|
||||
HasLegalHalfType = true;
|
||||
HasFastHalfType = true;
|
||||
} else if (Feature == "+avx512dq") {
|
||||
HasAVX512DQ = true;
|
||||
} else if (Feature == "+avx512bitalg") {
|
||||
|
@ -387,6 +387,20 @@ class OpenACCClauseCIREmitter final
|
||||
return recipeName;
|
||||
}
|
||||
|
||||
void createFirstprivateRecipeCopy(
|
||||
mlir::Location loc, mlir::Location locEnd, mlir::Value mainOp,
|
||||
CIRGenFunction::AutoVarEmission tempDeclEmission,
|
||||
mlir::acc::FirstprivateRecipeOp recipe, const VarDecl *varRecipe,
|
||||
const VarDecl *temporary) {
|
||||
builder.createBlock(&recipe.getCopyRegion(), recipe.getCopyRegion().end(),
|
||||
{mainOp.getType(), mainOp.getType()}, {loc, loc});
|
||||
builder.setInsertionPointToEnd(&recipe.getCopyRegion().back());
|
||||
|
||||
// TODO: OpenACC: Implement this copy to actually do something.
|
||||
|
||||
mlir::acc::YieldOp::create(builder, locEnd);
|
||||
}
|
||||
|
||||
// Create the 'init' section of the recipe, including the 'copy' section for
|
||||
// 'firstprivate'.
|
||||
template <typename RecipeTy>
|
||||
@ -401,12 +415,6 @@ class OpenACCClauseCIREmitter final
|
||||
cgf.cgm.errorNYI(exprRange, "OpenACC Reduction recipe init");
|
||||
}
|
||||
|
||||
if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>) {
|
||||
// We haven't implemented the 'init'/copy recipe for firstprivate yet, so
|
||||
// NYI it.
|
||||
cgf.cgm.errorNYI(exprRange, "OpenACC firstprivate recipe init");
|
||||
}
|
||||
|
||||
CIRGenFunction::AutoVarEmission tempDeclEmission{
|
||||
CIRGenFunction::AutoVarEmission::invalid()};
|
||||
|
||||
@ -442,17 +450,12 @@ class OpenACCClauseCIREmitter final
|
||||
mlir::acc::YieldOp::create(builder, locEnd);
|
||||
|
||||
if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>) {
|
||||
if (!varRecipe->getInit()) {
|
||||
// If we don't have any initialization recipe, we failed during Sema to
|
||||
// initialize this correctly. If we disable the
|
||||
// Sema::TentativeAnalysisScopes in SemaOpenACC::CreateInitRecipe, it'll
|
||||
// emit an error to tell us. However, emitting those errors during
|
||||
// production is a violation of the standard, so we cannot do them.
|
||||
cgf.cgm.errorNYI(
|
||||
exprRange, "firstprivate copy-init recipe not properly generated");
|
||||
}
|
||||
|
||||
cgf.cgm.errorNYI(exprRange, "firstprivate copy section generation");
|
||||
// TODO: OpenACC: we should have a errorNYI call here if
|
||||
// !varRecipe->getInit(), but as that generation isn't currently
|
||||
// implemented, it ends up being too noisy. So when we implement copy-init
|
||||
// generation both in Sema and here, we should have a diagnostic here.
|
||||
createFirstprivateRecipeCopy(loc, locEnd, mainOp, tempDeclEmission,
|
||||
recipe, varRecipe, temporary);
|
||||
}
|
||||
|
||||
// Make sure we cleanup after ourselves here.
|
||||
@ -1155,6 +1158,43 @@ public:
|
||||
llvm_unreachable("Unknown construct kind in VisitPrivateClause");
|
||||
}
|
||||
}
|
||||
|
||||
void VisitFirstPrivateClause(const OpenACCFirstPrivateClause &clause) {
|
||||
if constexpr (isOneOfTypes<OpTy, mlir::acc::ParallelOp,
|
||||
mlir::acc::SerialOp>) {
|
||||
for (const auto [varExpr, varRecipe] :
|
||||
llvm::zip_equal(clause.getVarList(), clause.getInitRecipes())) {
|
||||
CIRGenFunction::OpenACCDataOperandInfo opInfo =
|
||||
cgf.getOpenACCDataOperandInfo(varExpr);
|
||||
auto firstPrivateOp = mlir::acc::FirstprivateOp::create(
|
||||
builder, opInfo.beginLoc, opInfo.varValue, /*structured=*/true,
|
||||
/*implicit=*/false, opInfo.name, opInfo.bounds);
|
||||
|
||||
firstPrivateOp.setDataClause(mlir::acc::DataClause::acc_firstprivate);
|
||||
|
||||
{
|
||||
mlir::OpBuilder::InsertionGuard guardCase(builder);
|
||||
auto recipe = getOrCreateRecipe<mlir::acc::FirstprivateRecipeOp>(
|
||||
cgf.getContext(), varExpr, varRecipe.RecipeDecl,
|
||||
varRecipe.InitFromTemporary,
|
||||
Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
|
||||
firstPrivateOp.getResult());
|
||||
|
||||
// TODO: OpenACC: The dialect is going to change in the near future to
|
||||
// have these be on a different operation, so when that changes, we
|
||||
// probably need to change these here.
|
||||
operation.addFirstPrivatization(builder.getContext(), firstPrivateOp,
|
||||
recipe);
|
||||
}
|
||||
}
|
||||
} else if constexpr (isCombinedType<OpTy>) {
|
||||
// Unlike 'private', 'firstprivate' applies to the compute op, not the
|
||||
// loop op.
|
||||
applyToComputeOp(clause);
|
||||
} else {
|
||||
llvm_unreachable("Unknown construct kind in VisitFirstPrivateClause");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename OpTy>
|
||||
|
@ -358,7 +358,7 @@ static Value *emitCallMaybeConstrainedFPBuiltin(CodeGenFunction &CGF,
|
||||
|
||||
static llvm::FixedVectorType *GetNeonType(CodeGenFunction *CGF,
|
||||
NeonTypeFlags TypeFlags,
|
||||
bool HasLegalHalfType = true,
|
||||
bool HasFastHalfType = true,
|
||||
bool V1Ty = false,
|
||||
bool AllowBFloatArgsAndRet = true) {
|
||||
int IsQuad = TypeFlags.isQuad();
|
||||
@ -376,7 +376,7 @@ static llvm::FixedVectorType *GetNeonType(CodeGenFunction *CGF,
|
||||
else
|
||||
return llvm::FixedVectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad));
|
||||
case NeonTypeFlags::Float16:
|
||||
if (HasLegalHalfType)
|
||||
if (HasFastHalfType)
|
||||
return llvm::FixedVectorType::get(CGF->HalfTy, V1Ty ? 1 : (4 << IsQuad));
|
||||
else
|
||||
return llvm::FixedVectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad));
|
||||
@ -1754,12 +1754,12 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
|
||||
const bool Usgn = Type.isUnsigned();
|
||||
const bool Quad = Type.isQuad();
|
||||
const bool Floating = Type.isFloatingPoint();
|
||||
const bool HasLegalHalfType = getTarget().hasLegalHalfType();
|
||||
const bool HasFastHalfType = getTarget().hasFastHalfType();
|
||||
const bool AllowBFloatArgsAndRet =
|
||||
getTargetHooks().getABIInfo().allowBFloatArgsAndRet();
|
||||
|
||||
llvm::FixedVectorType *VTy =
|
||||
GetNeonType(this, Type, HasLegalHalfType, false, AllowBFloatArgsAndRet);
|
||||
GetNeonType(this, Type, HasFastHalfType, false, AllowBFloatArgsAndRet);
|
||||
llvm::Type *Ty = VTy;
|
||||
if (!Ty)
|
||||
return nullptr;
|
||||
@ -1886,7 +1886,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
|
||||
case NEON::BI__builtin_neon_vcvtq_f32_v:
|
||||
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
|
||||
Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, Quad),
|
||||
HasLegalHalfType);
|
||||
HasFastHalfType);
|
||||
return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
|
||||
: Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
|
||||
case NEON::BI__builtin_neon_vcvt_f16_s16:
|
||||
@ -1895,7 +1895,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
|
||||
case NEON::BI__builtin_neon_vcvtq_f16_u16:
|
||||
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
|
||||
Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float16, false, Quad),
|
||||
HasLegalHalfType);
|
||||
HasFastHalfType);
|
||||
return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
|
||||
: Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
|
||||
case NEON::BI__builtin_neon_vcvt_n_f16_s16:
|
||||
@ -3211,7 +3211,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
|
||||
bool rightShift = false;
|
||||
|
||||
llvm::FixedVectorType *VTy =
|
||||
GetNeonType(this, Type, getTarget().hasLegalHalfType(), false,
|
||||
GetNeonType(this, Type, getTarget().hasFastHalfType(), false,
|
||||
getTarget().hasBFloat16Type());
|
||||
llvm::Type *Ty = VTy;
|
||||
if (!Ty)
|
||||
|
@ -316,7 +316,7 @@ ABIArgInfo ARMABIInfo::classifyHomogeneousAggregate(QualType Ty,
|
||||
// Base can be a floating-point or a vector.
|
||||
if (const VectorType *VT = Base->getAs<VectorType>()) {
|
||||
// FP16 vectors should be converted to integer vectors
|
||||
if (!getTarget().hasLegalHalfType() && containsAnyFP16Vectors(Ty)) {
|
||||
if (!getTarget().hasFastHalfType() && containsAnyFP16Vectors(Ty)) {
|
||||
uint64_t Size = getContext().getTypeSize(VT);
|
||||
auto *NewVecTy = llvm::FixedVectorType::get(
|
||||
llvm::Type::getInt32Ty(getVMContext()), Size / 32);
|
||||
@ -582,7 +582,7 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, bool isVariadic,
|
||||
getDataLayout().getAllocaAddrSpace());
|
||||
// TODO: FP16/BF16 vectors should be converted to integer vectors
|
||||
// This check is similar to isIllegalVectorType - refactor?
|
||||
if ((!getTarget().hasLegalHalfType() &&
|
||||
if ((!getTarget().hasFastHalfType() &&
|
||||
(VT->getElementType()->isFloat16Type() ||
|
||||
VT->getElementType()->isHalfType())) ||
|
||||
(IsFloatABISoftFP &&
|
||||
@ -679,9 +679,9 @@ bool ARMABIInfo::isIllegalVectorType(QualType Ty) const {
|
||||
// into float, and we don't want the ABI to depend on whether or not they
|
||||
// are supported in hardware. Thus return false to coerce vectors of these
|
||||
// types into integer vectors.
|
||||
// We do not depend on hasLegalHalfType for bfloat as it is a
|
||||
// We do not depend on hasFastHalfType for bfloat as it is a
|
||||
// separate IR type.
|
||||
if ((!getTarget().hasLegalHalfType() &&
|
||||
if ((!getTarget().hasFastHalfType() &&
|
||||
(VT->getElementType()->isFloat16Type() ||
|
||||
VT->getElementType()->isHalfType())) ||
|
||||
(IsFloatABISoftFP &&
|
||||
|
@ -629,9 +629,16 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
|
||||
// name.
|
||||
!Style.isJavaScript() && Previous.isNot(tok::kw_template) &&
|
||||
CurrentState.BreakBeforeParameter) {
|
||||
for (const auto *Tok = &Previous; Tok; Tok = Tok->Previous)
|
||||
if (Tok->FirstAfterPPLine || Tok->is(TT_LineComment))
|
||||
for (const auto *Tok = &Previous; Tok; Tok = Tok->Previous) {
|
||||
if (Tok->is(TT_LineComment))
|
||||
return false;
|
||||
if (Tok->is(TT_TemplateCloser)) {
|
||||
Tok = Tok->MatchingParen;
|
||||
assert(Tok);
|
||||
}
|
||||
if (Tok->FirstAfterPPLine)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -763,6 +763,15 @@ struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ScalarEnumerationTraits<FormatStyle::SpaceInEmptyBracesStyle> {
|
||||
static void enumeration(IO &IO, FormatStyle::SpaceInEmptyBracesStyle &Value) {
|
||||
IO.enumCase(Value, "Always", FormatStyle::SIEB_Always);
|
||||
IO.enumCase(Value, "Block", FormatStyle::SIEB_Block);
|
||||
IO.enumCase(Value, "Never", FormatStyle::SIEB_Never);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> {
|
||||
static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) {
|
||||
IO.enumCase(Value, "Never", FormatStyle::SIAS_Never);
|
||||
@ -931,6 +940,7 @@ template <> struct MappingTraits<FormatStyle> {
|
||||
bool DeriveLineEnding = true;
|
||||
bool UseCRLF = false;
|
||||
|
||||
bool SpaceInEmptyBlock = false;
|
||||
bool SpaceInEmptyParentheses = false;
|
||||
bool SpacesInConditionalStatement = false;
|
||||
bool SpacesInCStyleCastParentheses = false;
|
||||
@ -960,6 +970,7 @@ template <> struct MappingTraits<FormatStyle> {
|
||||
IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
|
||||
IO.mapOptional("SpaceAfterControlStatementKeyword",
|
||||
Style.SpaceBeforeParens);
|
||||
IO.mapOptional("SpaceInEmptyBlock", SpaceInEmptyBlock);
|
||||
IO.mapOptional("SpaceInEmptyParentheses", SpaceInEmptyParentheses);
|
||||
IO.mapOptional("SpacesInConditionalStatement",
|
||||
SpacesInConditionalStatement);
|
||||
@ -1193,7 +1204,7 @@ template <> struct MappingTraits<FormatStyle> {
|
||||
Style.SpaceBeforeRangeBasedForLoopColon);
|
||||
IO.mapOptional("SpaceBeforeSquareBrackets",
|
||||
Style.SpaceBeforeSquareBrackets);
|
||||
IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock);
|
||||
IO.mapOptional("SpaceInEmptyBraces", Style.SpaceInEmptyBraces);
|
||||
IO.mapOptional("SpacesBeforeTrailingComments",
|
||||
Style.SpacesBeforeTrailingComments);
|
||||
IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
|
||||
@ -1276,6 +1287,13 @@ template <> struct MappingTraits<FormatStyle> {
|
||||
Style.LineEnding = FormatStyle::LE_DeriveCRLF;
|
||||
}
|
||||
|
||||
// If SpaceInEmptyBlock was specified but SpaceInEmptyBraces was not,
|
||||
// initialize the latter from the former for backward compatibility.
|
||||
if (SpaceInEmptyBlock &&
|
||||
Style.SpaceInEmptyBraces == FormatStyle::SIEB_Never) {
|
||||
Style.SpaceInEmptyBraces = FormatStyle::SIEB_Block;
|
||||
}
|
||||
|
||||
if (Style.SpacesInParens != FormatStyle::SIPO_Custom &&
|
||||
(SpacesInParentheses || SpaceInEmptyParentheses ||
|
||||
SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {
|
||||
@ -1677,7 +1695,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
|
||||
LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true;
|
||||
LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
|
||||
LLVMStyle.SpaceBeforeSquareBrackets = false;
|
||||
LLVMStyle.SpaceInEmptyBlock = false;
|
||||
LLVMStyle.SpaceInEmptyBraces = FormatStyle::SIEB_Never;
|
||||
LLVMStyle.SpacesBeforeTrailingComments = 1;
|
||||
LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never;
|
||||
LLVMStyle.SpacesInContainerLiterals = true;
|
||||
@ -1984,7 +2002,7 @@ FormatStyle getWebKitStyle() {
|
||||
Style.ObjCSpaceAfterProperty = true;
|
||||
Style.PointerAlignment = FormatStyle::PAS_Left;
|
||||
Style.SpaceBeforeCpp11BracedList = true;
|
||||
Style.SpaceInEmptyBlock = true;
|
||||
Style.SpaceInEmptyBraces = FormatStyle::SIEB_Always;
|
||||
return Style;
|
||||
}
|
||||
|
||||
|
@ -2590,6 +2590,9 @@ private:
|
||||
if (!Tok.Previous || Tok.isNot(tok::identifier) || Tok.is(TT_ClassHeadName))
|
||||
return false;
|
||||
|
||||
if (Tok.endsSequence(Keywords.kw_final, TT_ClassHeadName))
|
||||
return false;
|
||||
|
||||
if ((Style.isJavaScript() || Style.isJava()) && Tok.is(Keywords.kw_extends))
|
||||
return false;
|
||||
|
||||
@ -4513,16 +4516,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
|
||||
return Left.is(tok::hash);
|
||||
if (Left.isOneOf(tok::hashhash, tok::hash))
|
||||
return Right.is(tok::hash);
|
||||
if (Left.is(BK_Block) && Right.is(tok::r_brace) &&
|
||||
Right.MatchingParen == &Left && Line.Children.empty()) {
|
||||
return Style.SpaceInEmptyBlock;
|
||||
}
|
||||
if (Style.SpacesInParens == FormatStyle::SIPO_Custom) {
|
||||
if ((Left.is(tok::l_paren) && Right.is(tok::r_paren)) ||
|
||||
(Left.is(tok::l_brace) && Left.isNot(BK_Block) &&
|
||||
Right.is(tok::r_brace) && Right.isNot(BK_Block))) {
|
||||
if (Left.is(tok::l_paren) && Right.is(tok::r_paren))
|
||||
return Style.SpacesInParensOptions.InEmptyParentheses;
|
||||
}
|
||||
if (Style.SpacesInParensOptions.ExceptDoubleParentheses &&
|
||||
Left.is(tok::r_paren) && Right.is(tok::r_paren)) {
|
||||
auto *InnerLParen = Left.MatchingParen;
|
||||
@ -4800,8 +4796,6 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
|
||||
Right.is(TT_ArraySubscriptLSquare))) {
|
||||
return false;
|
||||
}
|
||||
if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
|
||||
return !Left.Children.empty(); // No spaces in "{}".
|
||||
if ((Left.is(tok::l_brace) && Left.isNot(BK_Block)) ||
|
||||
(Right.is(tok::r_brace) && Right.MatchingParen &&
|
||||
Right.MatchingParen->isNot(BK_Block))) {
|
||||
@ -4983,6 +4977,17 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
|
||||
if (Left.is(tok::star) && Right.is(tok::comment))
|
||||
return true;
|
||||
|
||||
if (Left.is(tok::l_brace) && Right.is(tok::r_brace) &&
|
||||
Left.Children.empty()) {
|
||||
if (Left.is(BK_Block))
|
||||
return Style.SpaceInEmptyBraces != FormatStyle::SIEB_Never;
|
||||
if (Style.Cpp11BracedListStyle) {
|
||||
return Style.SpacesInParens == FormatStyle::SIPO_Custom &&
|
||||
Style.SpacesInParensOptions.InEmptyParentheses;
|
||||
}
|
||||
return Style.SpaceInEmptyBraces == FormatStyle::SIEB_Always;
|
||||
}
|
||||
|
||||
const auto *BeforeLeft = Left.Previous;
|
||||
|
||||
if (IsCpp) {
|
||||
@ -6269,7 +6274,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
|
||||
}
|
||||
|
||||
if (Right.is(tok::colon) &&
|
||||
!Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon)) {
|
||||
!Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon,
|
||||
TT_BitFieldColon)) {
|
||||
return false;
|
||||
}
|
||||
if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) {
|
||||
|
@ -864,7 +864,8 @@ private:
|
||||
if (ShouldMerge()) {
|
||||
// We merge empty blocks even if the line exceeds the column limit.
|
||||
Tok->SpacesRequiredBefore =
|
||||
(Style.SpaceInEmptyBlock || Line.Last->is(tok::comment)) ? 1 : 0;
|
||||
Style.SpaceInEmptyBraces != FormatStyle::SIEB_Never ||
|
||||
Line.Last->is(tok::comment);
|
||||
Tok->CanBreakBefore = true;
|
||||
return 1;
|
||||
} else if (Limit != 0 && !Line.startsWithNamespace() &&
|
||||
|
@ -1667,9 +1667,8 @@ _mm256_cvtepu32_epi64(__m128i __V) {
|
||||
/// \param __b
|
||||
/// A 256-bit vector of [8 x i32] containing one of the source operands.
|
||||
/// \returns A 256-bit vector of [4 x i64] containing the products.
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256
|
||||
_mm256_mul_epi32(__m256i __a, __m256i __b)
|
||||
{
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
|
||||
_mm256_mul_epi32(__m256i __a, __m256i __b) {
|
||||
return (__m256i)__builtin_ia32_pmuldq256((__v8si)__a, (__v8si)__b);
|
||||
}
|
||||
|
||||
@ -1796,9 +1795,8 @@ _mm256_mullo_epi32 (__m256i __a, __m256i __b)
|
||||
/// \param __b
|
||||
/// A 256-bit vector of [8 x i32] containing one of the source operands.
|
||||
/// \returns A 256-bit vector of [4 x i64] containing the products.
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256
|
||||
_mm256_mul_epu32(__m256i __a, __m256i __b)
|
||||
{
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
|
||||
_mm256_mul_epu32(__m256i __a, __m256i __b) {
|
||||
return __builtin_ia32_pmuludq256((__v8si)__a, (__v8si)__b);
|
||||
}
|
||||
|
||||
|
@ -27,47 +27,35 @@
|
||||
#endif
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS_CONSTEXPR
|
||||
_mm512_popcnt_epi16(__m512i __A)
|
||||
{
|
||||
_mm512_popcnt_epi16(__m512i __A) {
|
||||
return (__m512i)__builtin_elementwise_popcount((__v32hu)__A);
|
||||
}
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_popcnt_epi16(__m512i __A, __mmask32 __U, __m512i __B)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_selectw_512((__mmask32) __U,
|
||||
(__v32hi) _mm512_popcnt_epi16(__B),
|
||||
(__v32hi) __A);
|
||||
}
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS
|
||||
_mm512_maskz_popcnt_epi16(__mmask32 __U, __m512i __B)
|
||||
{
|
||||
return _mm512_mask_popcnt_epi16((__m512i) _mm512_setzero_si512(),
|
||||
__U,
|
||||
__B);
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS_CONSTEXPR
|
||||
_mm512_mask_popcnt_epi16(__m512i __A, __mmask32 __U, __m512i __B) {
|
||||
return (__m512i)__builtin_ia32_selectw_512(
|
||||
(__mmask32)__U, (__v32hi)_mm512_popcnt_epi16(__B), (__v32hi)__A);
|
||||
}
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS_CONSTEXPR
|
||||
_mm512_popcnt_epi8(__m512i __A)
|
||||
{
|
||||
_mm512_maskz_popcnt_epi16(__mmask32 __U, __m512i __B) {
|
||||
return _mm512_mask_popcnt_epi16((__m512i)_mm512_setzero_si512(), __U, __B);
|
||||
}
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS_CONSTEXPR
|
||||
_mm512_popcnt_epi8(__m512i __A) {
|
||||
return (__m512i)__builtin_elementwise_popcount((__v64qu)__A);
|
||||
}
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_popcnt_epi8(__m512i __A, __mmask64 __U, __m512i __B)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_selectb_512((__mmask64) __U,
|
||||
(__v64qi) _mm512_popcnt_epi8(__B),
|
||||
(__v64qi) __A);
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS_CONSTEXPR
|
||||
_mm512_mask_popcnt_epi8(__m512i __A, __mmask64 __U, __m512i __B) {
|
||||
return (__m512i)__builtin_ia32_selectb_512(
|
||||
(__mmask64)__U, (__v64qi)_mm512_popcnt_epi8(__B), (__v64qi)__A);
|
||||
}
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS
|
||||
_mm512_maskz_popcnt_epi8(__mmask64 __U, __m512i __B)
|
||||
{
|
||||
return _mm512_mask_popcnt_epi8((__m512i) _mm512_setzero_si512(),
|
||||
__U,
|
||||
__B);
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS_CONSTEXPR
|
||||
_mm512_maskz_popcnt_epi8(__mmask64 __U, __m512i __B) {
|
||||
return _mm512_mask_popcnt_epi8((__m512i)_mm512_setzero_si512(), __U, __B);
|
||||
}
|
||||
|
||||
static __inline__ __mmask64 __DEFAULT_FN_ATTRS
|
||||
|
@ -1413,9 +1413,8 @@ _mm512_maskz_min_epu64 (__mmask8 __M, __m512i __A, __m512i __B)
|
||||
(__v8di)_mm512_setzero_si512());
|
||||
}
|
||||
|
||||
static __inline __m512i __DEFAULT_FN_ATTRS512
|
||||
_mm512_mul_epi32(__m512i __X, __m512i __Y)
|
||||
{
|
||||
static __inline __m512i __DEFAULT_FN_ATTRS512_CONSTEXPR
|
||||
_mm512_mul_epi32(__m512i __X, __m512i __Y) {
|
||||
return (__m512i)__builtin_ia32_pmuldq512((__v16si)__X, (__v16si) __Y);
|
||||
}
|
||||
|
||||
@ -1435,9 +1434,8 @@ _mm512_maskz_mul_epi32(__mmask8 __M, __m512i __X, __m512i __Y)
|
||||
(__v8di)_mm512_setzero_si512 ());
|
||||
}
|
||||
|
||||
static __inline __m512i __DEFAULT_FN_ATTRS512
|
||||
_mm512_mul_epu32(__m512i __X, __m512i __Y)
|
||||
{
|
||||
static __inline __m512i __DEFAULT_FN_ATTRS512_CONSTEXPR
|
||||
_mm512_mul_epu32(__m512i __X, __m512i __Y) {
|
||||
return (__m512i)__builtin_ia32_pmuludq512((__v16si)__X, (__v16si)__Y);
|
||||
}
|
||||
|
||||
@ -8935,36 +8933,28 @@ _mm512_mask_cvtpslo_pd (__m512d __W, __mmask8 __U, __m512 __A)
|
||||
return (__m512d) _mm512_mask_cvtps_pd(__W, __U, _mm512_castps512_ps256(__A));
|
||||
}
|
||||
|
||||
static __inline__ __m512d __DEFAULT_FN_ATTRS512
|
||||
_mm512_mask_mov_pd (__m512d __W, __mmask8 __U, __m512d __A)
|
||||
{
|
||||
return (__m512d) __builtin_ia32_selectpd_512 ((__mmask8) __U,
|
||||
(__v8df) __A,
|
||||
(__v8df) __W);
|
||||
static __inline__ __m512d __DEFAULT_FN_ATTRS512_CONSTEXPR
|
||||
_mm512_mask_mov_pd(__m512d __W, __mmask8 __U, __m512d __A) {
|
||||
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, (__v8df)__A,
|
||||
(__v8df)__W);
|
||||
}
|
||||
|
||||
static __inline__ __m512d __DEFAULT_FN_ATTRS512
|
||||
_mm512_maskz_mov_pd (__mmask8 __U, __m512d __A)
|
||||
{
|
||||
return (__m512d) __builtin_ia32_selectpd_512 ((__mmask8) __U,
|
||||
(__v8df) __A,
|
||||
(__v8df) _mm512_setzero_pd ());
|
||||
static __inline__ __m512d __DEFAULT_FN_ATTRS512_CONSTEXPR
|
||||
_mm512_maskz_mov_pd(__mmask8 __U, __m512d __A) {
|
||||
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, (__v8df)__A,
|
||||
(__v8df)_mm512_setzero_pd());
|
||||
}
|
||||
|
||||
static __inline__ __m512 __DEFAULT_FN_ATTRS512
|
||||
_mm512_mask_mov_ps (__m512 __W, __mmask16 __U, __m512 __A)
|
||||
{
|
||||
return (__m512) __builtin_ia32_selectps_512 ((__mmask16) __U,
|
||||
(__v16sf) __A,
|
||||
(__v16sf) __W);
|
||||
static __inline__ __m512 __DEFAULT_FN_ATTRS512_CONSTEXPR
|
||||
_mm512_mask_mov_ps(__m512 __W, __mmask16 __U, __m512 __A) {
|
||||
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, (__v16sf)__A,
|
||||
(__v16sf)__W);
|
||||
}
|
||||
|
||||
static __inline__ __m512 __DEFAULT_FN_ATTRS512
|
||||
_mm512_maskz_mov_ps (__mmask16 __U, __m512 __A)
|
||||
{
|
||||
return (__m512) __builtin_ia32_selectps_512 ((__mmask16) __U,
|
||||
(__v16sf) __A,
|
||||
(__v16sf) _mm512_setzero_ps ());
|
||||
static __inline__ __m512 __DEFAULT_FN_ATTRS512_CONSTEXPR
|
||||
_mm512_maskz_mov_ps(__mmask16 __U, __m512 __A) {
|
||||
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, (__v16sf)__A,
|
||||
(__v16sf)_mm512_setzero_ps());
|
||||
}
|
||||
|
||||
static __inline__ void __DEFAULT_FN_ATTRS512
|
||||
|
@ -33,91 +33,67 @@
|
||||
#endif
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
|
||||
_mm256_popcnt_epi16(__m256i __A)
|
||||
{
|
||||
_mm256_popcnt_epi16(__m256i __A) {
|
||||
return (__m256i)__builtin_elementwise_popcount((__v16hu)__A);
|
||||
}
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256
|
||||
_mm256_mask_popcnt_epi16(__m256i __A, __mmask16 __U, __m256i __B)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_selectw_256((__mmask16) __U,
|
||||
(__v16hi) _mm256_popcnt_epi16(__B),
|
||||
(__v16hi) __A);
|
||||
}
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256
|
||||
_mm256_maskz_popcnt_epi16(__mmask16 __U, __m256i __B)
|
||||
{
|
||||
return _mm256_mask_popcnt_epi16((__m256i) _mm256_setzero_si256(),
|
||||
__U,
|
||||
__B);
|
||||
}
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
|
||||
_mm_popcnt_epi16(__m128i __A)
|
||||
{
|
||||
return (__m128i)__builtin_elementwise_popcount((__v8hu)__A);
|
||||
}
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128
|
||||
_mm_mask_popcnt_epi16(__m128i __A, __mmask8 __U, __m128i __B)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_selectw_128((__mmask8) __U,
|
||||
(__v8hi) _mm_popcnt_epi16(__B),
|
||||
(__v8hi) __A);
|
||||
}
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128
|
||||
_mm_maskz_popcnt_epi16(__mmask8 __U, __m128i __B)
|
||||
{
|
||||
return _mm_mask_popcnt_epi16((__m128i) _mm_setzero_si128(),
|
||||
__U,
|
||||
__B);
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
|
||||
_mm256_mask_popcnt_epi16(__m256i __A, __mmask16 __U, __m256i __B) {
|
||||
return (__m256i)__builtin_ia32_selectw_256(
|
||||
(__mmask16)__U, (__v16hi)_mm256_popcnt_epi16(__B), (__v16hi)__A);
|
||||
}
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
|
||||
_mm256_popcnt_epi8(__m256i __A)
|
||||
{
|
||||
return (__m256i)__builtin_elementwise_popcount((__v32qu)__A);
|
||||
}
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256
|
||||
_mm256_mask_popcnt_epi8(__m256i __A, __mmask32 __U, __m256i __B)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_selectb_256((__mmask32) __U,
|
||||
(__v32qi) _mm256_popcnt_epi8(__B),
|
||||
(__v32qi) __A);
|
||||
}
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256
|
||||
_mm256_maskz_popcnt_epi8(__mmask32 __U, __m256i __B)
|
||||
{
|
||||
return _mm256_mask_popcnt_epi8((__m256i) _mm256_setzero_si256(),
|
||||
__U,
|
||||
__B);
|
||||
_mm256_maskz_popcnt_epi16(__mmask16 __U, __m256i __B) {
|
||||
return _mm256_mask_popcnt_epi16((__m256i)_mm256_setzero_si256(), __U, __B);
|
||||
}
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
|
||||
_mm_popcnt_epi8(__m128i __A)
|
||||
{
|
||||
_mm_popcnt_epi16(__m128i __A) {
|
||||
return (__m128i)__builtin_elementwise_popcount((__v8hu)__A);
|
||||
}
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
|
||||
_mm_mask_popcnt_epi16(__m128i __A, __mmask8 __U, __m128i __B) {
|
||||
return (__m128i)__builtin_ia32_selectw_128(
|
||||
(__mmask8)__U, (__v8hi)_mm_popcnt_epi16(__B), (__v8hi)__A);
|
||||
}
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
|
||||
_mm_maskz_popcnt_epi16(__mmask8 __U, __m128i __B) {
|
||||
return _mm_mask_popcnt_epi16((__m128i)_mm_setzero_si128(), __U, __B);
|
||||
}
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
|
||||
_mm256_popcnt_epi8(__m256i __A) {
|
||||
return (__m256i)__builtin_elementwise_popcount((__v32qu)__A);
|
||||
}
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
|
||||
_mm256_mask_popcnt_epi8(__m256i __A, __mmask32 __U, __m256i __B) {
|
||||
return (__m256i)__builtin_ia32_selectb_256(
|
||||
(__mmask32)__U, (__v32qi)_mm256_popcnt_epi8(__B), (__v32qi)__A);
|
||||
}
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
|
||||
_mm256_maskz_popcnt_epi8(__mmask32 __U, __m256i __B) {
|
||||
return _mm256_mask_popcnt_epi8((__m256i)_mm256_setzero_si256(), __U, __B);
|
||||
}
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
|
||||
_mm_popcnt_epi8(__m128i __A) {
|
||||
return (__m128i)__builtin_elementwise_popcount((__v16qu)__A);
|
||||
}
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128
|
||||
_mm_mask_popcnt_epi8(__m128i __A, __mmask16 __U, __m128i __B)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_selectb_128((__mmask16) __U,
|
||||
(__v16qi) _mm_popcnt_epi8(__B),
|
||||
(__v16qi) __A);
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
|
||||
_mm_mask_popcnt_epi8(__m128i __A, __mmask16 __U, __m128i __B) {
|
||||
return (__m128i)__builtin_ia32_selectb_128(
|
||||
(__mmask16)__U, (__v16qi)_mm_popcnt_epi8(__B), (__v16qi)__A);
|
||||
}
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128
|
||||
_mm_maskz_popcnt_epi8(__mmask16 __U, __m128i __B)
|
||||
{
|
||||
return _mm_mask_popcnt_epi8((__m128i) _mm_setzero_si128(),
|
||||
__U,
|
||||
__B);
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
|
||||
_mm_maskz_popcnt_epi8(__mmask16 __U, __m128i __B) {
|
||||
return _mm_mask_popcnt_epi8((__m128i)_mm_setzero_si128(), __U, __B);
|
||||
}
|
||||
|
||||
static __inline__ __mmask32 __DEFAULT_FN_ATTRS256
|
||||
|
@ -8264,68 +8264,52 @@ _mm256_maskz_moveldup_ps (__mmask8 __U, __m256 __A)
|
||||
(__v4si)_mm_shuffle_epi32((A), (I)), \
|
||||
(__v4si)_mm_setzero_si128()))
|
||||
|
||||
static __inline__ __m128d __DEFAULT_FN_ATTRS128
|
||||
_mm_mask_mov_pd (__m128d __W, __mmask8 __U, __m128d __A)
|
||||
{
|
||||
return (__m128d) __builtin_ia32_selectpd_128 ((__mmask8) __U,
|
||||
(__v2df) __A,
|
||||
(__v2df) __W);
|
||||
static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR
|
||||
_mm_mask_mov_pd(__m128d __W, __mmask8 __U, __m128d __A) {
|
||||
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)__A,
|
||||
(__v2df)__W);
|
||||
}
|
||||
|
||||
static __inline__ __m128d __DEFAULT_FN_ATTRS128
|
||||
_mm_maskz_mov_pd (__mmask8 __U, __m128d __A)
|
||||
{
|
||||
return (__m128d) __builtin_ia32_selectpd_128 ((__mmask8) __U,
|
||||
(__v2df) __A,
|
||||
(__v2df) _mm_setzero_pd ());
|
||||
static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR
|
||||
_mm_maskz_mov_pd(__mmask8 __U, __m128d __A) {
|
||||
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)__A,
|
||||
(__v2df)_mm_setzero_pd());
|
||||
}
|
||||
|
||||
static __inline__ __m256d __DEFAULT_FN_ATTRS256
|
||||
_mm256_mask_mov_pd (__m256d __W, __mmask8 __U, __m256d __A)
|
||||
{
|
||||
return (__m256d) __builtin_ia32_selectpd_256 ((__mmask8) __U,
|
||||
(__v4df) __A,
|
||||
(__v4df) __W);
|
||||
static __inline__ __m256d __DEFAULT_FN_ATTRS256_CONSTEXPR
|
||||
_mm256_mask_mov_pd(__m256d __W, __mmask8 __U, __m256d __A) {
|
||||
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)__A,
|
||||
(__v4df)__W);
|
||||
}
|
||||
|
||||
static __inline__ __m256d __DEFAULT_FN_ATTRS256
|
||||
_mm256_maskz_mov_pd (__mmask8 __U, __m256d __A)
|
||||
{
|
||||
return (__m256d) __builtin_ia32_selectpd_256 ((__mmask8) __U,
|
||||
(__v4df) __A,
|
||||
(__v4df) _mm256_setzero_pd ());
|
||||
static __inline__ __m256d __DEFAULT_FN_ATTRS256_CONSTEXPR
|
||||
_mm256_maskz_mov_pd(__mmask8 __U, __m256d __A) {
|
||||
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)__A,
|
||||
(__v4df)_mm256_setzero_pd());
|
||||
}
|
||||
|
||||
static __inline__ __m128 __DEFAULT_FN_ATTRS128
|
||||
_mm_mask_mov_ps (__m128 __W, __mmask8 __U, __m128 __A)
|
||||
{
|
||||
return (__m128) __builtin_ia32_selectps_128 ((__mmask8) __U,
|
||||
(__v4sf) __A,
|
||||
(__v4sf) __W);
|
||||
static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR
|
||||
_mm_mask_mov_ps(__m128 __W, __mmask8 __U, __m128 __A) {
|
||||
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)__A,
|
||||
(__v4sf)__W);
|
||||
}
|
||||
|
||||
static __inline__ __m128 __DEFAULT_FN_ATTRS128
|
||||
_mm_maskz_mov_ps (__mmask8 __U, __m128 __A)
|
||||
{
|
||||
return (__m128) __builtin_ia32_selectps_128 ((__mmask8) __U,
|
||||
(__v4sf) __A,
|
||||
(__v4sf) _mm_setzero_ps ());
|
||||
static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR
|
||||
_mm_maskz_mov_ps(__mmask8 __U, __m128 __A) {
|
||||
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)__A,
|
||||
(__v4sf)_mm_setzero_ps());
|
||||
}
|
||||
|
||||
static __inline__ __m256 __DEFAULT_FN_ATTRS256
|
||||
_mm256_mask_mov_ps (__m256 __W, __mmask8 __U, __m256 __A)
|
||||
{
|
||||
return (__m256) __builtin_ia32_selectps_256 ((__mmask8) __U,
|
||||
(__v8sf) __A,
|
||||
(__v8sf) __W);
|
||||
static __inline__ __m256 __DEFAULT_FN_ATTRS256_CONSTEXPR
|
||||
_mm256_mask_mov_ps(__m256 __W, __mmask8 __U, __m256 __A) {
|
||||
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)__A,
|
||||
(__v8sf)__W);
|
||||
}
|
||||
|
||||
static __inline__ __m256 __DEFAULT_FN_ATTRS256
|
||||
_mm256_maskz_mov_ps (__mmask8 __U, __m256 __A)
|
||||
{
|
||||
return (__m256) __builtin_ia32_selectps_256 ((__mmask8) __U,
|
||||
(__v8sf) __A,
|
||||
(__v8sf) _mm256_setzero_ps ());
|
||||
static __inline__ __m256 __DEFAULT_FN_ATTRS256_CONSTEXPR
|
||||
_mm256_maskz_mov_ps(__mmask8 __U, __m256 __A) {
|
||||
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)__A,
|
||||
(__v8sf)_mm256_setzero_ps());
|
||||
}
|
||||
|
||||
static __inline__ __m128 __DEFAULT_FN_ATTRS128
|
||||
@ -8388,7 +8372,6 @@ _mm256_maskz_cvtph_ps (__mmask8 __U, __m128i __A)
|
||||
#define _mm256_mask_cvtps_ph _mm256_mask_cvt_roundps_ph
|
||||
#define _mm256_maskz_cvtps_ph _mm256_maskz_cvt_roundps_ph
|
||||
|
||||
|
||||
#undef __DEFAULT_FN_ATTRS128
|
||||
#undef __DEFAULT_FN_ATTRS256
|
||||
#undef __DEFAULT_FN_ATTRS256_CONSTEXPR
|
||||
|
@ -16,19 +16,19 @@
|
||||
#define __AVX512VPOPCNTDQINTRIN_H
|
||||
|
||||
/* Define the default attributes for the functions in this file. */
|
||||
#if defined(__cplusplus) && (__cplusplus >= 201103L)
|
||||
#define __DEFAULT_FN_ATTRS \
|
||||
__attribute__((__always_inline__, __nodebug__, \
|
||||
__target__("avx512vpopcntdq,evex512"), \
|
||||
__min_vector_width__(512))) constexpr
|
||||
#else
|
||||
#define __DEFAULT_FN_ATTRS \
|
||||
__attribute__((__always_inline__, __nodebug__, \
|
||||
__target__("avx512vpopcntdq,evex512"), \
|
||||
__min_vector_width__(512)))
|
||||
|
||||
#if defined(__cplusplus) && (__cplusplus >= 201103L)
|
||||
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS constexpr
|
||||
#else
|
||||
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS
|
||||
#endif
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS_CONSTEXPR
|
||||
_mm512_popcnt_epi64(__m512i __A) {
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_popcnt_epi64(__m512i __A) {
|
||||
return (__m512i)__builtin_elementwise_popcount((__v8du)__A);
|
||||
}
|
||||
|
||||
@ -43,8 +43,7 @@ _mm512_maskz_popcnt_epi64(__mmask8 __U, __m512i __A) {
|
||||
return _mm512_mask_popcnt_epi64((__m512i)_mm512_setzero_si512(), __U, __A);
|
||||
}
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS_CONSTEXPR
|
||||
_mm512_popcnt_epi32(__m512i __A) {
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_popcnt_epi32(__m512i __A) {
|
||||
return (__m512i)__builtin_elementwise_popcount((__v16su)__A);
|
||||
}
|
||||
|
||||
@ -60,6 +59,5 @@ _mm512_maskz_popcnt_epi32(__mmask16 __U, __m512i __A) {
|
||||
}
|
||||
|
||||
#undef __DEFAULT_FN_ATTRS
|
||||
#undef __DEFAULT_FN_ATTRS_CONSTEXPR
|
||||
|
||||
#endif
|
||||
|
@ -16,6 +16,17 @@
|
||||
#define __AVX512VPOPCNTDQVLINTRIN_H
|
||||
|
||||
/* Define the default attributes for the functions in this file. */
|
||||
|
||||
#if defined(__cplusplus) && (__cplusplus >= 201103L)
|
||||
#define __DEFAULT_FN_ATTRS128 \
|
||||
__attribute__((__always_inline__, __nodebug__, \
|
||||
__target__("avx512vpopcntdq,avx512vl,no-evex512"), \
|
||||
__min_vector_width__(128))) constexpr
|
||||
#define __DEFAULT_FN_ATTRS256 \
|
||||
__attribute__((__always_inline__, __nodebug__, \
|
||||
__target__("avx512vpopcntdq,avx512vl,no-evex512"), \
|
||||
__min_vector_width__(256))) constexpr
|
||||
#else
|
||||
#define __DEFAULT_FN_ATTRS128 \
|
||||
__attribute__((__always_inline__, __nodebug__, \
|
||||
__target__("avx512vpopcntdq,avx512vl,no-evex512"), \
|
||||
@ -24,17 +35,9 @@
|
||||
__attribute__((__always_inline__, __nodebug__, \
|
||||
__target__("avx512vpopcntdq,avx512vl,no-evex512"), \
|
||||
__min_vector_width__(256)))
|
||||
|
||||
#if defined(__cplusplus) && (__cplusplus >= 201103L)
|
||||
#define __DEFAULT_FN_ATTRS128_CONSTEXPR __DEFAULT_FN_ATTRS128 constexpr
|
||||
#define __DEFAULT_FN_ATTRS256_CONSTEXPR __DEFAULT_FN_ATTRS256 constexpr
|
||||
#else
|
||||
#define __DEFAULT_FN_ATTRS128_CONSTEXPR __DEFAULT_FN_ATTRS128
|
||||
#define __DEFAULT_FN_ATTRS256_CONSTEXPR __DEFAULT_FN_ATTRS256
|
||||
#endif
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
|
||||
_mm_popcnt_epi64(__m128i __A) {
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_popcnt_epi64(__m128i __A) {
|
||||
return (__m128i)__builtin_elementwise_popcount((__v2du)__A);
|
||||
}
|
||||
|
||||
@ -49,8 +52,7 @@ _mm_maskz_popcnt_epi64(__mmask8 __U, __m128i __A) {
|
||||
return _mm_mask_popcnt_epi64((__m128i)_mm_setzero_si128(), __U, __A);
|
||||
}
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
|
||||
_mm_popcnt_epi32(__m128i __A) {
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_popcnt_epi32(__m128i __A) {
|
||||
return (__m128i)__builtin_elementwise_popcount((__v4su)__A);
|
||||
}
|
||||
|
||||
@ -65,7 +67,7 @@ _mm_maskz_popcnt_epi32(__mmask8 __U, __m128i __A) {
|
||||
return _mm_mask_popcnt_epi32((__m128i)_mm_setzero_si128(), __U, __A);
|
||||
}
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256
|
||||
_mm256_popcnt_epi64(__m256i __A) {
|
||||
return (__m256i)__builtin_elementwise_popcount((__v4du)__A);
|
||||
}
|
||||
@ -81,7 +83,7 @@ _mm256_maskz_popcnt_epi64(__mmask8 __U, __m256i __A) {
|
||||
return _mm256_mask_popcnt_epi64((__m256i)_mm256_setzero_si256(), __U, __A);
|
||||
}
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256
|
||||
_mm256_popcnt_epi32(__m256i __A) {
|
||||
return (__m256i)__builtin_elementwise_popcount((__v8su)__A);
|
||||
}
|
||||
@ -99,7 +101,5 @@ _mm256_maskz_popcnt_epi32(__mmask8 __U, __m256i __A) {
|
||||
|
||||
#undef __DEFAULT_FN_ATTRS128
|
||||
#undef __DEFAULT_FN_ATTRS256
|
||||
#undef __DEFAULT_FN_ATTRS128_CONSTEXPR
|
||||
#undef __DEFAULT_FN_ATTRS256_CONSTEXPR
|
||||
|
||||
#endif
|
||||
|
@ -62,6 +62,9 @@ typedef __bf16 __m128bh __attribute__((__vector_size__(16), __aligned__(16)));
|
||||
|
||||
#define __trunc64(x) \
|
||||
(__m64) __builtin_shufflevector((__v2di)(x), __extension__(__v2di){}, 0)
|
||||
#define __zext128(x) \
|
||||
(__m128i) __builtin_shufflevector((__v2si)(x), __extension__(__v2si){}, 0, \
|
||||
1, 2, 3)
|
||||
#define __anyext128(x) \
|
||||
(__m128i) __builtin_shufflevector((__v2si)(x), __extension__(__v2si){}, 0, \
|
||||
1, -1, -1)
|
||||
@ -2445,9 +2448,10 @@ _mm_mullo_epi16(__m128i __a, __m128i __b) {
|
||||
/// \param __b
|
||||
/// A 64-bit integer containing one of the source operands.
|
||||
/// \returns A 64-bit integer vector containing the product of both operands.
|
||||
static __inline__ __m64 __DEFAULT_FN_ATTRS _mm_mul_su32(__m64 __a, __m64 __b) {
|
||||
return __trunc64(__builtin_ia32_pmuludq128((__v4si)__anyext128(__a),
|
||||
(__v4si)__anyext128(__b)));
|
||||
static __inline__ __m64 __DEFAULT_FN_ATTRS_CONSTEXPR _mm_mul_su32(__m64 __a,
|
||||
__m64 __b) {
|
||||
return __trunc64(__builtin_ia32_pmuludq128((__v4si)__zext128(__a),
|
||||
(__v4si)__zext128(__b)));
|
||||
}
|
||||
|
||||
/// Multiplies 32-bit unsigned integer values contained in the lower
|
||||
@ -2463,8 +2467,8 @@ static __inline__ __m64 __DEFAULT_FN_ATTRS _mm_mul_su32(__m64 __a, __m64 __b) {
|
||||
/// \param __b
|
||||
/// A [2 x i64] vector containing one of the source operands.
|
||||
/// \returns A [2 x i64] vector containing the product of both operands.
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_mul_epu32(__m128i __a,
|
||||
__m128i __b) {
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS_CONSTEXPR
|
||||
_mm_mul_epu32(__m128i __a, __m128i __b) {
|
||||
return __builtin_ia32_pmuludq128((__v4si)__a, (__v4si)__b);
|
||||
}
|
||||
|
||||
|
@ -567,8 +567,8 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_mullo_epi32(__m128i __V1,
|
||||
/// A 128-bit vector of [4 x i32].
|
||||
/// \returns A 128-bit vector of [2 x i64] containing the products of both
|
||||
/// operands.
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_mul_epi32(__m128i __V1,
|
||||
__m128i __V2) {
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS_CONSTEXPR
|
||||
_mm_mul_epi32(__m128i __V1, __m128i __V2) {
|
||||
return (__m128i)__builtin_ia32_pmuldq128((__v4si)__V1, (__v4si)__V2);
|
||||
}
|
||||
|
||||
|
@ -174,8 +174,6 @@ void Lexer::InitLexer(const char *BufStart, const char *BufPtr,
|
||||
ExtendedTokenMode = 0;
|
||||
|
||||
NewLinePtr = nullptr;
|
||||
|
||||
IsFirstPPToken = true;
|
||||
}
|
||||
|
||||
/// Lexer constructor - Create a new lexer object for the specified buffer
|
||||
@ -3225,7 +3223,6 @@ std::optional<Token> Lexer::peekNextPPToken() {
|
||||
bool atStartOfLine = IsAtStartOfLine;
|
||||
bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
|
||||
bool leadingSpace = HasLeadingSpace;
|
||||
bool isFirstPPToken = IsFirstPPToken;
|
||||
|
||||
Token Tok;
|
||||
Lex(Tok);
|
||||
@ -3236,7 +3233,6 @@ std::optional<Token> Lexer::peekNextPPToken() {
|
||||
HasLeadingSpace = leadingSpace;
|
||||
IsAtStartOfLine = atStartOfLine;
|
||||
IsAtPhysicalStartOfLine = atPhysicalStartOfLine;
|
||||
IsFirstPPToken = isFirstPPToken;
|
||||
// Restore the lexer back to non-skipping mode.
|
||||
LexingRawMode = false;
|
||||
|
||||
@ -3726,11 +3722,6 @@ bool Lexer::Lex(Token &Result) {
|
||||
HasLeadingEmptyMacro = false;
|
||||
}
|
||||
|
||||
if (IsFirstPPToken) {
|
||||
Result.setFlag(Token::FirstPPToken);
|
||||
IsFirstPPToken = false;
|
||||
}
|
||||
|
||||
bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
|
||||
IsAtPhysicalStartOfLine = false;
|
||||
bool isRawLex = isLexingRawMode();
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "clang/Lex/MacroArgs.h"
|
||||
#include "clang/Lex/MacroInfo.h"
|
||||
#include "clang/Lex/ModuleLoader.h"
|
||||
#include "clang/Lex/NoTrivialPPDirectiveTracer.h"
|
||||
#include "clang/Lex/Pragma.h"
|
||||
#include "clang/Lex/PreprocessingRecord.h"
|
||||
#include "clang/Lex/PreprocessorLexer.h"
|
||||
@ -247,8 +248,6 @@ void Preprocessor::DumpToken(const Token &Tok, bool DumpFlags) const {
|
||||
llvm::errs() << " [LeadingSpace]";
|
||||
if (Tok.isExpandDisabled())
|
||||
llvm::errs() << " [ExpandDisabled]";
|
||||
if (Tok.isFirstPPToken())
|
||||
llvm::errs() << " [First pp-token]";
|
||||
if (Tok.needsCleaning()) {
|
||||
const char *Start = SourceMgr.getCharacterData(Tok.getLocation());
|
||||
llvm::errs() << " [UnClean='" << StringRef(Start, Tok.getLength())
|
||||
@ -577,8 +576,11 @@ void Preprocessor::EnterMainSourceFile() {
|
||||
// export module M; // error: module declaration must occur
|
||||
// // at the start of the translation unit.
|
||||
if (getLangOpts().CPlusPlusModules) {
|
||||
auto Tracer = std::make_unique<NoTrivialPPDirectiveTracer>(*this);
|
||||
DirTracer = Tracer.get();
|
||||
addPPCallbacks(std::move(Tracer));
|
||||
std::optional<Token> FirstPPTok = CurLexer->peekNextPPToken();
|
||||
if (FirstPPTok && FirstPPTok->isFirstPPToken())
|
||||
if (FirstPPTok)
|
||||
FirstPPTokenLoc = FirstPPTok->getLocation();
|
||||
}
|
||||
}
|
||||
@ -940,6 +942,8 @@ void Preprocessor::Lex(Token &Result) {
|
||||
StdCXXImportSeqState.handleHeaderName();
|
||||
break;
|
||||
case tok::kw_export:
|
||||
if (hasSeenNoTrivialPPDirective())
|
||||
Result.setFlag(Token::HasSeenNoTrivialPPDirective);
|
||||
TrackGMFState.handleExport();
|
||||
StdCXXImportSeqState.handleExport();
|
||||
ModuleDeclState.handleExport();
|
||||
@ -968,6 +972,8 @@ void Preprocessor::Lex(Token &Result) {
|
||||
}
|
||||
break;
|
||||
} else if (Result.getIdentifierInfo() == getIdentifierInfo("module")) {
|
||||
if (hasSeenNoTrivialPPDirective())
|
||||
Result.setFlag(Token::HasSeenNoTrivialPPDirective);
|
||||
TrackGMFState.handleModule(StdCXXImportSeqState.afterTopLevelSeq());
|
||||
ModuleDeclState.handleModule();
|
||||
break;
|
||||
@ -1682,3 +1688,31 @@ const char *Preprocessor::getCheckPoint(FileID FID, const char *Start) const {
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Preprocessor::hasSeenNoTrivialPPDirective() const {
|
||||
return DirTracer && DirTracer->hasSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
bool NoTrivialPPDirectiveTracer::hasSeenNoTrivialPPDirective() const {
|
||||
return SeenNoTrivialPPDirective;
|
||||
}
|
||||
|
||||
void NoTrivialPPDirectiveTracer::setSeenNoTrivialPPDirective() {
|
||||
if (InMainFile && !SeenNoTrivialPPDirective)
|
||||
SeenNoTrivialPPDirective = true;
|
||||
}
|
||||
|
||||
void NoTrivialPPDirectiveTracer::LexedFileChanged(
|
||||
FileID FID, LexedFileChangeReason Reason,
|
||||
SrcMgr::CharacteristicKind FileType, FileID PrevFID, SourceLocation Loc) {
|
||||
InMainFile = (FID == PP.getSourceManager().getMainFileID());
|
||||
}
|
||||
|
||||
void NoTrivialPPDirectiveTracer::MacroExpands(const Token &MacroNameTok,
|
||||
const MacroDefinition &MD,
|
||||
SourceRange Range,
|
||||
const MacroArgs *Args) {
|
||||
// FIXME: Does only enable builtin macro expansion make sense?
|
||||
if (!MD.getMacroInfo()->isBuiltinMacro())
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
@ -2363,9 +2363,10 @@ Parser::ParseModuleDecl(Sema::ModuleImportState &ImportState) {
|
||||
// Parse a global-module-fragment, if present.
|
||||
if (getLangOpts().CPlusPlusModules && Tok.is(tok::semi)) {
|
||||
SourceLocation SemiLoc = ConsumeToken();
|
||||
if (!Introducer.isFirstPPToken()) {
|
||||
if (ImportState != Sema::ModuleImportState::FirstDecl ||
|
||||
Introducer.hasSeenNoTrivialPPDirective()) {
|
||||
Diag(StartLoc, diag::err_global_module_introducer_not_at_start)
|
||||
<< SourceRange(StartLoc, SemiLoc);
|
||||
<< SourceRange(StartLoc, SemiLoc);
|
||||
return nullptr;
|
||||
}
|
||||
if (MDK == Sema::ModuleDeclKind::Interface) {
|
||||
@ -2420,7 +2421,8 @@ Parser::ParseModuleDecl(Sema::ModuleImportState &ImportState) {
|
||||
ExpectAndConsumeSemi(diag::err_module_expected_semi);
|
||||
|
||||
return Actions.ActOnModuleDecl(StartLoc, ModuleLoc, MDK, Path, Partition,
|
||||
ImportState, Introducer.isFirstPPToken());
|
||||
ImportState,
|
||||
Introducer.hasSeenNoTrivialPPDirective());
|
||||
}
|
||||
|
||||
Decl *Parser::ParseModuleImport(SourceLocation AtLoc,
|
||||
|
@ -2780,6 +2780,31 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
namespace clang::lifetimes {
|
||||
namespace {
|
||||
class LifetimeSafetyReporterImpl : public LifetimeSafetyReporter {
|
||||
|
||||
public:
|
||||
LifetimeSafetyReporterImpl(Sema &S) : S(S) {}
|
||||
|
||||
void reportUseAfterFree(const Expr *IssueExpr, const Expr *UseExpr,
|
||||
SourceLocation FreeLoc, Confidence C) override {
|
||||
S.Diag(IssueExpr->getExprLoc(),
|
||||
C == Confidence::Definite
|
||||
? diag::warn_lifetime_safety_loan_expires_permissive
|
||||
: diag::warn_lifetime_safety_loan_expires_strict)
|
||||
<< IssueExpr->getEndLoc();
|
||||
S.Diag(FreeLoc, diag::note_lifetime_safety_destroyed_here);
|
||||
S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
|
||||
<< UseExpr->getEndLoc();
|
||||
}
|
||||
|
||||
private:
|
||||
Sema &S;
|
||||
};
|
||||
} // namespace
|
||||
} // namespace clang::lifetimes
|
||||
|
||||
void clang::sema::AnalysisBasedWarnings::IssueWarnings(
|
||||
TranslationUnitDecl *TU) {
|
||||
if (!TU)
|
||||
@ -3029,8 +3054,10 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
|
||||
// TODO: Enable lifetime safety analysis for other languages once it is
|
||||
// stable.
|
||||
if (EnableLifetimeSafetyAnalysis && S.getLangOpts().CPlusPlus) {
|
||||
if (AC.getCFG())
|
||||
lifetimes::runLifetimeSafetyAnalysis(AC);
|
||||
if (AC.getCFG()) {
|
||||
lifetimes::LifetimeSafetyReporterImpl LifetimeSafetyReporter(S);
|
||||
lifetimes::runLifetimeSafetyAnalysis(AC, &LifetimeSafetyReporter);
|
||||
}
|
||||
}
|
||||
// Check for violations of "called once" parameter properties.
|
||||
if (S.getLangOpts().ObjC && !S.getLangOpts().CPlusPlus &&
|
||||
|
@ -265,10 +265,11 @@ Sema::DeclGroupPtrTy
|
||||
Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
|
||||
ModuleDeclKind MDK, ModuleIdPath Path,
|
||||
ModuleIdPath Partition, ModuleImportState &ImportState,
|
||||
bool IntroducerIsFirstPPToken) {
|
||||
bool SeenNoTrivialPPDirective) {
|
||||
assert(getLangOpts().CPlusPlusModules &&
|
||||
"should only have module decl in standard C++ modules");
|
||||
|
||||
bool IsFirstDecl = ImportState == ModuleImportState::FirstDecl;
|
||||
bool SeenGMF = ImportState == ModuleImportState::GlobalFragment;
|
||||
// If any of the steps here fail, we count that as invalidating C++20
|
||||
// module state;
|
||||
@ -336,7 +337,8 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
|
||||
|
||||
// In C++20, A module directive may only appear as the first preprocessing
|
||||
// tokens in a file (excluding the global module fragment.).
|
||||
if (getLangOpts().CPlusPlusModules && !IntroducerIsFirstPPToken && !SeenGMF) {
|
||||
if (getLangOpts().CPlusPlusModules &&
|
||||
(!IsFirstDecl || SeenNoTrivialPPDirective) && !SeenGMF) {
|
||||
Diag(ModuleLoc, diag::err_module_decl_not_at_start);
|
||||
SourceLocation BeginLoc = PP.getMainFileFirstPPTokenLoc();
|
||||
Diag(BeginLoc, diag::note_global_module_introducer_missing)
|
||||
|
@ -5669,7 +5669,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
||||
};
|
||||
Function->setDeclarationNameLoc(NameLocPointsToPattern());
|
||||
|
||||
EnterExpressionEvaluationContext EvalContext(
|
||||
EnterExpressionEvaluationContextForFunction EvalContext(
|
||||
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
|
||||
|
||||
Qualifiers ThisTypeQuals;
|
||||
|
@ -21,6 +21,27 @@
|
||||
#error "huh?"
|
||||
#endif
|
||||
|
||||
|
||||
inline constexpr void* operator new(__SIZE_TYPE__, void* p) noexcept { return p; }
|
||||
namespace std {
|
||||
using size_t = decltype(sizeof(0));
|
||||
template<typename T> struct allocator {
|
||||
constexpr T *allocate(size_t N) {
|
||||
return (T*)__builtin_operator_new(sizeof(T) * N); // #alloc
|
||||
}
|
||||
constexpr void deallocate(void *p, __SIZE_TYPE__) {
|
||||
__builtin_operator_delete(p);
|
||||
}
|
||||
};
|
||||
template<typename T, typename... Args>
|
||||
constexpr T* construct_at(T* p, Args&&... args) { return ::new((void*)p) T(static_cast<Args&&>(args)...); }
|
||||
|
||||
template<typename T>
|
||||
constexpr void destroy_at(T* p) {
|
||||
p->~T();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
typedef decltype(sizeof(int)) size_t;
|
||||
extern size_t wcslen(const wchar_t *p);
|
||||
@ -1767,6 +1788,28 @@ namespace WithinLifetime {
|
||||
}
|
||||
} xstd; // both-error {{is not a constant expression}} \
|
||||
// both-note {{in call to}}
|
||||
|
||||
consteval bool test_dynamic(bool read_after_deallocate) {
|
||||
std::allocator<int> a;
|
||||
int* p = a.allocate(1);
|
||||
// a.allocate starts the lifetime of an array,
|
||||
// the complete object of *p has started its lifetime
|
||||
if (__builtin_is_within_lifetime(p))
|
||||
return false;
|
||||
std::construct_at(p);
|
||||
if (!__builtin_is_within_lifetime(p))
|
||||
return false;
|
||||
std::destroy_at(p);
|
||||
if (__builtin_is_within_lifetime(p))
|
||||
return false;
|
||||
a.deallocate(p, 1);
|
||||
if (read_after_deallocate)
|
||||
__builtin_is_within_lifetime(p); // both-note {{read of heap allocated object that has been deleted}}
|
||||
return true;
|
||||
}
|
||||
static_assert(test_dynamic(false));
|
||||
static_assert(test_dynamic(true)); // both-error {{not an integral constant expression}} \
|
||||
// both-note {{in call to}}
|
||||
}
|
||||
|
||||
#ifdef __SIZEOF_INT128__
|
||||
|
87
clang/test/AST/ByteCode/builtin-object-size-codegen.cpp
Normal file
87
clang/test/AST/ByteCode/builtin-object-size-codegen.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
void foo() {
|
||||
struct A { char buf[16]; };
|
||||
struct B : A {};
|
||||
struct C { int i; B bs[1]; } *c;
|
||||
|
||||
int gi;
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
|
||||
gi = __builtin_object_size(&c->bs[0], 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
|
||||
gi = __builtin_object_size(&c->bs[0], 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 false)
|
||||
gi = __builtin_object_size(&c->bs[0], 2);
|
||||
// CHECK: store i32 16
|
||||
gi = __builtin_object_size(&c->bs[0], 3);
|
||||
}
|
||||
|
||||
|
||||
void foo2() {
|
||||
struct A { int a; };
|
||||
struct B { int b; };
|
||||
struct C: public A, public B {};
|
||||
|
||||
C c;
|
||||
|
||||
int gi;
|
||||
// CHECK: store i32 8
|
||||
gi = __builtin_object_size(&c, 0);
|
||||
// CHECK: store i32 8
|
||||
gi = __builtin_object_size((A*)&c, 0);
|
||||
// CHECK: store i32 4
|
||||
gi = __builtin_object_size((B*)&c, 0);
|
||||
|
||||
// CHECK: store i32 8
|
||||
gi = __builtin_object_size((char*)&c, 0);
|
||||
// CHECK: store i32 8
|
||||
gi = __builtin_object_size((char*)(A*)&c, 0);
|
||||
// CHECK: store i32 4
|
||||
gi = __builtin_object_size((char*)(B*)&c, 0);
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
double c[0];
|
||||
float f;
|
||||
} foofoo0_t;
|
||||
|
||||
unsigned babar0(foofoo0_t *f) {
|
||||
// CHECK: ret i32 0
|
||||
return __builtin_object_size(f->c, 1);
|
||||
}
|
||||
|
||||
void test2() {
|
||||
struct A { char buf[16]; };
|
||||
struct B : A {};
|
||||
struct C { int i; B bs[1]; } *c;
|
||||
|
||||
int gi;
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
|
||||
gi = __builtin_object_size(&c->bs[0], 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
|
||||
gi = __builtin_object_size(&c->bs[0], 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 false)
|
||||
gi = __builtin_object_size(&c->bs[0], 2);
|
||||
// CHECK: store i32 16
|
||||
gi = __builtin_object_size(&c->bs[0], 3);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
|
||||
gi = __builtin_object_size((A*)&c->bs[0], 0);
|
||||
// CHECK: store i32 16
|
||||
gi = __builtin_object_size((A*)&c->bs[0], 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 false)
|
||||
gi = __builtin_object_size(&c->bs[0].buf[0], 2);
|
||||
// CHECK: store i32 16
|
||||
gi = __builtin_object_size(&c->bs[0].buf[0], 3);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
|
||||
gi = __builtin_object_size(&c->bs[0].buf[0], 0);
|
||||
// CHECK: store i32 16
|
||||
gi = __builtin_object_size(&c->bs[0].buf[0], 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 false)
|
||||
gi = __builtin_object_size(&c->bs[0].buf[0], 2);
|
||||
// CHECK: store i32 16
|
||||
gi = __builtin_object_size(&c->bs[0].buf[0], 3);
|
||||
}
|
@ -132,8 +132,50 @@ void Test_TemplatedFunctionVariadic(int arg, ...);
|
||||
// CHECK-NEXT: ParagraphComment
|
||||
// CHECK-NEXT: TextComment{{.*}} Text=" More arguments"
|
||||
|
||||
/// \param[out] Aaa <summary>Short summary</summary>
|
||||
int Test_HTMLSummaryTag(int Aaa);
|
||||
// CHECK: FunctionDecl{{.*}}Test_HTMLSummaryTag
|
||||
// CHECK: ParamCommandComment{{.*}} [out] explicitly Param="Aaa"
|
||||
// CHECK-NEXT: ParagraphComment
|
||||
// CHECK: HTMLStartTagComment{{.*}} Name="summary"
|
||||
// CHECK-NEXT: TextComment{{.*}} Text="Short summary"
|
||||
// CHECK-NEXT: HTMLEndTagComment{{.*}} Name="summary"
|
||||
|
||||
/// \thread_safe test for underscore in special command
|
||||
int Test_UnderscoreInSpecialCommand;
|
||||
// CHECK: VarDecl{{.*}}Test_UnderscoreInSpecialCommand 'int'
|
||||
// CHECK: InlineCommandComment{{.*}} Name="thread_safe" RenderNormal
|
||||
// CHECK-NEXT: TextComment{{.*}} Text=" test for underscore in special command"
|
||||
|
||||
/// <details>
|
||||
/// <summary>
|
||||
/// Summary
|
||||
/// </summary>
|
||||
/// <p>Details</p>
|
||||
/// </details>
|
||||
///
|
||||
/// Some <mark>highlighting</mark>
|
||||
///
|
||||
/// <figure>
|
||||
/// <img src="pic.jpg">
|
||||
/// <figcaption>Figure 1</figcaption>
|
||||
/// </figure>
|
||||
int Test_AdditionalHTMLTags(int Aaa);
|
||||
// CHECK: FunctionDecl{{.*}}Test_AdditionalHTMLTags 'int (int)'
|
||||
// CHECK: HTMLStartTagComment{{.*}} Name="details"
|
||||
// CHECK: HTMLStartTagComment{{.*}} Name="summary"
|
||||
// CHECK-NEXT: TextComment{{.*}} Text=" Summary"
|
||||
// CHECK: HTMLEndTagComment{{.*}} Name="summary"
|
||||
// CHECK: HTMLStartTagComment{{.*}} Name="p"
|
||||
// CHECK-NEXT: TextComment{{.*}} Text="Details"
|
||||
// CHECK-NEXT: HTMLEndTagComment{{.*}} Name="p"
|
||||
// CHECK: HTMLEndTagComment{{.*}} Name="details"
|
||||
// CHECK: HTMLStartTagComment{{.*}} Name="mark"
|
||||
// CHECK-NEXT: TextComment{{.*}} Text="highlighting"
|
||||
// CHECK-NEXT: HTMLEndTagComment{{.*}} Name="mark"
|
||||
// CHECK: HTMLStartTagComment{{.*}} Name="figure"
|
||||
// CHECK: HTMLStartTagComment{{.*}} Name="img" Attrs: "src="pic.jpg"
|
||||
// CHECK: HTMLStartTagComment{{.*}} Name="figcaption"
|
||||
// CHECK-NEXT: TextComment{{.*}} Text="Figure 1"
|
||||
// CHECK-NEXT: HTMLEndTagComment{{.*}} Name="figcaption"
|
||||
// CHECK: HTMLEndTagComment{{.*}} Name="figure"
|
||||
|
571
clang/test/CIR/CodeGenOpenACC/combined-firstprivate-clause.cpp
Normal file
571
clang/test/CIR/CodeGenOpenACC/combined-firstprivate-clause.cpp
Normal file
@ -0,0 +1,571 @@
|
||||
// RUN: %clang_cc1 -fopenacc -triple x86_64-linux-gnu -Wno-openacc-self-if-potential-conflict -emit-cir -fclangir -triple x86_64-linux-pc %s -o - | FileCheck %s
|
||||
|
||||
struct NoCopyConstruct {};
|
||||
|
||||
struct CopyConstruct {
|
||||
CopyConstruct() = default;
|
||||
CopyConstruct(const CopyConstruct&);
|
||||
};
|
||||
|
||||
struct NonDefaultCtor {
|
||||
NonDefaultCtor();
|
||||
};
|
||||
|
||||
struct HasDtor {
|
||||
~HasDtor();
|
||||
};
|
||||
|
||||
// CHECK: acc.firstprivate.recipe @firstprivatization__ZTSA5_7HasDtor : !cir.ptr<!cir.array<!rec_HasDtor x 5>> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_HasDtor x 5>> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !cir.array<!rec_HasDtor x 5>, !cir.ptr<!cir.array<!rec_HasDtor x 5>>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!cir.array<!rec_HasDtor x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!rec_HasDtor x 5>> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
//
|
||||
// CHECK-NEXT: } destroy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_HasDtor x 5>> {{.*}}):
|
||||
// CHECK-NEXT: %[[LAST_IDX:.*]] = cir.const #cir.int<4> : !u64i
|
||||
// CHECK-NEXT: %[[ARRPTR:.*]] = cir.cast(array_to_ptrdecay, %[[ARG]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>), !cir.ptr<!rec_HasDtor>
|
||||
// CHECK-NEXT: %[[ELEM:.*]] = cir.ptr_stride(%[[ARRPTR]] : !cir.ptr<!rec_HasDtor>, %[[LAST_IDX]] : !u64i), !cir.ptr<!rec_HasDtor>
|
||||
// CHECK-NEXT: %[[ITR:.*]] = cir.alloca !cir.ptr<!rec_HasDtor>, !cir.ptr<!cir.ptr<!rec_HasDtor>>, ["__array_idx"]
|
||||
// CHECK-NEXT: cir.store %[[ELEM]], %[[ITR]] : !cir.ptr<!rec_HasDtor>, !cir.ptr<!cir.ptr<!rec_HasDtor>>
|
||||
// CHECK-NEXT: cir.do {
|
||||
// CHECK-NEXT: %[[ELEM_LOAD:.*]] = cir.load %[[ITR]] : !cir.ptr<!cir.ptr<!rec_HasDtor>>, !cir.ptr<!rec_HasDtor>
|
||||
// CHECK-NEXT: cir.call @_ZN7HasDtorD1Ev(%[[ELEM_LOAD]]) nothrow : (!cir.ptr<!rec_HasDtor>) -> ()
|
||||
// CHECK-NEXT: %[[NEG_ONE:.*]] = cir.const #cir.int<-1> : !s64i
|
||||
// CHECK-NEXT: %[[PREVELEM:.*]] = cir.ptr_stride(%[[ELEM_LOAD]] : !cir.ptr<!rec_HasDtor>, %[[NEG_ONE]] : !s64i), !cir.ptr<!rec_HasDtor>
|
||||
// CHECK-NEXT: cir.store %[[PREVELEM]], %[[ITR]] : !cir.ptr<!rec_HasDtor>, !cir.ptr<!cir.ptr<!rec_HasDtor>>
|
||||
// CHECK-NEXT: cir.yield
|
||||
// CHECK-NEXT: } while {
|
||||
// CHECK-NEXT: %[[ELEM_LOAD:.*]] = cir.load %[[ITR]] : !cir.ptr<!cir.ptr<!rec_HasDtor>>, !cir.ptr<!rec_HasDtor>
|
||||
// CHECK-NEXT: %[[CMP:.*]] = cir.cmp(ne, %[[ELEM_LOAD]], %[[ARRPTR]]) : !cir.ptr<!rec_HasDtor>, !cir.bool
|
||||
// CHECK-NEXT: cir.condition(%[[CMP]])
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_14NonDefaultCtor : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {{.*}}):
|
||||
// CHECK-NEXT: %[[ALLOCA:.*]] = cir.alloca !cir.array<!rec_NonDefaultCtor x 5>, !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_13CopyConstruct : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !cir.array<!rec_CopyConstruct x 5>, !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_15NoCopyConstruct : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !cir.array<!rec_NoCopyConstruct x 5>, !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_f : !cir.ptr<!cir.array<!cir.float x 5>> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!cir.float x 5>> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !cir.array<!cir.float x 5>, !cir.ptr<!cir.array<!cir.float x 5>>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!cir.float x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!cir.float x 5>> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_i : !cir.ptr<!cir.array<!s32i x 5>> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!s32i x 5>> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !cir.array<!s32i x 5>, !cir.ptr<!cir.array<!s32i x 5>>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!s32i x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!s32i x 5>> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS7HasDtor : !cir.ptr<!rec_HasDtor> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !rec_HasDtor, !cir.ptr<!rec_HasDtor>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } destroy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
|
||||
// CHECK-NEXT: cir.call @_ZN7HasDtorD1Ev(%[[ARG]]) nothrow : (!cir.ptr<!rec_HasDtor>) -> ()
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS14NonDefaultCtor : !cir.ptr<!rec_NonDefaultCtor> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}):
|
||||
// CHECK-NEXT: %[[ALLOCA:.*]] = cir.alloca !rec_NonDefaultCtor, !cir.ptr<!rec_NonDefaultCtor>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS13CopyConstruct : !cir.ptr<!rec_CopyConstruct> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !rec_CopyConstruct, !cir.ptr<!rec_CopyConstruct>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS15NoCopyConstruct : !cir.ptr<!rec_NoCopyConstruct> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_NoCopyConstruct> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !rec_NoCopyConstruct, !cir.ptr<!rec_NoCopyConstruct>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_NoCopyConstruct> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_NoCopyConstruct> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSf : !cir.ptr<!cir.float> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.float> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !cir.float, !cir.ptr<!cir.float>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!cir.float> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.float> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSi : !cir.ptr<!s32i> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!s32i> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !s32i, !cir.ptr<!s32i>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!s32i> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!s32i> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
|
||||
extern "C" void acc_combined() {
|
||||
// CHECK: cir.func{{.*}} @acc_combined() {
|
||||
|
||||
int someInt;
|
||||
// CHECK-NEXT: %[[SOMEINT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["someInt"]
|
||||
float someFloat;
|
||||
// CHECK-NEXT: %[[SOMEFLOAT:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["someFloat"]
|
||||
NoCopyConstruct noCopy;
|
||||
// CHECK-NEXT: %[[NOCOPY:.*]] = cir.alloca !rec_NoCopyConstruct, !cir.ptr<!rec_NoCopyConstruct>, ["noCopy"]
|
||||
CopyConstruct hasCopy;
|
||||
// CHECK-NEXT: %[[HASCOPY:.*]] = cir.alloca !rec_CopyConstruct, !cir.ptr<!rec_CopyConstruct>, ["hasCopy"]
|
||||
NonDefaultCtor notDefCtor;
|
||||
// CHECK-NEXT: %[[NOTDEFCTOR:.*]] = cir.alloca !rec_NonDefaultCtor, !cir.ptr<!rec_NonDefaultCtor>, ["notDefCtor", init]
|
||||
HasDtor dtor;
|
||||
// CHECK-NEXT: %[[DTOR:.*]] = cir.alloca !rec_HasDtor, !cir.ptr<!rec_HasDtor>, ["dtor"]
|
||||
int someIntArr[5];
|
||||
// CHECK-NEXT: %[[INTARR:.*]] = cir.alloca !cir.array<!s32i x 5>, !cir.ptr<!cir.array<!s32i x 5>>, ["someIntArr"]
|
||||
float someFloatArr[5];
|
||||
// CHECK-NEXT: %[[FLOATARR:.*]] = cir.alloca !cir.array<!cir.float x 5>, !cir.ptr<!cir.array<!cir.float x 5>>, ["someFloatArr"]
|
||||
NoCopyConstruct noCopyArr[5];
|
||||
// CHECK-NEXT: %[[NOCOPYARR:.*]] = cir.alloca !cir.array<!rec_NoCopyConstruct x 5>, !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>, ["noCopyArr"]
|
||||
CopyConstruct hasCopyArr[5];
|
||||
// CHECK-NEXT: %[[HASCOPYARR:.*]] = cir.alloca !cir.array<!rec_CopyConstruct x 5>, !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>, ["hasCopyArr"]
|
||||
NonDefaultCtor notDefCtorArr[5];
|
||||
// CHECK-NEXT: %[[NOTDEFCTORARR:.*]] = cir.alloca !cir.array<!rec_NonDefaultCtor x 5>, !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>, ["notDefCtorArr", init]
|
||||
HasDtor dtorArr[5];
|
||||
// CHECK-NEXT: %[[DTORARR:.*]] = cir.alloca !cir.array<!rec_HasDtor x 5>, !cir.ptr<!cir.array<!rec_HasDtor x 5>>, ["dtorArr"]
|
||||
// CHECK-NEXT: cir.call @_ZN14NonDefaultCtorC1Ev(%[[NOTDEFCTOR]]) : (!cir.ptr<!rec_NonDefaultCtor>) -> ()
|
||||
|
||||
#pragma acc parallel loop firstprivate(someInt)
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[SOMEINT]] : !cir.ptr<!s32i>) -> !cir.ptr<!s32i> {name = "someInt"}
|
||||
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSi -> %[[PRIVATE]] : !cir.ptr<!s32i>) {
|
||||
// CHECK-NEXT: acc.loop combined(parallel)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc serial loop firstprivate(someFloat)
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[SOMEFLOAT]] : !cir.ptr<!cir.float>) -> !cir.ptr<!cir.float> {name = "someFloat"}
|
||||
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTSf -> %[[PRIVATE]] : !cir.ptr<!cir.float>) {
|
||||
// CHECK-NEXT: acc.loop combined(serial)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
|
||||
#pragma acc parallel loop firstprivate(noCopy)
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOCOPY]] : !cir.ptr<!rec_NoCopyConstruct>) -> !cir.ptr<!rec_NoCopyConstruct> {name = "noCopy"}
|
||||
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTS15NoCopyConstruct -> %[[PRIVATE]] : !cir.ptr<!rec_NoCopyConstruct>) {
|
||||
// CHECK-NEXT: acc.loop combined(parallel)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc serial loop firstprivate(hasCopy)
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[HASCOPY]] : !cir.ptr<!rec_CopyConstruct>) -> !cir.ptr<!rec_CopyConstruct> {name = "hasCopy"}
|
||||
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTS13CopyConstruct -> %[[PRIVATE]] : !cir.ptr<!rec_CopyConstruct>) {
|
||||
// CHECK-NEXT: acc.loop combined(serial)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc serial loop firstprivate(notDefCtor)
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTOR]] : !cir.ptr<!rec_NonDefaultCtor>) -> !cir.ptr<!rec_NonDefaultCtor> {name = "notDefCtor"}
|
||||
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTS14NonDefaultCtor -> %[[PRIVATE]] : !cir.ptr<!rec_NonDefaultCtor>) {
|
||||
// CHECK-NEXT: acc.loop combined(serial)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc serial loop firstprivate(dtor)
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[DTOR]] : !cir.ptr<!rec_HasDtor>) -> !cir.ptr<!rec_HasDtor> {name = "dtor"}
|
||||
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTS7HasDtor -> %[[PRIVATE]] : !cir.ptr<!rec_HasDtor>) {
|
||||
// CHECK-NEXT: acc.loop combined(serial)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
|
||||
#pragma acc parallel loop firstprivate(someInt, someFloat, noCopy, hasCopy, notDefCtor, dtor)
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK: %[[PRIVATE1:.*]] = acc.firstprivate varPtr(%[[SOMEINT]] : !cir.ptr<!s32i>) -> !cir.ptr<!s32i> {name = "someInt"}
|
||||
// CHECK-NEXT: %[[PRIVATE2:.*]] = acc.firstprivate varPtr(%[[SOMEFLOAT]] : !cir.ptr<!cir.float>) -> !cir.ptr<!cir.float> {name = "someFloat"}
|
||||
// CHECK-NEXT: %[[PRIVATE3:.*]] = acc.firstprivate varPtr(%[[NOCOPY]] : !cir.ptr<!rec_NoCopyConstruct>) -> !cir.ptr<!rec_NoCopyConstruct> {name = "noCopy"}
|
||||
// CHECK-NEXT: %[[PRIVATE4:.*]] = acc.firstprivate varPtr(%[[HASCOPY]] : !cir.ptr<!rec_CopyConstruct>) -> !cir.ptr<!rec_CopyConstruct> {name = "hasCopy"}
|
||||
// CHECK-NEXT: %[[PRIVATE5:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTOR]] : !cir.ptr<!rec_NonDefaultCtor>) -> !cir.ptr<!rec_NonDefaultCtor> {name = "notDefCtor"}
|
||||
// CHECK-NEXT: %[[PRIVATE6:.*]] = acc.firstprivate varPtr(%[[DTOR]] : !cir.ptr<!rec_HasDtor>) -> !cir.ptr<!rec_HasDtor> {name = "dtor"}
|
||||
// CHECK: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSi -> %[[PRIVATE1]] : !cir.ptr<!s32i>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSf -> %[[PRIVATE2]] : !cir.ptr<!cir.float>,
|
||||
// CHECK-SAME: @firstprivatization__ZTS15NoCopyConstruct -> %[[PRIVATE3]] : !cir.ptr<!rec_NoCopyConstruct>,
|
||||
// CHECK-SAME: @firstprivatization__ZTS13CopyConstruct -> %[[PRIVATE4]] : !cir.ptr<!rec_CopyConstruct>,
|
||||
// CHECK-SAME: @firstprivatization__ZTS14NonDefaultCtor -> %[[PRIVATE5]] : !cir.ptr<!rec_NonDefaultCtor>,
|
||||
// CHECK-SAME: @firstprivatization__ZTS7HasDtor -> %[[PRIVATE6]] : !cir.ptr<!rec_HasDtor>)
|
||||
// CHECK-NEXT: acc.loop combined(parallel)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
|
||||
#pragma acc serial loop firstprivate(someIntArr[1])
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[INTARR]] : !cir.ptr<!cir.array<!s32i x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!s32i x 5>> {name = "someIntArr[1]"}
|
||||
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTSA5_i -> %[[PRIVATE]] : !cir.ptr<!cir.array<!s32i x 5>>) {
|
||||
// CHECK-NEXT: acc.loop combined(serial)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc parallel loop firstprivate(someFloatArr[1])
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[FLOATARR]] : !cir.ptr<!cir.array<!cir.float x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!cir.float x 5>> {name = "someFloatArr[1]"}
|
||||
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_f -> %[[PRIVATE]] : !cir.ptr<!cir.array<!cir.float x 5>>) {
|
||||
// CHECK-NEXT: acc.loop combined(parallel)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc serial loop firstprivate(noCopyArr[1])
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOCOPYARR]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {name = "noCopyArr[1]"}
|
||||
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTSA5_15NoCopyConstruct -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) {
|
||||
// CHECK-NEXT: acc.loop combined(serial)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc parallel loop firstprivate(hasCopyArr[1])
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[HASCOPYARR]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {name = "hasCopyArr[1]"}
|
||||
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_13CopyConstruct -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) {
|
||||
// CHECK-NEXT: acc.loop combined(parallel)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc parallel loop firstprivate(notDefCtorArr[1])
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTORARR]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {name = "notDefCtorArr[1]"}
|
||||
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_14NonDefaultCtor -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) {
|
||||
// CHECK-NEXT: acc.loop combined(parallel)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc parallel loop firstprivate(dtorArr[1])
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[DTORARR]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_HasDtor x 5>> {name = "dtorArr[1]"}
|
||||
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_7HasDtor -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) {
|
||||
// CHECK-NEXT: acc.loop combined(parallel)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc serial loop firstprivate(someIntArr[1], someFloatArr[1], noCopyArr[1], hasCopyArr[1], notDefCtorArr[1], dtorArr[1])
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE1:.*]] = acc.firstprivate varPtr(%[[INTARR]] : !cir.ptr<!cir.array<!s32i x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!s32i x 5>> {name = "someIntArr[1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE2:.*]] = acc.firstprivate varPtr(%[[FLOATARR]] : !cir.ptr<!cir.array<!cir.float x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!cir.float x 5>> {name = "someFloatArr[1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE3:.*]] = acc.firstprivate varPtr(%[[NOCOPYARR]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {name = "noCopyArr[1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE4:.*]] = acc.firstprivate varPtr(%[[HASCOPYARR]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {name = "hasCopyArr[1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE5:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTORARR]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {name = "notDefCtorArr[1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE6:.*]] = acc.firstprivate varPtr(%[[DTORARR]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_HasDtor x 5>> {name = "dtorArr[1]"}
|
||||
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTSA5_i -> %[[PRIVATE1]] : !cir.ptr<!cir.array<!s32i x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_f -> %[[PRIVATE2]] : !cir.ptr<!cir.array<!cir.float x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_15NoCopyConstruct -> %[[PRIVATE3]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_13CopyConstruct -> %[[PRIVATE4]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_14NonDefaultCtor -> %[[PRIVATE5]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_7HasDtor -> %[[PRIVATE6]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>)
|
||||
// CHECK-NEXT: acc.loop combined(serial)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
|
||||
#pragma acc parallel loop firstprivate(someIntArr[1:1])
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[INTARR]] : !cir.ptr<!cir.array<!s32i x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!s32i x 5>> {name = "someIntArr[1:1]"}
|
||||
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_i -> %[[PRIVATE]] : !cir.ptr<!cir.array<!s32i x 5>>) {
|
||||
// CHECK-NEXT: acc.loop combined(parallel)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc serial loop firstprivate(someFloatArr[1:1])
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[FLOATARR]] : !cir.ptr<!cir.array<!cir.float x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!cir.float x 5>> {name = "someFloatArr[1:1]"}
|
||||
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTSA5_f -> %[[PRIVATE]] : !cir.ptr<!cir.array<!cir.float x 5>>) {
|
||||
// CHECK-NEXT: acc.loop combined(serial)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc parallel loop firstprivate(noCopyArr[1:1])
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOCOPYARR]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {name = "noCopyArr[1:1]"}
|
||||
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_15NoCopyConstruct -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) {
|
||||
// CHECK-NEXT: acc.loop combined(parallel)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc serial loop firstprivate(hasCopyArr[1:1])
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[HASCOPYARR]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {name = "hasCopyArr[1:1]"}
|
||||
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTSA5_13CopyConstruct -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) {
|
||||
// CHECK-NEXT: acc.loop combined(serial)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc parallel loop firstprivate(notDefCtorArr[1:1])
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTORARR]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {name = "notDefCtorArr[1:1]"}
|
||||
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_14NonDefaultCtor -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) {
|
||||
// CHECK-NEXT: acc.loop combined(parallel)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc parallel loop firstprivate(dtorArr[1:1])
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[DTORARR]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_HasDtor x 5>> {name = "dtorArr[1:1]"}
|
||||
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_7HasDtor -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) {
|
||||
// CHECK-NEXT: acc.loop combined(parallel)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc parallel loop firstprivate(someIntArr[1:1], someFloatArr[1:1], noCopyArr[1:1], hasCopyArr[1:1], notDefCtorArr[1:1], dtorArr[1:1])
|
||||
for(int i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE1:.*]] = acc.firstprivate varPtr(%[[INTARR]] : !cir.ptr<!cir.array<!s32i x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!s32i x 5>> {name = "someIntArr[1:1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE2:.*]] = acc.firstprivate varPtr(%[[FLOATARR]] : !cir.ptr<!cir.array<!cir.float x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!cir.float x 5>> {name = "someFloatArr[1:1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE3:.*]] = acc.firstprivate varPtr(%[[NOCOPYARR]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {name = "noCopyArr[1:1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE4:.*]] = acc.firstprivate varPtr(%[[HASCOPYARR]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {name = "hasCopyArr[1:1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE5:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTORARR]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {name = "notDefCtorArr[1:1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE6:.*]] = acc.firstprivate varPtr(%[[DTORARR]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_HasDtor x 5>> {name = "dtorArr[1:1]"}
|
||||
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_i -> %[[PRIVATE1]] : !cir.ptr<!cir.array<!s32i x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_f -> %[[PRIVATE2]] : !cir.ptr<!cir.array<!cir.float x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_15NoCopyConstruct -> %[[PRIVATE3]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_13CopyConstruct -> %[[PRIVATE4]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_14NonDefaultCtor -> %[[PRIVATE5]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_7HasDtor -> %[[PRIVATE6]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>)
|
||||
// CHECK-NEXT: acc.loop combined(parallel)
|
||||
// CHECK: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
// RUN: %clang_cc1 -fopenacc -triple x86_64-linux-gnu -Wno-openacc-self-if-potential-conflict -emit-cir -fclangir -triple x86_64-linux-pc %s -o - | FileCheck %s
|
||||
|
||||
struct CopyConstruct {
|
||||
CopyConstruct() = default;
|
||||
CopyConstruct(const CopyConstruct&);
|
||||
};
|
||||
|
||||
struct NonDefaultCtor {
|
||||
NonDefaultCtor();
|
||||
};
|
||||
|
||||
struct HasDtor {
|
||||
~HasDtor();
|
||||
};
|
||||
|
||||
// CHECK: acc.firstprivate.recipe @firstprivatization__ZTSi : !cir.ptr<!s32i> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!s32i> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !s32i, !cir.ptr<!s32i>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!s32i> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!s32i> {{.*}}):
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS7HasDtor : !cir.ptr<!rec_HasDtor> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !rec_HasDtor, !cir.ptr<!rec_HasDtor>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } destroy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
|
||||
// CHECK-NEXT: cir.call @_ZN7HasDtorD1Ev(%[[ARG]]) nothrow : (!cir.ptr<!rec_HasDtor>) -> ()
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS14NonDefaultCtor : !cir.ptr<!rec_NonDefaultCtor> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}):
|
||||
// CHECK-NEXT: %[[ALLOCA:.*]] = cir.alloca !rec_NonDefaultCtor, !cir.ptr<!rec_NonDefaultCtor>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}):
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS13CopyConstruct : !cir.ptr<!rec_CopyConstruct> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !rec_CopyConstruct, !cir.ptr<!rec_CopyConstruct>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}):
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
|
||||
template<typename T, typename U, typename V, typename W>
|
||||
void dependent_version(const T &cc, const U &ndc, const V &dtor, const W &someInt) {
|
||||
// CHECK: cir.func {{.*}}@_Z17dependent_versionI13CopyConstruct14NonDefaultCtor7HasDtoriEvRKT_RKT0_RKT1_RKT2_(%[[ARG0:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}, %[[ARG1:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}, %[[ARG2:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}, %[[ARG3:.*]]: !cir.ptr<!s32i> {{.*}}) {
|
||||
// CHECK-NEXT: %[[CC:.*]] = cir.alloca !cir.ptr<!rec_CopyConstruct>, !cir.ptr<!cir.ptr<!rec_CopyConstruct>>, ["cc", init, const]
|
||||
// CHECK-NEXT: %[[NDC:.*]] = cir.alloca !cir.ptr<!rec_NonDefaultCtor>, !cir.ptr<!cir.ptr<!rec_NonDefaultCtor>>, ["ndc", init, const]
|
||||
// CHECK-NEXT: %[[DTOR:.*]] = cir.alloca !cir.ptr<!rec_HasDtor>, !cir.ptr<!cir.ptr<!rec_HasDtor>>, ["dtor", init, const]
|
||||
// CHECK-NEXT: %[[SOMEINT:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["someInt", init, const]
|
||||
// % 3 = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["someInt", init, const]
|
||||
|
||||
#pragma acc parallel firstprivate(cc, ndc, dtor, someInt)
|
||||
;
|
||||
// CHECK: %[[PRIV_LOAD:.*]] = cir.load %[[CC]] : !cir.ptr<!cir.ptr<!rec_CopyConstruct>>, !cir.ptr<!rec_CopyConstruct>
|
||||
// CHECK-NEXT: %[[PRIVATE1:.*]] = acc.firstprivate varPtr(%[[PRIV_LOAD]] : !cir.ptr<!rec_CopyConstruct>) -> !cir.ptr<!rec_CopyConstruct> {name = "cc"}
|
||||
// CHECK-NEXT: %[[PRIV_LOAD:.*]] = cir.load %[[NDC]] : !cir.ptr<!cir.ptr<!rec_NonDefaultCtor>>, !cir.ptr<!rec_NonDefaultCtor>
|
||||
// CHECK-NEXT: %[[PRIVATE2:.*]] = acc.firstprivate varPtr(%[[PRIV_LOAD]] : !cir.ptr<!rec_NonDefaultCtor>) -> !cir.ptr<!rec_NonDefaultCtor> {name = "ndc"}
|
||||
// CHECK-NEXT: %[[PRIV_LOAD:.*]] = cir.load %[[DTOR]] : !cir.ptr<!cir.ptr<!rec_HasDtor>>, !cir.ptr<!rec_HasDtor>
|
||||
// CHECK-NEXT: %[[PRIVATE3:.*]] = acc.firstprivate varPtr(%[[PRIV_LOAD]] : !cir.ptr<!rec_HasDtor>) -> !cir.ptr<!rec_HasDtor> {name = "dtor"}
|
||||
// CHECK-NEXT: %[[PRIV_LOAD:.*]] = cir.load %[[SOMEINT]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
|
||||
// CHECK-NEXT: %[[PRIVATE4:.*]] = acc.firstprivate varPtr(%[[PRIV_LOAD]] : !cir.ptr<!s32i>) -> !cir.ptr<!s32i> {name = "someInt"}
|
||||
|
||||
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTS13CopyConstruct -> %[[PRIVATE1]] : !cir.ptr<!rec_CopyConstruct>,
|
||||
// CHECK-SAME: @firstprivatization__ZTS14NonDefaultCtor -> %[[PRIVATE2]] : !cir.ptr<!rec_NonDefaultCtor>,
|
||||
// CHECK-SAME: @firstprivatization__ZTS7HasDtor -> %[[PRIVATE3]] : !cir.ptr<!rec_HasDtor>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSi -> %[[PRIVATE4]] : !cir.ptr<!s32i>) {
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
}
|
||||
|
||||
void use() {
|
||||
CopyConstruct cc;
|
||||
NonDefaultCtor ndc;
|
||||
HasDtor dtor;
|
||||
int i;
|
||||
dependent_version(cc, ndc, dtor, i);
|
||||
}
|
508
clang/test/CIR/CodeGenOpenACC/compute-firstprivate-clause.cpp
Normal file
508
clang/test/CIR/CodeGenOpenACC/compute-firstprivate-clause.cpp
Normal file
@ -0,0 +1,508 @@
|
||||
// RUN: %clang_cc1 -fopenacc -triple x86_64-linux-gnu -Wno-openacc-self-if-potential-conflict -emit-cir -fclangir -triple x86_64-linux-pc %s -o - | FileCheck %s
|
||||
|
||||
struct NoCopyConstruct {};
|
||||
|
||||
struct CopyConstruct {
|
||||
CopyConstruct() = default;
|
||||
CopyConstruct(const CopyConstruct&);
|
||||
};
|
||||
|
||||
struct NonDefaultCtor {
|
||||
NonDefaultCtor();
|
||||
};
|
||||
|
||||
struct HasDtor {
|
||||
~HasDtor();
|
||||
};
|
||||
|
||||
// CHECK: acc.firstprivate.recipe @firstprivatization__ZTSA5_7HasDtor : !cir.ptr<!cir.array<!rec_HasDtor x 5>> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_HasDtor x 5>> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !cir.array<!rec_HasDtor x 5>, !cir.ptr<!cir.array<!rec_HasDtor x 5>>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!cir.array<!rec_HasDtor x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!rec_HasDtor x 5>> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
//
|
||||
// CHECK-NEXT: } destroy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_HasDtor x 5>> {{.*}}):
|
||||
// CHECK-NEXT: %[[LAST_IDX:.*]] = cir.const #cir.int<4> : !u64i
|
||||
// CHECK-NEXT: %[[ARRPTR:.*]] = cir.cast(array_to_ptrdecay, %[[ARG]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>), !cir.ptr<!rec_HasDtor>
|
||||
// CHECK-NEXT: %[[ELEM:.*]] = cir.ptr_stride(%[[ARRPTR]] : !cir.ptr<!rec_HasDtor>, %[[LAST_IDX]] : !u64i), !cir.ptr<!rec_HasDtor>
|
||||
// CHECK-NEXT: %[[ITR:.*]] = cir.alloca !cir.ptr<!rec_HasDtor>, !cir.ptr<!cir.ptr<!rec_HasDtor>>, ["__array_idx"]
|
||||
// CHECK-NEXT: cir.store %[[ELEM]], %[[ITR]] : !cir.ptr<!rec_HasDtor>, !cir.ptr<!cir.ptr<!rec_HasDtor>>
|
||||
// CHECK-NEXT: cir.do {
|
||||
// CHECK-NEXT: %[[ELEM_LOAD:.*]] = cir.load %[[ITR]] : !cir.ptr<!cir.ptr<!rec_HasDtor>>, !cir.ptr<!rec_HasDtor>
|
||||
// CHECK-NEXT: cir.call @_ZN7HasDtorD1Ev(%[[ELEM_LOAD]]) nothrow : (!cir.ptr<!rec_HasDtor>) -> ()
|
||||
// CHECK-NEXT: %[[NEG_ONE:.*]] = cir.const #cir.int<-1> : !s64i
|
||||
// CHECK-NEXT: %[[PREVELEM:.*]] = cir.ptr_stride(%[[ELEM_LOAD]] : !cir.ptr<!rec_HasDtor>, %[[NEG_ONE]] : !s64i), !cir.ptr<!rec_HasDtor>
|
||||
// CHECK-NEXT: cir.store %[[PREVELEM]], %[[ITR]] : !cir.ptr<!rec_HasDtor>, !cir.ptr<!cir.ptr<!rec_HasDtor>>
|
||||
// CHECK-NEXT: cir.yield
|
||||
// CHECK-NEXT: } while {
|
||||
// CHECK-NEXT: %[[ELEM_LOAD:.*]] = cir.load %[[ITR]] : !cir.ptr<!cir.ptr<!rec_HasDtor>>, !cir.ptr<!rec_HasDtor>
|
||||
// CHECK-NEXT: %[[CMP:.*]] = cir.cmp(ne, %[[ELEM_LOAD]], %[[ARRPTR]]) : !cir.ptr<!rec_HasDtor>, !cir.bool
|
||||
// CHECK-NEXT: cir.condition(%[[CMP]])
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_14NonDefaultCtor : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {{.*}}):
|
||||
// CHECK-NEXT: %[[ALLOCA:.*]] = cir.alloca !cir.array<!rec_NonDefaultCtor x 5>, !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_13CopyConstruct : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !cir.array<!rec_CopyConstruct x 5>, !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_15NoCopyConstruct : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !cir.array<!rec_NoCopyConstruct x 5>, !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_f : !cir.ptr<!cir.array<!cir.float x 5>> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!cir.float x 5>> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !cir.array<!cir.float x 5>, !cir.ptr<!cir.array<!cir.float x 5>>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!cir.float x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!cir.float x 5>> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_i : !cir.ptr<!cir.array<!s32i x 5>> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!s32i x 5>> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !cir.array<!s32i x 5>, !cir.ptr<!cir.array<!s32i x 5>>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!s32i x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!s32i x 5>> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS7HasDtor : !cir.ptr<!rec_HasDtor> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !rec_HasDtor, !cir.ptr<!rec_HasDtor>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } destroy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
|
||||
// CHECK-NEXT: cir.call @_ZN7HasDtorD1Ev(%[[ARG]]) nothrow : (!cir.ptr<!rec_HasDtor>) -> ()
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS14NonDefaultCtor : !cir.ptr<!rec_NonDefaultCtor> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}):
|
||||
// CHECK-NEXT: %[[ALLOCA:.*]] = cir.alloca !rec_NonDefaultCtor, !cir.ptr<!rec_NonDefaultCtor>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS13CopyConstruct : !cir.ptr<!rec_CopyConstruct> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !rec_CopyConstruct, !cir.ptr<!rec_CopyConstruct>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS15NoCopyConstruct : !cir.ptr<!rec_NoCopyConstruct> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_NoCopyConstruct> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !rec_NoCopyConstruct, !cir.ptr<!rec_NoCopyConstruct>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_NoCopyConstruct> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_NoCopyConstruct> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSf : !cir.ptr<!cir.float> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.float> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !cir.float, !cir.ptr<!cir.float>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!cir.float> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.float> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
//
|
||||
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSi : !cir.ptr<!s32i> init {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!s32i> {{.*}}):
|
||||
// CHECK-NEXT: cir.alloca !s32i, !cir.ptr<!s32i>, ["openacc.private.init"]
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } copy {
|
||||
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!s32i> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!s32i> {{.*}}):
|
||||
//
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: }
|
||||
|
||||
extern "C" void acc_compute() {
|
||||
// CHECK: cir.func{{.*}} @acc_compute() {
|
||||
|
||||
int someInt;
|
||||
// CHECK-NEXT: %[[SOMEINT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["someInt"]
|
||||
float someFloat;
|
||||
// CHECK-NEXT: %[[SOMEFLOAT:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["someFloat"]
|
||||
NoCopyConstruct noCopy;
|
||||
// CHECK-NEXT: %[[NOCOPY:.*]] = cir.alloca !rec_NoCopyConstruct, !cir.ptr<!rec_NoCopyConstruct>, ["noCopy"]
|
||||
CopyConstruct hasCopy;
|
||||
// CHECK-NEXT: %[[HASCOPY:.*]] = cir.alloca !rec_CopyConstruct, !cir.ptr<!rec_CopyConstruct>, ["hasCopy"]
|
||||
NonDefaultCtor notDefCtor;
|
||||
// CHECK-NEXT: %[[NOTDEFCTOR:.*]] = cir.alloca !rec_NonDefaultCtor, !cir.ptr<!rec_NonDefaultCtor>, ["notDefCtor", init]
|
||||
HasDtor dtor;
|
||||
// CHECK-NEXT: %[[DTOR:.*]] = cir.alloca !rec_HasDtor, !cir.ptr<!rec_HasDtor>, ["dtor"]
|
||||
int someIntArr[5];
|
||||
// CHECK-NEXT: %[[INTARR:.*]] = cir.alloca !cir.array<!s32i x 5>, !cir.ptr<!cir.array<!s32i x 5>>, ["someIntArr"]
|
||||
float someFloatArr[5];
|
||||
// CHECK-NEXT: %[[FLOATARR:.*]] = cir.alloca !cir.array<!cir.float x 5>, !cir.ptr<!cir.array<!cir.float x 5>>, ["someFloatArr"]
|
||||
NoCopyConstruct noCopyArr[5];
|
||||
// CHECK-NEXT: %[[NOCOPYARR:.*]] = cir.alloca !cir.array<!rec_NoCopyConstruct x 5>, !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>, ["noCopyArr"]
|
||||
CopyConstruct hasCopyArr[5];
|
||||
// CHECK-NEXT: %[[HASCOPYARR:.*]] = cir.alloca !cir.array<!rec_CopyConstruct x 5>, !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>, ["hasCopyArr"]
|
||||
NonDefaultCtor notDefCtorArr[5];
|
||||
// CHECK-NEXT: %[[NOTDEFCTORARR:.*]] = cir.alloca !cir.array<!rec_NonDefaultCtor x 5>, !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>, ["notDefCtorArr", init]
|
||||
HasDtor dtorArr[5];
|
||||
// CHECK-NEXT: %[[DTORARR:.*]] = cir.alloca !cir.array<!rec_HasDtor x 5>, !cir.ptr<!cir.array<!rec_HasDtor x 5>>, ["dtorArr"]
|
||||
// CHECK-NEXT: cir.call @_ZN14NonDefaultCtorC1Ev(%[[NOTDEFCTOR]]) : (!cir.ptr<!rec_NonDefaultCtor>) -> ()
|
||||
|
||||
#pragma acc parallel firstprivate(someInt)
|
||||
;
|
||||
// CHECK: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[SOMEINT]] : !cir.ptr<!s32i>) -> !cir.ptr<!s32i> {name = "someInt"}
|
||||
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSi -> %[[PRIVATE]] : !cir.ptr<!s32i>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc serial firstprivate(someFloat)
|
||||
;
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[SOMEFLOAT]] : !cir.ptr<!cir.float>) -> !cir.ptr<!cir.float> {name = "someFloat"}
|
||||
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTSf -> %[[PRIVATE]] : !cir.ptr<!cir.float>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
|
||||
#pragma acc parallel firstprivate(noCopy)
|
||||
;
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOCOPY]] : !cir.ptr<!rec_NoCopyConstruct>) -> !cir.ptr<!rec_NoCopyConstruct> {name = "noCopy"}
|
||||
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTS15NoCopyConstruct -> %[[PRIVATE]] : !cir.ptr<!rec_NoCopyConstruct>
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc serial firstprivate(hasCopy)
|
||||
;
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[HASCOPY]] : !cir.ptr<!rec_CopyConstruct>) -> !cir.ptr<!rec_CopyConstruct> {name = "hasCopy"}
|
||||
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTS13CopyConstruct -> %[[PRIVATE]] : !cir.ptr<!rec_CopyConstruct>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc serial firstprivate(notDefCtor)
|
||||
;
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTOR]] : !cir.ptr<!rec_NonDefaultCtor>) -> !cir.ptr<!rec_NonDefaultCtor> {name = "notDefCtor"}
|
||||
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTS14NonDefaultCtor -> %[[PRIVATE]] : !cir.ptr<!rec_NonDefaultCtor>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc serial firstprivate(dtor)
|
||||
;
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[DTOR]] : !cir.ptr<!rec_HasDtor>) -> !cir.ptr<!rec_HasDtor> {name = "dtor"}
|
||||
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTS7HasDtor -> %[[PRIVATE]] : !cir.ptr<!rec_HasDtor>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
|
||||
#pragma acc parallel firstprivate(someInt, someFloat, noCopy, hasCopy, notDefCtor, dtor)
|
||||
;
|
||||
// CHECK: %[[PRIVATE1:.*]] = acc.firstprivate varPtr(%[[SOMEINT]] : !cir.ptr<!s32i>) -> !cir.ptr<!s32i> {name = "someInt"}
|
||||
// CHECK-NEXT: %[[PRIVATE2:.*]] = acc.firstprivate varPtr(%[[SOMEFLOAT]] : !cir.ptr<!cir.float>) -> !cir.ptr<!cir.float> {name = "someFloat"}
|
||||
// CHECK-NEXT: %[[PRIVATE3:.*]] = acc.firstprivate varPtr(%[[NOCOPY]] : !cir.ptr<!rec_NoCopyConstruct>) -> !cir.ptr<!rec_NoCopyConstruct> {name = "noCopy"}
|
||||
// CHECK-NEXT: %[[PRIVATE4:.*]] = acc.firstprivate varPtr(%[[HASCOPY]] : !cir.ptr<!rec_CopyConstruct>) -> !cir.ptr<!rec_CopyConstruct> {name = "hasCopy"}
|
||||
// CHECK-NEXT: %[[PRIVATE5:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTOR]] : !cir.ptr<!rec_NonDefaultCtor>) -> !cir.ptr<!rec_NonDefaultCtor> {name = "notDefCtor"}
|
||||
// CHECK-NEXT: %[[PRIVATE6:.*]] = acc.firstprivate varPtr(%[[DTOR]] : !cir.ptr<!rec_HasDtor>) -> !cir.ptr<!rec_HasDtor> {name = "dtor"}
|
||||
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSi -> %[[PRIVATE1]] : !cir.ptr<!s32i>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSf -> %[[PRIVATE2]] : !cir.ptr<!cir.float>,
|
||||
// CHECK-SAME: @firstprivatization__ZTS15NoCopyConstruct -> %[[PRIVATE3]] : !cir.ptr<!rec_NoCopyConstruct>,
|
||||
// CHECK-SAME: @firstprivatization__ZTS13CopyConstruct -> %[[PRIVATE4]] : !cir.ptr<!rec_CopyConstruct>,
|
||||
// CHECK-SAME: @firstprivatization__ZTS14NonDefaultCtor -> %[[PRIVATE5]] : !cir.ptr<!rec_NonDefaultCtor>,
|
||||
// CHECK-SAME: @firstprivatization__ZTS7HasDtor -> %[[PRIVATE6]] : !cir.ptr<!rec_HasDtor>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
|
||||
#pragma acc serial firstprivate(someIntArr[1])
|
||||
;
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[INTARR]] : !cir.ptr<!cir.array<!s32i x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!s32i x 5>> {name = "someIntArr[1]"}
|
||||
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTSA5_i -> %[[PRIVATE]] : !cir.ptr<!cir.array<!s32i x 5>>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc parallel firstprivate(someFloatArr[1])
|
||||
;
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[FLOATARR]] : !cir.ptr<!cir.array<!cir.float x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!cir.float x 5>> {name = "someFloatArr[1]"}
|
||||
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_f -> %[[PRIVATE]] : !cir.ptr<!cir.array<!cir.float x 5>>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc serial firstprivate(noCopyArr[1])
|
||||
;
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOCOPYARR]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {name = "noCopyArr[1]"}
|
||||
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTSA5_15NoCopyConstruct -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc parallel firstprivate(hasCopyArr[1])
|
||||
;
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[HASCOPYARR]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {name = "hasCopyArr[1]"}
|
||||
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_13CopyConstruct -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc parallel firstprivate(notDefCtorArr[1])
|
||||
;
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTORARR]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {name = "notDefCtorArr[1]"}
|
||||
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_14NonDefaultCtor -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc parallel firstprivate(dtorArr[1])
|
||||
;
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[DTORARR]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_HasDtor x 5>> {name = "dtorArr[1]"}
|
||||
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_7HasDtor -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc serial firstprivate(someIntArr[1], someFloatArr[1], noCopyArr[1], hasCopyArr[1], notDefCtorArr[1], dtorArr[1])
|
||||
;
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE1:.*]] = acc.firstprivate varPtr(%[[INTARR]] : !cir.ptr<!cir.array<!s32i x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!s32i x 5>> {name = "someIntArr[1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE2:.*]] = acc.firstprivate varPtr(%[[FLOATARR]] : !cir.ptr<!cir.array<!cir.float x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!cir.float x 5>> {name = "someFloatArr[1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE3:.*]] = acc.firstprivate varPtr(%[[NOCOPYARR]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {name = "noCopyArr[1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE4:.*]] = acc.firstprivate varPtr(%[[HASCOPYARR]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {name = "hasCopyArr[1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE5:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTORARR]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {name = "notDefCtorArr[1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE6:.*]] = acc.firstprivate varPtr(%[[DTORARR]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_HasDtor x 5>> {name = "dtorArr[1]"}
|
||||
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTSA5_i -> %[[PRIVATE1]] : !cir.ptr<!cir.array<!s32i x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_f -> %[[PRIVATE2]] : !cir.ptr<!cir.array<!cir.float x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_15NoCopyConstruct -> %[[PRIVATE3]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_13CopyConstruct -> %[[PRIVATE4]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_14NonDefaultCtor -> %[[PRIVATE5]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_7HasDtor -> %[[PRIVATE6]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
|
||||
#pragma acc parallel firstprivate(someIntArr[1:1])
|
||||
;
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[INTARR]] : !cir.ptr<!cir.array<!s32i x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!s32i x 5>> {name = "someIntArr[1:1]"}
|
||||
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_i -> %[[PRIVATE]] : !cir.ptr<!cir.array<!s32i x 5>>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc serial firstprivate(someFloatArr[1:1])
|
||||
;
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[FLOATARR]] : !cir.ptr<!cir.array<!cir.float x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!cir.float x 5>> {name = "someFloatArr[1:1]"}
|
||||
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTSA5_f -> %[[PRIVATE]] : !cir.ptr<!cir.array<!cir.float x 5>>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc parallel firstprivate(noCopyArr[1:1])
|
||||
;
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOCOPYARR]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {name = "noCopyArr[1:1]"}
|
||||
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_15NoCopyConstruct -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc serial firstprivate(hasCopyArr[1:1])
|
||||
;
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[HASCOPYARR]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {name = "hasCopyArr[1:1]"}
|
||||
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTSA5_13CopyConstruct -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc parallel firstprivate(notDefCtorArr[1:1])
|
||||
;
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTORARR]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {name = "notDefCtorArr[1:1]"}
|
||||
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_14NonDefaultCtor -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc parallel firstprivate(dtorArr[1:1])
|
||||
;
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[DTORARR]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_HasDtor x 5>> {name = "dtorArr[1:1]"}
|
||||
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_7HasDtor -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
#pragma acc parallel firstprivate(someIntArr[1:1], someFloatArr[1:1], noCopyArr[1:1], hasCopyArr[1:1], notDefCtorArr[1:1], dtorArr[1:1])
|
||||
;
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE1:.*]] = acc.firstprivate varPtr(%[[INTARR]] : !cir.ptr<!cir.array<!s32i x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!s32i x 5>> {name = "someIntArr[1:1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE2:.*]] = acc.firstprivate varPtr(%[[FLOATARR]] : !cir.ptr<!cir.array<!cir.float x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!cir.float x 5>> {name = "someFloatArr[1:1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE3:.*]] = acc.firstprivate varPtr(%[[NOCOPYARR]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {name = "noCopyArr[1:1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE4:.*]] = acc.firstprivate varPtr(%[[HASCOPYARR]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {name = "hasCopyArr[1:1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE5:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTORARR]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {name = "notDefCtorArr[1:1]"}
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
||||
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
|
||||
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
|
||||
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
|
||||
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
|
||||
// CHECK-NEXT: %[[PRIVATE6:.*]] = acc.firstprivate varPtr(%[[DTORARR]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_HasDtor x 5>> {name = "dtorArr[1:1]"}
|
||||
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_i -> %[[PRIVATE1]] : !cir.ptr<!cir.array<!s32i x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_f -> %[[PRIVATE2]] : !cir.ptr<!cir.array<!cir.float x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_15NoCopyConstruct -> %[[PRIVATE3]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_13CopyConstruct -> %[[PRIVATE4]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_14NonDefaultCtor -> %[[PRIVATE5]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>,
|
||||
// CHECK-SAME: @firstprivatization__ZTSA5_7HasDtor -> %[[PRIVATE6]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>)
|
||||
// CHECK-NEXT: acc.yield
|
||||
// CHECK-NEXT: } loc
|
||||
}
|
@ -10,9 +10,6 @@ void HelloWorld(int *A, int *B, int *C, int N) {
|
||||
// expected-error@+1{{ClangIR code gen Not Yet Implemented: OpenACC Declare Construct}}
|
||||
#pragma acc declare create(A)
|
||||
|
||||
// expected-error@+1{{ClangIR code gen Not Yet Implemented: OpenACC Clause: firstprivate}}
|
||||
#pragma acc parallel loop firstprivate(A)
|
||||
for(int i = 0; i <5; ++i);
|
||||
// expected-error@+1{{ClangIR code gen Not Yet Implemented: OpenACC Clause: reduction}}
|
||||
#pragma acc parallel loop reduction(+:A)
|
||||
for(int i = 0; i <5; ++i);
|
||||
|
@ -115,7 +115,7 @@ void usage() {
|
||||
S(); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
|
||||
S('A'); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't let that S-Char go!}}
|
||||
S(1);
|
||||
S(2.2);
|
||||
S(2.2); // expected-warning {{ignoring temporary created by a constructor declared with 'gnu::warn_unused_result' attribute}}
|
||||
Y(); // expected-warning {{ignoring temporary of type 'Y' declared with 'nodiscard' attribute: Don't throw me away either!}}
|
||||
S s;
|
||||
ConvertTo{}; // expected-warning {{ignoring return value of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}}
|
||||
|
@ -1,8 +1,147 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: mkdir -p %t
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %s -verify -o %t/M.pcm
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/line.cpp -verify -o %t/line.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/gnu_line_marker.cpp -verify -o %t/gnu_line_marker.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/include.cpp -verify -o %t/include.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/ident.cpp -verify -o %t/ident.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_comment.cpp -verify -o %t/pragma_comment.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_mark.cpp -verify -o %t/pragma_mark.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_detect_mismatch.cpp -verify -o %t/pragma_detect_mismatch.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_clang_debug.cpp -verify -o %t/pragma_clang_debug.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_message.cpp -verify -o %t/pragma_message.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_gcc_warn.cpp -verify -o %t/pragma_gcc_warn.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_gcc_error.cpp -verify -o %t/pragma_gcc_error.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_diag_push_pop.cpp -verify -o %t/pragma_diag_push_pop.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_diag_ignore.cpp -verify -o %t/pragma_diag_ignore.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_opencl_ext.cpp -verify -o %t/pragma_opencl_ext.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_push_pop.cpp -verify -o %t/pragma_push_pop.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_exec_charset.cpp -verify -o %t/pragma_exec_charset.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_clang_assume_nonnull.cpp -verify -o %t/pragma_clang_assume_nonnull.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/marco_expand.cpp -DMACRO="" -verify -o %t/marco_expand.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/define.cpp -verify -o %t/define.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/undef.cpp -verify -o %t/undef.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/defined.cpp -verify -o %t/defined.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/has_embed.cpp -verify -o %t/has_embed.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/has_include.cpp -verify -o %t/has_include.pcm
|
||||
|
||||
//--- header.h
|
||||
#ifndef HEADER_H
|
||||
#define HEADER_H
|
||||
|
||||
#endif // HEADER_H
|
||||
|
||||
//--- line.cpp
|
||||
// expected-no-diagnostics
|
||||
#line 3
|
||||
export module M;
|
||||
|
||||
//--- gnu_line_marker.cpp
|
||||
// expected-no-diagnostics
|
||||
# 1 __FILE__ 1 3
|
||||
export module M;
|
||||
|
||||
//--- include.cpp
|
||||
#include "header.h" // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}}
|
||||
export module M; // expected-error {{module declaration must occur at the start of the translation unit}}
|
||||
|
||||
//--- ident.cpp
|
||||
// expected-no-diagnostics
|
||||
#ident "$Header:$"
|
||||
export module M;
|
||||
|
||||
//--- pragma_comment.cpp
|
||||
// expected-no-diagnostics
|
||||
#pragma comment(lib, "msvcrt.lib")
|
||||
export module M;
|
||||
|
||||
//--- pragma_mark.cpp
|
||||
// expected-no-diagnostics
|
||||
#pragma mark LLVM's world
|
||||
export module M;
|
||||
|
||||
//--- pragma_detect_mismatch.cpp
|
||||
// expected-no-diagnostics
|
||||
#pragma detect_mismatch("test", "1")
|
||||
export module M;
|
||||
|
||||
//--- pragma_clang_debug.cpp
|
||||
// expected-no-diagnostics
|
||||
#pragma clang __debug dump Test
|
||||
export module M;
|
||||
|
||||
//--- pragma_message.cpp
|
||||
#pragma message "test" // expected-warning {{test}}
|
||||
export module M;
|
||||
|
||||
//--- pragma_gcc_warn.cpp
|
||||
#pragma GCC warning "Foo" // expected-warning {{Foo}}
|
||||
export module M;
|
||||
|
||||
//--- pragma_gcc_error.cpp
|
||||
#pragma GCC error "Foo" // expected-error {{Foo}}
|
||||
export module M;
|
||||
|
||||
//--- pragma_diag_push_pop.cpp
|
||||
// expected-no-diagnostics
|
||||
#pragma gcc diagnostic push
|
||||
#pragma gcc diagnostic pop
|
||||
export module M;
|
||||
|
||||
//--- pragma_diag_ignore.cpp
|
||||
// expected-no-diagnostics
|
||||
#pragma GCC diagnostic ignored "-Wframe-larger-than"
|
||||
export module M;
|
||||
|
||||
//--- pragma_opencl_ext.cpp
|
||||
// expected-no-diagnostics
|
||||
#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
|
||||
export module M;
|
||||
|
||||
//--- pragma_push_pop.cpp
|
||||
// expected-no-diagnostics
|
||||
#pragma warning(push)
|
||||
#pragma warning(pop)
|
||||
export module M;
|
||||
|
||||
//--- pragma_exec_charset.cpp
|
||||
// expected-no-diagnostics
|
||||
#pragma execution_character_set(push, "UTF-8")
|
||||
#pragma execution_character_set(pop)
|
||||
export module M;
|
||||
|
||||
//--- pragma_clang_assume_nonnull.cpp
|
||||
// expected-no-diagnostics
|
||||
#pragma clang assume_nonnull begin
|
||||
#pragma clang assume_nonnull end
|
||||
export module M;
|
||||
|
||||
//--- marco_expand.cpp
|
||||
MACRO // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}}
|
||||
export module M; // expected-error {{module declaration must occur at the start of the translation unit}}
|
||||
|
||||
//--- define.cpp
|
||||
// This is a comment
|
||||
#define I32 int // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}}
|
||||
export module M; // expected-error {{module declaration must occur at the start of the translation unit}}
|
||||
export I32 i32;
|
||||
|
||||
//--- undef.cpp
|
||||
#undef FOO // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}}
|
||||
export module M; // expected-error {{module declaration must occur at the start of the translation unit}}
|
||||
|
||||
//--- defined.cpp
|
||||
#if defined(FOO) // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}}
|
||||
#endif
|
||||
export module M; // expected-error {{module declaration must occur at the start of the translation unit}}
|
||||
|
||||
//--- has_embed.cpp
|
||||
#if __has_embed(__FILE__ ext::token(0xB055)) // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}}
|
||||
#endif
|
||||
export module M; // expected-error {{module declaration must occur at the start of the translation unit}}
|
||||
|
||||
//--- has_include.cpp
|
||||
#if __has_include(<stdio.h>) || __has_include_next(<stdlib.h>) // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}} \
|
||||
// expected-warning {{#include_next in primary source file; will search from start of include path}}
|
||||
#endif
|
||||
export module M; // expected-error {{module declaration must occur at the start of the translation unit}}
|
||||
|
@ -239,5 +239,21 @@ void f2() {
|
||||
|
||||
}
|
||||
|
||||
namespace GH153884 {
|
||||
bool f1() {
|
||||
auto f = [](auto) { return true; };
|
||||
if constexpr (0)
|
||||
return f(1);
|
||||
return false;
|
||||
}
|
||||
bool f2() {
|
||||
auto f = [](auto x) { if (x) return 1.5; else return "wat"; };
|
||||
// expected-error@-1 {{'auto' in return type deduced as 'const char *' here but deduced as 'double' in earlier return statement}}
|
||||
if constexpr (0)
|
||||
return f(1);
|
||||
// expected-note@-1 {{in instantiation of function template specialization 'GH153884::f2()}}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,66 @@
|
||||
// REQUIRES: riscv-registered-target
|
||||
|
||||
// RUN: %clang_cc1 -triple riscv32 -target-feature +v \
|
||||
// RUN: -mvscale-min=2 -mvscale-max=2 -O2 -emit-llvm %s -o - \
|
||||
// RUN: | FileCheck %s
|
||||
// RUN: %clang_cc1 -triple riscv64 -target-feature +v \
|
||||
// RUN: -mvscale-min=2 -mvscale-max=2 -O2 -emit-llvm %s -o - \
|
||||
// RUN: | FileCheck %s
|
||||
|
||||
// Test RISC-V V-extension fixed-length vector inline assembly constraints.
|
||||
#include <riscv_vector.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef vbool1_t fixed_bool1_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen)));
|
||||
typedef vint32m1_t fixed_i32m1_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen)));
|
||||
typedef vint8mf2_t fixed_i8mf2_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen / 2)));
|
||||
|
||||
typedef bool bx2 __attribute__((ext_vector_type(16)));
|
||||
typedef int i32x2 __attribute__((ext_vector_type(2)));
|
||||
typedef char i8x4 __attribute__((ext_vector_type(4)));
|
||||
|
||||
fixed_i32m1_t test_vr(fixed_i32m1_t a) {
|
||||
// CHECK-LABEL: define{{.*}} @test_vr
|
||||
// CHECK: %0 = tail call <4 x i32> asm sideeffect "vadd.vv $0, $1, $2", "=^vr,^vr,^vr"(<4 x i32> %a, <4 x i32> %a)
|
||||
fixed_i32m1_t ret;
|
||||
asm volatile ("vadd.vv %0, %1, %2" : "=vr"(ret) : "vr"(a), "vr"(a));
|
||||
return ret;
|
||||
}
|
||||
|
||||
i32x2 test_vr2(i32x2 a) {
|
||||
// CHECK-LABEL: define{{.*}} @test_vr2
|
||||
// CHECK: %1 = tail call <2 x i32> asm sideeffect "vadd.vv $0, $1, $2", "=^vr,^vr,^vr"(<2 x i32> %0, <2 x i32> %0)
|
||||
i32x2 ret;
|
||||
asm volatile ("vadd.vv %0, %1, %2" : "=vr"(ret) : "vr"(a), "vr"(a));
|
||||
return ret;
|
||||
}
|
||||
|
||||
fixed_i8mf2_t test_vd(fixed_i8mf2_t a) {
|
||||
// CHECK-LABEL: define{{.*}} @test_vd
|
||||
// CHECK: %0 = tail call <8 x i8> asm sideeffect "vadd.vv $0, $1, $2", "=^vd,^vr,^vr"(<8 x i8> %a, <8 x i8> %a)
|
||||
fixed_i8mf2_t ret;
|
||||
asm volatile ("vadd.vv %0, %1, %2" : "=vd"(ret) : "vr"(a), "vr"(a));
|
||||
return ret;
|
||||
}
|
||||
|
||||
i8x4 test_vd2(i8x4 a) {
|
||||
// CHECK-LABEL: define{{.*}} @test_vd2
|
||||
// CHECK: %1 = tail call <4 x i8> asm sideeffect "vadd.vv $0, $1, $2", "=^vd,^vr,^vr"(<4 x i8> %0, <4 x i8> %0)
|
||||
i8x4 ret;
|
||||
asm volatile ("vadd.vv %0, %1, %2" : "=vd"(ret) : "vr"(a), "vr"(a));
|
||||
return ret;
|
||||
}
|
||||
|
||||
fixed_bool1_t test_vm(fixed_bool1_t a) {
|
||||
// CHECK-LABEL: define{{.*}} @test_vm
|
||||
// CHECK: %1 = tail call <16 x i8> asm sideeffect "vmand.mm $0, $1, $2", "=^vm,^vm,^vm"(<16 x i8> %a, <16 x i8> %a)
|
||||
fixed_bool1_t ret;
|
||||
asm volatile ("vmand.mm %0, %1, %2" : "=vm"(ret) : "vm"(a), "vm"(a));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void test_vm2(bx2 a) {
|
||||
// CHECK-LABEL: define{{.*}} @test_vm2
|
||||
// CHECK: tail call void asm sideeffect "dummy $0", "^vm"(<16 x i1> %a1)
|
||||
asm volatile ("dummy %0" :: "vm"(a));
|
||||
}
|
@ -920,6 +920,7 @@ __m256i test_mm256_mul_epi32(__m256i a, __m256i b) {
|
||||
// CHECK: mul <4 x i64> %{{.*}}, %{{.*}}
|
||||
return _mm256_mul_epi32(a, b);
|
||||
}
|
||||
TEST_CONSTEXPR(match_m256i(_mm256_mul_epi32((__m256i)(__v8si){+1, -2, +3, -4, +5, -6, +7, -8}, (__m256i)(__v8si){-16, -14, +12, +10, -8, +6, -4, +2}), -16, 36, -40, -28));
|
||||
|
||||
__m256i test_mm256_mul_epu32(__m256i a, __m256i b) {
|
||||
// CHECK-LABEL: test_mm256_mul_epu32
|
||||
@ -928,6 +929,7 @@ __m256i test_mm256_mul_epu32(__m256i a, __m256i b) {
|
||||
// CHECK: mul <4 x i64> %{{.*}}, %{{.*}}
|
||||
return _mm256_mul_epu32(a, b);
|
||||
}
|
||||
TEST_CONSTEXPR(match_m256i(_mm256_mul_epu32((__m256i)(__v8si){+1, -2, +3, -4, +5, -6, +7, -8}, (__m256i)(__v8si){-16, -14, +12, +10, -8, +6, -4, +2}), 4294967280, 36, 21474836440, 30064771044));
|
||||
|
||||
__m256i test_mm256_mulhi_epu16(__m256i a, __m256i b) {
|
||||
// CHECK-LABEL: test_mm256_mulhi_epu16
|
||||
|
@ -19,12 +19,15 @@ __m512i test_mm512_mask_popcnt_epi16(__m512i __A, __mmask32 __U, __m512i __B) {
|
||||
// CHECK: select <32 x i1> %{{[0-9]+}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
|
||||
return _mm512_mask_popcnt_epi16(__A, __U, __B);
|
||||
}
|
||||
TEST_CONSTEXPR(match_v32hi(_mm512_mask_popcnt_epi16(_mm512_set1_epi16(-1), 0xF0F0F0F0, (__m512i)(__v32hi){+5, -3, -10, +8, 0, -256, +256, -128, +3, +9, +15, +33, +63, +129, +511, +1025, +5, -3, -10, +8, 0, -256, +256, -128, +3, +9, +15, +33, +63, +129, +511, +1025}), -1, -1, -1, -1, 0, 8, 1, 9, -1, -1, -1, -1, 6, 2, 9, 2, -1, -1, -1, -1, 0, 8, 1, 9, -1, -1, -1, -1, 6, 2, 9, 2));
|
||||
|
||||
__m512i test_mm512_maskz_popcnt_epi16(__mmask32 __U, __m512i __B) {
|
||||
// CHECK-LABEL: test_mm512_maskz_popcnt_epi16
|
||||
// CHECK: @llvm.ctpop.v32i16
|
||||
// CHECK: select <32 x i1> %{{[0-9]+}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
|
||||
return _mm512_maskz_popcnt_epi16(__U, __B);
|
||||
}
|
||||
TEST_CONSTEXPR(match_v32hi(_mm512_maskz_popcnt_epi16(0x0F0F0F0F, (__m512i)(__v32hi){+5, -3, -10, +8, 0, -256, +256, -128, +3, +9, +15, +33, +63, +129, +511, +1025, +5, -3, -10, +8, 0, -256, +256, -128, +3, +9, +15, +33, +63, +129, +511, +1025}), 2, 15, 14, 1, 0, 0, 0, 0, 2, 2, 4, 2, 0, 0, 0, 0, 2, 15, 14, 1, 0, 0, 0, 0, 2, 2, 4, 2, 0, 0, 0, 0));
|
||||
|
||||
__m512i test_mm512_popcnt_epi8(__m512i __A) {
|
||||
// CHECK-LABEL: test_mm512_popcnt_epi8
|
||||
@ -39,12 +42,15 @@ __m512i test_mm512_mask_popcnt_epi8(__m512i __A, __mmask64 __U, __m512i __B) {
|
||||
// CHECK: select <64 x i1> %{{[0-9]+}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
|
||||
return _mm512_mask_popcnt_epi8(__A, __U, __B);
|
||||
}
|
||||
TEST_CONSTEXPR(match_v64qi(_mm512_mask_popcnt_epi8(_mm512_set1_epi8(-1), 0xF0F0F0F00F0F0F0FULL, (__m512i)(__v64qi){+5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73, +5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73, +5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73, +5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73}), 2, 7, 6, 1, -1, -1, -1, -1, 2, 2, 4, 2, -1, -1, -1, -1, 2, 7, 6, 1, -1, -1, -1, -1, 2, 2, 4, 2, -1, -1, -1, -1, -1, -1, -1, -1, 0, 4, 1, 4, -1, -1, -1, -1, 6, 2, 4, 3, -1, -1, -1, -1, 0, 4, 1, 4, -1, -1, -1, -1, 6, 2, 4, 3));
|
||||
|
||||
__m512i test_mm512_maskz_popcnt_epi8(__mmask64 __U, __m512i __B) {
|
||||
// CHECK-LABEL: test_mm512_maskz_popcnt_epi8
|
||||
// CHECK: @llvm.ctpop.v64i8
|
||||
// CHECK: select <64 x i1> %{{[0-9]+}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
|
||||
return _mm512_maskz_popcnt_epi8(__U, __B);
|
||||
}
|
||||
TEST_CONSTEXPR(match_v64qi(_mm512_maskz_popcnt_epi8(0x0F0F0F0FF0F0F0F0ULL, (__m512i)(__v64qi){+5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73, +5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73, +5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73, +5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73}), 0, 0, 0, 0, 0, 4, 1, 4, 0, 0, 0, 0, 6, 2, 4, 3, 0, 0, 0, 0, 0, 4, 1, 4, 0, 0, 0, 0, 6, 2, 4, 3, 2, 7, 6, 1, 0, 0, 0, 0, 2, 2, 4, 2, 0, 0, 0, 0, 2, 7, 6, 1, 0, 0, 0, 0, 2, 2, 4, 2, 0, 0, 0, 0));
|
||||
|
||||
__mmask64 test_mm512_mask_bitshuffle_epi64_mask(__mmask64 __U, __m512i __A, __m512i __B) {
|
||||
// CHECK-LABEL: test_mm512_mask_bitshuffle_epi64_mask
|
||||
|
@ -3027,6 +3027,7 @@ __m512i test_mm512_mul_epi32(__m512i __A, __m512i __B) {
|
||||
//CHECK: mul <8 x i64> %{{.*}}, %{{.*}}
|
||||
return _mm512_mul_epi32(__A,__B);
|
||||
}
|
||||
TEST_CONSTEXPR(match_v8di(_mm512_mul_epi32((__m512i)(__v16si){+1, -2, +3, -4, +5, -6, +7, -8, +9, -10, +11, -12, +13, -14, +15, -16}, (__m512i)(__v16si){-32, -30, +28, +26, -24, -22, +20, +18, -16, -14, +12, +10, -8, +6, -4, +2}), -32, 84, -120, 140, -144, 132, -104, -60));
|
||||
|
||||
__m512i test_mm512_maskz_mul_epi32 (__mmask8 __k,__m512i __A, __m512i __B) {
|
||||
//CHECK-LABEL: test_mm512_maskz_mul_epi32
|
||||
@ -3057,6 +3058,7 @@ __m512i test_mm512_mul_epu32 (__m512i __A, __m512i __B) {
|
||||
//CHECK: mul <8 x i64> %{{.*}}, %{{.*}}
|
||||
return _mm512_mul_epu32(__A,__B);
|
||||
}
|
||||
TEST_CONSTEXPR(match_m512i(_mm512_mul_epu32((__m512i)(__v16si){+1, -2, +3, -4, +5, -6, +7, -8, +9, -10, +11, -12, +13, -14, +15, -16}, (__m512i)(__v16si){-32, -30, +28, +26, -24, -22, +20, +18, -16, -14, +12, +10, -8, +6, -4, +2}), 4294967264, 84, 21474836360, 140, 38654705520, 132, 55834574744, 64424509380));
|
||||
|
||||
__m512i test_mm512_maskz_mul_epu32 (__mmask8 __k,__m512i __A, __m512i __B) {
|
||||
//CHECK-LABEL: test_mm512_maskz_mul_epu32
|
||||
@ -8953,29 +8955,34 @@ __m512d test_mm512_maskz_cvtps_pd(__mmask8 __U, __m256 __A) {
|
||||
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
|
||||
return _mm512_maskz_cvtps_pd(__U, __A);
|
||||
}
|
||||
|
||||
__m512d test_mm512_mask_mov_pd(__m512d __W, __mmask8 __U, __m512d __A) {
|
||||
// CHECK-LABEL: test_mm512_mask_mov_pd
|
||||
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
|
||||
return _mm512_mask_mov_pd(__W, __U, __A);
|
||||
}
|
||||
TEST_CONSTEXPR(match_m512d(_mm512_mask_mov_pd((__m512d){-8.0, -7.0, -6.0, -5.0, -4.0, -3.0, -2.0, -1.0}, 0xC3, (__m512d){+1.0, +2.0, +3.0, +4.0, +5.0, +6.0, +7.0, +8.0}), +1.0, +2.0, -6.0, -5.0, -4.0, -3.0, +7.0, +8.0));
|
||||
|
||||
__m512d test_mm512_maskz_mov_pd(__mmask8 __U, __m512d __A) {
|
||||
// CHECK-LABEL: test_mm512_maskz_mov_pd
|
||||
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
|
||||
return _mm512_maskz_mov_pd(__U, __A);
|
||||
}
|
||||
TEST_CONSTEXPR(match_m512d(_mm512_maskz_mov_pd(0xC3, (__m512d){+1.0, +2.0, +3.0, +4.0, +5.0, +6.0, +7.0, +8.0}), +1.0, +2.0, +0.0, +0.0, +0.0, +0.0, +7.0, +8.0));
|
||||
|
||||
__m512 test_mm512_mask_mov_ps(__m512 __W, __mmask16 __U, __m512 __A) {
|
||||
// CHECK-LABEL: test_mm512_mask_mov_ps
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
|
||||
return _mm512_mask_mov_ps(__W, __U, __A);
|
||||
}
|
||||
TEST_CONSTEXPR(match_m512(_mm512_mask_mov_ps((__m512){-16.0f, -15.0f, -14.0f, -13.0f, -12.0f, -11.0f, -10.0f, -9.0f, -8.0f, -7.0f, -6.0f, -5.0f, -4.0f, -3.0f, -2.0f, -1.0f}, 0x0FF0, (__m512){+1.0f, +2.0f, +3.0f, +4.0f, +5.0f, +6.0f, +7.0f, +8.0f, +9.0f, +10.0f, +11.0f, +12.0f, +13.0f, +14.0f, +15.0f, +16.0f}), -16.0f, -15.0f, -14.0f, -13.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, -4.0f, -3.0f, -2.0f, -1.0f));
|
||||
|
||||
__m512 test_mm512_maskz_mov_ps(__mmask16 __U, __m512 __A) {
|
||||
// CHECK-LABEL: test_mm512_maskz_mov_ps
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
|
||||
return _mm512_maskz_mov_ps(__U, __A);
|
||||
}
|
||||
TEST_CONSTEXPR(match_m512(_mm512_maskz_mov_ps(0xF3F3, (__m512){+1.0f, +2.0f, +3.0f, +4.0f, +5.0f, +6.0f, +7.0f, +8.0f, +9.0f, +10.0f, +11.0f, +12.0f, +13.0f, +14.0f, +15.0f, +16.0f}), +1.0f, +2.0f, 0.0f, 0.0f, +5.0f, +6.0f, +7.0f, +8.0f, +9.0f, +10.0f, 0.0f, 0.0f, +13.0f, +14.0f, +15.0f, +16.0f));
|
||||
|
||||
void test_mm512_mask_compressstoreu_pd(void *__P, __mmask8 __U, __m512d __A) {
|
||||
// CHECK-LABEL: test_mm512_mask_compressstoreu_pd
|
||||
|
@ -9517,48 +9517,56 @@ __m128d test_mm_mask_mov_pd(__m128d __W, __mmask8 __U, __m128d __A) {
|
||||
// CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
|
||||
return _mm_mask_mov_pd(__W, __U, __A);
|
||||
}
|
||||
TEST_CONSTEXPR(match_m128d(_mm_mask_mov_pd((__m128d){-2.0, -1.0}, 0x2, (__m128d){+1.0, +2.0}), -2.0, +2.0));
|
||||
|
||||
__m128d test_mm_maskz_mov_pd(__mmask8 __U, __m128d __A) {
|
||||
// CHECK-LABEL: test_mm_maskz_mov_pd
|
||||
// CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
|
||||
return _mm_maskz_mov_pd(__U, __A);
|
||||
}
|
||||
TEST_CONSTEXPR(match_m128d(_mm_maskz_mov_pd(0x1, (__m128d){+1.0, +2.0}), +1.0, +0.0));
|
||||
|
||||
__m256d test_mm256_mask_mov_pd(__m256d __W, __mmask8 __U, __m256d __A) {
|
||||
// CHECK-LABEL: test_mm256_mask_mov_pd
|
||||
// CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
|
||||
return _mm256_mask_mov_pd(__W, __U, __A);
|
||||
}
|
||||
TEST_CONSTEXPR(match_m256d(_mm256_mask_mov_pd((__m256d){-4.0, -3.0, -2.0, -1.0}, 0x3, (__m256d){+1.0, +2.0, +3.0, +4.0}), +1.0, +2.0, -2.0, -1.0));
|
||||
|
||||
__m256d test_mm256_maskz_mov_pd(__mmask8 __U, __m256d __A) {
|
||||
// CHECK-LABEL: test_mm256_maskz_mov_pd
|
||||
// CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
|
||||
return _mm256_maskz_mov_pd(__U, __A);
|
||||
}
|
||||
TEST_CONSTEXPR(match_m256d(_mm256_maskz_mov_pd(0xC, (__m256d){+1.0, +2.0, +3.0, +4.0}), 0.0, 0.0, +3.0, +4.0));
|
||||
|
||||
__m128 test_mm_mask_mov_ps(__m128 __W, __mmask8 __U, __m128 __A) {
|
||||
// CHECK-LABEL: test_mm_mask_mov_ps
|
||||
// CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
|
||||
return _mm_mask_mov_ps(__W, __U, __A);
|
||||
}
|
||||
TEST_CONSTEXPR(match_m128(_mm_mask_mov_ps((__m128){-4.0f, -3.0f, -2.0f, -1.0f}, 0x3, (__m128){+1.0f, +2.0f, +3.0f, +4.0f}), +1.0f, +2.0f, -2.0f, -1.0f));
|
||||
|
||||
__m128 test_mm_maskz_mov_ps(__mmask8 __U, __m128 __A) {
|
||||
// CHECK-LABEL: test_mm_maskz_mov_ps
|
||||
// CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
|
||||
return _mm_maskz_mov_ps(__U, __A);
|
||||
}
|
||||
TEST_CONSTEXPR(match_m128(_mm_maskz_mov_ps(0xC, (__m128){+1.0f, +2.0f, +3.0f, +4.0f}), 0.0f, 0.0f, +3.0f, +4.0f));
|
||||
|
||||
__m256 test_mm256_mask_mov_ps(__m256 __W, __mmask8 __U, __m256 __A) {
|
||||
// CHECK-LABEL: test_mm256_mask_mov_ps
|
||||
// CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
|
||||
return _mm256_mask_mov_ps(__W, __U, __A);
|
||||
}
|
||||
TEST_CONSTEXPR(match_m256(_mm256_mask_mov_ps((__m256){-8.0f, -7.0f, -6.0f, -5.0f, -4.0f, -3.0f, -2.0f, -1.0f}, 0xC3, (__m256){+1.0f, +2.0f, +3.0f, +4.0f, +5.0f, +6.0f, +7.0f, +8.0f}), +1.0f, +2.0f, -6.0f, -5.0f, -4.0f, -3.0f, +7.0f, +8.0f));
|
||||
|
||||
__m256 test_mm256_maskz_mov_ps(__mmask8 __U, __m256 __A) {
|
||||
// CHECK-LABEL: test_mm256_maskz_mov_ps
|
||||
// CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
|
||||
return _mm256_maskz_mov_ps(__U, __A);
|
||||
}
|
||||
TEST_CONSTEXPR(match_m256(_mm256_maskz_mov_ps(0xC3, (__m256){+1.0f, +2.0f, +3.0f, +4.0f, +5.0f, +6.0f, +7.0f, +8.0f}), +1.0f, +2.0f, 0.0f, 0.0f, 0.0f, 0.0f, +7.0f, +8.0f));
|
||||
|
||||
__m128 test_mm_mask_cvtph_ps(__m128 __W, __mmask8 __U, __m128i __A) {
|
||||
// CHECK-LABEL: test_mm_mask_cvtph_ps
|
||||
|
@ -19,12 +19,15 @@ __m256i test_mm256_mask_popcnt_epi16(__m256i __A, __mmask16 __U, __m256i __B) {
|
||||
// CHECK: select <16 x i1> %{{[0-9]+}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
|
||||
return _mm256_mask_popcnt_epi16(__A, __U, __B);
|
||||
}
|
||||
TEST_CONSTEXPR(match_v16hi(_mm256_mask_popcnt_epi16(_mm256_set1_epi16(-1), 0xF0F0, (__m256i)(__v16hi){+5, -3, -10, +8, 0, -256, +256, -128, +3, +9, +15, +33, +63, +129, +511, +1025}), -1, -1, -1, -1, 0, 8, 1, 9, -1, -1, -1, -1, 6, 2, 9, 2));
|
||||
|
||||
__m256i test_mm256_maskz_popcnt_epi16(__mmask16 __U, __m256i __B) {
|
||||
// CHECK-LABEL: test_mm256_maskz_popcnt_epi16
|
||||
// CHECK: @llvm.ctpop.v16i16
|
||||
// CHECK: select <16 x i1> %{{[0-9]+}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
|
||||
return _mm256_maskz_popcnt_epi16(__U, __B);
|
||||
}
|
||||
TEST_CONSTEXPR(match_v16hi(_mm256_maskz_popcnt_epi16(0x0F0F, (__m256i)(__v16hi){+5, -3, -10, +8, 0, -256, +256, -128, +3, +9, +15, +33, +63, +129, +511, +1025}), 2, 15, 14, 1, 0, 0, 0, 0, 2, 2, 4, 2, 0, 0, 0, 0));
|
||||
|
||||
__m128i test_mm_popcnt_epi16(__m128i __A) {
|
||||
// CHECK-LABEL: test_mm_popcnt_epi16
|
||||
@ -39,12 +42,15 @@ __m128i test_mm_mask_popcnt_epi16(__m128i __A, __mmask8 __U, __m128i __B) {
|
||||
// CHECK: select <8 x i1> %{{[0-9]+}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
|
||||
return _mm_mask_popcnt_epi16(__A, __U, __B);
|
||||
}
|
||||
TEST_CONSTEXPR(match_v8hi(_mm_mask_popcnt_epi16(_mm_set1_epi16(-1), 0xF0, (__m128i)(__v8hi){+5, -3, -10, +8, 0, -256, +256, -128}), -1, -1, -1, -1, 0, 8, 1, 9));
|
||||
|
||||
__m128i test_mm_maskz_popcnt_epi16(__mmask8 __U, __m128i __B) {
|
||||
// CHECK-LABEL: test_mm_maskz_popcnt_epi16
|
||||
// CHECK: @llvm.ctpop.v8i16
|
||||
// CHECK: select <8 x i1> %{{[0-9]+}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
|
||||
return _mm_maskz_popcnt_epi16(__U, __B);
|
||||
}
|
||||
TEST_CONSTEXPR(match_v8hi(_mm_maskz_popcnt_epi16(0x0F, (__m128i)(__v8hi){+5, -3, -10, +8, 0, -256, +256, -128}), 2, 15, 14, 1, 0, 0, 0, 0));
|
||||
|
||||
__m256i test_mm256_popcnt_epi8(__m256i __A) {
|
||||
// CHECK-LABEL: test_mm256_popcnt_epi8
|
||||
@ -59,12 +65,15 @@ __m256i test_mm256_mask_popcnt_epi8(__m256i __A, __mmask32 __U, __m256i __B) {
|
||||
// CHECK: select <32 x i1> %{{[0-9]+}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
|
||||
return _mm256_mask_popcnt_epi8(__A, __U, __B);
|
||||
}
|
||||
TEST_CONSTEXPR(match_v32qi(_mm256_mask_popcnt_epi8(_mm256_set1_epi8(-1), 0xF00F, (__m256i)(__v32qi){+5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73, +5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73}), 2, 7, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, 6, 2, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1));
|
||||
|
||||
__m256i test_mm256_maskz_popcnt_epi8(__mmask32 __U, __m256i __B) {
|
||||
// CHECK-LABEL: test_mm256_maskz_popcnt_epi8
|
||||
// CHECK: @llvm.ctpop.v32i8
|
||||
// CHECK: select <32 x i1> %{{[0-9]+}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
|
||||
return _mm256_maskz_popcnt_epi8(__U, __B);
|
||||
}
|
||||
TEST_CONSTEXPR(match_v32qi(_mm256_maskz_popcnt_epi8(0x0FF0, (__m256i)(__v32qi){+5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73, +5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73}), 0, 0, 0, 0, 0, 4, 1, 4, 2, 2, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
|
||||
|
||||
__m128i test_mm_popcnt_epi8(__m128i __A) {
|
||||
// CHECK-LABEL: test_mm_popcnt_epi8
|
||||
@ -79,12 +88,15 @@ __m128i test_mm_mask_popcnt_epi8(__m128i __A, __mmask16 __U, __m128i __B) {
|
||||
// CHECK: select <16 x i1> %{{[0-9]+}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
|
||||
return _mm_mask_popcnt_epi8(__A, __U, __B);
|
||||
}
|
||||
TEST_CONSTEXPR(match_v16qi(_mm_mask_popcnt_epi8(_mm_set1_epi8(-1), 0xF00F, (__m128i)(__v16qi){+5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73}), 2, 7, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, 6, 2, 4, 3));
|
||||
|
||||
__m128i test_mm_maskz_popcnt_epi8(__mmask16 __U, __m128i __B) {
|
||||
// CHECK-LABEL: test_mm_maskz_popcnt_epi8
|
||||
// CHECK: @llvm.ctpop.v16i8
|
||||
// CHECK: select <16 x i1> %{{[0-9]+}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
|
||||
return _mm_maskz_popcnt_epi8(__U, __B);
|
||||
}
|
||||
TEST_CONSTEXPR(match_v16qi(_mm_maskz_popcnt_epi8(0x0FF0, (__m128i)(__v16qi){+5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73}), 0, 0, 0, 0, 0, 4, 1, 4, 2, 2, 4, 2, 0, 0, 0, 0));
|
||||
|
||||
__mmask32 test_mm256_mask_bitshuffle_epi64_mask(__mmask32 __U, __m256i __A, __m256i __B) {
|
||||
// CHECK-LABEL: test_mm256_mask_bitshuffle_epi64_mask
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,420 +1,426 @@
|
||||
// RUN: %clang_cc1 -ffreestanding %s -O0 -triple=x86_64 -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s
|
||||
// RUN: %clang_cc1 -ffreestanding %s -O0 -triple=i386 -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=x86_64 -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=x86_64 -target-feature +avx512bw -target-feature +avx512vl -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=i386 -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=i386 -target-feature +avx512bw -target-feature +avx512vl -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c++ -ffreestanding %s -O0 -triple=x86_64 -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c++ -ffreestanding %s -O0 -triple=x86_64 -target-feature +avx512bw -target-feature +avx512vl -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c++ -ffreestanding %s -O0 -triple=i386 -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c++ -ffreestanding %s -O0 -triple=i386 -target-feature +avx512bw -target-feature +avx512vl -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
|
||||
|
||||
#include <immintrin.h>
|
||||
|
||||
short test_mm_reduce_add_epi16(__m128i __W){
|
||||
// CHECK-LABEL: @test_mm_reduce_add_epi16(
|
||||
// CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> %{{.*}})
|
||||
// CHECK-LABEL: test_mm_reduce_add_epi16
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.add.v8i16(<8 x i16> %{{.*}})
|
||||
return _mm_reduce_add_epi16(__W);
|
||||
}
|
||||
|
||||
short test_mm_reduce_mul_epi16(__m128i __W){
|
||||
// CHECK-LABEL: @test_mm_reduce_mul_epi16(
|
||||
// CHECK: call i16 @llvm.vector.reduce.mul.v8i16(<8 x i16> %{{.*}})
|
||||
// CHECK-LABEL: test_mm_reduce_mul_epi16
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.mul.v8i16(<8 x i16> %{{.*}})
|
||||
return _mm_reduce_mul_epi16(__W);
|
||||
}
|
||||
|
||||
short test_mm_reduce_or_epi16(__m128i __W){
|
||||
// CHECK-LABEL: @test_mm_reduce_or_epi16(
|
||||
// CHECK: call i16 @llvm.vector.reduce.or.v8i16(<8 x i16> %{{.*}})
|
||||
// CHECK-LABEL: test_mm_reduce_or_epi16
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.or.v8i16(<8 x i16> %{{.*}})
|
||||
return _mm_reduce_or_epi16(__W);
|
||||
}
|
||||
|
||||
short test_mm_reduce_and_epi16(__m128i __W){
|
||||
// CHECK-LABEL: @test_mm_reduce_and_epi16(
|
||||
// CHECK: call i16 @llvm.vector.reduce.and.v8i16(<8 x i16> %{{.*}})
|
||||
// CHECK-LABEL: test_mm_reduce_and_epi16
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.and.v8i16(<8 x i16> %{{.*}})
|
||||
return _mm_reduce_and_epi16(__W);
|
||||
}
|
||||
|
||||
short test_mm_mask_reduce_add_epi16(__mmask8 __M, __m128i __W){
|
||||
// CHECK-LABEL: @test_mm_mask_reduce_add_epi16(
|
||||
// CHECK-LABEL: test_mm_mask_reduce_add_epi16
|
||||
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
|
||||
// CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.add.v8i16(<8 x i16> %{{.*}})
|
||||
return _mm_mask_reduce_add_epi16(__M, __W);
|
||||
}
|
||||
|
||||
short test_mm_mask_reduce_mul_epi16(__mmask8 __M, __m128i __W){
|
||||
// CHECK-LABEL: @test_mm_mask_reduce_mul_epi16(
|
||||
// CHECK-LABEL: test_mm_mask_reduce_mul_epi16
|
||||
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
|
||||
// CHECK: call i16 @llvm.vector.reduce.mul.v8i16(<8 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.mul.v8i16(<8 x i16> %{{.*}})
|
||||
return _mm_mask_reduce_mul_epi16(__M, __W);
|
||||
}
|
||||
|
||||
short test_mm_mask_reduce_and_epi16(__mmask8 __M, __m128i __W){
|
||||
// CHECK-LABEL: @test_mm_mask_reduce_and_epi16(
|
||||
// CHECK-LABEL: test_mm_mask_reduce_and_epi16
|
||||
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
|
||||
// CHECK: call i16 @llvm.vector.reduce.and.v8i16(<8 x i16> %{{.*}}
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.and.v8i16(<8 x i16> %{{.*}}
|
||||
return _mm_mask_reduce_and_epi16(__M, __W);
|
||||
}
|
||||
|
||||
short test_mm_mask_reduce_or_epi16(__mmask8 __M, __m128i __W){
|
||||
// CHECK-LABEL: @test_mm_mask_reduce_or_epi16(
|
||||
// CHECK-LABEL: test_mm_mask_reduce_or_epi16
|
||||
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
|
||||
// CHECK: call i16 @llvm.vector.reduce.or.v8i16(<8 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.or.v8i16(<8 x i16> %{{.*}})
|
||||
return _mm_mask_reduce_or_epi16(__M, __W);
|
||||
}
|
||||
|
||||
short test_mm256_reduce_add_epi16(__m256i __W){
|
||||
// CHECK-LABEL: @test_mm256_reduce_add_epi16(
|
||||
// CHECK: call i16 @llvm.vector.reduce.add.v16i16(<16 x i16> %{{.*}})
|
||||
// CHECK-LABEL: test_mm256_reduce_add_epi16
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.add.v16i16(<16 x i16> %{{.*}})
|
||||
return _mm256_reduce_add_epi16(__W);
|
||||
}
|
||||
|
||||
short test_mm256_reduce_mul_epi16(__m256i __W){
|
||||
// CHECK-LABEL: @test_mm256_reduce_mul_epi16(
|
||||
// CHECK: call i16 @llvm.vector.reduce.mul.v16i16(<16 x i16> %{{.*}})
|
||||
// CHECK-LABEL: test_mm256_reduce_mul_epi16
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.mul.v16i16(<16 x i16> %{{.*}})
|
||||
return _mm256_reduce_mul_epi16(__W);
|
||||
}
|
||||
|
||||
short test_mm256_reduce_or_epi16(__m256i __W){
|
||||
// CHECK-LABEL: @test_mm256_reduce_or_epi16(
|
||||
// CHECK: call i16 @llvm.vector.reduce.or.v16i16(<16 x i16> %{{.*}})
|
||||
// CHECK-LABEL: test_mm256_reduce_or_epi16
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.or.v16i16(<16 x i16> %{{.*}})
|
||||
return _mm256_reduce_or_epi16(__W);
|
||||
}
|
||||
|
||||
short test_mm256_reduce_and_epi16(__m256i __W){
|
||||
// CHECK-LABEL: @test_mm256_reduce_and_epi16(
|
||||
// CHECK: call i16 @llvm.vector.reduce.and.v16i16(<16 x i16> %{{.*}})
|
||||
// CHECK-LABEL: test_mm256_reduce_and_epi16
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.and.v16i16(<16 x i16> %{{.*}})
|
||||
return _mm256_reduce_and_epi16(__W);
|
||||
}
|
||||
|
||||
short test_mm256_mask_reduce_add_epi16(__mmask16 __M, __m256i __W){
|
||||
// CHECK-LABEL: @test_mm256_mask_reduce_add_epi16(
|
||||
// CHECK-LABEL: test_mm256_mask_reduce_add_epi16
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
|
||||
// CHECK: call i16 @llvm.vector.reduce.add.v16i16(<16 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.add.v16i16(<16 x i16> %{{.*}})
|
||||
return _mm256_mask_reduce_add_epi16(__M, __W);
|
||||
}
|
||||
|
||||
short test_mm256_mask_reduce_mul_epi16(__mmask16 __M, __m256i __W){
|
||||
// CHECK-LABEL: @test_mm256_mask_reduce_mul_epi16(
|
||||
// CHECK-LABEL: test_mm256_mask_reduce_mul_epi16
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
|
||||
// CHECK: call i16 @llvm.vector.reduce.mul.v16i16(<16 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.mul.v16i16(<16 x i16> %{{.*}})
|
||||
return _mm256_mask_reduce_mul_epi16(__M, __W);
|
||||
}
|
||||
|
||||
short test_mm256_mask_reduce_and_epi16(__mmask16 __M, __m256i __W){
|
||||
// CHECK-LABEL: @test_mm256_mask_reduce_and_epi16(
|
||||
// CHECK-LABEL: test_mm256_mask_reduce_and_epi16
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
|
||||
// CHECK: call i16 @llvm.vector.reduce.and.v16i16(<16 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.and.v16i16(<16 x i16> %{{.*}})
|
||||
return _mm256_mask_reduce_and_epi16(__M, __W);
|
||||
}
|
||||
|
||||
short test_mm256_mask_reduce_or_epi16(__mmask16 __M, __m256i __W){
|
||||
// CHECK-LABEL: @test_mm256_mask_reduce_or_epi16(
|
||||
// CHECK-LABEL: test_mm256_mask_reduce_or_epi16
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
|
||||
// CHECK: call i16 @llvm.vector.reduce.or.v16i16(<16 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.or.v16i16(<16 x i16> %{{.*}})
|
||||
return _mm256_mask_reduce_or_epi16(__M, __W);
|
||||
}
|
||||
|
||||
signed char test_mm_reduce_add_epi8(__m128i __W){
|
||||
// CHECK-LABEL: @test_mm_reduce_add_epi8(
|
||||
// CHECK: call i8 @llvm.vector.reduce.add.v16i8(<16 x i8> %{{.*}})
|
||||
// CHECK-LABEL: test_mm_reduce_add_epi8
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.add.v16i8(<16 x i8> %{{.*}})
|
||||
return _mm_reduce_add_epi8(__W);
|
||||
}
|
||||
|
||||
signed char test_mm_reduce_mul_epi8(__m128i __W){
|
||||
// CHECK-LABEL: @test_mm_reduce_mul_epi8(
|
||||
// CHECK: call i8 @llvm.vector.reduce.mul.v16i8(<16 x i8> %{{.*}})
|
||||
// CHECK-LABEL: test_mm_reduce_mul_epi8
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.mul.v16i8(<16 x i8> %{{.*}})
|
||||
return _mm_reduce_mul_epi8(__W);
|
||||
}
|
||||
|
||||
signed char test_mm_reduce_and_epi8(__m128i __W){
|
||||
// CHECK-LABEL: @test_mm_reduce_and_epi8(
|
||||
// CHECK: call i8 @llvm.vector.reduce.and.v16i8(<16 x i8> %{{.*}})
|
||||
// CHECK-LABEL: test_mm_reduce_and_epi8
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.and.v16i8(<16 x i8> %{{.*}})
|
||||
return _mm_reduce_and_epi8(__W);
|
||||
}
|
||||
|
||||
signed char test_mm_reduce_or_epi8(__m128i __W){
|
||||
// CHECK-LABEL: @test_mm_reduce_or_epi8(
|
||||
// CHECK: call i8 @llvm.vector.reduce.or.v16i8(<16 x i8> %{{.*}})
|
||||
// CHECK-LABEL: test_mm_reduce_or_epi8
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.or.v16i8(<16 x i8> %{{.*}})
|
||||
return _mm_reduce_or_epi8(__W);
|
||||
}
|
||||
|
||||
signed char test_mm_mask_reduce_add_epi8(__mmask16 __M, __m128i __W){
|
||||
// CHECK-LABEL: @test_mm_mask_reduce_add_epi8(
|
||||
// CHECK-LABEL: test_mm_mask_reduce_add_epi8
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
|
||||
// CHECK: call i8 @llvm.vector.reduce.add.v16i8(<16 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.add.v16i8(<16 x i8> %{{.*}})
|
||||
return _mm_mask_reduce_add_epi8(__M, __W);
|
||||
}
|
||||
|
||||
signed char test_mm_mask_reduce_mul_epi8(__mmask16 __M, __m128i __W){
|
||||
// CHECK-LABEL: @test_mm_mask_reduce_mul_epi8(
|
||||
// CHECK-LABEL: test_mm_mask_reduce_mul_epi8
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
|
||||
// CHECK: call i8 @llvm.vector.reduce.mul.v16i8(<16 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.mul.v16i8(<16 x i8> %{{.*}})
|
||||
return _mm_mask_reduce_mul_epi8(__M, __W);
|
||||
}
|
||||
|
||||
signed char test_mm_mask_reduce_and_epi8(__mmask16 __M, __m128i __W){
|
||||
// CHECK-LABEL: @test_mm_mask_reduce_and_epi8(
|
||||
// CHECK-LABEL: test_mm_mask_reduce_and_epi8
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
|
||||
// CHECK: call i8 @llvm.vector.reduce.and.v16i8(<16 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.and.v16i8(<16 x i8> %{{.*}})
|
||||
return _mm_mask_reduce_and_epi8(__M, __W);
|
||||
}
|
||||
|
||||
signed char test_mm_mask_reduce_or_epi8(__mmask16 __M, __m128i __W){
|
||||
// CHECK-LABEL: @test_mm_mask_reduce_or_epi8(
|
||||
// CHECK-LABEL: test_mm_mask_reduce_or_epi8
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
|
||||
// CHECK: call i8 @llvm.vector.reduce.or.v16i8(<16 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.or.v16i8(<16 x i8> %{{.*}})
|
||||
return _mm_mask_reduce_or_epi8(__M, __W);
|
||||
}
|
||||
|
||||
signed char test_mm256_reduce_add_epi8(__m256i __W){
|
||||
// CHECK-LABEL: @test_mm256_reduce_add_epi8(
|
||||
// CHECK: call i8 @llvm.vector.reduce.add.v32i8(<32 x i8> %{{.*}})
|
||||
// CHECK-LABEL: test_mm256_reduce_add_epi8
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.add.v32i8(<32 x i8> %{{.*}})
|
||||
return _mm256_reduce_add_epi8(__W);
|
||||
}
|
||||
|
||||
signed char test_mm256_reduce_mul_epi8(__m256i __W){
|
||||
// CHECK-LABEL: @test_mm256_reduce_mul_epi8(
|
||||
// CHECK: call i8 @llvm.vector.reduce.mul.v32i8(<32 x i8> %{{.*}})
|
||||
// CHECK-LABEL: test_mm256_reduce_mul_epi8
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.mul.v32i8(<32 x i8> %{{.*}})
|
||||
return _mm256_reduce_mul_epi8(__W);
|
||||
}
|
||||
|
||||
signed char test_mm256_reduce_and_epi8(__m256i __W){
|
||||
// CHECK-LABEL: @test_mm256_reduce_and_epi8(
|
||||
// CHECK: call i8 @llvm.vector.reduce.and.v32i8(<32 x i8> %{{.*}})
|
||||
// CHECK-LABEL: test_mm256_reduce_and_epi8
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.and.v32i8(<32 x i8> %{{.*}})
|
||||
return _mm256_reduce_and_epi8(__W);
|
||||
}
|
||||
|
||||
signed char test_mm256_reduce_or_epi8(__m256i __W){
|
||||
// CHECK-LABEL: @test_mm256_reduce_or_epi8(
|
||||
// CHECK: call i8 @llvm.vector.reduce.or.v32i8(<32 x i8> %{{.*}})
|
||||
// CHECK-LABEL: test_mm256_reduce_or_epi8
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.or.v32i8(<32 x i8> %{{.*}})
|
||||
return _mm256_reduce_or_epi8(__W);
|
||||
}
|
||||
|
||||
signed char test_mm256_mask_reduce_add_epi8(__mmask32 __M, __m256i __W){
|
||||
// CHECK-LABEL: @test_mm256_mask_reduce_add_epi8(
|
||||
// CHECK-LABEL: test_mm256_mask_reduce_add_epi8
|
||||
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
|
||||
// CHECK: call i8 @llvm.vector.reduce.add.v32i8(<32 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.add.v32i8(<32 x i8> %{{.*}})
|
||||
return _mm256_mask_reduce_add_epi8(__M, __W);
|
||||
}
|
||||
|
||||
signed char test_mm256_mask_reduce_mul_epi8(__mmask32 __M, __m256i __W){
|
||||
// CHECK-LABEL: @test_mm256_mask_reduce_mul_epi8(
|
||||
// CHECK-LABEL: test_mm256_mask_reduce_mul_epi8
|
||||
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
|
||||
// CHECK: call i8 @llvm.vector.reduce.mul.v32i8(<32 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.mul.v32i8(<32 x i8> %{{.*}})
|
||||
return _mm256_mask_reduce_mul_epi8(__M, __W);
|
||||
}
|
||||
|
||||
signed char test_mm256_mask_reduce_and_epi8(__mmask32 __M, __m256i __W){
|
||||
// CHECK-LABEL: @test_mm256_mask_reduce_and_epi8(
|
||||
// CHECK-LABEL: test_mm256_mask_reduce_and_epi8
|
||||
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
|
||||
// CHECK: call i8 @llvm.vector.reduce.and.v32i8(<32 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.and.v32i8(<32 x i8> %{{.*}})
|
||||
return _mm256_mask_reduce_and_epi8(__M, __W);
|
||||
}
|
||||
|
||||
signed char test_mm256_mask_reduce_or_epi8(__mmask32 __M, __m256i __W){
|
||||
// CHECK-LABEL: @test_mm256_mask_reduce_or_epi8(
|
||||
// CHECK-LABEL: test_mm256_mask_reduce_or_epi8
|
||||
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
|
||||
// CHECK: call i8 @llvm.vector.reduce.or.v32i8(<32 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.or.v32i8(<32 x i8> %{{.*}})
|
||||
return _mm256_mask_reduce_or_epi8(__M, __W);
|
||||
}
|
||||
|
||||
short test_mm_reduce_max_epi16(__m128i __W){
|
||||
// CHECK-LABEL: test_mm_reduce_max_epi16
|
||||
// CHECK: call i16 @llvm.vector.reduce.smax.v8i16(<8 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.smax.v8i16(<8 x i16> %{{.*}})
|
||||
return _mm_reduce_max_epi16(__W);
|
||||
}
|
||||
|
||||
short test_mm_reduce_min_epi16(__m128i __W){
|
||||
// CHECK-LABEL: test_mm_reduce_min_epi16
|
||||
// CHECK: call i16 @llvm.vector.reduce.smin.v8i16(<8 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.smin.v8i16(<8 x i16> %{{.*}})
|
||||
return _mm_reduce_min_epi16(__W);
|
||||
}
|
||||
|
||||
unsigned short test_mm_reduce_max_epu16(__m128i __W){
|
||||
// CHECK-LABEL: test_mm_reduce_max_epu16
|
||||
// CHECK: call i16 @llvm.vector.reduce.umax.v8i16(<8 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.umax.v8i16(<8 x i16> %{{.*}})
|
||||
return _mm_reduce_max_epu16(__W);
|
||||
}
|
||||
|
||||
unsigned short test_mm_reduce_min_epu16(__m128i __W){
|
||||
// CHECK-LABEL: test_mm_reduce_min_epu16
|
||||
// CHECK: call i16 @llvm.vector.reduce.umin.v8i16(<8 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.umin.v8i16(<8 x i16> %{{.*}})
|
||||
return _mm_reduce_min_epu16(__W);
|
||||
}
|
||||
|
||||
short test_mm_mask_reduce_max_epi16(__mmask8 __M, __m128i __W){
|
||||
// CHECK-LABEL: test_mm_mask_reduce_max_epi16
|
||||
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
|
||||
// CHECK: call i16 @llvm.vector.reduce.smax.v8i16(<8 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.smax.v8i16(<8 x i16> %{{.*}})
|
||||
return _mm_mask_reduce_max_epi16(__M, __W);
|
||||
}
|
||||
|
||||
short test_mm_mask_reduce_min_epi16(__mmask8 __M, __m128i __W){
|
||||
// CHECK-LABEL: test_mm_mask_reduce_min_epi16
|
||||
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
|
||||
// CHECK: call i16 @llvm.vector.reduce.smin.v8i16(<8 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.smin.v8i16(<8 x i16> %{{.*}})
|
||||
return _mm_mask_reduce_min_epi16(__M, __W);
|
||||
}
|
||||
|
||||
unsigned short test_mm_mask_reduce_max_epu16(__mmask8 __M, __m128i __W){
|
||||
// CHECK-LABEL: test_mm_mask_reduce_max_epu16
|
||||
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
|
||||
// CHECK: call i16 @llvm.vector.reduce.umax.v8i16(<8 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.umax.v8i16(<8 x i16> %{{.*}})
|
||||
return _mm_mask_reduce_max_epu16(__M, __W);
|
||||
}
|
||||
|
||||
unsigned short test_mm_mask_reduce_min_epu16(__mmask8 __M, __m128i __W){
|
||||
// CHECK-LABEL: test_mm_mask_reduce_min_epu16
|
||||
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
|
||||
// CHECK: call i16 @llvm.vector.reduce.umin.v8i16(<8 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.umin.v8i16(<8 x i16> %{{.*}})
|
||||
return _mm_mask_reduce_min_epu16(__M, __W);
|
||||
}
|
||||
|
||||
short test_mm256_reduce_max_epi16(__m256i __W){
|
||||
// CHECK-LABEL: test_mm256_reduce_max_epi16
|
||||
// CHECK: call i16 @llvm.vector.reduce.smax.v16i16(<16 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.smax.v16i16(<16 x i16> %{{.*}})
|
||||
return _mm256_reduce_max_epi16(__W);
|
||||
}
|
||||
|
||||
short test_mm256_reduce_min_epi16(__m256i __W){
|
||||
// CHECK-LABEL: test_mm256_reduce_min_epi16
|
||||
// CHECK: call i16 @llvm.vector.reduce.smin.v16i16(<16 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.smin.v16i16(<16 x i16> %{{.*}})
|
||||
return _mm256_reduce_min_epi16(__W);
|
||||
}
|
||||
|
||||
unsigned short test_mm256_reduce_max_epu16(__m256i __W){
|
||||
// CHECK-LABEL: test_mm256_reduce_max_epu16
|
||||
// CHECK: call i16 @llvm.vector.reduce.umax.v16i16(<16 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.umax.v16i16(<16 x i16> %{{.*}})
|
||||
return _mm256_reduce_max_epu16(__W);
|
||||
}
|
||||
|
||||
unsigned short test_mm256_reduce_min_epu16(__m256i __W){
|
||||
// CHECK-LABEL: test_mm256_reduce_min_epu16
|
||||
// CHECK: call i16 @llvm.vector.reduce.umin.v16i16(<16 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.umin.v16i16(<16 x i16> %{{.*}})
|
||||
return _mm256_reduce_min_epu16(__W);
|
||||
}
|
||||
|
||||
short test_mm256_mask_reduce_max_epi16(__mmask16 __M, __m256i __W){
|
||||
// CHECK-LABEL: test_mm256_mask_reduce_max_epi16
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
|
||||
// CHECK: call i16 @llvm.vector.reduce.smax.v16i16(<16 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.smax.v16i16(<16 x i16> %{{.*}})
|
||||
return _mm256_mask_reduce_max_epi16(__M, __W);
|
||||
}
|
||||
|
||||
short test_mm256_mask_reduce_min_epi16(__mmask16 __M, __m256i __W){
|
||||
// CHECK-LABEL: test_mm256_mask_reduce_min_epi16
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
|
||||
// CHECK: call i16 @llvm.vector.reduce.smin.v16i16(<16 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.smin.v16i16(<16 x i16> %{{.*}})
|
||||
return _mm256_mask_reduce_min_epi16(__M, __W);
|
||||
}
|
||||
|
||||
unsigned short test_mm256_mask_reduce_max_epu16(__mmask16 __M, __m256i __W){
|
||||
// CHECK-LABEL: test_mm256_mask_reduce_max_epu16
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
|
||||
// CHECK: call i16 @llvm.vector.reduce.umax.v16i16(<16 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.umax.v16i16(<16 x i16> %{{.*}})
|
||||
return _mm256_mask_reduce_max_epu16(__M, __W);
|
||||
}
|
||||
|
||||
unsigned short test_mm256_mask_reduce_min_epu16(__mmask16 __M, __m256i __W){
|
||||
// CHECK-LABEL: test_mm256_mask_reduce_min_epu16
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
|
||||
// CHECK: call i16 @llvm.vector.reduce.umin.v16i16(<16 x i16> %{{.*}})
|
||||
// CHECK: call {{.*}}i16 @llvm.vector.reduce.umin.v16i16(<16 x i16> %{{.*}})
|
||||
return _mm256_mask_reduce_min_epu16(__M, __W);
|
||||
}
|
||||
|
||||
signed char test_mm_reduce_max_epi8(__m128i __W){
|
||||
// CHECK-LABEL: test_mm_reduce_max_epi8
|
||||
// CHECK: call i8 @llvm.vector.reduce.smax.v16i8(<16 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.smax.v16i8(<16 x i8> %{{.*}})
|
||||
return _mm_reduce_max_epi8(__W);
|
||||
}
|
||||
|
||||
signed char test_mm_reduce_min_epi8(__m128i __W){
|
||||
// CHECK-LABEL: test_mm_reduce_min_epi8
|
||||
// CHECK: call i8 @llvm.vector.reduce.smin.v16i8(<16 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.smin.v16i8(<16 x i8> %{{.*}})
|
||||
return _mm_reduce_min_epi8(__W);
|
||||
}
|
||||
|
||||
unsigned char test_mm_reduce_max_epu8(__m128i __W){
|
||||
// CHECK-LABEL: test_mm_reduce_max_epu8
|
||||
// CHECK: call i8 @llvm.vector.reduce.umax.v16i8(<16 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.umax.v16i8(<16 x i8> %{{.*}})
|
||||
return _mm_reduce_max_epu8(__W);
|
||||
}
|
||||
|
||||
unsigned char test_mm_reduce_min_epu8(__m128i __W){
|
||||
// CHECK-LABEL: test_mm_reduce_min_epu8
|
||||
// CHECK: call i8 @llvm.vector.reduce.umin.v16i8(<16 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.umin.v16i8(<16 x i8> %{{.*}})
|
||||
return _mm_reduce_min_epu8(__W);
|
||||
}
|
||||
|
||||
signed char test_mm_mask_reduce_max_epi8(__mmask16 __M, __m128i __W){
|
||||
// CHECK-LABEL: test_mm_mask_reduce_max_epi8
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
|
||||
// CHECK: call i8 @llvm.vector.reduce.smax.v16i8(<16 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.smax.v16i8(<16 x i8> %{{.*}})
|
||||
return _mm_mask_reduce_max_epi8(__M, __W);
|
||||
}
|
||||
|
||||
signed char test_mm_mask_reduce_min_epi8(__mmask16 __M, __m128i __W){
|
||||
// CHECK-LABEL: test_mm_mask_reduce_min_epi8
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
|
||||
// CHECK: call i8 @llvm.vector.reduce.smin.v16i8(<16 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.smin.v16i8(<16 x i8> %{{.*}})
|
||||
return _mm_mask_reduce_min_epi8(__M, __W);
|
||||
}
|
||||
|
||||
unsigned char test_mm_mask_reduce_max_epu8(__mmask16 __M, __m128i __W){
|
||||
// CHECK-LABEL: test_mm_mask_reduce_max_epu8
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
|
||||
// CHECK: call i8 @llvm.vector.reduce.umax.v16i8(<16 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.umax.v16i8(<16 x i8> %{{.*}})
|
||||
return _mm_mask_reduce_max_epu8(__M, __W);
|
||||
}
|
||||
|
||||
unsigned char test_mm_mask_reduce_min_epu8(__mmask16 __M, __m128i __W){
|
||||
// CHECK-LABEL: test_mm_mask_reduce_min_epu8
|
||||
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
|
||||
// CHECK: call i8 @llvm.vector.reduce.umin.v16i8(<16 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.umin.v16i8(<16 x i8> %{{.*}})
|
||||
return _mm_mask_reduce_min_epu8(__M, __W);
|
||||
}
|
||||
|
||||
signed char test_mm256_reduce_max_epi8(__m256i __W){
|
||||
// CHECK-LABEL: test_mm256_reduce_max_epi8
|
||||
// CHECK: call i8 @llvm.vector.reduce.smax.v32i8(<32 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.smax.v32i8(<32 x i8> %{{.*}})
|
||||
return _mm256_reduce_max_epi8(__W);
|
||||
}
|
||||
|
||||
signed char test_mm256_reduce_min_epi8(__m256i __W){
|
||||
// CHECK-LABEL: test_mm256_reduce_min_epi8
|
||||
// CHECK: call i8 @llvm.vector.reduce.smin.v32i8(<32 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.smin.v32i8(<32 x i8> %{{.*}})
|
||||
return _mm256_reduce_min_epi8(__W);
|
||||
}
|
||||
|
||||
unsigned char test_mm256_reduce_max_epu8(__m256i __W){
|
||||
// CHECK-LABEL: test_mm256_reduce_max_epu8
|
||||
// CHECK: call i8 @llvm.vector.reduce.umax.v32i8(<32 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.umax.v32i8(<32 x i8> %{{.*}})
|
||||
return _mm256_reduce_max_epu8(__W);
|
||||
}
|
||||
|
||||
unsigned char test_mm256_reduce_min_epu8(__m256i __W){
|
||||
// CHECK-LABEL: test_mm256_reduce_min_epu8
|
||||
// CHECK: call i8 @llvm.vector.reduce.umin.v32i8(<32 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.umin.v32i8(<32 x i8> %{{.*}})
|
||||
return _mm256_reduce_min_epu8(__W);
|
||||
}
|
||||
|
||||
signed char test_mm256_mask_reduce_max_epi8(__mmask32 __M, __m256i __W){
|
||||
// CHECK-LABEL: test_mm256_mask_reduce_max_epi8
|
||||
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
|
||||
// CHECK: call i8 @llvm.vector.reduce.smax.v32i8(<32 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.smax.v32i8(<32 x i8> %{{.*}})
|
||||
return _mm256_mask_reduce_max_epi8(__M, __W);
|
||||
}
|
||||
|
||||
signed char test_mm256_mask_reduce_min_epi8(__mmask32 __M, __m256i __W){
|
||||
// CHECK-LABEL: test_mm256_mask_reduce_min_epi8
|
||||
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
|
||||
// CHECK: call i8 @llvm.vector.reduce.smin.v32i8(<32 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.smin.v32i8(<32 x i8> %{{.*}})
|
||||
return _mm256_mask_reduce_min_epi8(__M, __W);
|
||||
}
|
||||
|
||||
unsigned char test_mm256_mask_reduce_max_epu8(__mmask32 __M, __m256i __W){
|
||||
// CHECK-LABEL: test_mm256_mask_reduce_max_epu8
|
||||
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
|
||||
// CHECK: call i8 @llvm.vector.reduce.umax.v32i8(<32 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.umax.v32i8(<32 x i8> %{{.*}})
|
||||
return _mm256_mask_reduce_max_epu8(__M, __W);
|
||||
}
|
||||
|
||||
unsigned char test_mm256_mask_reduce_min_epu8(__mmask32 __M, __m256i __W){
|
||||
// CHECK-LABEL: test_mm256_mask_reduce_min_epu8
|
||||
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
|
||||
// CHECK: call i8 @llvm.vector.reduce.umin.v32i8(<32 x i8> %{{.*}})
|
||||
// CHECK: call {{.*}}i8 @llvm.vector.reduce.umin.v32i8(<32 x i8> %{{.*}})
|
||||
return _mm256_mask_reduce_min_epu8(__M, __W);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user