aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2005-11-01 18:12:32 -0800
committerRichard Henderson <rth@gcc.gnu.org>2005-11-01 18:12:32 -0800
commit745f2a84b9af863b30fa4eeaad778e0672feb4ab (patch)
treef8c7bb3ac6acc88ef7399b4180d01aa78289266f /gcc
parent12674da393dd9681b088012753fb0111156ab1b1 (diff)
downloadgcc-745f2a84b9af863b30fa4eeaad778e0672feb4ab.zip
gcc-745f2a84b9af863b30fa4eeaad778e0672feb4ab.tar.gz
gcc-745f2a84b9af863b30fa4eeaad778e0672feb4ab.tar.bz2
re PR target/21518 (unable to find a register with -fPIC and -O2 and non inlining static function)
PR 21518 * loop.c (scan_loop): Do not propagate computations to a hard register destination with SMALL_REGISTER_CLASSES. From-SVN: r106373
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/loop.c56
-rw-r--r--gcc/testsuite/gcc.target/i386/pr21518.c32
3 files changed, 68 insertions, 26 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b119e0f..e6d1b9c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2005-11-01 Richard Henderson <rth@redhat.com>
+
+ PR 21518
+ * loop.c (scan_loop): Do not propagate computations to a hard
+ register destination with SMALL_REGISTER_CLASSES.
+
2005-11-01 Joseph S. Myers <joseph@codesourcery.com>
* config/rs6000/rs6000.c (rs6000_rtx_costs): Do not add extra
diff --git a/gcc/loop.c b/gcc/loop.c
index 8142f63..b16c6a75 100644
--- a/gcc/loop.c
+++ b/gcc/loop.c
@@ -1266,12 +1266,13 @@ scan_loop (struct loop *loop, int flags)
{
struct movable *m;
int regno = REGNO (SET_DEST (set));
+ rtx user, user_set;
- /* A potential lossage is where we have a case where two insns
- can be combined as long as they are both in the loop, but
- we move one of them outside the loop. For large loops,
- this can lose. The most common case of this is the address
- of a function being called.
+ /* A potential lossage is where we have a case where two
+ insns can be combined as long as they are both in the
+ loop, but we move one of them outside the loop. For
+ large loops, this can lose. The most common case of
+ this is the address of a function being called.
Therefore, if this register is marked as being used
exactly once if we are in a loop with calls
@@ -1279,41 +1280,44 @@ scan_loop (struct loop *loop, int flags)
this register with the source of this SET. If we can,
delete this insn.
- Don't do this if P has a REG_RETVAL note or if we have
- SMALL_REGISTER_CLASSES and SET_SRC is a hard register. */
+ Don't do this if:
+ (1) P has a REG_RETVAL note or
+ (2) if we have SMALL_REGISTER_CLASSES and
+ (a) SET_SRC is a hard register or
+ (b) the destination of the user is a hard register. */
if (loop_info->has_call
- && regs->array[regno].single_usage != 0
- && regs->array[regno].single_usage != const0_rtx
+ && regno >= FIRST_PSEUDO_REGISTER
+ && (user = regs->array[regno].single_usage) != NULL
+ && user != const0_rtx
&& REGNO_FIRST_UID (regno) == INSN_UID (p)
- && (REGNO_LAST_UID (regno)
- == INSN_UID (regs->array[regno].single_usage))
+ && REGNO_LAST_UID (regno) == INSN_UID (user)
&& regs->array[regno].set_in_loop == 1
&& GET_CODE (SET_SRC (set)) != ASM_OPERANDS
&& ! side_effects_p (SET_SRC (set))
&& ! find_reg_note (p, REG_RETVAL, NULL_RTX)
- && (! SMALL_REGISTER_CLASSES
- || (! (REG_P (SET_SRC (set))
- && (REGNO (SET_SRC (set))
- < FIRST_PSEUDO_REGISTER))))
- && regno >= FIRST_PSEUDO_REGISTER
+ && (!SMALL_REGISTER_CLASSES
+ || !REG_P (SET_SRC (set))
+ || !HARD_REGISTER_P (SET_SRC (set)))
+ && (!SMALL_REGISTER_CLASSES
+ || !NONJUMP_INSN_P (user)
+ || !(user_set = single_set (user))
+ || !REG_P (SET_DEST (user_set))
+ || !HARD_REGISTER_P (SET_DEST (user_set)))
/* This test is not redundant; SET_SRC (set) might be
a call-clobbered register and the life of REGNO
might span a call. */
- && ! modified_between_p (SET_SRC (set), p,
- regs->array[regno].single_usage)
- && no_labels_between_p (p,
- regs->array[regno].single_usage)
- && validate_replace_rtx (SET_DEST (set), SET_SRC (set),
- regs->array[regno].single_usage))
+ && ! modified_between_p (SET_SRC (set), p, user)
+ && no_labels_between_p (p, user)
+ && validate_replace_rtx (SET_DEST (set),
+ SET_SRC (set), user))
{
/* Replace any usage in a REG_EQUAL note. Must copy
the new source, so that we don't get rtx sharing
between the SET_SOURCE and REG_NOTES of insn p. */
- REG_NOTES (regs->array[regno].single_usage)
- = (replace_rtx
- (REG_NOTES (regs->array[regno].single_usage),
- SET_DEST (set), copy_rtx (SET_SRC (set))));
+ REG_NOTES (user)
+ = replace_rtx (REG_NOTES (user), SET_DEST (set),
+ copy_rtx (SET_SRC (set)));
delete_insn (p);
for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set));
diff --git a/gcc/testsuite/gcc.target/i386/pr21518.c b/gcc/testsuite/gcc.target/i386/pr21518.c
new file mode 100644
index 0000000..f2ac666
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr21518.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -fno-tree-pre" } */
+/* { dg-require-effective-target ilp32 } */
+
+extern void __attribute__ ((regparm (3)))
+drawPointsLines (char type, int first, int *dd);
+
+int
+do_locator (int *call)
+{
+ char prephitmp5;
+ int type;
+ int i;
+
+ if (call == 0)
+ prephitmp5 = 1;
+ else
+ {
+ type = *call;
+ i = 0;
+ do
+ {
+ if (i != type)
+ drawPointsLines ((int) (char) type, 0, call);
+ i = i + 1;
+ }
+ while (i != 2);
+ prephitmp5 = (char) type;
+ }
+ drawPointsLines ((int) prephitmp5, 0, call);
+ return 0;
+}