aboutsummaryrefslogtreecommitdiff
path: root/gcc/final.c
diff options
context:
space:
mode:
authorJoern Rennecke <joern.rennecke@embecosm.com>2012-10-20 13:46:07 +0000
committerJoern Rennecke <amylaar@gcc.gnu.org>2012-10-20 14:46:07 +0100
commitf6df08e637baa5670a655e9f5736da11ea8627da (patch)
treec4385055d088a40f9ad6700d2461467bafef1710 /gcc/final.c
parent8e383849646654485307714640f89699bc6538ee (diff)
downloadgcc-f6df08e637baa5670a655e9f5736da11ea8627da.zip
gcc-f6df08e637baa5670a655e9f5736da11ea8627da.tar.gz
gcc-f6df08e637baa5670a655e9f5736da11ea8627da.tar.bz2
final.c (shorten_branches): When optimizing...
* final.c (shorten_branches): When optimizing, start with small length and increase from there, and don't decrease lengths. Co-Authored-By: Richard Sandiford <rdsandiford@googlemail.com> From-SVN: r192634
Diffstat (limited to 'gcc/final.c')
-rw-r--r--gcc/final.c46
1 files changed, 36 insertions, 10 deletions
diff --git a/gcc/final.c b/gcc/final.c
index 0839340..bffc1a9 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -1009,6 +1009,13 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
align_tab[i] = seq;
}
}
+
+ /* When optimizing, we start assuming minimum length, and keep increasing
+ lengths as we find the need for this, till nothing changes.
+ When not optimizing, we start assuming maximum lengths, and
+ do a single pass to update the lengths. */
+ bool increasing = optimize != 0;
+
#ifdef CASE_VECTOR_SHORTEN_MODE
if (optimize)
{
@@ -1062,11 +1069,16 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
flags.min_after_base = min > rel;
flags.max_after_base = max > rel;
ADDR_DIFF_VEC_FLAGS (pat) = flags;
+
+ if (increasing)
+ PUT_MODE (pat, CASE_VECTOR_SHORTEN_MODE (0, 0, pat));
}
}
#endif /* CASE_VECTOR_SHORTEN_MODE */
/* Compute initial lengths, addresses, and varying flags for each insn. */
+ int (*length_fun) (rtx) = increasing ? insn_min_length : insn_default_length;
+
for (insn_current_address = 0, insn = first;
insn != 0;
insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn))
@@ -1117,6 +1129,8 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
#else
const_delay_slots = 0;
#endif
+ int (*inner_length_fun) (rtx)
+ = const_delay_slots ? length_fun : insn_default_length;
/* Inside a delay slot sequence, we do not do any branch shortening
if the shortening could change the number of delay slots
of the branch. */
@@ -1131,7 +1145,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
inner_length = (asm_insn_count (PATTERN (inner_insn))
* insn_default_length (inner_insn));
else
- inner_length = insn_default_length (inner_insn);
+ inner_length = inner_length_fun (inner_insn);
insn_lengths[inner_uid] = inner_length;
if (const_delay_slots)
@@ -1149,7 +1163,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
}
else if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER)
{
- insn_lengths[uid] = insn_default_length (insn);
+ insn_lengths[uid] = length_fun (insn);
varying_length[uid] = insn_variable_length_p (insn);
}
@@ -1220,6 +1234,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
rtx prev;
int rel_align = 0;
addr_diff_vec_flags flags;
+ enum machine_mode vec_mode;
/* Avoid automatic aggregate initialization. */
flags = ADDR_DIFF_VEC_FLAGS (body);
@@ -1298,9 +1313,12 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
else
max_addr += align_fuzz (max_lab, rel_lab, 0, 0);
}
- PUT_MODE (body, CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr,
- max_addr - rel_addr,
- body));
+ vec_mode = CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr,
+ max_addr - rel_addr, body);
+ if (!increasing
+ || (GET_MODE_SIZE (vec_mode)
+ >= GET_MODE_SIZE (GET_MODE (body))))
+ PUT_MODE (body, vec_mode);
if (JUMP_TABLES_IN_TEXT_SECTION
|| readonly_data_section == text_section)
{
@@ -1362,10 +1380,15 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
if (inner_length != insn_lengths[inner_uid])
{
- insn_lengths[inner_uid] = inner_length;
- something_changed = 1;
+ if (!increasing || inner_length > insn_lengths[inner_uid])
+ {
+ insn_lengths[inner_uid] = inner_length;
+ something_changed = 1;
+ }
+ else
+ inner_length = insn_lengths[inner_uid];
}
- insn_current_address += insn_lengths[inner_uid];
+ insn_current_address += inner_length;
new_length += inner_length;
}
}
@@ -1382,14 +1405,17 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
insn_current_address += (new_length - tmp_length);
#endif
- if (new_length != insn_lengths[uid])
+ if (new_length != insn_lengths[uid]
+ && (!increasing || new_length > insn_lengths[uid]))
{
insn_lengths[uid] = new_length;
something_changed = 1;
}
+ else
+ insn_current_address += insn_lengths[uid] - new_length;
}
/* For a non-optimizing compile, do only a single pass. */
- if (!optimize)
+ if (!increasing)
break;
}