diff options
Diffstat (limited to 'compiler/optimizing')
| -rw-r--r-- | compiler/optimizing/code_generator.cc | 7 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 43 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_arm64.cc | 39 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_mips.cc | 20 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_mips64.cc | 13 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 72 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 71 | ||||
| -rw-r--r-- | compiler/optimizing/graph_visualizer.cc | 3 | ||||
| -rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 49 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_arm.cc | 14 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_arm64.cc | 14 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_mips.cc | 12 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_mips64.cc | 12 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_x86.cc | 16 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_x86_64.cc | 16 | ||||
| -rw-r--r-- | compiler/optimizing/locations.h | 4 | ||||
| -rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 20 | ||||
| -rw-r--r-- | compiler/optimizing/x86_memory_gen.cc | 84 | ||||
| -rw-r--r-- | compiler/optimizing/x86_memory_gen.h | 46 | 
19 files changed, 413 insertions, 142 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 4520f9b3e3..d40e2b9ad1 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -314,7 +314,8 @@ void CodeGenerator::InitializeCodeGeneration(size_t number_of_spill_slots,  void CodeGenerator::CreateCommonInvokeLocationSummary(      HInvoke* invoke, InvokeDexCallingConventionVisitor* visitor) {    ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetArena(); -  LocationSummary* locations = new (allocator) LocationSummary(invoke, LocationSummary::kCall); +  LocationSummary* locations = new (allocator) LocationSummary(invoke, +                                                               LocationSummary::kCallOnMainOnly);    for (size_t i = 0; i < invoke->GetNumberOfArguments(); i++) {      HInstruction* input = invoke->InputAt(i); @@ -378,7 +379,7 @@ void CodeGenerator::CreateUnresolvedFieldLocationSummary(    ArenaAllocator* allocator = field_access->GetBlock()->GetGraph()->GetArena();    LocationSummary* locations = -      new (allocator) LocationSummary(field_access, LocationSummary::kCall); +      new (allocator) LocationSummary(field_access, LocationSummary::kCallOnMainOnly);    locations->AddTemp(calling_convention.GetFieldIndexLocation()); @@ -499,7 +500,7 @@ void CodeGenerator::CreateLoadClassLocationSummary(HLoadClass* cls,                                                     bool code_generator_supports_read_barrier) {    ArenaAllocator* allocator = cls->GetBlock()->GetGraph()->GetArena();    LocationSummary::CallKind call_kind = cls->NeedsAccessCheck() -      ? LocationSummary::kCall +      ? LocationSummary::kCallOnMainOnly        : (((code_generator_supports_read_barrier && kEmitCompilerReadBarrier) ||            cls->CanCallRuntime())              ? LocationSummary::kCallOnSlowPath diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 690ecc3429..97645f3dec 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -2014,7 +2014,7 @@ void LocationsBuilderARM::VisitTypeConversion(HTypeConversion* conversion) {        (((input_type == Primitive::kPrimFloat || input_type == Primitive::kPrimDouble)          && result_type == Primitive::kPrimLong)         || (input_type == Primitive::kPrimLong && result_type == Primitive::kPrimFloat)) -      ? LocationSummary::kCall +      ? LocationSummary::kCallOnMainOnly        : LocationSummary::kNoCall;    LocationSummary* locations =        new (GetGraph()->GetArena()) LocationSummary(conversion, call_kind); @@ -2833,13 +2833,13 @@ void LocationsBuilderARM::VisitDiv(HDiv* div) {    LocationSummary::CallKind call_kind = LocationSummary::kNoCall;    if (div->GetResultType() == Primitive::kPrimLong) {      // pLdiv runtime call. -    call_kind = LocationSummary::kCall; +    call_kind = LocationSummary::kCallOnMainOnly;    } else if (div->GetResultType() == Primitive::kPrimInt && div->InputAt(1)->IsConstant()) {      // sdiv will be replaced by other instruction sequence.    } else if (div->GetResultType() == Primitive::kPrimInt &&               !codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {      // pIdivmod runtime call. -    call_kind = LocationSummary::kCall; +    call_kind = LocationSummary::kCallOnMainOnly;    }    LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(div, call_kind); @@ -2958,7 +2958,7 @@ void LocationsBuilderARM::VisitRem(HRem* rem) {    Primitive::Type type = rem->GetResultType();    // Most remainders are implemented in the runtime. -  LocationSummary::CallKind call_kind = LocationSummary::kCall; +  LocationSummary::CallKind call_kind = LocationSummary::kCallOnMainOnly;    if (rem->GetResultType() == Primitive::kPrimInt && rem->InputAt(1)->IsConstant()) {      // sdiv will be replaced by other instruction sequence.      call_kind = LocationSummary::kNoCall; @@ -3495,7 +3495,7 @@ void InstructionCodeGeneratorARM::VisitUShr(HUShr* ushr) {  void LocationsBuilderARM::VisitNewInstance(HNewInstance* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    if (instruction->IsStringAlloc()) {      locations->AddTemp(Location::RegisterLocation(kMethodRegisterArgument));    } else { @@ -3528,7 +3528,7 @@ void InstructionCodeGeneratorARM::VisitNewInstance(HNewInstance* instruction) {  void LocationsBuilderARM::VisitNewArray(HNewArray* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));    locations->SetOut(Location::RegisterLocation(R0)); @@ -5449,7 +5449,7 @@ void InstructionCodeGeneratorARM::VisitClearException(HClearException* clear ATT  void LocationsBuilderARM::VisitThrow(HThrow* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));  } @@ -5850,7 +5850,7 @@ void InstructionCodeGeneratorARM::VisitCheckCast(HCheckCast* instruction) {  void LocationsBuilderARM::VisitMonitorOperation(HMonitorOperation* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));  } @@ -6277,21 +6277,12 @@ void CodeGeneratorARM::GenerateReferenceLoadWithBakerReadBarrier(HInstruction* i    // /* LockWord */ lock_word = LockWord(monitor)    static_assert(sizeof(LockWord) == sizeof(int32_t),                  "art::LockWord and int32_t have different sizes."); -  // /* uint32_t */ rb_state = lock_word.ReadBarrierState() -  __ Lsr(temp_reg, temp_reg, LockWord::kReadBarrierStateShift); -  __ and_(temp_reg, temp_reg, ShifterOperand(LockWord::kReadBarrierStateMask)); -  static_assert( -      LockWord::kReadBarrierStateMask == ReadBarrier::rb_ptr_mask_, -      "art::LockWord::kReadBarrierStateMask is not equal to art::ReadBarrier::rb_ptr_mask_."); -  // Introduce a dependency on the high bits of rb_state, which shall -  // be all zeroes, to prevent load-load reordering, and without using +  // Introduce a dependency on the lock_word including the rb_state, +  // which shall prevent load-load reordering without using    // a memory barrier (which would be more expensive). -  // IP = rb_state & ~LockWord::kReadBarrierStateMask = 0 -  __ bic(IP, temp_reg, ShifterOperand(LockWord::kReadBarrierStateMask)); -  // obj is unchanged by this operation, but its value now depends on -  // IP, which depends on temp_reg. -  __ add(obj, obj, ShifterOperand(IP)); +  // obj is unchanged by this operation, but its value now depends on temp_reg. +  __ add(obj, obj, ShifterOperand(temp_reg, LSR, 32));    // The actual reference load.    if (index.IsValid()) { @@ -6328,8 +6319,14 @@ void CodeGeneratorARM::GenerateReferenceLoadWithBakerReadBarrier(HInstruction* i    // if (rb_state == ReadBarrier::gray_ptr_)    //   ref = ReadBarrier::Mark(ref); -  __ cmp(temp_reg, ShifterOperand(ReadBarrier::gray_ptr_)); -  __ b(slow_path->GetEntryLabel(), EQ); +  // Given the numeric representation, it's enough to check the low bit of the +  // rb_state. We do that by shifting the bit out of the lock word with LSRS +  // which can be a 16-bit instruction unlike the TST immediate. +  static_assert(ReadBarrier::white_ptr_ == 0, "Expecting white to have value 0"); +  static_assert(ReadBarrier::gray_ptr_ == 1, "Expecting gray to have value 1"); +  static_assert(ReadBarrier::black_ptr_ == 2, "Expecting black to have value 2"); +  __ Lsrs(temp_reg, temp_reg, LockWord::kReadBarrierStateShift + 1); +  __ b(slow_path->GetEntryLabel(), CS);  // Carry flag is the last bit shifted out by LSRS.    __ Bind(slow_path->GetExitLabel());  } diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index c8d33d5743..7cdcea2895 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -4273,7 +4273,7 @@ void InstructionCodeGeneratorARM64::VisitLongConstant(HLongConstant* constant AT  void LocationsBuilderARM64::VisitMonitorOperation(HMonitorOperation* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(0)));  } @@ -4371,7 +4371,7 @@ void InstructionCodeGeneratorARM64::VisitNeg(HNeg* neg) {  void LocationsBuilderARM64::VisitNewArray(HNewArray* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->AddTemp(LocationFrom(calling_convention.GetRegisterAt(0)));    locations->SetOut(LocationFrom(x0)); @@ -4396,7 +4396,7 @@ void InstructionCodeGeneratorARM64::VisitNewArray(HNewArray* instruction) {  void LocationsBuilderARM64::VisitNewInstance(HNewInstance* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    if (instruction->IsStringAlloc()) {      locations->AddTemp(LocationFrom(kArtMethodRegister)); @@ -4549,7 +4549,8 @@ void InstructionCodeGeneratorARM64::VisitPhi(HPhi* instruction ATTRIBUTE_UNUSED)  void LocationsBuilderARM64::VisitRem(HRem* rem) {    Primitive::Type type = rem->GetResultType();    LocationSummary::CallKind call_kind = -      Primitive::IsFloatingPointType(type) ? LocationSummary::kCall : LocationSummary::kNoCall; +      Primitive::IsFloatingPointType(type) ? LocationSummary::kCallOnMainOnly +                                           : LocationSummary::kNoCall;    LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, call_kind);    switch (type) { @@ -4766,7 +4767,7 @@ void InstructionCodeGeneratorARM64::VisitSuspendCheck(HSuspendCheck* instruction  void LocationsBuilderARM64::VisitThrow(HThrow* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(0)));  } @@ -5206,23 +5207,12 @@ void CodeGeneratorARM64::GenerateReferenceLoadWithBakerReadBarrier(HInstruction*    // /* LockWord */ lock_word = LockWord(monitor)    static_assert(sizeof(LockWord) == sizeof(int32_t),                  "art::LockWord and int32_t have different sizes."); -  // /* uint32_t */ rb_state = lock_word.ReadBarrierState() -  __ Lsr(temp, temp, LockWord::kReadBarrierStateShift); -  __ And(temp, temp, Operand(LockWord::kReadBarrierStateMask)); -  static_assert( -      LockWord::kReadBarrierStateMask == ReadBarrier::rb_ptr_mask_, -      "art::LockWord::kReadBarrierStateMask is not equal to art::ReadBarrier::rb_ptr_mask_."); -  // Introduce a dependency on the high bits of rb_state, which shall -  // be all zeroes, to prevent load-load reordering, and without using +  // Introduce a dependency on the lock_word including rb_state, +  // to prevent load-load reordering, and without using    // a memory barrier (which would be more expensive). -  // temp2 = rb_state & ~LockWord::kReadBarrierStateMask = 0 -  Register temp2 = temps.AcquireW(); -  __ Bic(temp2, temp, Operand(LockWord::kReadBarrierStateMask)); -  // obj is unchanged by this operation, but its value now depends on -  // temp2, which depends on temp. -  __ Add(obj, obj, Operand(temp2)); -  temps.Release(temp2); +  // obj is unchanged by this operation, but its value now depends on temp. +  __ Add(obj.X(), obj.X(), Operand(temp.X(), LSR, 32));    // The actual reference load.    if (index.IsValid()) { @@ -5248,7 +5238,7 @@ void CodeGeneratorARM64::GenerateReferenceLoadWithBakerReadBarrier(HInstruction*          uint32_t computed_offset = offset + (Int64ConstantFrom(index) << scale_factor);          Load(type, ref_reg, HeapOperand(obj, computed_offset));        } else { -        temp2 = temps.AcquireW(); +        Register temp2 = temps.AcquireW();          __ Add(temp2, obj, offset);          Load(type, ref_reg, HeapOperand(temp2, XRegisterFrom(index), LSL, scale_factor));          temps.Release(temp2); @@ -5274,8 +5264,11 @@ void CodeGeneratorARM64::GenerateReferenceLoadWithBakerReadBarrier(HInstruction*    // if (rb_state == ReadBarrier::gray_ptr_)    //   ref = ReadBarrier::Mark(ref); -  __ Cmp(temp, ReadBarrier::gray_ptr_); -  __ B(eq, slow_path->GetEntryLabel()); +  // Given the numeric representation, it's enough to check the low bit of the rb_state. +  static_assert(ReadBarrier::white_ptr_ == 0, "Expecting white to have value 0"); +  static_assert(ReadBarrier::gray_ptr_ == 1, "Expecting gray to have value 1"); +  static_assert(ReadBarrier::black_ptr_ == 2, "Expecting black to have value 2"); +  __ Tbnz(temp, LockWord::kReadBarrierStateShift, slow_path->GetEntryLabel());    __ Bind(slow_path->GetExitLabel());  } diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc index b6dca95354..1038b2da3a 100644 --- a/compiler/optimizing/code_generator_mips.cc +++ b/compiler/optimizing/code_generator_mips.cc @@ -1855,7 +1855,7 @@ void LocationsBuilderMIPS::VisitArraySet(HArraySet* instruction) {    bool needs_runtime_call = instruction->NeedsTypeCheck();    LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(        instruction, -      needs_runtime_call ? LocationSummary::kCall : LocationSummary::kNoCall); +      needs_runtime_call ? LocationSummary::kCallOnMainOnly : LocationSummary::kNoCall);    if (needs_runtime_call) {      InvokeRuntimeCallingConvention calling_convention;      locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -2467,7 +2467,7 @@ void InstructionCodeGeneratorMIPS::GenerateDivRemIntegral(HBinaryOperation* inst  void LocationsBuilderMIPS::VisitDiv(HDiv* div) {    Primitive::Type type = div->GetResultType();    LocationSummary::CallKind call_kind = (type == Primitive::kPrimLong) -      ? LocationSummary::kCall +      ? LocationSummary::kCallOnMainOnly        : LocationSummary::kNoCall;    LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(div, call_kind); @@ -3430,7 +3430,7 @@ void LocationsBuilderMIPS::HandleFieldGet(HInstruction* instruction, const Field    bool is_wide = (field_type == Primitive::kPrimLong) || (field_type == Primitive::kPrimDouble);    bool generate_volatile = field_info.IsVolatile() && is_wide;    LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary( -      instruction, generate_volatile ? LocationSummary::kCall : LocationSummary::kNoCall); +      instruction, generate_volatile ? LocationSummary::kCallOnMainOnly : LocationSummary::kNoCall);    locations->SetInAt(0, Location::RequiresRegister());    if (generate_volatile) { @@ -3557,7 +3557,7 @@ void LocationsBuilderMIPS::HandleFieldSet(HInstruction* instruction, const Field    bool is_wide = (field_type == Primitive::kPrimLong) || (field_type == Primitive::kPrimDouble);    bool generate_volatile = field_info.IsVolatile() && is_wide;    LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary( -      instruction, generate_volatile ? LocationSummary::kCall : LocationSummary::kNoCall); +      instruction, generate_volatile ? LocationSummary::kCallOnMainOnly : LocationSummary::kNoCall);    locations->SetInAt(0, Location::RequiresRegister());    if (generate_volatile) { @@ -4218,7 +4218,7 @@ void InstructionCodeGeneratorMIPS::VisitLongConstant(HLongConstant* constant ATT  void LocationsBuilderMIPS::VisitMonitorOperation(HMonitorOperation* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));  } @@ -4397,7 +4397,7 @@ void InstructionCodeGeneratorMIPS::VisitNeg(HNeg* instruction) {  void LocationsBuilderMIPS::VisitNewArray(HNewArray* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));    locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(2))); @@ -4423,7 +4423,7 @@ void InstructionCodeGeneratorMIPS::VisitNewArray(HNewArray* instruction) {  void LocationsBuilderMIPS::VisitNewInstance(HNewInstance* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    if (instruction->IsStringAlloc()) {      locations->AddTemp(Location::RegisterLocation(kMethodRegisterArgument)); @@ -4593,7 +4593,7 @@ void InstructionCodeGeneratorMIPS::VisitPhi(HPhi* instruction ATTRIBUTE_UNUSED)  void LocationsBuilderMIPS::VisitRem(HRem* rem) {    Primitive::Type type = rem->GetResultType();    LocationSummary::CallKind call_kind = -      (type == Primitive::kPrimInt) ? LocationSummary::kNoCall : LocationSummary::kCall; +      (type == Primitive::kPrimInt) ? LocationSummary::kNoCall : LocationSummary::kCallOnMainOnly;    LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, call_kind);    switch (type) { @@ -4830,7 +4830,7 @@ void InstructionCodeGeneratorMIPS::VisitSuspendCheck(HSuspendCheck* instruction)  void LocationsBuilderMIPS::VisitThrow(HThrow* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));  } @@ -4859,7 +4859,7 @@ void LocationsBuilderMIPS::VisitTypeConversion(HTypeConversion* conversion) {    if (!isR6 &&        ((Primitive::IsFloatingPointType(result_type) && input_type == Primitive::kPrimLong) ||         (result_type == Primitive::kPrimLong && Primitive::IsFloatingPointType(input_type)))) { -    call_kind = LocationSummary::kCall; +    call_kind = LocationSummary::kCallOnMainOnly;    }    LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(conversion, call_kind); diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc index 9f2664c0a5..aa1ba84178 100644 --- a/compiler/optimizing/code_generator_mips64.cc +++ b/compiler/optimizing/code_generator_mips64.cc @@ -1436,7 +1436,7 @@ void LocationsBuilderMIPS64::VisitArraySet(HArraySet* instruction) {    bool needs_runtime_call = instruction->NeedsTypeCheck();    LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(        instruction, -      needs_runtime_call ? LocationSummary::kCall : LocationSummary::kNoCall); +      needs_runtime_call ? LocationSummary::kCallOnMainOnly : LocationSummary::kNoCall);    if (needs_runtime_call) {      InvokeRuntimeCallingConvention calling_convention;      locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -3292,7 +3292,7 @@ void InstructionCodeGeneratorMIPS64::VisitLongConstant(HLongConstant* constant A  void LocationsBuilderMIPS64::VisitMonitorOperation(HMonitorOperation* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));  } @@ -3419,7 +3419,7 @@ void InstructionCodeGeneratorMIPS64::VisitNeg(HNeg* instruction) {  void LocationsBuilderMIPS64::VisitNewArray(HNewArray* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));    locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimNot)); @@ -3440,7 +3440,7 @@ void InstructionCodeGeneratorMIPS64::VisitNewArray(HNewArray* instruction) {  void LocationsBuilderMIPS64::VisitNewInstance(HNewInstance* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    if (instruction->IsStringAlloc()) {      locations->AddTemp(Location::RegisterLocation(kMethodRegisterArgument)); @@ -3600,7 +3600,8 @@ void InstructionCodeGeneratorMIPS64::VisitPhi(HPhi* instruction ATTRIBUTE_UNUSED  void LocationsBuilderMIPS64::VisitRem(HRem* rem) {    Primitive::Type type = rem->GetResultType();    LocationSummary::CallKind call_kind = -      Primitive::IsFloatingPointType(type) ? LocationSummary::kCall : LocationSummary::kNoCall; +      Primitive::IsFloatingPointType(type) ? LocationSummary::kCallOnMainOnly +                                           : LocationSummary::kNoCall;    LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, call_kind);    switch (type) { @@ -3813,7 +3814,7 @@ void InstructionCodeGeneratorMIPS64::VisitSuspendCheck(HSuspendCheck* instructio  void LocationsBuilderMIPS64::VisitThrow(HThrow* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));  } diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index be20f1f7cc..3f69d0b8c7 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -140,12 +140,29 @@ class BoundsCheckSlowPathX86 : public SlowPathCode {        // Live registers will be restored in the catch block if caught.        SaveLiveRegisters(codegen, instruction_->GetLocations());      } + +    // Are we using an array length from memory? +    HInstruction* array_length = instruction_->InputAt(1); +    Location length_loc = locations->InAt(1);      InvokeRuntimeCallingConvention calling_convention; +    if (array_length->IsArrayLength() && array_length->IsEmittedAtUseSite()) { +      // Load the array length into our temporary. +      uint32_t len_offset = CodeGenerator::GetArrayLengthOffset(array_length->AsArrayLength()); +      Location array_loc = array_length->GetLocations()->InAt(0); +      Address array_len(array_loc.AsRegister<Register>(), len_offset); +      length_loc = Location::RegisterLocation(calling_convention.GetRegisterAt(1)); +      // Check for conflicts with index. +      if (length_loc.Equals(locations->InAt(0))) { +        // We know we aren't using parameter 2. +        length_loc = Location::RegisterLocation(calling_convention.GetRegisterAt(2)); +      } +      __ movl(length_loc.AsRegister<Register>(), array_len); +    }      x86_codegen->EmitParallelMoves(          locations->InAt(0),          Location::RegisterLocation(calling_convention.GetRegisterAt(0)),          Primitive::kPrimInt, -        locations->InAt(1), +        length_loc,          Location::RegisterLocation(calling_convention.GetRegisterAt(1)),          Primitive::kPrimInt);      uint32_t entry_point_offset = instruction_->AsBoundsCheck()->IsStringCharAt() @@ -2185,7 +2202,7 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) {    LocationSummary::CallKind call_kind =        ((input_type == Primitive::kPrimFloat || input_type == Primitive::kPrimDouble)         && result_type == Primitive::kPrimLong) -      ? LocationSummary::kCall +      ? LocationSummary::kCallOnMainOnly        : LocationSummary::kNoCall;    LocationSummary* locations =        new (GetGraph()->GetArena()) LocationSummary(conversion, call_kind); @@ -3440,7 +3457,7 @@ void InstructionCodeGeneratorX86::GenerateDivRemIntegral(HBinaryOperation* instr  void LocationsBuilderX86::VisitDiv(HDiv* div) {    LocationSummary::CallKind call_kind = (div->GetResultType() == Primitive::kPrimLong) -      ? LocationSummary::kCall +      ? LocationSummary::kCallOnMainOnly        : LocationSummary::kNoCall;    LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(div, call_kind); @@ -3543,7 +3560,7 @@ void LocationsBuilderX86::VisitRem(HRem* rem) {    Primitive::Type type = rem->GetResultType();    LocationSummary::CallKind call_kind = (rem->GetResultType() == Primitive::kPrimLong) -      ? LocationSummary::kCall +      ? LocationSummary::kCallOnMainOnly        : LocationSummary::kNoCall;    LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, call_kind); @@ -3985,7 +4002,7 @@ void InstructionCodeGeneratorX86::VisitUShr(HUShr* ushr) {  void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    locations->SetOut(Location::RegisterLocation(EAX));    if (instruction->IsStringAlloc()) {      locations->AddTemp(Location::RegisterLocation(kMethodRegisterArgument)); @@ -4018,7 +4035,7 @@ void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {  void LocationsBuilderX86::VisitNewArray(HNewArray* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    locations->SetOut(Location::RegisterLocation(EAX));    InvokeRuntimeCallingConvention calling_convention;    locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -5517,10 +5534,16 @@ void InstructionCodeGeneratorX86::VisitArraySet(HArraySet* instruction) {  void LocationsBuilderX86::VisitArrayLength(HArrayLength* instruction) {    LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);    locations->SetInAt(0, Location::RequiresRegister()); -  locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); +  if (!instruction->IsEmittedAtUseSite()) { +    locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); +  }  }  void InstructionCodeGeneratorX86::VisitArrayLength(HArrayLength* instruction) { +  if (instruction->IsEmittedAtUseSite()) { +    return; +  } +    LocationSummary* locations = instruction->GetLocations();    uint32_t offset = CodeGenerator::GetArrayLengthOffset(instruction);    Register obj = locations->InAt(0).AsRegister<Register>(); @@ -5535,7 +5558,10 @@ void LocationsBuilderX86::VisitBoundsCheck(HBoundsCheck* instruction) {        : LocationSummary::kNoCall;    LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);    locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0))); -  locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); +  HInstruction* length = instruction->InputAt(1); +  if (!length->IsEmittedAtUseSite()) { +    locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); +  }    if (instruction->HasUses()) {      locations->SetOut(Location::SameAsFirstInput());    } @@ -5569,12 +5595,28 @@ void InstructionCodeGeneratorX86::VisitBoundsCheck(HBoundsCheck* instruction) {      codegen_->AddSlowPath(slow_path);      __ j(kAboveEqual, slow_path->GetEntryLabel());    } else { -    Register length = length_loc.AsRegister<Register>(); -    if (index_loc.IsConstant()) { -      int32_t value = CodeGenerator::GetInt32ValueOf(index_loc.GetConstant()); -      __ cmpl(length, Immediate(value)); +    HInstruction* array_length = instruction->InputAt(1); +    if (array_length->IsEmittedAtUseSite()) { +      // Address the length field in the array. +      DCHECK(array_length->IsArrayLength()); +      uint32_t len_offset = CodeGenerator::GetArrayLengthOffset(array_length->AsArrayLength()); +      Location array_loc = array_length->GetLocations()->InAt(0); +      Address array_len(array_loc.AsRegister<Register>(), len_offset); +      if (index_loc.IsConstant()) { +        int32_t value = CodeGenerator::GetInt32ValueOf(index_loc.GetConstant()); +        __ cmpl(array_len, Immediate(value)); +      } else { +        __ cmpl(array_len, index_loc.AsRegister<Register>()); +      } +      codegen_->MaybeRecordImplicitNullCheck(array_length);      } else { -      __ cmpl(length, index_loc.AsRegister<Register>()); +      Register length = length_loc.AsRegister<Register>(); +      if (index_loc.IsConstant()) { +        int32_t value = CodeGenerator::GetInt32ValueOf(index_loc.GetConstant()); +        __ cmpl(length, Immediate(value)); +      } else { +        __ cmpl(length, index_loc.AsRegister<Register>()); +      }      }      codegen_->AddSlowPath(slow_path);      __ j(kBelowEqual, slow_path->GetEntryLabel()); @@ -6242,7 +6284,7 @@ void InstructionCodeGeneratorX86::VisitClearException(HClearException* clear ATT  void LocationsBuilderX86::VisitThrow(HThrow* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));  } @@ -6694,7 +6736,7 @@ void InstructionCodeGeneratorX86::VisitCheckCast(HCheckCast* instruction) {  void LocationsBuilderX86::VisitMonitorOperation(HMonitorOperation* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));  } diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index cac33cddb8..32e8ee9d0c 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -194,14 +194,31 @@ class BoundsCheckSlowPathX86_64 : public SlowPathCode {        // Live registers will be restored in the catch block if caught.        SaveLiveRegisters(codegen, instruction_->GetLocations());      } +    // Are we using an array length from memory? +    HInstruction* array_length = instruction_->InputAt(1); +    Location length_loc = locations->InAt(1); +    InvokeRuntimeCallingConvention calling_convention; +    if (array_length->IsArrayLength() && array_length->IsEmittedAtUseSite()) { +      // Load the array length into our temporary. +      uint32_t len_offset = CodeGenerator::GetArrayLengthOffset(array_length->AsArrayLength()); +      Location array_loc = array_length->GetLocations()->InAt(0); +      Address array_len(array_loc.AsRegister<CpuRegister>(), len_offset); +      length_loc = Location::RegisterLocation(calling_convention.GetRegisterAt(1)); +      // Check for conflicts with index. +      if (length_loc.Equals(locations->InAt(0))) { +        // We know we aren't using parameter 2. +        length_loc = Location::RegisterLocation(calling_convention.GetRegisterAt(2)); +      } +      __ movl(length_loc.AsRegister<CpuRegister>(), array_len); +    } +      // We're moving two locations to locations that could overlap, so we need a parallel      // move resolver. -    InvokeRuntimeCallingConvention calling_convention;      codegen->EmitParallelMoves(          locations->InAt(0),          Location::RegisterLocation(calling_convention.GetRegisterAt(0)),          Primitive::kPrimInt, -        locations->InAt(1), +        length_loc,          Location::RegisterLocation(calling_convention.GetRegisterAt(1)),          Primitive::kPrimInt);      uint32_t entry_point_offset = instruction_->AsBoundsCheck()->IsStringCharAt() @@ -3913,7 +3930,7 @@ void InstructionCodeGeneratorX86_64::VisitUShr(HUShr* ushr) {  void LocationsBuilderX86_64::VisitNewInstance(HNewInstance* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    if (instruction->IsStringAlloc()) {      locations->AddTemp(Location::RegisterLocation(kMethodRegisterArgument)); @@ -3946,7 +3963,7 @@ void InstructionCodeGeneratorX86_64::VisitNewInstance(HNewInstance* instruction)  void LocationsBuilderX86_64::VisitNewArray(HNewArray* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));    locations->SetOut(Location::RegisterLocation(RAX)); @@ -4987,10 +5004,16 @@ void LocationsBuilderX86_64::VisitArrayLength(HArrayLength* instruction) {    LocationSummary* locations =        new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);    locations->SetInAt(0, Location::RequiresRegister()); -  locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); +  if (!instruction->IsEmittedAtUseSite()) { +    locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); +  }  }  void InstructionCodeGeneratorX86_64::VisitArrayLength(HArrayLength* instruction) { +  if (instruction->IsEmittedAtUseSite()) { +    return; +  } +    LocationSummary* locations = instruction->GetLocations();    uint32_t offset = CodeGenerator::GetArrayLengthOffset(instruction);    CpuRegister obj = locations->InAt(0).AsRegister<CpuRegister>(); @@ -5005,7 +5028,10 @@ void LocationsBuilderX86_64::VisitBoundsCheck(HBoundsCheck* instruction) {        : LocationSummary::kNoCall;    LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);    locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0))); -  locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); +  HInstruction* length = instruction->InputAt(1); +  if (!length->IsEmittedAtUseSite()) { +    locations->SetInAt(1, Location::RegisterOrConstant(length)); +  }    if (instruction->HasUses()) {      locations->SetOut(Location::SameAsFirstInput());    } @@ -5015,8 +5041,7 @@ void InstructionCodeGeneratorX86_64::VisitBoundsCheck(HBoundsCheck* instruction)    LocationSummary* locations = instruction->GetLocations();    Location index_loc = locations->InAt(0);    Location length_loc = locations->InAt(1); -  SlowPathCode* slow_path = -      new (GetGraph()->GetArena()) BoundsCheckSlowPathX86_64(instruction); +  SlowPathCode* slow_path = new (GetGraph()->GetArena()) BoundsCheckSlowPathX86_64(instruction);    if (length_loc.IsConstant()) {      int32_t length = CodeGenerator::GetInt32ValueOf(length_loc.GetConstant()); @@ -5039,12 +5064,28 @@ void InstructionCodeGeneratorX86_64::VisitBoundsCheck(HBoundsCheck* instruction)      codegen_->AddSlowPath(slow_path);      __ j(kAboveEqual, slow_path->GetEntryLabel());    } else { -    CpuRegister length = length_loc.AsRegister<CpuRegister>(); -    if (index_loc.IsConstant()) { -      int32_t value = CodeGenerator::GetInt32ValueOf(index_loc.GetConstant()); -      __ cmpl(length, Immediate(value)); +    HInstruction* array_length = instruction->InputAt(1); +    if (array_length->IsEmittedAtUseSite()) { +      // Address the length field in the array. +      DCHECK(array_length->IsArrayLength()); +      uint32_t len_offset = CodeGenerator::GetArrayLengthOffset(array_length->AsArrayLength()); +      Location array_loc = array_length->GetLocations()->InAt(0); +      Address array_len(array_loc.AsRegister<CpuRegister>(), len_offset); +      if (index_loc.IsConstant()) { +        int32_t value = CodeGenerator::GetInt32ValueOf(index_loc.GetConstant()); +        __ cmpl(array_len, Immediate(value)); +      } else { +        __ cmpl(array_len, index_loc.AsRegister<CpuRegister>()); +      } +      codegen_->MaybeRecordImplicitNullCheck(array_length);      } else { -      __ cmpl(length, index_loc.AsRegister<CpuRegister>()); +      CpuRegister length = length_loc.AsRegister<CpuRegister>(); +      if (index_loc.IsConstant()) { +        int32_t value = CodeGenerator::GetInt32ValueOf(index_loc.GetConstant()); +        __ cmpl(length, Immediate(value)); +      } else { +        __ cmpl(length, index_loc.AsRegister<CpuRegister>()); +      }      }      codegen_->AddSlowPath(slow_path);      __ j(kBelowEqual, slow_path->GetEntryLabel()); @@ -5654,7 +5695,7 @@ void InstructionCodeGeneratorX86_64::VisitClearException(HClearException* clear  void LocationsBuilderX86_64::VisitThrow(HThrow* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));  } @@ -6164,7 +6205,7 @@ void InstructionCodeGeneratorX86_64::VisitCheckCast(HCheckCast* instruction) {  void LocationsBuilderX86_64::VisitMonitorOperation(HMonitorOperation* instruction) {    LocationSummary* locations = -      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); +      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));  } diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc index 9d67373321..e14f603fe1 100644 --- a/compiler/optimizing/graph_visualizer.cc +++ b/compiler/optimizing/graph_visualizer.cc @@ -401,6 +401,9 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {    void VisitArrayLength(HArrayLength* array_length) OVERRIDE {      StartAttributeStream("is_string_length") << std::boolalpha          << array_length->IsStringLength() << std::noboolalpha; +    if (array_length->IsEmittedAtUseSite()) { +      StartAttributeStream("emitted_at_use") << "true"; +    }    }    void VisitBoundsCheck(HBoundsCheck* bounds_check) OVERRIDE { diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index e0410dcdb2..4ca0600dba 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -920,6 +920,7 @@ void InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruct  void InstructionSimplifierVisitor::VisitAdd(HAdd* instruction) {    HConstant* input_cst = instruction->GetConstantRight();    HInstruction* input_other = instruction->GetLeastConstantLeft(); +  bool integral_type = Primitive::IsIntegralType(instruction->GetType());    if ((input_cst != nullptr) && input_cst->IsArithmeticZero()) {      // Replace code looking like      //    ADD dst, src, 0 @@ -928,7 +929,7 @@ void InstructionSimplifierVisitor::VisitAdd(HAdd* instruction) {      // Note that we cannot optimize `x + 0.0` to `x` for floating-point. When      // `x` is `-0.0`, the former expression yields `0.0`, while the later      // yields `-0.0`. -    if (Primitive::IsIntegralType(instruction->GetType())) { +    if (integral_type) {        instruction->ReplaceWith(input_other);        instruction->GetBlock()->RemoveInstruction(instruction);        RecordSimplification(); @@ -974,10 +975,31 @@ void InstructionSimplifierVisitor::VisitAdd(HAdd* instruction) {    // so no need to return.    TryHandleAssociativeAndCommutativeOperation(instruction); -  if ((instruction->GetLeft()->IsSub() || instruction->GetRight()->IsSub()) && +  if ((left->IsSub() || right->IsSub()) &&        TrySubtractionChainSimplification(instruction)) {      return;    } + +  if (integral_type) { +    // Replace code patterns looking like +    //    SUB dst1, x, y        SUB dst1, x, y +    //    ADD dst2, dst1, y     ADD dst2, y, dst1 +    // with +    //    SUB dst1, x, y +    // ADD instruction is not needed in this case, we may use +    // one of inputs of SUB instead. +    if (left->IsSub() && left->InputAt(1) == right) { +      instruction->ReplaceWith(left->InputAt(0)); +      RecordSimplification(); +      instruction->GetBlock()->RemoveInstruction(instruction); +      return; +    } else if (right->IsSub() && right->InputAt(1) == left) { +      instruction->ReplaceWith(right->InputAt(0)); +      RecordSimplification(); +      instruction->GetBlock()->RemoveInstruction(instruction); +      return; +    } +  }  }  void InstructionSimplifierVisitor::VisitAnd(HAnd* instruction) { @@ -1511,6 +1533,29 @@ void InstructionSimplifierVisitor::VisitSub(HSub* instruction) {    if (TrySubtractionChainSimplification(instruction)) {      return;    } + +  if (left->IsAdd()) { +    // Replace code patterns looking like +    //    ADD dst1, x, y        ADD dst1, x, y +    //    SUB dst2, dst1, y     SUB dst2, dst1, x +    // with +    //    ADD dst1, x, y +    // SUB instruction is not needed in this case, we may use +    // one of inputs of ADD instead. +    // It is applicable to integral types only. +    DCHECK(Primitive::IsIntegralType(type)); +    if (left->InputAt(1) == right) { +      instruction->ReplaceWith(left->InputAt(0)); +      RecordSimplification(); +      instruction->GetBlock()->RemoveInstruction(instruction); +      return; +    } else if (left->InputAt(0) == right) { +      instruction->ReplaceWith(left->InputAt(1)); +      RecordSimplification(); +      instruction->GetBlock()->RemoveInstruction(instruction); +      return; +    } +  }  }  void InstructionSimplifierVisitor::VisitUShr(HUShr* instruction) { diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc index 579fb9d3bb..bbdcee431a 100644 --- a/compiler/optimizing/intrinsics_arm.cc +++ b/compiler/optimizing/intrinsics_arm.cc @@ -1212,7 +1212,7 @@ static void GenerateVisitStringIndexOf(HInvoke* invoke,  void IntrinsicLocationsBuilderARM::VisitStringIndexOf(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    // We have a hand-crafted assembly stub that follows the runtime calling convention. So it's    // best to align the inputs accordingly. @@ -1232,7 +1232,7 @@ void IntrinsicCodeGeneratorARM::VisitStringIndexOf(HInvoke* invoke) {  void IntrinsicLocationsBuilderARM::VisitStringIndexOfAfter(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    // We have a hand-crafted assembly stub that follows the runtime calling convention. So it's    // best to align the inputs accordingly. @@ -1250,7 +1250,7 @@ void IntrinsicCodeGeneratorARM::VisitStringIndexOfAfter(HInvoke* invoke) {  void IntrinsicLocationsBuilderARM::VisitStringNewStringFromBytes(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -1280,7 +1280,7 @@ void IntrinsicCodeGeneratorARM::VisitStringNewStringFromBytes(HInvoke* invoke) {  void IntrinsicLocationsBuilderARM::VisitStringNewStringFromChars(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -1307,7 +1307,7 @@ void IntrinsicCodeGeneratorARM::VisitStringNewStringFromChars(HInvoke* invoke) {  void IntrinsicLocationsBuilderARM::VisitStringNewStringFromString(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -1665,7 +1665,7 @@ static void CreateFPToFPCallLocations(ArenaAllocator* arena, HInvoke* invoke) {    DCHECK_EQ(invoke->GetType(), Primitive::kPrimDouble);    LocationSummary* const locations = new (arena) LocationSummary(invoke, -                                                                 LocationSummary::kCall, +                                                                 LocationSummary::kCallOnMainOnly,                                                                   kIntrinsified);    const InvokeRuntimeCallingConvention calling_convention; @@ -1692,7 +1692,7 @@ static void CreateFPFPToFPCallLocations(ArenaAllocator* arena, HInvoke* invoke)    DCHECK_EQ(invoke->GetType(), Primitive::kPrimDouble);    LocationSummary* const locations = new (arena) LocationSummary(invoke, -                                                                 LocationSummary::kCall, +                                                                 LocationSummary::kCallOnMainOnly,                                                                   kIntrinsified);    const InvokeRuntimeCallingConvention calling_convention; diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc index 1d507530aa..16438a7594 100644 --- a/compiler/optimizing/intrinsics_arm64.cc +++ b/compiler/optimizing/intrinsics_arm64.cc @@ -1405,7 +1405,7 @@ static void GenerateVisitStringIndexOf(HInvoke* invoke,  void IntrinsicLocationsBuilderARM64::VisitStringIndexOf(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    // We have a hand-crafted assembly stub that follows the runtime calling convention. So it's    // best to align the inputs accordingly. @@ -1425,7 +1425,7 @@ void IntrinsicCodeGeneratorARM64::VisitStringIndexOf(HInvoke* invoke) {  void IntrinsicLocationsBuilderARM64::VisitStringIndexOfAfter(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    // We have a hand-crafted assembly stub that follows the runtime calling convention. So it's    // best to align the inputs accordingly. @@ -1443,7 +1443,7 @@ void IntrinsicCodeGeneratorARM64::VisitStringIndexOfAfter(HInvoke* invoke) {  void IntrinsicLocationsBuilderARM64::VisitStringNewStringFromBytes(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(0))); @@ -1473,7 +1473,7 @@ void IntrinsicCodeGeneratorARM64::VisitStringNewStringFromBytes(HInvoke* invoke)  void IntrinsicLocationsBuilderARM64::VisitStringNewStringFromChars(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(0))); @@ -1500,7 +1500,7 @@ void IntrinsicCodeGeneratorARM64::VisitStringNewStringFromChars(HInvoke* invoke)  void IntrinsicLocationsBuilderARM64::VisitStringNewStringFromString(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(0))); @@ -1531,7 +1531,7 @@ static void CreateFPToFPCallLocations(ArenaAllocator* arena, HInvoke* invoke) {    DCHECK(Primitive::IsFloatingPointType(invoke->GetType()));    LocationSummary* const locations = new (arena) LocationSummary(invoke, -                                                                 LocationSummary::kCall, +                                                                 LocationSummary::kCallOnMainOnly,                                                                   kIntrinsified);    InvokeRuntimeCallingConvention calling_convention; @@ -1546,7 +1546,7 @@ static void CreateFPFPToFPCallLocations(ArenaAllocator* arena, HInvoke* invoke)    DCHECK(Primitive::IsFloatingPointType(invoke->GetType()));    LocationSummary* const locations = new (arena) LocationSummary(invoke, -                                                                 LocationSummary::kCall, +                                                                 LocationSummary::kCallOnMainOnly,                                                                   kIntrinsified);    InvokeRuntimeCallingConvention calling_convention; diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc index d4f44d63e2..0bfa02512f 100644 --- a/compiler/optimizing/intrinsics_mips.cc +++ b/compiler/optimizing/intrinsics_mips.cc @@ -1875,7 +1875,7 @@ void IntrinsicCodeGeneratorMIPS::VisitUnsafeCASObject(HInvoke* invoke) {  // int java.lang.String.compareTo(String anotherString)  void IntrinsicLocationsBuilderMIPS::VisitStringCompareTo(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -2071,7 +2071,7 @@ static void GenerateStringIndexOf(HInvoke* invoke,  // int java.lang.String.indexOf(int ch)  void IntrinsicLocationsBuilderMIPS::VisitStringIndexOf(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    // We have a hand-crafted assembly stub that follows the runtime    // calling convention. So it's best to align the inputs accordingly. @@ -2096,7 +2096,7 @@ void IntrinsicCodeGeneratorMIPS::VisitStringIndexOf(HInvoke* invoke) {  // int java.lang.String.indexOf(int ch, int fromIndex)  void IntrinsicLocationsBuilderMIPS::VisitStringIndexOfAfter(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    // We have a hand-crafted assembly stub that follows the runtime    // calling convention. So it's best to align the inputs accordingly. @@ -2122,7 +2122,7 @@ void IntrinsicCodeGeneratorMIPS::VisitStringIndexOfAfter(HInvoke* invoke) {  // java.lang.StringFactory.newStringFromBytes(byte[] data, int high, int offset, int byteCount)  void IntrinsicLocationsBuilderMIPS::VisitStringNewStringFromBytes(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -2155,7 +2155,7 @@ void IntrinsicCodeGeneratorMIPS::VisitStringNewStringFromBytes(HInvoke* invoke)  // java.lang.StringFactory.newStringFromChars(int offset, int charCount, char[] data)  void IntrinsicLocationsBuilderMIPS::VisitStringNewStringFromChars(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -2187,7 +2187,7 @@ void IntrinsicCodeGeneratorMIPS::VisitStringNewStringFromChars(HInvoke* invoke)  // java.lang.StringFactory.newStringFromString(String toCopy)  void IntrinsicLocationsBuilderMIPS::VisitStringNewStringFromString(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); diff --git a/compiler/optimizing/intrinsics_mips64.cc b/compiler/optimizing/intrinsics_mips64.cc index cc4971b8f8..a9807bd0d2 100644 --- a/compiler/optimizing/intrinsics_mips64.cc +++ b/compiler/optimizing/intrinsics_mips64.cc @@ -1519,7 +1519,7 @@ void IntrinsicCodeGeneratorMIPS64::VisitUnsafeCASObject(HInvoke* invoke) {  // int java.lang.String.compareTo(String anotherString)  void IntrinsicLocationsBuilderMIPS64::VisitStringCompareTo(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -1707,7 +1707,7 @@ static void GenerateStringIndexOf(HInvoke* invoke,  // int java.lang.String.indexOf(int ch)  void IntrinsicLocationsBuilderMIPS64::VisitStringIndexOf(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    // We have a hand-crafted assembly stub that follows the runtime    // calling convention. So it's best to align the inputs accordingly. @@ -1728,7 +1728,7 @@ void IntrinsicCodeGeneratorMIPS64::VisitStringIndexOf(HInvoke* invoke) {  // int java.lang.String.indexOf(int ch, int fromIndex)  void IntrinsicLocationsBuilderMIPS64::VisitStringIndexOfAfter(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    // We have a hand-crafted assembly stub that follows the runtime    // calling convention. So it's best to align the inputs accordingly. @@ -1748,7 +1748,7 @@ void IntrinsicCodeGeneratorMIPS64::VisitStringIndexOfAfter(HInvoke* invoke) {  // java.lang.StringFactory.newStringFromBytes(byte[] data, int high, int offset, int byteCount)  void IntrinsicLocationsBuilderMIPS64::VisitStringNewStringFromBytes(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -1783,7 +1783,7 @@ void IntrinsicCodeGeneratorMIPS64::VisitStringNewStringFromBytes(HInvoke* invoke  // java.lang.StringFactory.newStringFromChars(int offset, int charCount, char[] data)  void IntrinsicLocationsBuilderMIPS64::VisitStringNewStringFromChars(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -1816,7 +1816,7 @@ void IntrinsicCodeGeneratorMIPS64::VisitStringNewStringFromChars(HInvoke* invoke  // java.lang.StringFactory.newStringFromString(String toCopy)  void IntrinsicLocationsBuilderMIPS64::VisitStringNewStringFromString(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc index 812bdf550e..6c81421713 100644 --- a/compiler/optimizing/intrinsics_x86.cc +++ b/compiler/optimizing/intrinsics_x86.cc @@ -706,7 +706,7 @@ static void CreateSSE41FPToFPLocations(ArenaAllocator* arena,    // We have to fall back to a call to the intrinsic.    LocationSummary* locations = new (arena) LocationSummary(invoke, -                                                           LocationSummary::kCall); +                                                           LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetFpuRegisterAt(0)));    locations->SetOut(Location::FpuRegisterLocation(XMM0)); @@ -774,7 +774,7 @@ void IntrinsicLocationsBuilderX86::VisitMathRoundFloat(HInvoke* invoke) {    // We have to fall back to a call to the intrinsic.    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                           LocationSummary::kCall); +                                                           LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetFpuRegisterAt(0)));    locations->SetOut(Location::RegisterLocation(EAX)); @@ -831,7 +831,7 @@ void IntrinsicCodeGeneratorX86::VisitMathRoundFloat(HInvoke* invoke) {  static void CreateFPToFPCallLocations(ArenaAllocator* arena,                                        HInvoke* invoke) {    LocationSummary* locations = new (arena) LocationSummary(invoke, -                                                           LocationSummary::kCall, +                                                           LocationSummary::kCallOnMainOnly,                                                             kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(0))); @@ -985,7 +985,7 @@ void IntrinsicCodeGeneratorX86::VisitMathTanh(HInvoke* invoke) {  static void CreateFPFPToFPCallLocations(ArenaAllocator* arena,                                          HInvoke* invoke) {    LocationSummary* locations = new (arena) LocationSummary(invoke, -                                                           LocationSummary::kCall, +                                                           LocationSummary::kCallOnMainOnly,                                                             kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(0))); @@ -1216,7 +1216,7 @@ void IntrinsicCodeGeneratorX86::VisitSystemArrayCopyChar(HInvoke* invoke) {  void IntrinsicLocationsBuilderX86::VisitStringCompareTo(HInvoke* invoke) {    // The inputs plus one temp.    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -1490,7 +1490,7 @@ void IntrinsicCodeGeneratorX86::VisitStringIndexOfAfter(HInvoke* invoke) {  void IntrinsicLocationsBuilderX86::VisitStringNewStringFromBytes(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -1518,7 +1518,7 @@ void IntrinsicCodeGeneratorX86::VisitStringNewStringFromBytes(HInvoke* invoke) {  void IntrinsicLocationsBuilderX86::VisitStringNewStringFromChars(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -1543,7 +1543,7 @@ void IntrinsicCodeGeneratorX86::VisitStringNewStringFromChars(HInvoke* invoke) {  void IntrinsicLocationsBuilderX86::VisitStringNewStringFromString(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc index 891aaf5ff9..28f1f4f15b 100644 --- a/compiler/optimizing/intrinsics_x86_64.cc +++ b/compiler/optimizing/intrinsics_x86_64.cc @@ -526,7 +526,7 @@ static void CreateSSE41FPToFPLocations(ArenaAllocator* arena,    // We have to fall back to a call to the intrinsic.    LocationSummary* locations = new (arena) LocationSummary(invoke, -                                                           LocationSummary::kCall); +                                                           LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetFpuRegisterAt(0)));    locations->SetOut(Location::FpuRegisterLocation(XMM0)); @@ -588,7 +588,7 @@ static void CreateSSE41FPToIntLocations(ArenaAllocator* arena,    // We have to fall back to a call to the intrinsic.    LocationSummary* locations = new (arena) LocationSummary(invoke, -                                                           LocationSummary::kCall); +                                                           LocationSummary::kCallOnMainOnly);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetFpuRegisterAt(0)));    locations->SetOut(Location::RegisterLocation(RAX)); @@ -699,7 +699,7 @@ void IntrinsicCodeGeneratorX86_64::VisitMathRoundDouble(HInvoke* invoke) {  static void CreateFPToFPCallLocations(ArenaAllocator* arena,                                        HInvoke* invoke) {    LocationSummary* locations = new (arena) LocationSummary(invoke, -                                                           LocationSummary::kCall, +                                                           LocationSummary::kCallOnMainOnly,                                                             kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(0))); @@ -839,7 +839,7 @@ void IntrinsicCodeGeneratorX86_64::VisitMathTanh(HInvoke* invoke) {  static void CreateFPFPToFPCallLocations(ArenaAllocator* arena,                                          HInvoke* invoke) {    LocationSummary* locations = new (arena) LocationSummary(invoke, -                                                           LocationSummary::kCall, +                                                           LocationSummary::kCallOnMainOnly,                                                             kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(0))); @@ -1303,7 +1303,7 @@ void IntrinsicCodeGeneratorX86_64::VisitSystemArrayCopy(HInvoke* invoke) {  void IntrinsicLocationsBuilderX86_64::VisitStringCompareTo(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -1577,7 +1577,7 @@ void IntrinsicCodeGeneratorX86_64::VisitStringIndexOfAfter(HInvoke* invoke) {  void IntrinsicLocationsBuilderX86_64::VisitStringNewStringFromBytes(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -1606,7 +1606,7 @@ void IntrinsicCodeGeneratorX86_64::VisitStringNewStringFromBytes(HInvoke* invoke  void IntrinsicLocationsBuilderX86_64::VisitStringNewStringFromChars(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); @@ -1632,7 +1632,7 @@ void IntrinsicCodeGeneratorX86_64::VisitStringNewStringFromChars(HInvoke* invoke  void IntrinsicLocationsBuilderX86_64::VisitStringNewStringFromString(HInvoke* invoke) {    LocationSummary* locations = new (arena_) LocationSummary(invoke, -                                                            LocationSummary::kCall, +                                                            LocationSummary::kCallOnMainOnly,                                                              kIntrinsified);    InvokeRuntimeCallingConvention calling_convention;    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); diff --git a/compiler/optimizing/locations.h b/compiler/optimizing/locations.h index 3f27c911be..7a78bfdc8d 100644 --- a/compiler/optimizing/locations.h +++ b/compiler/optimizing/locations.h @@ -481,7 +481,7 @@ class LocationSummary : public ArenaObject<kArenaAllocLocationSummary> {    enum CallKind {      kNoCall,      kCallOnSlowPath, -    kCall +    kCallOnMainOnly    };    LocationSummary(HInstruction* instruction, @@ -541,7 +541,7 @@ class LocationSummary : public ArenaObject<kArenaAllocLocationSummary> {    Location Out() const { return output_; }    bool CanCall() const { return call_kind_ != kNoCall; } -  bool WillCall() const { return call_kind_ == kCall; } +  bool WillCall() const { return call_kind_ == kCallOnMainOnly; }    bool OnlyCallsOnSlowPath() const { return call_kind_ == kCallOnSlowPath; }    bool NeedsSafepoint() const { return CanCall(); } diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index d703b0f94f..d6e09d7acb 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -37,6 +37,10 @@  #include "pc_relative_fixups_x86.h"  #endif +#if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64) +#include "x86_memory_gen.h" +#endif +  #include "art_method-inl.h"  #include "base/arena_allocator.h"  #include "base/arena_containers.h" @@ -485,13 +489,27 @@ static void RunArchOptimizations(InstructionSet instruction_set,      case kX86: {        x86::PcRelativeFixups* pc_relative_fixups =            new (arena) x86::PcRelativeFixups(graph, codegen, stats); +      x86::X86MemoryOperandGeneration* memory_gen = +          new(arena) x86::X86MemoryOperandGeneration(graph, stats, codegen);        HOptimization* x86_optimizations[] = { -          pc_relative_fixups +          pc_relative_fixups, +          memory_gen        };        RunOptimizations(x86_optimizations, arraysize(x86_optimizations), pass_observer);        break;      }  #endif +#ifdef ART_ENABLE_CODEGEN_x86_64 +    case kX86_64: { +      x86::X86MemoryOperandGeneration* memory_gen = +          new(arena) x86::X86MemoryOperandGeneration(graph, stats, codegen); +      HOptimization* x86_64_optimizations[] = { +          memory_gen +      }; +      RunOptimizations(x86_64_optimizations, arraysize(x86_64_optimizations), pass_observer); +      break; +    } +#endif      default:        break;    } diff --git a/compiler/optimizing/x86_memory_gen.cc b/compiler/optimizing/x86_memory_gen.cc new file mode 100644 index 0000000000..195159f61b --- /dev/null +++ b/compiler/optimizing/x86_memory_gen.cc @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "x86_memory_gen.h" +#include "code_generator.h" + +namespace art { +namespace x86 { + +/** + * Replace instructions with memory operand forms. + */ +class MemoryOperandVisitor : public HGraphVisitor { + public: +  MemoryOperandVisitor(HGraph* graph, bool do_implicit_null_checks) +      : HGraphVisitor(graph), +        do_implicit_null_checks_(do_implicit_null_checks) {} + + private: +  void VisitBoundsCheck(HBoundsCheck* check) OVERRIDE { +    // Replace the length by the array itself, so that we can do compares to memory. +    HArrayLength* array_len = check->InputAt(1)->AsArrayLength(); + +    // We only want to replace an ArrayLength. +    if (array_len == nullptr) { +      return; +    } + +    HInstruction* array = array_len->InputAt(0); +    DCHECK_EQ(array->GetType(), Primitive::kPrimNot); + +    // Don't apply this optimization when the array is nullptr. +    if (array->IsConstant() || (array->IsNullCheck() && array->InputAt(0)->IsConstant())) { +      return; +    } + +    // Is there a null check that could be an implicit check? +    if (array->IsNullCheck() && do_implicit_null_checks_) { +      // The ArrayLen may generate the implicit null check.  Can the +      // bounds check do so as well? +      if (array_len->GetNextDisregardingMoves() != check) { +        // No, it won't.  Leave as is. +        return; +      } +    } + +    // Can we suppress the ArrayLength and generate at BoundCheck? +    if (array_len->HasOnlyOneNonEnvironmentUse()) { +      array_len->MarkEmittedAtUseSite(); +      // We need the ArrayLength just before the BoundsCheck. +      array_len->MoveBefore(check); +    } +  } + +  bool do_implicit_null_checks_; +}; + +X86MemoryOperandGeneration::X86MemoryOperandGeneration(HGraph* graph, +                                                       OptimizingCompilerStats* stats, +                                                       CodeGenerator* codegen) +    : HOptimization(graph, kX86MemoryOperandGenerationPassName, stats), +      do_implicit_null_checks_(codegen->GetCompilerOptions().GetImplicitNullChecks()) { +} + +void X86MemoryOperandGeneration::Run() { +  MemoryOperandVisitor visitor(graph_, do_implicit_null_checks_); +  visitor.VisitInsertionOrder(); +} + +}  // namespace x86 +}  // namespace art diff --git a/compiler/optimizing/x86_memory_gen.h b/compiler/optimizing/x86_memory_gen.h new file mode 100644 index 0000000000..7e886819bb --- /dev/null +++ b/compiler/optimizing/x86_memory_gen.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_COMPILER_OPTIMIZING_X86_MEMORY_GEN_H_ +#define ART_COMPILER_OPTIMIZING_X86_MEMORY_GEN_H_ + +#include "nodes.h" +#include "optimization.h" + +namespace art { +class CodeGenerator; + +namespace x86 { + +class X86MemoryOperandGeneration : public HOptimization { + public: +  X86MemoryOperandGeneration(HGraph* graph, +                             OptimizingCompilerStats* stats, +                             CodeGenerator* codegen); + +  void Run() OVERRIDE; + +  static constexpr const char* kX86MemoryOperandGenerationPassName = +          "x86_memory_operand_generation"; + + private: +  bool do_implicit_null_checks_; +}; + +}  // namespace x86 +}  // namespace art + +#endif  // ART_COMPILER_OPTIMIZING_X86_MEMORY_GEN_H_  |