This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] do not always push DImode constants to memory before loadingthem to registers on ARM


This patch lets the ARM backend builds DImode constants with immediate 
values when worth it.  This makes for faster and often smaller code.

[date]  Nicolas Pitre <nico@cam.org

	* config/arm/arm.c (const_double_needs_minipool): New function
	determining if a CONST_DOUBLE should be pushed to the minipool.
	(note_invalid_constants): Use it.

Index: gcc/config/arm/arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.418
diff -u -r1.418 arm.c
--- gcc/config/arm/arm.c	11 Nov 2004 14:52:54 -0000	1.418
+++ gcc/config/arm/arm.c	17 Nov 2004 18:04:12 -0000
@@ -7253,6 +7268,46 @@
   minipool_fix_tail = fix;
 }
 
+/* Determine if a CONST_DOUBLE should be pushed to the minipool */
+static bool
+const_double_needs_minipool (rtx val)
+{
+  long parts[2];
+
+  /* thumb only knows to load a CONST_DOUBLE from memory at the moment */
+  if (TARGET_THUMB)
+    return true;
+
+  if (GET_MODE (val) == DFmode)
+    {
+      REAL_VALUE_TYPE r;
+      if (!TARGET_SOFT_FLOAT)
+	return true;
+      REAL_VALUE_FROM_CONST_DOUBLE (r, val);
+      REAL_VALUE_TO_TARGET_DOUBLE (r, parts);
+    }
+  else if (GET_MODE (val) != VOIDmode)
+    return true;
+  else
+    {
+      parts[0] = CONST_DOUBLE_LOW (val);
+      parts[1] = CONST_DOUBLE_HIGH (val);
+    }
+
+  /* Don't push anything to the minipool if a CONST_DOUBLE can be built
+     with a few ALU instructions directly.
+     Limit it to 3 insns.  Beyond that a load from memory is likely to be
+     faster and not larger than 4 words in size.
+     When optimizing for size it's less clear if a 3 ALU insns assignment
+     will always be smaller as minipool entries can be shared, so let's
+     make it up to 2 insns so it may never make for larger code. */
+  return (  arm_gen_constant (SET, SImode, NULL_RTX, parts[0],
+			      NULL_RTX, NULL_RTX, 0, 0)
+	  + arm_gen_constant (SET, SImode, NULL_RTX, parts[1],
+			      NULL_RTX, NULL_RTX, 0, 0)
+	  > (optimize_size ? 2 : 3));
+}
+
 /* Scan INSN and note any of its operands that need fixing.
    If DO_PUSHES is false we do not actually push any of the fixups
    needed.  The function returns TRUE is any fixups were needed/pushed.
@@ -7289,7 +7343,9 @@
 	{
 	  rtx op = recog_data.operand[opno];
 
-	  if (CONSTANT_P (op))
+	  if (CONSTANT_P (op)
+	      && (GET_CODE (op) != CONST_DOUBLE
+		  || const_double_needs_minipool (op)))
 	    {
 	      if (do_pushes)
 		push_minipool_fix (insn, address, recog_data.operand_loc[opno],


Nicolas


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