https://github.com/kieroxide updated https://github.com/llvm/llvm-project/pull/212459
>From 81fc881ca80c9d44883c7487a6db7e968a91f5ca Mon Sep 17 00:00:00 2001 From: Kieran Bailey <[email protected]> Date: Fri, 31 Jul 2026 09:27:31 +0000 Subject: [PATCH] [Clang][AArch64] Fix immediate range check for NEON widening left-shifts Change the immediate check for c intrinsic vshll_n from 0..((eltsize*2) - 1) to 0..eltsize. The ACLE specifies this intrinsic to have a valid immediate range size of 0..eltsize. Update the range check to match the specified behaviour --- .../include/clang/Basic/arm_immcheck_incl.td | 43 ++++++++++--------- clang/include/clang/Basic/arm_neon.td | 12 +++--- clang/lib/Sema/SemaARM.cpp | 4 ++ .../vector-shift-left.c | 39 +++++++++++------ 4 files changed, 58 insertions(+), 40 deletions(-) diff --git a/clang/include/clang/Basic/arm_immcheck_incl.td b/clang/include/clang/Basic/arm_immcheck_incl.td index 6892b8299771b..52f3f57a9b37d 100644 --- a/clang/include/clang/Basic/arm_immcheck_incl.td +++ b/clang/include/clang/Basic/arm_immcheck_incl.td @@ -11,27 +11,28 @@ def ImmCheckExtract : ImmCheckType<2>; // 0..(2048/sizeinbits(elt) def ImmCheckShiftRight : ImmCheckType<3>; // 1..sizeinbits(elt) def ImmCheckShiftRightNarrow : ImmCheckType<4>; // 1..sizeinbits(elt)/2 def ImmCheckShiftLeft : ImmCheckType<5>; // 0..(sizeinbits(elt) - 1) -def ImmCheck0_7 : ImmCheckType<6>; // 0..7 -def ImmCheckLaneIndex : ImmCheckType<7>; // 0..(container_size/(sizeinbits(elt)) - 1) -def ImmCheckCvt : ImmCheckType<8>; // 1..sizeinbits(elt) (same as ShiftRight) -def ImmCheckLaneIndexCompRotate : ImmCheckType<9>; // 0..(container_size/(2*sizeinbits(elt)) - 1) -def ImmCheckLaneIndexDot : ImmCheckType<10>; // 0..(container_size/(4*sizeinbits(elt)) - 1) -def ImmCheckComplexRot90_270 : ImmCheckType<11>; // [90,270] -def ImmCheckComplexRotAll90 : ImmCheckType<12>; // [0, 90, 180,270] -def ImmCheck0_13 : ImmCheckType<13>; // 0..13 -def ImmCheck0_1 : ImmCheckType<14>; // 0..1 -def ImmCheck0_2 : ImmCheckType<15>; // 0..2 -def ImmCheck0_3 : ImmCheckType<16>; // 0..3 -def ImmCheck0_0 : ImmCheckType<17>; // 0..0 -def ImmCheck0_15 : ImmCheckType<18>; // 0..15 -def ImmCheck0_255 : ImmCheckType<19>; // 0..255 -def ImmCheck2_4_Mul2 : ImmCheckType<20>; // 2, 4 -def ImmCheck1_1 : ImmCheckType<21>; // 1..1 -def ImmCheck1_3 : ImmCheckType<22>; // 1..3 -def ImmCheck1_7 : ImmCheckType<23>; // 1..7 -def ImmCheck1_32 : ImmCheckType<24>; // 1..32 -def ImmCheck1_64 : ImmCheckType<25>; // 1..64 -def ImmCheck0_63 : ImmCheckType<26>; // 0..63 +def ImmCheckShiftLeftLong : ImmCheckType<6>; // 0..(sizeinbits(elt)/2) +def ImmCheck0_7 : ImmCheckType<7>; // 0..7 +def ImmCheckLaneIndex : ImmCheckType<8>; // 0..(container_size/(sizeinbits(elt)) - 1) +def ImmCheckCvt : ImmCheckType<9>; // 1..sizeinbits(elt) (same as ShiftRight) +def ImmCheckLaneIndexCompRotate : ImmCheckType<10>; // 0..(container_size/(2*sizeinbits(elt)) - 1) +def ImmCheckLaneIndexDot : ImmCheckType<11>; // 0..(container_size/(4*sizeinbits(elt)) - 1) +def ImmCheckComplexRot90_270 : ImmCheckType<12>; // [90,270] +def ImmCheckComplexRotAll90 : ImmCheckType<13>; // [0, 90, 180,270] +def ImmCheck0_13 : ImmCheckType<14>; // 0..13 +def ImmCheck0_1 : ImmCheckType<15>; // 0..1 +def ImmCheck0_2 : ImmCheckType<16>; // 0..2 +def ImmCheck0_3 : ImmCheckType<17>; // 0..3 +def ImmCheck0_0 : ImmCheckType<18>; // 0..0 +def ImmCheck0_15 : ImmCheckType<19>; // 0..15 +def ImmCheck0_255 : ImmCheckType<20>; // 0..255 +def ImmCheck2_4_Mul2 : ImmCheckType<21>; // 2, 4 +def ImmCheck1_1 : ImmCheckType<22>; // 1..1 +def ImmCheck1_3 : ImmCheckType<23>; // 1..3 +def ImmCheck1_7 : ImmCheckType<24>; // 1..7 +def ImmCheck1_32 : ImmCheckType<25>; // 1..32 +def ImmCheck1_64 : ImmCheckType<26>; // 1..64 +def ImmCheck0_63 : ImmCheckType<27>; // 0..63 class ImmCheck<int immArgIdx, ImmCheckType kind, int typeArgIdx = -1> { // Parameter index of immediate argument to be verified diff --git a/clang/include/clang/Basic/arm_neon.td b/clang/include/clang/Basic/arm_neon.td index 041a420875290..ee16669605ae6 100644 --- a/clang/include/clang/Basic/arm_neon.td +++ b/clang/include/clang/Basic/arm_neon.td @@ -432,13 +432,13 @@ def VRSHRN_N : IInst<"vrshrn_n", "<QI", "silUsUiUl", def VQRSHRN_N : SInst<"vqrshrn_n", "<QI", "silUsUiUl", [ImmCheck<1, ImmCheckShiftRight>]>; -// Widening left-shifts should have a range of 0..(sizeinbits(arg)-1). -// This polymorphic builtin is supplied the wider return type as it's overloaded -// base type, so the range here is actually 0..(sizeinbits(arg)*2). -// This cannot be rectified currently due to a use of vshll_n_s16 with an -// out-of-bounds immediate in the defintiion of vcvt_f32_bf16. +// Widening left-shifts should have an immediate range of 0..sizeinbits(arg). +// However, as the overloaded type code that is supplied to a polymorphic builtin +// is that of the return type (twice as wide as the argument in this case). +// ImmCheckShiftLeftLong produces the correct behavior here. def VSHLL_N : SInst<"vshll_n", "(>Q).I", "csiUcUsUi", - [ImmCheck<1, ImmCheckShiftLeft>]>; + [ImmCheck<1, ImmCheckShiftLeftLong>]>; + [ImmCheck<1, ImmCheckShiftLeftLong>]>; //////////////////////////////////////////////////////////////////////////////// // E.3.13 Shifts with insert diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp index 5e7504fab416d..f549016bb17ae 100644 --- a/clang/lib/Sema/SemaARM.cpp +++ b/clang/lib/Sema/SemaARM.cpp @@ -452,6 +452,10 @@ bool SemaARM::CheckImmediateArg(CallExpr *TheCall, unsigned CheckTy, if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, EltBitWidth - 1)) return true; break; + case ImmCheckType::ImmCheckShiftLeftLong: + if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, (EltBitWidth / 2))) + return true; + break; case ImmCheckType::ImmCheckLaneIndex: if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, (ContainerBitWidth / EltBitWidth) - 1)) diff --git a/clang/test/Sema/aarch64-neon-immediate-ranges/vector-shift-left.c b/clang/test/Sema/aarch64-neon-immediate-ranges/vector-shift-left.c index 1def72fc843d9..c136e16ffec0a 100644 --- a/clang/test/Sema/aarch64-neon-immediate-ranges/vector-shift-left.c +++ b/clang/test/Sema/aarch64-neon-immediate-ranges/vector-shift-left.c @@ -1,3 +1,4 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 // RUN: %clang_cc1 -triple aarch64-linux-gnu -target-feature +neon -ffreestanding -fsyntax-only -verify %s #include <arm_neon.h> @@ -328,63 +329,75 @@ void test_vector_saturating_shift_left_u64(uint64x1_t arg_u64x1, uint64_t arg_u6 void test_vector_shift_left_and_widen_s8(int8x8_t arg_i8x8, int8x16_t arg_i8x16) { vshll_n_s8(arg_i8x8, 0); - vshll_n_s8(arg_i8x8, 7); + vshll_n_s8(arg_i8x8, 8); vshll_n_s8(arg_i8x8, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} - + vshll_n_s8(arg_i8x8, 9); // expected-error-re {{argument value {{.*}} is outside the valid range}} vshll_high_n_s8(arg_i8x16, 0); - vshll_high_n_s8(arg_i8x16, 7); + vshll_high_n_s8(arg_i8x16, 8); vshll_high_n_s8(arg_i8x16, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vshll_high_n_s8(arg_i8x16, 9); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_vector_shift_left_and_widen_s16(int16x4_t arg_i16x4, int16x8_t arg_i16x8) { vshll_n_s16(arg_i16x4, 0); - vshll_n_s16(arg_i16x4, 15); + vshll_n_s16(arg_i16x4, 16); vshll_n_s16(arg_i16x4, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vshll_n_s16(arg_i16x4, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}} vshll_high_n_s16(arg_i16x8, 0); - vshll_high_n_s16(arg_i16x8, 15); + vshll_high_n_s16(arg_i16x8, 16); vshll_high_n_s16(arg_i16x8, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vshll_high_n_s16(arg_i16x8, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_vector_shift_left_and_widen_s32(int32x2_t arg_i32x2, int32x4_t arg_i32x4) { vshll_n_s32(arg_i32x2, 0); - vshll_n_s32(arg_i32x2, 31); + vshll_n_s32(arg_i32x2, 32); vshll_n_s32(arg_i32x2, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vshll_n_s32(arg_i32x2, 33); // expected-error-re {{argument value {{.*}} is outside the valid range}} vshll_high_n_s32(arg_i32x4, 0); - vshll_high_n_s32(arg_i32x4, 31); + vshll_high_n_s32(arg_i32x4, 32); vshll_high_n_s32(arg_i32x4, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vshll_high_n_s32(arg_i32x4, 33); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_vector_shift_left_and_widen_u8(uint8x8_t arg_u8x8, uint8x16_t arg_u8x16) { vshll_n_u8(arg_u8x8, 0); - vshll_n_u8(arg_u8x8, 7); + vshll_n_u8(arg_u8x8, 8); vshll_n_u8(arg_u8x8, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vshll_n_u8(arg_u8x8, 9); // expected-error-re {{argument value {{.*}} is outside the valid range}} vshll_high_n_u8(arg_u8x16, 0); - vshll_high_n_u8(arg_u8x16, 7); + vshll_high_n_u8(arg_u8x16, 8); vshll_high_n_u8(arg_u8x16, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vshll_high_n_u8(arg_u8x16, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vshll_high_n_u8(arg_u8x16, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_vector_shift_left_and_widen_u16(uint16x4_t arg_u16x4, uint16x8_t arg_u16x8) { vshll_n_u16(arg_u16x4, 0); - vshll_n_u16(arg_u16x4, 15); + vshll_n_u16(arg_u16x4, 16); vshll_n_u16(arg_u16x4, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vshll_n_u16(arg_u16x4, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}} vshll_high_n_u16(arg_u16x8, 0); - vshll_high_n_u16(arg_u16x8, 15); + vshll_high_n_u16(arg_u16x8, 16); vshll_high_n_u16(arg_u16x8, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vshll_high_n_u16(arg_u16x8, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_vector_shift_left_and_widen_u32(uint32x2_t arg_u32x2, uint32x4_t arg_u32x4) { vshll_n_u32(arg_u32x2, 0); - vshll_n_u32(arg_u32x2, 31); + vshll_n_u32(arg_u32x2, 32); vshll_n_u32(arg_u32x2, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vshll_n_u32(arg_u32x2, 33); // expected-error-re {{argument value {{.*}} is outside the valid range}} vshll_high_n_u32(arg_u32x4, 0); - vshll_high_n_u32(arg_u32x4, 31); + vshll_high_n_u32(arg_u32x4, 32); vshll_high_n_u32(arg_u32x4, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vshll_high_n_u32(arg_u32x4, 33); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_vector_shift_left_and_insert_s8(int8x8_t arg_i8x8, int8x16_t arg_i8x16) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
