This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] PowerPC load_multiple fix (PR 8362)
- From: David Edelsohn <dje at watson dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Mark Mitchell <mark at codesourcery dot com>
- Date: Sat, 16 Nov 2002 13:06:30 -0500
- Subject: [PATCH] PowerPC load_multiple fix (PR 8362)
The following patch fixes PR 8362 by exposing the load_multiple
vector operands so that reload will substitute the hard reg in all
locations. This is based on similar patterns in the ARM backend.
Bootstrapped with no regressions. I eventually will commit this to the
gcc-3.2 branch when Mark allows.
David
* config/rs6000/rs6000.c (rs6000_outout_load_multiple): New function.
* config/rs6000/rs6000.md (movti_string): Remove output modifier
when scratch register never needed.
(ldmsi[3-8]): New patterns.
Index: rs6000-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000-protos.h,v
retrieving revision 1.47
diff -c -p -r1.47 rs6000-protos.h
*** rs6000-protos.h 23 Oct 2002 15:20:38 -0000 1.47
--- rs6000-protos.h 16 Nov 2002 01:56:48 -0000
*************** extern int constant_pool_expr_p PARAMS (
*** 84,89 ****
--- 84,90 ----
extern int toc_relative_expr_p PARAMS ((rtx));
extern int expand_block_move PARAMS ((rtx[]));
extern int load_multiple_operation PARAMS ((rtx, enum machine_mode));
+ extern const char * rs6000_output_load_multiple PARAMS ((rtx[]));
extern int store_multiple_operation PARAMS ((rtx, enum machine_mode));
extern int branch_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int branch_positive_comparison_operator
*************** extern void rs6000_emit_load_toc_table P
*** 186,192 ****
extern void rs6000_aix_emit_builtin_unwind_init PARAMS ((void));
extern void rs6000_emit_epilogue PARAMS ((int));
extern void debug_stack_info PARAMS ((rs6000_stack_t *));
! extern const char *output_isel PARAMS ((rtx *));
extern int vrsave_operation PARAMS ((rtx, enum machine_mode));
extern int rs6000_register_move_cost PARAMS ((enum machine_mode,
enum reg_class, enum reg_class));
--- 187,193 ----
extern void rs6000_aix_emit_builtin_unwind_init PARAMS ((void));
extern void rs6000_emit_epilogue PARAMS ((int));
extern void debug_stack_info PARAMS ((rs6000_stack_t *));
! extern const char * output_isel PARAMS ((rtx *));
extern int vrsave_operation PARAMS ((rtx, enum machine_mode));
extern int rs6000_register_move_cost PARAMS ((enum machine_mode,
enum reg_class, enum reg_class));
Index: rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.397
diff -c -p -r1.397 rs6000.c
*** rs6000.c 2 Nov 2002 21:55:55 -0000 1.397
--- rs6000.c 16 Nov 2002 01:56:49 -0000
*************** store_multiple_operation (op, mode)
*** 6390,6395 ****
--- 6390,6453 ----
return 1;
}
+ /* Return a string to perform a load_multiple operation.
+ operands[0] is the vector.
+ operands[1] is the source address.
+ operands[2] is the first destination register. */
+
+ const char *
+ rs6000_output_load_multiple (operands)
+ rtx operands[2];
+ {
+ /* We have to handle the case where the pseudo used to contain the address
+ is assigned to one of the output registers. */
+ int i, j;
+ int words = XVECLEN (operands[0], 0);
+ rtx xop[10];
+
+ if (XVECLEN (operands[0], 0) == 1)
+ return "{l|lwz} %2,0(%1)";
+
+ for (i = 0; i < words; i++)
+ if (refers_to_regno_p (REGNO (operands[2]) + i,
+ REGNO (operands[2]) + i + 1, operands[1], 0))
+ {
+ if (i == words-1)
+ {
+ xop[0] = GEN_INT (4 * (words-1));
+ xop[1] = operands[1];
+ xop[2] = operands[2];
+ output_asm_insn ("{lsi|lswi} %2,%1,%0\n\t{l|lwz} %1,%0(%1)", xop);
+ return "";
+ }
+ else if (i == 0)
+ {
+ xop[0] = GEN_INT (4 * (words-1));
+ xop[1] = operands[1];
+ xop[2] = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
+ output_asm_insn ("{cal %1,4(%1)|addi %1,%1,4}\n\t{lsi|lswi} %2,%1,%0\n\t{l|lwz} %1,-4(%1)", xop);
+ return "";
+ }
+ else
+ {
+ for (j = 0; j < words; j++)
+ if (j != i)
+ {
+ xop[0] = GEN_INT (j * 4);
+ xop[1] = operands[1];
+ xop[2] = gen_rtx_REG (SImode, REGNO (operands[2]) + j);
+ output_asm_insn ("{l|lwz} %2,%0(%1)", xop);
+ }
+ xop[0] = GEN_INT (i * 4);
+ xop[1] = operands[1];
+ output_asm_insn ("{l|lwz} %1,%0(%1)", xop);
+ return "";
+ }
+ }
+
+ return "{lsi|lswi} %2,%1,%N0";
+ }
+
/* Return 1 for a parallel vrsave operation. */
int
Index: rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.221
diff -c -p -r1.221 rs6000.md
*** rs6000.md 7 Nov 2002 00:34:42 -0000 1.221
--- rs6000.md 16 Nov 2002 01:56:49 -0000
***************
*** 9250,9256 ****
(define_insn "*movti_string"
[(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r")
(match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))
! (clobber (match_scratch:SI 2 "=X,X,X,X,X"))]
"TARGET_STRING && ! TARGET_POWER && ! TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
"*
--- 9250,9256 ----
(define_insn "*movti_string"
[(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r")
(match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))
! (clobber (match_scratch:SI 2 "X,X,X,X,X"))]
"TARGET_STRING && ! TARGET_POWER && ! TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
"*
***************
*** 9371,9435 ****
adjust_address (op1, SImode, i * 4));
}")
! (define_insn ""
[(match_parallel 0 "load_multiple_operation"
! [(set (match_operand:SI 1 "gpc_reg_operand" "=r")
! (mem:SI (match_operand:SI 2 "gpc_reg_operand" "b")))])]
! "TARGET_STRING"
"*
! {
! /* We have to handle the case where the pseudo used to contain the address
! is assigned to one of the output registers. */
! int i, j;
! int words = XVECLEN (operands[0], 0);
! rtx xop[10];
!
! if (XVECLEN (operands[0], 0) == 1)
! return \"{l|lwz} %1,0(%2)\";
!
! for (i = 0; i < words; i++)
! if (refers_to_regno_p (REGNO (operands[1]) + i,
! REGNO (operands[1]) + i + 1, operands[2], 0))
! {
! if (i == words-1)
! {
! xop[0] = operands[1];
! xop[1] = operands[2];
! xop[2] = GEN_INT (4 * (words-1));
! output_asm_insn (\"{lsi|lswi} %0,%1,%2\;{l|lwz} %1,%2(%1)\", xop);
! return \"\";
! }
! else if (i == 0)
! {
! xop[0] = operands[1];
! xop[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
! xop[2] = GEN_INT (4 * (words-1));
! output_asm_insn (\"{cal %0,4(%0)|addi %0,%0,4}\;{lsi|lswi} %1,%0,%2\;{l|lwz} %0,-4(%0)\", xop);
! return \"\";
! }
! else
! {
! for (j = 0; j < words; j++)
! if (j != i)
! {
! xop[0] = gen_rtx_REG (SImode, REGNO (operands[1]) + j);
! xop[1] = operands[2];
! xop[2] = GEN_INT (j * 4);
! output_asm_insn (\"{l|lwz} %0,%2(%1)\", xop);
! }
! xop[0] = operands[2];
! xop[1] = GEN_INT (i * 4);
! output_asm_insn (\"{l|lwz} %0,%1(%0)\", xop);
! return \"\";
! }
! }
! return \"{lsi|lswi} %1,%2,%N0\";
! }"
[(set_attr "type" "load")
(set_attr "length" "32")])
-
(define_expand "store_multiple"
[(match_par_dup 3 [(set (match_operand:SI 0 "" "")
(match_operand:SI 1 "" ""))
--- 9371,9490 ----
adjust_address (op1, SImode, i * 4));
}")
! (define_insn "*ldmsi8"
[(match_parallel 0 "load_multiple_operation"
! [(set (match_operand:SI 2 "gpc_reg_operand" "")
! (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
! (set (match_operand:SI 3 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 4))))
! (set (match_operand:SI 4 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 8))))
! (set (match_operand:SI 5 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 12))))
! (set (match_operand:SI 6 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 16))))
! (set (match_operand:SI 7 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 20))))
! (set (match_operand:SI 8 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 24))))
! (set (match_operand:SI 9 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 28))))])]
! "TARGET_STRING && XVECLEN (operands[0], 0) == 8"
"*
! { return rs6000_output_load_multiple (operands); }"
! [(set_attr "type" "load")
! (set_attr "length" "32")])
! (define_insn "*ldmsi7"
! [(match_parallel 0 "load_multiple_operation"
! [(set (match_operand:SI 2 "gpc_reg_operand" "")
! (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
! (set (match_operand:SI 3 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 4))))
! (set (match_operand:SI 4 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 8))))
! (set (match_operand:SI 5 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 12))))
! (set (match_operand:SI 6 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 16))))
! (set (match_operand:SI 7 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 20))))
! (set (match_operand:SI 8 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 24))))])]
! "TARGET_STRING && XVECLEN (operands[0], 0) == 7"
! "*
! { return rs6000_output_load_multiple (operands); }"
! [(set_attr "type" "load")
! (set_attr "length" "32")])
!
! (define_insn "*ldmsi6"
! [(match_parallel 0 "load_multiple_operation"
! [(set (match_operand:SI 2 "gpc_reg_operand" "")
! (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
! (set (match_operand:SI 3 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 4))))
! (set (match_operand:SI 4 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 8))))
! (set (match_operand:SI 5 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 12))))
! (set (match_operand:SI 6 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 16))))
! (set (match_operand:SI 7 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 20))))])]
! "TARGET_STRING && XVECLEN (operands[0], 0) == 6"
! "*
! { return rs6000_output_load_multiple (operands); }"
! [(set_attr "type" "load")
! (set_attr "length" "32")])
!
! (define_insn "*ldmsi5"
! [(match_parallel 0 "load_multiple_operation"
! [(set (match_operand:SI 2 "gpc_reg_operand" "")
! (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
! (set (match_operand:SI 3 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 4))))
! (set (match_operand:SI 4 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 8))))
! (set (match_operand:SI 5 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 12))))
! (set (match_operand:SI 6 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 16))))])]
! "TARGET_STRING && XVECLEN (operands[0], 0) == 5"
! "*
! { return rs6000_output_load_multiple (operands); }"
! [(set_attr "type" "load")
! (set_attr "length" "32")])
!
! (define_insn "*ldmsi4"
! [(match_parallel 0 "load_multiple_operation"
! [(set (match_operand:SI 2 "gpc_reg_operand" "")
! (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
! (set (match_operand:SI 3 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 4))))
! (set (match_operand:SI 4 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 8))))
! (set (match_operand:SI 5 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
! "TARGET_STRING && XVECLEN (operands[0], 0) == 4"
! "*
! { return rs6000_output_load_multiple (operands); }"
! [(set_attr "type" "load")
! (set_attr "length" "32")])
!
! (define_insn "*ldmsi3"
! [(match_parallel 0 "load_multiple_operation"
! [(set (match_operand:SI 2 "gpc_reg_operand" "")
! (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
! (set (match_operand:SI 3 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 4))))
! (set (match_operand:SI 4 "gpc_reg_operand" "")
! (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
! "TARGET_STRING && XVECLEN (operands[0], 0) == 3"
! "*
! { return rs6000_output_load_multiple (operands); }"
[(set_attr "type" "load")
(set_attr "length" "32")])
(define_expand "store_multiple"
[(match_par_dup 3 [(set (match_operand:SI 0 "" "")
(match_operand:SI 1 "" ""))
***************
*** 9474,9480 ****
gen_rtx_REG (SImode, regno + i));
}")
! (define_insn ""
[(match_parallel 0 "store_multiple_operation"
[(set (match_operand:SI 1 "indirect_operand" "=Q")
(match_operand:SI 2 "gpc_reg_operand" "r"))
--- 9529,9535 ----
gen_rtx_REG (SImode, regno + i));
}")
! (define_insn "*store_multiple_power"
[(match_parallel 0 "store_multiple_operation"
[(set (match_operand:SI 1 "indirect_operand" "=Q")
(match_operand:SI 2 "gpc_reg_operand" "r"))
***************
*** 9483,9489 ****
"{stsi|stswi} %2,%P1,%O0"
[(set_attr "type" "store")])
! (define_insn ""
[(match_parallel 0 "store_multiple_operation"
[(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
(match_operand:SI 2 "gpc_reg_operand" "r"))
--- 9538,9544 ----
"{stsi|stswi} %2,%P1,%O0"
[(set_attr "type" "store")])
! (define_insn "*store_multiple_string"
[(match_parallel 0 "store_multiple_operation"
[(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
(match_operand:SI 2 "gpc_reg_operand" "r"))