Skip to content

Commit

Permalink
[AArch64] Warn when calling a NEON builtin in a streaming function (#…
Browse files Browse the repository at this point in the history
…73672)

This patch introduces a warning that is emitted when a Neon builtin is
called from a streaming function, as that situation is not supported.

Uses work by Kerry McLaughlin.
  • Loading branch information
SamTebbs33 committed Nov 30, 2023
1 parent 1f88e62 commit 5234fe3
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -3148,6 +3148,9 @@ def err_attribute_bad_sve_vector_size : Error<
def err_attribute_arm_feature_sve_bits_unsupported : Error<
"%0 is only supported when '-msve-vector-bits=<bits>' is specified with a "
"value of 128, 256, 512, 1024 or 2048.">;
def warn_attribute_arm_sm_incompat_builtin : Warning<
"builtin call has undefined behaviour when called from a %0 function">,
InGroup<DiagGroup<"undefined-arm-streaming">>;
def err_sve_vector_in_non_sve_target : Error<
"SVE vector type %0 cannot be used in a target without sve">;
def err_attribute_riscv_rvv_bits_unsupported : Error<
Expand Down
49 changes: 49 additions & 0 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2993,6 +2993,38 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context,
llvm_unreachable("Invalid NeonTypeFlag!");
}

enum ArmStreamingType { ArmNonStreaming, ArmStreaming, ArmStreamingCompatible };

static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) {
if (FD->hasAttr<ArmLocallyStreamingAttr>())
return ArmStreaming;
if (const auto *T = FD->getType()->getAs<FunctionProtoType>()) {
if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask)
return ArmStreaming;
if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMCompatibleMask)
return ArmStreamingCompatible;
}
return ArmNonStreaming;
}

static void checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall,
const FunctionDecl *FD,
ArmStreamingType BuiltinType) {
ArmStreamingType FnType = getArmStreamingFnType(FD);

if (FnType == ArmStreaming && BuiltinType == ArmNonStreaming) {
S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin)
<< TheCall->getSourceRange() << "streaming";
}

if (FnType == ArmStreamingCompatible &&
BuiltinType != ArmStreamingCompatible) {
S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin)
<< TheCall->getSourceRange() << "streaming compatible";
return;
}
}

bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
// Range check SVE intrinsics that take immediate values.
SmallVector<std::tuple<int,int,int>, 3> ImmChecks;
Expand Down Expand Up @@ -3148,6 +3180,23 @@ bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {

bool Sema::CheckNeonBuiltinFunctionCall(const TargetInfo &TI,
unsigned BuiltinID, CallExpr *TheCall) {
if (const FunctionDecl *FD = getCurFunctionDecl()) {

switch (BuiltinID) {
default:
break;
#define GET_NEON_BUILTINS
#define TARGET_BUILTIN(id, ...) case NEON::BI##id:
#define BUILTIN(id, ...) case NEON::BI##id:
#include "clang/Basic/arm_neon.inc"
checkArmStreamingBuiltin(*this, TheCall, FD, ArmNonStreaming);
break;
#undef TARGET_BUILTIN
#undef BUILTIN
#undef GET_NEON_BUILTINS
}
}

llvm::APSInt Result;
uint64_t mask = 0;
unsigned TV = 0;
Expand Down
22 changes: 22 additions & 0 deletions clang/test/Sema/aarch64-incompat-sm-builtin-calls.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \
// RUN: -target-feature +sme -target-feature +sve2 -target-feature +neon -fsyntax-only -verify %s

// REQUIRES: aarch64-registered-target

#include "arm_neon.h"

int16x8_t incompat_neon_sm(int16x8_t splat) __arm_streaming {
// expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}}
return (int16x8_t)__builtin_neon_vqaddq_v((int8x16_t)splat, (int8x16_t)splat, 33);
}

__arm_locally_streaming int16x8_t incompat_neon_ls(int16x8_t splat) {
// expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}}
return (int16x8_t)__builtin_neon_vqaddq_v((int8x16_t)splat, (int8x16_t)splat, 33);
}

int16x8_t incompat_neon_smc(int16x8_t splat) __arm_streaming_compatible {
// expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming compatible function}}
return (int16x8_t)__builtin_neon_vqaddq_v((int8x16_t)splat, (int8x16_t)splat, 33);
}

0 comments on commit 5234fe3

Please sign in to comment.