arm.c (const_double_needs_minipool): New function to determine if a CONST_DOUBLE...
authorNicolas Pitre <nico@cam.org>
Thu, 18 Nov 2004 20:28:04 +0000 (20:28 +0000)
committerNicolas Pitre <nico@gcc.gnu.org>
Thu, 18 Nov 2004 20:28:04 +0000 (20:28 +0000)
* config/arm/arm.c (const_double_needs_minipool): New function to
determine if a CONST_DOUBLE should be pushed to the minipool.
(note_invalid_constants): Use it.

From-SVN: r90881

gcc/ChangeLog
gcc/config/arm/arm.c

index 51b74ebcb7ac47b3908b4f06c6681596cd12abec..2cb26b672dd4d7979ccb4ee0ec3f7263a5f71377 100644 (file)
@@ -1,3 +1,9 @@
+2004-11-18  Nicolas Pitre <nico@cam.org>
+
+       * config/arm/arm.c (const_double_needs_minipool): New function to
+       determine if a CONST_DOUBLE should be pushed to the minipool.
+       (note_invalid_constants): Use it.
+
 2004-11-18  Paul Brook  <paul@codesourcery.com>
 
        * config/arm/arm.c (target_float_switch): New variable..
index 80f1f582a01c0e8ead7d87e7df29998243fe78fb..192fdb4f17b929b728979b068739184c661ded58 100644 (file)
@@ -7258,6 +7258,45 @@ push_minipool_fix (rtx insn, HOST_WIDE_INT address, rtx *loc,
   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 insns directly. On balance, the optimum is likely to be around
+     3 insns, except when there are no load delay slots where it should be 4.
+     When optimizing for size, a limit of 3 allows saving at least one word
+     except for cases where a single minipool entry could be shared more than
+     2 times which is rather unlikely to outweight the overall savings. */
+  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 || (tune_flags & FL_LDSCHED)) ? 3 : 4));
+}
+
 /* 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.
@@ -7294,7 +7333,9 @@ note_invalid_constants (rtx insn, HOST_WIDE_INT address, int do_pushes)
        {
          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],