This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[Xtensa Patch] Improve peformance when assembling Exception Table Entries
- From: Sterling Augustine <sterling at tensilica dot com>
- To: <binutils at sourceware dot org>
- Date: Wed, 19 Aug 2009 09:22:10 -0700
- Subject: [Xtensa Patch] Improve peformance when assembling Exception Table Entries
When the Xtensa port of gas encounters an expression that takes the
difference of two symbols, it walks the frags between those two symbols.
C++ exception tables as produced by GCC have a lot of these expressions,
and they are of the form a - b, a - c, a - d. This results in n-squared
performance in the length of the C++ function, which in turn prevents
certain G++ torture tests from completing in a reasonable amount of time.
This patch caches the second frag, allowing the traversal to continue
from where it left off, resulting in linear performance and allowing the
GCC torture tests to complete in reasonable time.
Sterling
2009-08-19 Sterling Augustine <sterling@tensilica.com>
* config/tc-xtensa.h (xtensa_frag_data): Rename unused field
fr_prev to no_transform_end.
* config/tc-xtensa.c (xtensa_mark_difference_of_two_symbols):
Set and use no_transform_end.
Index: tc-xtensa.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-xtensa.c,v
retrieving revision 1.112
diff -u -p -r1.112 tc-xtensa.c
--- tc-xtensa.c 18 Aug 2009 16:42:15 -0000 1.112
+++ tc-xtensa.c 19 Aug 2009 16:00:02 -0000
@@ -7460,6 +7460,7 @@ xtensa_mark_difference_of_two_symbols (v
{
fragS *start;
fragS *end;
+ fragS *walk;
if (symbol_get_frag (left)->fr_address
<= symbol_get_frag (right)->fr_address)
@@ -7472,12 +7473,19 @@ xtensa_mark_difference_of_two_symbols (v
start = symbol_get_frag (right);
end = symbol_get_frag (left);
}
+
+ if (start->tc_frag_data.no_transform_end != NULL)
+ walk = start->tc_frag_data.no_transform_end;
+ else
+ walk = start;
do
{
- start->tc_frag_data.is_no_transform = 1;
- start = start->fr_next;
+ walk->tc_frag_data.is_no_transform = 1;
+ walk = walk->fr_next;
}
- while (start && start->fr_address < end->fr_address);
+ while (walk && walk->fr_address < end->fr_address);
+
+ start->tc_frag_data.no_transform_end = walk;
}
}
}
Index: tc-xtensa.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-xtensa.h,v
retrieving revision 1.32
diff -u -p -r1.32 tc-xtensa.h
--- tc-xtensa.h 4 Nov 2008 23:11:02 -0000 1.32
+++ tc-xtensa.h 19 Aug 2009 16:00:02 -0000
@@ -263,9 +263,10 @@ struct xtensa_frag_type
symbolS *slot_symbols[MAX_SLOTS];
offsetT slot_offsets[MAX_SLOTS];
- /* The global aligner needs to walk backward through the list of
- frags. This field is only valid after xtensa_end. */
- fragS *fr_prev;
+ /* When marking frags after this one in the chain as no transform,
+ cache the last one in the chain, so that we can skip to the
+ end of the chain. */
+ fragS *no_transform_end;
};