aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2015-02-04 16:39:16 +0000
committerNick Clifton <nickc@gcc.gnu.org>2015-02-04 16:39:16 +0000
commit771bef141f7b3233843415e91b58909c161c7f11 (patch)
treef38afb1a2745b90f21c2060a666dd6bc4ce1c643
parentf435bff380b38ad9ecd5b67a54de88c1ee5b1d22 (diff)
downloadgcc-771bef141f7b3233843415e91b58909c161c7f11.zip
gcc-771bef141f7b3233843415e91b58909c161c7f11.tar.gz
gcc-771bef141f7b3233843415e91b58909c161c7f11.tar.bz2
fpmath-sf.S (__rl78_int_pack_a_r8): Fix edge case rounding up the fraction.
* config/rl78/fpmath-sf.S (__rl78_int_pack_a_r8): Fix edge case rounding up the fraction. * config/rl78/rl78.c (rl78_note_reg_set): Note the use of REGs inside a MEM. From-SVN: r220410
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/rl78/rl78.c368
-rw-r--r--libgcc/ChangeLog5
-rw-r--r--libgcc/config/rl78/fpmath-sf.S14
4 files changed, 254 insertions, 138 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4e03848..74728f8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2015-02-04 Nick Clifton <nickc@redhat.com>
+
+ * config/rl78/rl78.c (rl78_note_reg_set): Note the use of REGs
+ inside a MEM.
+
2015-02-04 Jakub Jelinek <jakub@redhat.com>
* builtins.def (DEF_BUILTIN_CHKP): Define if not defined.
diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c
index 818f077..1ab483e 100644
--- a/gcc/config/rl78/rl78.c
+++ b/gcc/config/rl78/rl78.c
@@ -1003,7 +1003,6 @@ rl78_valid_pointer_mode (machine_mode m)
return (m == HImode || m == SImode);
}
-
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
@@ -2723,7 +2722,7 @@ transcode_memory_rtx (rtx m, rtx newbase, rtx before)
if (REGNO (base) == SP_REG)
{
- if (addend >= 0 && addend <= limit)
+ if (addend >= 0 && addend <= limit)
return m;
}
@@ -2933,8 +2932,8 @@ rl78_alloc_physical_registers_op1 (rtx_insn * insn)
It is tempting to perform this optimization when OP(0) does
not hold a MEM, but this leads to bigger code in general.
The problem is that if OP(1) holds a MEM then swapping it
- into BC means a BC-relative load is used and these 3 bytes
- long vs 1 byte for an HL load. */
+ into BC means a BC-relative load is used and these are 3
+ bytes long vs 1 byte for an HL load. */
if (MEM_P (OP (0))
&& already_contains (HL, XEXP (OP (0), 0)))
{
@@ -3379,6 +3378,12 @@ rl78_alloc_address_registers_macax (rtx_insn * insn)
MUST_BE_OK (insn);
}
+static void
+rl78_alloc_address_registers_div (rtx_insn * insn)
+{
+ MUST_BE_OK (insn);
+}
+
/* Scan all insns and devirtualize them. */
static void
rl78_alloc_physical_registers (void)
@@ -3457,6 +3462,18 @@ rl78_alloc_physical_registers (void)
record_content (BC, NULL_RTX);
record_content (DE, NULL_RTX);
}
+ else if (valloc_method == VALLOC_DIVHI)
+ {
+ record_content (AX, NULL_RTX);
+ record_content (BC, NULL_RTX);
+ }
+ else if (valloc_method == VALLOC_DIVSI)
+ {
+ record_content (AX, NULL_RTX);
+ record_content (BC, NULL_RTX);
+ record_content (DE, NULL_RTX);
+ record_content (HL, NULL_RTX);
+ }
if (insn_ok_now (insn))
continue;
@@ -3492,6 +3509,20 @@ rl78_alloc_physical_registers (void)
record_content (BC, NULL_RTX);
record_content (DE, NULL_RTX);
break;
+ case VALLOC_DIVSI:
+ rl78_alloc_address_registers_div (insn);
+ record_content (AX, NULL_RTX);
+ record_content (BC, NULL_RTX);
+ record_content (DE, NULL_RTX);
+ record_content (HL, NULL_RTX);
+ break;
+ case VALLOC_DIVHI:
+ rl78_alloc_address_registers_div (insn);
+ record_content (AX, NULL_RTX);
+ record_content (BC, NULL_RTX);
+ break;
+ default:
+ gcc_unreachable ();
}
if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
@@ -3577,6 +3608,9 @@ rl78_note_reg_set (char *dead, rtx d, rtx insn)
{
int r, i;
+ if (GET_CODE (d) == MEM)
+ rl78_note_reg_uses (dead, XEXP (d, 0), insn);
+
if (GET_CODE (d) != REG)
return;
@@ -3620,7 +3654,21 @@ rl78_calculate_death_notes (void)
case INSN:
p = PATTERN (insn);
if (GET_CODE (p) == PARALLEL)
- p = XVECEXP (p, 0, 0);
+ {
+ rtx q = XVECEXP (p, 0 ,1);
+
+ /* This happens with the DIV patterns. */
+ if (GET_CODE (q) == SET)
+ {
+ s = SET_SRC (q);
+ d = SET_DEST (q);
+ rl78_note_reg_set (dead, d, insn);
+ rl78_note_reg_uses (dead, s, insn);
+
+ }
+ p = XVECEXP (p, 0, 0);
+ }
+
switch (GET_CODE (p))
{
case SET:
@@ -3674,6 +3722,175 @@ reset_origins (int *rp, int *age)
}
}
+static void
+set_origin (rtx pat, rtx_insn * insn, int * origins, int * age)
+{
+ rtx src = SET_SRC (pat);
+ rtx dest = SET_DEST (pat);
+ int mb = GET_MODE_SIZE (GET_MODE (dest));
+ int i;
+
+ if (GET_CODE (dest) == REG)
+ {
+ int dr = REGNO (dest);
+
+ if (GET_CODE (src) == REG)
+ {
+ int sr = REGNO (src);
+ bool same = true;
+ int best_age, best_reg;
+
+ /* See if the copy is not needed. */
+ for (i = 0; i < mb; i ++)
+ if (origins[dr + i] != origins[sr + i])
+ same = false;
+
+ if (same)
+ {
+ if (dump_file)
+ fprintf (dump_file, "deleting because dest already has correct value\n");
+ delete_insn (insn);
+ return;
+ }
+
+ if (dr < 8 || sr >= 8)
+ {
+ int ar;
+
+ best_age = -1;
+ best_reg = -1;
+
+ /* See if the copy can be made from another
+ bank 0 register instead, instead of the
+ virtual src register. */
+ for (ar = 0; ar < 8; ar += mb)
+ {
+ same = true;
+
+ for (i = 0; i < mb; i ++)
+ if (origins[ar + i] != origins[sr + i])
+ same = false;
+
+ /* The chip has some reg-reg move limitations. */
+ if (mb == 1 && dr > 3)
+ same = false;
+
+ if (same)
+ {
+ if (best_age == -1 || best_age > age[sr + i])
+ {
+ best_age = age[sr + i];
+ best_reg = sr;
+ }
+ }
+ }
+
+ if (best_reg != -1)
+ {
+ /* FIXME: copy debug info too. */
+ SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
+ sr = best_reg;
+ }
+ }
+
+ for (i = 0; i < mb; i++)
+ {
+ origins[dr + i] = origins[sr + i];
+ age[dr + i] = age[sr + i] + 1;
+ }
+ }
+ else
+ {
+ /* The destination is computed, its origin is itself. */
+ if (dump_file)
+ fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
+ dr, mb, mb == 1 ? "" : "s");
+
+ for (i = 0; i < mb; i ++)
+ {
+ origins[dr + i] = dr + i;
+ age[dr + i] = 0;
+ }
+ }
+
+ /* Any registers marked with that reg as an origin are reset. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (origins[i] >= dr && origins[i] < dr + mb)
+ {
+ origins[i] = i;
+ age[i] = 0;
+ }
+ }
+
+ /* Special case - our MUL patterns uses AX and sometimes BC. */
+ if (get_attr_valloc (insn) == VALLOC_MACAX)
+ {
+ if (dump_file)
+ fprintf (dump_file, "Resetting origin of AX/BC for MUL pattern.\n");
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (i <= 3 || origins[i] <= 3)
+ {
+ origins[i] = i;
+ age[i] = 0;
+ }
+ }
+ else if (get_attr_valloc (insn) == VALLOC_DIVHI)
+ {
+ if (dump_file)
+ fprintf (dump_file, "Resetting origin of AX/DE for DIVHI pattern.\n");
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (i == A_REG
+ || i == X_REG
+ || i == D_REG
+ || i == E_REG
+ || origins[i] == A_REG
+ || origins[i] == X_REG
+ || origins[i] == D_REG
+ || origins[i] == E_REG)
+ {
+ origins[i] = i;
+ age[i] = 0;
+ }
+ }
+ else if (get_attr_valloc (insn) == VALLOC_DIVSI)
+ {
+ if (dump_file)
+ fprintf (dump_file, "Resetting origin of AX/BC/DE/HL for DIVSI pattern.\n");
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (i <= 7 || origins[i] <= 7)
+ {
+ origins[i] = i;
+ age[i] = 0;
+ }
+ }
+
+ if (GET_CODE (src) == ASHIFT
+ || GET_CODE (src) == ASHIFTRT
+ || GET_CODE (src) == LSHIFTRT)
+ {
+ rtx count = XEXP (src, 1);
+
+ if (GET_CODE (count) == REG)
+ {
+ /* Special case - our pattern clobbers the count register. */
+ int r = REGNO (count);
+
+ if (dump_file)
+ fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (i == r || origins[i] == r)
+ {
+ origins[i] = i;
+ age[i] = 0;
+ }
+ }
+ }
+}
+
/* The idea behind this optimization is to look for cases where we
move data from A to B to C, and instead move from A to B, and A to
C. If B is a virtual register or memory, this is a big win on its
@@ -3740,136 +3957,18 @@ rl78_propogate_register_origins (void)
age[cr + i] = 0;
}
}
+ /* This happens with the DIV patterns. */
+ else if (GET_CODE (clobber) == SET)
+ {
+ set_origin (clobber, insn, origins, age);
+ }
else
break;
}
if (GET_CODE (pat) == SET)
{
- rtx src = SET_SRC (pat);
- rtx dest = SET_DEST (pat);
- int mb = GET_MODE_SIZE (GET_MODE (dest));
-
- if (GET_CODE (dest) == REG)
- {
- int dr = REGNO (dest);
-
- if (GET_CODE (src) == REG)
- {
- int sr = REGNO (src);
- int same = 1;
- int best_age, best_reg;
-
- /* See if the copy is not needed. */
- for (i = 0; i < mb; i ++)
- if (origins[dr + i] != origins[sr + i])
- same = 0;
- if (same)
- {
- if (dump_file)
- fprintf (dump_file, "deleting because dest already has correct value\n");
- delete_insn (insn);
- break;
- }
-
- if (dr < 8 || sr >= 8)
- {
- int ar;
-
- best_age = -1;
- best_reg = -1;
- /* See if the copy can be made from another
- bank 0 register instead, instead of the
- virtual src register. */
- for (ar = 0; ar < 8; ar += mb)
- {
- same = 1;
- for (i = 0; i < mb; i ++)
- if (origins[ar + i] != origins[sr + i])
- same = 0;
-
- /* The chip has some reg-reg move limitations. */
- if (mb == 1 && dr > 3)
- same = 0;
-
- if (same)
- {
- if (best_age == -1 || best_age > age[sr + i])
- {
- best_age = age[sr + i];
- best_reg = sr;
- }
- }
- }
-
- if (best_reg != -1)
- {
- /* FIXME: copy debug info too. */
- SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
- sr = best_reg;
- }
- }
-
- for (i = 0; i < mb; i++)
- {
- origins[dr + i] = origins[sr + i];
- age[dr + i] = age[sr + i] + 1;
- }
- }
- else
- {
- /* The destination is computed, its origin is itself. */
- if (dump_file)
- fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
- dr, mb, mb == 1 ? "" : "s");
- for (i = 0; i < mb; i ++)
- {
- origins[dr + i] = dr + i;
- age[dr + i] = 0;
- }
- }
-
- /* Any registers marked with that reg as an origin are reset. */
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (origins[i] >= dr && origins[i] < dr + mb)
- {
- origins[i] = i;
- age[i] = 0;
- }
- }
-
- /* Special case - our ADDSI3 macro uses AX and sometimes BC. */
- if (get_attr_valloc (insn) == VALLOC_MACAX)
- {
- if (dump_file)
- fprintf (dump_file, "Resetting origin of AX/BC for macro.\n");
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (i <= 3 || origins[i] <= 3)
- {
- origins[i] = i;
- age[i] = 0;
- }
- }
-
- if (GET_CODE (src) == ASHIFT
- || GET_CODE (src) == ASHIFTRT
- || GET_CODE (src) == LSHIFTRT)
- {
- rtx count = XEXP (src, 1);
- if (GET_CODE (count) == REG)
- {
- /* Special case - our pattern clobbers the count register. */
- int r = REGNO (count);
- if (dump_file)
- fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (i == r || origins[i] == r)
- {
- origins[i] = i;
- age[i] = 0;
- }
- }
- }
+ set_origin (pat, insn, origins, age);
}
else if (GET_CODE (pat) == CLOBBER
&& GET_CODE (XEXP (pat, 0)) == REG)
@@ -3907,7 +4006,11 @@ rl78_remove_unused_sets (void)
continue;
if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
- delete_insn (insn);
+ {
+ if (dump_file)
+ fprintf (dump_file, "deleting because the set register is never used.\n");
+ delete_insn (insn);
+ }
}
}
@@ -4023,8 +4126,6 @@ static bool rl78_rtx_costs (rtx x,
}
-
-
static GTY(()) section * saddr_section;
static GTY(()) section * frodata_section;
@@ -4326,7 +4427,6 @@ rl78_asm_out_integer (rtx x, unsigned int size, int aligned_p)
return false;
}
-
#undef TARGET_UNWIND_WORD_MODE
#define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
@@ -4441,7 +4541,7 @@ rl78_flags_already_set (rtx op, rtx operand)
return res;
}
-
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-rl78.h"
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 8d7a6b0..d5540b0 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,8 @@
+2015-02-02 Nick Clifton <nickc@redhat.com>
+
+ * config/rl78/fpmath-sf.S (__rl78_int_pack_a_r8): Fix edge case
+ rounding up the fraction.
+
2015-01-31 John David Anglin <danglin@gcc.gnu.org>
* config/pa/linux-atomic.c (__kernel_cmpxchg2): Change declaration of
diff --git a/libgcc/config/rl78/fpmath-sf.S b/libgcc/config/rl78/fpmath-sf.S
index f232f6b..6d4d4bd 100644
--- a/libgcc/config/rl78/fpmath-sf.S
+++ b/libgcc/config/rl78/fpmath-sf.S
@@ -49,9 +49,6 @@ START_FUNC __int_isinf
END_FUNC __int_isinf
-START_FUNC _int_unpack_sf
- ;; convert 32-bit SFmode [DE] to 6-byte struct [HL] ("A")
-
#define A_SIGN [hl+0] /* byte */
#define A_EXP [hl+2] /* word */
#define A_FRAC_L [hl+4] /* word */
@@ -66,6 +63,9 @@ START_FUNC _int_unpack_sf
#define B_FRAC_H [hl+14]
#define B_FRAC_HH [hl+15]
+START_FUNC _int_unpack_sf
+ ;; convert 32-bit SFmode [DE] to 6-byte struct [HL] ("A")
+
mov a, [de+3]
sar a, 7
mov A_SIGN, a
@@ -517,8 +517,14 @@ START_FUNC __rl78_int_pack_a_r8
movw ax, A_FRAC_L
addw ax, #1
movw A_FRAC_L, ax
- sknc
+ bnc $1f
incw A_FRAC_H
+
+ ;; If the rounding set the bit beyond the end of the fraction, increment the exponent.
+ mov a, A_FRAC_HH
+ bf a.1, $1f
+ incw A_EXP
+
1:
movw ax, A_FRAC_H
shrw ax, 1