This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch to SHmedia divide patterns
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: 18 Nov 2002 14:57:28 +0000
- Subject: Patch to SHmedia divide patterns
For TARGET_SHMEDIA_FPU, the udivsi3 pattern generates the
following sequence:
(set (match_dup 3)
(zero_extend:DI (match_operand:SI 1 "register_operand" "")))
(set (match_dup 4)
(zero_extend:DI (match_operand:SI 2 "register_operand" "")))
(set (match_dup 5) (float:DF (match_dup 3)))
(set (match_dup 6) (float:DF (match_dup 4)))
(set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
(set (match_dup 8) (fix:DI (match_dup 7)))
(set (match_operand:SI 0 "register_operand" "")
(truncate:SI (match_dup 8)))
and then puts the whole thing in a REG_LIBCALL/REG_RETVAL block.
In the test case below, the result of one such block was constant
folded and so the block was removed. Unfortunately, gcse had
reused the result of a conversion in a later instruction.
So, question is: is gcse wrong to reuse a value from inside a libcall
block, or shouldn't the backend have created one in the first place?
Looking though the ports, I think sh is the only one that wraps
pseudo operations in libcall block, so I assume it's the backend
that needs to change.
Patch tested on sh64-elf, fixes the attached test case.
OK to install?
Richard
* config/sh/sh.md (udivsi3): Don't put udivsi3_i4_media instructions
into a libcall block.
(divsi3): Likewise divsi3_i4_media.
Index: config/sh/sh.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.md,v
retrieving revision 1.125
diff -c -d -p -F^[(a-zA-Z0-9_^#] -r1.125 sh.md
*** config/sh/sh.md 31 Oct 2002 12:53:06 -0000 1.125
--- config/sh/sh.md 14 Nov 2002 17:11:14 -0000
*************** (define_expand "udivsi3"
*** 1341,1347 ****
""
"
{
! rtx first = 0, last;
operands[3] = gen_reg_rtx (Pmode);
/* Emit the move of the address to a pseudo outside of the libcall. */
--- 1341,1347 ----
""
"
{
! rtx first, last;
operands[3] = gen_reg_rtx (Pmode);
/* Emit the move of the address to a pseudo outside of the libcall. */
*************** (define_expand "udivsi3"
*** 1358,1365 ****
{
operands[1] = force_reg (SImode, operands[1]);
operands[2] = force_reg (SImode, operands[2]);
! last = gen_udivsi3_i4_media (operands[0], operands[1], operands[2]);
! first = last;
}
else if (TARGET_SH5)
{
--- 1358,1365 ----
{
operands[1] = force_reg (SImode, operands[1]);
operands[2] = force_reg (SImode, operands[2]);
! emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
! DONE;
}
else if (TARGET_SH5)
{
*************** (define_expand "udivsi3"
*** 1386,1396 ****
gen_rtx_SYMBOL_REF (SImode, \"__udivsi3\"));
last = gen_udivsi3_i1 (operands[0], operands[3]);
}
! if (! first)
! {
! first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
! emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
! }
last = emit_insn (last);
/* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
invariant code motion can move it. */
--- 1386,1393 ----
gen_rtx_SYMBOL_REF (SImode, \"__udivsi3\"));
last = gen_udivsi3_i1 (operands[0], operands[3]);
}
! first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
! emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
last = emit_insn (last);
/* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
invariant code motion can move it. */
*************** (define_expand "divsi3"
*** 1494,1500 ****
""
"
{
! rtx first = 0, last;
operands[3] = gen_reg_rtx (Pmode);
/* Emit the move of the address to a pseudo outside of the libcall. */
--- 1491,1497 ----
""
"
{
! rtx first, last;
operands[3] = gen_reg_rtx (Pmode);
/* Emit the move of the address to a pseudo outside of the libcall. */
*************** (define_expand "divsi3"
*** 1511,1518 ****
{
operands[1] = force_reg (SImode, operands[1]);
operands[2] = force_reg (SImode, operands[2]);
! last = gen_divsi3_i4_media (operands[0], operands[1], operands[2]);
! first = last;
}
else if (TARGET_SH5)
{
--- 1508,1515 ----
{
operands[1] = force_reg (SImode, operands[1]);
operands[2] = force_reg (SImode, operands[2]);
! emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
! DONE;
}
else if (TARGET_SH5)
{
*************** (define_expand "divsi3"
*** 1538,1548 ****
emit_move_insn (operands[3], gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3\"));
last = gen_divsi3_i1 (operands[0], operands[3]);
}
! if (! first)
! {
! first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
! emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
! }
last = emit_insn (last);
/* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
invariant code motion can move it. */
--- 1535,1542 ----
emit_move_insn (operands[3], gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3\"));
last = gen_divsi3_i1 (operands[0], operands[3]);
}
! first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
! emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
last = emit_insn (last);
/* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
invariant code motion can move it. */
*** /dev/null Tue Nov 14 21:44:43 2000
--- testsuite/gcc.c-torture/execute/20021112-4.c Thu Nov 14 17:11:08 2002
***************
*** 0 ****
--- 1,21 ----
+ int g1, g2;
+
+ void foo (int x)
+ {
+ int y;
+
+ if (x)
+ y = 793;
+ else
+ y = 793;
+ g1 = 7930 / y;
+ g2 = 7930 / x;
+ }
+
+ int main ()
+ {
+ foo (793);
+ if (g1 != 10 || g2 != 10)
+ abort ();
+ exit (0);
+ }