Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
modernize-use-starts-ends-with
==============================

Checks whether a ``find`` or ``rfind`` result is compared with 0 and suggests
replacing with ``starts_with`` when the method exists in the class. Notably,
this will work with ``std::string`` and ``std::string_view``.
Checks for common roundabout ways to express ``starts_with`` and ``ends_with``
and suggests replacing with ``starts_with`` when the method is available.
Notably, this will work with ``std::string`` and ``std::string_view``.

.. code-block:: c++

std::string s = "...";
if (s.find("prefix") == 0) { /* do something */ }
if (s.rfind("prefix", 0) == 0) { /* do something */ }
if (s.compare(0, strlen("prefix"), "prefix") == 0) { /* do something */ }
becomes

Expand All @@ -20,3 +21,4 @@ becomes
std::string s = "...";
if (s.starts_with("prefix")) { /* do something */ }
if (s.starts_with("prefix")) { /* do something */ }
if (s.starts_with("prefix")) { /* do something */ }
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ struct basic_string {
int compare(const C* s) const;
int compare(size_type pos, size_type len, const _Type&) const;
int compare(size_type pos, size_type len, const C* s) const;
template<class StringViewLike>
int compare(size_type pos1, size_type count1, const StringViewLike& t) const;

size_type find(const _Type& str, size_type pos = 0) const;
size_type find(const C* s, size_type pos = 0) const;
Expand Down Expand Up @@ -129,6 +131,8 @@ bool operator!=(const char*, const std::string&);
bool operator==(const std::wstring&, const std::wstring&);
bool operator==(const std::wstring&, const wchar_t*);
bool operator==(const wchar_t*, const std::wstring&);

size_t strlen(const char* str);
}

#endif // _STRING_
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
#include "stddef.h"

void *memcpy(void *dest, const void *src, size_t n);
size_t strlen(const char* str);

#endif // _STRING_H_
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// RUN: %check_clang_tidy %s abseil-redundant-strcat-calls %t -- -- -isystem %clang_tidy_headers
#include <string>

int strlen(const char *);

namespace absl {

class string_view {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// RUN: %check_clang_tidy %s bugprone-return-const-ref-from-parameter %t

using T = int;
using TConst = int const;
using TConstRef = int const&;

namespace invalid {

int const &f1(int const &a) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:38: warning: returning a constant reference parameter

int const &f2(T const &a) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:36: warning: returning a constant reference parameter

int const &f3(TConstRef a) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: returning a constant reference parameter

int const &f4(TConst &a) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: returning a constant reference parameter

} // namespace invalid

namespace valid {

int const &f1(int &a) { return a; }

int const &f2(int &&a) { return a; }

int f1(int const &a) { return a; }

} // namespace valid
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// RUN: %check_clang_tidy -std=c++20 %s modernize-use-starts-ends-with %t -- \
// RUN: -- -isystem %clang_tidy_headers

#include <string.h>
#include <string>

std::string foo(std::string);
Expand Down Expand Up @@ -158,10 +159,64 @@ void test(std::string s, std::string_view sv, sub_string ss, sub_sub_string sss,
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use startsWith
// CHECK-FIXES: puvi.startsWith("a");

s.compare(0, 1, "a") == 0;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of compare() == 0
// CHECK-FIXES: s.starts_with("a");

s.compare(0, 1, "a") != 0;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of compare() != 0
// CHECK-FIXES: !s.starts_with("a");

s.compare(0, strlen("a"), "a") == 0;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
// CHECK-FIXES: s.starts_with("a");

s.compare(0, std::strlen("a"), "a") == 0;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
// CHECK-FIXES: s.starts_with("a");

s.compare(0, std::strlen(("a")), "a") == 0;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
// CHECK-FIXES: s.starts_with("a");

s.compare(0, std::strlen(("a")), (("a"))) == 0;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
// CHECK-FIXES: s.starts_with("a");

s.compare(0, s.size(), s) == 0;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
// CHECK-FIXES: s.starts_with(s);

s.compare(0, s.length(), s) == 0;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
// CHECK-FIXES: s.starts_with(s);

0 != s.compare(0, sv.length(), sv);
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
// CHECK-FIXES: s.starts_with(sv);

#define LENGTH(x) (x).length()
s.compare(0, LENGTH(s), s) == 0;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
// CHECK-FIXES: s.starts_with(s);

s.compare(ZERO, LENGTH(s), s) == ZERO;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
// CHECK-FIXES: s.starts_with(s);

s.compare(ZERO, LENGTH(sv), sv) != 0;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
// CHECK-FIXES: !s.starts_with(sv);

// Expressions that don't trigger the check are here.
#define EQ(x, y) ((x) == (y))
EQ(s.find("a"), 0);

#define DOTFIND(x, y) (x).find(y)
DOTFIND(s, "a") == 0;

#define STARTS_WITH_COMPARE(x, y) (x).compare(0, (x).size(), (y))
STARTS_WITH_COMPARE(s, s) == 0;

s.compare(0, 1, "ab") == 0;
}
2 changes: 2 additions & 0 deletions clang/cmake/caches/Release.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ if (LLVM_RELEASE_ENABLE_PGO)
set(CLANG_BOOTSTRAP_TARGETS
generate-profdata
stage2
stage2-package
stage2-clang
stage2-distribution
stage2-install
Expand Down Expand Up @@ -57,6 +58,7 @@ set(LLVM_TARGETS_TO_BUILD Native CACHE STRING "")
set(BOOTSTRAP_CLANG_ENABLE_BOOTSTRAP ON CACHE STRING "")
set(BOOTSTRAP_CLANG_BOOTSTRAP_TARGETS
clang
package
check-all
check-llvm
check-clang CACHE STRING "")
Expand Down
7 changes: 6 additions & 1 deletion clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,9 @@ Bug Fixes in This Version
operator.
Fixes (#GH83267).

- Fix crash on ill-formed partial specialization with CRTP.
Fixes (#GH89374).

- Clang now correctly generates overloads for bit-precise integer types for
builtin operators in C++. Fixes #GH82998.

Expand Down Expand Up @@ -557,7 +560,6 @@ Bug Fixes to C++ Support
- Fix a crash in requires expression with templated base class member function. Fixes (#GH84020).
- Fix a crash caused by defined struct in a type alias template when the structure
has fields with dependent type. Fixes (#GH75221).
- Fix placement new initializes typedef array with correct size. Fixes (#GH41441).
- Fix the Itanium mangling of lambdas defined in a member of a local class (#GH88906)
- Fixed a crash when trying to evaluate a user-defined ``static_assert`` message whose ``size()``
function returns a large or negative value. Fixes (#GH89407).
Expand Down Expand Up @@ -708,6 +710,9 @@ clang-format
libclang
--------

- ``clang_getSpellingLocation`` now correctly resolves macro expansions; that
is, it returns the spelling location instead of the expansion location.

Static Analyzer
---------------

Expand Down
3 changes: 3 additions & 0 deletions clang/docs/UsersManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4921,6 +4921,9 @@ directory. Using the example installation above, this would mean passing
If the user links the program with the ``clang`` or ``clang-cl`` drivers, the
driver will pass this flag for them.

The auto-linking can be disabled with -fno-rtlib-defaultlib. If that flag is
used, pass the complete flag to required libraries as described for ASan below.

If the linker cannot find the appropriate library, it will emit an error like
this::

Expand Down
10 changes: 4 additions & 6 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -3755,14 +3755,12 @@ def err_sme_definition_using_za_in_non_sme_target : Error<
def err_sme_definition_using_zt0_in_non_sme2_target : Error<
"function using ZT0 state requires 'sme2'">;
def warn_sme_streaming_pass_return_vl_to_non_streaming : Warning<
"passing a VL-dependent argument to/from a function that has a different"
" streaming-mode. The streaming and non-streaming vector lengths may be"
" different">,
"%select{returning|passing}0 a VL-dependent argument %select{from|to}0 a function with a different"
" streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime">,
InGroup<AArch64SMEAttributes>, DefaultIgnore;
def warn_sme_locally_streaming_has_vl_args_returns : Warning<
"passing/returning a VL-dependent argument to/from a __arm_locally_streaming"
" function. The streaming and non-streaming vector"
" lengths may be different">,
"%select{returning|passing}0 a VL-dependent argument %select{from|to}0 a locally streaming function is undefined"
" behaviour when the streaming and non-streaming vector lengths are different at runtime">,
InGroup<AArch64SMEAttributes>, DefaultIgnore;
def err_conflicting_attributes_arm_state : Error<
"conflicting attributes for state '%0'">;
Expand Down
97 changes: 74 additions & 23 deletions clang/include/clang/Basic/riscv_vector.td

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -5512,6 +5512,14 @@ def fno_rtlib_add_rpath: Flag<["-"], "fno-rtlib-add-rpath">,
Visibility<[ClangOption, FlangOption]>,
HelpText<"Do not add -rpath with architecture-specific resource directory to the linker flags. "
"When --hip-link is specified, do not add -rpath with HIP runtime library directory to the linker flags">;
def frtlib_defaultlib : Flag<["-"], "frtlib-defaultlib">,
Visibility<[ClangOption, CLOption]>,
Group<f_Group>,
HelpText<"On Windows, emit /defaultlib: directives to link compiler-rt libraries (default)">;
def fno_rtlib_defaultlib : Flag<["-"], "fno-rtlib-defaultlib">,
Visibility<[ClangOption, CLOption]>,
Group<f_Group>,
HelpText<"On Windows, do not emit /defaultlib: directives to link compiler-rt libraries">;
def offload_add_rpath: Flag<["--"], "offload-add-rpath">,
Flags<[NoArgumentUnused]>,
Alias<frtlib_add_rpath>;
Expand Down
135 changes: 91 additions & 44 deletions clang/include/clang/ExtractAPI/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,20 +208,20 @@ struct APIRecord {
RK_ClassTemplate,
RK_ClassTemplateSpecialization,
RK_ClassTemplatePartialSpecialization,
RK_LastRecordContext,
RK_GlobalFunction,
RK_GlobalFunctionTemplate,
RK_GlobalFunctionTemplateSpecialization,
RK_StructField,
RK_UnionField,
RK_CXXField,
RK_StaticField,
RK_CXXFieldTemplate,
RK_GlobalVariable,
RK_GlobalVariableTemplate,
RK_GlobalVariableTemplateSpecialization,
RK_GlobalVariableTemplatePartialSpecialization,
RK_LastRecordContext,
RK_GlobalFunction,
RK_GlobalFunctionTemplate,
RK_GlobalFunctionTemplateSpecialization,
RK_EnumConstant,
RK_StructField,
RK_UnionField,
RK_StaticField,
RK_CXXField,
RK_CXXFieldTemplate,
RK_Concept,
RK_CXXStaticMethod,
RK_CXXInstanceMethod,
Expand Down Expand Up @@ -321,6 +321,10 @@ class RecordContext {

RecordContext(APIRecord::RecordKind Kind) : Kind(Kind) {}

/// Append \p Other children chain into ours and empty out Other's record
/// chain.
void stealRecordChain(RecordContext &Other);

APIRecord::RecordKind getKind() const { return Kind; }

struct record_iterator {
Expand Down Expand Up @@ -370,6 +374,7 @@ class RecordContext {
APIRecord::RecordKind Kind;
mutable APIRecord *First = nullptr;
mutable APIRecord *Last = nullptr;
bool IsWellFormed() const;

protected:
friend class APISet;
Expand Down Expand Up @@ -475,31 +480,36 @@ struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord {
};

/// This holds information associated with global functions.
struct GlobalVariableRecord : APIRecord {
struct GlobalVariableRecord : APIRecord, RecordContext {
GlobalVariableRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(RK_GlobalVariable, USR, Name, Parent, Loc,
std::move(Availability), Linkage, Comment, Declaration,
SubHeading, IsFromSystemHeader) {}
SubHeading, IsFromSystemHeader),
RecordContext(RK_GlobalVariable) {}

GlobalVariableRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent,

PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
Linkage, Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
IsFromSystemHeader),
RecordContext(Kind) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_GlobalVariable; }
static bool classofKind(RecordKind K) {
return K == RK_GlobalVariable || K == RK_GlobalVariableTemplate ||
K == RK_GlobalVariableTemplateSpecialization ||
K == RK_GlobalVariableTemplatePartialSpecialization;
}

private:
virtual void anchor();
Expand Down Expand Up @@ -591,36 +601,64 @@ struct EnumConstantRecord : APIRecord {
virtual void anchor();
};

struct TagRecord : APIRecord, RecordContext {
TagRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
bool IsFromSystemHeader, bool IsEmbeddedInVarDeclarator,
AccessControl Access = AccessControl())
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader, std::move(Access)),
RecordContext(Kind),
IsEmbeddedInVarDeclarator(IsEmbeddedInVarDeclarator){};

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_Struct || K == RK_Union || K == RK_Enum;
}

bool IsEmbeddedInVarDeclarator;

virtual ~TagRecord() = 0;
};

/// This holds information associated with enums.
struct EnumRecord : APIRecord, RecordContext {
struct EnumRecord : TagRecord {
EnumRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(RK_Enum, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
RecordContext(RK_Enum) {}
DeclarationFragments SubHeading, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator,
AccessControl Access = AccessControl())
: TagRecord(RK_Enum, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator, std::move(Access)) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}

static bool classofKind(RecordKind K) { return K == RK_Enum; }

private:
virtual void anchor();
};

/// This holds information associated with struct or union fields fields.
struct RecordFieldRecord : APIRecord {
struct RecordFieldRecord : APIRecord, RecordContext {
RecordFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
IsFromSystemHeader),
RecordContext(Kind) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand All @@ -633,16 +671,17 @@ struct RecordFieldRecord : APIRecord {
};

/// This holds information associated with structs and unions.
struct RecordRecord : APIRecord, RecordContext {
struct RecordRecord : TagRecord {
RecordRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
RecordContext(Kind) {}
DeclarationFragments SubHeading, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator,
AccessControl Access = AccessControl())
: TagRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator, std::move(Access)) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand All @@ -651,6 +690,8 @@ struct RecordRecord : APIRecord, RecordContext {
return K == RK_Struct || K == RK_Union;
}

bool isAnonymousWithNoTypedef() { return Name.empty(); }

virtual ~RecordRecord() = 0;
};

Expand All @@ -676,9 +717,11 @@ struct StructRecord : RecordRecord {
StructRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
DeclarationFragments SubHeading, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator)
: RecordRecord(RK_Struct, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader) {}
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand Down Expand Up @@ -711,9 +754,11 @@ struct UnionRecord : RecordRecord {
UnionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
DeclarationFragments SubHeading, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator)
: RecordRecord(RK_Union, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader) {}
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand All @@ -724,15 +769,16 @@ struct UnionRecord : RecordRecord {
virtual void anchor();
};

struct CXXFieldRecord : APIRecord {
struct CXXFieldRecord : APIRecord, RecordContext {
CXXFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
bool IsFromSystemHeader)
: APIRecord(RK_CXXField, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader, std::move(Access)) {}
IsFromSystemHeader, std::move(Access)),
RecordContext(RK_CXXField) {}

CXXFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
Expand All @@ -742,7 +788,8 @@ struct CXXFieldRecord : APIRecord {
bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader, std::move(Access)) {}
IsFromSystemHeader, std::move(Access)),
RecordContext(Kind) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand Down Expand Up @@ -1118,18 +1165,18 @@ struct ObjCContainerRecord : APIRecord, RecordContext {
virtual ~ObjCContainerRecord() = 0;
};

struct CXXClassRecord : APIRecord, RecordContext {
struct CXXClassRecord : RecordRecord {
SmallVector<SymbolReference> Bases;

CXXClassRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, RecordKind Kind,
AccessControl Access, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader, std::move(Access)),
RecordContext(Kind) {}
AccessControl Access, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator = false)
: RecordRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator, std::move(Access)) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand Down
16 changes: 14 additions & 2 deletions clang/include/clang/ExtractAPI/APIRecords.inc
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ CONCRETE_RECORD(GlobalVariableTemplateSpecializationRecord,
CONCRETE_RECORD(GlobalVariableTemplatePartialSpecializationRecord,
GlobalVariableRecord,
RK_GlobalVariableTemplatePartialSpecialization)
ABSTRACT_RECORD(TagRecord, APIRecord)
CONCRETE_RECORD(EnumConstantRecord, APIRecord, RK_EnumConstant)
CONCRETE_RECORD(EnumRecord, APIRecord, RK_Enum)
CONCRETE_RECORD(EnumRecord, TagRecord, RK_Enum)
ABSTRACT_RECORD(RecordFieldRecord, APIRecord)
ABSTRACT_RECORD(RecordRecord, APIRecord)
ABSTRACT_RECORD(RecordRecord, TagRecord)
CONCRETE_RECORD(StructFieldRecord, RecordFieldRecord, RK_StructField)
CONCRETE_RECORD(StructRecord, APIRecord, RK_Struct)
CONCRETE_RECORD(UnionFieldRecord, RecordFieldRecord, RK_UnionField)
Expand Down Expand Up @@ -99,5 +100,16 @@ RECORD_CONTEXT(ClassTemplateSpecializationRecord,
RK_ClassTemplateSpecialization)
RECORD_CONTEXT(ClassTemplatePartialSpecializationRecord,
RK_ClassTemplatePartialSpecialization)
RECORD_CONTEXT(StructFieldRecord, RK_StructField)
RECORD_CONTEXT(UnionFieldRecord, RK_UnionField)
RECORD_CONTEXT(CXXFieldRecord, RK_CXXField)
RECORD_CONTEXT(StaticFieldRecord, RK_StaticField)
RECORD_CONTEXT(CXXFieldTemplateRecord, RK_CXXFieldTemplate)
RECORD_CONTEXT(GlobalVariableRecord, RK_GlobalVariable)
RECORD_CONTEXT(GlobalVariableTemplateRecord, RK_GlobalVariableTemplate)
RECORD_CONTEXT(GlobalVariableTemplateSpecializationRecord,
RK_GlobalVariableTemplateSpecialization)
RECORD_CONTEXT(GlobalVariableTemplatePartialSpecializationRecord,
RK_GlobalVariableTemplatePartialSpecialization)

#undef RECORD_CONTEXT
84 changes: 57 additions & 27 deletions clang/include/clang/ExtractAPI/DeclarationFragments.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Lex/MacroInfo.h"
#include <iterator>
#include <utility>
#include <vector>

namespace clang {
Expand Down Expand Up @@ -113,28 +115,26 @@ class DeclarationFragments {

ConstFragmentIterator cend() const { return Fragments.cend(); }

// Add a new Fragment at an arbitrary offset.
DeclarationFragments &insert(FragmentIterator It, StringRef Spelling,
FragmentKind Kind,
StringRef PreciseIdentifier = "",
const Decl *Declaration = nullptr) {
Fragments.insert(It,
Fragment(Spelling, Kind, PreciseIdentifier, Declaration));
return *this;
/// Prepend another DeclarationFragments to the beginning.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive operations.
DeclarationFragments &prepend(DeclarationFragments Other) {
return insert(begin(), std::move(Other));
}

DeclarationFragments &insert(FragmentIterator It,
DeclarationFragments &&Other) {
Fragments.insert(It, std::make_move_iterator(Other.Fragments.begin()),
std::make_move_iterator(Other.Fragments.end()));
Other.Fragments.clear();
return *this;
/// Append another DeclarationFragments to the end.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive operations.
DeclarationFragments &append(DeclarationFragments Other) {
return insert(end(), std::move(Other));
}

/// Append a new Fragment to the end of the Fragments.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive appends.
/// appending to chain up consecutive operations.
DeclarationFragments &append(StringRef Spelling, FragmentKind Kind,
StringRef PreciseIdentifier = "",
const Decl *Declaration = nullptr) {
Expand All @@ -149,18 +149,48 @@ class DeclarationFragments {
return *this;
}

/// Append another DeclarationFragments to the end.
///
/// Note: \p Other is moved from and cannot be used after a call to this
/// method.
/// Inserts another DeclarationFragments at \p It.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive appends.
DeclarationFragments &append(DeclarationFragments &&Other) {
Fragments.insert(Fragments.end(),
std::make_move_iterator(Other.Fragments.begin()),
std::make_move_iterator(Other.Fragments.end()));
Other.Fragments.clear();
/// appending to chain up consecutive operations.
DeclarationFragments &insert(FragmentIterator It,
DeclarationFragments Other) {
if (Other.Fragments.empty())
return *this;

if (Fragments.empty()) {
Fragments = std::move(Other.Fragments);
return *this;
}

const auto &OtherFrags = Other.Fragments;
auto ToInsertBegin = std::make_move_iterator(Other.begin());
auto ToInsertEnd = std::make_move_iterator(Other.end());

// If we aren't inserting at the end let's make sure that we merge their
// last fragment with It if both are text fragments.
if (It != end() && It->Kind == FragmentKind::Text &&
OtherFrags.back().Kind == FragmentKind::Text) {
auto &TheirBackSpelling = OtherFrags.back().Spelling;
It->Spelling.reserve(It->Spelling.size() + TheirBackSpelling.size());
It->Spelling.insert(It->Spelling.begin(), TheirBackSpelling.begin(),
TheirBackSpelling.end());
--ToInsertEnd;
}

// If we aren't inserting at the beginning we want to merge their first
// fragment with the fragment before It if both are text fragments.
if (It != begin() && std::prev(It)->Kind == FragmentKind::Text &&
OtherFrags.front().Kind == FragmentKind::Text) {
auto PrevIt = std::prev(It);
auto &TheirFrontSpelling = OtherFrags.front().Spelling;
PrevIt->Spelling.reserve(PrevIt->Spelling.size() +
TheirFrontSpelling.size());
PrevIt->Spelling.append(TheirFrontSpelling);
++ToInsertBegin;
}

Fragments.insert(It, ToInsertBegin, ToInsertEnd);
return *this;
}

Expand All @@ -177,13 +207,13 @@ class DeclarationFragments {
/// Append a text Fragment of a space character.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive appends.
/// appending to chain up consecutive operations.
DeclarationFragments &appendSpace();

/// Append a text Fragment of a semicolon character.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive appends.
/// appending to chain up consecutive operations.
DeclarationFragments &appendSemicolon();

/// Removes a trailing semicolon character if present.
Expand Down
76 changes: 53 additions & 23 deletions clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,29 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {

return API.createSymbolReference(Name, USR, getOwningModuleName(D));
}

bool isEmbeddedInVarDeclarator(const TagDecl &D) {
return D.getName().empty() && getTypedefName(&D).empty() &&
D.isEmbeddedInDeclarator();
}

void maybeMergeWithAnonymousTag(const DeclaratorDecl &D,
RecordContext *NewRecordContext) {
if (!NewRecordContext)
return;
auto *Tag = D.getType()->getAsTagDecl();
SmallString<128> TagUSR;
clang::index::generateUSRForDecl(Tag, TagUSR);
if (auto *Record = llvm::dyn_cast_if_present<TagRecord>(
API.findRecordForUSR(TagUSR))) {
if (Record->IsEmbeddedInVarDeclarator) {
NewRecordContext->stealRecordChain(*Record);
auto *NewRecord = cast<APIRecord>(NewRecordContext);
if (NewRecord->Comment.empty())
NewRecord->Comment = Record->Comment;
}
}
}
};

template <typename Derived>
Expand Down Expand Up @@ -273,12 +296,18 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) {
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
SubHeading, Access, isInSystemHeader(Decl));
} else
} else {
// Add the global variable record to the API set.
API.createRecord<GlobalVariableRecord>(
auto *NewRecord = API.createRecord<GlobalVariableRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
SubHeading, isInSystemHeader(Decl));

// If this global variable has a non typedef'd anonymous tag type let's
// pretend the type's child records are under us in the hierarchy.
maybeMergeWithAnonymousTag(*Decl, NewRecord);
}

return true;
}

Expand Down Expand Up @@ -364,7 +393,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitEnumDecl(const EnumDecl *Decl) {
if (Name.empty()) {
llvm::raw_svector_ostream OS(QualifiedNameBuffer);
Decl->printQualifiedName(OS);
Name = QualifiedNameBuffer.str();
Name = QualifiedNameBuffer;
}

SmallString<128> USR;
Expand All @@ -385,7 +414,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitEnumDecl(const EnumDecl *Decl) {
auto *ER = API.createRecord<EnumRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
isInSystemHeader(Decl));
isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl));

// Now collect information about the enumerators in this enum.
getDerivedExtractAPIVisitor().recordEnumConstants(ER, Decl->enumerators());
Expand Down Expand Up @@ -510,16 +539,10 @@ bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
return true;

SmallString<128> QualifiedNameBuffer;
// Collect symbol information.
StringRef Name = Decl->getName();
if (Name.empty())
Name = getTypedefName(Decl);
if (Name.empty()) {
llvm::raw_svector_ostream OS(QualifiedNameBuffer);
Decl->printQualifiedName(OS);
Name = QualifiedNameBuffer.str();
}

SmallString<128> USR;
index::generateUSRForDecl(Decl, USR);
Expand All @@ -541,12 +564,12 @@ bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
API.createRecord<UnionRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, isInSystemHeader(Decl));
SubHeading, isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl));
else
API.createRecord<StructRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, isInSystemHeader(Decl));
SubHeading, isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl));

return true;
}
Expand All @@ -559,6 +582,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
return true;

StringRef Name = Decl->getName();
if (Name.empty())
Name = getTypedefName(Decl);

SmallString<128> USR;
index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Expand All @@ -585,8 +611,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
CXXClassRecord *Record;
if (Decl->getDescribedClassTemplate()) {
// Inject template fragments before class fragments.
Declaration.insert(
Declaration.begin(),
Declaration.prepend(
DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
Decl->getDescribedClassTemplate()));
Record = API.createRecord<ClassTemplateRecord>(
Expand All @@ -598,7 +623,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
Record = API.createRecord<CXXClassRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, Kind, Access, isInSystemHeader(Decl));
SubHeading, Kind, Access, isInSystemHeader(Decl),
isEmbeddedInVarDeclarator(*Decl));

Record->Bases = getBases(Decl);

Expand Down Expand Up @@ -1075,18 +1101,17 @@ bool ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
// If the underlying type was defined as part of the typedef modify it's
// fragments directly and pretend the typedef doesn't exist.
if (auto *TagDecl = Decl->getUnderlyingType()->getAsTagDecl()) {
if (TagDecl->getName() == Decl->getName() &&
TagDecl->isEmbeddedInDeclarator() && TagDecl->isCompleteDefinition()) {
if (TagDecl->isEmbeddedInDeclarator() && TagDecl->isCompleteDefinition() &&
Decl->getName() == TagDecl->getName()) {
SmallString<128> TagUSR;
index::generateUSRForDecl(TagDecl, TagUSR);
if (auto *Record = API.findRecordForUSR(TagUSR)) {
DeclarationFragments LeadingFragments;
LeadingFragments.append("typedef",
DeclarationFragments::FragmentKind::Keyword, "",
nullptr);
DeclarationFragments::FragmentKind::Keyword);
LeadingFragments.appendSpace();
Record->Declaration.removeTrailingSemicolon()
.insert(Record->Declaration.begin(), std::move(LeadingFragments))
.prepend(std::move(LeadingFragments))
.append(" { ... } ", DeclarationFragments::FragmentKind::Text)
.append(Name, DeclarationFragments::FragmentKind::Identifier)
.appendSemicolon();
Expand Down Expand Up @@ -1221,26 +1246,31 @@ bool ExtractAPIVisitorBase<Derived>::VisitFieldDecl(const FieldDecl *Decl) {
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);

RecordContext *NewRecord = nullptr;
if (isa<CXXRecordDecl>(Decl->getDeclContext())) {
AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);

API.createRecord<CXXFieldRecord>(
NewRecord = API.createRecord<CXXFieldRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, Access, isInSystemHeader(Decl));
} else if (auto *RD = dyn_cast<RecordDecl>(Decl->getDeclContext())) {
if (RD->isUnion())
API.createRecord<UnionFieldRecord>(
NewRecord = API.createRecord<UnionFieldRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, isInSystemHeader(Decl));
else
API.createRecord<StructFieldRecord>(
NewRecord = API.createRecord<StructFieldRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, isInSystemHeader(Decl));
}

// If this field has a non typedef'd anonymous tag type let's pretend the
// type's child records are under us in the hierarchy.
maybeMergeWithAnonymousTag(*Decl, NewRecord);

return true;
}

Expand Down
14 changes: 10 additions & 4 deletions clang/include/clang/Lex/HeaderSearch.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ class TargetInfo;
/// The preprocessor keeps track of this information for each
/// file that is \#included.
struct HeaderFileInfo {
// TODO: Whether the file was included is not a property of the file itself.
// It's a preprocessor state, move it there.
/// True if this file has been included (or imported) **locally**.
LLVM_PREFERRED_TYPE(bool)
unsigned IsLocallyIncluded : 1;

// TODO: Whether the file was imported is not a property of the file itself.
// It's a preprocessor state, move it there.
/// True if this is a \#import'd file.
Expand Down Expand Up @@ -135,10 +141,10 @@ struct HeaderFileInfo {
StringRef Framework;

HeaderFileInfo()
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
External(false), isModuleHeader(false), isTextualModuleHeader(false),
isCompilingModuleHeader(false), Resolved(false),
IndexHeaderMapHeader(false), IsValid(false) {}
: IsLocallyIncluded(false), isImport(false), isPragmaOnce(false),
DirInfo(SrcMgr::C_User), External(false), isModuleHeader(false),
isTextualModuleHeader(false), isCompilingModuleHeader(false),
Resolved(false), IndexHeaderMapHeader(false), IsValid(false) {}

/// Retrieve the controlling macro for this header file, if
/// any.
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Support/RISCVVIntrinsicUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,8 @@ enum RVVRequire : uint32_t {
RVV_REQ_Zvksed = 1 << 14,
RVV_REQ_Zvksh = 1 << 15,
RVV_REQ_Zvfbfwma = 1 << 16,
RVV_REQ_Experimental = 1 << 17,
RVV_REQ_Zvfbfmin = 1 << 17,
RVV_REQ_Experimental = 1 << 18,

LLVM_MARK_AS_BITMASK_ENUM(RVV_REQ_Experimental)
};
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets/RISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/Triple.h"
#include <optional>

Expand Down
12 changes: 6 additions & 6 deletions clang/lib/Basic/Targets/WebAssembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,18 +148,18 @@ bool WebAssemblyTargetInfo::initFeatureMap(
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
const std::vector<std::string> &FeaturesVec) const {
if (CPU == "bleeding-edge") {
Features["nontrapping-fptoint"] = true;
Features["sign-ext"] = true;
Features["bulk-memory"] = true;
Features["atomics"] = true;
Features["bulk-memory"] = true;
Features["multimemory"] = true;
Features["mutable-globals"] = true;
Features["tail-call"] = true;
Features["nontrapping-fptoint"] = true;
Features["reference-types"] = true;
Features["multimemory"] = true;
Features["sign-ext"] = true;
Features["tail-call"] = true;
setSIMDLevel(Features, SIMD128, true);
} else if (CPU == "generic") {
Features["sign-ext"] = true;
Features["mutable-globals"] = true;
Features["sign-ext"] = true;
}

return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
Expand Down
6 changes: 2 additions & 4 deletions clang/lib/CodeGen/CGCoroutine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,10 +413,8 @@ llvm::Function *
CodeGenFunction::generateAwaitSuspendWrapper(Twine const &CoroName,
Twine const &SuspendPointName,
CoroutineSuspendExpr const &S) {
std::string FuncName = "__await_suspend_wrapper_";
FuncName += CoroName.str();
FuncName += '_';
FuncName += SuspendPointName.str();
std::string FuncName =
(CoroName + ".__await_suspend_wrapper__" + SuspendPointName).str();

ASTContext &C = getContext();

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/xxhash.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/TargetParser/X86TargetParser.h"
#include <optional>
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include <cstdlib> // ::getenv
#include <map>
#include <memory>
Expand Down
8 changes: 6 additions & 2 deletions clang/lib/Driver/SanitizerArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1192,7 +1192,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
BinaryMetadataIgnorelistFiles);
}

if (TC.getTriple().isOSWindows() && needsUbsanRt()) {
if (TC.getTriple().isOSWindows() && needsUbsanRt() &&
Args.hasFlag(options::OPT_frtlib_defaultlib,
options::OPT_fno_rtlib_defaultlib, true)) {
// Instruct the code generator to embed linker directives in the object file
// that cause the required runtime libraries to be linked.
CmdArgs.push_back(
Expand All @@ -1203,7 +1205,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
"--dependent-lib=" +
TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx")));
}
if (TC.getTriple().isOSWindows() && needsStatsRt()) {
if (TC.getTriple().isOSWindows() && needsStatsRt() &&
Args.hasFlag(options::OPT_frtlib_defaultlib,
options::OPT_fno_rtlib_defaultlib, true)) {
CmdArgs.push_back(Args.MakeArgString(
"--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client")));

Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Driver/ToolChains/AMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,8 +617,7 @@ void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {

std::string Linker = getToolChain().GetProgramPath(getShortName());
std::string Linker = getToolChain().GetLinkerPath();
ArgStringList CmdArgs;
CmdArgs.push_back("--no-undefined");
CmdArgs.push_back("-shared");
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Arch/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/RISCVTargetParser.h"

using namespace clang::driver;
Expand Down
10 changes: 7 additions & 3 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/Support/YAMLParser.h"
#include "llvm/TargetParser/ARMTargetParserCommon.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/TargetParser/LoongArchTargetParser.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/RISCVTargetParser.h"
#include <cctype>

Expand Down Expand Up @@ -637,7 +637,9 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
ProfileGenerateArg->getValue()));
// The default is to use Clang Instrumentation.
CmdArgs.push_back("-fprofile-instrument=clang");
if (TC.getTriple().isWindowsMSVCEnvironment()) {
if (TC.getTriple().isWindowsMSVCEnvironment() &&
Args.hasFlag(options::OPT_frtlib_defaultlib,
options::OPT_fno_rtlib_defaultlib, true)) {
// Add dependent lib for clang_rt.profile
CmdArgs.push_back(Args.MakeArgString(
"--dependent-lib=" + TC.getCompilerRTBasename(Args, "profile")));
Expand All @@ -656,7 +658,9 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
CmdArgs.push_back("-fprofile-instrument=csllvm");
}
if (PGOGenArg) {
if (TC.getTriple().isWindowsMSVCEnvironment()) {
if (TC.getTriple().isWindowsMSVCEnvironment() &&
Args.hasFlag(options::OPT_frtlib_defaultlib,
options::OPT_fno_rtlib_defaultlib, true)) {
// Add dependent lib for clang_rt.profile
CmdArgs.push_back(Args.MakeArgString(
"--dependent-lib=" + TC.getCompilerRTBasename(Args, "profile")));
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include "llvm/Frontend/Debug/Options.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/RISCVTargetParser.h"

#include <cassert>
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Gnu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
#include "llvm/Option/ArgList.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/TargetParser.h"
#include <system_error>

Expand Down
22 changes: 22 additions & 0 deletions clang/lib/ExtractAPI/API.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,28 @@ RecordContext *APIRecord::castToRecordContext(const APIRecord *Record) {
}
}

bool RecordContext::IsWellFormed() const {
// Check that First and Last are both null or both non-null.
return (First == nullptr) == (Last == nullptr);
}

void RecordContext::stealRecordChain(RecordContext &Other) {
assert(IsWellFormed());
// If we don't have an empty chain append Other's chain into ours.
if (First)
Last->NextInContext = Other.First;
else
First = Other.First;

Last = Other.Last;

// Delete Other's chain to ensure we don't accidentally traverse it.
Other.First = nullptr;
Other.Last = nullptr;
}

void RecordContext::addToRecordChain(APIRecord *Record) const {
assert(IsWellFormed());
if (!First) {
First = Record;
Last = Record;
Expand Down Expand Up @@ -95,6 +116,7 @@ SymbolReference APISet::createSymbolReference(StringRef Name, StringRef USR,
}

APIRecord::~APIRecord() {}
TagRecord::~TagRecord() {}
RecordRecord::~RecordRecord() {}
RecordFieldRecord::~RecordFieldRecord() {}
ObjCContainerRecord::~ObjCContainerRecord() {}
Expand Down
17 changes: 13 additions & 4 deletions clang/lib/ExtractAPI/DeclarationFragments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,8 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
const TagDecl *Decl = TagTy->getDecl();
// Anonymous decl, skip this fragment.
if (Decl->getName().empty())
return Fragments;
return Fragments.append("{ ... }",
DeclarationFragments::FragmentKind::Text);
SmallString<128> TagUSR;
clang::index::generateUSRForDecl(Decl, TagUSR);
return Fragments.append(Decl->getName(),
Expand Down Expand Up @@ -743,11 +744,16 @@ DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {

QualType IntegerType = EnumDecl->getIntegerType();
if (!IntegerType.isNull())
Fragments.append(": ", DeclarationFragments::FragmentKind::Text)
Fragments.appendSpace()
.append(": ", DeclarationFragments::FragmentKind::Text)
.append(
getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
.append(std::move(After));

if (EnumDecl->getName().empty())
Fragments.appendSpace().append("{ ... }",
DeclarationFragments::FragmentKind::Text);

return Fragments.appendSemicolon();
}

Expand Down Expand Up @@ -778,9 +784,12 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
else
Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);

Fragments.appendSpace();
if (!Record->getName().empty())
Fragments.appendSpace().append(
Record->getName(), DeclarationFragments::FragmentKind::Identifier);
Fragments.append(Record->getName(),
DeclarationFragments::FragmentKind::Identifier);
else
Fragments.append("{ ... }", DeclarationFragments::FragmentKind::Text);

return Fragments.appendSemicolon();
}
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,14 @@ bool SymbolGraphSerializer::shouldSkip(const APIRecord *Record) const {
if (Record->Availability.isUnconditionallyUnavailable())
return true;

// Filter out symbols without a name as we can generate correct symbol graphs
// for them. In practice these are anonymous record types that aren't attached
// to a declaration.
if (auto *Tag = dyn_cast<TagRecord>(Record)) {
if (Tag->IsEmbeddedInVarDeclarator)
return true;
}

// Filter out symbols prefixed with an underscored as they are understood to
// be symbols clients should not use.
if (Record->Name.starts_with("_"))
Expand Down
41 changes: 35 additions & 6 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -819,8 +819,11 @@ FormatToken *UnwrappedLineParser::parseBlock(bool MustBeDeclaration,
return IfLBrace;
}

if (FormatTok->is(tok::r_brace) && Tok->is(TT_NamespaceLBrace))
FormatTok->setFinalizedType(TT_NamespaceRBrace);
if (FormatTok->is(tok::r_brace)) {
FormatTok->setBlockKind(BK_Block);
if (Tok->is(TT_NamespaceLBrace))
FormatTok->setFinalizedType(TT_NamespaceRBrace);
}

const bool IsFunctionRBrace =
FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace);
Expand Down Expand Up @@ -3910,6 +3913,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
const FormatToken &InitialToken = *FormatTok;
nextToken();

const FormatToken *ClassName = nullptr;
bool IsDerived = false;
auto IsNonMacroIdentifier = [](const FormatToken *Tok) {
return Tok->is(tok::identifier) && Tok->TokenText != Tok->TokenText.upper();
};
Expand All @@ -3934,15 +3939,35 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
}
if (FormatTok->is(tok::l_square) && handleCppAttributes())
continue;
const auto *Previous = FormatTok;
nextToken();
// We can have macros in between 'class' and the class name.
if (!IsNonMacroIdentifier(FormatTok->Previous) &&
FormatTok->is(tok::l_paren)) {
parseParens();
switch (FormatTok->Tok.getKind()) {
case tok::l_paren:
// We can have macros in between 'class' and the class name.
if (!IsNonMacroIdentifier(Previous))
parseParens();
break;
case tok::coloncolon:
break;
default:
if (!ClassName && Previous->is(tok::identifier))
ClassName = Previous;
}
}

auto IsListInitialization = [&] {
if (!ClassName || IsDerived)
return false;
assert(FormatTok->is(tok::l_brace));
const auto *Prev = FormatTok->getPreviousNonComment();
assert(Prev);
return Prev != ClassName && Prev->is(tok::identifier) &&
Prev->isNot(Keywords.kw_final) && tryToParseBracedList();
};

if (FormatTok->isOneOf(tok::colon, tok::less)) {
if (FormatTok->is(tok::colon))
IsDerived = true;
int AngleNestingLevel = 0;
do {
if (FormatTok->is(tok::less))
Expand All @@ -3955,6 +3980,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
break;
}
if (FormatTok->is(tok::l_brace)) {
if (AngleNestingLevel == 0 && IsListInitialization())
return;
calculateBraceTypes(/*ExpectClassBody=*/true);
if (!tryToParseBracedList())
break;
Expand Down Expand Up @@ -3999,6 +4026,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
}
};
if (FormatTok->is(tok::l_brace)) {
if (IsListInitialization())
return;
auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken);
FormatTok->setFinalizedType(OpenBraceType);
if (ParseAsExpr) {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Lex/HeaderSearch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1574,6 +1574,7 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP,
}
}

FileInfo.IsLocallyIncluded = true;
IsFirstIncludeOfFile = PP.markIncluded(File);
return true;
}
Expand Down
18 changes: 13 additions & 5 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7953,7 +7953,8 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
// For variadic functions, we may have more args than parameters.
// For some K&R functions, we may have less args than parameters.
const auto N = std::min<unsigned>(Proto->getNumParams(), Args.size());
bool AnyScalableArgsOrRet = Proto->getReturnType()->isSizelessVectorType();
bool IsScalableRet = Proto->getReturnType()->isSizelessVectorType();
bool IsScalableArg = false;
for (unsigned ArgIdx = 0; ArgIdx < N; ++ArgIdx) {
// Args[ArgIdx] can be null in malformed code.
if (const Expr *Arg = Args[ArgIdx]) {
Expand All @@ -7968,7 +7969,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,

QualType ParamTy = Proto->getParamType(ArgIdx);
if (ParamTy->isSizelessVectorType())
AnyScalableArgsOrRet = true;
IsScalableArg = true;
QualType ArgTy = Arg->getType();
CheckArgAlignment(Arg->getExprLoc(), FDecl, std::to_string(ArgIdx + 1),
ArgTy, ParamTy);
Expand All @@ -7993,7 +7994,8 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
// arguments or return values, then warn the user that the streaming and
// non-streaming vector lengths may be different.
const auto *CallerFD = dyn_cast<FunctionDecl>(CurContext);
if (CallerFD && (!FD || !FD->getBuiltinID()) && AnyScalableArgsOrRet) {
if (CallerFD && (!FD || !FD->getBuiltinID()) &&
(IsScalableArg || IsScalableRet)) {
bool IsCalleeStreaming =
ExtInfo.AArch64SMEAttributes & FunctionType::SME_PStateSMEnabledMask;
bool IsCalleeStreamingCompatible =
Expand All @@ -8002,8 +8004,14 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD);
if (!IsCalleeStreamingCompatible &&
(CallerFnType == ArmStreamingCompatible ||
((CallerFnType == ArmStreaming) ^ IsCalleeStreaming)))
Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming);
((CallerFnType == ArmStreaming) ^ IsCalleeStreaming))) {
if (IsScalableArg)
Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
<< /*IsArg=*/true;
if (IsScalableRet)
Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
<< /*IsArg=*/false;
}
}

FunctionType::ArmStateValue CalleeArmZAState =
Expand Down
10 changes: 7 additions & 3 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12417,12 +12417,16 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
bool UsesZT0 = Attr && Attr->isNewZT0();

if (NewFD->hasAttr<ArmLocallyStreamingAttr>()) {
if (NewFD->getReturnType()->isSizelessVectorType() ||
llvm::any_of(NewFD->parameters(), [](ParmVarDecl *P) {
if (NewFD->getReturnType()->isSizelessVectorType())
Diag(NewFD->getLocation(),
diag::warn_sme_locally_streaming_has_vl_args_returns)
<< /*IsArg=*/false;
if (llvm::any_of(NewFD->parameters(), [](ParmVarDecl *P) {
return P->getOriginalType()->isSizelessVectorType();
}))
Diag(NewFD->getLocation(),
diag::warn_sme_locally_streaming_has_vl_args_returns);
diag::warn_sme_locally_streaming_has_vl_args_returns)
<< /*IsArg=*/true;
}
if (const auto *FPT = NewFD->getType()->getAs<FunctionProtoType>()) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Sema/SemaRISCVVectorLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ void RISCVIntrinsicManagerImpl::ConstructRVVIntrinsics(
{"zvksed", RVV_REQ_Zvksed},
{"zvksh", RVV_REQ_Zvksh},
{"zvfbfwma", RVV_REQ_Zvfbfwma},
{"zvfbfmin", RVV_REQ_Zvfbfmin},
{"experimental", RVV_REQ_Experimental}};

// Construction of RVVIntrinsicRecords need to sync with createRVVIntrinsics
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9460,6 +9460,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
<< ClassTemplate->getDeclName();
isPartialSpecialization = false;
Invalid = true;
}
}

Expand Down Expand Up @@ -9675,6 +9676,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
if (SkipBody && SkipBody->ShouldSkip)
return SkipBody->Previous;

Specialization->setInvalidDecl(Invalid);
return Specialization;
}

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaTemplateDeduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1914,6 +1914,9 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
if (!S.isCompleteType(Info.getLocation(), A))
return Result;

if (getCanonicalRD(A)->isInvalidDecl())
return Result;

// Reset the incorrectly deduced argument from above.
Deduced = DeducedOrig;

Expand Down
1 change: 1 addition & 0 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5184,6 +5184,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,

ParmVarDecl *Parm = Function->getParamDecl(0);
TypeSourceInfo *NewParmSI = IR.TransformType(Parm->getTypeSourceInfo());
assert(NewParmSI && "Type transformation failed.");
Parm->setType(NewParmSI->getType());
Parm->setTypeSourceInfo(NewParmSI);
};
Expand Down
14 changes: 1 addition & 13 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -12943,19 +12943,6 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
ArraySize = NewArraySize.get();
}

// Per C++0x [expr.new]p5, the type being constructed may be a
// typedef of an array type.
QualType AllocType = AllocTypeInfo->getType();
if (ArraySize && E->isTypeDependent()) {
if (const ConstantArrayType *Array =
SemaRef.Context.getAsConstantArrayType(AllocType)) {
ArraySize = IntegerLiteral::Create(SemaRef.Context, Array->getSize(),
SemaRef.Context.getSizeType(),
E->getBeginLoc());
AllocType = Array->getElementType();
}
}

// Transform the placement arguments (if any).
bool ArgumentChanged = false;
SmallVector<Expr*, 8> PlacementArgs;
Expand Down Expand Up @@ -13017,6 +13004,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
return E;
}

QualType AllocType = AllocTypeInfo->getType();
if (!ArraySize) {
// If no array size was specified, but the new expression was
// instantiated with an array type (e.g., "new T" where T is
Expand Down
81 changes: 45 additions & 36 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,34 +171,9 @@ GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) {
.ModulesPruneNonAffectingModuleMaps)
return std::nullopt;

SmallVector<const Module *> ModulesToProcess{RootModule};

const HeaderSearch &HS = PP.getHeaderSearchInfo();

SmallVector<OptionalFileEntryRef, 16> FilesByUID;
HS.getFileMgr().GetUniqueIDMapping(FilesByUID);

if (FilesByUID.size() > HS.header_file_size())
FilesByUID.resize(HS.header_file_size());

for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) {
OptionalFileEntryRef File = FilesByUID[UID];
if (!File)
continue;

const HeaderFileInfo *HFI = HS.getExistingLocalFileInfo(*File);
if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader))
continue;

for (const auto &KH : HS.findResolvedModulesForHeader(*File)) {
if (!KH.getModule())
continue;
ModulesToProcess.push_back(KH.getModule());
}
}

const ModuleMap &MM = HS.getModuleMap();
SourceManager &SourceMgr = PP.getSourceManager();
const SourceManager &SourceMgr = PP.getSourceManager();

std::set<const FileEntry *> ModuleMaps;
auto CollectIncludingModuleMaps = [&](FileID FID, FileEntryRef F) {
Expand Down Expand Up @@ -233,12 +208,48 @@ GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) {
}
};

for (const Module *CurrentModule : ModulesToProcess) {
// Handle all the affecting modules referenced from the root module.

std::queue<const Module *> Q;
Q.push(RootModule);
while (!Q.empty()) {
const Module *CurrentModule = Q.front();
Q.pop();

CollectIncludingMapsFromAncestors(CurrentModule);
for (const Module *ImportedModule : CurrentModule->Imports)
CollectIncludingMapsFromAncestors(ImportedModule);
for (const Module *UndeclaredModule : CurrentModule->UndeclaredUses)
CollectIncludingMapsFromAncestors(UndeclaredModule);

for (auto *M : CurrentModule->submodules())
Q.push(M);
}

// Handle textually-included headers that belong to other modules.

SmallVector<OptionalFileEntryRef, 16> FilesByUID;
HS.getFileMgr().GetUniqueIDMapping(FilesByUID);

if (FilesByUID.size() > HS.header_file_size())
FilesByUID.resize(HS.header_file_size());

for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) {
OptionalFileEntryRef File = FilesByUID[UID];
if (!File)
continue;

const HeaderFileInfo *HFI = HS.getExistingLocalFileInfo(*File);
if (!HFI)
continue; // We have no information on this being a header file.
if (!HFI->isCompilingModuleHeader && HFI->isModuleHeader)
continue; // Modular header, handled in the above module-based loop.
if (!HFI->isCompilingModuleHeader && !HFI->IsLocallyIncluded)
continue; // Non-modular header not included locally is not affecting.

for (const auto &KH : HS.findResolvedModulesForHeader(*File))
if (const Module *M = KH.getModule())
CollectIncludingMapsFromAncestors(M);
}

return ModuleMaps;
Expand Down Expand Up @@ -2053,14 +2064,13 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
if (!File)
continue;

// Get the file info. Skip emitting this file if we have no information on
// it as a header file (in which case HFI will be null) or if it hasn't
// changed since it was loaded. Also skip it if it's for a modular header
// from a different module; in that case, we rely on the module(s)
// containing the header to provide this information.
const HeaderFileInfo *HFI = HS.getExistingLocalFileInfo(*File);
if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader))
continue;
if (!HFI)
continue; // We have no information on this being a header file.
if (!HFI->isCompilingModuleHeader && HFI->isModuleHeader)
continue; // Header file info is tracked by the owning module file.
if (!HFI->isCompilingModuleHeader && !PP->alreadyIncluded(*File))
continue; // Non-modular header not included is not needed.

// Massage the file path into an appropriate form.
StringRef Filename = File->getName();
Expand Down Expand Up @@ -3618,7 +3628,6 @@ class ASTIdentifierTableTrait {
/// doesn't check whether the name has macros defined; use PublicMacroIterator
/// to check that.
bool isInterestingIdentifier(const IdentifierInfo *II, uint64_t MacroOffset) {
II->getObjCOrBuiltinID();
bool IsInteresting =
II->getNotableIdentifierID() !=
tok::NotableIdentifierKind::not_notable ||
Expand Down Expand Up @@ -5097,7 +5106,7 @@ void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) {
DeclsToCheckForDeferredDiags.push_back(getDeclID(D));
if (!DeclsToCheckForDeferredDiags.empty())
Stream.EmitRecord(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS,
DeclsToCheckForDeferredDiags);
DeclsToCheckForDeferredDiags);

// Write the record containing CUDA-specific declaration references.
RecordData CUDASpecialDeclRefs;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ struct StreamOperationEvaluator {
SValBuilder &SVB;
const ASTContext &ACtx;

SymbolRef StreamSym;
SymbolRef StreamSym = nullptr;
const StreamState *SS = nullptr;
const CallExpr *CE = nullptr;
StreamErrorState NewES;
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
// REQUIRES: riscv-registered-target
// RUN: %clang_cc1 -triple riscv64 -target-feature +v \
// RUN: -target-feature +experimental-zvfbfmin \
// RUN: -target-feature +experimental-zvfbfwma -disable-O0-optnone \
// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \
// RUN: FileCheck --check-prefix=CHECK-RV64 %s

#include <riscv_vector.h>

// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vle16_v_bf16mf4(
// CHECK-RV64-SAME: ptr noundef [[RS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vle.nxv1bf16.i64(<vscale x 1 x bfloat> poison, ptr [[RS1]], i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
//
vbfloat16mf4_t test_vle16_v_bf16mf4(const __bf16 *rs1, size_t vl) {
return __riscv_vle16_v_bf16mf4(rs1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vle16_v_bf16mf2(
// CHECK-RV64-SAME: ptr noundef [[RS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vle.nxv2bf16.i64(<vscale x 2 x bfloat> poison, ptr [[RS1]], i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
//
vbfloat16mf2_t test_vle16_v_bf16mf2(const __bf16 *rs1, size_t vl) {
return __riscv_vle16_v_bf16mf2(rs1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vle16_v_bf16m1(
// CHECK-RV64-SAME: ptr noundef [[RS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vle.nxv4bf16.i64(<vscale x 4 x bfloat> poison, ptr [[RS1]], i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
//
vbfloat16m1_t test_vle16_v_bf16m1(const __bf16 *rs1, size_t vl) {
return __riscv_vle16_v_bf16m1(rs1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vle16_v_bf16m2(
// CHECK-RV64-SAME: ptr noundef [[RS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vle.nxv8bf16.i64(<vscale x 8 x bfloat> poison, ptr [[RS1]], i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
//
vbfloat16m2_t test_vle16_v_bf16m2(const __bf16 *rs1, size_t vl) {
return __riscv_vle16_v_bf16m2(rs1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vle16_v_bf16m4(
// CHECK-RV64-SAME: ptr noundef [[RS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vle.nxv16bf16.i64(<vscale x 16 x bfloat> poison, ptr [[RS1]], i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
//
vbfloat16m4_t test_vle16_v_bf16m4(const __bf16 *rs1, size_t vl) {
return __riscv_vle16_v_bf16m4(rs1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vle16_v_bf16m8(
// CHECK-RV64-SAME: ptr noundef [[RS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vle.nxv32bf16.i64(<vscale x 32 x bfloat> poison, ptr [[RS1]], i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
//
vbfloat16m8_t test_vle16_v_bf16m8(const __bf16 *rs1, size_t vl) {
return __riscv_vle16_v_bf16m8(rs1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vle16_v_bf16mf4_m(
// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], ptr noundef [[RS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vle.mask.nxv1bf16.i64(<vscale x 1 x bfloat> poison, ptr [[RS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
//
vbfloat16mf4_t test_vle16_v_bf16mf4_m(vbool64_t vm, const __bf16 *rs1,
size_t vl) {
return __riscv_vle16_v_bf16mf4_m(vm, rs1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vle16_v_bf16mf2_m(
// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], ptr noundef [[RS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vle.mask.nxv2bf16.i64(<vscale x 2 x bfloat> poison, ptr [[RS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
//
vbfloat16mf2_t test_vle16_v_bf16mf2_m(vbool32_t vm, const __bf16 *rs1,
size_t vl) {
return __riscv_vle16_v_bf16mf2_m(vm, rs1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vle16_v_bf16m1_m(
// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], ptr noundef [[RS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vle.mask.nxv4bf16.i64(<vscale x 4 x bfloat> poison, ptr [[RS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
//
vbfloat16m1_t test_vle16_v_bf16m1_m(vbool16_t vm, const __bf16 *rs1,
size_t vl) {
return __riscv_vle16_v_bf16m1_m(vm, rs1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vle16_v_bf16m2_m(
// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], ptr noundef [[RS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vle.mask.nxv8bf16.i64(<vscale x 8 x bfloat> poison, ptr [[RS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
//
vbfloat16m2_t test_vle16_v_bf16m2_m(vbool8_t vm, const __bf16 *rs1, size_t vl) {
return __riscv_vle16_v_bf16m2_m(vm, rs1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vle16_v_bf16m4_m(
// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], ptr noundef [[RS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vle.mask.nxv16bf16.i64(<vscale x 16 x bfloat> poison, ptr [[RS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
//
vbfloat16m4_t test_vle16_v_bf16m4_m(vbool4_t vm, const __bf16 *rs1, size_t vl) {
return __riscv_vle16_v_bf16m4_m(vm, rs1, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vle16_v_bf16m8_m(
// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], ptr noundef [[RS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vle.mask.nxv32bf16.i64(<vscale x 32 x bfloat> poison, ptr [[RS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
//
vbfloat16m8_t test_vle16_v_bf16m8_m(vbool2_t vm, const __bf16 *rs1, size_t vl) {
return __riscv_vle16_v_bf16m8_m(vm, rs1, vl);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
// REQUIRES: riscv-registered-target
// RUN: %clang_cc1 -triple riscv64 -target-feature +v \
// RUN: -target-feature +experimental-zvfbfmin \
// RUN: -target-feature +experimental-zvfbfwma -disable-O0-optnone \
// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \
// RUN: FileCheck --check-prefix=CHECK-RV64 %s

#include <riscv_vector.h>

// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vle16ff_v_bf16mf4(
// CHECK-RV64-SAME: ptr noundef [[RS1:%.*]], ptr noundef [[NEW_VL:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { <vscale x 1 x bfloat>, i64 } @llvm.riscv.vleff.nxv1bf16.i64(<vscale x 1 x bfloat> poison, ptr [[RS1]], i64 [[VL]])
// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { <vscale x 1 x bfloat>, i64 } [[TMP0]], 0
// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { <vscale x 1 x bfloat>, i64 } [[TMP0]], 1
// CHECK-RV64-NEXT: store i64 [[TMP2]], ptr [[NEW_VL]], align 8
// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP1]]
//
vbfloat16mf4_t test_vle16ff_v_bf16mf4(const __bf16 *rs1, size_t *new_vl,
size_t vl) {
return __riscv_vle16ff_v_bf16mf4(rs1, new_vl, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vle16ff_v_bf16mf2(
// CHECK-RV64-SAME: ptr noundef [[RS1:%.*]], ptr noundef [[NEW_VL:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { <vscale x 2 x bfloat>, i64 } @llvm.riscv.vleff.nxv2bf16.i64(<vscale x 2 x bfloat> poison, ptr [[RS1]], i64 [[VL]])
// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { <vscale x 2 x bfloat>, i64 } [[TMP0]], 0
// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { <vscale x 2 x bfloat>, i64 } [[TMP0]], 1
// CHECK-RV64-NEXT: store i64 [[TMP2]], ptr [[NEW_VL]], align 8
// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP1]]
//
vbfloat16mf2_t test_vle16ff_v_bf16mf2(const __bf16 *rs1, size_t *new_vl,
size_t vl) {
return __riscv_vle16ff_v_bf16mf2(rs1, new_vl, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vle16ff_v_bf16m1(
// CHECK-RV64-SAME: ptr noundef [[RS1:%.*]], ptr noundef [[NEW_VL:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { <vscale x 4 x bfloat>, i64 } @llvm.riscv.vleff.nxv4bf16.i64(<vscale x 4 x bfloat> poison, ptr [[RS1]], i64 [[VL]])
// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { <vscale x 4 x bfloat>, i64 } [[TMP0]], 0
// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { <vscale x 4 x bfloat>, i64 } [[TMP0]], 1
// CHECK-RV64-NEXT: store i64 [[TMP2]], ptr [[NEW_VL]], align 8
// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP1]]
//
vbfloat16m1_t test_vle16ff_v_bf16m1(const __bf16 *rs1, size_t *new_vl,
size_t vl) {
return __riscv_vle16ff_v_bf16m1(rs1, new_vl, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vle16ff_v_bf16m2(
// CHECK-RV64-SAME: ptr noundef [[RS1:%.*]], ptr noundef [[NEW_VL:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { <vscale x 8 x bfloat>, i64 } @llvm.riscv.vleff.nxv8bf16.i64(<vscale x 8 x bfloat> poison, ptr [[RS1]], i64 [[VL]])
// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { <vscale x 8 x bfloat>, i64 } [[TMP0]], 0
// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { <vscale x 8 x bfloat>, i64 } [[TMP0]], 1
// CHECK-RV64-NEXT: store i64 [[TMP2]], ptr [[NEW_VL]], align 8
// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP1]]
//
vbfloat16m2_t test_vle16ff_v_bf16m2(const __bf16 *rs1, size_t *new_vl,
size_t vl) {
return __riscv_vle16ff_v_bf16m2(rs1, new_vl, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vle16ff_v_bf16m4(
// CHECK-RV64-SAME: ptr noundef [[RS1:%.*]], ptr noundef [[NEW_VL:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { <vscale x 16 x bfloat>, i64 } @llvm.riscv.vleff.nxv16bf16.i64(<vscale x 16 x bfloat> poison, ptr [[RS1]], i64 [[VL]])
// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { <vscale x 16 x bfloat>, i64 } [[TMP0]], 0
// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { <vscale x 16 x bfloat>, i64 } [[TMP0]], 1
// CHECK-RV64-NEXT: store i64 [[TMP2]], ptr [[NEW_VL]], align 8
// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP1]]
//
vbfloat16m4_t test_vle16ff_v_bf16m4(const __bf16 *rs1, size_t *new_vl,
size_t vl) {
return __riscv_vle16ff_v_bf16m4(rs1, new_vl, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vle16ff_v_bf16m8(
// CHECK-RV64-SAME: ptr noundef [[RS1:%.*]], ptr noundef [[NEW_VL:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { <vscale x 32 x bfloat>, i64 } @llvm.riscv.vleff.nxv32bf16.i64(<vscale x 32 x bfloat> poison, ptr [[RS1]], i64 [[VL]])
// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { <vscale x 32 x bfloat>, i64 } [[TMP0]], 0
// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { <vscale x 32 x bfloat>, i64 } [[TMP0]], 1
// CHECK-RV64-NEXT: store i64 [[TMP2]], ptr [[NEW_VL]], align 8
// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP1]]
//
vbfloat16m8_t test_vle16ff_v_bf16m8(const __bf16 *rs1, size_t *new_vl,
size_t vl) {
return __riscv_vle16ff_v_bf16m8(rs1, new_vl, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vle16ff_v_bf16mf4_m(
// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], ptr noundef [[RS1:%.*]], ptr noundef [[NEW_VL:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { <vscale x 1 x bfloat>, i64 } @llvm.riscv.vleff.mask.nxv1bf16.i64(<vscale x 1 x bfloat> poison, ptr [[RS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { <vscale x 1 x bfloat>, i64 } [[TMP0]], 0
// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { <vscale x 1 x bfloat>, i64 } [[TMP0]], 1
// CHECK-RV64-NEXT: store i64 [[TMP2]], ptr [[NEW_VL]], align 8
// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP1]]
//
vbfloat16mf4_t test_vle16ff_v_bf16mf4_m(vbool64_t vm, const __bf16 *rs1,
size_t *new_vl, size_t vl) {
return __riscv_vle16ff_v_bf16mf4_m(vm, rs1, new_vl, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vle16ff_v_bf16mf2_m(
// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], ptr noundef [[RS1:%.*]], ptr noundef [[NEW_VL:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { <vscale x 2 x bfloat>, i64 } @llvm.riscv.vleff.mask.nxv2bf16.i64(<vscale x 2 x bfloat> poison, ptr [[RS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { <vscale x 2 x bfloat>, i64 } [[TMP0]], 0
// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { <vscale x 2 x bfloat>, i64 } [[TMP0]], 1
// CHECK-RV64-NEXT: store i64 [[TMP2]], ptr [[NEW_VL]], align 8
// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP1]]
//
vbfloat16mf2_t test_vle16ff_v_bf16mf2_m(vbool32_t vm, const __bf16 *rs1,
size_t *new_vl, size_t vl) {
return __riscv_vle16ff_v_bf16mf2_m(vm, rs1, new_vl, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vle16ff_v_bf16m1_m(
// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], ptr noundef [[RS1:%.*]], ptr noundef [[NEW_VL:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { <vscale x 4 x bfloat>, i64 } @llvm.riscv.vleff.mask.nxv4bf16.i64(<vscale x 4 x bfloat> poison, ptr [[RS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { <vscale x 4 x bfloat>, i64 } [[TMP0]], 0
// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { <vscale x 4 x bfloat>, i64 } [[TMP0]], 1
// CHECK-RV64-NEXT: store i64 [[TMP2]], ptr [[NEW_VL]], align 8
// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP1]]
//
vbfloat16m1_t test_vle16ff_v_bf16m1_m(vbool16_t vm, const __bf16 *rs1,
size_t *new_vl, size_t vl) {
return __riscv_vle16ff_v_bf16m1_m(vm, rs1, new_vl, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vle16ff_v_bf16m2_m(
// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], ptr noundef [[RS1:%.*]], ptr noundef [[NEW_VL:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { <vscale x 8 x bfloat>, i64 } @llvm.riscv.vleff.mask.nxv8bf16.i64(<vscale x 8 x bfloat> poison, ptr [[RS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { <vscale x 8 x bfloat>, i64 } [[TMP0]], 0
// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { <vscale x 8 x bfloat>, i64 } [[TMP0]], 1
// CHECK-RV64-NEXT: store i64 [[TMP2]], ptr [[NEW_VL]], align 8
// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP1]]
//
vbfloat16m2_t test_vle16ff_v_bf16m2_m(vbool8_t vm, const __bf16 *rs1,
size_t *new_vl, size_t vl) {
return __riscv_vle16ff_v_bf16m2_m(vm, rs1, new_vl, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vle16ff_v_bf16m4_m(
// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], ptr noundef [[RS1:%.*]], ptr noundef [[NEW_VL:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { <vscale x 16 x bfloat>, i64 } @llvm.riscv.vleff.mask.nxv16bf16.i64(<vscale x 16 x bfloat> poison, ptr [[RS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { <vscale x 16 x bfloat>, i64 } [[TMP0]], 0
// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { <vscale x 16 x bfloat>, i64 } [[TMP0]], 1
// CHECK-RV64-NEXT: store i64 [[TMP2]], ptr [[NEW_VL]], align 8
// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP1]]
//
vbfloat16m4_t test_vle16ff_v_bf16m4_m(vbool4_t vm, const __bf16 *rs1,
size_t *new_vl, size_t vl) {
return __riscv_vle16ff_v_bf16m4_m(vm, rs1, new_vl, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vle16ff_v_bf16m8_m(
// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], ptr noundef [[RS1:%.*]], ptr noundef [[NEW_VL:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { <vscale x 32 x bfloat>, i64 } @llvm.riscv.vleff.mask.nxv32bf16.i64(<vscale x 32 x bfloat> poison, ptr [[RS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { <vscale x 32 x bfloat>, i64 } [[TMP0]], 0
// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { <vscale x 32 x bfloat>, i64 } [[TMP0]], 1
// CHECK-RV64-NEXT: store i64 [[TMP2]], ptr [[NEW_VL]], align 8
// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP1]]
//
vbfloat16m8_t test_vle16ff_v_bf16m8_m(vbool2_t vm, const __bf16 *rs1,
size_t *new_vl, size_t vl) {
return __riscv_vle16ff_v_bf16m8_m(vm, rs1, new_vl, vl);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
// REQUIRES: riscv-registered-target
// RUN: %clang_cc1 -triple riscv64 -target-feature +v \
// RUN: -target-feature +experimental-zvfbfmin \
// RUN: -target-feature +experimental-zvfbfwma -disable-O0-optnone \
// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \
// RUN: FileCheck --check-prefix=CHECK-RV64 %s

#include <riscv_vector.h>

// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vlmul_ext_v_bf16mf4_bf16mf2(
// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VALUE:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.vector.insert.nxv2bf16.nxv1bf16(<vscale x 2 x bfloat> poison, <vscale x 1 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
//
vbfloat16mf2_t test_vlmul_ext_v_bf16mf4_bf16mf2(vbfloat16mf4_t value) {
return __riscv_vlmul_ext_v_bf16mf4_bf16mf2(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vlmul_ext_v_bf16mf4_bf16m1(
// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.vector.insert.nxv4bf16.nxv1bf16(<vscale x 4 x bfloat> poison, <vscale x 1 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
//
vbfloat16m1_t test_vlmul_ext_v_bf16mf4_bf16m1(vbfloat16mf4_t value) {
return __riscv_vlmul_ext_v_bf16mf4_bf16m1(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vlmul_ext_v_bf16mf4_bf16m2(
// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.vector.insert.nxv8bf16.nxv1bf16(<vscale x 8 x bfloat> poison, <vscale x 1 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
//
vbfloat16m2_t test_vlmul_ext_v_bf16mf4_bf16m2(vbfloat16mf4_t value) {
return __riscv_vlmul_ext_v_bf16mf4_bf16m2(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vlmul_ext_v_bf16mf4_bf16m4(
// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.vector.insert.nxv16bf16.nxv1bf16(<vscale x 16 x bfloat> poison, <vscale x 1 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
//
vbfloat16m4_t test_vlmul_ext_v_bf16mf4_bf16m4(vbfloat16mf4_t value) {
return __riscv_vlmul_ext_v_bf16mf4_bf16m4(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vlmul_ext_v_bf16mf4_bf16m8(
// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.vector.insert.nxv32bf16.nxv1bf16(<vscale x 32 x bfloat> poison, <vscale x 1 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
//
vbfloat16m8_t test_vlmul_ext_v_bf16mf4_bf16m8(vbfloat16mf4_t value) {
return __riscv_vlmul_ext_v_bf16mf4_bf16m8(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vlmul_ext_v_bf16mf2_bf16m1(
// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.vector.insert.nxv4bf16.nxv2bf16(<vscale x 4 x bfloat> poison, <vscale x 2 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
//
vbfloat16m1_t test_vlmul_ext_v_bf16mf2_bf16m1(vbfloat16mf2_t value) {
return __riscv_vlmul_ext_v_bf16mf2_bf16m1(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vlmul_ext_v_bf16mf2_bf16m2(
// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.vector.insert.nxv8bf16.nxv2bf16(<vscale x 8 x bfloat> poison, <vscale x 2 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
//
vbfloat16m2_t test_vlmul_ext_v_bf16mf2_bf16m2(vbfloat16mf2_t value) {
return __riscv_vlmul_ext_v_bf16mf2_bf16m2(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vlmul_ext_v_bf16mf2_bf16m4(
// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.vector.insert.nxv16bf16.nxv2bf16(<vscale x 16 x bfloat> poison, <vscale x 2 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
//
vbfloat16m4_t test_vlmul_ext_v_bf16mf2_bf16m4(vbfloat16mf2_t value) {
return __riscv_vlmul_ext_v_bf16mf2_bf16m4(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vlmul_ext_v_bf16mf2_bf16m8(
// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.vector.insert.nxv32bf16.nxv2bf16(<vscale x 32 x bfloat> poison, <vscale x 2 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
//
vbfloat16m8_t test_vlmul_ext_v_bf16mf2_bf16m8(vbfloat16mf2_t value) {
return __riscv_vlmul_ext_v_bf16mf2_bf16m8(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vlmul_ext_v_bf16m1_bf16m2(
// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.vector.insert.nxv8bf16.nxv4bf16(<vscale x 8 x bfloat> poison, <vscale x 4 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
//
vbfloat16m2_t test_vlmul_ext_v_bf16m1_bf16m2(vbfloat16m1_t value) {
return __riscv_vlmul_ext_v_bf16m1_bf16m2(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vlmul_ext_v_bf16m1_bf16m4(
// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.vector.insert.nxv16bf16.nxv4bf16(<vscale x 16 x bfloat> poison, <vscale x 4 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
//
vbfloat16m4_t test_vlmul_ext_v_bf16m1_bf16m4(vbfloat16m1_t value) {
return __riscv_vlmul_ext_v_bf16m1_bf16m4(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vlmul_ext_v_bf16m1_bf16m8(
// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.vector.insert.nxv32bf16.nxv4bf16(<vscale x 32 x bfloat> poison, <vscale x 4 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
//
vbfloat16m8_t test_vlmul_ext_v_bf16m1_bf16m8(vbfloat16m1_t value) {
return __riscv_vlmul_ext_v_bf16m1_bf16m8(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vlmul_ext_v_bf16m2_bf16m4(
// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.vector.insert.nxv16bf16.nxv8bf16(<vscale x 16 x bfloat> poison, <vscale x 8 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
//
vbfloat16m4_t test_vlmul_ext_v_bf16m2_bf16m4(vbfloat16m2_t value) {
return __riscv_vlmul_ext_v_bf16m2_bf16m4(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vlmul_ext_v_bf16m2_bf16m8(
// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.vector.insert.nxv32bf16.nxv8bf16(<vscale x 32 x bfloat> poison, <vscale x 8 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
//
vbfloat16m8_t test_vlmul_ext_v_bf16m2_bf16m8(vbfloat16m2_t value) {
return __riscv_vlmul_ext_v_bf16m2_bf16m8(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vlmul_ext_v_bf16m4_bf16m8(
// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.vector.insert.nxv32bf16.nxv16bf16(<vscale x 32 x bfloat> poison, <vscale x 16 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
//
vbfloat16m8_t test_vlmul_ext_v_bf16m4_bf16m8(vbfloat16m4_t value) {
return __riscv_vlmul_ext_v_bf16m4_bf16m8(value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
// REQUIRES: riscv-registered-target
// RUN: %clang_cc1 -triple riscv64 -target-feature +v \
// RUN: -target-feature +experimental-zvfbfmin \
// RUN: -target-feature +experimental-zvfbfwma -disable-O0-optnone \
// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \
// RUN: FileCheck --check-prefix=CHECK-RV64 %s

#include <riscv_vector.h>

// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vlmul_trunc_v_bf16mf2_bf16mf4(
// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VALUE:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.vector.extract.nxv1bf16.nxv2bf16(<vscale x 2 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
//
vbfloat16mf4_t test_vlmul_trunc_v_bf16mf2_bf16mf4(vbfloat16mf2_t value) {
return __riscv_vlmul_trunc_v_bf16mf2_bf16mf4(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vlmul_trunc_v_bf16m1_bf16mf4(
// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.vector.extract.nxv1bf16.nxv4bf16(<vscale x 4 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
//
vbfloat16mf4_t test_vlmul_trunc_v_bf16m1_bf16mf4(vbfloat16m1_t value) {
return __riscv_vlmul_trunc_v_bf16m1_bf16mf4(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vlmul_trunc_v_bf16m1_bf16mf2(
// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.vector.extract.nxv2bf16.nxv4bf16(<vscale x 4 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
//
vbfloat16mf2_t test_vlmul_trunc_v_bf16m1_bf16mf2(vbfloat16m1_t value) {
return __riscv_vlmul_trunc_v_bf16m1_bf16mf2(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vlmul_trunc_v_bf16m2_bf16mf4(
// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.vector.extract.nxv1bf16.nxv8bf16(<vscale x 8 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
//
vbfloat16mf4_t test_vlmul_trunc_v_bf16m2_bf16mf4(vbfloat16m2_t value) {
return __riscv_vlmul_trunc_v_bf16m2_bf16mf4(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vlmul_trunc_v_bf16m2_bf16mf2(
// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.vector.extract.nxv2bf16.nxv8bf16(<vscale x 8 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
//
vbfloat16mf2_t test_vlmul_trunc_v_bf16m2_bf16mf2(vbfloat16m2_t value) {
return __riscv_vlmul_trunc_v_bf16m2_bf16mf2(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vlmul_trunc_v_bf16m2_bf16m1(
// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.vector.extract.nxv4bf16.nxv8bf16(<vscale x 8 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
//
vbfloat16m1_t test_vlmul_trunc_v_bf16m2_bf16m1(vbfloat16m2_t value) {
return __riscv_vlmul_trunc_v_bf16m2_bf16m1(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vlmul_trunc_v_bf16m4_bf16mf4(
// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.vector.extract.nxv1bf16.nxv16bf16(<vscale x 16 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
//
vbfloat16mf4_t test_vlmul_trunc_v_bf16m4_bf16mf4(vbfloat16m4_t value) {
return __riscv_vlmul_trunc_v_bf16m4_bf16mf4(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vlmul_trunc_v_bf16m4_bf16mf2(
// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.vector.extract.nxv2bf16.nxv16bf16(<vscale x 16 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
//
vbfloat16mf2_t test_vlmul_trunc_v_bf16m4_bf16mf2(vbfloat16m4_t value) {
return __riscv_vlmul_trunc_v_bf16m4_bf16mf2(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vlmul_trunc_v_bf16m4_bf16m1(
// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.vector.extract.nxv4bf16.nxv16bf16(<vscale x 16 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
//
vbfloat16m1_t test_vlmul_trunc_v_bf16m4_bf16m1(vbfloat16m4_t value) {
return __riscv_vlmul_trunc_v_bf16m4_bf16m1(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vlmul_trunc_v_bf16m4_bf16m2(
// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.vector.extract.nxv8bf16.nxv16bf16(<vscale x 16 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
//
vbfloat16m2_t test_vlmul_trunc_v_bf16m4_bf16m2(vbfloat16m4_t value) {
return __riscv_vlmul_trunc_v_bf16m4_bf16m2(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vlmul_trunc_v_bf16m8_bf16mf4(
// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.vector.extract.nxv1bf16.nxv32bf16(<vscale x 32 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
//
vbfloat16mf4_t test_vlmul_trunc_v_bf16m8_bf16mf4(vbfloat16m8_t value) {
return __riscv_vlmul_trunc_v_bf16m8_bf16mf4(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vlmul_trunc_v_bf16m8_bf16mf2(
// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.vector.extract.nxv2bf16.nxv32bf16(<vscale x 32 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
//
vbfloat16mf2_t test_vlmul_trunc_v_bf16m8_bf16mf2(vbfloat16m8_t value) {
return __riscv_vlmul_trunc_v_bf16m8_bf16mf2(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vlmul_trunc_v_bf16m8_bf16m1(
// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.vector.extract.nxv4bf16.nxv32bf16(<vscale x 32 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
//
vbfloat16m1_t test_vlmul_trunc_v_bf16m8_bf16m1(vbfloat16m8_t value) {
return __riscv_vlmul_trunc_v_bf16m8_bf16m1(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vlmul_trunc_v_bf16m8_bf16m2(
// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.vector.extract.nxv8bf16.nxv32bf16(<vscale x 32 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
//
vbfloat16m2_t test_vlmul_trunc_v_bf16m8_bf16m2(vbfloat16m8_t value) {
return __riscv_vlmul_trunc_v_bf16m8_bf16m2(value);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vlmul_trunc_v_bf16m8_bf16m4(
// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.vector.extract.nxv16bf16.nxv32bf16(<vscale x 32 x bfloat> [[VALUE]], i64 0)
// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
//
vbfloat16m4_t test_vlmul_trunc_v_bf16m8_bf16m4(vbfloat16m8_t value) {
return __riscv_vlmul_trunc_v_bf16m8_bf16m4(value);
}
Loading