This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch to speed up relaxation


I just checked in the appended patch to speed up relaxation
significantly in some cases.  This moves the time it takes to assemble
one testcase from about 3 minutes to about 3 seconds.

This probably shouldn't go into 2.11 without more testing than I have
done.  It should be safe in the sense that it will not fail silently.


Incidentally, the i386 gas testsuite appears to be broken.  It looks
like somebody changed the disassembler without updating the
testsuite.  When I run `make check-gas', I get several failures like
these in ``naked reg'':

regexp_diff match failure
regexp "^   0:	66 26 ff 23 [ 	]*jmpw   \*%es:\(%ebx\)$"
line   "   0:	66 26 ff 23          	jmp    *%es:(%ebx)"
regexp_diff match failure
regexp "^   4:	8a 25 50 00 00 00 [ 	]*mov    0x50,%ah$"
line   "   4:	8a 25 50 00 00 00    	movb   0x50,%ah"


Ian

Index: write.c
===================================================================
RCS file: /cvs/src/src/gas/write.c,v
retrieving revision 1.25
diff -u -r1.25 write.c
--- write.c	2000/12/28 19:14:37	1.25
+++ write.c	2001/02/13 21:18:52
@@ -1998,21 +1998,30 @@
 static int is_dnrange PARAMS ((fragS *, fragS *));
 
 /* Subroutines of relax_segment.  */
+
 static int
 is_dnrange (f1, f2)
      fragS *f1;
      fragS *f2;
 {
+  addressT f2addr;
+
+  f2addr = f2->fr_address;
   for (; f1; f1 = f1->fr_next)
-    if (f1->fr_next == f2)
-      return 1;
+    {
+      if (f1->fr_next == f2)
+	return 1;
+      if (f1->fr_address > f2addr)
+	break;
+    }
   return 0;
 }
 
 /* Relax a fragment by scanning TC_GENERIC_RELAX_TABLE.  */
 
 long
-relax_frag (fragP, stretch)
+relax_frag (segment, fragP, stretch)
+     segT segment;
      fragS *fragP;
      long stretch;
 {
@@ -2034,6 +2043,10 @@
 
   if (symbolP)
     {
+      fragS *sym_frag;
+
+      sym_frag = symbol_get_frag (symbolP);
+
 #ifndef DIFF_EXPR_OK
 #if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
       know ((S_GET_SEGMENT (symbolP) == SEG_ABSOLUTE)
@@ -2041,23 +2054,24 @@
 	    || (S_GET_SEGMENT (symbolP) == SEG_BSS)
 	    || (S_GET_SEGMENT (symbolP) == SEG_TEXT));
 #endif
-      know (symbolP->sy_frag);
+      know (sym_frag != NULL);
 #endif
       know (!(S_GET_SEGMENT (symbolP) == absolute_section)
-	    || symbolP->sy_frag == &zero_address_frag);
-      target += S_GET_VALUE (symbolP) + symbol_get_frag (symbolP)->fr_address;
+	    || sym_frag == &zero_address_frag);
+      target += S_GET_VALUE (symbolP) + sym_frag->fr_address;
 
       /* If frag has yet to be reached on this pass,
 	 assume it will move by STRETCH just as we did.
 	 If this is not so, it will be because some frag
 	 between grows, and that will force another pass.
-
-	 Beware zero-length frags.
 
-	 There should be a faster way to do this.  */
+	 Beware zero-length frags.  */
 
-      if (symbol_get_frag (symbolP)->fr_address >= was_address
-	  && is_dnrange (fragP, symbol_get_frag (symbolP)))
+      if (stretch != 0
+	  && S_GET_SEGMENT (symbolP) == segment
+	  && (sym_frag->fr_address > was_address
+	      || (sym_frag->fr_address == was_address
+		  && is_dnrange (fragP, sym_frag))))
 	{
 	  target += stretch;
 	}
@@ -2413,12 +2427,12 @@
 
 	      case rs_machine_dependent:
 #ifdef md_relax_frag
-		growth = md_relax_frag (fragP, stretch);
+		growth = md_relax_frag (segment, fragP, stretch);
 #else
 #ifdef TC_GENERIC_RELAX_TABLE
 		/* The default way to relax a frag is to look through
 		   TC_GENERIC_RELAX_TABLE.  */
-		growth = relax_frag (fragP, stretch);
+		growth = relax_frag (segment, fragP, stretch);
 #endif /* TC_GENERIC_RELAX_TABLE  */
 #endif
 		break;
Index: write.h
===================================================================
RCS file: /cvs/src/src/gas/write.h,v
retrieving revision 1.3
diff -u -r1.3 write.h
--- write.h	2000/12/28 10:07:55	1.3
+++ write.h	2001/02/13 21:18:52
@@ -181,7 +181,7 @@
 extern int get_recorded_alignment PARAMS ((segT seg));
 extern void subsegs_finish PARAMS ((void));
 extern void write_object_file PARAMS ((void));
-extern long relax_frag PARAMS ((fragS *, long));
+extern long relax_frag PARAMS ((segT, fragS *, long));
 extern void relax_segment
   PARAMS ((struct frag * seg_frag_root, segT seg_type));
 
Index: config/tc-fr30.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-fr30.c,v
retrieving revision 1.3
diff -u -r1.3 tc-fr30.c
--- tc-fr30.c	2000/09/26 07:09:18	1.3
+++ tc-fr30.c	2001/02/13 21:18:52
@@ -208,7 +208,8 @@
 };
 
 long
-fr30_relax_frag (fragP, stretch)
+fr30_relax_frag (segment, fragP, stretch)
+     segT    segment;
      fragS * fragP;
      long    stretch;
 {
@@ -235,7 +236,7 @@
     }
   else
     {
-      growth = relax_frag (fragP, stretch);
+      growth = relax_frag (segment, fragP, stretch);
 
       /* Long jump on odd halfword boundary?  */
       if (fragP->fr_subtype == 2 && (address & 3) != 0)
Index: config/tc-m32r.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-m32r.c,v
retrieving revision 1.15
diff -u -r1.15 tc-m32r.c
--- tc-m32r.c	2001/01/23 13:31:10	1.15
+++ tc-m32r.c	2001/02/13 21:18:52
@@ -1384,7 +1384,8 @@
 };
 
 long
-m32r_relax_frag (fragP, stretch)
+m32r_relax_frag (segment, fragP, stretch)
+     segT segment;
      fragS *fragP;
      long stretch;
 {
@@ -1411,7 +1412,7 @@
     }
   else
     {
-      growth = relax_frag (fragP, stretch);
+      growth = relax_frag (segment, fragP, stretch);
 
       /* Long jump on odd halfword boundary?  */
       if (fragP->fr_subtype == 2 && (address & 3) != 0)
Index: config/tc-m32r.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-m32r.h,v
retrieving revision 1.3
diff -u -r1.3 tc-m32r.h
--- tc-m32r.h	2000/12/28 10:07:56	1.3
+++ tc-m32r.h	2001/02/13 21:18:52
@@ -54,9 +54,9 @@
 #define md_prepare_relax_scan(fragP, address, aim, this_state, this_type) \
 m32r_prepare_relax_scan (fragP, address, aim, this_state, this_type)
 #else
-extern long m32r_relax_frag PARAMS ((fragS *, long));
-#define md_relax_frag(fragP, stretch) \
-m32r_relax_frag (fragP, stretch)
+extern long m32r_relax_frag PARAMS ((segT, fragS *, long));
+#define md_relax_frag(segment, fragP, stretch) \
+m32r_relax_frag (segment, fragP, stretch)
 #endif
 /* Account for nop if 32 bit insn falls on odd halfword boundary.  */
 #define TC_CGEN_MAX_RELAX(insn, len) (6)
Index: config/tc-mips.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.h,v
retrieving revision 1.7
diff -u -r1.7 tc-mips.h
--- tc-mips.h	2000/12/28 10:07:56	1.7
+++ tc-mips.h	2001/02/13 21:18:52
@@ -49,7 +49,7 @@
    relocation: */
 #define MAX_GPREL_OFFSET (0x7FF4)
 
-#define md_relax_frag(fragp, stretch) mips_relax_frag(fragp, stretch)
+#define md_relax_frag(segment, fragp, stretch) mips_relax_frag(fragp, stretch)
 extern int mips_relax_frag PARAMS ((struct frag *, long));
 
 #define md_undefined_symbol(name)	(0)
Index: config/tc-tic54x.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-tic54x.h,v
retrieving revision 1.3
diff -u -r1.3 tc-tic54x.h
--- tc-tic54x.h	2000/11/28 21:29:02	1.3
+++ tc-tic54x.h	2001/02/13 21:18:52
@@ -108,7 +108,7 @@
 tic54x_estimate_size_before_relax(f,s)
 extern int tic54x_estimate_size_before_relax(fragS *, segT);
 
-#define md_relax_frag(f,s) tic54x_relax_frag(f,s)
+#define md_relax_frag(seg, f,s) tic54x_relax_frag(f,s)
 extern int tic54x_relax_frag(fragS *, long);
 
 #define md_convert_frag(b,s,f)	tic54x_convert_frag(b,s,f)
Index: doc/internals.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/internals.texi,v
retrieving revision 1.20
diff -u -r1.20 internals.texi
--- internals.texi	2000/12/31 19:54:58	1.20
+++ internals.texi	2001/02/13 21:18:52
@@ -1166,9 +1166,10 @@
 
 @item md_relax_frag
 @cindex md_relax_frag
-This macro may be defined to relax a frag.  GAS will call this with the frag
-and the change in size of all previous frags; @code{md_relax_frag} should
-return the change in size of the frag.  @xref{Relaxation}.
+This macro may be defined to relax a frag.  GAS will call this with the
+segment, the frag, and the change in size of all previous frags;
+@code{md_relax_frag} should return the change in size of the frag.
+@xref{Relaxation}.
 
 @item TC_GENERIC_RELAX_TABLE
 @cindex TC_GENERIC_RELAX_TABLE


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]