https://gcc.gnu.org/g:2e1c12409662c20f45b0e4dabaadff033ef674f7
commit r16-4060-g2e1c12409662c20f45b0e4dabaadff033ef674f7 Author: Richard Earnshaw <rearn...@arm.com> Date: Fri Sep 5 15:25:55 2025 +0100 arm: mve: fix out-of range literal pool for a const_vector [PR121810] 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. Diff: --- gcc/config/arm/mve.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gcc/config/arm/mve.md b/gcc/config/arm/mve.md index 8527bd753e30..96faa05908f0 100644 --- a/gcc/config/arm/mve.md +++ b/gcc/config/arm/mve.md @@ -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]