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> {