예제 #1
0
 void visitSelect(Select* curr) {
   if (isDead(curr->ifTrue)) {
     replaceCurrent(curr->ifTrue);
     return;
   }
   if (isDead(curr->ifFalse)) {
     auto* block = getModule()->allocator.alloc<Block>();
     block->list.resize(2);
     block->list[0] = curr->ifTrue;
     block->list[1] = curr->ifFalse;
     block->finalize();
     replaceCurrent(block);
     return;
   }
   if (isDead(curr->condition)) {
     auto* block = getModule()->allocator.alloc<Block>();
     block->list.resize(3);
     block->list[0] = curr->ifTrue;
     block->list[1] = curr->ifFalse;
     block->list[2] = curr->condition;
     block->finalize();
     replaceCurrent(block);
     return;
   }
 }
예제 #2
0
 void visitCallImport(CallImport *curr) {
   WasmType type = getModule()->getFunctionType(getModule()->getImport(curr->target)->functionType)->result;
   if (type == none) {
     replaceCurrent(getModule()->allocator.alloc<Nop>());
   } else {
     Literal nopLiteral;
     nopLiteral.type = type;
     replaceCurrent(getModule()->allocator.alloc<Const>()->set(nopLiteral));
   }
 }
예제 #3
0
 void visitCallImport(CallImport *curr) {
   WasmType type = module->getImport(curr->target)->type->result;
   if (type == none) {
     replaceCurrent(allocator->alloc<Nop>());
   } else {
     Literal nopLiteral;
     nopLiteral.type = type;
     replaceCurrent(allocator->alloc<Const>()->set(nopLiteral));
   }
 }
예제 #4
0
 void visitBinary(Binary* curr) {
   if (isDead(curr->left)) {
     replaceCurrent(curr->left);
     return;
   }
   if (isDead(curr->right)) {
     auto* block = getModule()->allocator.alloc<Block>();
     block->list.resize(2);
     block->list[0] = curr->left;
     block->list[1] = curr->right;
     block->finalize();
     replaceCurrent(block);
   }
 }
예제 #5
0
 void visitStore(Store* curr) {
   if (isDead(curr->ptr)) {
     replaceCurrent(curr->ptr);
     return;
   }
   if (isDead(curr->value)) {
     auto* block = getModule()->allocator.alloc<Block>();
     block->list.resize(2);
     block->list[0] = curr->ptr;
     block->list[1] = curr->value;
     block->finalize();
     replaceCurrent(block);
   }
 }
예제 #6
0
 void visitReturn(Return* curr) {
   if (isDead(curr->value)) {
     replaceCurrent(curr->value);
     return;
   }
   reachable = false;
 }
예제 #7
0
 Block* optimize(Expression* curr, Expression*& child, Block* outer = nullptr, Expression** dependency1 = nullptr, Expression** dependency2 = nullptr) {
   if (!child) return outer;
   if (dependency1 && *dependency1 && EffectAnalyzer(*dependency1).hasSideEffects()) return outer;
   if (dependency2 && *dependency2 && EffectAnalyzer(*dependency2).hasSideEffects()) return outer;
   if (auto* block = child->dynCast<Block>()) {
     if (!block->name.is() && block->list.size() >= 2) {
       child = block->list.back();
       if (outer == nullptr) {
         // reuse the block, move it out
         block->list.back() = curr;
         block->finalize(); // last block element was our input, and is now our output, which may differ TODO optimize
         replaceCurrent(block);
         return block;
       } else {
         // append to an existing outer block
         assert(outer->list.back() == curr);
         outer->list.pop_back();
         for (Index i = 0; i < block->list.size() - 1; i++) {
           outer->list.push_back(block->list[i]);
         }
         outer->list.push_back(curr);
       }
     }
   }
   return outer;
 }
예제 #8
0
 void visitCallIndirect(CallIndirect* curr) {
   if (isDead(curr->target)) {
     replaceCurrent(curr->target);
     return;
   }
   handleCall(curr, curr->target);
 }
예제 #9
0
        void visitCallImport(CallImport* curr) {
          auto iter = illegalToLegal->find(curr->target);
          if (iter == illegalToLegal->end()) return;

          if (iter->second == getFunction()->name) return; // inside the stub function itself, is the one safe place to do the call
          replaceCurrent(Builder(*getModule()).makeCall(iter->second, curr->operands, curr->type));
        }
예제 #10
0
 // preparation: try to unify branches, as the fewer there are, the higher a chance we can remove them
 // specifically for if-else, turn an if-else with branches to the same target at the end of each
 // child, and with a value, to a branch to that target containing the if-else
 void visitIf(If* curr) override {
   if (!curr->ifFalse) return;
   if (curr->type != none) return; // already has a returned value
   // an if_else that indirectly returns a value by breaking to the same target can potentially remove both breaks, and break outside once
   auto getLast = [](Expression *side) -> Expression* {
     Block* b = side->dyn_cast<Block>();
     if (!b) return nullptr;
     if (b->list.size() == 0) return nullptr;
     return b->list.back();
   };
   auto process = [&](Expression *side, bool doIt) {
     Expression* last = getLast(side);
     if (!last) return Name();
     Block* b = side->cast<Block>();
     Break* br = last->dyn_cast<Break>();
     if (!br) return Name();
     if (br->condition) return Name();
     if (!br->value) return Name();
     if (doIt) {
       b->list[b->list.size()-1] = br->value;
     }
     return br->name;
   };
   // do both, or none
   if (process(curr->ifTrue, false).is() && process(curr->ifTrue, false) == process(curr->ifFalse, false)) {
     auto br = getLast(curr->ifTrue)->cast<Break>(); // we are about to discard this, so why not reuse it!
     process(curr->ifTrue, true);
     process(curr->ifFalse, true);
     curr->type = br->value->type; // if_else now returns a value
     br->value = curr;
     // no need to change anything else in the br - target is correct already
     replaceCurrent(br);
   }
 }
예제 #11
0
 void visitSetLocal(SetLocal* curr) {
   if (curr->index == labelIndex) {
     if (Index(curr->value->cast<Const>()->value.geti32()) == targetNum) {
       replaceCurrent(Builder(*getModule()).makeBreak(targetName));
     }
   }
 }
예제 #12
0
void PlaylistHistory::addToCurrent(const QList<QUrl> &filelist)
{
    Playlist *playlist = current();
    if (playlist != 0)
        playlist->append(filelist);
    else
        replaceCurrent(new Playlist(filelist));
}
예제 #13
0
 void visitIf(If* curr) {
   // the ifStack has the branch that joins us, either from before if just an if, or the ifTrue if an if-else
   reachable = reachable || ifStack.back();
   ifStack.pop_back();
   if (isDead(curr->condition)) {
     replaceCurrent(curr->condition);
   }
 }
예제 #14
0
 void visitSetLocal(SetLocal* curr) {
   if (ExpressionAnalyzer::isResultUsed(expressionStack, getFunction())) {
     Builder builder(*getModule());
     replaceCurrent(builder.makeSequence(
       curr,
       builder.makeGetLocal(curr->index, curr->type)
     ));
   }
 }
예제 #15
0
 void visitCallImport(CallImport* curr) {
   // special asm.js imports can be optimized
   auto* import = getModule()->getImport(curr->target);
   if (import->module == GLOBAL_MATH) {
     if (import->base == POW) {
       if (auto* exponent = curr->operands[1]->dynCast<Const>()) {
         if (exponent->value == Literal(double(2.0))) {
           // This is just a square operation, do a multiply
           Localizer localizer(curr->operands[0], getFunction(), getModule());
           Builder builder(*getModule());
           replaceCurrent(builder.makeBinary(MulFloat64, localizer.expr, builder.makeGetLocal(localizer.index, localizer.expr->type)));
         } else if (exponent->value == Literal(double(0.5))) {
           // This is just a square root operation
           replaceCurrent(Builder(*getModule()).makeUnary(SqrtFloat64, curr->operands[0]));
         }
       }
     }
   }
 }
예제 #16
0
 void visitBlock(Block* curr) {
   blockStack.pop_back();
   if (curr->name.is()) {
     reachable = reachable || reachableBreaks.count(curr->name);
     reachableBreaks.erase(curr->name);
   }
   if (curr->list.size() == 1 && isDead(curr->list[0])) {
     replaceCurrent(curr->list[0]);
   }
 }
예제 #17
0
 void visitGetLocal(GetLocal *curr) {
   auto found = sinkables.find(curr->name);
   if (found != sinkables.end()) {
     // sink it, and nop the origin TODO: clean up nops
     replaceCurrent(*found->second.item);
     // reuse the getlocal that is dying
     *found->second.item = curr;
     ExpressionManipulator::nop(curr);
     sinkables.erase(found);
   }
 }
예제 #18
0
/* TextEditor::onFRDBtnReplace
 * Called when the 'Replace' button on the Find+Replace frame is
 * clicked
 *******************************************************************/
void TextEditor::onFRDBtnReplace(wxCommandEvent& e)
{
	// Set search options
	int flags = 0;
	if (dlg_fr->matchCase()) flags |= wxSTC_FIND_MATCHCASE;
	if (dlg_fr->matchWord()) flags |= wxSTC_FIND_WHOLEWORD;
	SetSearchFlags(flags);

	// Do replace
	replaceCurrent(dlg_fr->getFindString(), dlg_fr->getReplaceString());
}
예제 #19
0
 void visitCall(Call* curr) {
   auto* import = getModule()->getFunctionOrNull(curr->target);
   if (!import || !import->imported() || import->module != ENV) return;
   for (auto name : ATEXIT_NAMES) {
     if (name == import->base) {
       replaceCurrent(
         Builder(*getModule()).replaceWithIdenticalType(curr)
       );
     }
   }
 }
예제 #20
0
 void visitBreak(Break* curr) {
   if (isDead(curr->value)) {
     // the condition is evaluated last, so if the value was unreachable, the whole thing is
     replaceCurrent(curr->value);
     return;
   }
   addBreak(curr->name);
   if (!curr->condition) {
     reachable = false;
   }
 }
예제 #21
0
 void visitIf(If* curr) {
   if (!curr->ifFalse) {
     // if without an else. try to reduce   if (condition) br  =>  br_if (condition)
     Break* br = curr->ifTrue->dynCast<Break>();
     if (br && !br->condition) { // TODO: if there is a condition, join them
       br->condition = curr->condition;
       replaceCurrent(br);
       anotherCycle = true;
     }
   }
 }
예제 #22
0
 void visitSwitch(Switch* curr) {
   if (isDead(curr->value)) {
     replaceCurrent(curr->value);
     return;
   }
   for (auto target : curr->targets) {
     addBreak(target);
   }
   addBreak(curr->default_);
   reachable = false;
 }
예제 #23
0
  void visitLoad(Load* curr) {
    if (curr->align == 0 || curr->align >= curr->bytes) {
      return;
    }

    // Switch unaligned loads of floats to unaligned loads of integers (which we
    // can actually implement) and then use reinterpretation to get the float
    // back out.
    switch (curr->type) {
      case f32:
        curr->type = i32;
        replaceCurrent(builder->makeUnary(ReinterpretInt32, curr));
        break;
      case f64:
        curr->type = i64;
        replaceCurrent(builder->makeUnary(ReinterpretInt64, curr));
        break;
      default:
        break;
    }
  }
예제 #24
0
 void visitBlock(Block *curr) {
   // compress out nops and other dead code
   int skip = 0;
   auto& list = curr->list;
   size_t size = list.size();
   bool needResize = false;
   for (size_t z = 0; z < size; z++) {
     auto* optimized = optimize(list[z], z == size - 1 && isConcreteWasmType(curr->type));
     if (!optimized) {
       skip++;
       needResize = true;
     } else {
       if (optimized != list[z]) {
         list[z] = optimized;
       }
       if (skip > 0) {
         list[z - skip] = list[z];
       }
       // if this is an unconditional br, the rest is dead code
       Break* br = list[z - skip]->dynCast<Break>();
       Switch* sw = list[z - skip]->dynCast<Switch>();
       if ((br && !br->condition) || sw) {
         auto* last = list.back();
         list.resize(z - skip + 1);
         // if we removed the last one, and it was a return value, it must be returned
         if (list.back() != last && isConcreteWasmType(last->type)) {
           list.push_back(last);
         }
         needResize = false;
         break;
       }
     }
   }
   if (needResize) {
     list.resize(size - skip);
   }
   if (!curr->name.is()) {
     if (list.size() == 1) {
       // just one element. replace the block, either with it or with a nop if it's not needed
       if (isConcreteWasmType(curr->type) || EffectAnalyzer(getPassOptions(), list[0]).hasSideEffects()) {
         replaceCurrent(list[0]);
       } else {
         if (curr->type == unreachable) {
           ExpressionManipulator::convert<Block, Unreachable>(curr);
         } else {
           ExpressionManipulator::nop(curr);
         }
       }
     } else if (list.size() == 0) {
       ExpressionManipulator::nop(curr);
     }
   }
 }
예제 #25
0
 void visitLoop(Loop* curr) {
   if (curr->in.is()) {
     reachableBreaks.erase(curr->in);
   }
   if (curr->out.is()) {
     reachable = reachable || reachableBreaks.count(curr->out);
     reachableBreaks.erase(curr->out);
   }
   if (isDead(curr->body)) {
     replaceCurrent(curr->body);
     return;
   }
 }
예제 #26
0
  void rewriteCopysign(Binary* curr) {
    Literal signBit, otherBits;
    UnaryOp int2float, float2int;
    BinaryOp bitAnd, bitOr;
    switch (curr->op) {
      case CopySignFloat32:
        float2int = ReinterpretFloat32;
        int2float = ReinterpretInt32;
        bitAnd = AndInt32;
        bitOr = OrInt32;
        signBit = Literal(uint32_t(1 << 31));
        otherBits = Literal(uint32_t(1 << 31) - 1);
        break;

      case CopySignFloat64:
        float2int = ReinterpretFloat64;
        int2float = ReinterpretInt64;
        bitAnd = AndInt64;
        bitOr = OrInt64;
        signBit = Literal(uint64_t(1) << 63);
        otherBits = Literal((uint64_t(1) << 63) - 1);
        break;

      default: return;
    }

    replaceCurrent(
      builder->makeUnary(
        int2float,
        builder->makeBinary(
          bitOr,
          builder->makeBinary(
            bitAnd,
            builder->makeUnary(
              float2int,
              curr->left
            ),
            builder->makeConst(otherBits)
          ),
          builder->makeBinary(
            bitAnd,
            builder->makeUnary(
              float2int,
              curr->right
            ),
            builder->makeConst(signBit)
          )
        )
      )
    );
  }
예제 #27
0
 void visitIf(If* curr) {
   // if the condition is a constant, just apply it
   // we can just return the ifTrue or ifFalse.
   if (auto* value = curr->condition->dynCast<Const>()) {
     if (value->value.getInteger()) {
       replaceCurrent(curr->ifTrue);
       return;
     } else {
       if (curr->ifFalse) {
         replaceCurrent(curr->ifFalse);
       } else {
         ExpressionManipulator::nop(curr);
       }
       return;
     }
   }
   if (curr->ifFalse) {
     if (curr->ifFalse->is<Nop>()) {
       curr->ifFalse = nullptr;
     } else if (curr->ifTrue->is<Nop>()) {
       curr->ifTrue = curr->ifFalse;
       curr->ifFalse = nullptr;
       curr->condition = Builder(*getModule()).makeUnary(EqZInt32, curr->condition);
     } else if (curr->ifTrue->is<Drop>() && curr->ifFalse->is<Drop>()) {
       // instead of dropping both sides, drop the if
       curr->ifTrue = curr->ifTrue->cast<Drop>()->value;
       curr->ifFalse = curr->ifFalse->cast<Drop>()->value;
       curr->finalize();
       replaceCurrent(Builder(*getModule()).makeDrop(curr));
     }
   } else {
     // no else
     if (curr->ifTrue->is<Nop>()) {
       // no nothing
       replaceCurrent(Builder(*getModule()).makeDrop(curr->condition));
     }
   }
 }
예제 #28
0
 void visitExpression(Expression* curr) {
   if (curr->is<Const>()) return;
   // try to evaluate this into a const
   Flow flow;
   try {
     flow = StandaloneExpressionRunner().visit(curr);
   } catch (StandaloneExpressionRunner::NonstandaloneException& e) {
     return;
   }
   if (flow.breaking()) return; // TODO: can create a break as a replacement in some cases (not NONSTANDALONE)
   if (isConcreteWasmType(flow.value.type)) {
     replaceCurrent(Builder(*getModule()).makeConst(flow.value));
   }
 }
예제 #29
0
/* TextEditor::onFRDKeyDown
 * Called when a key is pressed on the Find+Replace frame
 *******************************************************************/
void TextEditor::onFRDKeyDown(wxKeyEvent& e)
{
	// Esc (close)
	if (e.GetKeyCode() == WXK_ESCAPE)
		dlg_fr->Close();

	// Enter
	else if (e.GetKeyCode() == WXK_RETURN)
	{
		// Find Next
		if (dlg_fr->getTextFind()->HasFocus())
		{
			// Check find string
			string find = dlg_fr->getFindString();
			if (find.IsEmpty())
				return;

			// Set search options
			int flags = 0;
			if (dlg_fr->matchCase()) flags |= wxSTC_FIND_MATCHCASE;
			if (dlg_fr->matchWord()) flags |= wxSTC_FIND_WHOLEWORD;
			SetSearchFlags(flags);

			// Do find
			if (!findNext(find))
				wxLogMessage("No text matching \"%s\" found.", find);
		}

		// Replace
		else if (dlg_fr->getTextReplace()->HasFocus())
		{
			// Set search options
			int flags = 0;
			if (dlg_fr->matchCase()) flags |= wxSTC_FIND_MATCHCASE;
			if (dlg_fr->matchWord()) flags |= wxSTC_FIND_WHOLEWORD;
			SetSearchFlags(flags);

			// Do replace
			replaceCurrent(dlg_fr->getFindString(), dlg_fr->getReplaceString());
		}

		else
			e.Skip();
	}

	// Other
	else
		e.Skip();
}
예제 #30
0
 void visitIf(If *curr) {
   if (curr->ifFalse) {
     auto block = allocator->alloc<Block>();
     auto name = namer->getUnique("L"); // TODO: getUniqueInFunction
     block->name = name;
     block->list.push_back(curr);
     block->list.push_back(curr->ifFalse);
     curr->ifFalse = nullptr;
     auto break_ = allocator->alloc<Break>();
     break_->name = name;
     break_->value = curr->ifTrue;
     curr->ifTrue = break_;
     replaceCurrent(block);
   }
 }