Skip to content

Commit

Permalink
Merged main:d40413013425 into amd-gfx:85fdb0385e9e
Browse files Browse the repository at this point in the history
Local branch amd-gfx 85fdb03 Manually merged main:416884544e02 into amd-gfx:39064028b3b3
Remote branch main d404130 [libc] Fix accidental LIBC_NAMESPACE_syscall definition (llvm#69548)
  • Loading branch information
SC llvm team authored and SC llvm team committed Oct 19, 2023
2 parents 85fdb03 + d404130 commit 63f08b5
Show file tree
Hide file tree
Showing 49 changed files with 801 additions and 88 deletions.
8 changes: 8 additions & 0 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,14 @@ Let ``T`` be one of the following types:

For scalar types, consider the operation applied to a vector with a single element.

*Vector Size*
To determine the number of elements in a vector, use ``__builtin_vectorelements()``.
For fixed-sized vectors, e.g., defined via ``__attribute__((vector_size(N)))`` or ARM
NEON's vector types (e.g., ``uint16x8_t``), this returns the constant number of
elements at compile-time. For scalable vectors, e.g., SVE or RISC-V V, the number of
elements is not known at compile-time and is determined at runtime. This builtin can
be used, e.g., to increment the loop-counter in vector-type agnostic loops.

*Elementwise Builtins*

Each builtin returns a vector equivalent to applying the specified operation
Expand Down
6 changes: 6 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@ C23 Feature Support
Non-comprehensive list of changes in this release
-------------------------------------------------

* Clang now has a ``__builtin_vectorelements()`` function that determines the number of elements in a vector.
For fixed-sized vectors, e.g., defined via ``__attribute__((vector_size(N)))`` or ARM NEON's vector types
(e.g., ``uint16x8_t``), this returns the constant number of elements at compile-time.
For scalable vectors, e.g., SVE or RISC-V V, the number of elements is not known at compile-time and is
determined at runtime.

New Compiler Flags
------------------

Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -2060,6 +2060,9 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
bool isSizelessType() const;
bool isSizelessBuiltinType() const;

/// Returns true for all scalable vector types.
bool isSizelessVectorType() const;

/// Returns true for SVE scalable vector types.
bool isSVESizelessBuiltinType() const;

Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/Builtins.def
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,7 @@ BUILTIN(__builtin_debugtrap, "v", "n")
BUILTIN(__builtin_unreachable, "v", "nr")
BUILTIN(__builtin_shufflevector, "v." , "nct")
BUILTIN(__builtin_convertvector, "v." , "nct")
BUILTIN(__builtin_vectorelements, "v." , "nct")
BUILTIN(__builtin_alloca, "v*z" , "Fn")
BUILTIN(__builtin_alloca_uninitialized, "v*z", "Fn")
BUILTIN(__builtin_alloca_with_align, "v*zIz", "Fn")
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticASTKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,8 @@ def note_constexpr_unsupported_layout : Note<
"type %0 has unexpected layout">;
def note_constexpr_unsupported_flexible_array : Note<
"flexible array initialization is not yet supported">;
def note_constexpr_non_const_vectorelements : Note<
"cannot determine number of elements for sizeless vectors in a constant expression">;
def err_experimental_clang_interp_failed : Error<
"the experimental clang interpreter failed to evaluate an expression">;

Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -10169,8 +10169,8 @@ def err_shufflevector_argument_too_large : Error<

def err_convertvector_non_vector : Error<
"first argument to __builtin_convertvector must be a vector">;
def err_convertvector_non_vector_type : Error<
"second argument to __builtin_convertvector must be a vector type">;
def err_builtin_non_vector_type : Error<
"%0 argument to %1 must be of vector type">;
def err_convertvector_incompatible_vector : Error<
"first two arguments to __builtin_convertvector must have the same number of elements">;

Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/TokenKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,7 @@ ALIAS("_pascal" , __pascal , KEYBORLAND)

// Clang Extensions.
KEYWORD(__builtin_convertvector , KEYALL)
UNARY_EXPR_OR_TYPE_TRAIT(__builtin_vectorelements, VectorElements, KEYALL)
ALIAS("__char16_t" , char16_t , KEYCXX)
ALIAS("__char32_t" , char32_t , KEYCXX)
KEYWORD(__builtin_bit_cast , KEYALL)
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/arm_sve.td
Original file line number Diff line number Diff line change
Expand Up @@ -1862,6 +1862,7 @@ def SVBGRP_N : SInst<"svbgrp[_n_{d}]", "dda", "UcUsUiUl", MergeNone, "aarch64_sv
let TargetGuard = "sve2p1" in {
def SVFCLAMP : SInst<"svclamp[_{d}]", "dddd", "hfd", MergeNone, "aarch64_sve_fclamp", [], []>;
def SVPTRUE_COUNT : SInst<"svptrue_{d}", "}v", "QcQsQiQl", MergeNone, "aarch64_sve_ptrue_{d}", [IsOverloadNone], []>;
def SVPFALSE_COUNT_ALIAS : SInst<"svpfalse_c", "}v", "", MergeNone, "", [IsOverloadNone]>;

def SVPEXT_SINGLE : SInst<"svpext_lane_{d}", "P}i", "QcQsQiQl", MergeNone, "aarch64_sve_pext", [], [ImmCheck<1, ImmCheck0_3>]>;
def SVPEXT_X2 : SInst<"svpext_lane_{d}_x2", "2.P}i", "QcQsQiQl", MergeNone, "aarch64_sve_pext_x2", [], [ImmCheck<1, ImmCheck0_1>]>;
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13595,6 +13595,20 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
Info.Ctx.getOpenMPDefaultSimdAlign(E->getArgumentType()))
.getQuantity(),
E);
case UETT_VectorElements: {
QualType Ty = E->getTypeOfArgument();
// If the vector has a fixed size, we can determine the number of elements
// at compile time.
if (Ty->isVectorType())
return Success(Ty->castAs<VectorType>()->getNumElements(), E);

assert(Ty->isSizelessVectorType());
if (Info.InConstantContext)
Info.CCEDiag(E, diag::note_constexpr_non_const_vectorelements)
<< E->getSourceRange();

return false;
}
}

llvm_unreachable("unknown expr/type trait");
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5127,6 +5127,14 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
Diags.Report(DiagID);
return;
}
case UETT_VectorElements: {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error,
"cannot yet mangle __builtin_vectorelements expression");
Diags.Report(DiagID);
return;
}
}
break;
}
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2369,7 +2369,7 @@ bool Type::isIncompleteType(NamedDecl **Def) const {
}

bool Type::isSizelessBuiltinType() const {
if (isSVESizelessBuiltinType() || isRVVSizelessBuiltinType())
if (isSizelessVectorType())
return true;

if (const BuiltinType *BT = getAs<BuiltinType>()) {
Expand Down Expand Up @@ -2403,6 +2403,10 @@ bool Type::isWebAssemblyTableType() const {

bool Type::isSizelessType() const { return isSizelessBuiltinType(); }

bool Type::isSizelessVectorType() const {
return isSVESizelessBuiltinType() || isRVVSizelessBuiltinType();
}

bool Type::isSVESizelessBuiltinType() const {
if (const BuiltinType *BT = getAs<BuiltinType>()) {
switch (BT->getKind()) {
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10160,6 +10160,13 @@ Value *CodeGenFunction::EmitAArch64SVEBuiltinExpr(unsigned BuiltinID,
case SVE::BI__builtin_sve_svpfalse_b:
return ConstantInt::getFalse(Ty);

case SVE::BI__builtin_sve_svpfalse_c: {
auto SVBoolTy = ScalableVectorType::get(Builder.getInt1Ty(), 16);
Function *CastToSVCountF =
CGM.getIntrinsic(Intrinsic::aarch64_sve_convert_from_svbool, Ty);
return Builder.CreateCall(CastToSVCountF, ConstantInt::getFalse(SVBoolTy));
}

case SVE::BI__builtin_sve_svlen_bf16:
case SVE::BI__builtin_sve_svlen_f16:
case SVE::BI__builtin_sve_svlen_f32:
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3083,6 +3083,9 @@ ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
E->getTypeOfArgument()->getPointeeType()))
.getQuantity();
return llvm::ConstantInt::get(CGF.SizeTy, Alignment);
} else if (E->getKind() == UETT_VectorElements) {
auto *VecTy = cast<llvm::VectorType>(ConvertType(E->getTypeOfArgument()));
return Builder.CreateElementCount(CGF.SizeTy, VecTy->getElementCount());
}

// If this isn't sizeof(vla), the result must be constant; use the constant
Expand Down
46 changes: 39 additions & 7 deletions clang/lib/Lex/Lexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@
#include <tuple>
#include <utility>

#ifdef __SSE4_2__
#include <nmmintrin.h>
#endif

using namespace clang;

//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -1847,19 +1851,47 @@ bool Lexer::LexUnicodeIdentifierStart(Token &Result, uint32_t C,
return true;
}

static const char *
fastParseASCIIIdentifier(const char *CurPtr,
[[maybe_unused]] const char *BufferEnd) {
#ifdef __SSE4_2__
alignas(16) static constexpr char AsciiIdentifierRange[16] = {
'_', '_', 'A', 'Z', 'a', 'z', '0', '9',
};
constexpr ssize_t BytesPerRegister = 16;

__m128i AsciiIdentifierRangeV =
_mm_load_si128((const __m128i *)AsciiIdentifierRange);

while (LLVM_LIKELY(BufferEnd - CurPtr >= BytesPerRegister)) {
__m128i Cv = _mm_loadu_si128((const __m128i *)(CurPtr));

int Consumed = _mm_cmpistri(AsciiIdentifierRangeV, Cv,
_SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES |
_SIDD_UBYTE_OPS | _SIDD_NEGATIVE_POLARITY);
CurPtr += Consumed;
if (Consumed == BytesPerRegister)
continue;
return CurPtr;
}
#endif

unsigned char C = *CurPtr;
while (isAsciiIdentifierContinue(C))
C = *++CurPtr;
return CurPtr;
}

bool Lexer::LexIdentifierContinue(Token &Result, const char *CurPtr) {
// Match [_A-Za-z0-9]*, we have already matched an identifier start.

while (true) {
unsigned char C = *CurPtr;
// Fast path.
if (isAsciiIdentifierContinue(C)) {
++CurPtr;
continue;
}

CurPtr = fastParseASCIIIdentifier(CurPtr, BufferEnd);

unsigned Size;
// Slow path: handle trigraph, unicode codepoints, UCNs.
C = getCharAndSize(CurPtr, Size);
unsigned char C = getCharAndSize(CurPtr, Size);
if (isAsciiIdentifierContinue(C)) {
CurPtr = ConsumeChar(CurPtr, Size, Result);
continue;
Expand Down
9 changes: 7 additions & 2 deletions clang/lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1463,6 +1463,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression
// unary-expression: '__builtin_omp_required_simd_align' '(' type-name ')'
case tok::kw___builtin_omp_required_simd_align:
case tok::kw___builtin_vectorelements:
if (NotPrimaryExpression)
*NotPrimaryExpression = true;
AllowSuffix = false;
Expand Down Expand Up @@ -2339,7 +2340,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual, tok::kw_sizeof,
tok::kw___alignof, tok::kw_alignof, tok::kw__Alignof,
tok::kw_vec_step,
tok::kw___builtin_omp_required_simd_align) &&
tok::kw___builtin_omp_required_simd_align,
tok::kw___builtin_vectorelements) &&
"Not a typeof/sizeof/alignof/vec_step expression!");

ExprResult Operand;
Expand Down Expand Up @@ -2460,7 +2462,8 @@ ExprResult Parser::ParseSYCLUniqueStableNameExpression() {
ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof,
tok::kw__Alignof, tok::kw_vec_step,
tok::kw___builtin_omp_required_simd_align) &&
tok::kw___builtin_omp_required_simd_align,
tok::kw___builtin_vectorelements) &&
"Not a sizeof/alignof/vec_step expression!");
Token OpTok = Tok;
ConsumeToken();
Expand Down Expand Up @@ -2539,6 +2542,8 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
ExprKind = UETT_VecStep;
else if (OpTok.is(tok::kw___builtin_omp_required_simd_align))
ExprKind = UETT_OpenMPRequiredSimdAlign;
else if (OpTok.is(tok::kw___builtin_vectorelements))
ExprKind = UETT_VectorElements;

if (isCastExpr)
return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(),
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8752,8 +8752,9 @@ ExprResult Sema::SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
diag::err_convertvector_non_vector)
<< E->getSourceRange());
if (!DstTy->isVectorType() && !DstTy->isDependentType())
return ExprError(Diag(BuiltinLoc,
diag::err_convertvector_non_vector_type));
return ExprError(Diag(BuiltinLoc, diag::err_builtin_non_vector_type)
<< "second"
<< "__builtin_convertvector");

if (!SrcTy->isDependentType() && !DstTy->isDependentType()) {
unsigned SrcElts = SrcTy->castAs<VectorType>()->getNumElements();
Expand Down
23 changes: 23 additions & 0 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TypeTraits.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/AnalysisBasedWarnings.h"
Expand Down Expand Up @@ -4353,6 +4354,18 @@ static bool CheckVecStepTraitOperandType(Sema &S, QualType T,
return false;
}

static bool CheckVectorElementsTraitOperandType(Sema &S, QualType T,
SourceLocation Loc,
SourceRange ArgRange) {
// builtin_vectorelements supports both fixed-sized and scalable vectors.
if (!T->isVectorType() && !T->isSizelessVectorType())
return S.Diag(Loc, diag::err_builtin_non_vector_type)
<< ""
<< "__builtin_vectorelements" << T << ArgRange;

return false;
}

static bool CheckExtensionTraitOperandType(Sema &S, QualType T,
SourceLocation Loc,
SourceRange ArgRange,
Expand Down Expand Up @@ -4454,6 +4467,10 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
return CheckVecStepTraitOperandType(*this, ExprTy, E->getExprLoc(),
E->getSourceRange());

if (ExprKind == UETT_VectorElements)
return CheckVectorElementsTraitOperandType(*this, ExprTy, E->getExprLoc(),
E->getSourceRange());

// Explicitly list some types as extensions.
if (!CheckExtensionTraitOperandType(*this, ExprTy, E->getExprLoc(),
E->getSourceRange(), ExprKind))
Expand Down Expand Up @@ -4745,6 +4762,10 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType,
if (ExprKind == UETT_VecStep)
return CheckVecStepTraitOperandType(*this, ExprType, OpLoc, ExprRange);

if (ExprKind == UETT_VectorElements)
return CheckVectorElementsTraitOperandType(*this, ExprType, OpLoc,
ExprRange);

// Explicitly list some types as extensions.
if (!CheckExtensionTraitOperandType(*this, ExprType, OpLoc, ExprRange,
ExprKind))
Expand Down Expand Up @@ -4851,6 +4872,8 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
} else if (E->refersToBitField()) { // C99 6.5.3.4p1.
Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 0;
isInvalid = true;
} else if (ExprKind == UETT_VectorElements) {
isInvalid = CheckUnaryExprOrTypeTraitOperand(E, UETT_VectorElements);
} else {
isInvalid = CheckUnaryExprOrTypeTraitOperand(E, UETT_SizeOf);
}
Expand Down
30 changes: 30 additions & 0 deletions clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pfalse.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// REQUIRES: aarch64-registered-target
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes=mem2reg,tailcallelim | FileCheck %s
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK
// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes=mem2reg,tailcallelim | FileCheck %s
// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s
#include <arm_sve.h>

#ifdef SVE_OVERLOADED_FORMS
// A simple used,unused... macro, long enough to represent any SVE builtin.
#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3
#else
#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4
#endif

// CHECK-LABEL: @test_svpfalse_c(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt(<vscale x 16 x i1> zeroinitializer)
// CHECK-NEXT: ret target("aarch64.svcount") [[TMP0]]
//
// CPP-CHECK-LABEL: @_Z15test_svpfalse_cv(
// CPP-CHECK-NEXT: entry:
// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt(<vscale x 16 x i1> zeroinitializer)
// CPP-CHECK-NEXT: ret target("aarch64.svcount") [[TMP0]]
//
svcount_t test_svpfalse_c()
{
return SVE_ACLE_FUNC(svpfalse_c,,,)();
}
Loading

0 comments on commit 63f08b5

Please sign in to comment.