4 * @author Sebastian Hack
5 * @brief Machine dependent firm optimizations.
14 #include "irgraph_t.h"
21 #include "dbginfo_t.h"
22 #include "iropt_dbg.h"
33 /** The params got from the factopry in arch_dep_init(...). */
34 static const arch_dep_params_t *params = NULL;
36 /** The bit mask, which optimizations to apply. */
37 static arch_dep_opts_t opts;
39 void arch_dep_init(arch_dep_params_factory_t factory)
47 void arch_dep_set_opts(arch_dep_opts_t the_opts) {
51 ir_node *arch_dep_replace_mul_with_shifts(ir_node *irn)
54 ir_node *operand = NULL;
55 ir_node *left, *right;
56 ir_mode *mode = get_irn_mode(irn);
59 /* If the architecture dependent optimizations were not initialized
60 or this optimization was not enabled. */
61 if(params == NULL || (opts & arch_dep_mul_to_shift) == 0)
65 && get_irn_opcode(irn) == iro_Mul
66 && mode_is_int(mode)) {
68 left = get_binop_left(irn);
69 right = get_binop_right(irn);
71 /* Look, if one operand is a constant. */
72 if(get_irn_opcode(left) == iro_Const) {
73 tv = get_Const_tarval(left);
75 } else if(get_irn_opcode(right) == iro_Const) {
76 tv = get_Const_tarval(right);
81 int maximum_shifts = params->maximum_shifts;
82 int also_use_subs = params->also_use_subs;
83 int highest_shift_amount = params->highest_shift_amount;
85 char *bitstr = get_tarval_bitpattern(tv);
91 char compr[MAX_BITSTR];
95 int shift_with_sub[MAX_BITSTR] = { 0 };
96 int shift_without_sub[MAX_BITSTR] = { 0 };
97 int shift_with_sub_pos = 0;
98 int shift_without_sub_pos = 0;
102 int val = (int) get_tarval_long(tv);
103 fprintf(stderr, "Found mul with %d(%x) = ", val, val);
104 for(p = bitstr; *p != '\0'; p++)
110 for(p = bitstr; *p != '\0'; p++) {
114 case -1: // The last was 1 we are now at 0
115 case 1: // The last was 0 and we are now at 1
116 compr[compr_len++] = counter;
125 compr[compr_len++] = counter;
130 const char *prefix = "";
131 for(i = 0; i < compr_len; i++, prefix = ",")
132 fprintf(stderr, "%s%d", prefix, compr[i]);
137 // Go over all recorded one groups.
140 for(i = 1; i < compr_len; i = end_of_group + 2) {
141 int j, zeros_in_group, ones_in_group;
143 ones_in_group = compr[i];
146 // Scan for singular 0s in a sequence
147 for(j = i + 1; j < compr_len && compr[j] == 1; j += 2) {
149 ones_in_group += (j + 1 < compr_len ? compr[j + 1] : 0);
151 end_of_group = j - 1;
153 if(zeros_in_group >= ones_in_group - 1)
157 fprintf(stderr, " i:%d, eg:%d\n", i, end_of_group);
160 singleton = compr[i] == 1 && i == end_of_group;
161 for(j = i; j <= end_of_group; j += 2) {
162 int curr_ones = compr[j];
163 int biased_curr_bit = curr_bit + 1;
167 fprintf(stderr, " j:%d, ones:%d\n", j, curr_ones);
170 // If this ones group is a singleton group (it has no
171 // singleton zeros inside
173 shift_with_sub[shift_with_sub_pos++] = biased_curr_bit;
175 shift_with_sub[shift_with_sub_pos++] = -biased_curr_bit;
177 for(k = 0; k < curr_ones; k++)
178 shift_without_sub[shift_without_sub_pos++] = biased_curr_bit + k;
180 curr_bit += curr_ones;
181 biased_curr_bit = curr_bit + 1;
183 if(!singleton && j == end_of_group)
184 shift_with_sub[shift_with_sub_pos++] = biased_curr_bit;
185 else if(j != end_of_group)
186 shift_with_sub[shift_with_sub_pos++] = -biased_curr_bit;
188 curr_bit += compr[j + 1];
194 int *shifts = shift_with_sub;
195 int n = shift_with_sub_pos;
196 int highest_shift_wide = 0;
197 int highest_shift_seq = 0;
200 /* If we may not use subs, or we can achive the same with adds,
202 if(!also_use_subs || shift_with_sub_pos >= shift_without_sub_pos) {
203 shifts = shift_without_sub;
204 n = shift_without_sub_pos;
207 /* If the number of needed shifts exceeds the given maximum,
208 use the Mul and exit. */
209 if(n > maximum_shifts) {
211 fprintf(stderr, "Only allowed %d shifts, but %d are needed\n",
217 /* Compute the highest shift needed for both, the
218 sequential and wide representations. */
219 for(i = 0; i < n; i++) {
220 int curr = abs(shifts[i]);
221 int curr_seq = curr - last;
223 highest_shift_wide = curr > highest_shift_wide ? curr
224 : highest_shift_wide;
225 highest_shift_seq = curr_seq > highest_shift_seq ? curr_seq
231 /* If the highest shift amount is greater than the given limit,
233 if(highest_shift_seq > highest_shift_amount) {
235 fprintf(stderr, "Shift argument %d exceeds maximum %d\n",
236 highest_shift_seq, highest_shift_amount);
241 /* If we have subs, we cannot do sequential. */
242 if(1 /* also_use_subs */) {
244 ir_node *curr = NULL;
249 int curr_shift = shifts[i];
250 int sub = curr_shift < 0;
251 int amount = abs(curr_shift) - 1;
252 ir_node *aux = operand;
255 assert(amount >= 0 && "What is a negative shift??");
258 tarval *shift_amount = new_tarval_from_long(amount, mode_Iu);
259 ir_node *cnst = new_Const(mode_Iu, shift_amount);
260 aux = new_Shl(operand, cnst, mode);
265 curr = new_Sub(curr, aux, mode);
267 curr = new_Add(curr, aux, mode);
279 const char *prefix = "";
280 for(i = 0; i < n; i++) {
281 fprintf(stderr, "%s%d", prefix, shifts[i]);
284 fprintf(stderr, "\n");
300 static const arch_dep_params_t default_params = {
301 1, /* also use subs */
302 4, /* maximum shifts */
303 31 /* maximum shift amount */
306 const arch_dep_params_t *arch_dep_default_factory(void) {
307 return &default_params;