Improve Thumb-2 relaxation algorithm.

Paul Brook paul@codesourcery.com
Thu Aug 9 15:11:00 GMT 2007


The Thumb-2 assembly relaxation code contains logic to terminate relaxation if 
it looks like conflicting alignment requirements may cause an infinite loop.

However the code to calculate offsets during relaxation does not compensate 
for alignment directives, which leads to false positives if previous 
relaxations changes moved the target symbol.

The patch below borrows code from the mips assembler to help maintain proper 
alignment during relaxation.  The old behaviour isn't wrong per se, just 
generated unnecessarily large code.

Tested on arm-none-eabi.
Applied to cvs head.

Paul

2007-08-09  Paul Brook  <paul@codesourcery.com>

	gas/
	* config/tc-arm.c (relaxed_symbol_addr): Compensate for alignment.

	gas/testsuite/
	* gas/arm/relax_load_align.d: new test.
	* gas/arm/relax_load_align.s: new test.

Index: gas/testsuite/gas/arm/relax_load_align.d
===================================================================
--- gas/testsuite/gas/arm/relax_load_align.d	(revision 0)
+++ gas/testsuite/gas/arm/relax_load_align.d	(revision 0)
@@ -0,0 +1,9 @@
+# as: -march=armv6kt2
+# objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+0+000 <[^>]+> f510 707a 	adds.w	r0, r0, #1000	; 0x3e8
+0+004 <[^>]+> 4800      	ldr	r0, \[pc, #0\]	\(0+008 <[^>]+>\)
+0+006 <[^>]+> 4800      	ldr	r0, \[pc, #0\]	\(0+008 <[^>]+>\)
Index: gas/testsuite/gas/arm/relax_load_align.s
===================================================================
--- gas/testsuite/gas/arm/relax_load_align.s	(revision 0)
+++ gas/testsuite/gas/arm/relax_load_align.s	(revision 0)
@@ -0,0 +1,12 @@
+@ The relaxation algorithm used to not compensate for alignment statements.
+@ The early termination to avoid infinite looping would make the second load
+@ a wide instruction.
+	.text
+	.thumb
+	.syntax unified
+fn:
+	adds r0, r0, #1000
+	ldr r0, 1f
+	ldr r0, 1f
+.align 2
+1:
Index: gas/config/tc-arm.c
===================================================================
--- gas/config/tc-arm.c	(revision 178502)
+++ gas/config/tc-arm.c	(working copy)
@@ -16771,7 +16771,31 @@ relaxed_symbol_addr(fragS *fragp, long s
 
   if (stretch != 0
       && sym_frag->relax_marker != fragp->relax_marker)
-    addr += stretch;
+    {
+      fragS *f;
+
+      /* Adjust stretch for any alignment frag.  Note that if have
+	 been expanding the earlier code, the symbol may be
+	 defined in what appears to be an earlier frag.  FIXME:
+	 This doesn't handle the fr_subtype field, which specifies
+	 a maximum number of bytes to skip when doing an
+	 alignment.  */
+      for (f = fragp; f != NULL && f != sym_frag; f = f->fr_next)
+	{
+	  if (f->fr_type == rs_align || f->fr_type == rs_align_code)
+	    {
+	      if (stretch < 0)
+		stretch = - ((- stretch)
+			     & ~ ((1 << (int) f->fr_offset) - 1));
+	      else
+		stretch &= ~ ((1 << (int) f->fr_offset) - 1);
+	      if (stretch == 0)
+		break;
+	    }
+	}
+      if (f != NULL)
+	addr += stretch;
+    }
 
   return addr;
 }



More information about the Binutils mailing list