com.wrmsr.wava.basic.match.LoopMatching.java Source code

Java tutorial

Introduction

Here is the source code for com.wrmsr.wava.basic.match.LoopMatching.java

Source

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.wrmsr.wava.basic.match;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.wrmsr.wava.core.node.Block;
import com.wrmsr.wava.core.node.Break;
import com.wrmsr.wava.core.node.BreakTable;
import com.wrmsr.wava.core.node.If;
import com.wrmsr.wava.core.node.Loop;
import com.wrmsr.wava.core.node.Node;
import com.wrmsr.wava.core.node.Nop;
import com.wrmsr.wava.core.node.Unary;
import com.wrmsr.wava.core.op.UnaryOp;
import com.wrmsr.wava.core.type.Name;
import com.wrmsr.wava.core.type.Type;
import com.wrmsr.wava.basic.Basic;
import com.wrmsr.wava.basic.BasicLoopInfo;
import com.wrmsr.wava.basic.BasicSet;

import java.util.stream.Stream;

import static com.google.common.collect.Iterables.getOnlyElement;
import static java.util.Objects.requireNonNull;

public final class LoopMatching {
    private LoopMatching() {
    }

    public static final class SelfLoopMatch {
        public final Node condition;
        public final Name outer;

        public SelfLoopMatch(Node condition, Name outer) {
            this.condition = requireNonNull(condition);
            this.outer = requireNonNull(outer);
        }
    }

    // FIXME handle n-ary via (statementized?) temp, can't reeval condition expr... actually make that another xform, all effectively boolean conditions made so
    public static Stream<SelfLoopMatch> matchSelfLoop(BasicLoopInfo loopInfo, Basic basic) {
        if (!loopInfo.isLoop(basic.getName()) || basic.getBreakTable().getTargets().size() != 1
                || basic.getAllTargets().size() != 2 || !basic.getAllTargets().contains(basic.getName())
                || !loopInfo.getBackEdges(basic.getName()).equals(ImmutableSet.of(basic.getName()))) {
            return Stream.empty();
        }
        if (basic.getBreakTable().getDefaultTarget().equals(basic.getName())) {
            return Stream.of(new SelfLoopMatch(basic.getBreakTable().getCondition(),
                    getOnlyElement(basic.getBreakTable().getTargets())));
        } else {
            return Stream
                    .of(new SelfLoopMatch(new Unary(UnaryOp.EqZ, Type.I32, basic.getBreakTable().getCondition()),
                            basic.getBreakTable().getDefaultTarget()));
        }
    }

    public static Stream<BasicSet> shrinkSelfLoops(BasicLoopInfo loopInfo, BasicSet basics, Basic basic) {
        return matchSelfLoop(loopInfo, basic).map(m -> {
            Node loop = new Loop(basic.getName(), new Block(ImmutableList.<Node>builder().addAll(basic.getBody())
                    .add(new If(m.condition, new Break(basic.getName(), new Nop()), new Nop())).build()));
            Basic newBasic = new Basic(basic.getName(), ImmutableList.of(loop),
                    new BreakTable(ImmutableList.of(), m.outer, new Nop()), basic.getIndex());
            return basics.replace(newBasic);
        });
    }
}