Check for consistent SSA in CF before register allocation
Change-Id: Ifcf8a5bf2054b58d25acb988c9cd5e260fa4285e
diff --git a/src/main/java/com/android/tools/r8/ir/code/Dup.java b/src/main/java/com/android/tools/r8/ir/code/Dup.java
index 4ef2370..89542a7 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Dup.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Dup.java
@@ -30,6 +30,7 @@
assert outValue == null || !outValue.hasUsersInfo() || !outValue.isUsed() ||
value instanceof StackValues;
this.outValue = value;
+ this.outValue.definition = this;
for (StackValue val : ((StackValues)value).getStackValues()) {
val.definition = this;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Dup2.java b/src/main/java/com/android/tools/r8/ir/code/Dup2.java
index 6d61f58..fcb5b8e 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Dup2.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Dup2.java
@@ -44,6 +44,7 @@
assert outValue == null || !outValue.hasUsersInfo() || !outValue.isUsed() ||
value instanceof StackValues;
this.outValue = value;
+ this.outValue.definition = this;
for (StackValue val : ((StackValues)value).getStackValues()) {
val.definition = this;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCode.java b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
index cb93a5e..bef2765 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IRCode.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
@@ -20,6 +20,7 @@
import com.google.common.collect.Sets;
import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Deque;
@@ -34,6 +35,7 @@
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
public class IRCode {
@@ -575,7 +577,10 @@
}
private boolean verifyDefinition(Value value) {
- assert value.definition.outValue() == value;
+ Value outValue = value.definition.outValue();
+ assert outValue == value
+ || (value instanceof StackValue
+ && Arrays.asList(((StackValues) outValue).getStackValues()).contains(value));
return true;
}
@@ -662,11 +667,15 @@
}
// After the throwing instruction only debug instructions and the final jump
// instruction is allowed.
+ // TODO(mkroghj) Temporarily allow stack-operations to be after throwing instructions.
if (seenThrowing) {
assert instruction.isDebugInstruction()
|| instruction.isJumpInstruction()
|| instruction.isStore()
- || instruction.isPop();
+ || instruction.isPop()
+ || instruction.isDup()
+ || instruction.isDup2()
+ || instruction.isSwap();
}
}
}
@@ -675,7 +684,7 @@
}
public boolean verifyNoImpreciseOrBottomTypes() {
- return verifySSATypeLattice(
+ Predicate<Value> verifyValue =
v -> {
assert v.getTypeLattice().isPreciseType();
assert !v.getTypeLattice().isFineGrainedType();
@@ -685,6 +694,16 @@
assert !(v.definition instanceof ImpreciseMemberTypeInstruction)
|| ((ImpreciseMemberTypeInstruction) v.definition).getMemberType().isPrecise();
return true;
+ };
+ return verifySSATypeLattice(
+ v -> {
+ // StackValues is an artificial type created to allow returning multiple values from an
+ // instruction.
+ if (v instanceof StackValues) {
+ return Stream.of(((StackValues) v).getStackValues()).allMatch(verifyValue);
+ } else {
+ return verifyValue(v);
+ }
});
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Swap.java b/src/main/java/com/android/tools/r8/ir/code/Swap.java
index 80edc80..3c623d6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Swap.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Swap.java
@@ -33,6 +33,7 @@
assert outValue == null || !outValue.hasUsersInfo() || !outValue.isUsed() ||
value instanceof StackValues;
this.outValue = value;
+ this.outValue.definition = this;
for (StackValue val : ((StackValues)value).getStackValues()) {
val.definition = this;
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
index 4dcc839..6b5f6c4 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
@@ -166,6 +166,7 @@
reachedFixpoint = !phiOptimizations.optimize(code);
}
}
+ assert code.isConsistentSSA();
registerAllocator = new CfRegisterAllocator(code, options, typeVerificationHelper);
registerAllocator.allocateRegisters();
loadStoreHelper.insertPhiMoves(registerAllocator);