36 #define DEBUG_NAME "compiler2/LivetimeAnalysis"
51 return MBB->
back()->successor_begin();
55 get_successor_end(MachineBasicBlock* MBB) {
56 return MBB->back()->successor_end();
67 class InsertPhiOperands :
public std::unary_function<MachineBasicBlock*,void> {
70 struct PhiOperandInserter :
public std::unary_function<MachinePhiInst*,void> {
74 PhiOperandInserter(LiveInSetTy &
live, std::size_t
index)
75 : live(live), index(index) {}
77 void operator()(MachinePhiInst* phi) {
86 InsertPhiOperands(LiveInSetTy &
live, MachineBasicBlock *
current)
87 : live(live), current(current) {}
89 void operator()(MachineBasicBlock* MBB) {
90 std::for_each(MBB->phi_begin(), MBB->phi_end(),
91 PhiOperandInserter(
live,MBB->get_predecessor_index(
current)));
98 struct UnionLiveIn :
public std::unary_function<MachineBasicBlock*,void> {
104 : live_set(live_set), live_map(live_map) {}
106 void operator()(MachineBasicBlock* MBB) {
107 LiveInSetTy &other_set =
live_map[MBB];
108 live_set.insert(other_set.begin(), other_set.end());
113 inline LivetimeInterval& find_or_insert(LivetimeIntervalMapTy &
lti_map, MachineOperand*
op) {
114 LivetimeIntervalMapTy::iterator
i = lti_map.find(op);
115 if (i == lti_map.end()) {
116 LivetimeInterval lti(op);
117 i = lti_map.insert(std::make_pair(op,lti)).first;
125 class AddOperandInterval :
public std::unary_function<MachineOperand*,void> {
128 MachineBasicBlock *
BB;
131 AddOperandInterval(LivetimeIntervalMapTy <i_map, MachineBasicBlock *
BB)
132 : lti_map(lti_map), BB(BB) {}
133 void operator()(MachineOperand* op) {
135 if (op->needs_allocation()) {
136 LOG2(
"AddOperandInterval: op=" << *op <<
" BasicBlock: " << *
BB <<
nl);
146 class ProcessOutOperands :
public std::unary_function<MachineOperandDesc,void> {
148 LivetimeIntervalMapTy &
lti_map;
154 ProcessOutOperands(LivetimeIntervalMapTy <i_map, MIIterator i, MIIterator
e,
155 LiveInSetTy &
live) : lti_map(lti_map), i(i), e(e), live(live) {}
156 void operator()(MachineOperandDesc &op) {
157 if (op.op && op.op->needs_allocation()) {
158 LOG2(
"ProcessOutOperand: op=" << *(op.op) <<
" set form: " << **i <<
nl);
159 LivetimeInterval <i = find_or_insert(lti_map,op.op);
163 if ((*i)->is_move()) {
164 MachineOperand *op = (*i)->get(0).op;
165 if (op->needs_allocation()) {
166 LOG2(
"set hint " << op <<
" inst: " << *i <<
" lti: " << lti <<
nl);
176 class ProcessInOperands :
public std::unary_function<MachineOperandDesc,void> {
178 LivetimeIntervalMapTy &
lti_map;
179 MachineBasicBlock *
BB;
184 ProcessInOperands(LivetimeIntervalMapTy <i_map, MachineBasicBlock *
BB,
185 MIIterator i, LiveInSetTy &
live) : lti_map(lti_map), BB(BB), i(i), live(live) {}
186 void operator()(MachineOperandDesc &op) {
187 if (op.op && op.op->needs_allocation()) {
188 LOG2(
"ProcessInOperand: op=" << *(op.op) <<
" range form: "
189 <<
BB->front() <<
" to " << **i <<
nl);
190 LivetimeInterval <i = find_or_insert(lti_map,op.op);
201 struct RemovePhi :
public std::unary_function<MachinePhiInst*,void> {
204 RemovePhi(LiveInSetTy &
live) : live(live) {}
206 void operator()(MachinePhiInst* phi) {
207 LOG2(
"Remove phi result" << *phi->get_result().op <<
nl);
208 live.erase(phi->get_result().op);
215 class ProcessLoops :
public std::unary_function<MachineLoop*,void> {
217 struct ForEachLiveOperand :
public std::unary_function<MachineOperand*,void> {
218 LivetimeIntervalMapTy &
lti_map;
219 MachineBasicBlock *
BB;
222 ForEachLiveOperand(LivetimeIntervalMapTy <i_map, MachineBasicBlock *
BB,
MachineLoop *
loop)
223 : lti_map(lti_map), BB(BB), loop(loop) {}
224 void operator()(MachineOperand* op) {
225 assert(op->needs_allocation());
226 LOG2(
"ProcessLoops: operand " << op <<
" range from " <<
BB->mi_first()
227 <<
" to " <<
loop->get_exit()->mi_last() <<
nl );
232 LivetimeIntervalMapTy &
lti_map;
233 MachineBasicBlock *
BB;
237 ProcessLoops(LivetimeIntervalMapTy <i_map, MachineBasicBlock *
BB,
238 LiveInSetTy &
live) : lti_map(lti_map), BB(BB), live(live) {}
241 std::for_each(
live.begin(),
live.end(), ForEachLiveOperand(lti_map,
BB, loop));
252 LOG(
"LivetimeAnalysisPass::run()" <<
nl);
253 MIS = get_Pass<MachineInstructionSchedulingPass>();
262 LOG1(
"BasicBlock: " << *BB <<
nl);
264 LiveInSetTy &
live = liveIn[
BB];
267 std::for_each(get_successor_begin(BB), get_successor_end(BB), UnionLiveIn(live,liveIn));
270 std::for_each(get_successor_begin(BB), get_successor_end(BB), InsertPhiOperands(live,BB));
273 std::for_each(live.begin(),live.end(),AddOperandInterval(lti_map,BB));
278 if ((*i)->is_phi())
continue;
280 LOG2(
"MInst: " << **i <<
nl);
285 std::for_each((*i)->begin(),(*i)->end(), ProcessInOperands(lti_map, BB, BB->
convert(i),
live));
288 std::for_each((*i)->dummy_begin(),(*i)->dummy_end(), ProcessInOperands(lti_map, BB, BB->
convert(i),
live));
295 if (MLT->is_loop_header(BB)) {
297 std::for_each (loops.first, loops.second, ProcessLoops(lti_map, BB, live));
300 LOG1(
"LiveIn " << *BB <<
": ");
304 if (option::print_intervals) {
305 OStream fout(fopen(
"LiveIntervalTable.csv",
"w"));
315 struct PrintLivetimeState :
public std::unary_function<LivetimeIntervalMapTy::value_type,void> {
318 PrintLivetimeState(OStream &
OS, MIIterator
pos) : OS(OS), pos(pos) {}
319 void operator()(LivetimeIntervalMapTy::value_type lti) {
320 switch (lti.second.get_State(
pos)){
323 bool use = lti.second.is_use_at(
pos);
324 bool def = lti.second.is_def_at(
pos);
343 OS <<
"BasicBlock;Instruction;";
344 for (LivetimeIntervalMapTy::const_iterator i = lti_map.begin(),
345 e = lti_map.end(); i !=
e ; ++
i) {
354 OS << *BB <<
";" << **pos <<
";";
355 std::for_each(lti_map.begin(),lti_map.end(),PrintLivetimeState(OS,pos));
359 OS << *BB <<
";" << **i <<
";";
360 std::for_each(lti_map.begin(),lti_map.end(),PrintLivetimeState(OS,pos));
366 OS << *BB <<
";" << **pos <<
";";
367 std::for_each(lti_map.begin(),lti_map.end(),PrintLivetimeState(OS,pos));
376 for (LivetimeIntervalMapTy::const_iterator i = lti_map.begin(),
377 e = lti_map.end(); i !=
e ; ++
i) {
382 if ( old > (
signed)i->first) {
383 err() <<
"use not ordered " << old <<
" > " << i->first <<
nl;
391 if ( old > (
signed)i->first) {
392 err() <<
"def not ordered " << old <<
" > " << i->first <<
nl;
virtual void initialize()
Initialize the Pass.
const_phi_iterator phi_end() const
returns an const iterator to the phi instructions
OStream & print(OStream &OS) const
reverse_iterator rbegin()
returns an reverse_iterator to the beginning
std::reverse_iterator< const_iterator > const_reverse_iterator
reverse_iterator rend()
returns an reverse_iterator to the end
UseListTy::const_iterator const_use_iterator
alloc::map< MachineBasicBlock *, LiveInSetTy >::type LiveInMapTy
MIIterator mi_last()
returns an MIIterator to the last element (included)
PhiListTy::const_iterator const_phi_iterator
A basic block of (scheduled) machine instructions.
OStream & print_container(OStream &OS, _ForwardIterator i, const _ForwardIterator &e)
MachineInstructionSchedulingPass TODO: more info.
iterator end()
returns an iterator to the end
MIIterator mi_first()
returns an MIIterator to the first element
const_use_iterator use_begin() const
iterator begin()
returns an iterator to the beginning
LoopBase< MachineBasicBlock > MachineLoop
iterator end()
returns an iterator to the end
alloc::map< MachineOperand *, LivetimeInterval, MachineOperandComp >::type LivetimeIntervalMapTy
const_phi_iterator phi_begin() const
returns an const iterator to the phi instructions
MachineBasicBlock * current
const_reference back() const
access the last element
iterator begin()
returns an iterator to the beginning
Container::reverse_iterator reverse_iterator
virtual bool run(JITData &JD)
Run the Pass.
Stores the interdependencies of a pass.
Simple stream class for formatted output.
virtual bool verify() const
Verify the Result.
const_def_iterator def_begin() const
This file contains the command line option parsing library.
#define LOG(STMT)
Analogous to DEBUG.
LivetimeIntervalMapTy & lti_map
MIIterator convert(iterator pos)
get a MIIterator form a iterator
Operands that can be directly used by the machine (register, memory, stackslot)
alloc::set< MachineOperand * >::type LiveInSetTy
reverse_iterator rbegin()
returns an reverse_iterator to the beginning
const_use_iterator use_end() const
virtual PassUsage & get_PassUsage(PassUsage &PA) const
Set the requirements for the pass.
const_def_iterator def_end() const
std::pair< const_loop_iterator, const_loop_iterator > ConstLoopIteratorPair
reverse_iterator rend()
returns an reverse_iterator to the end
successor_list::iterator successor_iterator
LivetimeIntervalMapTy lti_map
MachineInstructionSchedule * MIS
static PassRegistry< BasicBlockSchedulingPass > X("BasicBlockSchedulingPass")
OStream & dbg()
The default destination for logging messages.
void add_requires()
PassName is required.
DefListTy::const_iterator const_def_iterator