Pseudocode: Track merged values. Compute closure of value usages over merge instructions. Exclude merge instructions from usage lists

This commit is contained in:
Alexey Sedunov
2014-07-17 16:29:42 +04:00
parent 267ea81bbe
commit ffd4af872c
4 changed files with 50 additions and 27 deletions
@@ -17,13 +17,15 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import com.google.common.collect.*;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.util.containers.BidirectionalMap;
import kotlin.Function0;
import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.Label;
import org.jetbrains.jet.lang.cfg.LoopInfo;
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.*;
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.MergeInstruction;
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.jumps.AbstractJumpInstruction;
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.jumps.ConditionalJumpInstruction;
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.jumps.NondeterministicJumpInstruction;
@@ -91,14 +93,8 @@ public class PseudocodeImpl implements Pseudocode {
private final BidirectionalMap<JetElement, PseudoValue> elementsToValues = new BidirectionalMap<JetElement, PseudoValue>();
private final NotNullLazyValue<Map<PseudoValue, List<? extends Instruction>>> valueUsages =
new NotNullLazyValue<Map<PseudoValue, List<? extends Instruction>>>() {
@NotNull
@Override
protected Map<PseudoValue, List<? extends Instruction>> compute() {
return PseudocodePackage.collectValueUsages(PseudocodeImpl.this);
}
};
private final Map<PseudoValue, List<Instruction>> valueUsages = Maps.newHashMap();
private final Map<PseudoValue, Set<PseudoValue>> mergedValues = Maps.newHashMap();
private Pseudocode parent = null;
private Set<LocalFunctionDeclarationInstruction> localDeclarations = null;
@@ -232,6 +228,17 @@ public class PseudocodeImpl implements Pseudocode {
JetElementInstruction elementInstruction = (JetElementInstruction) instruction;
representativeInstructions.put(elementInstruction.getElement(), instruction);
}
if (instruction instanceof MergeInstruction) {
addMergedValues((MergeInstruction) instruction);
}
for (PseudoValue inputValue : instruction.getInputValues()) {
addValueUsage(inputValue, instruction);
for (PseudoValue mergedValue : getMergedValues(inputValue)) {
addValueUsage(mergedValue, instruction);
}
}
}
/*package*/ void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
@@ -272,7 +279,7 @@ public class PseudocodeImpl implements Pseudocode {
@NotNull
@Override
public List<? extends Instruction> getUsages(@Nullable PseudoValue value) {
List<? extends Instruction> result = valueUsages.getValue().get(value);
List<? extends Instruction> result = valueUsages.get(value);
return result != null ? result : Collections.<Instruction>emptyList();
}
@@ -283,6 +290,34 @@ public class PseudocodeImpl implements Pseudocode {
/*package*/ void bindLabel(Label label) {
((PseudocodeLabel) label).setTargetInstructionIndex(mutableInstructionList.size());
}
private Set<PseudoValue> getMergedValues(@NotNull PseudoValue value) {
Set<PseudoValue> result = mergedValues.get(value);
return result != null ? result : Collections.<PseudoValue>emptySet();
}
private void addMergedValues(@NotNull MergeInstruction instruction) {
Set<PseudoValue> result = new LinkedHashSet<PseudoValue>();
for (PseudoValue value : instruction.getInputValues()) {
result.addAll(getMergedValues(value));
result.add(value);
}
mergedValues.put(instruction.getOutputValue(), result);
}
private void addValueUsage(PseudoValue value, Instruction usage) {
if (usage instanceof MergeInstruction) return;
KotlinPackage.getOrPut(
valueUsages,
value,
new Function0<List<Instruction>>() {
@Override
public List<Instruction> invoke() {
return Lists.newArrayList();
}
}
).add(usage);
}
public void postProcess() {
if (postPrecessed) return;
@@ -135,16 +135,4 @@ public fun Instruction.getPrimaryDeclarationDescriptorIfAny(bindingContext: Bind
is CallInstruction -> return resolvedCall.getResultingDescriptor()
else -> PseudocodeUtil.extractVariableDescriptorIfAny(this, false, bindingContext)
}
}
private fun Pseudocode.collectValueUsages(): Map<PseudoValue, List<Instruction>> {
val map = HashMap<PseudoValue, MutableList<Instruction>>()
traverseFollowingInstructions(getEnterInstruction(), HashSet(), TraversalOrder.FORWARD) {
for (value in it.inputValues) {
map.getOrPut(value){ ArrayList() }.add(it)
}
true
}
return map
}
@@ -268,8 +268,8 @@ fun t11() {
}
}
---------------------
1 <v0>: * NEW: r(1) -> <v0>
2 <v1>: Unit NEW: r(2) -> <v1>
1 <v0>: {<: Unit} NEW: r(1) -> <v0>
2 <v1>: {<: Unit} NEW: r(2) -> <v1>
=====================
== t12 ==
fun t12() : Int {
@@ -17,7 +17,7 @@ fun dowhile() {
while(0 > 1)
}
---------------------
0 <v0>: * NEW: r(0) -> <v0>
1 <v1>: * NEW: r(1) -> <v1>
0 > 1 <v2>: * NEW: call(0 > 1, compareTo|<v0>, <v1>) -> <v2>
0 <v0>: {<: Comparable<Int>} NEW: r(0) -> <v0>
1 <v1>: Int NEW: r(1) -> <v1>
0 > 1 <v2>: Boolean NEW: call(0 > 1, compareTo|<v0>, <v1>) -> <v2>
=====================