ART: Implement DeadPhiHandling in PrimitiveTypePropagation
DeadPhiHandling revives non-conflicting phis with environment uses
but does not properly merge types. To not duplicate code, this patch
modifies PrimitiveTypePropagation to deal with conflicts and thus
replaces DeadPhiHandling altogether.
Bug: 24252151
Bug: 24252100
Change-Id: I198c71d1b8167fc05783a5a24aa9f1e3804acafe
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 0f2c1cf..1995797 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -4238,7 +4238,7 @@
inputs_(number_of_inputs, arena->Adapter(kArenaAllocPhiInputs)),
reg_number_(reg_number),
type_(type),
- is_live_(false),
+ is_live_(true),
can_be_null_(true) {
}
@@ -4263,7 +4263,18 @@
void RemoveInputAt(size_t index);
Primitive::Type GetType() const OVERRIDE { return type_; }
- void SetType(Primitive::Type type) { type_ = type; }
+ void SetType(Primitive::Type new_type) {
+ // Make sure that only valid type changes occur. The following are allowed:
+ // (1) void -> * (initial type assignment),
+ // (2) int -> float/ref (primitive type propagation),
+ // (3) long -> double (primitive type propagation).
+ DCHECK(type_ == new_type ||
+ type_ == Primitive::kPrimVoid ||
+ (type_ == Primitive::kPrimInt && new_type == Primitive::kPrimFloat) ||
+ (type_ == Primitive::kPrimInt && new_type == Primitive::kPrimNot) ||
+ (type_ == Primitive::kPrimLong && new_type == Primitive::kPrimDouble));
+ type_ = new_type;
+ }
bool CanBeNull() const OVERRIDE { return can_be_null_; }
void SetCanBeNull(bool can_be_null) { can_be_null_ = can_be_null; }
@@ -4485,7 +4496,8 @@
SideEffects additional_side_effects = SideEffects::None())
: HExpression(type,
SideEffects::ArrayReadOfType(type).Union(additional_side_effects),
- dex_pc) {
+ dex_pc),
+ fixed_type_(type != Primitive::kPrimInt && type != Primitive::kPrimLong) {
SetRawInputAt(0, array);
SetRawInputAt(1, index);
}
@@ -4503,7 +4515,13 @@
return false;
}
- void SetType(Primitive::Type type) { type_ = type; }
+ void SetType(Primitive::Type type) {
+ DCHECK(type_ == type || !IsTypeFixed());
+ type_ = type;
+ }
+
+ bool IsTypeFixed() const { return fixed_type_; }
+ void FixType() { fixed_type_ = true; }
HInstruction* GetArray() const { return InputAt(0); }
HInstruction* GetIndex() const { return InputAt(1); }
@@ -4511,6 +4529,12 @@
DECLARE_INSTRUCTION(ArrayGet);
private:
+ // Bytecode aget(-wide) instructions have ambiguous type (int/float, long/double).
+ // If the type can be determined from uses, `fixed_type_` should be set to true,
+ // to prevent PrimitiveTypePropagation from changing it while typing phis. With
+ // other aget-* variants, the type is always unambiguous.
+ bool fixed_type_;
+
DISALLOW_COPY_AND_ASSIGN(HArrayGet);
};