1 // Philipp Klaus Krause, philipp@informatik.uni-frankfurt.de, pkk@spth.de, 2010 - 2013
3 // (c) 2010 - 2013 Goethe-Universität Frankfurt
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License as published by the
7 // Free Software Foundation; either version 2, or (at your option) any
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 // An optimal, polynomial-time register allocator.
21 //#define DEBUG_RALLOC_DEC // Uncomment to get debug messages while doing register allocation on the tree decomposition.
22 //#define DEBUG_RALLOC_DEC_ASS // Uncomment to get debug messages about assignments while doing register allocation on the tree decomposition (much more verbose than the one above).
24 #include "SDCCralloc.hpp"
25 #include "SDCCsalloc.hpp"
31 float drym6502iCode (iCode
*ic
);
32 bool m6502_assignment_optimal
;
40 static void add_operand_conflicts_in_node(const cfg_node
&n
, I_t
&I
)
42 const iCode
*ic
= n
.ic
;
44 const operand
*result
= IC_RESULT(ic
);
45 const operand
*left
= IC_LEFT(ic
);
46 const operand
*right
= IC_RIGHT(ic
);
48 if(!result
|| !IS_SYMOP(result
))
51 // Todo: Identify more operations that code generation can always handle and exclude them (as done for the z80-like ports).
55 operand_map_t::const_iterator oir
, oir_end
, oirs
;
56 boost::tie(oir
, oir_end
) = n
.operands
.equal_range(OP_SYMBOL_CONST(result
)->key
);
60 operand_map_t::const_iterator oio
, oio_end
;
62 if(left
&& IS_SYMOP(left
))
63 for(boost::tie(oio
, oio_end
) = n
.operands
.equal_range(OP_SYMBOL_CONST(left
)->key
); oio
!= oio_end
; ++oio
)
64 for(oirs
= oir
; oirs
!= oir_end
; ++oirs
)
66 var_t rvar
= oirs
->second
;
67 var_t ovar
= oio
->second
;
68 if(I
[rvar
].byte
< I
[ovar
].byte
)
69 boost::add_edge(rvar
, ovar
, I
);
72 if(right
&& IS_SYMOP(right
))
73 for(boost::tie(oio
, oio_end
) = n
.operands
.equal_range(OP_SYMBOL_CONST(right
)->key
); oio
!= oio_end
; ++oio
)
74 for(oirs
= oir
; oirs
!= oir_end
; ++oirs
)
76 var_t rvar
= oirs
->second
;
77 var_t ovar
= oio
->second
;
78 if(I
[rvar
].byte
< I
[ovar
].byte
)
79 boost::add_edge(rvar
, ovar
, I
);
83 // Return true, iff the operand is placed (partially) in r.
85 static bool operand_in_reg(const operand
*o
, reg_t r
, const i_assignment_t
&ia
, unsigned short int i
, const G_t
&G
)
87 if(!o
|| !IS_SYMOP(o
))
90 if(r
>= port
->num_regs
)
93 operand_map_t::const_iterator oi
, oi_end
;
94 for(boost::tie(oi
, oi_end
) = G
[i
].operands
.equal_range(OP_SYMBOL_CONST(o
)->key
); oi
!= oi_end
; ++oi
)
95 if(oi
->second
== ia
.registers
[r
][1] || oi
->second
== ia
.registers
[r
][0])
101 // Return true, iff the operand is placed in a reg.
102 template <class G_t
, class I_t
>
103 static bool operand_is_ax(const operand
*o
, const assignment
&a
, unsigned short int i
, const G_t
&G
, const I_t
&I
)
105 if(!o
|| !IS_SYMOP(o
))
108 operand_map_t::const_iterator oi
, oi2
, oi_end
;
109 boost::tie(oi
, oi_end
) = G
[i
].operands
.equal_range(OP_SYMBOL_CONST(o
)->key
);
119 // Register combinations code generation cannot handle yet (AX, AY, XY, YA).
120 if(std::binary_search(a
.local
.begin(), a
.local
.end(), oi
->second
) && std::binary_search(a
.local
.begin(), a
.local
.end(), oi2
->second
))
122 const reg_t l
= a
.global
[oi
->second
];
123 const reg_t h
= a
.global
[oi2
->second
];
124 if(l
== REG_X
&& h
== REG_A
)
131 // Return true, iff the operand is placed in xa
132 template <class G_t
, class I_t
>
133 static bool XAinst_ok(const assignment
&a
, unsigned short int i
, const G_t
&G
, const I_t
&I
)
135 const iCode
*ic
= G
[i
].ic
;
137 // Instructions that can handle anything.
140 ic
->op
== UNARYMINUS
||
143 ic
->op
== FUNCTION
||
144 ic
->op
== ENDFUNCTION
||
154 ic
->op
== '<' || ic
->op
== '>' || ic
->op
== LE_OP
|| ic
->op
== GE_OP
||
155 ic
->op
== NE_OP
|| ic
->op
== EQ_OP
||
160 ic
->op
== BITWISEAND
||
166 ic
->op
== RIGHT_OP
||
167 //ic->op == '=' || /* both regular assignment and POINTER_SET safe */
168 //ic->op == GET_VALUE_AT_ADDRESS ||
169 ic
->op
== ADDRESS_OF
||
171 ic
->op
== DUMMY_READ_VOLATILE
)
174 if(ic
->op
== IFX
&& ic
->generated
)
177 const i_assignment_t
&ia
= a
.i_assignment
;
179 bool unused_A
= (ia
.registers
[REG_A
][1] < 0);
180 bool unused_Y
= (ia
.registers
[REG_Y
][1] < 0);
181 bool unused_X
= (ia
.registers
[REG_X
][1] < 0);
183 if(unused_X
&& unused_A
&& unused_Y
)
187 std::cout
<< "XAinst_ok: at (" << i
<< ", " << ic
->key
<< ")\nX = (" << ia
.registers
[REG_X
][0] << ", " << ia
.registers
[REG_X
][1] << "), A = (" << ia
.registers
[REG_A
][0] << ", " << ia
.registers
[REG_A
][1] << ")inst " << i
<< ", " << ic
->key
<< "\n";
190 const operand
*left
= IC_LEFT(ic
);
191 const operand
*right
= IC_RIGHT(ic
);
192 const operand
*result
= IC_RESULT(ic
);
194 bool result_in_A
= operand_in_reg(result
, REG_A
, ia
, i
, G
) && !(ic
->op
== '=' && POINTER_SET(ic
));
195 bool result_in_Y
= operand_in_reg(result
, REG_Y
, ia
, i
, G
) && !(ic
->op
== '=' && POINTER_SET(ic
));
196 bool result_in_X
= operand_in_reg(result
, REG_X
, ia
, i
, G
) && !(ic
->op
== '=' && POINTER_SET(ic
));
197 bool left_in_A
= operand_in_reg(result
, REG_A
, ia
, i
, G
);
198 bool left_in_X
= operand_in_reg(result
, REG_X
, ia
, i
, G
);
200 const cfg_dying_t
&dying
= G
[i
].dying
;
202 bool dying_A
= result_in_A
|| dying
.find(ia
.registers
[REG_A
][1]) != dying
.end() || dying
.find(ia
.registers
[REG_A
][0]) != dying
.end();
203 bool dying_Y
= result_in_Y
|| dying
.find(ia
.registers
[REG_Y
][1]) != dying
.end() || dying
.find(ia
.registers
[REG_Y
][0]) != dying
.end();
204 bool dying_X
= result_in_X
|| dying
.find(ia
.registers
[REG_X
][1]) != dying
.end() || dying
.find(ia
.registers
[REG_X
][0]) != dying
.end();
206 bool result_only_XA
= (result_in_X
|| unused_X
|| dying_X
) && (result_in_A
|| unused_A
|| dying_A
);
208 if(ic
->op
== JUMPTABLE
&& (unused_A
|| dying_A
))
211 if(ic
->op
== IPUSH
&& (unused_A
|| dying_A
|| left_in_A
|| operand_in_reg(left
, REG_Y
, ia
, i
, G
) || left_in_X
))
214 if(ic
->op
== RECEIVE
&& (!ic
->next
|| !(ic
->next
->op
== RECEIVE
) || !result_in_X
|| getSize(operandType(result
)) >= 2))
217 if(ic
->op
== SEND
&& ic
->next
&& ic
->next
->op
== SEND
&& ic
->next
->next
&& ic
->next
->next
->op
== SEND
)
220 if(ic
->op
== SEND
&& ic
->next
&& ic
->next
->op
== SEND
&& (unused_X
|| dying_X
))
223 if(ic
->op
== SEND
&& (unused_X
|| dying_X
) && (unused_A
|| dying_A
))
226 if(ic
->op
== SEND
&& ic
->next
&& (ic
->next
->op
== CALL
|| ic
->next
->op
== PCALL
)) // Might mess up A and X, but these would have been saved before if surviving, and will not be needed again before the call.
229 if((ic
->op
== CRITICAL
|| ic
->op
== ENDCRITICAL
) && (unused_A
|| dying_A
))
233 if ((ic
->op
== GET_VALUE_AT_ADDRESS
) && (unused_Y
|| dying_Y
))
235 if (POINTER_SET(ic
) && (unused_Y
|| dying_Y
))
243 template <class G_t
, class I_t
>
244 static bool AXinst_ok(const assignment
&a
, unsigned short int i
, const G_t
&G
, const I_t
&I
)
246 const iCode
*ic
= G
[i
].ic
;
248 const i_assignment_t
&ia
= a
.i_assignment
;
254 ic
->op
== FUNCTION
||
255 ic
->op
== ENDFUNCTION
||
261 ic
->op
== NE_OP
|| ic
->op
== EQ_OP
||
264 ic
->op
== BITWISEAND
||
268 /*ic->op == LEFT_OP ||
269 ic->op == RIGHT_OP ||*/
270 ic
->op
== GET_VALUE_AT_ADDRESS
||
272 ic
->op
== ADDRESS_OF
||
275 ic
->op
== DUMMY_READ_VOLATILE
||
276 ic
->op
== CRITICAL
||
277 ic
->op
== ENDCRITICAL
||
278 ic
->op
== ROT
&& IS_OP_LITERAL (IC_RIGHT (ic
)) && operandLitValueUll (IC_RIGHT (ic
)) * 2 == bitsForType (operandType (IC_LEFT (ic
))))
281 bool unused_A
= (ia
.registers
[REG_A
][1] < 0);
282 bool unused_X
= (ia
.registers
[REG_X
][1] < 0);
284 if (unused_A
|| unused_X
)
287 const operand
*left
= IC_LEFT(ic
);
288 const operand
*right
= IC_RIGHT(ic
);
289 const operand
*result
= IC_RESULT(ic
);
291 bool result_in_A
= operand_in_reg(result
, REG_A
, ia
, i
, G
) && !(ic
->op
== '=' && POINTER_SET(ic
));
292 bool result_in_X
= operand_in_reg(result
, REG_X
, ia
, i
, G
) && !(ic
->op
== '=' && POINTER_SET(ic
));
293 bool left_in_A
= operand_in_reg(result
, REG_A
, ia
, i
, G
);
294 bool left_in_X
= operand_in_reg(result
, REG_X
, ia
, i
, G
);
295 bool right_in_A
= operand_in_reg(result
, REG_A
, ia
, i
, G
);
296 bool right_in_X
= operand_in_reg(result
, REG_X
, ia
, i
, G
);
298 bool result_is_ax
= operand_is_ax (result
, a
, i
, G
, I
);
299 bool left_is_ax
= operand_is_ax (left
, a
, i
, G
, I
);
300 bool right_is_ax
= operand_is_ax (right
, a
, i
, G
, I
);
302 if (!result_is_ax
&& !left_is_ax
&& !right_is_ax
)
308 template <class G_t
, class I_t
>
309 static void set_surviving_regs(const assignment
&a
, unsigned short int i
, const G_t
&G
, const I_t
&I
)
313 bitVectClear(ic
->rMask
);
314 bitVectClear(ic
->rSurv
);
316 cfg_alive_t::const_iterator v
, v_end
;
317 for (v
= G
[i
].alive
.begin(), v_end
= G
[i
].alive
.end(); v
!= v_end
; ++v
)
321 ic
->rMask
= bitVectSetBit(ic
->rMask
, a
.global
[*v
]);
323 if(G
[i
].dying
.find(*v
) == G
[i
].dying
.end())
324 if(!((IC_RESULT(ic
) && !POINTER_SET(ic
)) && IS_SYMOP(IC_RESULT(ic
)) && OP_SYMBOL_CONST(IC_RESULT(ic
))->key
== I
[*v
].v
))
325 ic
->rSurv
= bitVectSetBit(ic
->rSurv
, a
.global
[*v
]);
329 template <class G_t
, class I_t
>
330 static void assign_operand_for_cost(operand
*o
, const assignment
&a
, unsigned short int i
, const G_t
&G
, const I_t
&I
)
332 if(!o
|| !IS_SYMOP(o
))
334 symbol
*sym
= OP_SYMBOL(o
);
335 operand_map_t::const_iterator oi
, oi_end
;
336 for(boost::tie(oi
, oi_end
) = G
[i
].operands
.equal_range(OP_SYMBOL_CONST(o
)->key
); oi
!= oi_end
; ++oi
)
338 var_t v
= oi
->second
;
341 sym
->regs
[I
[v
].byte
] = regsm6502
+ a
.global
[v
];
343 sym
->isspilt
= false;
344 sym
->nRegs
= I
[v
].size
;
350 sym
->nRegs
= I
[v
].size
;
351 for(int i
= 0; i
< I
[v
].size
; i
++)
357 template <class G_t
, class I_t
>
358 static void assign_operands_for_cost(const assignment
&a
, unsigned short int i
, const G_t
&G
, const I_t
&I
)
360 const iCode
*ic
= G
[i
].ic
;
362 assign_operand_for_cost(IC_LEFT(ic
), a
, i
, G
, I
);
363 assign_operand_for_cost(IC_RIGHT(ic
), a
, i
, G
, I
);
364 assign_operand_for_cost(IC_RESULT(ic
), a
, i
, G
, I
);
366 if(ic
->op
== SEND
&& ic
->builtinSEND
)
367 assign_operands_for_cost(a
, (unsigned short)*(adjacent_vertices(i
, G
).first
), G
, I
);
370 // Check that the operand is either fully in registers or fully in memory.
371 template <class G_t
, class I_t
>
372 static bool operand_sane(const operand
*o
, const assignment
&a
, unsigned short int i
, const G_t
&G
, const I_t
&I
)
374 if(!o
|| !IS_SYMOP(o
))
377 operand_map_t::const_iterator oi
, oi2
, oi_end
;
378 boost::tie(oi
, oi_end
) = G
[i
].operands
.equal_range(OP_SYMBOL_CONST(o
)->key
);
383 // Go to the second byte. If the operand is only a single byte, it cannot be
384 // an unsupported register combination or split between register and memory.
390 // Register combinations code generation cannot handle yet (AY, XY, YA).
391 if(std::binary_search(a
.local
.begin(), a
.local
.end(), oi
->second
) && std::binary_search(a
.local
.begin(), a
.local
.end(), oi2
->second
))
393 const reg_t l
= a
.global
[oi
->second
];
394 const reg_t h
= a
.global
[oi2
->second
];
395 // if(l == REG_A && h == REG_Y || l == REG_Y)
396 if(l
!= REG_A
|| h
!= REG_X
)
401 if(std::binary_search(a
.local
.begin(), a
.local
.end(), oi
->second
))
403 while(++oi
!= oi_end
)
404 if(!std::binary_search(a
.local
.begin(), a
.local
.end(), oi
->second
))
406 if (OP_SYMBOL_CONST (o
)->nRegs
> 2) // cannot handle register operand wider than 2 B yet.
411 while(++oi
!= oi_end
)
412 if(std::binary_search(a
.local
.begin(), a
.local
.end(), oi
->second
))
419 template <class G_t
, class I_t
>
420 static bool inst_sane(const assignment
&a
, unsigned short int i
, const G_t
&G
, const I_t
&I
)
422 const iCode
*ic
= G
[i
].ic
;
424 return(operand_sane(IC_RESULT(ic
), a
, i
, G
, I
) && operand_sane(IC_LEFT(ic
), a
, i
, G
, I
) && operand_sane(IC_RIGHT(ic
), a
, i
, G
, I
));
428 template <class G_t
, class I_t
>
429 static float instruction_cost(const assignment
&a
, unsigned short int i
, const G_t
&G
, const I_t
&I
)
434 wassert (TARGET_IS_MOS6502
|| TARGET_IS_MOS65C02
);
437 if(!inst_sane(a
, i
, G
, I
))
438 return(std::numeric_limits
<float>::infinity());
441 std::cout
<< "Calculating at cost at ic " << ic
->key
<< ", op " << ic
->op
<< " for: ";
450 std::cout
<< "Skipping, already generated.\n";
455 if(!XAinst_ok(a
, i
, G
, I
))
456 return(std::numeric_limits
<float>::infinity());
458 if(!AXinst_ok(a
, i
, G
, I
))
459 return(std::numeric_limits
<float>::infinity());
463 // Register assignment doesn't matter for these:
470 std::cout
<< "Skipping, indepent from assignment.\n";
482 case IPUSH_VALUE_AT_ADDRESS
:
504 case GET_VALUE_AT_ADDRESS
:
505 // case SET_VALUE_AT_ADDRESS:
513 case DUMMY_READ_VOLATILE
:
516 assign_operands_for_cost(a
, i
, G
, I
);
517 set_surviving_regs(a
, i
, G
, I
);
518 c
= drym6502iCode(ic
);
519 ic
->generated
= false;
521 std::cout
<< "Got cost " << c
<< "\n";
525 std::cout
<< "no cost for op " << ic
->op
<< "\n";
530 // For early removal of assignments that cannot be extended to valid assignments. This is just a dummy for now.
531 template <class G_t
, class I_t
>
532 static bool assignment_hopeless(const assignment
&a
, unsigned short int i
, const G_t
&G
, const I_t
&I
, const var_t lastvar
)
537 // Increase chance of finding good compatible assignments at join nodes.
539 static void get_best_local_assignment_biased(assignment
&a
, typename
boost::graph_traits
<T_t
>::vertex_descriptor t
, const T_t
&T
)
541 a
= *T
[t
].assignments
.begin();
544 std::set_union(T
[t
].alive
.begin(), T
[t
].alive
.end(), a
.local
.begin(), a
.local
.end(), std::inserter(newlocal
, newlocal
.end()));
548 // This is just a dummy for now, it probably isn't really needed for m6502 due to the low number of registers.
549 template <class G_t
, class I_t
>
550 static float rough_cost_estimate(const assignment
&a
, unsigned short int i
, const G_t
&G
, const I_t
&I
)
555 // Code for another ic is generated when generating this one. Mark the other as generated.
556 static void extra_ic_generated(iCode
*ic
)
558 if(ic
->op
== '>' || ic
->op
== '<' || ic
->op
== LE_OP
|| ic
->op
== GE_OP
|| ic
->op
== EQ_OP
|| ic
->op
== NE_OP
|| ic
->op
== '^' || ic
->op
== '|' || ic
->op
== BITWISEAND
)
561 if (ifx
= ifxForOp (IC_RESULT (ic
), ic
))
563 OP_SYMBOL (IC_RESULT (ic
))->for_newralloc
= false;
564 OP_SYMBOL (IC_RESULT (ic
))->regType
= REG_CND
;
565 ifx
->generated
= true;
568 if(ic
->op
== '-' && IS_VALOP (IC_RIGHT (ic
)) && operandLitValue (IC_RIGHT (ic
)) == 1 && getSize(operandType(IC_RESULT (ic
))) == 1 && !isOperandInFarSpace (IC_RESULT (ic
)) && isOperandEqual (IC_RESULT (ic
), IC_LEFT (ic
)))
571 if (ifx
= ifxForOp (IC_RESULT (ic
), ic
))
573 OP_SYMBOL (IC_RESULT (ic
))->for_newralloc
= false;
574 OP_SYMBOL (IC_RESULT (ic
))->regType
= REG_CND
;
575 ifx
->generated
= true;
580 template <class T_t
, class G_t
, class I_t
>
581 static bool tree_dec_ralloc(T_t
&T
, G_t
&G
, const I_t
&I
)
583 bool assignment_optimal
;
585 con2_t
I2(boost::num_vertices(I
));
586 for(unsigned int i
= 0; i
< boost::num_vertices(I
); i
++)
589 I2
[i
].byte
= I
[i
].byte
;
590 I2
[i
].size
= I
[i
].size
;
591 I2
[i
].name
= I
[i
].name
;
593 typename
boost::graph_traits
<I_t
>::edge_iterator e
, e_end
;
594 for(boost::tie(e
, e_end
) = boost::edges(I
); e
!= e_end
; ++e
)
595 add_edge(boost::source(*e
, I
), boost::target(*e
, I
), I2
);
598 assignment_optimal
= true;
599 tree_dec_ralloc_nodes(T
, find_root(T
), G
, I2
, ac
, &assignment_optimal
);
601 const assignment
&winner
= *(T
[find_root(T
)].assignments
.begin());
603 #ifdef DEBUG_RALLOC_DEC
604 std::cout
<< "Winner: ";
605 for(unsigned int i
= 0; i
< boost::num_vertices(I
); i
++)
607 std::cout
<< "(" << i
<< ", " << int(winner
.global
[i
]) << ") ";
610 std::cout
<< "Cost: " << winner
.s
<< "\n";
614 // Todo: Make this an assertion
615 if(winner
.global
.size() != boost::num_vertices(I
))
617 std::cerr
<< "ERROR: No Assignments at root\n";
621 for(unsigned int v
= 0; v
< boost::num_vertices(I
); v
++)
623 symbol
*sym
= (symbol
*)(hTabItemWithKey(liveRanges
, I
[v
].v
));
624 if(winner
.global
[v
] >= 0)
626 sym
->regs
[I
[v
].byte
] = regsm6502
+ winner
.global
[v
];
628 sym
->isspilt
= false;
629 sym
->nRegs
= I
[v
].size
;
633 for(int i
= 0; i
< I
[v
].size
; i
++)
636 sym
->nRegs
= I
[v
].size
;
637 wassert (sym
->nRegs
);
638 //m6502SpillThis(sym); Leave it to regFix, which can do some spillocation compaction. Todo: Use Thorup instead.
639 sym
->isspilt
= false;
643 for(unsigned int i
= 0; i
< boost::num_vertices(G
); i
++)
644 set_surviving_regs(winner
, i
, G
, I
);
646 return(!assignment_optimal
);
649 iCode
*m6502_ralloc2_cc(ebbIndex
*ebbi
)
651 eBBlock
**const ebbs
= ebbi
->bbOrder
;
652 const int count
= ebbi
->count
;
654 #ifdef DEBUG_RALLOC_DEC
655 std::cout
<< "Processing " << currFunc
->name
<< " from " << dstFileName
<< "\n"; std::cout
.flush();
658 cfg_t control_flow_graph
;
660 con_t conflict_graph
;
662 iCode
*ic
= create_cfg(control_flow_graph
, conflict_graph
, ebbi
);
664 if(optimize
.genconstprop
)
665 recomputeValinfos(ic
, ebbi
, "_2");
667 guessCounts(ic
, ebbi
);
669 if(options
.dump_graphs
)
670 dump_cfg(control_flow_graph
);
672 if(options
.dump_graphs
)
673 dump_con(conflict_graph
);
675 tree_dec_t tree_decomposition
;
677 get_nice_tree_decomposition(tree_decomposition
, control_flow_graph
);
679 alive_tree_dec(tree_decomposition
, control_flow_graph
);
681 good_re_root(tree_decomposition
);
682 nicify(tree_decomposition
);
683 alive_tree_dec(tree_decomposition
, control_flow_graph
);
685 if(options
.dump_graphs
)
686 dump_tree_decomposition(tree_decomposition
);
688 guessCounts (ic
, ebbi
);
690 m6502_assignment_optimal
= !tree_dec_ralloc(tree_decomposition
, control_flow_graph
, conflict_graph
);
692 m6502RegFix (ebbs
, count
);
694 /* do the overlaysegment stuff SDCCmem.c */
695 doOverlays (ebbs
, count
);