ConvertTemps().toStackSlots(_function);
}
V4IR::Optimizer::showMeTheCode(_function);
+ QSet<V4IR::Jump *> removableJumps = opt.calculateOptionalJumps();
+ qSwap(_removableJumps, removableJumps);
Assembler* oldAssembler = _as;
_as = new Assembler(this, _function, executableAllocator, 6); // 6 == max argc for calls to built-ins with an argument array
qSwap(_reentryBlocks, reentryBlocks);
delete _as;
_as = oldAssembler;
+ qSwap(_removableJumps, removableJumps);
}
void *InstructionSelection::addConstantTable(QVector<Primitive> *values)
void InstructionSelection::visitJump(V4IR::Jump *s)
{
- _as->jumpToBlock(_block, s->target);
+ if (!_removableJumps.contains(s))
+ _as->jumpToBlock(_block, s->target);
}
void InstructionSelection::visitCJump(V4IR::CJump *s)
V4IR::BasicBlock *_block;
V4IR::Function* _function;
+ QSet<V4IR::Jump *> _removableJumps;
Assembler* _as;
QSet<V4IR::BasicBlock*> _reentryBlocks;
stackSlotAllocator = new StackSlotAllocator(opt.lifeRanges(), _function->tempCount);
opt.convertOutOfSSA();
}
+
qSwap(_stackSlotAllocator, stackSlotAllocator);
+ QSet<V4IR::Jump *> removableJumps = opt.calculateOptionalJumps();
+ qSwap(_removableJumps, removableJumps);
+
V4IR::Stmt *cs = 0;
qSwap(_currentStatement, cs);
codeRefs.insert(_function, squeezeCode());
qSwap(_currentStatement, cs);
+ qSwap(_removableJumps, removableJumps);
qSwap(_stackSlotAllocator, stackSlotAllocator);
delete stackSlotAllocator;
qSwap(_function, function);
{
if (s->target == _nextBlock)
return;
+ if (_removableJumps.contains(s))
+ return;
Instruction::Jump jump;
jump.offset = 0;
uchar *_codeEnd;
StackSlotAllocator *_stackSlotAllocator;
+ QSet<V4IR::Jump *> _removableJumps;
V4IR::Stmt *_currentStatement;
CompilationUnit *compilationUnit;
return lifeRanges.ranges();
}
+QSet<Jump *> Optimizer::calculateOptionalJumps()
+{
+ QSet<Jump *> optional;
+ QSet<BasicBlock *> reachableWithoutJump;
+
+ const int maxSize = function->basicBlocks.size();
+ optional.reserve(maxSize);
+ reachableWithoutJump.reserve(maxSize);
+
+ for (int i = function->basicBlocks.size() - 1; i >= 0; --i) {
+ BasicBlock *bb = function->basicBlocks[i];
+
+ if (Jump *jump = bb->statements.last()->asJump()) {
+ if (reachableWithoutJump.contains(jump->target)) {
+ if (bb->statements.size() > 1)
+ reachableWithoutJump.clear();
+ optional.insert(jump);
+ reachableWithoutJump.insert(bb);
+ continue;
+ }
+ }
+
+ reachableWithoutJump.clear();
+ reachableWithoutJump.insert(bb);
+ }
+
+#if 0
+ QTextStream out(stdout, QIODevice::WriteOnly);
+ out << "Jumps to ignore:" << endl;
+ foreach (Jump *j, removed) {
+ out << "\t" << j->id << ": ";
+ j->dump(out, Stmt::MIR);
+ out << endl;
+ }
+#endif
+
+ return optional;
+}
+
void Optimizer::showMeTheCode(Function *function)
{
::showMeTheCode(function);
QVector<LifeTimeInterval> lifeRanges() const;
+ QSet<V4IR::Jump *> calculateOptionalJumps();
+
static void showMeTheCode(Function *function);
private: