beifg: Simplify the quite complicated way to divide a number by 2 in be_ifg_stat().
[libfirm] / ir / stat / const_stat.c
1 /*
2  * This file is part of libFirm.
3  * Copyright (C) 2012 University of Karlsruhe.
4  */
5
6 /**
7  * @file
8  * @brief   Statistic functions for constant counting.
9  * @author  Michael Beck
10  */
11 #include "config.h"
12
13 #include "firmstat_t.h"
14 #include "tv_t.h"
15 #include "util.h"
16
17 /**
18  * calculated the dual logarithm of |value|
19  */
20 static unsigned log2abs(long value)
21 {
22         unsigned res = 0;
23
24         if (value < 0)
25                 value = -value;
26
27         if (value > 0xFFFF) {
28                 res += 16;
29                 value >>= 16;
30         }
31         if (value > 0xFF) {
32                 res += 8;
33                 value >>= 8;
34         }
35         if (value > 0xF) {
36                 res += 4;
37                 value >>= 4;
38         }
39         if (value > 3) {
40                 res += 2;
41                 value >>= 2;
42         }
43         if (value > 1) {
44                 res += 1;
45         }
46
47         return res;
48 }
49
50 /**
51  * classify the value of a float tarval
52  */
53 static float_classify_t classify_float_value(ir_tarval *tv)
54 {
55         ir_mode *mode = get_tarval_mode(tv);
56
57         if (tv == get_mode_null(mode))
58                 return STAT_FC_0;
59         else if (tv == get_mode_one(mode))
60                 return STAT_FC_1;
61         else if (tarval_is_finite(tv) && tarval_zero_mantissa(tv)) {
62                 int exp = tarval_get_exponent(tv);
63
64                 if (! tarval_is_negative(tv)) {
65                         if (exp == 1)
66                                 return STAT_FC_2;
67                         else if (exp == -1)
68                                 return STAT_FC_0_5;
69                 }
70                 return STAT_FC_POWER_OF_TWO;
71         }
72         return STAT_FC_OTHER;
73 }
74
75 /* return a human readable name for an float classification */
76 const char *stat_fc_name(float_classify_t classification)
77 {
78         switch (classification) {
79         case STAT_FC_0:            return "0.0";
80         case STAT_FC_1:            return "1.0";
81         case STAT_FC_2:            return "2.0";
82         case STAT_FC_0_5:          return "0.5";
83         case STAT_FC_POWER_OF_TWO: return "2.0^x";
84         case STAT_FC_OTHER:        return "other";
85         default:                   return "<UNKNOWN>";
86         }
87 }
88
89 /* update info on Consts */
90 void stat_update_const(stat_info_t *status, ir_node *node, graph_entry_t *graph)
91 {
92         ir_mode   *mode = get_irn_mode(node);
93         ir_tarval *tv;
94         unsigned   bits;
95         (void) graph;
96
97         if (mode_is_int(mode)) {
98                 tv   = get_Const_tarval(node);
99
100                 /* FIXME: */
101                 if (! tarval_is_long(tv))
102                         return;
103
104                 bits = log2abs(get_tarval_long(tv));
105
106                 if (bits > ARRAY_SIZE(status->const_info.int_bits_count))
107                         bits = ARRAY_SIZE(status->const_info.int_bits_count);
108
109                 cnt_inc(&status->const_info.int_bits_count[bits]);
110         } else if (mode_is_float(mode)) {
111                 tv = get_Const_tarval(node);
112
113                 cnt_inc(&status->const_info.floats[classify_float_value(tv)]);
114         } else {
115                 /* something different */
116                 cnt_inc(&status->const_info.others);
117         }
118 }
119
120 /* clears the const statistics for a new snapshot */
121 void stat_const_clear(stat_info_t *status)
122 {
123         size_t i;
124
125         for (i = 0; i < ARRAY_SIZE(status->const_info.int_bits_count); ++i)
126                 cnt_clr(&status->const_info.int_bits_count[i]);
127
128         for (i = 0; i < ARRAY_SIZE(status->const_info.floats); ++i)
129                 cnt_clr(&status->const_info.floats[i]);
130
131         cnt_clr(&status->const_info.others);
132 }
133
134 /* initialize the Const statistic. */
135 void stat_init_const_cnt(stat_info_t *status)
136 {
137         (void) status;
138         /* currently nothing */
139 }