simon_tatham created this revision.
simon_tatham added reviewers: dmgreen, miyuki, MarkMurrayARM.
Herald added subscribers: llvm-commits, cfe-commits, kristof.beyls.
Herald added projects: clang, LLVM.

The ACLE intrinsics with `gather_base` or `scatter_base` in the name
are wrappers on the MVE load/store instructions that take a vector of
base addresses and an immediate offset. The immediate offset can be up
to 127 times the alignment unit, and it can be positive or negative.

At the MC layer, we got that right. But in the Sema error checking for
the wrapping intrinsics, the offset was erroneously constrained to be
positive.

To fix this I've adjusted the `imm_mem7bit` class in the Tablegen that
defines the intrinsics. But that causes integer literals like
`0xfffffffffffffe04` to appear in the autogenerated calls to
`SemaBuiltinConstantArgRange`, which provokes a compiler warning
because that's out of the non-overflowing range of an `int64_t`. So
I've also tweaked `MveEmitter` to emit that as `-0x1fc` instead.

Updated the tests of the Sema checks themselves, and also adjusted a
random sample of the CodeGen tests to actually use negative offsets
and prove they get all the way through code generation without causing
a crash.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D72268

Files:
  clang/include/clang/Basic/arm_mve_defs.td
  clang/test/CodeGen/arm-mve-intrinsics/scatter-gather.c
  clang/test/Sema/arm-mve-immediates.c
  clang/utils/TableGen/MveEmitter.cpp
  llvm/test/CodeGen/Thumb2/mve-intrinsics/scatter-gather.ll

Index: llvm/test/CodeGen/Thumb2/mve-intrinsics/scatter-gather.ll
===================================================================
--- llvm/test/CodeGen/Thumb2/mve-intrinsics/scatter-gather.ll
+++ llvm/test/CodeGen/Thumb2/mve-intrinsics/scatter-gather.ll
@@ -191,11 +191,11 @@
 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 @@
 ; 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 @@
 ; 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 @@
 ; 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 @@
 ; 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 @@
 ; 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 @@
 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 @@
 ; 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 @@
 ; 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 @@
 ; 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 @@
 ; 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 @@
 ; 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
 }
Index: clang/utils/TableGen/MveEmitter.cpp
===================================================================
--- clang/utils/TableGen/MveEmitter.cpp
+++ clang/utils/TableGen/MveEmitter.cpp
@@ -861,6 +861,13 @@
   }
   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 @@
         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;
Index: clang/test/Sema/arm-mve-immediates.c
===================================================================
--- clang/test/Sema/arm-mve-immediates.c
+++ clang/test/Sema/arm-mve-immediates.c
@@ -11,8 +11,11 @@
   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 @@
   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 @@
   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 @@
   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}}
 }
Index: clang/test/CodeGen/arm-mve-intrinsics/scatter-gather.c
===================================================================
--- clang/test/CodeGen/arm-mve-intrinsics/scatter-gather.c
+++ clang/test/CodeGen/arm-mve-intrinsics/scatter-gather.c
@@ -196,12 +196,12 @@
 
 // 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 @@
 // 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 @@
 //
 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 @@
 // 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 @@
 // 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 @@
 //
 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 @@
 // 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 @@
 //
 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 @@
 // 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 @@
 
 // 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 @@
 // 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 @@
 // 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 @@
 // 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 @@
 // 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 @@
 // 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 */
 }
 
Index: clang/include/clang/Basic/arm_mve_defs.td
===================================================================
--- clang/include/clang/Basic/arm_mve_defs.td
+++ clang/include/clang/Basic/arm_mve_defs.td
@@ -345,9 +345,10 @@
 
 // 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);
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to