]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Backport of r270226 from mainline to gcc-7-branch
authorMatthew Malcomson <matthew.malcomson@arm.com>
Wed, 10 Apr 2019 13:34:54 +0000 (13:34 +0000)
committerMatthew Malcomson <matmal01@gcc.gnu.org>
Wed, 10 Apr 2019 13:34:54 +0000 (13:34 +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 and regtested on arm-none-linux-gnueabihf

gcc/ChangeLog:

2019-04-10  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-10  Matthew Malcomson  <matthew.malcomson@arm.com>

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

From-SVN: r270253

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 08e2ec88ba2c895687a68bae8d6bd366c5ebed86..00910dcf37550d4b617eb3eeeed2d21a635e7bd7 100644 (file)
@@ -1,3 +1,13 @@
+2019-04-10  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-07  Uroš Bizjak  <ubizjak@gmail.com>
 
        PR target/89945
index c8cd873e96dc44b00e01a051a4180a164e3e63fc..4cbc342e86f8d541b8b72c0e3a4721d7a07bb24d 100644 (file)
@@ -11696,8 +11696,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 0bd87dd32af1de9a0be58640ec94e83a76ce092c..9b5ec891b13185f9ddc400319d53c32168b82406 100644 (file)
@@ -31,7 +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
+;; in ARM/Thumb-2 state: Da, Db, Dc, Dd, Dn, DN, Dm, Dl, DL, Do, Dv, Dy, Di,
+;;                      Dt, Dp, Dz
 ;; in Thumb-1 state: Pa, Pb, Pc, Pd, Pe
 ;; in Thumb-2 state: Pj, PJ, Ps, Pt, Pu, Pv, Pw, Px, Py
 ;; 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 5ddef4956f5d0b4f8b1037d1a71c224385ff43de..c1a28f903f95a4985a575b9228f084c92eba227b 100644 (file)
 
 (define_insn "*neon_mov<mode>"
   [(set (match_operand:VDX 0 "nonimmediate_operand"
-         "=w,Un,w, w,  ?r,?w,?r,?r, ?Us")
+         "=w,Un,w, w, w,  ?r,?w,?r,?r, ?Us")
        (match_operand:VDX 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%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 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>";
     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>,mov_reg,\
-                    neon_load1_2reg, neon_store1_2reg")
-  (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>,mov_reg,neon_load1_2reg,\
+                   neon_store1_2reg")
+  (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,*")])
 
 (define_expand "movti"
   [(set (match_operand:TI 0 "nonimmediate_operand" "")
 (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 ffca0544038cf6740ecd62fcfdc0156eade6889d..d5d5187aeb9db7920dfcccd06e7fae379a5b1a0d 100644 (file)
@@ -1,3 +1,8 @@
+2019-04-10  Matthew Malcomson  <matthew.malcomson@arm.com>
+
+       PR target/90024
+       * gcc.dg/torture/neon-immediate-timode.c: New test.
+
 2019-04-07  Uroš Bizjak  <ubizjak@gmail.com>
 
        PR target/89945
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]);
+}