OpenASIP  2.0
Peel2BBLoops.cc
Go to the documentation of this file.
1 /**
2  * @file Peel2BBLoops.cc
3  *
4  * This optimizer optimizes some 2-bb loops into
5  * 1-BB loop be peeling out the 1st iteration which jumps into the middle
6  * of the jump. The resulting 1-BB loop can then be loop-scheduled.
7  *
8  * @author Heikki Kultala 2016 (heikki.kultala@tut.fi)
9  * @note rating: red
10  */
11 
12 #include "SimpleIfConverter.hh"
13 #include "Peel2BBLoops.hh"
14 #include "ProgramOperation.hh"
15 #include "MoveNode.hh"
16 #include "BasicBlock.hh"
17 #include "Instruction.hh"
18 #include "Procedure.hh"
19 #include "Program.hh"
20 #include "ControlFlowGraph.hh"
21 #include "Move.hh"
22 #include "CodeGenerator.hh"
24 #include "TerminalFUPort.hh"
25 #include "Operation.hh"
26 #include "MoveGuard.hh"
27 #include "Guard.hh"
28 #include "OperationPool.hh"
29 #include "MachineInfo.hh"
30 
32  InterPassData& data, const TTAMachine::Machine& targetMachine) :
34  codeGenerator_(new TTAProgram::CodeGenerator(targetMachine)),
35  irm_(NULL), mach_(targetMachine) {}
36 
38 
39  // entry/exit node or wrong number of succs/preds
40  if (!bbn.isNormalBB() || cfg.outDegree(bbn) != 2 ||
41  cfg.inDegree(bbn) != 2) {
42  return false;
43  }
44 
45  // find possible loop begin node and pre-loop node.
46  auto iEdges = cfg.inEdges(bbn);
47  BasicBlockNode *loopBegin = NULL;
48  BasicBlockNode* preLoop = NULL;
49  for (auto e: iEdges) {
50  if (e->isFallThroughEdge()) {
51  loopBegin = &cfg.tailNode(*e);
52  } else {
53  preLoop = &cfg.tailNode(*e);
54  }
55  }
56  if (loopBegin == NULL || preLoop == NULL) {
57  return false;
58  }
59 
60  auto oEdges = cfg.outEdges(bbn);
61  BasicBlockNode *afterLoop = NULL;
62  for (auto e: oEdges) {
63  if (e->isFallThroughEdge()) {
64  afterLoop = &cfg.headNode(*e);
65  } else { // jump to loop begin
66  if (&cfg.headNode(*e) != loopBegin) {
67  return false;
68  }
69  }
70  }
71 
72  if (afterLoop == NULL) {
73  return false;
74  }
75 
76  if (cfg.inDegree(*loopBegin) != 1 || cfg.outDegree(*loopBegin) != 1) {
77  return false;
78  }
79 
80  if (!cfg.outEdge(*loopBegin, 0).isFallThroughEdge() ||
81  cfg.inEdge(*loopBegin, 0).isFallThroughEdge()) {
82  return false;
83  }
84 
85  // incoming must not be fall-through.
86  if (cfg.outDegree(*preLoop) != 1) {
87  return false;
88  }
89 
90  return BBNodes(preLoop, loopBegin, &bbn, afterLoop);
91 }
92 
93 
94 
95 /**
96  * Handles a cfg.
97  *
98  * @param cfg cfg to be optimized.
99  */
100 void
102  ControlFlowGraph& cfg, const TTAMachine::Machine& targetMachine) {
103  if (codeGenerator_ == NULL) {
104  codeGenerator_ = new TTAProgram::CodeGenerator(targetMachine);
105  }
106 
108 
109  for (int i = 0; i < cfg.nodeCount(); i++) {
110 
111  // first find the block containing the main body(end) of the loop
112  BasicBlockNode& bbn = cfg.node(i);
113 
114  if (auto loopBlocks = testIf2BBLoop(cfg, bbn)) {
115  peel2BBLoop(cfg, loopBlocks);
116 
117  // performing this may change other basic blocks so lets start
118  // from beginning(may it?)
119  i = 0;
120  }
121  }
122 }
123 
125  performCodeMotion(bbns);
126  updateCFG(cfg, bbns);
127 }
128 
129 
131  // pre to loop-end needs to be converted from jump to fall-through,
132  // with correct predicate(which is got from the loop node, reversing it
133  cfg.disconnectNodes(*bbns.preLoop, *bbns.endLoop);
134  auto exitEdge = *cfg.connectingEdges(*bbns.endLoop, *bbns.postLoop).begin();
135  auto loopEdge = *cfg.connectingEdges(*bbns.endLoop, *bbns.beginLoop).begin();
136 
137  ControlFlowEdge* intoLoop = new ControlFlowEdge(
138  loopEdge->edgePredicate(),
140 
141  ControlFlowEdge* overLoop = new ControlFlowEdge(
142  exitEdge->edgePredicate(),
144 
145  cfg.moveOutEdge(*bbns.endLoop, *bbns.beginLoop, *loopEdge);
146  loopEdge->setBackEdge();
147  cfg.moveOutEdge(*bbns.endLoop, *bbns.beginLoop, *exitEdge);
148  cfg.connectNodes(*bbns.preLoop, *bbns.beginLoop, *intoLoop);
149  cfg.connectNodes(*bbns.preLoop, *bbns.postLoop, *overLoop);
150 
151  // old loop end bb
152  cfg.deleteNodeAndRefs(*bbns.endLoop);
153 }
154 
155 
157  // the nasty jump to middle of bb, removed because copying the code
159 
160  // then append the end of the loop into the pre-loop BB,
161  // and inverse the guard and update the jump destination the post-loop
162  appendBB(bbns.endLoop->basicBlock(),
163  bbns.preLoop->basicBlock(),
164  bbns.postLoop);
165 
166  // append end of loop to begin of the loop. no need to update jump.
167  appendBB(bbns.endLoop->basicBlock(),
168  bbns.beginLoop->basicBlock(),
169  nullptr);
170 }
171 
173  const TTAProgram::BasicBlock& src, TTAProgram::BasicBlock& dest, BasicBlockNode* newJumpDest) {
174 
175  std::map<ProgramOperationPtr,ProgramOperationPtr> poMapping;
176 
177  ProgramOperationPtr prevPO = nullptr;
178  for (int j = 0; j < src.instructionCount(); j++) {
179  const TTAProgram::Instruction& ins = src.instructionAtIndex(j);
181  dest.add(newIns);
182  for (int i = 0; i < ins.moveCount(); i++) {
183  const TTAProgram::Move& move = ins.move(i);
184  auto moveCopy = move.copy();
185  MoveNode* newMN = nullptr;
186 
187  if (moveCopy->source().isFUPort()) {
188  ProgramOperationPtr newPO =
190  static_cast<TTAProgram::TerminalFUPort&>(
191  moveCopy->source()),
192  poMapping);
193  if (newPO != NULL) {
194  prevPO = newPO;
195  newMN = new MoveNode(moveCopy);
196  newPO->addOutputNode(*newMN);
197  newMN->setSourceOperationPtr(newPO);
198  }
199  }
200  if (moveCopy->destination().isFUPort()) {
202  static_cast<TTAProgram::TerminalFUPort&>(
203  moveCopy->destination()),
204  poMapping);
205  if (newPO != NULL) {
206  prevPO = newPO;
207  if (newMN == nullptr)
208  newMN = new MoveNode(moveCopy);
209  newPO->addInputNode(*newMN);
210  newMN->addDestinationOperationPtr(newPO);
211  }
212  }
213 
214  // for jumps, need to update target and inverse guard.
215  if (moveCopy->isJump() && newJumpDest != nullptr) {
216  if (!moveCopy->isUnconditional()) {
217 
218  // if fake guard, first try to inverse the op that
219  // generated it, but if it fails negate the guard.
220  if (!(moveCopy->guard().guard().parentBus() == nullptr
221  && negateOp(prevPO))) {
222 
223  moveCopy->setGuard(
225  moveCopy->guard()));
226  }
227 
228  } else { // bz / bnz
229  // TODO: put these into a map?
230  std::map<std::string, std::string> branchNegations =
231  {{"BZ", "BNZ"}, {"BNZ", "BZ"},
232  {"BZ1", "BNZ1"}, {"BNZ1", "BZ1"},
233  {"BEQ", "BNE"}, {"BNE", "BEQ"},
234  {"BGT", "BLE"}, {"BLE", "BGT"},
235  {"BGTU", "BLEU"}, {"BLEU", "BGTU"},
236  {"BLT", "BGE"}, {"BGE", "BLT"},
237  {"BLTU", "BGEU"}, {"BGEU", "BLTU"}
238  };
239  auto *dest = dynamic_cast<TTAProgram::TerminalFUPort*>(
240  &moveCopy->destination());
241  assert(dest);
242  TCEString jumpName = dest->hintOperation().name();
243  if (branchNegations.count(jumpName) > 0) {
244  OperationPool pool;
245  std::string negatedOpName = branchNegations[jumpName];
246  const Operation& negatedOp =
247  pool.operation(negatedOpName.c_str());
248  newMN->destinationOperation().setOperation(negatedOp);
249  } else {
250  assert (false &&
251  "Cannot neg unknown conditional jump instr");
252  }
253  }
254  moveCopy->setSource(
256  newJumpDest->basicBlock()));
257  }
258  newIns->addMove(moveCopy);
259  }
260  }
261 }
262 
263 /**
264  * Negates operation into operation which generates opposite
265  * predicate value.
266  */
268 
269  // TODO: Shouldn't these be CAPSed? does this really work?
270  std::map<TCEString, TCEString> negateOps;
271  negateOps["eq"] = "ne";
272  negateOps["ne"] = "eq";
273  negateOps["le"] = "gt";
274  negateOps["gt"] = "le";
275  negateOps["lt"] = "ge";
276  negateOps["ge"] = "lt";
277  negateOps["leu"] = "gtu";
278  negateOps["gtu"] = "leu";
279  negateOps["ltu"] = "geu";
280  negateOps["geu"] = "ltu";
281 
282  const Operation& op = po->operation();
283  std::cerr << "negating op: " << op.name() << std::endl;
284  auto i = negateOps.find(op.name());
285  if (i == negateOps.end()) {
286  std::cerr << "negated op for: " << op.name() << " not found!" << std::endl;
287  return false;
288  }
289  std::cerr << "negated opname: " << i->second << std::endl;
290 
291  if (!MachineInfo::supportsOperation(mach_, i->second)) {
292  return false;
293  }
294  OperationPool pool;
295  const Operation& negatedOp = pool.operation(i->second.c_str());
296  po->setOperation(negatedOp);
297  return true;
298 }
TTAProgram::Move::copy
std::shared_ptr< Move > copy() const
Definition: Move.cc:413
TTAProgram
Definition: Estimator.hh:65
Peel2BBLoops::irm_
TTAProgram::InstructionReferenceManager * irm_
Definition: Peel2BBLoops.hh:63
BoostGraph::connectNodes
virtual void connectNodes(const Node &nTail, const Node &nHead, Edge &e)
BoostGraph::outEdge
virtual Edge & outEdge(const Node &node, const int index) const
TTAProgram::Instruction::addMove
void addMove(std::shared_ptr< Move > move)
Definition: Instruction.cc:147
OperationPool::operation
Operation & operation(const char *name)
Definition: OperationPool.cc:99
SimpleIfConverter.hh
Peel2BBLoops::BBNodes::postLoop
BasicBlockNode * postLoop
Definition: Peel2BBLoops.hh:47
BoostGraph::tailNode
virtual Node & tailNode(const Edge &edge) const
SimpleIfConverter::fixTerminalPO
static ProgramOperationPtr fixTerminalPO(TTAProgram::TerminalFUPort &terminal, std::map< ProgramOperationPtr, ProgramOperationPtr > &poMapping)
Definition: SimpleIfConverter.cc:563
TTAProgram::Instruction::move
Move & move(int i) const
Definition: Instruction.cc:193
BoostGraph::headNode
virtual Node & headNode(const Edge &edge) const
BoostGraph::node
Node & node(const int index) const
MachineInfo::supportsOperation
static bool supportsOperation(const TTAMachine::Machine &mach, TCEString operation)
Definition: MachineInfo.cc:382
Peel2BBLoops::BBNodes::beginLoop
BasicBlockNode * beginLoop
Definition: Peel2BBLoops.hh:45
TTAProgram::Instruction
Definition: Instruction.hh:57
Procedure.hh
MachineInfo.hh
MoveNode
Definition: MoveNode.hh:65
Peel2BBLoops.hh
ControlFlowGraph::instructionReferenceManager
TTAProgram::InstructionReferenceManager & instructionReferenceManager()
Definition: ControlFlowGraph.cc:2401
BoostGraph::moveOutEdge
virtual void moveOutEdge(const Node &source, const Node &destination, Edge &edge, const Node *head=NULL, bool childs=false)
Operation::name
virtual TCEString name() const
Definition: Operation.cc:93
TerminalBasicBlockReference.hh
ControlFlowEdge
Definition: ControlFlowEdge.hh:50
Peel2BBLoops::negateOp
bool negateOp(ProgramOperationPtr po)
Definition: Peel2BBLoops.cc:267
ProgramOperationPtr
std::shared_ptr< ProgramOperation > ProgramOperationPtr
Definition: MoveNode.hh:52
BoostGraph::outDegree
virtual int outDegree(const Node &node) const
BoostGraph::disconnectNodes
virtual void disconnectNodes(const Node &nTail, const Node &nHead)
MoveNode::setSourceOperationPtr
void setSourceOperationPtr(ProgramOperationPtr po)
Definition: MoveNode.cc:541
BasicBlockNode::basicBlock
TTAProgram::BasicBlock & basicBlock()
Definition: BasicBlockNode.cc:126
assert
#define assert(condition)
Definition: Application.hh:86
Peel2BBLoops::Peel2BBLoops
Peel2BBLoops(InterPassData &data, const TTAMachine::Machine &targetMachine)
Definition: Peel2BBLoops.cc:31
Instruction.hh
MoveNode::addDestinationOperationPtr
void addDestinationOperationPtr(ProgramOperationPtr po)
Definition: MoveNode.cc:533
TTAProgram::CodeSnippet::instructionCount
virtual int instructionCount() const
Definition: CodeSnippet.cc:205
ControlFlowGraph.hh
TTAProgram::CodeSnippet::add
virtual void add(Instruction *ins)
Definition: CodeSnippet.cc:432
BoostGraph::inEdge
virtual Edge & inEdge(const Node &node, const int index) const
BasicBlockNode
Definition: BasicBlockNode.hh:64
Peel2BBLoops::updateCFG
void updateCFG(ControlFlowGraph &cfg, BBNodes &bbns)
Definition: Peel2BBLoops.cc:130
BasicBlockNode::isNormalBB
bool isNormalBB() const
Definition: BasicBlockNode.cc:239
InterPassData
Definition: InterPassData.hh:48
Guard.hh
Operation.hh
TerminalFUPort.hh
Peel2BBLoops::peel2BBLoop
void peel2BBLoop(ControlFlowGraph &cfg, BBNodes &bbns)
Definition: Peel2BBLoops.cc:124
TTAProgram::Move
Definition: Move.hh:55
Peel2BBLoops::BBNodes
Definition: Peel2BBLoops.hh:36
ControlFlowEdge::isFallThroughEdge
bool isFallThroughEdge() const
Definition: ControlFlowEdge.cc:158
BoostGraph::inDegree
virtual int inDegree(const Node &node) const
Operation
Definition: Operation.hh:59
TTAProgram::TerminalBasicBlockReference
Definition: TerminalBasicBlockReference.hh:42
BoostGraph::inEdges
virtual EdgeSet inEdges(const Node &node) const
BoostGraph::connectingEdges
EdgeSet connectingEdges(const Node &nTail, const Node &nHead) const
Peel2BBLoops::BBNodes::endLoop
BasicBlockNode * endLoop
Definition: Peel2BBLoops.hh:46
TTAProgram::TerminalFUPort
Definition: TerminalFUPort.hh:56
ProgramOperation.hh
BoostGraph::outEdges
virtual EdgeSet outEdges(const Node &node) const
MoveNode::destinationOperation
ProgramOperation & destinationOperation(unsigned int index=0) const
Peel2BBLoops::appendBB
void appendBB(const TTAProgram::BasicBlock &src, TTAProgram::BasicBlock &dest, BasicBlockNode *newJumpDest)
Definition: Peel2BBLoops.cc:172
TTAProgram::BasicBlock
Definition: BasicBlock.hh:85
Peel2BBLoops::BBNodes::preLoop
BasicBlockNode * preLoop
Definition: Peel2BBLoops.hh:44
Peel2BBLoops::codeGenerator_
TTAProgram::CodeGenerator * codeGenerator_
Definition: Peel2BBLoops.hh:62
CodeGenerator.hh
Program.hh
ProgramOperation::setOperation
void setOperation(const Operation &op)
Definition: ProgramOperation.cc:941
TCEString
Definition: TCEString.hh:53
BasicBlock.hh
SimpleIfConverter::removeJump
static bool removeJump(TTAProgram::BasicBlock &bb)
Definition: SimpleIfConverter.cc:679
TTAProgram::CodeGenerator
Definition: CodeGenerator.hh:53
Peel2BBLoops::handleControlFlowGraph
void handleControlFlowGraph(ControlFlowGraph &cfg, const TTAMachine::Machine &targetMachine) override
Definition: Peel2BBLoops.cc:101
TTAProgram::CodeSnippet::instructionAtIndex
virtual Instruction & instructionAtIndex(int index) const
Definition: CodeSnippet.cc:285
ControlFlowGraphPass
Definition: ControlFlowGraphPass.hh:50
Peel2BBLoops::testIf2BBLoop
BBNodes testIf2BBLoop(ControlFlowGraph &cfg, BasicBlockNode &bbn)
Definition: Peel2BBLoops.cc:37
OperationPool
Definition: OperationPool.hh:52
TTAProgram::CodeGenerator::createInverseGuard
static TTAProgram::MoveGuard * createInverseGuard(const TTAProgram::MoveGuard &mg, const TTAMachine::Bus *bus=NULL)
Definition: CodeGenerator.cc:837
Move.hh
MoveNode.hh
ControlFlowEdge::CFLOW_EDGE_FALLTHROUGH
@ CFLOW_EDGE_FALLTHROUGH
Definition: ControlFlowEdge.hh:62
BoostGraph::nodeCount
int nodeCount() const
OperationPool.hh
ControlFlowGraph::deleteNodeAndRefs
void deleteNodeAndRefs(BasicBlockNode &node)
Definition: ControlFlowGraph.cc:2395
ControlFlowEdge::CFLOW_EDGE_JUMP
@ CFLOW_EDGE_JUMP
Definition: ControlFlowEdge.hh:60
TTAProgram::Instruction::moveCount
int moveCount() const
Definition: Instruction.cc:176
Peel2BBLoops::mach_
const TTAMachine::Machine & mach_
Definition: Peel2BBLoops.hh:64
ControlFlowGraph
Definition: ControlFlowGraph.hh:100
TTAMachine::Machine
Definition: Machine.hh:73
MoveGuard.hh
Peel2BBLoops::performCodeMotion
void performCodeMotion(BBNodes &bbns)
Definition: Peel2BBLoops.cc:156