patch for arm_gen_constant

Philip Blundell philb@gnu.org
Thu Jan 4 12:18:00 GMT 2001


>This is ok, except for the cost that it incurs when there is no likely 
>benefit to be gained.  Can we devise a check that will only run the code 
>when there is a likely benefit.  Perhaps wrapping the new code in 

Good idea.  Here's what I checked in.

p.

2001-01-04  Philip Blundell  <philb@gnu.org>

	* config/arm/arm.c (arm_gen_constant): Prefer to emit constants
	from bit 31 downwards, if this requires no more insns.
	(count_insns_for_constant): New helper function for above.

Index: arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.130
diff -u -p -u -r1.130 arm.c
--- arm.c	2000/12/30 16:34:00	1.130
+++ arm.c	2001/01/04 20:15:05
@@ -986,6 +986,33 @@ arm_split_constant (code, mode, val, tar
   return arm_gen_constant (code, mode, val, target, source, subtargets, 1);
 }
 
+static int
+count_insns_for_constant (HOST_WIDE_INT remainder, int i)
+{
+  HOST_WIDE_INT temp1;
+  int num_insns = 0;
+  do
+    {
+      int end;
+	  
+      if (i <= 0)
+	i += 32;
+      if (remainder & (3 << (i - 2)))
+	{
+	  end = i - 8;
+	  if (end < 0)
+	    end += 32;
+	  temp1 = remainder & ((0x0ff << end)
+				    | ((i < end) ? (0xff >> (32 - end)) : 0));
+	  remainder &= ~temp1;
+	  num_insns++;
+	  i -= 6;
+	}
+      i -= 2;
+    } while (remainder);
+  return num_insns;
+}
+
 /* As above, but extra parameter GENERATE which, if clear, suppresses
    RTL generation.  */
 static int
@@ -1465,10 +1492,37 @@ arm_gen_constant (code, mode, val, targe
 	    i -= 2;
 	  }
       }
+
+    /* So long as it won't require any more insns to do so, it's
+       desirable to emit a small constant (in bits 0...9) in the last
+       insn.  This way there is more chance that it can be combined with
+       a later addressing insn to form a pre-indexed load or store
+       operation.  Consider:
+
+	       *((volatile int *)0xe0000100) = 1;
+	       *((volatile int *)0xe0000110) = 2;
+
+       We want this to wind up as:
+
+		mov rA, #0xe0000000
+		mov rB, #1
+		str rB, [rA, #0x100]
+		mov rB, #2
+		str rB, [rA, #0x110]
+
+       rather than having to synthesize both large constants from scratch.
+
+       Therefore, we calculate how many insns would be required to emit
+       the constant starting from `best_start', and also starting from 
+       zero (ie with bit 31 first to be output).  If `best_start' doesn't 
+       yield a shorter sequence, we may as well use zero.  */
+    if (best_start != 0
+	&& ((((unsigned HOST_WIDE_INT) 1) << best_start) < remainder)
+	&& (count_insns_for_constant (remainder, 0) <= 
+	    count_insns_for_constant (remainder, best_start)))
+      best_start = 0;
 
-    /* Now start emitting the insns, starting with the one with the highest
-       bit set: we do this so that the smallest number will be emitted last;
-       this is more likely to be combinable with addressing insns.  */
+    /* Now start emitting the insns.  */
     i = best_start;
     do
       {




More information about the Gcc-patches mailing list