1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19 
20 /**
21  * @file
22  * @brief   Statistic functions for constant counting.
23  * @author  Michael Beck
24  */
25 #include "config.h"
26 
27 #include "firmstat_t.h"
28 #include "tv_t.h"
29 #include "util.h"
30 
31 /**
32  * calculated the dual logarithm of |value|
33  */
log2abs(long value)34 static unsigned log2abs(long value)
35 {
36 	unsigned res = 0;
37 
38 	if (value < 0)
39 		value = -value;
40 
41 	if (value > 0xFFFF) {
42 		res += 16;
43 		value >>= 16;
44 	}
45 	if (value > 0xFF) {
46 		res += 8;
47 		value >>= 8;
48 	}
49 	if (value > 0xF) {
50 		res += 4;
51 		value >>= 4;
52 	}
53 	if (value > 3) {
54 		res += 2;
55 		value >>= 2;
56 	}
57 	if (value > 1) {
58 		res += 1;
59 	}
60 
61 	return res;
62 }
63 
64 /**
65  * classify the value of a float tarval
66  */
classify_float_value(ir_tarval * tv)67 static float_classify_t classify_float_value(ir_tarval *tv)
68 {
69 	ir_mode *mode = get_tarval_mode(tv);
70 
71 	if (tv == get_mode_null(mode))
72 		return STAT_FC_0;
73 	else if (tv == get_mode_one(mode))
74 		return STAT_FC_1;
75 	else if (tarval_is_finite(tv) && tarval_zero_mantissa(tv)) {
76 		int exp = tarval_get_exponent(tv);
77 
78 		if (! tarval_is_negative(tv)) {
79 			if (exp == 1)
80 				return STAT_FC_2;
81 			else if (exp == -1)
82 				return STAT_FC_0_5;
83 		}
84 		return STAT_FC_POWER_OF_TWO;
85 	}
86 	return STAT_FC_OTHER;
87 }
88 
89 /* return a human readable name for an float classification */
stat_fc_name(float_classify_t classification)90 const char *stat_fc_name(float_classify_t classification)
91 {
92 	switch (classification) {
93 	case STAT_FC_0:            return "0.0";
94 	case STAT_FC_1:            return "1.0";
95 	case STAT_FC_2:            return "2.0";
96 	case STAT_FC_0_5:          return "0.5";
97 	case STAT_FC_POWER_OF_TWO: return "2.0^x";
98 	case STAT_FC_OTHER:        return "other";
99 	default:                   return "<UNKNOWN>";
100 	}
101 }
102 
103 /* update info on Consts */
stat_update_const(stat_info_t * status,ir_node * node,graph_entry_t * graph)104 void stat_update_const(stat_info_t *status, ir_node *node, graph_entry_t *graph)
105 {
106 	ir_mode   *mode = get_irn_mode(node);
107 	ir_tarval *tv;
108 	unsigned   bits;
109 	(void) graph;
110 
111 	if (mode_is_int(mode)) {
112 		tv   = get_Const_tarval(node);
113 
114 		/* FIXME: */
115 		if (! tarval_is_long(tv))
116 			return;
117 
118 		bits = log2abs(get_tarval_long(tv));
119 
120 		if (bits > ARRAY_SIZE(status->const_info.int_bits_count))
121 			bits = ARRAY_SIZE(status->const_info.int_bits_count);
122 
123 		cnt_inc(&status->const_info.int_bits_count[bits]);
124 	} else if (mode_is_float(mode)) {
125 		tv = get_Const_tarval(node);
126 
127 		cnt_inc(&status->const_info.floats[classify_float_value(tv)]);
128 	} else {
129 		/* something different */
130 		cnt_inc(&status->const_info.others);
131 	}
132 }
133 
134 /* clears the const statistics for a new snapshot */
stat_const_clear(stat_info_t * status)135 void stat_const_clear(stat_info_t *status)
136 {
137 	size_t i;
138 
139 	for (i = 0; i < ARRAY_SIZE(status->const_info.int_bits_count); ++i)
140 		cnt_clr(&status->const_info.int_bits_count[i]);
141 
142 	for (i = 0; i < ARRAY_SIZE(status->const_info.floats); ++i)
143 		cnt_clr(&status->const_info.floats[i]);
144 
145 	cnt_clr(&status->const_info.others);
146 }
147 
148 /* initialize the Const statistic. */
stat_init_const_cnt(stat_info_t * status)149 void stat_init_const_cnt(stat_info_t *status)
150 {
151 	(void) status;
152 	/* currently nothing */
153 }
154