diff options
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/builder.cc | 90 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 73 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm64.cc | 3 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 98 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 81 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 51 |
9 files changed, 403 insertions, 5 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index e338178f7..d3ac4e02c 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -1047,6 +1047,36 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 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 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 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 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 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 c2e9a2e5d..56546c290 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -2809,5 +2809,78 @@ void InstructionCodeGeneratorARM::VisitMonitorOperation(HMonitorOperation* instr 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 5d519937f..d69531002 100644 --- a/compiler/optimizing/code_generator_arm.h +++ b/compiler/optimizing/code_generator_arm.h @@ -105,9 +105,10 @@ class LocationsBuilderARM : public HGraphVisitor { #undef DECLARE_VISIT_INSTRUCTION + private: void HandleInvoke(HInvoke* invoke); + void HandleBitwiseOperation(HBinaryOperation* operation); - private: CodeGeneratorARM* const codegen_; InvokeDexCallingConventionVisitor parameter_visitor_; @@ -133,6 +134,7 @@ class InstructionCodeGeneratorARM : public HGraphVisitor { // 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 95c2fe7fa..887a4efa1 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -631,6 +631,7 @@ InstructionCodeGeneratorARM64::InstructionCodeGeneratorARM64(HGraph* graph, codegen_(codegen) {} #define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M) \ + M(And) \ M(CheckCast) \ M(ClinitCheck) \ M(DivZeroCheck) \ @@ -640,11 +641,13 @@ InstructionCodeGeneratorARM64::InstructionCodeGeneratorARM64(HGraph* graph, 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 bed44b294..d47034576 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -1448,7 +1448,7 @@ void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) { } 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 @@ void InstructionCodeGeneratorX86::VisitSub(HSub* sub) { } 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 @@ void InstructionCodeGeneratorX86::VisitMonitorOperation(HMonitorOperation* instr 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 85fe21ca7..9e42b0a90 100644 --- a/compiler/optimizing/code_generator_x86.h +++ b/compiler/optimizing/code_generator_x86.h @@ -100,9 +100,10 @@ class LocationsBuilderX86 : public HGraphVisitor { #undef DECLARE_VISIT_INSTRUCTION + private: + void HandleBitwiseOperation(HBinaryOperation* instruction); void HandleInvoke(HInvoke* invoke); - private: CodeGeneratorX86* const codegen_; InvokeDexCallingConventionVisitor parameter_visitor_; @@ -128,6 +129,7 @@ class InstructionCodeGeneratorX86 : public HGraphVisitor { // 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 112c17975..3c7dd3f56 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -2910,5 +2910,86 @@ void InstructionCodeGeneratorX86_64::VisitMonitorOperation(HMonitorOperation* in 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 9565b6f87..52806f34d 100644 --- a/compiler/optimizing/code_generator_x86_64.h +++ b/compiler/optimizing/code_generator_x86_64.h @@ -104,9 +104,10 @@ class LocationsBuilderX86_64 : public HGraphVisitor { #undef DECLARE_VISIT_INSTRUCTION + private: void HandleInvoke(HInvoke* invoke); + void HandleBitwiseOperation(HBinaryOperation* operation); - private: CodeGeneratorX86_64* const codegen_; InvokeDexCallingConventionVisitor parameter_visitor_; @@ -132,6 +133,7 @@ class InstructionCodeGeneratorX86_64 : public HGraphVisitor { // 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 1545b0a02..6224a11f2 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -475,6 +475,7 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { #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 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { 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 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { 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 @@ class HDivZeroCheck : public HExpression<1> { 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> { |