CACAO
ScheduleLatePass.cpp
Go to the documentation of this file.
1 /* src/vm/jit/compiler2/ScheduleLatePass.cpp - ScheduleLatePass
2 
3  Copyright (C) 2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
34 
35 #include "toolbox/logging.hpp"
36 
37 #define DEBUG_NAME "compiler2/ScheduleLate"
38 
39 namespace cacao {
40 namespace jit {
41 namespace compiler2 {
42 
43 namespace {
44 
45 struct ScheduleLate : public std::unary_function<Instruction*,void> {
46  Instruction *I;
47  BeginInst *&block;
48  DominatorTree *DT;
49  // ctor
50  ScheduleLate(Instruction *I, BeginInst *&block, DominatorTree *DT) :
51  I(I), block(block), DT(DT) {}
52 
53  // function call operator
54  void operator()(Instruction* user) {
55  assert(user);
56  assert(user->get_BeginInst());
57  PHIInst *phi = user->to_PHIInst();
58  if (phi) {
59  int index = phi->get_operand_index(I);
60  assert(index >= 0);
61  BeginInst *pred = phi->get_BeginInst()->get_predecessor(index);
62  block = DT->find_nearest_common_dom(block,pred);
63  } else {
64  block = DT->find_nearest_common_dom(block,user->get_BeginInst());
65  }
66  }
67 };
68 
69 
70 struct ScheduleUser : public std::unary_function<Instruction*,void> {
71  ScheduleLatePass *parent;
72  ScheduleUser(ScheduleLatePass *parent) : parent(parent) {}
73  void operator()(Instruction* user) {
74  assert(user);
75  if (!user->get_BeginInst()) {
76  parent->schedule_late(user);
77  }
78  }
79 };
80 
81 } // end anonymous namespace
82 
84  // for each user
85  std::for_each(I->user_begin(), I->user_end(), ScheduleUser(this));
86  // for each dependent instruction
87  std::for_each(I->rdep_begin(), I->rdep_end(), ScheduleUser(this));
88  if (I->get_BeginInst())
89  return;
90  LOG1("schedule_late: " << I << nl);
91  BeginInst* block = NULL;
92  // for all users
93  std::for_each(I->user_begin(), I->user_end(), ScheduleLate(I,block,DT));
94  // for all dependant instructions
95  std::for_each(I->rdep_begin(), I->rdep_end(), ScheduleLate(I,block,DT));
96 
97  if (!block) {
98  // block is unused (e.g. dead code)
99  // XXX for the time being use early
100  block = early->get(I);
101  LOG("scheduled to " << block << nl);
102  // set the basic block
103  I->set_BeginInst(block);
104  return;
105  }
106  assert(block);
107  /**
108  * We want to schedule a block as late as possible, but
109  * outside of loop bodies (except for constants)
110  * In most cases constants can be encoded in the instructions.
111  * @todo register pressure
112  * @todo evaluate this!
113  */
114  BeginInst* latest = block;
115  BeginInst* best = latest;
116  if (I->get_opcode() != Instruction::CONSTInstID) {
117  BeginInst* earliest = DT->get_idominator(early->get(I));
118  LOG1("Sched.Late: " << latest << nl);
119  LOG1("Sched.Early: " << early->get(I) << nl);
120 
121  while (latest != earliest) {
122  Loop* loop_latest = LT->get_Loop(latest);
123  Loop* loop_best = LT->get_Loop(best);
124  // if the best is in an inner loop
125  LOG2( "Loop best: " << best << " " << LT->loop_nest(loop_best)
126  << " Loop latest: " << latest << " " << LT->loop_nest(loop_latest) << nl);
127  if ( LT->is_inner_loop(loop_best, loop_latest) ) {
128  best = latest;
129  }
130  latest = DT->get_idominator(latest);
131  }
132  }
133  LOG("scheduled to " << best << nl);
134  // set the basic block
135  I->set_BeginInst(best);
136 }
137 
139  DT = get_Pass<DominatorPass>();
140  LT = get_Pass<LoopPass>();
141  early = get_Pass<ScheduleEarlyPass>();
142  M = JD.get_Method();
143  for (Method::InstructionListTy::const_iterator i = M->begin(),
144  e = M->end() ; i != e ; ++i) {
145  if ((*i)->is_floating()) {
146  (*i)->set_BeginInst(NULL);
147  }
148  }
149  for (Method::InstructionListTy::const_iterator i = M->begin(),
150  e = M->end() ; i != e ; ++i) {
151  schedule_late(*i);
152  }
153  set_schedule(M);
154  // clear schedule
155  M->clear_schedule();
156  return true;
157 }
158 
162  PU.add_requires<LoopPass>();
163  return PU;
164 }
165 
166 // registrate Pass
167 static PassRegistry<ScheduleLatePass> X("ScheduleLatePass");
168 
169 } // end namespace compiler2
170 } // end namespace jit
171 } // end namespace cacao
172 
173 
174 /*
175  * These are local overrides for various environment variables in Emacs.
176  * Please do not remove this and leave it at the end of the file, where
177  * Emacs will automagically detect them.
178  * ---------------------------------------------------------------------
179  * Local variables:
180  * mode: c++
181  * indent-tabs-mode: t
182  * c-basic-offset: 4
183  * tab-width: 4
184  * End:
185  * vim:noexpandtab:sw=4:ts=4:
186  */
virtual bool run(JITData &JD)
Run the Pass.
std::size_t index
const_dep_iterator rdep_begin() const
bool is_inner_loop(LoopType *inner, LoopType *outer) const
Test if a loop is a strictly inner loop of another loop.
Definition: LoopBase.hpp:187
DominatorTree & DT
UserListTy::const_iterator user_begin() const
Definition: Value.hpp:72
This Instruction marks the start of a basic block.
#define LOG1(STMT)
Definition: logging.hpp:92
UserListTy::const_iterator user_end() const
Definition: Value.hpp:73
InstID get_opcode() const
return the opcode of the instruction
BeginInst *& block
NodeTy * get_idominator(NodeTy *a) const
Get the immediate dominator.
Stores the interdependencies of a pass.
Definition: PassUsage.hpp:55
Instruction super class.
Definition: Instruction.hpp:75
const_dep_iterator rdep_end() const
MIIterator i
#define LOG2(STMT)
Definition: logging.hpp:93
BeginInst * get(const Instruction *I) const
MIIterator e
#define LOG(STMT)
Analogous to DEBUG.
Definition: logging.hpp:91
Calculate the Loop Tree.
#define I(value)
Definition: codegen.c:279
virtual PassUsage & get_PassUsage(PassUsage &PU) const
Set the requirements for the pass.
virtual bool set_BeginInst(BeginInst *b)
virtual BeginInst * get_BeginInst() const
Get the corresponding BeginInst.
int loop_nest(LoopType *loop) const
TODO: cache?
Definition: LoopBase.hpp:205
LoopType * get_Loop(NodeType *BI) const
Get the inner most loop which contains BI or NULL if not contained in any loop.
Definition: LoopBase.hpp:148
static PassRegistry< BasicBlockSchedulingPass > X("BasicBlockSchedulingPass")
Nl nl
Definition: OStream.cpp:56
LoopTreeGraph * parent
void add_requires()
PassName is required.
Definition: PassUsage.hpp:78
Calculate the Dominator Tree.