]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
arm: mve: fix out-of range literal pool for a const_vector [PR121810]
authorRichard Earnshaw <rearnsha@arm.com>
Fri, 5 Sep 2025 14:25:55 +0000 (15:25 +0100)
committerRichard Earnshaw <rearnsha@arm.com>
Tue, 23 Sep 2025 14:36:59 +0000 (15:36 +0100)
For the pattern mve_mov<mode>, the alternative that describes literal
pool support is incorrect.  This leads to compiler getting the
calculations wrong for the available distance to the next pool
fragment because the selected alternative is a shorter sequence than
the correct one.  In particular the sequence generated for a 128-bit
constant is

vldr.64  d0, Pool    // Insn length 4, alternative 7 (part 1)
vldr.64  d1, Pool+8  // Insn length 4, alternative 7 (part 2)

Note that the second instruction needs 4 bytes more range than the
first because the PC has advanced by 4 bytes, but the next slot in the
pool has advanced by 8.

The fix is to move the 'Ui' constraint to the correct alternative
and to move the pool-range attributes to that alternative as well.

I've fixed a couple of other nits in this code at the same time:
- the thumb2_neg_pool_range attribute was misnamed (as neg_pool_range),
meaning it was ignored in Thumb state, which is the only time this
pattern is available.
- the load range was not a multiple of 4, which makes no sense for
an insn sequence that is a multiple of 4 bytes long.  I've rounded the
value down out of caution, but it may well have been OK with 1020 as
the forward range.

I'm not adding a testcase for this patch; the code to reproduce is
simply too complex to reliably test for a regression.

gcc/ChangeLog:
PR target/121810
* config/arm/mve.md (mve_mov<mode>): Move the Ui constraint
and pool_range attributes to the final alternative.  Fix
the forward range value and correctly name the negative
range.

gcc/config/arm/mve.md

index 8527bd753e309e1d114dd1de92bfef0a6400aef2..96faa05908f0f232aff405881e49659cc3aeb92c 100644 (file)
@@ -18,8 +18,8 @@
 ;; <http://www.gnu.org/licenses/>.
 
 (define_insn "mve_mov<mode>"
-  [(set (match_operand:MVE_types 0 "nonimmediate_operand" "=w,w,r,w   , w,   r,Ux,w")
-       (match_operand:MVE_types 1 "general_operand"      " w,r,w,DnDm,UxUi,r,w, Ul"))]
+  [(set (match_operand:MVE_types 0 "nonimmediate_operand" "=w,w,r,w   ,w, r,Ux,w")
+       (match_operand:MVE_types 1 "general_operand"      " w,r,w,DnDm,Ux,r,w, UlUi"))]
   "TARGET_HAVE_MVE || TARGET_HAVE_MVE_FLOAT"
 {
   switch (which_alternative)
@@ -56,7 +56,7 @@
          }
       }
 
-    case 4:  /* [w,UxUi].  */
+    case 4:  /* [w,Ux].  */
       if (<MODE>mode == V2DFmode || <MODE>mode == V2DImode
          || <MODE>mode == TImode)
        return "vldrw.u32\t%q0, %E1";
@@ -73,7 +73,7 @@
       else
        return "vstr<V_sz_elem1>.<V_sz_elem>\t%q1, %E0";
 
-    case 7:  /* [w,Ul].  */
+    case 7:  /* [w,UlUi].  */
        return output_move_neon (operands);
 
     default:
@@ -91,8 +91,8 @@
                                                   (symbol_ref "CODE_FOR_nothing")])
    (set_attr "type" "mve_move,mve_move,mve_move,mve_move,mve_load,multiple,mve_store,mve_load")
    (set_attr "length" "4,8,8,4,4,8,4,8")
-   (set_attr "thumb2_pool_range" "*,*,*,*,1018,*,*,*")
-   (set_attr "neg_pool_range" "*,*,*,*,996,*,*,*")])
+   (set_attr "thumb2_pool_range" "*,*,*,*,*,*,*,1016")
+   (set_attr "thumb2_neg_pool_range" "*,*,*,*,*,*,*,996")])
 
 ;;
 ;; [vdupq_n_u, vdupq_n_s, vdupq_n_f]