* predict.c (expensive_function_p): New.
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 25 Aug 2001 21:08:28 +0000 (21:08 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 25 Aug 2001 21:08:28 +0000 (21:08 +0000)
* rtl.h (expensive_function_p): Declare.
* i386.c (FAST_PROLOGUE_INSN_COUNT): New constant.
(use_fast_prologue_epilogue): New static variable.
(expand_prologue): Set it; emit short prologues if unset.
(expand_epilogue): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@45176 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/predict.c
gcc/rtl.h

index f3ad806..4b32717 100644 (file)
@@ -1,3 +1,12 @@
+Sat Aug 25 23:07:35 CEST 2001  Jan Hubicka  <jh@suse.cz>
+
+       * predict.c (expensive_function_p): New.
+       * rtl.h (expensive_function_p): Declare.
+       * i386.c (FAST_PROLOGUE_INSN_COUNT): New constant.
+       (use_fast_prologue_epilogue): New static variable.
+       (expand_prologue): Set it; emit short prologues if unset.
+       (expand_epilogue): Likewise.
+
 2001-08-22  Geoffrey Keating  <geoffk@redhat.com>
 
        * config.gcc: Add stormy16-*-elf case.
index 51d32f6..23612b6 100644 (file)
@@ -319,6 +319,14 @@ const int x86_accumulate_outgoing_args = m_ATHLON | m_PENT4 | m_PPRO;
 const int x86_prologue_using_move = m_ATHLON | m_PENT4 | m_PPRO;
 const int x86_epilogue_using_move = m_ATHLON | m_PENT4 | m_PPRO;
 
+/* In case the avreage insn count for single function invocation is
+   lower than this constant, emit fast (but longer) prologue and
+   epilogue code.  */
+#define FAST_PROLOGUE_INSN_COUNT 30
+/* Set by prologue expander and used by epilogue expander to determine
+   the style used.  */
+static int use_fast_prologue_epilogue;
+
 #define AT_BP(mode) (gen_rtx_MEM ((mode), hard_frame_pointer_rtx))
 
 const char * const hi_reg_name[] = HI_REGISTER_NAMES;
@@ -2653,9 +2661,15 @@ ix86_expand_prologue ()
                                  || current_function_uses_const_pool)
                      && !TARGET_64BIT);
   struct ix86_frame frame;
-  int use_mov = (TARGET_PROLOGUE_USING_MOVE && !optimize_size);
+  int use_mov = 0;
   HOST_WIDE_INT allocate;
 
+  if (TARGET_PROLOGUE_USING_MOVE && !optimize_size)
+    {
+      use_fast_prologue_epilogue
+        = !expensive_function_p (FAST_PROLOGUE_INSN_COUNT);
+      use_mov = use_fast_prologue_epilogue;
+    }
   ix86_compute_frame_layout (&frame);
 
   /* Note: AT&T enter does NOT have reversed args.  Enter is probably
@@ -2794,10 +2808,11 @@ ix86_expand_epilogue (style)
      tuning in future.  */
   if ((!sp_valid && frame.nregs <= 1)
       || (TARGET_EPILOGUE_USING_MOVE && !optimize_size
+         && use_fast_prologue_epilogue
          && (frame.nregs > 1 || frame.to_allocate))
       || (frame_pointer_needed && !frame.nregs && frame.to_allocate)
       || (frame_pointer_needed && TARGET_USE_LEAVE && !optimize_size
-         && frame.nregs == 1)
+         && use_fast_prologue_epilogue && frame.nregs == 1)
       || style == 2)
     {
       /* Restore registers.  We can use ebp or esp to address the memory
@@ -2844,7 +2859,7 @@ ix86_expand_epilogue (style)
                    GEN_INT (frame.to_allocate
                             + frame.nregs * UNITS_PER_WORD)));
       /* If not an i386, mov & pop is faster than "leave".  */
-      else if (TARGET_USE_LEAVE || optimize_size)
+      else if (TARGET_USE_LEAVE || optimize_size || !use_fast_prologue_epilogue)
        emit_insn (TARGET_64BIT ? gen_leave_rex64 () : gen_leave ());
       else
        {
index f7e8b6d..70460ab 100644 (file)
@@ -782,6 +782,51 @@ counts_to_freqs ()
     }
 }
 
+/* Return true if function is likely to be expensive, so there is no point
+   to optimizer performance of prologue, epilogue or do inlining at the
+   expense of code size growth.  THRESHOLD is the limit of number
+   of isntructions function can execute at average to be still considered
+   not expensive.  */
+bool
+expensive_function_p (threshold)
+       int threshold;
+{
+  unsigned int sum = 0;
+  int i;
+  int limit;
+
+  /* We can not compute accurately for large thresholds due to scaled
+     frequencies.  */
+  if (threshold > BB_FREQ_MAX)
+    abort ();
+
+  /* Frequencies are out of range.  This eighter means that function contains
+     internal loop executing more than BB_FREQ_MAX times or profile feedback
+     is available and function has not been executed at all.  */
+  if (ENTRY_BLOCK_PTR->frequency == 0)
+    return true;
+    
+  /* Maximally BB_FREQ_MAX^2 so overflow won't happen.  */
+  limit = ENTRY_BLOCK_PTR->frequency * threshold;
+  for (i = 0; i < n_basic_blocks; i++)
+    {
+      basic_block bb = BASIC_BLOCK (i);
+      rtx insn;
+
+      for (insn = bb->head; insn != NEXT_INSN (bb->end);
+          insn = NEXT_INSN (insn))
+       {
+         if (active_insn_p (insn))
+           {
+             sum += bb->frequency;
+             if (sum > limit)
+               return true;
+           }
+       }
+    }
+  return false;
+}
+
 /* Estimate basic blocks frequency by given branch probabilities.  */
 static void
 estimate_bb_frequencies (loops)
index 819bf51..3a0a019 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2028,4 +2028,5 @@ extern void if_convert                    PARAMS ((int));
 
 /* In predict.c */
 extern void invert_br_probabilities    PARAMS ((rtx));
+extern bool expensive_function_p       PARAMS ((int));
 #endif /* ! GCC_RTL_H */