summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/arm_mve_defs.td5
-rw-r--r--clang/test/CodeGen/arm-mve-intrinsics/scatter-gather.c60
-rw-r--r--clang/test/Sema/arm-mve-immediates.c28
-rw-r--r--clang/utils/TableGen/MveEmitter.cpp11
-rw-r--r--llvm/test/CodeGen/Thumb2/mve-intrinsics/scatter-gather.ll48
5 files changed, 86 insertions, 66 deletions
diff --git a/clang/include/clang/Basic/arm_mve_defs.td b/clang/include/clang/Basic/arm_mve_defs.td
index 939d5eb0cd6..6fba88df34b 100644
--- a/clang/include/clang/Basic/arm_mve_defs.td
+++ b/clang/include/clang/Basic/arm_mve_defs.td
@@ -345,9 +345,10 @@ def imm_1248 : Immediate<u32, IB_ConstRange<1, 8>> {
// imm_mem7bit<n> is a valid immediate offset for a load/store intrinsic whose
// memory access size is n bytes (e.g. 1 for vldrb_[whatever], 2 for vldrh,
-// ...). The set of valid immediates for these is {0*n, 1*n, ..., 127*n}.
+// ...). The set of valid immediates for these is {-127*n, ..., -1*n, 0*n, 1*n,
+// ..., 127*n}.
class imm_mem7bit<int membytes>
- : Immediate<sint, IB_ConstRange<0, !mul(membytes, 127)>> {
+ : Immediate<sint, IB_ConstRange<!mul(membytes, -127), !mul(membytes, 127)>> {
let extra = !if(!eq(membytes, 1), ?, "Multiple");
let extraarg = !cast<string>(membytes);
}
diff --git a/clang/test/CodeGen/arm-mve-intrinsics/scatter-gather.c b/clang/test/CodeGen/arm-mve-intrinsics/scatter-gather.c
index 8bf2111a9e6..564965acc04 100644
--- a/clang/test/CodeGen/arm-mve-intrinsics/scatter-gather.c
+++ b/clang/test/CodeGen/arm-mve-intrinsics/scatter-gather.c
@@ -196,12 +196,12 @@ int64x2_t test_vldrdq_gather_base_s64(uint64x2_t addr)
// CHECK-LABEL: @test_vldrdq_gather_base_u64(
// CHECK-NEXT: entry:
-// CHECK-NEXT: [[TMP0:%.*]] = call <2 x i64> @llvm.arm.mve.vldr.gather.base.v2i64.v2i64(<2 x i64> [[ADDR:%.*]], i32 336)
+// CHECK-NEXT: [[TMP0:%.*]] = call <2 x i64> @llvm.arm.mve.vldr.gather.base.v2i64.v2i64(<2 x i64> [[ADDR:%.*]], i32 -336)
// CHECK-NEXT: ret <2 x i64> [[TMP0]]
//
uint64x2_t test_vldrdq_gather_base_u64(uint64x2_t addr)
{
- return vldrdq_gather_base_u64(addr, 0x150);
+ return vldrdq_gather_base_u64(addr, -0x150);
}
// CHECK-LABEL: @test_vldrdq_gather_base_wb_s64(
@@ -221,7 +221,7 @@ int64x2_t test_vldrdq_gather_base_wb_s64(uint64x2_t *addr)
// CHECK-LABEL: @test_vldrdq_gather_base_wb_u64(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load <2 x i64>, <2 x i64>* [[ADDR:%.*]], align 8
-// CHECK-NEXT: [[TMP1:%.*]] = call { <2 x i64>, <2 x i64> } @llvm.arm.mve.vldr.gather.base.wb.v2i64.v2i64(<2 x i64> [[TMP0]], i32 328)
+// CHECK-NEXT: [[TMP1:%.*]] = call { <2 x i64>, <2 x i64> } @llvm.arm.mve.vldr.gather.base.wb.v2i64.v2i64(<2 x i64> [[TMP0]], i32 -328)
// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { <2 x i64>, <2 x i64> } [[TMP1]], 1
// CHECK-NEXT: store <2 x i64> [[TMP2]], <2 x i64>* [[ADDR]], align 8
// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <2 x i64>, <2 x i64> } [[TMP1]], 0
@@ -229,7 +229,7 @@ int64x2_t test_vldrdq_gather_base_wb_s64(uint64x2_t *addr)
//
uint64x2_t test_vldrdq_gather_base_wb_u64(uint64x2_t *addr)
{
- return vldrdq_gather_base_wb_u64(addr, 0x148);
+ return vldrdq_gather_base_wb_u64(addr, -0x148);
}
// CHECK-LABEL: @test_vldrdq_gather_base_wb_z_s64(
@@ -280,12 +280,12 @@ int64x2_t test_vldrdq_gather_base_z_s64(uint64x2_t addr, mve_pred16_t p)
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32
// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]])
-// CHECK-NEXT: [[TMP2:%.*]] = call <2 x i64> @llvm.arm.mve.vldr.gather.base.predicated.v2i64.v2i64.v4i1(<2 x i64> [[ADDR:%.*]], i32 1000, <4 x i1> [[TMP1]])
+// CHECK-NEXT: [[TMP2:%.*]] = call <2 x i64> @llvm.arm.mve.vldr.gather.base.predicated.v2i64.v2i64.v4i1(<2 x i64> [[ADDR:%.*]], i32 -1000, <4 x i1> [[TMP1]])
// CHECK-NEXT: ret <2 x i64> [[TMP2]]
//
uint64x2_t test_vldrdq_gather_base_z_u64(uint64x2_t addr, mve_pred16_t p)
{
- return vldrdq_gather_base_z_u64(addr, 0x3e8, p);
+ return vldrdq_gather_base_z_u64(addr, -0x3e8, p);
}
// CHECK-LABEL: @test_vldrdq_gather_offset_s64(
@@ -741,7 +741,7 @@ uint32x4_t test_vldrwq_gather_base_u32(uint32x4_t addr)
// CHECK-LABEL: @test_vldrwq_gather_base_wb_f32(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load <4 x i32>, <4 x i32>* [[ADDR:%.*]], align 8
-// CHECK-NEXT: [[TMP1:%.*]] = call { <4 x float>, <4 x i32> } @llvm.arm.mve.vldr.gather.base.wb.v4f32.v4i32(<4 x i32> [[TMP0]], i32 64)
+// CHECK-NEXT: [[TMP1:%.*]] = call { <4 x float>, <4 x i32> } @llvm.arm.mve.vldr.gather.base.wb.v4f32.v4i32(<4 x i32> [[TMP0]], i32 -64)
// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { <4 x float>, <4 x i32> } [[TMP1]], 1
// CHECK-NEXT: store <4 x i32> [[TMP2]], <4 x i32>* [[ADDR]], align 8
// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <4 x float>, <4 x i32> } [[TMP1]], 0
@@ -749,7 +749,7 @@ uint32x4_t test_vldrwq_gather_base_u32(uint32x4_t addr)
//
float32x4_t test_vldrwq_gather_base_wb_f32(uint32x4_t *addr)
{
- return vldrwq_gather_base_wb_f32(addr, 0x40);
+ return vldrwq_gather_base_wb_f32(addr, -0x40);
}
// CHECK-LABEL: @test_vldrwq_gather_base_wb_s32(
@@ -785,7 +785,7 @@ uint32x4_t test_vldrwq_gather_base_wb_u32(uint32x4_t *addr)
// CHECK-NEXT: [[TMP0:%.*]] = load <4 x i32>, <4 x i32>* [[ADDR:%.*]], align 8
// CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[P:%.*]] to i32
// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP1]])
-// CHECK-NEXT: [[TMP3:%.*]] = call { <4 x float>, <4 x i32> } @llvm.arm.mve.vldr.gather.base.wb.predicated.v4f32.v4i32.v4i1(<4 x i32> [[TMP0]], i32 352, <4 x i1> [[TMP2]])
+// CHECK-NEXT: [[TMP3:%.*]] = call { <4 x float>, <4 x i32> } @llvm.arm.mve.vldr.gather.base.wb.predicated.v4f32.v4i32.v4i1(<4 x i32> [[TMP0]], i32 -352, <4 x i1> [[TMP2]])
// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <4 x float>, <4 x i32> } [[TMP3]], 1
// CHECK-NEXT: store <4 x i32> [[TMP4]], <4 x i32>* [[ADDR]], align 8
// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { <4 x float>, <4 x i32> } [[TMP3]], 0
@@ -793,7 +793,7 @@ uint32x4_t test_vldrwq_gather_base_wb_u32(uint32x4_t *addr)
//
float32x4_t test_vldrwq_gather_base_wb_z_f32(uint32x4_t *addr, mve_pred16_t p)
{
- return vldrwq_gather_base_wb_z_f32(addr, 0x160, p);
+ return vldrwq_gather_base_wb_z_f32(addr, -0x160, p);
}
// CHECK-LABEL: @test_vldrwq_gather_base_wb_z_s32(
@@ -856,12 +856,12 @@ int32x4_t test_vldrwq_gather_base_z_s32(uint32x4_t addr, mve_pred16_t p)
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32
// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]])
-// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vldr.gather.base.predicated.v4i32.v4i32.v4i1(<4 x i32> [[ADDR:%.*]], i32 300, <4 x i1> [[TMP1]])
+// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vldr.gather.base.predicated.v4i32.v4i32.v4i1(<4 x i32> [[ADDR:%.*]], i32 -300, <4 x i1> [[TMP1]])
// CHECK-NEXT: ret <4 x i32> [[TMP2]]
//
uint32x4_t test_vldrwq_gather_base_z_u32(uint32x4_t addr, mve_pred16_t p)
{
- return vldrwq_gather_base_z_u32(addr, 0x12c, p);
+ return vldrwq_gather_base_z_u32(addr, -0x12c, p);
}
// CHECK-LABEL: @test_vldrwq_gather_offset_f32(
@@ -1272,15 +1272,15 @@ void test_vstrdq_scatter_base_s64(uint64x2_t addr, int64x2_t value)
// CHECK-LABEL: @test_vstrdq_scatter_base_u64(
// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @llvm.arm.mve.vstr.scatter.base.v2i64.v2i64(<2 x i64> [[ADDR:%.*]], i32 472, <2 x i64> [[VALUE:%.*]])
+// CHECK-NEXT: call void @llvm.arm.mve.vstr.scatter.base.v2i64.v2i64(<2 x i64> [[ADDR:%.*]], i32 -472, <2 x i64> [[VALUE:%.*]])
// CHECK-NEXT: ret void
//
void test_vstrdq_scatter_base_u64(uint64x2_t addr, uint64x2_t value)
{
#ifdef POLYMORPHIC
- vstrdq_scatter_base(addr, 0x1d8, value);
+ vstrdq_scatter_base(addr, -0x1d8, value);
#else /* POLYMORPHIC */
- vstrdq_scatter_base_u64(addr, 0x1d8, value);
+ vstrdq_scatter_base_u64(addr, -0x1d8, value);
#endif /* POLYMORPHIC */
}
@@ -1339,16 +1339,16 @@ void test_vstrdq_scatter_base_wb_s64(uint64x2_t *addr, int64x2_t value)
// CHECK-LABEL: @test_vstrdq_scatter_base_wb_u64(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load <2 x i64>, <2 x i64>* [[ADDR:%.*]], align 8
-// CHECK-NEXT: [[TMP1:%.*]] = call <2 x i64> @llvm.arm.mve.vstr.scatter.base.wb.v2i64.v2i64(<2 x i64> [[TMP0]], i32 168, <2 x i64> [[VALUE:%.*]])
+// CHECK-NEXT: [[TMP1:%.*]] = call <2 x i64> @llvm.arm.mve.vstr.scatter.base.wb.v2i64.v2i64(<2 x i64> [[TMP0]], i32 -168, <2 x i64> [[VALUE:%.*]])
// CHECK-NEXT: store <2 x i64> [[TMP1]], <2 x i64>* [[ADDR]], align 8
// CHECK-NEXT: ret void
//
void test_vstrdq_scatter_base_wb_u64(uint64x2_t *addr, uint64x2_t value)
{
#ifdef POLYMORPHIC
- vstrdq_scatter_base_wb(addr, 0xa8, value);
+ vstrdq_scatter_base_wb(addr, -0xa8, value);
#else /* POLYMORPHIC */
- vstrdq_scatter_base_wb_u64(addr, 0xa8, value);
+ vstrdq_scatter_base_wb_u64(addr, -0xa8, value);
#endif /* POLYMORPHIC */
}
@@ -1790,15 +1790,15 @@ void test_vstrwq_scatter_base_f32(uint32x4_t addr, float32x4_t value)
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32
// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]])
-// CHECK-NEXT: call void @llvm.arm.mve.vstr.scatter.base.predicated.v4i32.v4f32.v4i1(<4 x i32> [[ADDR:%.*]], i32 400, <4 x float> [[VALUE:%.*]], <4 x i1> [[TMP1]])
+// CHECK-NEXT: call void @llvm.arm.mve.vstr.scatter.base.predicated.v4i32.v4f32.v4i1(<4 x i32> [[ADDR:%.*]], i32 -400, <4 x float> [[VALUE:%.*]], <4 x i1> [[TMP1]])
// CHECK-NEXT: ret void
//
void test_vstrwq_scatter_base_p_f32(uint32x4_t addr, float32x4_t value, mve_pred16_t p)
{
#ifdef POLYMORPHIC
- vstrwq_scatter_base_p(addr, 0x190, value, p);
+ vstrwq_scatter_base_p(addr, -0x190, value, p);
#else /* POLYMORPHIC */
- vstrwq_scatter_base_p_f32(addr, 0x190, value, p);
+ vstrwq_scatter_base_p_f32(addr, -0x190, value, p);
#endif /* POLYMORPHIC */
}
@@ -1822,15 +1822,15 @@ void test_vstrwq_scatter_base_p_s32(uint32x4_t addr, int32x4_t value, mve_pred16
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32
// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]])
-// CHECK-NEXT: call void @llvm.arm.mve.vstr.scatter.base.predicated.v4i32.v4i32.v4i1(<4 x i32> [[ADDR:%.*]], i32 376, <4 x i32> [[VALUE:%.*]], <4 x i1> [[TMP1]])
+// CHECK-NEXT: call void @llvm.arm.mve.vstr.scatter.base.predicated.v4i32.v4i32.v4i1(<4 x i32> [[ADDR:%.*]], i32 -376, <4 x i32> [[VALUE:%.*]], <4 x i1> [[TMP1]])
// CHECK-NEXT: ret void
//
void test_vstrwq_scatter_base_p_u32(uint32x4_t addr, uint32x4_t value, mve_pred16_t p)
{
#ifdef POLYMORPHIC
- vstrwq_scatter_base_p(addr, 0x178, value, p);
+ vstrwq_scatter_base_p(addr, -0x178, value, p);
#else /* POLYMORPHIC */
- vstrwq_scatter_base_p_u32(addr, 0x178, value, p);
+ vstrwq_scatter_base_p_u32(addr, -0x178, value, p);
#endif /* POLYMORPHIC */
}
@@ -1865,16 +1865,16 @@ void test_vstrwq_scatter_base_u32(uint32x4_t addr, uint32x4_t value)
// CHECK-LABEL: @test_vstrwq_scatter_base_wb_f32(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load <4 x i32>, <4 x i32>* [[ADDR:%.*]], align 8
-// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.arm.mve.vstr.scatter.base.wb.v4i32.v4f32(<4 x i32> [[TMP0]], i32 412, <4 x float> [[VALUE:%.*]])
+// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.arm.mve.vstr.scatter.base.wb.v4i32.v4f32(<4 x i32> [[TMP0]], i32 -412, <4 x float> [[VALUE:%.*]])
// CHECK-NEXT: store <4 x i32> [[TMP1]], <4 x i32>* [[ADDR]], align 8
// CHECK-NEXT: ret void
//
void test_vstrwq_scatter_base_wb_f32(uint32x4_t *addr, float32x4_t value)
{
#ifdef POLYMORPHIC
- vstrwq_scatter_base_wb(addr, 0x19c, value);
+ vstrwq_scatter_base_wb(addr, -0x19c, value);
#else /* POLYMORPHIC */
- vstrwq_scatter_base_wb_f32(addr, 0x19c, value);
+ vstrwq_scatter_base_wb_f32(addr, -0x19c, value);
#endif /* POLYMORPHIC */
}
@@ -1935,16 +1935,16 @@ void test_vstrwq_scatter_base_wb_p_u32(uint32x4_t *addr, uint32x4_t value, mve_p
// CHECK-LABEL: @test_vstrwq_scatter_base_wb_s32(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load <4 x i32>, <4 x i32>* [[ADDR:%.*]], align 8
-// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.arm.mve.vstr.scatter.base.wb.v4i32.v4i32(<4 x i32> [[TMP0]], i32 152, <4 x i32> [[VALUE:%.*]])
+// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.arm.mve.vstr.scatter.base.wb.v4i32.v4i32(<4 x i32> [[TMP0]], i32 -152, <4 x i32> [[VALUE:%.*]])
// CHECK-NEXT: store <4 x i32> [[TMP1]], <4 x i32>* [[ADDR]], align 8
// CHECK-NEXT: ret void
//
void test_vstrwq_scatter_base_wb_s32(uint32x4_t *addr, int32x4_t value)
{
#ifdef POLYMORPHIC
- vstrwq_scatter_base_wb(addr, 0x98, value);
+ vstrwq_scatter_base_wb(addr, -0x98, value);
#else /* POLYMORPHIC */
- vstrwq_scatter_base_wb_s32(addr, 0x98, value);
+ vstrwq_scatter_base_wb_s32(addr, -0x98, value);
#endif /* POLYMORPHIC */
}
diff --git a/clang/test/Sema/arm-mve-immediates.c b/clang/test/Sema/arm-mve-immediates.c
index 45b2357a600..54cdb96efcd 100644
--- a/clang/test/Sema/arm-mve-immediates.c
+++ b/clang/test/Sema/arm-mve-immediates.c
@@ -11,8 +11,11 @@ void test_load_offsets(uint32x4_t addr32, uint64x2_t addr64)
vldrdq_gather_base_s64(addr64, 125*8);
vldrdq_gather_base_s64(addr64, 126*8);
vldrdq_gather_base_s64(addr64, 127*8);
- vldrdq_gather_base_s64(addr64, -8); // expected-error {{argument value -8 is outside the valid range [0, 1016]}}
- vldrdq_gather_base_s64(addr64, 128*8); // expected-error {{argument value 1024 is outside the valid range [0, 1016]}}
+ vldrdq_gather_base_s64(addr64, -125*8);
+ vldrdq_gather_base_s64(addr64, -126*8);
+ vldrdq_gather_base_s64(addr64, -127*8);
+ vldrdq_gather_base_s64(addr64, 128*8); // expected-error {{argument value 1024 is outside the valid range [-1016, 1016]}}
+ vldrdq_gather_base_s64(addr64, -128*8); // expected-error {{argument value -1024 is outside the valid range [-1016, 1016]}}
vldrdq_gather_base_s64(addr64, 4); // expected-error {{argument should be a multiple of 8}}
vldrdq_gather_base_s64(addr64, 1); // expected-error {{argument should be a multiple of 8}}
@@ -23,8 +26,11 @@ void test_load_offsets(uint32x4_t addr32, uint64x2_t addr64)
vldrwq_gather_base_s32(addr32, 125*4);
vldrwq_gather_base_s32(addr32, 126*4);
vldrwq_gather_base_s32(addr32, 127*4);
- vldrwq_gather_base_s32(addr32, -4); // expected-error {{argument value -4 is outside the valid range [0, 508]}}
- vldrwq_gather_base_s32(addr32, 128*4); // expected-error {{argument value 512 is outside the valid range [0, 508]}}
+ vldrwq_gather_base_s32(addr32, -125*4);
+ vldrwq_gather_base_s32(addr32, -126*4);
+ vldrwq_gather_base_s32(addr32, -127*4);
+ vldrwq_gather_base_s32(addr32, 128*4); // expected-error {{argument value 512 is outside the valid range [-508, 508]}}
+ vldrwq_gather_base_s32(addr32, -128*4); // expected-error {{argument value -512 is outside the valid range [-508, 508]}}
vldrwq_gather_base_s32(addr32, 2); // expected-error {{argument should be a multiple of 4}}
vldrwq_gather_base_s32(addr32, 1); // expected-error {{argument should be a multiple of 4}}
@@ -37,8 +43,11 @@ void test_load_offsets(uint32x4_t addr32, uint64x2_t addr64)
vstrdq_scatter_base(addr64, 125*8, addr64);
vstrdq_scatter_base(addr64, 126*8, addr64);
vstrdq_scatter_base(addr64, 127*8, addr64);
- vstrdq_scatter_base(addr64, -8, addr64); // expected-error {{argument value -8 is outside the valid range [0, 1016]}}
- vstrdq_scatter_base(addr64, 128*8, addr64); // expected-error {{argument value 1024 is outside the valid range [0, 1016]}}
+ vstrdq_scatter_base(addr64, -125*8, addr64);
+ vstrdq_scatter_base(addr64, -126*8, addr64);
+ vstrdq_scatter_base(addr64, -127*8, addr64);
+ vstrdq_scatter_base(addr64, 128*8, addr64); // expected-error {{argument value 1024 is outside the valid range [-1016, 1016]}}
+ vstrdq_scatter_base(addr64, -128*8, addr64); // expected-error {{argument value -1024 is outside the valid range [-1016, 1016]}}
vstrdq_scatter_base(addr64, 4, addr64); // expected-error {{argument should be a multiple of 8}}
vstrdq_scatter_base(addr64, 1, addr64); // expected-error {{argument should be a multiple of 8}}
@@ -49,8 +58,11 @@ void test_load_offsets(uint32x4_t addr32, uint64x2_t addr64)
vstrwq_scatter_base(addr32, 125*4, addr32);
vstrwq_scatter_base(addr32, 126*4, addr32);
vstrwq_scatter_base(addr32, 127*4, addr32);
- vstrwq_scatter_base(addr32, -4, addr32); // expected-error {{argument value -4 is outside the valid range [0, 508]}}
- vstrwq_scatter_base(addr32, 128*4, addr32); // expected-error {{argument value 512 is outside the valid range [0, 508]}}
+ vstrwq_scatter_base(addr32, -125*4, addr32);
+ vstrwq_scatter_base(addr32, -126*4, addr32);
+ vstrwq_scatter_base(addr32, -127*4, addr32);
+ vstrwq_scatter_base(addr32, 128*4, addr32); // expected-error {{argument value 512 is outside the valid range [-508, 508]}}
+ vstrwq_scatter_base(addr32, -128*4, addr32); // expected-error {{argument value -512 is outside the valid range [-508, 508]}}
vstrwq_scatter_base(addr32, 2, addr32); // expected-error {{argument should be a multiple of 4}}
vstrwq_scatter_base(addr32, 1, addr32); // expected-error {{argument should be a multiple of 4}}
}
diff --git a/clang/utils/TableGen/MveEmitter.cpp b/clang/utils/TableGen/MveEmitter.cpp
index ae4c9b218f8..6f3fd2522ce 100644
--- a/clang/utils/TableGen/MveEmitter.cpp
+++ b/clang/utils/TableGen/MveEmitter.cpp
@@ -861,6 +861,13 @@ public:
}
bool hasCode() const { return Code != nullptr; }
+ static std::string signedHexLiteral(const llvm::APInt &iOrig) {
+ llvm::APInt i = iOrig.trunc(64);
+ SmallString<40> s;
+ i.toString(s, 16, true, true);
+ return s.str();
+ }
+
std::string genSema() const {
std::vector<std::string> SemaChecks;
@@ -895,8 +902,8 @@ public:
SemaChecks.push_back("SemaBuiltinConstantArg(TheCall, " + Index + ")");
else
SemaChecks.push_back("SemaBuiltinConstantArgRange(TheCall, " + Index +
- ", 0x" + lo.toString(16, true) + ", 0x" +
- hi.toString(16, true) + ")");
+ ", " + signedHexLiteral(lo) + ", " +
+ signedHexLiteral(hi) + ")");
if (!IA.ExtraCheckType.empty()) {
std::string Suffix;
diff --git a/llvm/test/CodeGen/Thumb2/mve-intrinsics/scatter-gather.ll b/llvm/test/CodeGen/Thumb2/mve-intrinsics/scatter-gather.ll
index 5e19f81cbf5..7eac79094f5 100644
--- a/llvm/test/CodeGen/Thumb2/mve-intrinsics/scatter-gather.ll
+++ b/llvm/test/CodeGen/Thumb2/mve-intrinsics/scatter-gather.ll
@@ -191,11 +191,11 @@ declare <2 x i64> @llvm.arm.mve.vldr.gather.base.v2i64.v2i64(<2 x i64>, i32)
define arm_aapcs_vfpcc <2 x i64> @test_vldrdq_gather_base_u64(<2 x i64> %addr) {
; CHECK-LABEL: test_vldrdq_gather_base_u64:
; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: vldrd.u64 q1, [q0, #336]
+; CHECK-NEXT: vldrd.u64 q1, [q0, #-336]
; CHECK-NEXT: vmov q0, q1
; CHECK-NEXT: bx lr
entry:
- %0 = call <2 x i64> @llvm.arm.mve.vldr.gather.base.v2i64.v2i64(<2 x i64> %addr, i32 336)
+ %0 = call <2 x i64> @llvm.arm.mve.vldr.gather.base.v2i64.v2i64(<2 x i64> %addr, i32 -336)
ret <2 x i64> %0
}
@@ -221,12 +221,12 @@ define arm_aapcs_vfpcc <2 x i64> @test_vldrdq_gather_base_wb_u64(<2 x i64>* %add
; CHECK-LABEL: test_vldrdq_gather_base_wb_u64:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vldrw.u32 q0, [r0]
-; CHECK-NEXT: vldrd.u64 q1, [q0, #328]!
+; CHECK-NEXT: vldrd.u64 q1, [q0, #-328]!
; CHECK-NEXT: vstrw.32 q1, [r0]
; CHECK-NEXT: bx lr
entry:
%0 = load <2 x i64>, <2 x i64>* %addr, align 8
- %1 = call { <2 x i64>, <2 x i64> } @llvm.arm.mve.vldr.gather.base.wb.v2i64.v2i64(<2 x i64> %0, i32 328)
+ %1 = call { <2 x i64>, <2 x i64> } @llvm.arm.mve.vldr.gather.base.wb.v2i64.v2i64(<2 x i64> %0, i32 -328)
%2 = extractvalue { <2 x i64>, <2 x i64> } %1, 1
store <2 x i64> %2, <2 x i64>* %addr, align 8
%3 = extractvalue { <2 x i64>, <2 x i64> } %1, 0
@@ -297,13 +297,13 @@ define arm_aapcs_vfpcc <2 x i64> @test_vldrdq_gather_base_z_u64(<2 x i64> %addr,
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vmsr p0, r0
; CHECK-NEXT: vpst
-; CHECK-NEXT: vldrdt.u64 q1, [q0, #1000]
+; CHECK-NEXT: vldrdt.u64 q1, [q0, #-1000]
; CHECK-NEXT: vmov q0, q1
; CHECK-NEXT: bx lr
entry:
%0 = zext i16 %p to i32
%1 = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 %0)
- %2 = call <2 x i64> @llvm.arm.mve.vldr.gather.base.predicated.v2i64.v2i64.v4i1(<2 x i64> %addr, i32 1000, <4 x i1> %1)
+ %2 = call <2 x i64> @llvm.arm.mve.vldr.gather.base.predicated.v2i64.v2i64.v4i1(<2 x i64> %addr, i32 -1000, <4 x i1> %1)
ret <2 x i64> %2
}
@@ -728,12 +728,12 @@ define arm_aapcs_vfpcc <4 x float> @test_vldrwq_gather_base_wb_f32(<4 x i32>* %a
; CHECK-LABEL: test_vldrwq_gather_base_wb_f32:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vldrw.u32 q0, [r0]
-; CHECK-NEXT: vldrw.u32 q1, [q0, #64]!
+; CHECK-NEXT: vldrw.u32 q1, [q0, #-64]!
; CHECK-NEXT: vstrw.32 q1, [r0]
; CHECK-NEXT: bx lr
entry:
%0 = load <4 x i32>, <4 x i32>* %addr, align 8
- %1 = call { <4 x float>, <4 x i32> } @llvm.arm.mve.vldr.gather.base.wb.v4f32.v4i32(<4 x i32> %0, i32 64)
+ %1 = call { <4 x float>, <4 x i32> } @llvm.arm.mve.vldr.gather.base.wb.v4f32.v4i32(<4 x i32> %0, i32 -64)
%2 = extractvalue { <4 x float>, <4 x i32> } %1, 1
store <4 x i32> %2, <4 x i32>* %addr, align 8
%3 = extractvalue { <4 x float>, <4 x i32> } %1, 0
@@ -782,14 +782,14 @@ define arm_aapcs_vfpcc <4 x float> @test_vldrwq_gather_base_wb_z_f32(<4 x i32>*
; CHECK-NEXT: vmsr p0, r1
; CHECK-NEXT: vldrw.u32 q0, [r0]
; CHECK-NEXT: vpst
-; CHECK-NEXT: vldrwt.u32 q1, [q0, #352]!
+; CHECK-NEXT: vldrwt.u32 q1, [q0, #-352]!
; CHECK-NEXT: vstrw.32 q1, [r0]
; CHECK-NEXT: bx lr
entry:
%0 = load <4 x i32>, <4 x i32>* %addr, align 8
%1 = zext i16 %p to i32
%2 = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 %1)
- %3 = call { <4 x float>, <4 x i32> } @llvm.arm.mve.vldr.gather.base.wb.predicated.v4f32.v4i32.v4i1(<4 x i32> %0, i32 352, <4 x i1> %2)
+ %3 = call { <4 x float>, <4 x i32> } @llvm.arm.mve.vldr.gather.base.wb.predicated.v4f32.v4i32.v4i1(<4 x i32> %0, i32 -352, <4 x i1> %2)
%4 = extractvalue { <4 x float>, <4 x i32> } %3, 1
store <4 x i32> %4, <4 x i32>* %addr, align 8
%5 = extractvalue { <4 x float>, <4 x i32> } %3, 0
@@ -845,13 +845,13 @@ define arm_aapcs_vfpcc <4 x float> @test_vldrwq_gather_base_z_f32(<4 x i32> %add
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vmsr p0, r0
; CHECK-NEXT: vpst
-; CHECK-NEXT: vldrwt.u32 q1, [q0, #300]
+; CHECK-NEXT: vldrwt.u32 q1, [q0, #-300]
; CHECK-NEXT: vmov q0, q1
; CHECK-NEXT: bx lr
entry:
%0 = zext i16 %p to i32
%1 = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 %0)
- %2 = call <4 x float> @llvm.arm.mve.vldr.gather.base.predicated.v4f32.v4i32.v4i1(<4 x i32> %addr, i32 300, <4 x i1> %1)
+ %2 = call <4 x float> @llvm.arm.mve.vldr.gather.base.predicated.v4f32.v4i32.v4i1(<4 x i32> %addr, i32 -300, <4 x i1> %1)
ret <4 x float> %2
}
@@ -1254,10 +1254,10 @@ declare void @llvm.arm.mve.vstr.scatter.base.v2i64.v2i64(<2 x i64>, i32, <2 x i6
define arm_aapcs_vfpcc void @test_vstrdq_scatter_base_u64(<2 x i64> %addr, <2 x i64> %value) {
; CHECK-LABEL: test_vstrdq_scatter_base_u64:
; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: vstrd.64 q1, [q0, #472]
+; CHECK-NEXT: vstrd.64 q1, [q0, #-472]
; CHECK-NEXT: bx lr
entry:
- call void @llvm.arm.mve.vstr.scatter.base.v2i64.v2i64(<2 x i64> %addr, i32 472, <2 x i64> %value)
+ call void @llvm.arm.mve.vstr.scatter.base.v2i64.v2i64(<2 x i64> %addr, i32 -472, <2 x i64> %value)
ret void
}
@@ -1319,12 +1319,12 @@ define arm_aapcs_vfpcc void @test_vstrdq_scatter_base_wb_u64(<2 x i64>* %addr, <
; CHECK-LABEL: test_vstrdq_scatter_base_wb_u64:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vldrw.u32 q1, [r0]
-; CHECK-NEXT: vstrd.64 q0, [q1, #168]!
+; CHECK-NEXT: vstrd.64 q0, [q1, #-168]!
; CHECK-NEXT: vstrw.32 q1, [r0]
; CHECK-NEXT: bx lr
entry:
%0 = load <2 x i64>, <2 x i64>* %addr, align 8
- %1 = call <2 x i64> @llvm.arm.mve.vstr.scatter.base.wb.v2i64.v2i64(<2 x i64> %0, i32 168, <2 x i64> %value)
+ %1 = call <2 x i64> @llvm.arm.mve.vstr.scatter.base.wb.v2i64.v2i64(<2 x i64> %0, i32 -168, <2 x i64> %value)
store <2 x i64> %1, <2 x i64>* %addr, align 8
ret void
}
@@ -1698,12 +1698,12 @@ define arm_aapcs_vfpcc void @test_vstrwq_scatter_base_p_f32(<4 x i32> %addr, <4
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vmsr p0, r0
; CHECK-NEXT: vpst
-; CHECK-NEXT: vstrwt.32 q1, [q0, #400]
+; CHECK-NEXT: vstrwt.32 q1, [q0, #-400]
; CHECK-NEXT: bx lr
entry:
%0 = zext i16 %p to i32
%1 = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 %0)
- call void @llvm.arm.mve.vstr.scatter.base.predicated.v4i32.v4f32.v4i1(<4 x i32> %addr, i32 400, <4 x float> %value, <4 x i1> %1)
+ call void @llvm.arm.mve.vstr.scatter.base.predicated.v4i32.v4f32.v4i1(<4 x i32> %addr, i32 -400, <4 x float> %value, <4 x i1> %1)
ret void
}
@@ -1730,12 +1730,12 @@ define arm_aapcs_vfpcc void @test_vstrwq_scatter_base_p_u32(<4 x i32> %addr, <4
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vmsr p0, r0
; CHECK-NEXT: vpst
-; CHECK-NEXT: vstrwt.32 q1, [q0, #376]
+; CHECK-NEXT: vstrwt.32 q1, [q0, #-376]
; CHECK-NEXT: bx lr
entry:
%0 = zext i16 %p to i32
%1 = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 %0)
- call void @llvm.arm.mve.vstr.scatter.base.predicated.v4i32.v4i32.v4i1(<4 x i32> %addr, i32 376, <4 x i32> %value, <4 x i1> %1)
+ call void @llvm.arm.mve.vstr.scatter.base.predicated.v4i32.v4i32.v4i1(<4 x i32> %addr, i32 -376, <4 x i32> %value, <4 x i1> %1)
ret void
}
@@ -1765,12 +1765,12 @@ define arm_aapcs_vfpcc void @test_vstrwq_scatter_base_wb_f32(<4 x i32>* %addr, <
; CHECK-LABEL: test_vstrwq_scatter_base_wb_f32:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vldrw.u32 q1, [r0]
-; CHECK-NEXT: vstrw.32 q0, [q1, #412]!
+; CHECK-NEXT: vstrw.32 q0, [q1, #-412]!
; CHECK-NEXT: vstrw.32 q1, [r0]
; CHECK-NEXT: bx lr
entry:
%0 = load <4 x i32>, <4 x i32>* %addr, align 8
- %1 = call <4 x i32> @llvm.arm.mve.vstr.scatter.base.wb.v4i32.v4f32(<4 x i32> %0, i32 412, <4 x float> %value)
+ %1 = call <4 x i32> @llvm.arm.mve.vstr.scatter.base.wb.v4i32.v4f32(<4 x i32> %0, i32 -412, <4 x float> %value)
store <4 x i32> %1, <4 x i32>* %addr, align 8
ret void
}
@@ -1839,12 +1839,12 @@ define arm_aapcs_vfpcc void @test_vstrwq_scatter_base_wb_s32(<4 x i32>* %addr, <
; CHECK-LABEL: test_vstrwq_scatter_base_wb_s32:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vldrw.u32 q1, [r0]
-; CHECK-NEXT: vstrw.32 q0, [q1, #152]!
+; CHECK-NEXT: vstrw.32 q0, [q1, #-152]!
; CHECK-NEXT: vstrw.32 q1, [r0]
; CHECK-NEXT: bx lr
entry:
%0 = load <4 x i32>, <4 x i32>* %addr, align 8
- %1 = call <4 x i32> @llvm.arm.mve.vstr.scatter.base.wb.v4i32.v4i32(<4 x i32> %0, i32 152, <4 x i32> %value)
+ %1 = call <4 x i32> @llvm.arm.mve.vstr.scatter.base.wb.v4i32.v4i32(<4 x i32> %0, i32 -152, <4 x i32> %value)
store <4 x i32> %1, <4 x i32>* %addr, align 8
ret void
}
OpenPOWER on IntegriCloud