@@ -248,6 +248,9 @@ extern int vfp3_const_double_for_fract_bits (rtx);
extern void arm_emit_coreregs_64bit_shift (enum rtx_code, rtx, rtx, rtx, rtx,
rtx);
extern bool arm_validize_comparison (rtx *, rtx *, rtx *);
+extern void arm_split_tocx_imoves (rtx *, enum machine_mode);
+extern void arm_split_eimoves (rtx *);
+
#endif /* RTX_CODE */
extern void arm_expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel);
@@ -26410,4 +26410,95 @@ arm_validize_comparison (rtx *comparison, rtx
* op1, rtx * op2)
}
+/* EImode values are usually in 3 DImode registers. This could be suitably
+ split into TImode moves and DImode moves. */
+void
+arm_split_eimoves (rtx *operands)
+{
+ int rdest = REGNO (operands[0]);
+ int rsrc = REGNO (operands[1]);
+ int count = 0;
+ int increment = 0;
+ rtx dest[3], src[3];
+ int i, j;
+
+ if (NEON_REGNO_OK_FOR_QUAD (rdest) && NEON_REGNO_OK_FOR_QUAD (rsrc))
+ {
+ dest[0] = gen_rtx_REG (TImode, rdest);
+ src[0] = gen_rtx_REG (TImode, rsrc);
+ count = 2;
+ increment = 4;
+ }
+ else
+ {
+ dest[0] = gen_rtx_REG (DImode, rdest);
+ src[0] = gen_rtx_REG (DImode, rsrc);
+ dest[1] = gen_rtx_REG (DImode, rdest + 2);
+ src[1] = gen_rtx_REG (DImode, rsrc + 2);
+ count = 3;
+ increment = 2;
+ }
+
+ dest[count - 1] = gen_rtx_REG (DImode, rdest + 4);
+ src[count - 1] = gen_rtx_REG (DImode, rsrc + 4);
+
+ neon_disambiguate_copy (operands, dest, src, count);
+
+ for (i = 0, j = 0 ; j < count ; i = i + 2, j++)
+ emit_move_insn (operands[i], operands[i + 1]);
+
+ return;
+}
+
+/* Split TI, CI, OI and XImode moves into appropriate smaller
+ forms. */
+void
+arm_split_tocx_imoves (rtx *operands, enum machine_mode mode)
+{
+ int rdest = REGNO (operands[0]);
+ int rsrc = REGNO (operands[1]);
+ enum machine_mode split_mode;
+ int count = 0;
+ int factor = 0;
+ int j;
+ /* We never should need more than 8 DImode registers in the worst case. */
+ rtx dest[8], src[8];
+ int i;
+
+ if (NEON_REGNO_OK_FOR_QUAD (rdest) && NEON_REGNO_OK_FOR_QUAD (rsrc))
+ {
+ split_mode = TImode;
+ if (dump_file)
+ fprintf (dump_file, "split_mode is TImode\n");
+ }
+ else
+ {
+ split_mode = DImode;
+ if (dump_file)
+ fprintf (dump_file, "split_mode is DImode\n");
+ }
+
+
+ count = GET_MODE_SIZE (mode) / GET_MODE_SIZE (split_mode);
+ factor = GET_MODE_SIZE (split_mode) / UNITS_PER_WORD;
+
+ if (dump_file)
+ fprintf (dump_file, "count %d factor %d\n", count, factor);
+
+ for (i = 0 ; i < count; i++)
+ {
+ dest[i] = gen_rtx_REG (split_mode, rdest + i * factor );
+ src[i] = gen_rtx_REG (split_mode, rsrc + i * factor);
+ }
+
+ neon_disambiguate_copy (operands, dest, src, count);
+ for (j = 0, i = 0 ; j < count ; j++, i = i + 2)
+ {
+ emit_move_insn (operands[i], operands[i + 1]);
+ }
+
+ return;
+
+}
+
#include "gt-arm.h"
@@ -89,6 +89,9 @@
;; Opaque structure types wider than TImode.
(define_mode_iterator VSTRUCT [EI OI CI XI])
+;; Opaque structure types other than EImode.
+(define_mode_iterator TOCXI [TI OI CI XI])
+
;; Opaque structure types used in table lookups (except vtbl1/vtbx1).
(define_mode_iterator VTAB [TI EI OI])
@@ -293,85 +293,21 @@
[(set (match_operand:EI 0 "s_register_operand" "")
(match_operand:EI 1 "s_register_operand" ""))]
"TARGET_NEON && reload_completed"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 2) (match_dup 3))]
+ [(const_int 0)]
{
- int rdest = REGNO (operands[0]);
- int rsrc = REGNO (operands[1]);
- rtx dest[2], src[2];
-
- dest[0] = gen_rtx_REG (TImode, rdest);
- src[0] = gen_rtx_REG (TImode, rsrc);
- dest[1] = gen_rtx_REG (DImode, rdest + 4);
- src[1] = gen_rtx_REG (DImode, rsrc + 4);
-
- neon_disambiguate_copy (operands, dest, src, 2);
+ arm_split_eimoves (operands);
+ DONE;
})
-(define_split
- [(set (match_operand:OI 0 "s_register_operand" "")
- (match_operand:OI 1 "s_register_operand" ""))]
+;; Splitter for TI, OI, CI and XI modes.
+(define_split ;; TI, OI, CI and XImode move split.
+ [(set (match_operand:TOCXI 0 "s_register_operand" "")
+ (match_operand:TOCXI 1 "s_register_operand" ""))]
"TARGET_NEON && reload_completed"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 2) (match_dup 3))]
+ [(const_int 0)]
{
- int rdest = REGNO (operands[0]);
- int rsrc = REGNO (operands[1]);
- rtx dest[2], src[2];
-
- dest[0] = gen_rtx_REG (TImode, rdest);
- src[0] = gen_rtx_REG (TImode, rsrc);
- dest[1] = gen_rtx_REG (TImode, rdest + 4);
- src[1] = gen_rtx_REG (TImode, rsrc + 4);
-
- neon_disambiguate_copy (operands, dest, src, 2);
-})
-
-(define_split
- [(set (match_operand:CI 0 "s_register_operand" "")
- (match_operand:CI 1 "s_register_operand" ""))]
- "TARGET_NEON && reload_completed"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (match_dup 5))]
-{
- int rdest = REGNO (operands[0]);
- int rsrc = REGNO (operands[1]);
- rtx dest[3], src[3];
-
- dest[0] = gen_rtx_REG (TImode, rdest);
- src[0] = gen_rtx_REG (TImode, rsrc);
- dest[1] = gen_rtx_REG (TImode, rdest + 4);
- src[1] = gen_rtx_REG (TImode, rsrc + 4);
- dest[2] = gen_rtx_REG (TImode, rdest + 8);
- src[2] = gen_rtx_REG (TImode, rsrc + 8);
-
- neon_disambiguate_copy (operands, dest, src, 3);
-})
-
-(define_split
- [(set (match_operand:XI 0 "s_register_operand" "")
- (match_operand:XI 1 "s_register_operand" ""))]
- "TARGET_NEON && reload_completed"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (match_dup 5))
- (set (match_dup 6) (match_dup 7))]
-{
- int rdest = REGNO (operands[0]);
- int rsrc = REGNO (operands[1]);
- rtx dest[4], src[4];
-
- dest[0] = gen_rtx_REG (TImode, rdest);
- src[0] = gen_rtx_REG (TImode, rsrc);
- dest[1] = gen_rtx_REG (TImode, rdest + 4);
- src[1] = gen_rtx_REG (TImode, rsrc + 4);
- dest[2] = gen_rtx_REG (TImode, rdest + 8);
- src[2] = gen_rtx_REG (TImode, rsrc + 8);
- dest[3] = gen_rtx_REG (TImode, rdest + 12);
- src[3] = gen_rtx_REG (TImode, rsrc + 12);
-
- neon_disambiguate_copy (operands, dest, src, 4);
+ arm_split_tocx_imoves (operands, <MODE>mode);
+ DONE;
})
(define_expand "movmisalign<mode>"