2011-09-28 Richard Sandiford gcc/ Backport from mainline: 2011-09-28 Richard Sandiford * config/arm/neon.md (neon_move_lo_quad_): Delete. (neon_move_hi_quad_): Likewise. (move_hi_quad_, move_lo_quad_): Use subreg moves. 2011-09-28 Richard Sandiford gcc/ Backport from mainline: 2011-09-27 Richard Sandiford * config/arm/neon.md (neon_vget_highv16qi, neon_vget_highv8hi) (neon_vget_highv4si, neon_vget_highv4sf, neon_vget_highv2di) (neon_vget_lowv16qi, neon_vget_lowv8hi, neon_vget_lowv4si) (neon_vget_lowv4sf, neon_vget_lowv2di): Turn into define_expands that produce subreg moves. Define using VQX iterators. 2011-09-28 Richard Sandiford gcc/ Backport from mainline: 2011-09-14 Richard Sandiford * simplify-rtx.c (simplify_subreg): Check that the inner mode is a scalar integer before applying integer-only optimisations to inner arithmetic. === modified file 'gcc/config/arm/neon.md' --- old/gcc/config/arm/neon.md 2011-07-04 14:03:49 +0000 +++ new/gcc/config/arm/neon.md 2011-09-28 15:14:59 +0000 @@ -1235,66 +1235,14 @@ (const_string "neon_int_1") (const_string "neon_int_5")))] ) -; FIXME: We wouldn't need the following insns if we could write subregs of -; vector registers. Make an attempt at removing unnecessary moves, though -; we're really at the mercy of the register allocator. - -(define_insn "neon_move_lo_quad_" - [(set (match_operand:ANY128 0 "s_register_operand" "+w") - (vec_concat:ANY128 - (match_operand: 1 "s_register_operand" "w") - (vec_select: - (match_dup 0) - (match_operand:ANY128 2 "vect_par_constant_high" ""))))] - "TARGET_NEON" -{ - int dest = REGNO (operands[0]); - int src = REGNO (operands[1]); - - if (dest != src) - return "vmov\t%e0, %P1"; - else - return ""; -} - [(set_attr "neon_type" "neon_bp_simple")] -) - -(define_insn "neon_move_hi_quad_" - [(set (match_operand:ANY128 0 "s_register_operand" "+w") - (vec_concat:ANY128 - (vec_select: - (match_dup 0) - (match_operand:ANY128 2 "vect_par_constant_low" "")) - (match_operand: 1 "s_register_operand" "w")))] - - "TARGET_NEON" -{ - int dest = REGNO (operands[0]); - int src = REGNO (operands[1]); - - if (dest != src) - return "vmov\t%f0, %P1"; - else - return ""; -} - [(set_attr "neon_type" "neon_bp_simple")] -) - (define_expand "move_hi_quad_" [(match_operand:ANY128 0 "s_register_operand" "") (match_operand: 1 "s_register_operand" "")] "TARGET_NEON" { - rtvec v = rtvec_alloc (/2); - rtx t1; - int i; - - for (i=0; i < (/2); i++) - RTVEC_ELT (v, i) = GEN_INT (i); - - t1 = gen_rtx_PARALLEL (mode, v); - emit_insn (gen_neon_move_hi_quad_ (operands[0], operands[1], t1)); - + emit_move_insn (simplify_gen_subreg (mode, operands[0], mode, + GET_MODE_SIZE (mode)), + operands[1]); DONE; }) @@ -1303,16 +1251,9 @@ (match_operand: 1 "s_register_operand" "")] "TARGET_NEON" { - rtvec v = rtvec_alloc (/2); - rtx t1; - int i; - - for (i=0; i < (/2); i++) - RTVEC_ELT (v, i) = GEN_INT ((/2) + i); - - t1 = gen_rtx_PARALLEL (mode, v); - emit_insn (gen_neon_move_lo_quad_ (operands[0], operands[1], t1)); - + emit_move_insn (simplify_gen_subreg (mode, operands[0], + mode, 0), + operands[1]); DONE; }) @@ -2950,183 +2891,27 @@ (set_attr "neon_type" "neon_bp_simple")] ) -(define_insn "neon_vget_highv16qi" - [(set (match_operand:V8QI 0 "s_register_operand" "=w") - (vec_select:V8QI (match_operand:V16QI 1 "s_register_operand" "w") - (parallel [(const_int 8) (const_int 9) - (const_int 10) (const_int 11) - (const_int 12) (const_int 13) - (const_int 14) (const_int 15)])))] - "TARGET_NEON" -{ - int dest = REGNO (operands[0]); - int src = REGNO (operands[1]); - - if (dest != src + 2) - return "vmov\t%P0, %f1"; - else - return ""; -} - [(set_attr "neon_type" "neon_bp_simple")] -) - -(define_insn "neon_vget_highv8hi" - [(set (match_operand:V4HI 0 "s_register_operand" "=w") - (vec_select:V4HI (match_operand:V8HI 1 "s_register_operand" "w") - (parallel [(const_int 4) (const_int 5) - (const_int 6) (const_int 7)])))] - "TARGET_NEON" -{ - int dest = REGNO (operands[0]); - int src = REGNO (operands[1]); - - if (dest != src + 2) - return "vmov\t%P0, %f1"; - else - return ""; -} - [(set_attr "neon_type" "neon_bp_simple")] -) - -(define_insn "neon_vget_highv4si" - [(set (match_operand:V2SI 0 "s_register_operand" "=w") - (vec_select:V2SI (match_operand:V4SI 1 "s_register_operand" "w") - (parallel [(const_int 2) (const_int 3)])))] - "TARGET_NEON" -{ - int dest = REGNO (operands[0]); - int src = REGNO (operands[1]); - - if (dest != src + 2) - return "vmov\t%P0, %f1"; - else - return ""; -} - [(set_attr "neon_type" "neon_bp_simple")] -) - -(define_insn "neon_vget_highv4sf" - [(set (match_operand:V2SF 0 "s_register_operand" "=w") - (vec_select:V2SF (match_operand:V4SF 1 "s_register_operand" "w") - (parallel [(const_int 2) (const_int 3)])))] - "TARGET_NEON" -{ - int dest = REGNO (operands[0]); - int src = REGNO (operands[1]); - - if (dest != src + 2) - return "vmov\t%P0, %f1"; - else - return ""; -} - [(set_attr "neon_type" "neon_bp_simple")] -) - -(define_insn "neon_vget_highv2di" - [(set (match_operand:DI 0 "s_register_operand" "=w") - (vec_select:DI (match_operand:V2DI 1 "s_register_operand" "w") - (parallel [(const_int 1)])))] - "TARGET_NEON" -{ - int dest = REGNO (operands[0]); - int src = REGNO (operands[1]); - - if (dest != src + 2) - return "vmov\t%P0, %f1"; - else - return ""; -} - [(set_attr "neon_type" "neon_bp_simple")] -) - -(define_insn "neon_vget_lowv16qi" - [(set (match_operand:V8QI 0 "s_register_operand" "=w") - (vec_select:V8QI (match_operand:V16QI 1 "s_register_operand" "w") - (parallel [(const_int 0) (const_int 1) - (const_int 2) (const_int 3) - (const_int 4) (const_int 5) - (const_int 6) (const_int 7)])))] - "TARGET_NEON" -{ - int dest = REGNO (operands[0]); - int src = REGNO (operands[1]); - - if (dest != src) - return "vmov\t%P0, %e1"; - else - return ""; -} - [(set_attr "neon_type" "neon_bp_simple")] -) - -(define_insn "neon_vget_lowv8hi" - [(set (match_operand:V4HI 0 "s_register_operand" "=w") - (vec_select:V4HI (match_operand:V8HI 1 "s_register_operand" "w") - (parallel [(const_int 0) (const_int 1) - (const_int 2) (const_int 3)])))] - "TARGET_NEON" -{ - int dest = REGNO (operands[0]); - int src = REGNO (operands[1]); - - if (dest != src) - return "vmov\t%P0, %e1"; - else - return ""; -} - [(set_attr "neon_type" "neon_bp_simple")] -) - -(define_insn "neon_vget_lowv4si" - [(set (match_operand:V2SI 0 "s_register_operand" "=w") - (vec_select:V2SI (match_operand:V4SI 1 "s_register_operand" "w") - (parallel [(const_int 0) (const_int 1)])))] - "TARGET_NEON" -{ - int dest = REGNO (operands[0]); - int src = REGNO (operands[1]); - - if (dest != src) - return "vmov\t%P0, %e1"; - else - return ""; -} - [(set_attr "neon_type" "neon_bp_simple")] -) - -(define_insn "neon_vget_lowv4sf" - [(set (match_operand:V2SF 0 "s_register_operand" "=w") - (vec_select:V2SF (match_operand:V4SF 1 "s_register_operand" "w") - (parallel [(const_int 0) (const_int 1)])))] - "TARGET_NEON" -{ - int dest = REGNO (operands[0]); - int src = REGNO (operands[1]); - - if (dest != src) - return "vmov\t%P0, %e1"; - else - return ""; -} - [(set_attr "neon_type" "neon_bp_simple")] -) - -(define_insn "neon_vget_lowv2di" - [(set (match_operand:DI 0 "s_register_operand" "=w") - (vec_select:DI (match_operand:V2DI 1 "s_register_operand" "w") - (parallel [(const_int 0)])))] - "TARGET_NEON" -{ - int dest = REGNO (operands[0]); - int src = REGNO (operands[1]); - - if (dest != src) - return "vmov\t%P0, %e1"; - else - return ""; -} - [(set_attr "neon_type" "neon_bp_simple")] -) +(define_expand "neon_vget_high" + [(match_operand: 0 "s_register_operand") + (match_operand:VQX 1 "s_register_operand")] + "TARGET_NEON" +{ + emit_move_insn (operands[0], + simplify_gen_subreg (mode, operands[1], mode, + GET_MODE_SIZE (mode))); + DONE; +}) + +(define_expand "neon_vget_low" + [(match_operand: 0 "s_register_operand") + (match_operand:VQX 1 "s_register_operand")] + "TARGET_NEON" +{ + emit_move_insn (operands[0], + simplify_gen_subreg (mode, operands[1], + mode, 0)); + DONE; +}) (define_insn "neon_vcvt" [(set (match_operand: 0 "s_register_operand" "=w") === modified file 'gcc/simplify-rtx.c' --- old/gcc/simplify-rtx.c 2011-08-13 08:32:32 +0000 +++ new/gcc/simplify-rtx.c 2011-09-28 15:11:59 +0000 @@ -5567,6 +5567,7 @@ /* Optimize SUBREG truncations of zero and sign extended values. */ if ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND) + && SCALAR_INT_MODE_P (innermode) && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode)) { unsigned int bitpos = subreg_lsb_1 (outermode, innermode, byte); @@ -5605,6 +5606,7 @@ if ((GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ASHIFTRT) && SCALAR_INT_MODE_P (outermode) + && SCALAR_INT_MODE_P (innermode) /* Ensure that OUTERMODE is at least twice as wide as the INNERMODE to avoid the possibility that an outer LSHIFTRT shifts by more than the sign extension's sign_bit_copies and introduces zeros @@ -5624,6 +5626,7 @@ if ((GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ASHIFTRT) && SCALAR_INT_MODE_P (outermode) + && SCALAR_INT_MODE_P (innermode) && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode) && CONST_INT_P (XEXP (op, 1)) && GET_CODE (XEXP (op, 0)) == ZERO_EXTEND @@ -5638,6 +5641,7 @@ the outer subreg is effectively a truncation to the original mode. */ if (GET_CODE (op) == ASHIFT && SCALAR_INT_MODE_P (outermode) + && SCALAR_INT_MODE_P (innermode) && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode) && CONST_INT_P (XEXP (op, 1)) && (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND @@ -5651,7 +5655,7 @@ /* Recognize a word extraction from a multi-word subreg. */ if ((GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ASHIFTRT) - && SCALAR_INT_MODE_P (outermode) + && SCALAR_INT_MODE_P (innermode) && GET_MODE_BITSIZE (outermode) >= BITS_PER_WORD && GET_MODE_BITSIZE (innermode) >= (2 * GET_MODE_BITSIZE (outermode)) && CONST_INT_P (XEXP (op, 1)) @@ -5673,6 +5677,7 @@ if ((GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ASHIFTRT) + && SCALAR_INT_MODE_P (innermode) && MEM_P (XEXP (op, 0)) && CONST_INT_P (XEXP (op, 1)) && GET_MODE_SIZE (outermode) < GET_MODE_SIZE (GET_MODE (op))