summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2005-11-21 05:41:36 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2005-11-21 05:41:36 +0000
commit5b75b0ba2eae5a416236e3ce672cb716ad442cfa (patch)
tree891b2df27aca9fecd5a0db1dc87070296af18bee /gcc
parent0ab04fbf45c28653f78852187514c67d86295140 (diff)
downloadgcc-5b75b0ba2eae5a416236e3ce672cb716ad442cfa.tar.gz
./:
PR rtl-optimization/24883 * combine.c (combinable_i3pat): When checking whether the destination of i3 is used in i3, consider paradoxical subregs. testsuite/: PR rtl-optimization/24883 * gcc.c-torture/compile/pr24883.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@107279 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/combine.c29
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr24883.c21
4 files changed, 51 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5f1e761a4ad..630bebc1bbf 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2005-11-20 Ian Lance Taylor <ian@airs.com>
+
+ PR rtl-optimization/24883
+ * combine.c (combinable_i3pat): When checking whether the
+ destination of i3 is used in i3, consider paradoxical subregs.
+
2005-11-21 Kazu Hirata <kazu@codesourcery.com>
PR middle-end/20583
diff --git a/gcc/combine.c b/gcc/combine.c
index 6497336bf44..abd64582d3e 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -1423,6 +1423,7 @@ combinable_i3pat (rtx i3, rtx *loc, rtx i2dest, rtx i1dest,
rtx dest = SET_DEST (set);
rtx src = SET_SRC (set);
rtx inner_dest = dest;
+ rtx subdest;
while (GET_CODE (inner_dest) == STRICT_LOW_PART
|| GET_CODE (inner_dest) == SUBREG
@@ -1457,27 +1458,35 @@ combinable_i3pat (rtx i3, rtx *loc, rtx i2dest, rtx i1dest,
|| (i1_not_in_src && reg_overlap_mentioned_p (i1dest, src)))
return 0;
- /* If DEST is used in I3, it is being killed in this insn,
- so record that for later.
+ /* If DEST is used in I3, it is being killed in this insn, so
+ record that for later. We have to consider paradoxical
+ subregs here, since they kill the whole register, but we
+ ignore partial subregs, STRICT_LOW_PART, etc.
Never add REG_DEAD notes for the FRAME_POINTER_REGNUM or the
STACK_POINTER_REGNUM, since these are always considered to be
live. Similarly for ARG_POINTER_REGNUM if it is fixed. */
- if (pi3dest_killed && REG_P (dest)
- && reg_referenced_p (dest, PATTERN (i3))
- && REGNO (dest) != FRAME_POINTER_REGNUM
+ subdest = dest;
+ if (GET_CODE (subdest) == SUBREG
+ && (GET_MODE_SIZE (GET_MODE (subdest))
+ >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (subdest)))))
+ subdest = SUBREG_REG (subdest);
+ if (pi3dest_killed
+ && REG_P (subdest)
+ && reg_referenced_p (subdest, PATTERN (i3))
+ && REGNO (subdest) != FRAME_POINTER_REGNUM
#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
- && REGNO (dest) != HARD_FRAME_POINTER_REGNUM
+ && REGNO (subdest) != HARD_FRAME_POINTER_REGNUM
#endif
#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
- && (REGNO (dest) != ARG_POINTER_REGNUM
- || ! fixed_regs [REGNO (dest)])
+ && (REGNO (subdest) != ARG_POINTER_REGNUM
+ || ! fixed_regs [REGNO (subdest)])
#endif
- && REGNO (dest) != STACK_POINTER_REGNUM)
+ && REGNO (subdest) != STACK_POINTER_REGNUM)
{
if (*pi3dest_killed)
return 0;
- *pi3dest_killed = dest;
+ *pi3dest_killed = subdest;
}
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 48f03546b5f..1a05c183fec 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2005-11-20 Ian Lance Taylor <ian@airs.com>
+
+ PR rtl-optimization/24883
+ * gcc.c-torture/compile/pr24883.c: New test.
+
2005-11-21 Kazu Hirata <kazu@codesourcery.com>
PR middle-end/20583
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr24883.c b/gcc/testsuite/gcc.c-torture/compile/pr24883.c
new file mode 100644
index 00000000000..b2ced75ac96
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr24883.c
@@ -0,0 +1,21 @@
+typedef struct _rec_stl rec_stl;
+struct _rec_stl {
+ unsigned char **strs;
+};
+orec_str_list(int count) {
+ rec_stl *stl;
+ int i, j;
+ int li, lj;
+ unsigned char ci, cj;
+ for (i = 0; i < count; i++) {
+ for (j = i + 1; j < count; j++) {
+ cj = lj > 2 ? stl->strs[j][0] : (long)stl->strs[j] & 0xff;
+ if ((count >= 16 && cj < ci) || (cj == ci && lj > li)) {
+ stl->strs[j] = stl->strs[i];
+ ci ^= cj;
+ cj ^= ci;
+ ci ^= cj;
+ }
+ }
+ }
+}