diff options
-rw-r--r-- | compiler/optimizing/builder.cc | 5 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 28 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 26 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 26 | ||||
-rw-r--r-- | compiler/optimizing/codegen_test.cc | 25 | ||||
-rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 12 |
7 files changed, 102 insertions, 22 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 4d575cbdcf..f48f4c3990 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -748,6 +748,11 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 break; } + case Instruction::NOT_INT: { + Unop_12x<HNot>(instruction, Primitive::kPrimInt); + break; + } + case Instruction::ADD_INT: { Binop_23x<HAdd>(instruction, Primitive::kPrimInt); break; diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 7ed802ec7b..b042beb795 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -1351,17 +1351,33 @@ void InstructionCodeGeneratorARM::VisitParameterValue(HParameterValue* instructi // Nothing to do, the parameter is already at its location. } -void LocationsBuilderARM::VisitNot(HNot* instruction) { +void LocationsBuilderARM::VisitNot(HNot* not_) { LocationSummary* locations = - new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); + new (GetGraph()->GetArena()) LocationSummary(not_, LocationSummary::kNoCall); locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); } -void InstructionCodeGeneratorARM::VisitNot(HNot* instruction) { - LocationSummary* locations = instruction->GetLocations(); - __ eor(locations->Out().As<Register>(), - locations->InAt(0).As<Register>(), ShifterOperand(1)); +void InstructionCodeGeneratorARM::VisitNot(HNot* not_) { + LocationSummary* locations = not_->GetLocations(); + Location out = locations->Out(); + Location in = locations->InAt(0); + switch (not_->InputAt(0)->GetType()) { + case Primitive::kPrimBoolean: + __ eor(out.As<Register>(), in.As<Register>(), ShifterOperand(1)); + break; + + case Primitive::kPrimInt: + __ mvn(out.As<Register>(), ShifterOperand(in.As<Register>())); + break; + + case Primitive::kPrimLong: + LOG(FATAL) << "Not yet implemented type for not operation " << not_->GetResultType(); + break; + + default: + LOG(FATAL) << "Unimplemented type for not operation " << not_->GetResultType(); + } } void LocationsBuilderARM::VisitCompare(HCompare* compare) { diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 5f01265b85..3b4b8359c7 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -1356,18 +1356,34 @@ void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) { void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) { } -void LocationsBuilderX86::VisitNot(HNot* instruction) { +void LocationsBuilderX86::VisitNot(HNot* not_) { LocationSummary* locations = - new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); + new (GetGraph()->GetArena()) LocationSummary(not_, LocationSummary::kNoCall); locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::SameAsFirstInput()); } -void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) { - LocationSummary* locations = instruction->GetLocations(); +void InstructionCodeGeneratorX86::VisitNot(HNot* not_) { + LocationSummary* locations = not_->GetLocations(); + DCHECK_EQ(locations->InAt(0).As<Register>(), locations->Out().As<Register>()); Location out = locations->Out(); DCHECK_EQ(locations->InAt(0).As<Register>(), out.As<Register>()); - __ xorl(out.As<Register>(), Immediate(1)); + switch (not_->InputAt(0)->GetType()) { + case Primitive::kPrimBoolean: + __ xorl(out.As<Register>(), Immediate(1)); + break; + + case Primitive::kPrimInt: + __ notl(out.As<Register>()); + break; + + case Primitive::kPrimLong: + LOG(FATAL) << "Not yet implemented type for not operation " << not_->GetResultType(); + break; + + default: + LOG(FATAL) << "Unimplemented type for not operation " << not_->GetResultType(); + } } void LocationsBuilderX86::VisitCompare(HCompare* compare) { diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 38a40dc7de..ac623f6a5d 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -1276,18 +1276,34 @@ void InstructionCodeGeneratorX86_64::VisitParameterValue(HParameterValue* instru // Nothing to do, the parameter is already at its location. } -void LocationsBuilderX86_64::VisitNot(HNot* instruction) { +void LocationsBuilderX86_64::VisitNot(HNot* not_) { LocationSummary* locations = - new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); + new (GetGraph()->GetArena()) LocationSummary(not_, LocationSummary::kNoCall); locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::SameAsFirstInput()); } -void InstructionCodeGeneratorX86_64::VisitNot(HNot* instruction) { - LocationSummary* locations = instruction->GetLocations(); +void InstructionCodeGeneratorX86_64::VisitNot(HNot* not_) { + LocationSummary* locations = not_->GetLocations(); DCHECK_EQ(locations->InAt(0).As<CpuRegister>().AsRegister(), locations->Out().As<CpuRegister>().AsRegister()); - __ xorq(locations->Out().As<CpuRegister>(), Immediate(1)); + Location out = locations->Out(); + switch (not_->InputAt(0)->GetType()) { + case Primitive::kPrimBoolean: + __ xorq(out.As<CpuRegister>(), Immediate(1)); + break; + + case Primitive::kPrimInt: + __ notl(out.As<CpuRegister>()); + break; + + case Primitive::kPrimLong: + LOG(FATAL) << "Not yet implemented type for not operation " << not_->GetResultType(); + break; + + default: + LOG(FATAL) << "Unimplemented type for not operation " << not_->GetResultType(); + } } void LocationsBuilderX86_64::VisitPhi(HPhi* instruction) { diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc index af4cf73867..a84931a679 100644 --- a/compiler/optimizing/codegen_test.cc +++ b/compiler/optimizing/codegen_test.cc @@ -260,6 +260,31 @@ TEST(CodegenTest, ReturnIf2) { TestCode(data, true, 0); } +// Exercise bit-wise (one's complement) not-int instruction. +#define NOT_INT_TEST(TEST_NAME, INPUT, EXPECTED_OUTPUT) \ +TEST(CodegenTest, TEST_NAME) { \ + const int32_t input = INPUT; \ + const uint16_t input_lo = input & 0x0000FFFF; \ + const uint16_t input_hi = input >> 16; \ + const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( \ + Instruction::CONST | 0 << 8, input_lo, input_hi, \ + Instruction::NOT_INT | 1 << 8 | 0 << 12 , \ + Instruction::RETURN | 1 << 8); \ + \ + TestCode(data, true, EXPECTED_OUTPUT); \ +} + +NOT_INT_TEST(ReturnNotIntMinus2, -2, 1) +NOT_INT_TEST(ReturnNotIntMinus1, -1, 0) +NOT_INT_TEST(ReturnNotInt0, 0, -1) +NOT_INT_TEST(ReturnNotInt1, 1, -2) +NOT_INT_TEST(ReturnNotIntINT_MIN, -2147483648, 2147483647) // (2^31) - 1 +NOT_INT_TEST(ReturnNotIntINT_MINPlus1, -2147483647, 2147483646) // (2^31) - 2 +NOT_INT_TEST(ReturnNotIntINT_MAXMinus1, 2147483646, -2147483647) // -(2^31) - 1 +NOT_INT_TEST(ReturnNotIntINT_MAX, 2147483647, -2147483648) // -(2^31) + +#undef NOT_INT_TEST + TEST(CodegenTest, ReturnAdd1) { const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( Instruction::CONST_4 | 3 << 12 | 0, diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 2d9e35c3b6..29eabe7e29 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -50,7 +50,7 @@ void InstructionSimplifier::VisitEqual(HEqual* equal) { // Replace (bool_value == 0) with !bool_value DCHECK_EQ(input2->AsIntConstant()->GetValue(), 0); equal->GetBlock()->ReplaceAndRemoveInstructionWith( - equal, new (GetGraph()->GetArena()) HNot(input1)); + equal, new (GetGraph()->GetArena()) HNot(Primitive::kPrimBoolean, input1)); } } } diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 9b7ff88b68..9c923d6f59 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -485,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) \ @@ -1708,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: |