diff options
author | Richard Henderson <rth@redhat.com> | 2005-11-01 18:12:32 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2005-11-01 18:12:32 -0800 |
commit | 745f2a84b9af863b30fa4eeaad778e0672feb4ab (patch) | |
tree | f8c7bb3ac6acc88ef7399b4180d01aa78289266f /gcc | |
parent | 12674da393dd9681b088012753fb0111156ab1b1 (diff) | |
download | gcc-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/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/loop.c | 56 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr21518.c | 32 |
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 @@ -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; +} |