]> gcc.gnu.org Git - gcc.git/commitdiff
expr.c (compress_float_constant): New.
authorRichard Henderson <rth@redhat.com>
Sun, 12 May 2002 17:09:24 +0000 (10:09 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Sun, 12 May 2002 17:09:24 +0000 (10:09 -0700)
        * expr.c (compress_float_constant): New.
        (emit_move_insn): Use it.
        (float_extend_from_mem): New.
        (init_expr_once): Initialize it.
        * real.c (exact_real_truncate): New.

        * config/i386/i386.h (CONST_COSTS): Assume CONST_DOUBLE gets
        dropped into memory; penalize for size.
        (RTX_COSTS): FLOAT_EXTEND is free.
        * config/i386/i386.md (extendsfdf2, extendsfxf2, extendsftf2,
        extenddfxf2, extenddftf2): Accept constants and drop them to memory.

From-SVN: r53401

gcc/ChangeLog
gcc/config/i386/i386.h
gcc/config/i386/i386.md
gcc/expr.c
gcc/real.c

index 627ed8ecd52b5c1111a68af9d5dcc6a47a850c83..235d652c0cc5997cf73b830b5e756ddbf54e9f91 100644 (file)
@@ -1,3 +1,17 @@
+2002-05-12  Richard Henderson  <rth@redhat.com>
+
+       * expr.c (compress_float_constant): New.
+       (emit_move_insn): Use it.
+       (float_extend_from_mem): New.
+       (init_expr_once): Initialize it.
+       * real.c (exact_real_truncate): New.
+
+       * config/i386/i386.h (CONST_COSTS): Assume CONST_DOUBLE gets
+       dropped into memory; penalize for size.
+       (RTX_COSTS): FLOAT_EXTEND is free.
+       * config/i386/i386.md (extendsfdf2, extendsfxf2, extendsftf2,
+       extenddfxf2, extenddftf2): Accept constants and drop them to memory.
+
 2002-05-12  Richard Henderson  <rth@redhat.com>
 
        * profile.h (profile_info): Add missing extern to declaration.
index 5bfa582e9a516a8538602d40476f32e21b1a542b..680605b9955df922c089174b67686b750e141fdd 100644 (file)
@@ -2595,16 +2595,21 @@ do {                                                    \
     return flag_pic && SYMBOLIC_CONST (RTX) ? 1 : 0;           \
                                                                \
   case CONST_DOUBLE:                                           \
-    {                                                          \
-      int code;                                                        \
-      if (GET_MODE (RTX) == VOIDmode)                          \
-       return 0;                                               \
-                                                               \
-      code = standard_80387_constant_p (RTX);                  \
-      return code == 1 ? 1 :                                   \
-            code == 2 ? 2 :                                    \
-                        3;                                     \
-    }
+    if (GET_MODE (RTX) == VOIDmode)                            \
+      return 0;                                                        \
+    switch (standard_80387_constant_p (RTX))                   \
+      {                                                                \
+      case 1: /* 0.0 */                                                \
+       return 1;                                               \
+      case 2: /* 1.0 */                                                \
+       return 2;                                               \
+      default:                                                 \
+       /* Start with (MEM (SYMBOL_REF)), since that's where    \
+          it'll probably end up.  Add a penalty for size.  */  \
+       return (COSTS_N_INSNS (1) + (flag_pic != 0)             \
+               + (GET_MODE (RTX) == SFmode ? 0                 \
+                  : GET_MODE (RTX) == DFmode ? 1 : 2));        \
+      }
 
 /* Delete the definition here when TOPLEVEL_COSTS_N_INSNS gets added to cse.c */
 #define TOPLEVEL_COSTS_N_INSNS(N) \
@@ -2766,6 +2771,9 @@ do {                                                      \
       TOPLEVEL_COSTS_N_INSNS (ix86_cost->add * 2);                     \
     TOPLEVEL_COSTS_N_INSNS (ix86_cost->add);                           \
                                                                        \
+  case FLOAT_EXTEND:                                                   \
+    TOPLEVEL_COSTS_N_INSNS (0);                                                \
+                                                                       \
   egress_rtx_costs:                                                    \
     break;
 
index 54e1305e8ecbf79be7425659dfd84d4276f48114..11ab6f421776a972a953ee6fda110d9debf20508 100644 (file)
 
 (define_expand "extendsfdf2"
   [(set (match_operand:DF 0 "nonimmediate_operand" "")
-        (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "")))]
+        (float_extend:DF (match_operand:SF 1 "general_operand" "")))]
   "TARGET_80387 || TARGET_SSE2"
 {
+  /* ??? Needed for compress_float_constant since all fp constants
+     are LEGITIMATE_CONSTANT_P.  */
+  if (GET_CODE (operands[1]) == CONST_DOUBLE)
+    operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
     operands[1] = force_reg (SFmode, operands[1]);
 })
 
 (define_expand "extendsfxf2"
   [(set (match_operand:XF 0 "nonimmediate_operand" "")
-        (float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "")))]
+        (float_extend:XF (match_operand:SF 1 "general_operand" "")))]
   "!TARGET_64BIT && TARGET_80387"
 {
+  /* ??? Needed for compress_float_constant since all fp constants
+     are LEGITIMATE_CONSTANT_P.  */
+  if (GET_CODE (operands[1]) == CONST_DOUBLE)
+    operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
     operands[1] = force_reg (SFmode, operands[1]);
 })
 
 (define_expand "extendsftf2"
   [(set (match_operand:TF 0 "nonimmediate_operand" "")
-        (float_extend:TF (match_operand:SF 1 "nonimmediate_operand" "")))]
+        (float_extend:TF (match_operand:SF 1 "general_operand" "")))]
   "TARGET_80387"
 {
+  /* ??? Needed for compress_float_constant since all fp constants
+     are LEGITIMATE_CONSTANT_P.  */
+  if (GET_CODE (operands[1]) == CONST_DOUBLE)
+    operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
     operands[1] = force_reg (SFmode, operands[1]);
 })
 
 (define_expand "extenddfxf2"
   [(set (match_operand:XF 0 "nonimmediate_operand" "")
-        (float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "")))]
+        (float_extend:XF (match_operand:DF 1 "general_operand" "")))]
   "!TARGET_64BIT && TARGET_80387"
 {
+  /* ??? Needed for compress_float_constant since all fp constants
+     are LEGITIMATE_CONSTANT_P.  */
+  if (GET_CODE (operands[1]) == CONST_DOUBLE)
+    operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
     operands[1] = force_reg (DFmode, operands[1]);
 })
 
 (define_expand "extenddftf2"
   [(set (match_operand:TF 0 "nonimmediate_operand" "")
-        (float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "")))]
+        (float_extend:TF (match_operand:DF 1 "general_operand" "")))]
   "TARGET_80387"
 {
+  /* ??? Needed for compress_float_constant since all fp constants
+     are LEGITIMATE_CONSTANT_P.  */
+  if (GET_CODE (operands[1]) == CONST_DOUBLE)
+    operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
     operands[1] = force_reg (DFmode, operands[1]);
 })
index 84443e014e6e115afcaab3b54d36656d6b077128..1a8d051832380487ebc2ccce7027d4aef9fcdac7 100644 (file)
@@ -134,6 +134,7 @@ static void store_by_pieces_1       PARAMS ((struct store_by_pieces *,
 static void store_by_pieces_2  PARAMS ((rtx (*) (rtx, ...),
                                         enum machine_mode,
                                         struct store_by_pieces *));
+static rtx compress_float_constant PARAMS ((rtx, rtx));
 static rtx get_subtarget       PARAMS ((rtx));
 static int is_zeros_p          PARAMS ((tree));
 static int mostly_zeros_p      PARAMS ((tree));
@@ -167,6 +168,10 @@ static void do_tablejump PARAMS ((rtx, enum machine_mode, rtx, rtx, rtx));
 static char direct_load[NUM_MACHINE_MODES];
 static char direct_store[NUM_MACHINE_MODES];
 
+/* Record for each mode whether we can float-extend from memory.  */
+
+static bool float_extend_from_mem[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
+
 /* If a memory-to-memory move would take MOVE_RATIO or more simple
    move-instruction sequences, we will do a movstr or libcall instead.  */
 
@@ -265,6 +270,28 @@ init_expr_once ()
          }
     }
 
+  mem = gen_rtx_MEM (VOIDmode, gen_rtx_raw_REG (Pmode, 10000));
+
+  for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
+       mode = GET_MODE_WIDER_MODE (mode))
+    {
+      enum machine_mode srcmode;
+      for (srcmode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); srcmode != mode;
+           srcmode = GET_MODE_WIDER_MODE (srcmode))
+       {
+         enum insn_code ic;
+
+         ic = can_extend_p (mode, srcmode, 0);
+         if (ic == CODE_FOR_nothing)
+           continue;
+
+         PUT_MODE (mem, srcmode);
+         
+         if ((*insn_data[ic].operand[1].predicate) (mem, srcmode))
+           float_extend_from_mem[mode][srcmode] = true;
+       }
+    }
+
   end_sequence ();
 }
 
@@ -2771,10 +2798,18 @@ emit_move_insn (x, y)
   /* Never force constant_p_rtx to memory.  */
   if (GET_CODE (y) == CONSTANT_P_RTX)
     ;
-  else if (CONSTANT_P (y) && ! LEGITIMATE_CONSTANT_P (y))
+  else if (CONSTANT_P (y))
     {
-      y_cst = y;
-      y = force_const_mem (mode, y);
+      if (optimize
+         && FLOAT_MODE_P (GET_MODE (x))
+         && (last_insn = compress_float_constant (x, y)))
+       return last_insn;
+
+      if (!LEGITIMATE_CONSTANT_P (y))
+       {
+         y_cst = y;
+         y = force_const_mem (mode, y);
+       }
     }
 
   /* If X or Y are memory references, verify that their addresses are valid
@@ -3100,6 +3135,64 @@ emit_move_insn_1 (x, y)
   else
     abort ();
 }
+
+/* If Y is representable exactly in a narrower mode, and the target can
+   perform the extension directly from constant or memory, then emit the
+   move as an extension.  */
+
+static rtx
+compress_float_constant (x, y)
+     rtx x, y;
+{
+  enum machine_mode dstmode = GET_MODE (x);
+  enum machine_mode orig_srcmode = GET_MODE (y);
+  enum machine_mode srcmode;
+  REAL_VALUE_TYPE r;
+
+  REAL_VALUE_FROM_CONST_DOUBLE (r, y);
+
+  for (srcmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_srcmode));
+       srcmode != orig_srcmode;
+       srcmode = GET_MODE_WIDER_MODE (srcmode))
+    {
+      enum insn_code ic;
+      rtx trunc_y, last_insn;
+
+      /* Skip if the target can't extend this way.  */
+      ic = can_extend_p (dstmode, srcmode, 0);
+      if (ic == CODE_FOR_nothing)
+       continue;
+
+      /* Skip if the narrowed value isn't exact.  */
+      if (! exact_real_truncate (srcmode, &r))
+       continue;
+
+      trunc_y = CONST_DOUBLE_FROM_REAL_VALUE (r, srcmode);
+
+      if (LEGITIMATE_CONSTANT_P (trunc_y))
+       {
+         /* Skip if the target needs extra instructions to perform
+            the extension.  */
+         if (! (*insn_data[ic].operand[1].predicate) (trunc_y, srcmode))
+           continue;
+       }
+      else if (float_extend_from_mem[dstmode][srcmode])
+       trunc_y = validize_mem (force_const_mem (srcmode, trunc_y));
+      else
+       continue;
+
+      emit_unop_insn (ic, x, trunc_y, UNKNOWN);
+      last_insn = get_last_insn ();
+
+      if (GET_CODE (x) == REG)
+       REG_NOTES (last_insn)
+         = gen_rtx_EXPR_LIST (REG_EQUAL, y, REG_NOTES (last_insn));
+
+      return last_insn;
+    }
+
+  return NULL_RTX;
+}
 \f
 /* Pushing data onto the stack.  */
 
index 912986260765b65174225f88dc733891c19eec40..a4196981a1ba39df5f28783135e96e76aa2ad77a 100644 (file)
@@ -1066,6 +1066,22 @@ real_value_truncate (mode, arg)
   return (r);
 }
 
+/* Return true if ARG can be represented exactly in MODE.  */
+
+bool
+exact_real_truncate (mode, arg)
+     enum machine_mode mode;
+     REAL_VALUE_TYPE *arg;
+{
+  REAL_VALUE_TYPE trunc;
+
+  if (target_isnan (*arg))
+    return false;
+
+  trunc = real_value_truncate (mode, *arg);
+  return ereal_cmp (*arg, trunc) == 0;
+}
+
 /* Try to change R into its exact multiplicative inverse in machine mode
    MODE.  Return nonzero function value if successful.  */
 
This page took 2.199452 seconds and 5 git commands to generate.