summaryrefslogtreecommitdiff
path: root/compiler/optimizing/nodes.h
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/nodes.h')
-rw-r--r--compiler/optimizing/nodes.h192
1 files changed, 174 insertions, 18 deletions
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 677a4f8591..7adb84008a 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -399,6 +399,7 @@ class HBasicBlock : public ArenaObject {
void ReplaceAndRemoveInstructionWith(HInstruction* initial,
HInstruction* replacement);
void AddPhi(HPhi* phi);
+ void InsertPhiAfter(HPhi* instruction, HPhi* cursor);
void RemovePhi(HPhi* phi);
bool IsLoopHeader() const {
@@ -484,7 +485,7 @@ class HBasicBlock : public ArenaObject {
M(Local, Instruction) \
M(LongConstant, Constant) \
M(NewInstance, Instruction) \
- M(Not, Instruction) \
+ M(Not, UnaryOperation) \
M(ParameterValue, Instruction) \
M(ParallelMove, Instruction) \
M(Phi, Instruction) \
@@ -502,11 +503,17 @@ class HBasicBlock : public ArenaObject {
M(NullCheck, Instruction) \
M(Temporary, Instruction) \
M(SuspendCheck, Instruction) \
+ M(Mul, BinaryOperation) \
+ M(Neg, UnaryOperation) \
+ M(FloatConstant, Constant) \
+ M(DoubleConstant, Constant) \
+ M(NewArray, Instruction) \
#define FOR_EACH_INSTRUCTION(M) \
FOR_EACH_CONCRETE_INSTRUCTION(M) \
M(Constant, Instruction) \
- M(BinaryOperation, Instruction) \
+ M(UnaryOperation, Instruction) \
+ M(BinaryOperation, Instruction) \
M(Invoke, Instruction)
#define FORWARD_DECLARATION(type, super) class H##type;
@@ -650,6 +657,7 @@ class HInstruction : public ArenaObject {
virtual bool NeedsEnvironment() const { return false; }
virtual bool IsControlFlow() const { return false; }
+ virtual bool CanThrow() const { return false; }
bool HasSideEffects() const { return side_effects_.HasSideEffects(); }
void AddUseAt(HInstruction* user, size_t index) {
@@ -682,9 +690,10 @@ class HInstruction : public ArenaObject {
return result;
}
- // Does this instruction dominate `other_instruction`? Aborts if
- // this instruction and `other_instruction` are both phis.
- bool Dominates(HInstruction* other_instruction) const;
+ // Does this instruction strictly dominate `other_instruction`?
+ // Returns false if this instruction and `other_instruction` are the same.
+ // Aborts if this instruction and `other_instruction` are both phis.
+ bool StrictlyDominates(HInstruction* other_instruction) const;
int GetId() const { return id_; }
void SetId(int id) { id_ = id; }
@@ -705,6 +714,7 @@ class HInstruction : public ArenaObject {
void SetLocations(LocationSummary* locations) { locations_ = locations; }
void ReplaceWith(HInstruction* instruction);
+ void ReplaceInput(HInstruction* replacement, size_t index);
bool HasOnlyOneUse() const {
return uses_ != nullptr && uses_->GetTail() == nullptr;
@@ -990,8 +1000,8 @@ class HExpression : public HTemplateInstruction<N> {
virtual Primitive::Type GetType() const { return type_; }
- private:
- const Primitive::Type type_;
+ protected:
+ Primitive::Type type_;
};
// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
@@ -1083,6 +1093,34 @@ class HIf : public HTemplateInstruction<1> {
DISALLOW_COPY_AND_ASSIGN(HIf);
};
+class HUnaryOperation : public HExpression<1> {
+ public:
+ HUnaryOperation(Primitive::Type result_type, HInstruction* input)
+ : HExpression(result_type, SideEffects::None()) {
+ SetRawInputAt(0, input);
+ }
+
+ HInstruction* GetInput() const { return InputAt(0); }
+ Primitive::Type GetResultType() const { return GetType(); }
+
+ virtual bool CanBeMoved() const { return true; }
+ virtual bool InstructionDataEquals(HInstruction* other) const { return true; }
+
+ // Try to statically evaluate `operation` and return a HConstant
+ // containing the result of this evaluation. If `operation` cannot
+ // be evaluated as a constant, return nullptr.
+ HConstant* TryStaticEvaluation() const;
+
+ // Apply this operation to `x`.
+ virtual int32_t Evaluate(int32_t x) const = 0;
+ virtual int64_t Evaluate(int64_t x) const = 0;
+
+ DECLARE_INSTRUCTION(UnaryOperation);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HUnaryOperation);
+};
+
class HBinaryOperation : public HExpression<2> {
public:
HBinaryOperation(Primitive::Type result_type,
@@ -1101,10 +1139,10 @@ class HBinaryOperation : public HExpression<2> {
virtual bool CanBeMoved() const { return true; }
virtual bool InstructionDataEquals(HInstruction* other) const { return true; }
- // Try to statically evaluate `operation` and return an HConstant
+ // Try to statically evaluate `operation` and return a HConstant
// containing the result of this evaluation. If `operation` cannot
// be evaluated as a constant, return nullptr.
- HConstant* TryStaticEvaluation(ArenaAllocator* allocator) const;
+ HConstant* TryStaticEvaluation() const;
// Apply this operation to `x` and `y`.
virtual int32_t Evaluate(int32_t x, int32_t y) const = 0;
@@ -1368,6 +1406,48 @@ class HConstant : public HExpression<0> {
DISALLOW_COPY_AND_ASSIGN(HConstant);
};
+class HFloatConstant : public HConstant {
+ public:
+ explicit HFloatConstant(float value) : HConstant(Primitive::kPrimFloat), value_(value) {}
+
+ float GetValue() const { return value_; }
+
+ virtual bool InstructionDataEquals(HInstruction* other) const {
+ return bit_cast<float, int32_t>(other->AsFloatConstant()->value_) ==
+ bit_cast<float, int32_t>(value_);
+ }
+
+ virtual size_t ComputeHashCode() const { return static_cast<size_t>(GetValue()); }
+
+ DECLARE_INSTRUCTION(FloatConstant);
+
+ private:
+ const float value_;
+
+ DISALLOW_COPY_AND_ASSIGN(HFloatConstant);
+};
+
+class HDoubleConstant : public HConstant {
+ public:
+ explicit HDoubleConstant(double value) : HConstant(Primitive::kPrimDouble), value_(value) {}
+
+ double GetValue() const { return value_; }
+
+ virtual bool InstructionDataEquals(HInstruction* other) const {
+ return bit_cast<double, int64_t>(other->AsDoubleConstant()->value_) ==
+ bit_cast<double, int64_t>(value_);
+ }
+
+ virtual size_t ComputeHashCode() const { return static_cast<size_t>(GetValue()); }
+
+ DECLARE_INSTRUCTION(DoubleConstant);
+
+ private:
+ const double value_;
+
+ DISALLOW_COPY_AND_ASSIGN(HDoubleConstant);
+};
+
// Constants of the type int. Those can be from Dex instructions, or
// synthesized (for example with the if-eqz instruction).
class HIntConstant : public HConstant {
@@ -1515,6 +1595,44 @@ class HNewInstance : public HExpression<0> {
DISALLOW_COPY_AND_ASSIGN(HNewInstance);
};
+class HNeg : public HUnaryOperation {
+ public:
+ explicit HNeg(Primitive::Type result_type, HInstruction* input)
+ : HUnaryOperation(result_type, input) {}
+
+ virtual int32_t Evaluate(int32_t x) const OVERRIDE { return -x; }
+ virtual int64_t Evaluate(int64_t x) const OVERRIDE { return -x; }
+
+ DECLARE_INSTRUCTION(Neg);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HNeg);
+};
+
+class HNewArray : public HExpression<1> {
+ public:
+ HNewArray(HInstruction* length, uint32_t dex_pc, uint16_t type_index)
+ : HExpression(Primitive::kPrimNot, SideEffects::None()),
+ dex_pc_(dex_pc),
+ type_index_(type_index) {
+ SetRawInputAt(0, length);
+ }
+
+ uint32_t GetDexPc() const { return dex_pc_; }
+ uint16_t GetTypeIndex() const { return type_index_; }
+
+ // Calls runtime so needs an environment.
+ virtual bool NeedsEnvironment() const { return true; }
+
+ DECLARE_INSTRUCTION(NewArray);
+
+ private:
+ const uint32_t dex_pc_;
+ const uint16_t type_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(HNewArray);
+};
+
class HAdd : public HBinaryOperation {
public:
HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
@@ -1555,6 +1673,22 @@ class HSub : public HBinaryOperation {
DISALLOW_COPY_AND_ASSIGN(HSub);
};
+class HMul : public HBinaryOperation {
+ public:
+ HMul(Primitive::Type result_type, HInstruction* left, HInstruction* right)
+ : HBinaryOperation(result_type, left, right) {}
+
+ virtual bool IsCommutative() { return true; }
+
+ virtual int32_t Evaluate(int32_t x, int32_t y) const { return x * y; }
+ virtual int64_t Evaluate(int64_t x, int64_t y) const { return x * y; }
+
+ DECLARE_INSTRUCTION(Mul);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HMul);
+};
+
// The value of a parameter in this method. Its location depends on
// the calling convention.
class HParameterValue : public HExpression<0> {
@@ -1574,15 +1708,17 @@ class HParameterValue : public HExpression<0> {
DISALLOW_COPY_AND_ASSIGN(HParameterValue);
};
-class HNot : public HExpression<1> {
+class HNot : public HUnaryOperation {
public:
- explicit HNot(HInstruction* input) : HExpression(Primitive::kPrimBoolean, SideEffects::None()) {
- SetRawInputAt(0, input);
- }
+ explicit HNot(Primitive::Type result_type, HInstruction* input)
+ : HUnaryOperation(result_type, input) {}
virtual bool CanBeMoved() const { return true; }
virtual bool InstructionDataEquals(HInstruction* other) const { return true; }
+ virtual int32_t Evaluate(int32_t x) const OVERRIDE { return ~x; }
+ virtual int64_t Evaluate(int64_t x) const OVERRIDE { return ~x; }
+
DECLARE_INSTRUCTION(Not);
private:
@@ -1642,6 +1778,8 @@ class HNullCheck : public HExpression<1> {
virtual bool NeedsEnvironment() const { return true; }
+ virtual bool CanThrow() const { return true; }
+
uint32_t GetDexPc() const { return dex_pc_; }
DECLARE_INSTRUCTION(NullCheck);
@@ -1729,6 +1867,7 @@ class HArrayGet : public HExpression<2> {
virtual bool CanBeMoved() const { return true; }
virtual bool InstructionDataEquals(HInstruction* other) const { return true; }
+ void SetType(Primitive::Type type) { type_ = type; }
DECLARE_INSTRUCTION(ArrayGet);
@@ -1741,11 +1880,11 @@ class HArraySet : public HTemplateInstruction<3> {
HArraySet(HInstruction* array,
HInstruction* index,
HInstruction* value,
- Primitive::Type component_type,
+ Primitive::Type expected_component_type,
uint32_t dex_pc)
: HTemplateInstruction(SideEffects::ChangesSomething()),
dex_pc_(dex_pc),
- component_type_(component_type) {
+ expected_component_type_(expected_component_type) {
SetRawInputAt(0, array);
SetRawInputAt(1, index);
SetRawInputAt(2, value);
@@ -1759,13 +1898,24 @@ class HArraySet : public HTemplateInstruction<3> {
uint32_t GetDexPc() const { return dex_pc_; }
- Primitive::Type GetComponentType() const { return component_type_; }
+ HInstruction* GetValue() const { return InputAt(2); }
+
+ Primitive::Type GetComponentType() const {
+ // The Dex format does not type floating point index operations. Since the
+ // `expected_component_type_` is set during building and can therefore not
+ // be correct, we also check what is the value type. If it is a floating
+ // point type, we must use that type.
+ Primitive::Type value_type = GetValue()->GetType();
+ return ((value_type == Primitive::kPrimFloat) || (value_type == Primitive::kPrimDouble))
+ ? value_type
+ : expected_component_type_;
+ }
DECLARE_INSTRUCTION(ArraySet);
private:
const uint32_t dex_pc_;
- const Primitive::Type component_type_;
+ const Primitive::Type expected_component_type_;
DISALLOW_COPY_AND_ASSIGN(HArraySet);
};
@@ -1802,6 +1952,8 @@ class HBoundsCheck : public HExpression<2> {
virtual bool NeedsEnvironment() const { return true; }
+ virtual bool CanThrow() const { return true; }
+
uint32_t GetDexPc() const { return dex_pc_; }
DECLARE_INSTRUCTION(BoundsCheck);
@@ -1956,8 +2108,12 @@ class HGraphVisitor : public ValueObject {
virtual void VisitInstruction(HInstruction* instruction) {}
virtual void VisitBasicBlock(HBasicBlock* block);
+ // Visit the graph following basic block insertion order.
void VisitInsertionOrder();
+ // Visit the graph following dominator tree reverse post-order.
+ void VisitReversePostOrder();
+
HGraph* GetGraph() const { return graph_; }
// Visit functions for instruction classes.
@@ -1969,7 +2125,7 @@ class HGraphVisitor : public ValueObject {
#undef DECLARE_VISIT_INSTRUCTION
private:
- HGraph* graph_;
+ HGraph* const graph_;
DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
};