Implement and/or/xor in optimizing.
Change-Id: I7cf6da1fd334a7177a5580931b8f174dd40b7cec
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index e338178..d3ac4e0 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -1047,6 +1047,36 @@
break;
}
+ case Instruction::AND_INT: {
+ Binop_23x<HAnd>(instruction, Primitive::kPrimInt);
+ break;
+ }
+
+ case Instruction::AND_LONG: {
+ Binop_23x<HAnd>(instruction, Primitive::kPrimLong);
+ break;
+ }
+
+ case Instruction::OR_INT: {
+ Binop_23x<HOr>(instruction, Primitive::kPrimInt);
+ break;
+ }
+
+ case Instruction::OR_LONG: {
+ Binop_23x<HOr>(instruction, Primitive::kPrimLong);
+ break;
+ }
+
+ case Instruction::XOR_INT: {
+ Binop_23x<HXor>(instruction, Primitive::kPrimInt);
+ break;
+ }
+
+ case Instruction::XOR_LONG: {
+ Binop_23x<HXor>(instruction, Primitive::kPrimLong);
+ break;
+ }
+
case Instruction::ADD_LONG_2ADDR: {
Binop_12x<HAdd>(instruction, Primitive::kPrimLong);
break;
@@ -1118,11 +1148,56 @@
break;
}
+ case Instruction::AND_INT_2ADDR: {
+ Binop_12x<HAnd>(instruction, Primitive::kPrimInt);
+ break;
+ }
+
+ case Instruction::AND_LONG_2ADDR: {
+ Binop_12x<HAnd>(instruction, Primitive::kPrimLong);
+ break;
+ }
+
+ case Instruction::OR_INT_2ADDR: {
+ Binop_12x<HOr>(instruction, Primitive::kPrimInt);
+ break;
+ }
+
+ case Instruction::OR_LONG_2ADDR: {
+ Binop_12x<HOr>(instruction, Primitive::kPrimLong);
+ break;
+ }
+
+ case Instruction::XOR_INT_2ADDR: {
+ Binop_12x<HXor>(instruction, Primitive::kPrimInt);
+ break;
+ }
+
+ case Instruction::XOR_LONG_2ADDR: {
+ Binop_12x<HXor>(instruction, Primitive::kPrimLong);
+ break;
+ }
+
case Instruction::ADD_INT_LIT16: {
Binop_22s<HAdd>(instruction, false);
break;
}
+ case Instruction::AND_INT_LIT16: {
+ Binop_22s<HAnd>(instruction, false);
+ break;
+ }
+
+ case Instruction::OR_INT_LIT16: {
+ Binop_22s<HOr>(instruction, false);
+ break;
+ }
+
+ case Instruction::XOR_INT_LIT16: {
+ Binop_22s<HXor>(instruction, false);
+ break;
+ }
+
case Instruction::RSUB_INT: {
Binop_22s<HSub>(instruction, true);
break;
@@ -1138,6 +1213,21 @@
break;
}
+ case Instruction::AND_INT_LIT8: {
+ Binop_22b<HAnd>(instruction, false);
+ break;
+ }
+
+ case Instruction::OR_INT_LIT8: {
+ Binop_22b<HOr>(instruction, false);
+ break;
+ }
+
+ case Instruction::XOR_INT_LIT8: {
+ Binop_22b<HXor>(instruction, false);
+ break;
+ }
+
case Instruction::RSUB_INT_LIT8: {
Binop_22b<HSub>(instruction, true);
break;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index c2e9a2e..56546c2 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -2809,5 +2809,78 @@
instruction->GetDexPc());
}
+void LocationsBuilderARM::VisitAnd(HAnd* instruction) { HandleBitwiseOperation(instruction); }
+void LocationsBuilderARM::VisitOr(HOr* instruction) { HandleBitwiseOperation(instruction); }
+void LocationsBuilderARM::VisitXor(HXor* instruction) { HandleBitwiseOperation(instruction); }
+
+void LocationsBuilderARM::HandleBitwiseOperation(HBinaryOperation* instruction) {
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
+ DCHECK(instruction->GetResultType() == Primitive::kPrimInt
+ || instruction->GetResultType() == Primitive::kPrimLong);
+ locations->SetInAt(0, Location::RequiresRegister());
+ locations->SetInAt(1, Location::RequiresRegister());
+ bool output_overlaps = (instruction->GetResultType() == Primitive::kPrimLong);
+ locations->SetOut(Location::RequiresRegister(), output_overlaps);
+}
+
+void InstructionCodeGeneratorARM::VisitAnd(HAnd* instruction) {
+ HandleBitwiseOperation(instruction);
+}
+
+void InstructionCodeGeneratorARM::VisitOr(HOr* instruction) {
+ HandleBitwiseOperation(instruction);
+}
+
+void InstructionCodeGeneratorARM::VisitXor(HXor* instruction) {
+ HandleBitwiseOperation(instruction);
+}
+
+void InstructionCodeGeneratorARM::HandleBitwiseOperation(HBinaryOperation* instruction) {
+ LocationSummary* locations = instruction->GetLocations();
+
+ if (instruction->GetResultType() == Primitive::kPrimInt) {
+ Register first = locations->InAt(0).As<Register>();
+ Register second = locations->InAt(1).As<Register>();
+ Register out = locations->Out().As<Register>();
+ if (instruction->IsAnd()) {
+ __ and_(out, first, ShifterOperand(second));
+ } else if (instruction->IsOr()) {
+ __ orr(out, first, ShifterOperand(second));
+ } else {
+ DCHECK(instruction->IsXor());
+ __ eor(out, first, ShifterOperand(second));
+ }
+ } else {
+ DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimLong);
+ Location first = locations->InAt(0);
+ Location second = locations->InAt(1);
+ Location out = locations->Out();
+ if (instruction->IsAnd()) {
+ __ and_(out.AsRegisterPairLow<Register>(),
+ first.AsRegisterPairLow<Register>(),
+ ShifterOperand(second.AsRegisterPairLow<Register>()));
+ __ and_(out.AsRegisterPairHigh<Register>(),
+ first.AsRegisterPairHigh<Register>(),
+ ShifterOperand(second.AsRegisterPairHigh<Register>()));
+ } else if (instruction->IsOr()) {
+ __ orr(out.AsRegisterPairLow<Register>(),
+ first.AsRegisterPairLow<Register>(),
+ ShifterOperand(second.AsRegisterPairLow<Register>()));
+ __ orr(out.AsRegisterPairHigh<Register>(),
+ first.AsRegisterPairHigh<Register>(),
+ ShifterOperand(second.AsRegisterPairHigh<Register>()));
+ } else {
+ DCHECK(instruction->IsXor());
+ __ eor(out.AsRegisterPairLow<Register>(),
+ first.AsRegisterPairLow<Register>(),
+ ShifterOperand(second.AsRegisterPairLow<Register>()));
+ __ eor(out.AsRegisterPairHigh<Register>(),
+ first.AsRegisterPairHigh<Register>(),
+ ShifterOperand(second.AsRegisterPairHigh<Register>()));
+ }
+ }
+}
+
} // namespace arm
} // namespace art
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index 5d51993..d695310 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -105,9 +105,10 @@
#undef DECLARE_VISIT_INSTRUCTION
- void HandleInvoke(HInvoke* invoke);
-
private:
+ void HandleInvoke(HInvoke* invoke);
+ void HandleBitwiseOperation(HBinaryOperation* operation);
+
CodeGeneratorARM* const codegen_;
InvokeDexCallingConventionVisitor parameter_visitor_;
@@ -133,6 +134,7 @@
// the suspend call.
void GenerateSuspendCheck(HSuspendCheck* check, HBasicBlock* successor);
void GenerateClassInitializationCheck(SlowPathCodeARM* slow_path, Register class_reg);
+ void HandleBitwiseOperation(HBinaryOperation* operation);
ArmAssembler* const assembler_;
CodeGeneratorARM* const codegen_;
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 95c2fe7..887a4ef 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -631,6 +631,7 @@
codegen_(codegen) {}
#define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M) \
+ M(And) \
M(CheckCast) \
M(ClinitCheck) \
M(DivZeroCheck) \
@@ -640,11 +641,13 @@
M(LoadException) \
M(LoadString) \
M(MonitorOperation) \
+ M(Or) \
M(ParallelMove) \
M(StaticFieldGet) \
M(StaticFieldSet) \
M(Throw) \
M(TypeConversion) \
+ M(Xor) \
#define UNIMPLEMENTED_INSTRUCTION_BREAK_CODE(name) name##UnimplementedInstructionBreakCode
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index bed44b2..d470345 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1448,7 +1448,7 @@
}
case Primitive::kPrimLong: {
- if (second.IsRegister()) {
+ if (second.IsRegisterPair()) {
__ addl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>());
__ adcl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>());
} else {
@@ -1524,7 +1524,7 @@
}
case Primitive::kPrimLong: {
- if (second.IsRegister()) {
+ if (second.IsRegisterPair()) {
__ subl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>());
__ sbbl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>());
} else {
@@ -2919,5 +2919,99 @@
codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
}
+void LocationsBuilderX86::VisitAnd(HAnd* instruction) { HandleBitwiseOperation(instruction); }
+void LocationsBuilderX86::VisitOr(HOr* instruction) { HandleBitwiseOperation(instruction); }
+void LocationsBuilderX86::VisitXor(HXor* instruction) { HandleBitwiseOperation(instruction); }
+
+void LocationsBuilderX86::HandleBitwiseOperation(HBinaryOperation* instruction) {
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
+ DCHECK(instruction->GetResultType() == Primitive::kPrimInt
+ || instruction->GetResultType() == Primitive::kPrimLong);
+ locations->SetInAt(0, Location::RequiresRegister());
+ locations->SetInAt(1, Location::Any());
+ locations->SetOut(Location::SameAsFirstInput());
+}
+
+void InstructionCodeGeneratorX86::VisitAnd(HAnd* instruction) {
+ HandleBitwiseOperation(instruction);
+}
+
+void InstructionCodeGeneratorX86::VisitOr(HOr* instruction) {
+ HandleBitwiseOperation(instruction);
+}
+
+void InstructionCodeGeneratorX86::VisitXor(HXor* instruction) {
+ HandleBitwiseOperation(instruction);
+}
+
+void InstructionCodeGeneratorX86::HandleBitwiseOperation(HBinaryOperation* instruction) {
+ LocationSummary* locations = instruction->GetLocations();
+ Location first = locations->InAt(0);
+ Location second = locations->InAt(1);
+ DCHECK(first.Equals(locations->Out()));
+
+ if (instruction->GetResultType() == Primitive::kPrimInt) {
+ if (second.IsRegister()) {
+ if (instruction->IsAnd()) {
+ __ andl(first.As<Register>(), second.As<Register>());
+ } else if (instruction->IsOr()) {
+ __ orl(first.As<Register>(), second.As<Register>());
+ } else {
+ DCHECK(instruction->IsXor());
+ __ xorl(first.As<Register>(), second.As<Register>());
+ }
+ } else if (second.IsConstant()) {
+ if (instruction->IsAnd()) {
+ __ andl(first.As<Register>(), Immediate(second.GetConstant()->AsIntConstant()->GetValue()));
+ } else if (instruction->IsOr()) {
+ __ orl(first.As<Register>(), Immediate(second.GetConstant()->AsIntConstant()->GetValue()));
+ } else {
+ DCHECK(instruction->IsXor());
+ __ xorl(first.As<Register>(), Immediate(second.GetConstant()->AsIntConstant()->GetValue()));
+ }
+ } else {
+ if (instruction->IsAnd()) {
+ __ andl(first.As<Register>(), Address(ESP, second.GetStackIndex()));
+ } else if (instruction->IsOr()) {
+ __ orl(first.As<Register>(), Address(ESP, second.GetStackIndex()));
+ } else {
+ DCHECK(instruction->IsXor());
+ __ xorl(first.As<Register>(), Address(ESP, second.GetStackIndex()));
+ }
+ }
+ } else {
+ DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimLong);
+ if (second.IsRegisterPair()) {
+ if (instruction->IsAnd()) {
+ __ andl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>());
+ __ andl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>());
+ } else if (instruction->IsOr()) {
+ __ orl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>());
+ __ orl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>());
+ } else {
+ DCHECK(instruction->IsXor());
+ __ xorl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>());
+ __ xorl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>());
+ }
+ } else {
+ if (instruction->IsAnd()) {
+ __ andl(first.AsRegisterPairLow<Register>(), Address(ESP, second.GetStackIndex()));
+ __ andl(first.AsRegisterPairHigh<Register>(),
+ Address(ESP, second.GetHighStackIndex(kX86WordSize)));
+ } else if (instruction->IsOr()) {
+ __ orl(first.AsRegisterPairLow<Register>(), Address(ESP, second.GetStackIndex()));
+ __ orl(first.AsRegisterPairHigh<Register>(),
+ Address(ESP, second.GetHighStackIndex(kX86WordSize)));
+ } else {
+ DCHECK(instruction->IsXor());
+ __ xorl(first.AsRegisterPairLow<Register>(), Address(ESP, second.GetStackIndex()));
+ __ xorl(first.AsRegisterPairHigh<Register>(),
+ Address(ESP, second.GetHighStackIndex(kX86WordSize)));
+ }
+ }
+ }
+}
+
} // namespace x86
} // namespace art
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 85fe21c..9e42b0a 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -100,9 +100,10 @@
#undef DECLARE_VISIT_INSTRUCTION
+ private:
+ void HandleBitwiseOperation(HBinaryOperation* instruction);
void HandleInvoke(HInvoke* invoke);
- private:
CodeGeneratorX86* const codegen_;
InvokeDexCallingConventionVisitor parameter_visitor_;
@@ -128,6 +129,7 @@
// the suspend call.
void GenerateSuspendCheck(HSuspendCheck* check, HBasicBlock* successor);
void GenerateClassInitializationCheck(SlowPathCodeX86* slow_path, Register class_reg);
+ void HandleBitwiseOperation(HBinaryOperation* instruction);
X86Assembler* const assembler_;
CodeGeneratorX86* const codegen_;
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 112c179..3c7dd3f 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -2910,5 +2910,86 @@
codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
}
+void LocationsBuilderX86_64::VisitAnd(HAnd* instruction) { HandleBitwiseOperation(instruction); }
+void LocationsBuilderX86_64::VisitOr(HOr* instruction) { HandleBitwiseOperation(instruction); }
+void LocationsBuilderX86_64::VisitXor(HXor* instruction) { HandleBitwiseOperation(instruction); }
+
+void LocationsBuilderX86_64::HandleBitwiseOperation(HBinaryOperation* instruction) {
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
+ DCHECK(instruction->GetResultType() == Primitive::kPrimInt
+ || instruction->GetResultType() == Primitive::kPrimLong);
+ locations->SetInAt(0, Location::RequiresRegister());
+ if (instruction->GetType() == Primitive::kPrimInt) {
+ locations->SetInAt(1, Location::Any());
+ } else {
+ // Request a register to avoid loading a 64bits constant.
+ locations->SetInAt(1, Location::RequiresRegister());
+ }
+ locations->SetOut(Location::SameAsFirstInput());
+}
+
+void InstructionCodeGeneratorX86_64::VisitAnd(HAnd* instruction) {
+ HandleBitwiseOperation(instruction);
+}
+
+void InstructionCodeGeneratorX86_64::VisitOr(HOr* instruction) {
+ HandleBitwiseOperation(instruction);
+}
+
+void InstructionCodeGeneratorX86_64::VisitXor(HXor* instruction) {
+ HandleBitwiseOperation(instruction);
+}
+
+void InstructionCodeGeneratorX86_64::HandleBitwiseOperation(HBinaryOperation* instruction) {
+ LocationSummary* locations = instruction->GetLocations();
+ Location first = locations->InAt(0);
+ Location second = locations->InAt(1);
+ DCHECK(first.Equals(locations->Out()));
+
+ if (instruction->GetResultType() == Primitive::kPrimInt) {
+ if (second.IsRegister()) {
+ if (instruction->IsAnd()) {
+ __ andl(first.As<CpuRegister>(), second.As<CpuRegister>());
+ } else if (instruction->IsOr()) {
+ __ orl(first.As<CpuRegister>(), second.As<CpuRegister>());
+ } else {
+ DCHECK(instruction->IsXor());
+ __ xorl(first.As<CpuRegister>(), second.As<CpuRegister>());
+ }
+ } else if (second.IsConstant()) {
+ Immediate imm(second.GetConstant()->AsIntConstant()->GetValue());
+ if (instruction->IsAnd()) {
+ __ andl(first.As<CpuRegister>(), imm);
+ } else if (instruction->IsOr()) {
+ __ orl(first.As<CpuRegister>(), imm);
+ } else {
+ DCHECK(instruction->IsXor());
+ __ xorl(first.As<CpuRegister>(), imm);
+ }
+ } else {
+ Address address(CpuRegister(RSP), second.GetStackIndex());
+ if (instruction->IsAnd()) {
+ __ andl(first.As<CpuRegister>(), address);
+ } else if (instruction->IsOr()) {
+ __ orl(first.As<CpuRegister>(), address);
+ } else {
+ DCHECK(instruction->IsXor());
+ __ xorl(first.As<CpuRegister>(), address);
+ }
+ }
+ } else {
+ DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimLong);
+ if (instruction->IsAnd()) {
+ __ andq(first.As<CpuRegister>(), second.As<CpuRegister>());
+ } else if (instruction->IsOr()) {
+ __ orq(first.As<CpuRegister>(), second.As<CpuRegister>());
+ } else {
+ DCHECK(instruction->IsXor());
+ __ xorq(first.As<CpuRegister>(), second.As<CpuRegister>());
+ }
+ }
+}
+
} // namespace x86_64
} // namespace art
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index 9565b6f..52806f3 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -104,9 +104,10 @@
#undef DECLARE_VISIT_INSTRUCTION
- void HandleInvoke(HInvoke* invoke);
-
private:
+ void HandleInvoke(HInvoke* invoke);
+ void HandleBitwiseOperation(HBinaryOperation* operation);
+
CodeGeneratorX86_64* const codegen_;
InvokeDexCallingConventionVisitor parameter_visitor_;
@@ -132,6 +133,7 @@
// the suspend call.
void GenerateSuspendCheck(HSuspendCheck* instruction, HBasicBlock* successor);
void GenerateClassInitializationCheck(SlowPathCodeX86_64* slow_path, CpuRegister class_reg);
+ void HandleBitwiseOperation(HBinaryOperation* operation);
X86_64Assembler* const assembler_;
CodeGeneratorX86_64* const codegen_;
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 1545b0a..6224a11 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -475,6 +475,7 @@
#define FOR_EACH_CONCRETE_INSTRUCTION(M) \
M(Add, BinaryOperation) \
+ M(And, BinaryOperation) \
M(ArrayGet, Instruction) \
M(ArrayLength, Instruction) \
M(ArraySet, Instruction) \
@@ -516,6 +517,7 @@
M(Not, UnaryOperation) \
M(NotEqual, Condition) \
M(NullCheck, Instruction) \
+ M(Or, BinaryOperation) \
M(ParallelMove, Instruction) \
M(ParameterValue, Instruction) \
M(Phi, Instruction) \
@@ -529,6 +531,7 @@
M(Temporary, Instruction) \
M(Throw, Instruction) \
M(TypeConversion, Instruction) \
+ M(Xor, BinaryOperation) \
#define FOR_EACH_INSTRUCTION(M) \
FOR_EACH_CONCRETE_INSTRUCTION(M) \
@@ -1791,6 +1794,54 @@
DISALLOW_COPY_AND_ASSIGN(HDivZeroCheck);
};
+class HAnd : public HBinaryOperation {
+ public:
+ HAnd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
+ : HBinaryOperation(result_type, left, right) {}
+
+ bool IsCommutative() OVERRIDE { return true; }
+
+ int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x & y; }
+ int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x & y; }
+
+ DECLARE_INSTRUCTION(And);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HAnd);
+};
+
+class HOr : public HBinaryOperation {
+ public:
+ HOr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
+ : HBinaryOperation(result_type, left, right) {}
+
+ bool IsCommutative() OVERRIDE { return true; }
+
+ int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x | y; }
+ int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x | y; }
+
+ DECLARE_INSTRUCTION(Or);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HOr);
+};
+
+class HXor : public HBinaryOperation {
+ public:
+ HXor(Primitive::Type result_type, HInstruction* left, HInstruction* right)
+ : HBinaryOperation(result_type, left, right) {}
+
+ bool IsCommutative() OVERRIDE { return true; }
+
+ int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x ^ y; }
+ int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x ^ y; }
+
+ DECLARE_INSTRUCTION(Xor);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HXor);
+};
+
// The value of a parameter in this method. Its location depends on
// the calling convention.
class HParameterValue : public HExpression<0> {