ARM: VIXL32: Fix some test failures.
Test: ART_USE_VIXL_ARM_BACKEND=true m test-art-host
Test: ART_USE_VIXL_ARM_BACKEND=true m test-art-target
Change-Id: I6cc179a56c967fc35936a5743a953013a2388c90
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index e399f32..bb6857d 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -2215,10 +2215,9 @@
break;
}
- // TODO(VIXL): https://android-review.googlesource.com/#/c/254144/
case Primitive::kPrimLong: {
locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::RequiresRegister());
+ locations->SetInAt(1, ArmEncodableConstantOrRegister(add->InputAt(1), ADD));
locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
break;
}
@@ -2248,11 +2247,15 @@
}
break;
- // TODO(VIXL): https://android-review.googlesource.com/#/c/254144/
case Primitive::kPrimLong: {
- DCHECK(second.IsRegisterPair());
- __ Adds(LowRegisterFrom(out), LowRegisterFrom(first), LowRegisterFrom(second));
- __ Adc(HighRegisterFrom(out), HighRegisterFrom(first), HighRegisterFrom(second));
+ if (second.IsConstant()) {
+ uint64_t value = static_cast<uint64_t>(Int64FromConstant(second.GetConstant()));
+ GenerateAddLongConst(out, first, value);
+ } else {
+ DCHECK(second.IsRegisterPair());
+ __ Adds(LowRegisterFrom(out), LowRegisterFrom(first), LowRegisterFrom(second));
+ __ Adc(HighRegisterFrom(out), HighRegisterFrom(first), HighRegisterFrom(second));
+ }
break;
}
@@ -2277,10 +2280,9 @@
break;
}
- // TODO(VIXL): https://android-review.googlesource.com/#/c/254144/
case Primitive::kPrimLong: {
locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::RequiresRegister());
+ locations->SetInAt(1, ArmEncodableConstantOrRegister(sub->InputAt(1), SUB));
locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
break;
}
@@ -2307,11 +2309,15 @@
break;
}
- // TODO(VIXL): https://android-review.googlesource.com/#/c/254144/
case Primitive::kPrimLong: {
- DCHECK(second.IsRegisterPair());
- __ Subs(LowRegisterFrom(out), LowRegisterFrom(first), LowRegisterFrom(second));
- __ Sbc(HighRegisterFrom(out), HighRegisterFrom(first), HighRegisterFrom(second));
+ if (second.IsConstant()) {
+ uint64_t value = static_cast<uint64_t>(Int64FromConstant(second.GetConstant()));
+ GenerateAddLongConst(out, first, -value);
+ } else {
+ DCHECK(second.IsRegisterPair());
+ __ Subs(LowRegisterFrom(out), LowRegisterFrom(first), LowRegisterFrom(second));
+ __ Sbc(HighRegisterFrom(out), HighRegisterFrom(first), HighRegisterFrom(second));
+ }
break;
}
@@ -2478,7 +2484,8 @@
int shift;
CalculateMagicAndShiftForDivRem(imm, false /* is_long */, &magic, &shift);
- __ Mov(temp1, Operand::From(magic));
+ // TODO(VIXL): Change the static cast to Operand::From() after VIXL is fixed.
+ __ Mov(temp1, static_cast<int32_t>(magic));
__ Smull(temp2, temp1, dividend, temp1);
if (imm > 0 && magic < 0) {
@@ -4215,6 +4222,7 @@
} else {
codegen_->LoadFromShiftedRegOffset(type, out_loc, temp, RegisterFrom(index));
}
+ temps.Release(temp);
}
break;
}
@@ -4254,6 +4262,7 @@
__ Add(temp, obj, data_offset);
}
codegen_->LoadFromShiftedRegOffset(type, out_loc, temp, RegisterFrom(index));
+ temps.Release(temp);
codegen_->MaybeRecordImplicitNullCheck(instruction);
// If read barriers are enabled, emit read barriers other than
@@ -4275,6 +4284,7 @@
vixl32::Register temp = temps.Acquire();
__ Add(temp, obj, Operand(RegisterFrom(index), vixl32::LSL, TIMES_8));
GetAssembler()->LoadFromOffset(kLoadWordPair, LowRegisterFrom(out_loc), temp, data_offset);
+ temps.Release(temp);
}
break;
}
@@ -4288,6 +4298,7 @@
vixl32::Register temp = temps.Acquire();
__ Add(temp, obj, Operand(RegisterFrom(index), vixl32::LSL, TIMES_4));
GetAssembler()->LoadSFromOffset(out, temp, data_offset);
+ temps.Release(temp);
}
break;
}
@@ -4300,6 +4311,7 @@
vixl32::Register temp = temps.Acquire();
__ Add(temp, obj, Operand(RegisterFrom(index), vixl32::LSL, TIMES_8));
GetAssembler()->LoadDFromOffset(DRegisterFrom(out_loc), temp, data_offset);
+ temps.Release(temp);
}
break;
}
@@ -4389,6 +4401,7 @@
__ Add(temp, array, data_offset);
}
codegen_->StoreToShiftedRegOffset(value_type, value_loc, temp, RegisterFrom(index));
+ temps.Release(temp);
}
break;
}
@@ -4410,6 +4423,7 @@
vixl32::Register temp = temps.Acquire();
__ Add(temp, array, data_offset);
codegen_->StoreToShiftedRegOffset(value_type, value_loc, temp, RegisterFrom(index));
+ temps.Release(temp);
}
codegen_->MaybeRecordImplicitNullCheck(instruction);
DCHECK(!needs_write_barrier);
@@ -4443,6 +4457,7 @@
vixl32::Register temp = temps.Acquire();
__ Add(temp, array, data_offset);
codegen_->StoreToShiftedRegOffset(value_type, value_loc, temp, RegisterFrom(index));
+ temps.Release(temp);
}
codegen_->MaybeRecordImplicitNullCheck(instruction);
__ B(&done);
@@ -4512,6 +4527,7 @@
LocationFrom(source),
temp,
RegisterFrom(index));
+ temps.Release(temp);
}
if (!may_need_runtime_call_for_type_check) {
@@ -4541,6 +4557,7 @@
vixl32::Register temp = temps.Acquire();
__ Add(temp, array, Operand(RegisterFrom(index), vixl32::LSL, TIMES_8));
GetAssembler()->StoreToOffset(kStoreWordPair, LowRegisterFrom(value), temp, data_offset);
+ temps.Release(temp);
}
break;
}
@@ -4555,6 +4572,7 @@
vixl32::Register temp = temps.Acquire();
__ Add(temp, array, Operand(RegisterFrom(index), vixl32::LSL, TIMES_4));
GetAssembler()->StoreSToOffset(SRegisterFrom(value), temp, data_offset);
+ temps.Release(temp);
}
break;
}
@@ -4569,6 +4587,7 @@
vixl32::Register temp = temps.Acquire();
__ Add(temp, array, Operand(RegisterFrom(index), vixl32::LSL, TIMES_8));
GetAssembler()->StoreDToOffset(DRegisterFrom(value), temp, data_offset);
+ temps.Release(temp);
}
break;
}
@@ -4904,9 +4923,12 @@
} else if (source.IsStackSlot() && destination.IsRegister()) {
Exchange(RegisterFrom(destination), source.GetStackIndex());
} else if (source.IsStackSlot() && destination.IsStackSlot()) {
- TODO_VIXL32(FATAL);
+ Exchange(source.GetStackIndex(), destination.GetStackIndex());
} else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
- TODO_VIXL32(FATAL);
+ vixl32::SRegister temp = temps.AcquireS();
+ __ Vmov(temp, SRegisterFrom(source));
+ __ Vmov(SRegisterFrom(source), SRegisterFrom(destination));
+ __ Vmov(SRegisterFrom(destination), temp);
} else if (source.IsRegisterPair() && destination.IsRegisterPair()) {
vixl32::DRegister temp = temps.AcquireD();
__ Vmov(temp, LowRegisterFrom(source), HighRegisterFrom(source));
@@ -4929,9 +4951,27 @@
__ Vmov(first, second);
__ Vmov(second, temp);
} else if (source.IsFpuRegisterPair() || destination.IsFpuRegisterPair()) {
- TODO_VIXL32(FATAL);
+ vixl32::DRegister reg = source.IsFpuRegisterPair()
+ ? DRegisterFrom(source)
+ : DRegisterFrom(destination);
+ int mem = source.IsFpuRegisterPair()
+ ? destination.GetStackIndex()
+ : source.GetStackIndex();
+ vixl32::DRegister temp = temps.AcquireD();
+ __ Vmov(temp, reg);
+ GetAssembler()->LoadDFromOffset(reg, sp, mem);
+ GetAssembler()->StoreDToOffset(temp, sp, mem);
} else if (source.IsFpuRegister() || destination.IsFpuRegister()) {
- TODO_VIXL32(FATAL);
+ vixl32::SRegister reg = source.IsFpuRegister()
+ ? SRegisterFrom(source)
+ : SRegisterFrom(destination);
+ int mem = source.IsFpuRegister()
+ ? destination.GetStackIndex()
+ : source.GetStackIndex();
+ vixl32::Register temp = temps.Acquire();
+ __ Vmov(temp, reg);
+ GetAssembler()->LoadSFromOffset(reg, sp, mem);
+ GetAssembler()->StoreToOffset(kStoreWord, temp, sp, mem);
} else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
vixl32::DRegister temp1 = temps.AcquireD();
vixl32::DRegister temp2 = temps.AcquireD();
@@ -5715,6 +5755,33 @@
__ Eor(out, first, value);
}
+void InstructionCodeGeneratorARMVIXL::GenerateAddLongConst(Location out,
+ Location first,
+ uint64_t value) {
+ vixl32::Register out_low = LowRegisterFrom(out);
+ vixl32::Register out_high = HighRegisterFrom(out);
+ vixl32::Register first_low = LowRegisterFrom(first);
+ vixl32::Register first_high = HighRegisterFrom(first);
+ uint32_t value_low = Low32Bits(value);
+ uint32_t value_high = High32Bits(value);
+ if (value_low == 0u) {
+ if (!out_low.Is(first_low)) {
+ __ Mov(out_low, first_low);
+ }
+ __ Add(out_high, first_high, value_high);
+ return;
+ }
+ __ Adds(out_low, first_low, value_low);
+ if (GetAssembler()->ShifterOperandCanHold(ADC, value_high, kCcKeep)) {
+ __ Adc(out_high, first_high, value_high);
+ } else if (GetAssembler()->ShifterOperandCanHold(SBC, ~value_high, kCcKeep)) {
+ __ Sbc(out_high, first_high, ~value_high);
+ } else {
+ LOG(FATAL) << "Unexpected constant " << value_high;
+ UNREACHABLE();
+ }
+}
+
void InstructionCodeGeneratorARMVIXL::HandleBitwiseOperation(HBinaryOperation* instruction) {
LocationSummary* locations = instruction->GetLocations();
Location first = locations->InAt(0);
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index 38c756f..89fef43 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -386,6 +386,7 @@
void GenerateAndConst(vixl::aarch32::Register out, vixl::aarch32::Register first, uint32_t value);
void GenerateOrrConst(vixl::aarch32::Register out, vixl::aarch32::Register first, uint32_t value);
void GenerateEorConst(vixl::aarch32::Register out, vixl::aarch32::Register first, uint32_t value);
+ void GenerateAddLongConst(Location out, Location first, uint64_t value);
void HandleBitwiseOperation(HBinaryOperation* operation);
void HandleCondition(HCondition* condition);
void HandleIntegerRotate(HRor* ror);
diff --git a/test/538-checker-embed-constants/src/Main.java b/test/538-checker-embed-constants/src/Main.java
index 6b25747..0329e63 100644
--- a/test/538-checker-embed-constants/src/Main.java
+++ b/test/538-checker-embed-constants/src/Main.java
@@ -105,7 +105,7 @@
/// CHECK-NOT: and{{(\.w)?}}
/// CHECK-NOT: bic{{(\.w)?}}
/// CHECK-DAG: and {{r\d+}}, {{r\d+}}, #0xff
- /// CHECK-DAG: movs {{r\d+}}, #0
+ /// CHECK-DAG: mov{{s?}} {{r\d+}}, #0
/// CHECK-NOT: and{{(\.w)?}}
/// CHECK-NOT: bic{{(\.w)?}}
@@ -115,7 +115,7 @@
/// CHECK-START-ARM: long Main.and511(long) disassembly (after)
/// CHECK: mov {{r\d+}}, #511
- /// CHECK-NEXT: movs {{r\d+}}, #0
+ /// CHECK-NEXT: mov{{s?}} {{r\d+}}, #0
/// CHECK-NOT: and{{(\.w)?}}
/// CHECK-NOT: bic{{(\.w)?}}
/// CHECK: and{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
@@ -167,7 +167,7 @@
/// CHECK-START-ARM: long Main.or511(long) disassembly (after)
/// CHECK: mov {{r\d+}}, #511
- /// CHECK-NEXT: movs {{r\d+}}, #0
+ /// CHECK-NEXT: mov{{s?}} {{r\d+}}, #0
/// CHECK-NOT: orr{{(\.w)?}}
/// CHECK-NOT: orn
/// CHECK: orr{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
@@ -218,7 +218,7 @@
/// CHECK-START-ARM: long Main.xor511(long) disassembly (after)
/// CHECK: mov {{r\d+}}, #511
- /// CHECK-NEXT: movs {{r\d+}}, #0
+ /// CHECK-NEXT: mov{{s?}} {{r\d+}}, #0
/// CHECK-NOT: eor{{(\.w)?}}
/// CHECK: eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
/// CHECK-NEXT: eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
@@ -242,7 +242,7 @@
// Note: No support for partial long constant embedding.
/// CHECK-START-ARM: long Main.xor0xfffffff00000000f(long) disassembly (after)
- /// CHECK-DAG: movs {{r\d+}}, #15
+ /// CHECK-DAG: mov{{s?}} {{r\d+}}, #15
/// CHECK-DAG: mvn {{r\d+}}, #15
/// CHECK-NOT: eor{{(\.w)?}}
/// CHECK-DAG: eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
@@ -507,7 +507,7 @@
/// CHECK: <<Arg:j\d+>> ParameterValue
/// CHECK: <<ConstM1:j\d+>> LongConstant -1
/// CHECK: Add [<<Arg>>,<<ConstM1>>]
- /// CHECK-NEXT: subs r{{\d+}}, #1
+ /// CHECK-NEXT: {{adds|subs}} r{{\d+}}, #{{4294967295|1}}
/// CHECK-NEXT: adc r{{\d+}}, r{{\d+}}, #4294967295
/// CHECK: Sub [<<Arg>>,<<ConstM1>>]
/// CHECK-NEXT: adds r{{\d+}}, #1
diff --git a/test/Android.arm_vixl.mk b/test/Android.arm_vixl.mk
index 21b31b4..72616a1 100644
--- a/test/Android.arm_vixl.mk
+++ b/test/Android.arm_vixl.mk
@@ -16,36 +16,9 @@
# Known broken tests for the ARM VIXL backend.
TEST_ART_BROKEN_OPTIMIZING_ARM_VIXL_RUN_TESTS := \
- 003-omnibus-opcodes \
- 020-string \
- 021-string2 \
- 042-new-instance \
- 044-proxy \
- 080-oom-throw \
- 082-inline-execute \
- 096-array-copy-concurrent-gc \
- 099-vmdebug \
- 100-reflect2 \
103-string-append \
- 114-ParallelGC \
- 122-npe \
- 129-ThreadGetId \
137-cfi \
- 144-static-field-sigquit \
- 412-new-array \
- 439-npe \
- 450-checker-types \
488-checker-inline-recursive-calls \
- 515-dce-dominator \
- 520-equivalent-phi \
- 525-checker-arrays-fields1 \
- 525-checker-arrays-fields2 \
- 527-checker-array-access-split \
- 538-checker-embed-constants \
552-checker-sharpening \
562-checker-no-intermediate \
- 570-checker-osr \
602-deoptimizeable \
- 700-LoadArgRegs \
- 800-smali \
-