Skip to content

Commit 5234fe3

Browse files
authored
[AArch64] Warn when calling a NEON builtin in a streaming function (#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.
1 parent 1f88e62 commit 5234fe3

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3148,6 +3148,9 @@ def err_attribute_bad_sve_vector_size : Error<
31483148
def err_attribute_arm_feature_sve_bits_unsupported : Error<
31493149
"%0 is only supported when '-msve-vector-bits=<bits>' is specified with a "
31503150
"value of 128, 256, 512, 1024 or 2048.">;
3151+
def warn_attribute_arm_sm_incompat_builtin : Warning<
3152+
"builtin call has undefined behaviour when called from a %0 function">,
3153+
InGroup<DiagGroup<"undefined-arm-streaming">>;
31513154
def err_sve_vector_in_non_sve_target : Error<
31523155
"SVE vector type %0 cannot be used in a target without sve">;
31533156
def err_attribute_riscv_rvv_bits_unsupported : Error<

clang/lib/Sema/SemaChecking.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2993,6 +2993,38 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context,
29932993
llvm_unreachable("Invalid NeonTypeFlag!");
29942994
}
29952995

2996+
enum ArmStreamingType { ArmNonStreaming, ArmStreaming, ArmStreamingCompatible };
2997+
2998+
static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) {
2999+
if (FD->hasAttr<ArmLocallyStreamingAttr>())
3000+
return ArmStreaming;
3001+
if (const auto *T = FD->getType()->getAs<FunctionProtoType>()) {
3002+
if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask)
3003+
return ArmStreaming;
3004+
if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMCompatibleMask)
3005+
return ArmStreamingCompatible;
3006+
}
3007+
return ArmNonStreaming;
3008+
}
3009+
3010+
static void checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall,
3011+
const FunctionDecl *FD,
3012+
ArmStreamingType BuiltinType) {
3013+
ArmStreamingType FnType = getArmStreamingFnType(FD);
3014+
3015+
if (FnType == ArmStreaming && BuiltinType == ArmNonStreaming) {
3016+
S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin)
3017+
<< TheCall->getSourceRange() << "streaming";
3018+
}
3019+
3020+
if (FnType == ArmStreamingCompatible &&
3021+
BuiltinType != ArmStreamingCompatible) {
3022+
S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin)
3023+
<< TheCall->getSourceRange() << "streaming compatible";
3024+
return;
3025+
}
3026+
}
3027+
29963028
bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
29973029
// Range check SVE intrinsics that take immediate values.
29983030
SmallVector<std::tuple<int,int,int>, 3> ImmChecks;
@@ -3148,6 +3180,23 @@ bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
31483180

31493181
bool Sema::CheckNeonBuiltinFunctionCall(const TargetInfo &TI,
31503182
unsigned BuiltinID, CallExpr *TheCall) {
3183+
if (const FunctionDecl *FD = getCurFunctionDecl()) {
3184+
3185+
switch (BuiltinID) {
3186+
default:
3187+
break;
3188+
#define GET_NEON_BUILTINS
3189+
#define TARGET_BUILTIN(id, ...) case NEON::BI##id:
3190+
#define BUILTIN(id, ...) case NEON::BI##id:
3191+
#include "clang/Basic/arm_neon.inc"
3192+
checkArmStreamingBuiltin(*this, TheCall, FD, ArmNonStreaming);
3193+
break;
3194+
#undef TARGET_BUILTIN
3195+
#undef BUILTIN
3196+
#undef GET_NEON_BUILTINS
3197+
}
3198+
}
3199+
31513200
llvm::APSInt Result;
31523201
uint64_t mask = 0;
31533202
unsigned TV = 0;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \
3+
// RUN: -target-feature +sme -target-feature +sve2 -target-feature +neon -fsyntax-only -verify %s
4+
5+
// REQUIRES: aarch64-registered-target
6+
7+
#include "arm_neon.h"
8+
9+
int16x8_t incompat_neon_sm(int16x8_t splat) __arm_streaming {
10+
// expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}}
11+
return (int16x8_t)__builtin_neon_vqaddq_v((int8x16_t)splat, (int8x16_t)splat, 33);
12+
}
13+
14+
__arm_locally_streaming int16x8_t incompat_neon_ls(int16x8_t splat) {
15+
// expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}}
16+
return (int16x8_t)__builtin_neon_vqaddq_v((int8x16_t)splat, (int8x16_t)splat, 33);
17+
}
18+
19+
int16x8_t incompat_neon_smc(int16x8_t splat) __arm_streaming_compatible {
20+
// expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming compatible function}}
21+
return (int16x8_t)__builtin_neon_vqaddq_v((int8x16_t)splat, (int8x16_t)splat, 33);
22+
}

0 commit comments

Comments
 (0)