Add some more instruction support to optimizing compiler.
This adds a few more DEX instructions to the optimizing compiler's
builder (constants, moves, if_xx, etc).
Also:
* Changes the codegen for IF_XX instructions to use a condition
rather than comparing a value against 0.
* Fixes some instructions in the ARM disassembler.
* Fixes PushList and PopList in the thumb2 assembler.
* Switches the assembler for the optimizing compiler to thumb2
rather than ARM.
Change-Id: Iaafcd02243ccc5b03a054ef7a15285b84c06740f
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 143d5c9..503f31d 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -38,6 +38,15 @@
static const int kDefaultNumberOfPredecessors = 2;
static const int kDefaultNumberOfBackEdges = 1;
+enum IfCondition {
+ kCondEQ,
+ kCondNE,
+ kCondLT,
+ kCondLE,
+ kCondGT,
+ kCondGE,
+};
+
class HInstructionList {
public:
HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
@@ -66,7 +75,7 @@
maximum_number_of_out_vregs_(0),
number_of_vregs_(0),
number_of_in_vregs_(0),
- current_instruction_id_(0) { }
+ current_instruction_id_(0) {}
ArenaAllocator* GetArena() const { return arena_; }
const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; }
@@ -381,7 +390,13 @@
#define FOR_EACH_INSTRUCTION(M) \
M(Add) \
+ M(Condition) \
M(Equal) \
+ M(NotEqual) \
+ M(LessThan) \
+ M(LessThanOrEqual) \
+ M(GreaterThan) \
+ M(GreaterThanOrEqual) \
M(Exit) \
M(Goto) \
M(If) \
@@ -400,6 +415,7 @@
M(StoreLocal) \
M(Sub) \
+
#define FORWARD_DECLARATION(type) class H##type;
FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
#undef FORWARD_DECLARATION
@@ -413,7 +429,7 @@
class HUseListNode : public ArenaObject {
public:
HUseListNode(T* user, size_t index, HUseListNode* tail)
- : user_(user), index_(index), tail_(tail) { }
+ : user_(user), index_(index), tail_(tail) {}
HUseListNode* GetTail() const { return tail_; }
T* GetUser() const { return user_; }
@@ -444,7 +460,7 @@
live_interval_(nullptr),
lifetime_position_(kNoLifetime) {}
- virtual ~HInstruction() { }
+ virtual ~HInstruction() {}
HInstruction* GetNext() const { return next_; }
HInstruction* GetPrevious() const { return previous_; }
@@ -507,6 +523,10 @@
void ReplaceWith(HInstruction* instruction);
+ bool HasOnlyOneUse() const {
+ return uses_ != nullptr && uses_->GetTail() == nullptr;
+ }
+
#define INSTRUCTION_TYPE_CHECK(type) \
bool Is##type() { return (As##type() != nullptr); } \
virtual H##type* As##type() { return nullptr; }
@@ -616,7 +636,7 @@
class HInputIterator : public ValueObject {
public:
- explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) { }
+ explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) {}
bool Done() const { return index_ == instruction_->InputCount(); }
HInstruction* Current() const { return instruction_->InputAt(index_); }
@@ -676,7 +696,7 @@
template<typename T, intptr_t N>
class EmbeddedArray {
public:
- EmbeddedArray() : elements_() { }
+ EmbeddedArray() : elements_() {}
intptr_t GetLength() const { return N; }
@@ -721,8 +741,8 @@
template<intptr_t N>
class HTemplateInstruction: public HInstruction {
public:
- HTemplateInstruction<N>() : inputs_() { }
- virtual ~HTemplateInstruction() { }
+ HTemplateInstruction<N>() : inputs_() {}
+ virtual ~HTemplateInstruction() {}
virtual size_t InputCount() const { return N; }
virtual HInstruction* InputAt(size_t i) const { return inputs_[i]; }
@@ -738,6 +758,18 @@
friend class SsaBuilder;
};
+template<intptr_t N>
+class HExpression: public HTemplateInstruction<N> {
+ public:
+ explicit HExpression<N>(Primitive::Type type) : type_(type) {}
+ virtual ~HExpression() {}
+
+ virtual Primitive::Type GetType() const { return type_; }
+
+ private:
+ const Primitive::Type type_;
+};
+
// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
// instruction that branches to the exit block.
class HReturnVoid : public HTemplateInstruction<0> {
@@ -800,6 +832,7 @@
DISALLOW_COPY_AND_ASSIGN(HGoto);
};
+
// Conditional branch. A block ending with an HIf instruction must have
// two successors.
class HIf : public HTemplateInstruction<1> {
@@ -820,53 +853,143 @@
DECLARE_INSTRUCTION(If);
+ virtual bool IsIfInstruction() const { return true; }
+
private:
DISALLOW_COPY_AND_ASSIGN(HIf);
};
-class HBinaryOperation : public HTemplateInstruction<2> {
+class HBinaryOperation : public HExpression<2> {
public:
HBinaryOperation(Primitive::Type result_type,
HInstruction* left,
- HInstruction* right) : result_type_(result_type) {
+ HInstruction* right) : HExpression(result_type) {
SetRawInputAt(0, left);
SetRawInputAt(1, right);
}
HInstruction* GetLeft() const { return InputAt(0); }
HInstruction* GetRight() const { return InputAt(1); }
- Primitive::Type GetResultType() const { return result_type_; }
+ Primitive::Type GetResultType() const { return GetType(); }
virtual bool IsCommutative() { return false; }
- virtual Primitive::Type GetType() const { return GetResultType(); }
private:
- const Primitive::Type result_type_;
-
DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
};
-
-// Instruction to check if two inputs are equal to each other.
-class HEqual : public HBinaryOperation {
+class HCondition : public HBinaryOperation {
public:
- HEqual(HInstruction* first, HInstruction* second)
+ HCondition(HInstruction* first, HInstruction* second)
: HBinaryOperation(Primitive::kPrimBoolean, first, second) {}
virtual bool IsCommutative() { return true; }
+ bool NeedsMaterialization() const;
- virtual Primitive::Type GetType() const { return Primitive::kPrimBoolean; }
+ DECLARE_INSTRUCTION(Condition);
+
+ virtual IfCondition GetCondition() const = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HCondition);
+};
+
+// Instruction to check if two inputs are equal to each other.
+class HEqual : public HCondition {
+ public:
+ HEqual(HInstruction* first, HInstruction* second)
+ : HCondition(first, second) {}
DECLARE_INSTRUCTION(Equal);
+ virtual IfCondition GetCondition() const {
+ return kCondEQ;
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(HEqual);
};
+class HNotEqual : public HCondition {
+ public:
+ HNotEqual(HInstruction* first, HInstruction* second)
+ : HCondition(first, second) {}
+
+ DECLARE_INSTRUCTION(NotEqual);
+
+ virtual IfCondition GetCondition() const {
+ return kCondNE;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HNotEqual);
+};
+
+class HLessThan : public HCondition {
+ public:
+ HLessThan(HInstruction* first, HInstruction* second)
+ : HCondition(first, second) {}
+
+ DECLARE_INSTRUCTION(LessThan);
+
+ virtual IfCondition GetCondition() const {
+ return kCondLT;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HLessThan);
+};
+
+class HLessThanOrEqual : public HCondition {
+ public:
+ HLessThanOrEqual(HInstruction* first, HInstruction* second)
+ : HCondition(first, second) {}
+
+ DECLARE_INSTRUCTION(LessThanOrEqual);
+
+ virtual IfCondition GetCondition() const {
+ return kCondLE;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual);
+};
+
+class HGreaterThan : public HCondition {
+ public:
+ HGreaterThan(HInstruction* first, HInstruction* second)
+ : HCondition(first, second) {}
+
+ DECLARE_INSTRUCTION(GreaterThan);
+
+ virtual IfCondition GetCondition() const {
+ return kCondGT;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HGreaterThan);
+};
+
+class HGreaterThanOrEqual : public HCondition {
+ public:
+ HGreaterThanOrEqual(HInstruction* first, HInstruction* second)
+ : HCondition(first, second) {}
+
+ DECLARE_INSTRUCTION(GreaterThanOrEqual);
+
+ virtual IfCondition GetCondition() const {
+ return kCondGE;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual);
+};
+
+
// A local in the graph. Corresponds to a Dex register.
class HLocal : public HTemplateInstruction<0> {
public:
- explicit HLocal(uint16_t reg_number) : reg_number_(reg_number) { }
+ explicit HLocal(uint16_t reg_number) : reg_number_(reg_number) {}
DECLARE_INSTRUCTION(Local);
@@ -880,21 +1003,17 @@
};
// Load a given local. The local is an input of this instruction.
-class HLoadLocal : public HTemplateInstruction<1> {
+class HLoadLocal : public HExpression<1> {
public:
- explicit HLoadLocal(HLocal* local, Primitive::Type type) : type_(type) {
+ explicit HLoadLocal(HLocal* local, Primitive::Type type) : HExpression(type) {
SetRawInputAt(0, local);
}
- virtual Primitive::Type GetType() const { return type_; }
-
HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
DECLARE_INSTRUCTION(LoadLocal);
private:
- const Primitive::Type type_;
-
DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
};
@@ -917,12 +1036,11 @@
// Constants of the type int. Those can be from Dex instructions, or
// synthesized (for example with the if-eqz instruction).
-class HIntConstant : public HTemplateInstruction<0> {
+class HIntConstant : public HExpression<0> {
public:
- explicit HIntConstant(int32_t value) : value_(value) { }
+ explicit HIntConstant(int32_t value) : HExpression(Primitive::kPrimInt), value_(value) {}
int32_t GetValue() const { return value_; }
- virtual Primitive::Type GetType() const { return Primitive::kPrimInt; }
DECLARE_INSTRUCTION(IntConstant);
@@ -932,9 +1050,9 @@
DISALLOW_COPY_AND_ASSIGN(HIntConstant);
};
-class HLongConstant : public HTemplateInstruction<0> {
+class HLongConstant : public HExpression<0> {
public:
- explicit HLongConstant(int64_t value) : value_(value) { }
+ explicit HLongConstant(int64_t value) : HExpression(Primitive::kPrimLong), value_(value) {}
int64_t GetValue() const { return value_; }
@@ -1008,15 +1126,14 @@
DISALLOW_COPY_AND_ASSIGN(HInvokeStatic);
};
-class HNewInstance : public HTemplateInstruction<0> {
+class HNewInstance : public HExpression<0> {
public:
- HNewInstance(uint32_t dex_pc, uint16_t type_index) : dex_pc_(dex_pc), type_index_(type_index) {}
+ HNewInstance(uint32_t dex_pc, uint16_t type_index) : HExpression(Primitive::kPrimNot),
+ dex_pc_(dex_pc), type_index_(type_index) {}
uint32_t GetDexPc() const { return dex_pc_; }
uint16_t GetTypeIndex() const { return type_index_; }
- virtual Primitive::Type GetType() const { return Primitive::kPrimNot; }
-
// Calls runtime so needs an environment.
virtual bool NeedsEnvironment() const { return true; }
@@ -1057,15 +1174,13 @@
// The value of a parameter in this method. Its location depends on
// the calling convention.
-class HParameterValue : public HTemplateInstruction<0> {
+class HParameterValue : public HExpression<0> {
public:
HParameterValue(uint8_t index, Primitive::Type parameter_type)
- : index_(index), parameter_type_(parameter_type) {}
+ : HExpression(parameter_type), index_(index) {}
uint8_t GetIndex() const { return index_; }
- virtual Primitive::Type GetType() const { return parameter_type_; }
-
DECLARE_INSTRUCTION(ParameterValue);
private:
@@ -1073,19 +1188,15 @@
// than HGraph::number_of_in_vregs_;
const uint8_t index_;
- const Primitive::Type parameter_type_;
-
DISALLOW_COPY_AND_ASSIGN(HParameterValue);
};
-class HNot : public HTemplateInstruction<1> {
+class HNot : public HExpression<1> {
public:
- explicit HNot(HInstruction* input) {
+ explicit HNot(HInstruction* input) : HExpression(Primitive::kPrimBoolean) {
SetRawInputAt(0, input);
}
- virtual Primitive::Type GetType() const { return Primitive::kPrimBoolean; }
-
DECLARE_INSTRUCTION(Not);
private:
@@ -1210,10 +1321,10 @@
class HGraphVisitor : public ValueObject {
public:
- explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }
- virtual ~HGraphVisitor() { }
+ explicit HGraphVisitor(HGraph* graph) : graph_(graph) {}
+ virtual ~HGraphVisitor() {}
- virtual void VisitInstruction(HInstruction* instruction) { }
+ virtual void VisitInstruction(HInstruction* instruction) {}
virtual void VisitBasicBlock(HBasicBlock* block);
void VisitInsertionOrder();