Hi there,
authorMatthew Malcomson <matthew.malcomson@arm.com>
Tue, 9 Apr 2019 11:39:59 +0000 (11:39 +0000)
committerMatthew Malcomson <matmal01@gcc.gnu.org>
Tue, 9 Apr 2019 11:39:59 +0000 (11:39 +0000)
The "*neon_mov<mode>" patterns for 128 bit sized quantities uses the "Dn"
constraint to match vmov.f32 and vmov.i<vec-width> patterns.
This constraint boils down to using the `neon_immediate_valid` function.
Once the constraint has matched, the output C statement asserts that function
passes.

The output C statement calls `neon_immediate_valid` with the mode taken from the
iterator, while the constraint takes the mode from the operand.
This can cause a discrepency when the operand is a CONST_INT, as the constraint
passes VOIDmode which `neon_immediate_valid` treats as DImode, while the C
statement passes the mode of the iterator which can be TImode.
When this happens, the `neon_immediate_valid` can fail in the second call (if
e.g. the CONST_INT is a valid immediate in DImode but not TImode) which would
trigger the assertion.

The testcase added with this patch triggers this when compiled with an arm cross
compiler using the command line below.
gcc -march=armv8-a -c neon-immediate-timode.c -O1 -mfloat-abi=hard -mfpu=neon-fp-armv8

This patch splits the original "Dn" constraint into three new constraints, "DN"
for TImode CONST_INT, "Dn" for DImode CONST_INT, and "Dm" for CONST_VECTOR.
Splitting things up this way requires using one extra alternative in the
"*neon_mov<mode>" patterns, but makes it clear from the constraint what mode is
being used.

We also remove the behaviour of treating VOIDmode as DImode in
`neon_valid_immediate` since the original "Dn" constraint was the only place
that functionality was used.  VOIDmode is now never passed to that function.
An assertion has been added to the function to ensure this problem is caught
earlier on.

Bootstrapped on arm-none-linux-gnueabihf
Regtested on cross-compiler arm-none-eabi

gcc/ChangeLog:

2019-04-09  Matthew Malcomson  <matthew.malcomson@arm.com>

PR target/90024
* config/arm/arm.c (neon_valid_immediate): Disallow VOIDmode parameter.
* config/arm/constraints.md (Dm, DN, Dn): Split previous Dn constraint
into three.
* config/arm/neon.md (*neon_mov<mode>): Account for TImode and DImode
differences directly.
(*smax<mode>3_neon, vashl<mode>3, vashr<mode>3_imm): Use Dm constraint.

gcc/testsuite/ChangeLog:

2019-04-09  Matthew Malcomson  <matthew.malcomson@arm.com>

PR target/90024
* gcc.dg/torture/neon-immediate-timode.c: New test.

From-SVN: r270226

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/constraints.md
gcc/config/arm/neon.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/neon-immediate-timode.c [new file with mode: 0644]

index 7136f6bbb9a2a8b0034263f7688033bc4c8da96c..9d21ce38b032473c643142368c0860e1f8487ba9 100644 (file)
@@ -1,3 +1,13 @@
+2019-04-09  Matthew Malcomson  <matthew.malcomson@arm.com>
+
+       PR target/90024
+       * config/arm/arm.c (neon_valid_immediate): Disallow VOIDmode parameter.
+       * config/arm/constraints.md (Dm, DN, Dn): Split previous Dn constraint
+       into three.
+       * config/arm/neon.md (*neon_mov<mode>): Account for TImode and DImode
+       differences directly.
+       (*smax<mode>3_neon, vashl<mode>3, vashr<mode>3_imm): Use Dm constraint.
+
 2019-04-09  Jakub Jelinek  <jakub@redhat.com>
 
        PR translation/90011
index 7ce063f43d23c50b9bd34e3ae473f7b81c6c6c46..12ccb7d69018e7aa23cb0fbd3a03d98f92cd4769 100644 (file)
@@ -11998,8 +11998,7 @@ neon_valid_immediate (rtx op, machine_mode mode, int inverse,
   else
     {
       n_elts = 1;
-      if (mode == VOIDmode)
-       mode = DImode;
+      gcc_assert (mode != VOIDmode);
     }
 
   innersize = GET_MODE_UNIT_SIZE (mode);
index 57ec06396220b9f7f356943dae1443c4c763741f..d4a4c5967aea09816485d77f9ab90020aa085e73 100644 (file)
@@ -31,8 +31,8 @@
 ;; 'H' was previously used for FPA.
 
 ;; The following multi-letter normal constraints have been used:
-;; in ARM/Thumb-2 state: Da, Db, Dc, Dd, Dn, Dl, DL, Do, Dv, Dy, Di, Dt, Dp,
-;;                      Dz, Tu
+;; in ARM/Thumb-2 state: Da, Db, Dc, Dd, Dn, DN, Dm, Dl, DL, Do, Dv, Dy, Di,
+;;                      Dt, Dp, Dz, Tu
 ;; in Thumb-1 state: Pa, Pb, Pc, Pd, Pe
 ;; in Thumb-2 state: Ha, Pj, PJ, Ps, Pt, Pu, Pv, Pw, Px, Py, Pz
 ;; in all states: Pf
  (and (match_code "const_double,const_int")
       (match_test "TARGET_32BIT && arm_const_double_by_immediates (op)")))
 
-(define_constraint "Dn"
+(define_constraint "Dm"
  "@internal
-  In ARM/Thumb-2 state a const_vector or const_int which can be loaded with a
-  Neon vmov immediate instruction."
- (and (match_code "const_vector,const_int")
+  In ARM/Thumb-2 state a const_vector which can be loaded with a Neon vmov
+  immediate instruction."
+ (and (match_code "const_vector")
       (match_test "TARGET_32BIT
                   && imm_for_neon_mov_operand (op, GET_MODE (op))")))
 
+(define_constraint "Dn"
+ "@internal
+  In ARM/Thumb-2 state a DImode const_int which can be loaded with a Neon vmov
+  immediate instruction."
+ (and (match_code "const_int")
+      (match_test "TARGET_32BIT && imm_for_neon_mov_operand (op, DImode)")))
+
+(define_constraint "DN"
+ "@internal
+  In ARM/Thumb-2 state a TImode const_int which can be loaded with a Neon vmov
+  immediate instruction."
+ (and (match_code "const_int")
+      (match_test "TARGET_32BIT && imm_for_neon_mov_operand (op, TImode)")))
+
 (define_constraint "Dl"
  "@internal
   In ARM/Thumb-2 state a const_vector which can be used with a Neon vorr or
index 48556d9dd5fa71aad532cba241007488e2e24349..726b7281a11be92d0b7a91fa7b8ba9efd1b68ac9 100644 (file)
 
 (define_insn "*neon_mov<mode>"
   [(set (match_operand:VDX 0 "nonimmediate_operand"
-         "=w,Un,w, w,  ?r,?w,?r, ?Us,*r")
+         "=w,Un,w, w, w,  ?r,?w,?r, ?Us,*r")
        (match_operand:VDX 1 "general_operand"
-         " w,w, Dn,Uni, w, r, Usi,r,*r"))]
+         " w,w, Dm,Dn,Uni, w, r, Usi,r,*r"))]
   "TARGET_NEON
    && (register_operand (operands[0], <MODE>mode)
        || register_operand (operands[1], <MODE>mode))"
 {
-  if (which_alternative == 2)
+  if (which_alternative == 2 || which_alternative == 3)
     {
       int width, is_valid;
       static char templ[40];
   switch (which_alternative)
     {
     case 0: return "vmov\t%P0, %P1  @ <mode>";
-    case 1: case 3: return output_move_neon (operands);
-    case 2: gcc_unreachable ();
-    case 4: return "vmov\t%Q0, %R0, %P1  @ <mode>";
-    case 5: return "vmov\t%P0, %Q1, %R1  @ <mode>";
-    case 8: return "#";
+    case 1: case 4: return output_move_neon (operands);
+    case 2: case 3: gcc_unreachable ();
+    case 5: return "vmov\t%Q0, %R0, %P1  @ <mode>";
+    case 6: return "vmov\t%P0, %Q1, %R1  @ <mode>";
+    case 9: return "#";
     default: return output_move_double (operands, true, NULL);
     }
 }
  [(set_attr "type" "neon_move<q>,neon_store1_1reg,neon_move<q>,\
-                    neon_load1_1reg, neon_to_gp<q>,neon_from_gp<q>,\
-                    neon_load1_2reg, neon_store1_2reg, multiple")
-  (set_attr "length" "4,4,4,4,4,4,8,8,8")
-  (set_attr "arm_pool_range"     "*,*,*,1020,*,*,1020,*,*")
-  (set_attr "thumb2_pool_range"     "*,*,*,1018,*,*,1018,*,*")
-  (set_attr "neg_pool_range" "*,*,*,1004,*,*,1004,*,*")])
+                    neon_move<q>,neon_load1_1reg, neon_to_gp<q>,\
+                    neon_from_gp<q>,neon_load1_2reg, neon_store1_2reg,\
+                   multiple")
+  (set_attr "length" "4,4,4,4,4,4,4,8,8,8")
+  (set_attr "arm_pool_range"     "*,*,*,*,1020,*,*,1020,*,*")
+  (set_attr "thumb2_pool_range"     "*,*,*,*,1018,*,*,1018,*,*")
+  (set_attr "neg_pool_range" "*,*,*,*,1004,*,*,1004,*,*")])
 
 (define_insn "*neon_mov<mode>"
   [(set (match_operand:VQXMOV 0 "nonimmediate_operand"
-         "=w,Un,w, w,  ?r,?w,?r,?r,  ?Us")
+         "=w,Un,w, w, w,  ?r,?w,?r,?r,  ?Us")
        (match_operand:VQXMOV 1 "general_operand"
-         " w,w, Dn,Uni, w, r, r, Usi, r"))]
+         " w,w, Dm,DN,Uni, w, r, r, Usi, r"))]
   "TARGET_NEON
    && (register_operand (operands[0], <MODE>mode)
        || register_operand (operands[1], <MODE>mode))"
 {
-  if (which_alternative == 2)
+  if (which_alternative == 2 || which_alternative == 3)
     {
       int width, is_valid;
       static char templ[40];
   switch (which_alternative)
     {
     case 0: return "vmov\t%q0, %q1  @ <mode>";
-    case 1: case 3: return output_move_neon (operands);
-    case 2: gcc_unreachable ();
-    case 4: return "vmov\t%Q0, %R0, %e1  @ <mode>\;vmov\t%J0, %K0, %f1";
-    case 5: return "vmov\t%e0, %Q1, %R1  @ <mode>\;vmov\t%f0, %J1, %K1";
+    case 1: case 4: return output_move_neon (operands);
+    case 2: case 3: gcc_unreachable ();
+    case 5: return "vmov\t%Q0, %R0, %e1  @ <mode>\;vmov\t%J0, %K0, %f1";
+    case 6: return "vmov\t%e0, %Q1, %R1  @ <mode>\;vmov\t%f0, %J1, %K1";
     default: return output_move_quad (operands);
     }
 }
   [(set_attr "type" "neon_move_q,neon_store2_2reg_q,neon_move_q,\
-                     neon_load2_2reg_q,neon_to_gp_q,neon_from_gp_q,\
-                     mov_reg,neon_load1_4reg,neon_store1_4reg")
-   (set_attr "length" "4,8,4,8,8,8,16,8,16")
-   (set_attr "arm_pool_range" "*,*,*,1020,*,*,*,1020,*")
-   (set_attr "thumb2_pool_range" "*,*,*,1018,*,*,*,1018,*")
-   (set_attr "neg_pool_range" "*,*,*,996,*,*,*,996,*")])
+                     neon_move_q,neon_load2_2reg_q,neon_to_gp_q,\
+                     neon_from_gp_q,mov_reg,neon_load1_4reg,neon_store1_4reg")
+   (set_attr "length" "4,8,4,4,8,8,8,16,8,16")
+   (set_attr "arm_pool_range" "*,*,*,*,1020,*,*,*,1020,*")
+   (set_attr "thumb2_pool_range" "*,*,*,*,1018,*,*,*,1018,*")
+   (set_attr "neg_pool_range" "*,*,*,*,996,*,*,*,996,*")])
 
 /* We define these mov expanders to match the standard mov$a optab to prevent
    the mid-end from trying to do a subreg for these modes which is the most
 (define_insn "vashl<mode>3"
   [(set (match_operand:VDQIW 0 "s_register_operand" "=w,w")
        (ashift:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w,w")
-                     (match_operand:VDQIW 2 "imm_lshift_or_reg_neon" "w,Dn")))]
+                     (match_operand:VDQIW 2 "imm_lshift_or_reg_neon" "w,Dm")))]
   "TARGET_NEON"
   {
     switch (which_alternative)
 (define_insn "vashr<mode>3_imm"
   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
        (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
-                       (match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dn")))]
+                       (match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dm")))]
   "TARGET_NEON"
   {
     return neon_output_shift_immediate ("vshr", 's', &operands[2],
 (define_insn "vlshr<mode>3_imm"
   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
        (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
-                       (match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dn")))]
+                       (match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dm")))]
   "TARGET_NEON"
   {
     return neon_output_shift_immediate ("vshr", 'u', &operands[2],
index 29d1a81c8d8260fa810579a34f5acd5663156478..71eaabc499763db2459d5dbe8b924c22457d17ea 100644 (file)
@@ -1,3 +1,8 @@
+2019-04-09  Matthew Malcomson  <matthew.malcomson@arm.com>
+
+       PR target/90024
+       * gcc.dg/torture/neon-immediate-timode.c: New test.
+
 2019-04-09  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/89998
diff --git a/gcc/testsuite/gcc.dg/torture/neon-immediate-timode.c b/gcc/testsuite/gcc.dg/torture/neon-immediate-timode.c
new file mode 100644 (file)
index 0000000..35f7d2c
--- /dev/null
@@ -0,0 +1,10 @@
+union a {
+  char b;
+  long long c;
+};
+union a d;
+int g(int, union a, union a);
+void e() {
+  union a f[2] = {-1L};
+  g(0, d, f[0]);
+}