Beispiel #1
0
 private bool ReplacePushDupPushPopPattern(BlockStatement b) {
   Contract.Requires(b != null);
   bool replacedPattern = false;
   var statements = b.Statements;
   for (int i = 0; i < statements.Count-4; i++) {
     var push1 = statements[i] as PushStatement;
     if (push1 == null) continue;
     var exprS1 = statements[i+1] as ExpressionStatement;
     if (exprS1 == null) continue;
     var assign1 = exprS1.Expression as Assignment;
     if (assign1 == null) continue;
     if (!(assign1.Source is DupValue) || assign1.Target.Instance != null) continue;
     var push2 = statements[i+2] as PushStatement;
     if (push2 == null) continue;
     var popCounter = new PopCounter();
     popCounter.Traverse(push2);
     if (popCounter.count != 1) continue;
     if (!this.singleUseExpressionChecker.ExpressionCanBeMovedAndDoesNotReference(push1.ValueToPush, assign1.Target.Definition)) continue;
     assign1.Source = push1.ValueToPush;
     var popReplacer = new SinglePopReplacer(this.host, assign1);
     popReplacer.Rewrite(push2.ValueToPush);
     statements.RemoveRange(i, 2);
     replacedPattern = true;
   }
   return replacedPattern;
 }
Beispiel #2
0
    internal static bool ReplacePushPopPattern(BlockStatement b, IMetadataHost host) {
      Contract.Requires(b != null);
      Contract.Requires(host != null);

      bool replacedPattern = false;
      var statements = b.Statements;
      for (int i = 0; i < statements.Count-1; i++) {
        //First identify count consecutive push statements
        int count = 0;
        while (i+count < statements.Count-1 && statements[i+count] is PushStatement) count++;
        if (count == 0) continue;
        Contract.Assert(i+count < statements.Count);
        Contract.Assert(count < statements.Count);
        for (int j = 0; j < count; j++) {
          Contract.Assume(statements[i+j] is PushStatement);
          if (((PushStatement)statements[i+j]).ValueToPush is DupValue) goto nextIteration;
        }
        Contract.Assert(i >= 0);
        Contract.Assert(i < statements.Count-1);
        //If any of the push statements (other than the first one) contains pop expressions, replace them with the corresponding push values and remove the pushes.
        int pushcount = 1; //the number of push statements that are eligble for removal at this point.
        for (int j = i + 1; j < i + count; j++) {
          Contract.Assume(j < statements.Count); //because i+count < statements.Count for the initial value of count and count just decreases
          Contract.Assume(j >= 0); //because i >= 0 and j never decreases to less than i
          Contract.Assume(statements[j] is PushStatement); //because i < j < i+count and i..i+count-1 are all push statements
          PushStatement st = (PushStatement)statements[j];
          PopCounter pcc = new PopCounter();
          pcc.Traverse(st.ValueToPush);
          int numberOfPushesToRemove = pushcount;
          if (pcc.count > 0) {
            if (pcc.count < numberOfPushesToRemove) numberOfPushesToRemove = pcc.count;
            int firstPushToRemove = j - numberOfPushesToRemove;
            PopReplacer prr = new PopReplacer(host, statements, firstPushToRemove, pcc.count-numberOfPushesToRemove);
            st.ValueToPush = prr.Rewrite(st.ValueToPush);
            statements.RemoveRange(firstPushToRemove, numberOfPushesToRemove);
            if (pcc.count > numberOfPushesToRemove) return true; //We've consumed all of the pushes and we're done.
            count -= numberOfPushesToRemove; //Fewer pushes now remain
            pushcount -= numberOfPushesToRemove; //Likewise fewer eligible pushes remain
            //Start over again at firstPushToRemove, which now indexes the first statement not yet considered.
            j = firstPushToRemove-1;
            continue;
          }
          pushcount++;
        }
        Contract.Assume(count >= 0);
        Contract.Assume(i+count < statements.Count);
        var nextStatement = statements[i + count];
        Contract.Assume(nextStatement != null);
        if (!(nextStatement is IExpressionStatement || nextStatement is IPushStatement || nextStatement is IReturnStatement || nextStatement is IThrowStatement)) continue;
        PopCounter pc = new PopCounter();
        pc.Traverse(nextStatement);
        if (pc.count == 0) continue;
        if (pc.count < count) {
          i += count-pc.count; //adjust i to point to the first push statement to remove because of subsequent pops.
          count = pc.count;
        }
        Contract.Assume(i < statements.Count);
        PopReplacer pr = new PopReplacer(host, statements, i, pc.count-count);
        pr.Rewrite(nextStatement);
        var s = nextStatement as Statement;
        if (s != null)
          s.Locations.AddRange(statements[i].Locations);
        Contract.Assume(count >= 0);
        Contract.Assert(i+count < statements.Count);
        statements.RemoveRange(i, count);
        replacedPattern = true;
      nextIteration: ;
      }
      return replacedPattern;
    }
Beispiel #3
0
 private bool ReplacePushDupPopPattern(BlockStatement b) {
   Contract.Requires(b != null);
   bool replacedPattern = false;
   var statements = b.Statements;
   for (int i = 0; i < statements.Count-3; i++) {
     var push1 = statements[i] as PushStatement;
     if (push1 == null) continue;
     var binop1 = push1.ValueToPush as BinaryOperation;
     if (binop1 == null) continue;
     var bound1 = binop1.LeftOperand as BoundExpression;
     if (bound1 == null) continue;
     var exprS1 = statements[i+1] as ExpressionStatement;
     if (exprS1 == null) continue;
     var assign1 = exprS1.Expression as Assignment;
     if (assign1 == null) continue;
     if (assign1.Target.Definition != bound1.Definition) continue;
     if (assign1.Target.Instance != bound1.Instance) {
       if (!(assign1.Target.Instance is IPopValue && bound1.Instance is IDupValue)) continue;
     }
     if (!(assign1.Source is DupValue)) continue;
     var statement = statements[i+2] as Statement;
     if (statement == null) continue;
     var popCounter = new PopCounter();
     popCounter.Traverse(statement);
     if (popCounter.count != 1) continue;
     binop1.LeftOperand = assign1.Target;
     var popReplacer = new SinglePopReplacer(this.host, binop1);
     popReplacer.Rewrite(statement);
     statements.RemoveRange(i, 2);
     replacedPattern = true;
   }
   return replacedPattern;
 }