ART: Introduce Uint8 compiler data type.
This CL adds all the necessary codegen for the Uint8 type
but does not add code transformations that use that code.
Vectorization codegens are modified to use Uint8 as the
packed type when appropriate. The side effects are now
disconnected from the instruction's type after the graph has
been built to allow changing HArrayGet/H*FieldGet/HVecLoad
to use a type different from the underlying field or array.
Note: HArrayGet for String.charAt() is modified to have
no side effects whatsoever; Strings are immutable.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing --jit
Test: testrunner.py --target --optimizing on Nexus 6P
Test: Nexus 6P boots.
Bug: 23964345
Change-Id: If2dfffedcfb1f50db24570a1e9bd517b3f17bfd0
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 42e9f68..468e93a 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -1929,17 +1929,18 @@
const MemOperand& src) {
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
__ Ldrb(Register(dst), src);
break;
case DataType::Type::kInt8:
__ Ldrsb(Register(dst), src);
break;
- case DataType::Type::kInt16:
- __ Ldrsh(Register(dst), src);
- break;
case DataType::Type::kUint16:
__ Ldrh(Register(dst), src);
break;
+ case DataType::Type::kInt16:
+ __ Ldrsh(Register(dst), src);
+ break;
case DataType::Type::kInt32:
case DataType::Type::kReference:
case DataType::Type::kInt64:
@@ -1972,14 +1973,7 @@
MemOperand base = MemOperand(temp_base);
switch (type) {
case DataType::Type::kBool:
- {
- ExactAssemblyScope eas(masm, kInstructionSize, CodeBufferCheckScope::kExactSize);
- __ ldarb(Register(dst), base);
- if (needs_null_check) {
- MaybeRecordImplicitNullCheck(instruction);
- }
- }
- break;
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
{
ExactAssemblyScope eas(masm, kInstructionSize, CodeBufferCheckScope::kExactSize);
@@ -1988,17 +1982,11 @@
MaybeRecordImplicitNullCheck(instruction);
}
}
- __ Sbfx(Register(dst), Register(dst), 0, DataType::Size(type) * kBitsPerByte);
- break;
- case DataType::Type::kUint16:
- {
- ExactAssemblyScope eas(masm, kInstructionSize, CodeBufferCheckScope::kExactSize);
- __ ldarh(Register(dst), base);
- if (needs_null_check) {
- MaybeRecordImplicitNullCheck(instruction);
- }
+ if (type == DataType::Type::kInt8) {
+ __ Sbfx(Register(dst), Register(dst), 0, DataType::Size(type) * kBitsPerByte);
}
break;
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
{
ExactAssemblyScope eas(masm, kInstructionSize, CodeBufferCheckScope::kExactSize);
@@ -2007,7 +1995,9 @@
MaybeRecordImplicitNullCheck(instruction);
}
}
- __ Sbfx(Register(dst), Register(dst), 0, DataType::Size(type) * kBitsPerByte);
+ if (type == DataType::Type::kInt16) {
+ __ Sbfx(Register(dst), Register(dst), 0, DataType::Size(type) * kBitsPerByte);
+ }
break;
case DataType::Type::kInt32:
case DataType::Type::kReference:
@@ -2048,6 +2038,7 @@
const MemOperand& dst) {
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
__ Strb(Register(src), dst);
break;
@@ -2087,6 +2078,7 @@
// Ensure that between store and MaybeRecordImplicitNullCheck there are no pools emitted.
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
{
ExactAssemblyScope eas(masm, kInstructionSize, CodeBufferCheckScope::kExactSize);
@@ -3222,9 +3214,10 @@
DataType::Type in_type = compare->InputAt(0)->GetType();
switch (in_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32:
case DataType::Type::kInt64: {
locations->SetInAt(0, Location::RequiresRegister());
@@ -3255,9 +3248,10 @@
// -1 if: left < right
switch (in_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32:
case DataType::Type::kInt64: {
Register result = OutputRegister(compare);
@@ -5744,7 +5738,8 @@
new (GetGraph()->GetArena()) LocationSummary(conversion, LocationSummary::kNoCall);
DataType::Type input_type = conversion->GetInputType();
DataType::Type result_type = conversion->GetResultType();
- DCHECK_NE(input_type, result_type);
+ DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type))
+ << input_type << " -> " << result_type;
if ((input_type == DataType::Type::kReference) || (input_type == DataType::Type::kVoid) ||
(result_type == DataType::Type::kReference) || (result_type == DataType::Type::kVoid)) {
LOG(FATAL) << "Unexpected type conversion from " << input_type << " to " << result_type;
@@ -5767,7 +5762,8 @@
DataType::Type result_type = conversion->GetResultType();
DataType::Type input_type = conversion->GetInputType();
- DCHECK_NE(input_type, result_type);
+ DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type))
+ << input_type << " -> " << result_type;
if (DataType::IsIntegralType(result_type) && DataType::IsIntegralType(input_type)) {
int result_size = DataType::Size(result_type);
@@ -5784,11 +5780,9 @@
// 32bit input value as a 64bit value assuming that the top 32 bits are
// zero.
__ Mov(output.W(), source.W());
- } else if (result_type == DataType::Type::kUint16 ||
- (input_type == DataType::Type::kUint16 && input_size < result_size)) {
- __ Ubfx(output,
- output.IsX() ? source.X() : source.W(),
- 0, DataType::Size(DataType::Type::kUint16) * kBitsPerByte);
+ } else if (DataType::IsUnsignedType(result_type) ||
+ (DataType::IsUnsignedType(input_type) && input_size < result_size)) {
+ __ Ubfx(output, output.IsX() ? source.X() : source.W(), 0, result_size * kBitsPerByte);
} else {
__ Sbfx(output, output.IsX() ? source.X() : source.W(), 0, min_size * kBitsPerByte);
}
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 2b9e0fe..d4fb064 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -282,6 +282,58 @@
return stack_offset;
}
+static LoadOperandType GetLoadOperandType(DataType::Type type) {
+ switch (type) {
+ case DataType::Type::kReference:
+ return kLoadWord;
+ case DataType::Type::kBool:
+ case DataType::Type::kUint8:
+ return kLoadUnsignedByte;
+ case DataType::Type::kInt8:
+ return kLoadSignedByte;
+ case DataType::Type::kUint16:
+ return kLoadUnsignedHalfword;
+ case DataType::Type::kInt16:
+ return kLoadSignedHalfword;
+ case DataType::Type::kInt32:
+ return kLoadWord;
+ case DataType::Type::kInt64:
+ return kLoadWordPair;
+ case DataType::Type::kFloat32:
+ return kLoadSWord;
+ case DataType::Type::kFloat64:
+ return kLoadDWord;
+ default:
+ LOG(FATAL) << "Unreachable type " << type;
+ UNREACHABLE();
+ }
+}
+
+static StoreOperandType GetStoreOperandType(DataType::Type type) {
+ switch (type) {
+ case DataType::Type::kReference:
+ return kStoreWord;
+ case DataType::Type::kBool:
+ case DataType::Type::kUint8:
+ case DataType::Type::kInt8:
+ return kStoreByte;
+ case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
+ return kStoreHalfword;
+ case DataType::Type::kInt32:
+ return kStoreWord;
+ case DataType::Type::kInt64:
+ return kStoreWordPair;
+ case DataType::Type::kFloat32:
+ return kStoreSWord;
+ case DataType::Type::kFloat64:
+ return kStoreDWord;
+ default:
+ LOG(FATAL) << "Unreachable type " << type;
+ UNREACHABLE();
+ }
+}
+
void SlowPathCodeARMVIXL::SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) {
size_t stack_offset = codegen->GetFirstRegisterSlotInSlowPath();
size_t orig_offset = stack_offset;
@@ -2598,12 +2650,13 @@
Location InvokeDexCallingConventionVisitorARMVIXL::GetNextLocation(DataType::Type type) {
switch (type) {
+ case DataType::Type::kReference:
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
- case DataType::Type::kInt32:
- case DataType::Type::kReference: {
+ case DataType::Type::kInt32: {
uint32_t index = gp_index_++;
uint32_t stack_index = stack_index_++;
if (index < calling_convention.GetNumberOfRegisters()) {
@@ -2674,12 +2727,13 @@
Location InvokeDexCallingConventionVisitorARMVIXL::GetReturnLocation(DataType::Type type) const {
switch (type) {
+ case DataType::Type::kReference:
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
- case DataType::Type::kInt32:
- case DataType::Type::kReference: {
+ case DataType::Type::kInt32: {
return LocationFrom(r0);
}
@@ -3728,7 +3782,8 @@
void LocationsBuilderARMVIXL::VisitTypeConversion(HTypeConversion* conversion) {
DataType::Type result_type = conversion->GetResultType();
DataType::Type input_type = conversion->GetInputType();
- DCHECK_NE(result_type, input_type);
+ DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type))
+ << input_type << " -> " << result_type;
// The float-to-long, double-to-long and long-to-float type conversions
// rely on a call to the runtime.
@@ -3741,67 +3796,30 @@
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(conversion, call_kind);
- // The Java language does not allow treating boolean as an integral type but
- // our bit representation makes it safe.
-
switch (result_type) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- switch (input_type) {
- case DataType::Type::kInt64:
- // Type conversion from long to byte is a result of code transformations.
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
- case DataType::Type::kInt16:
- case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-byte' instruction.
- locations->SetInAt(0, Location::RequiresRegister());
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
- break;
-
- default:
- LOG(FATAL) << "Unexpected type conversion from " << input_type
- << " to " << result_type;
- }
- break;
-
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
- switch (input_type) {
- case DataType::Type::kInt64:
- // Type conversion from long to short is a result of code transformations.
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
- case DataType::Type::kInt8:
- case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-short' instruction.
- locations->SetInAt(0, Location::RequiresRegister());
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
- break;
-
- default:
- LOG(FATAL) << "Unexpected type conversion from " << input_type
- << " to " << result_type;
- }
+ DCHECK(DataType::IsIntegralType(input_type)) << input_type;
+ locations->SetInAt(0, Location::RequiresRegister());
+ locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
break;
case DataType::Type::kInt32:
switch (input_type) {
case DataType::Type::kInt64:
- // Processing a Dex `long-to-int' instruction.
locations->SetInAt(0, Location::Any());
locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
break;
case DataType::Type::kFloat32:
- // Processing a Dex `float-to-int' instruction.
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetOut(Location::RequiresRegister());
locations->AddTemp(Location::RequiresFpuRegister());
break;
case DataType::Type::kFloat64:
- // Processing a Dex `double-to-int' instruction.
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetOut(Location::RequiresRegister());
locations->AddTemp(Location::RequiresFpuRegister());
@@ -3816,18 +3834,16 @@
case DataType::Type::kInt64:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-long' instruction.
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
break;
case DataType::Type::kFloat32: {
- // Processing a Dex `float-to-long' instruction.
InvokeRuntimeCallingConventionARMVIXL calling_convention;
locations->SetInAt(0, LocationFrom(calling_convention.GetFpuRegisterAt(0)));
locations->SetOut(LocationFrom(r0, r1));
@@ -3835,7 +3851,6 @@
}
case DataType::Type::kFloat64: {
- // Processing a Dex `double-to-long' instruction.
InvokeRuntimeCallingConventionARMVIXL calling_convention;
locations->SetInAt(0, LocationFrom(calling_convention.GetFpuRegisterAt(0),
calling_convention.GetFpuRegisterAt(1)));
@@ -3849,41 +3864,19 @@
}
break;
- case DataType::Type::kUint16:
- switch (input_type) {
- case DataType::Type::kInt64:
- // Type conversion from long to char is a result of code transformations.
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
- case DataType::Type::kInt8:
- case DataType::Type::kInt16:
- case DataType::Type::kInt32:
- // Processing a Dex `int-to-char' instruction.
- locations->SetInAt(0, Location::RequiresRegister());
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
- break;
-
- default:
- LOG(FATAL) << "Unexpected type conversion from " << input_type
- << " to " << result_type;
- }
- break;
-
case DataType::Type::kFloat32:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-float' instruction.
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::RequiresFpuRegister());
break;
case DataType::Type::kInt64: {
- // Processing a Dex `long-to-float' instruction.
InvokeRuntimeCallingConventionARMVIXL calling_convention;
locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(0),
calling_convention.GetRegisterAt(1)));
@@ -3892,7 +3885,6 @@
}
case DataType::Type::kFloat64:
- // Processing a Dex `double-to-float' instruction.
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
break;
@@ -3906,18 +3898,16 @@
case DataType::Type::kFloat64:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-double' instruction.
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::RequiresFpuRegister());
break;
case DataType::Type::kInt64:
- // Processing a Dex `long-to-double' instruction.
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::RequiresFpuRegister());
locations->AddTemp(Location::RequiresFpuRegister());
@@ -3925,7 +3915,6 @@
break;
case DataType::Type::kFloat32:
- // Processing a Dex `float-to-double' instruction.
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
break;
@@ -3948,22 +3937,55 @@
Location in = locations->InAt(0);
DataType::Type result_type = conversion->GetResultType();
DataType::Type input_type = conversion->GetInputType();
- DCHECK_NE(result_type, input_type);
+ DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type))
+ << input_type << " -> " << result_type;
switch (result_type) {
- case DataType::Type::kInt8:
+ case DataType::Type::kUint8:
switch (input_type) {
- case DataType::Type::kInt64:
- // Type conversion from long to byte is a result of code transformations.
- __ Sbfx(OutputRegister(conversion), LowRegisterFrom(in), 0, 8);
- break;
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
+ __ Ubfx(OutputRegister(conversion), InputRegisterAt(conversion, 0), 0, 8);
+ break;
+ case DataType::Type::kInt64:
+ __ Ubfx(OutputRegister(conversion), LowRegisterFrom(in), 0, 8);
+ break;
+
+ default:
+ LOG(FATAL) << "Unexpected type conversion from " << input_type
+ << " to " << result_type;
+ }
+ break;
+
+ case DataType::Type::kInt8:
+ switch (input_type) {
+ case DataType::Type::kUint8:
case DataType::Type::kUint16:
- // Processing a Dex `int-to-byte' instruction.
+ case DataType::Type::kInt16:
+ case DataType::Type::kInt32:
__ Sbfx(OutputRegister(conversion), InputRegisterAt(conversion, 0), 0, 8);
break;
+ case DataType::Type::kInt64:
+ __ Sbfx(OutputRegister(conversion), LowRegisterFrom(in), 0, 8);
+ break;
+
+ default:
+ LOG(FATAL) << "Unexpected type conversion from " << input_type
+ << " to " << result_type;
+ }
+ break;
+
+ case DataType::Type::kUint16:
+ switch (input_type) {
+ case DataType::Type::kInt8:
+ case DataType::Type::kInt16:
+ case DataType::Type::kInt32:
+ __ Ubfx(OutputRegister(conversion), InputRegisterAt(conversion, 0), 0, 16);
+ break;
+ case DataType::Type::kInt64:
+ __ Ubfx(OutputRegister(conversion), LowRegisterFrom(in), 0, 16);
+ break;
default:
LOG(FATAL) << "Unexpected type conversion from " << input_type
@@ -3973,18 +3995,13 @@
case DataType::Type::kInt16:
switch (input_type) {
- case DataType::Type::kInt64:
- // Type conversion from long to short is a result of code transformations.
- __ Sbfx(OutputRegister(conversion), LowRegisterFrom(in), 0, 16);
- break;
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
- case DataType::Type::kInt8:
- case DataType::Type::kInt32:
case DataType::Type::kUint16:
- // Processing a Dex `int-to-short' instruction.
+ case DataType::Type::kInt32:
__ Sbfx(OutputRegister(conversion), InputRegisterAt(conversion, 0), 0, 16);
break;
+ case DataType::Type::kInt64:
+ __ Sbfx(OutputRegister(conversion), LowRegisterFrom(in), 0, 16);
+ break;
default:
LOG(FATAL) << "Unexpected type conversion from " << input_type
@@ -3995,7 +4012,6 @@
case DataType::Type::kInt32:
switch (input_type) {
case DataType::Type::kInt64:
- // Processing a Dex `long-to-int' instruction.
DCHECK(out.IsRegister());
if (in.IsRegisterPair()) {
__ Mov(OutputRegister(conversion), LowRegisterFrom(in));
@@ -4013,7 +4029,6 @@
break;
case DataType::Type::kFloat32: {
- // Processing a Dex `float-to-int' instruction.
vixl32::SRegister temp = LowSRegisterFrom(locations->GetTemp(0));
__ Vcvt(S32, F32, temp, InputSRegisterAt(conversion, 0));
__ Vmov(OutputRegister(conversion), temp);
@@ -4021,7 +4036,6 @@
}
case DataType::Type::kFloat64: {
- // Processing a Dex `double-to-int' instruction.
vixl32::SRegister temp_s = LowSRegisterFrom(locations->GetTemp(0));
__ Vcvt(S32, F64, temp_s, DRegisterFrom(in));
__ Vmov(OutputRegister(conversion), temp_s);
@@ -4037,12 +4051,11 @@
case DataType::Type::kInt64:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-long' instruction.
DCHECK(out.IsRegisterPair());
DCHECK(in.IsRegister());
__ Mov(LowRegisterFrom(out), InputRegisterAt(conversion, 0));
@@ -4051,13 +4064,11 @@
break;
case DataType::Type::kFloat32:
- // Processing a Dex `float-to-long' instruction.
codegen_->InvokeRuntime(kQuickF2l, conversion, conversion->GetDexPc());
CheckEntrypointTypes<kQuickF2l, int64_t, float>();
break;
case DataType::Type::kFloat64:
- // Processing a Dex `double-to-long' instruction.
codegen_->InvokeRuntime(kQuickD2l, conversion, conversion->GetDexPc());
CheckEntrypointTypes<kQuickD2l, int64_t, double>();
break;
@@ -4068,49 +4079,24 @@
}
break;
- case DataType::Type::kUint16:
- switch (input_type) {
- case DataType::Type::kInt64:
- // Type conversion from long to char is a result of code transformations.
- __ Ubfx(OutputRegister(conversion), LowRegisterFrom(in), 0, 16);
- break;
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
- case DataType::Type::kInt8:
- case DataType::Type::kInt16:
- case DataType::Type::kInt32:
- // Processing a Dex `int-to-char' instruction.
- __ Ubfx(OutputRegister(conversion), InputRegisterAt(conversion, 0), 0, 16);
- break;
-
- default:
- LOG(FATAL) << "Unexpected type conversion from " << input_type
- << " to " << result_type;
- }
- break;
-
case DataType::Type::kFloat32:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16: {
- // Processing a Dex `int-to-float' instruction.
__ Vmov(OutputSRegister(conversion), InputRegisterAt(conversion, 0));
__ Vcvt(F32, S32, OutputSRegister(conversion), OutputSRegister(conversion));
break;
- }
case DataType::Type::kInt64:
- // Processing a Dex `long-to-float' instruction.
codegen_->InvokeRuntime(kQuickL2f, conversion, conversion->GetDexPc());
CheckEntrypointTypes<kQuickL2f, float, int64_t>();
break;
case DataType::Type::kFloat64:
- // Processing a Dex `double-to-float' instruction.
__ Vcvt(F32, F64, OutputSRegister(conversion), DRegisterFrom(in));
break;
@@ -4123,19 +4109,16 @@
case DataType::Type::kFloat64:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16: {
- // Processing a Dex `int-to-double' instruction.
__ Vmov(LowSRegisterFrom(out), InputRegisterAt(conversion, 0));
__ Vcvt(F64, S32, DRegisterFrom(out), LowSRegisterFrom(out));
break;
- }
case DataType::Type::kInt64: {
- // Processing a Dex `long-to-double' instruction.
vixl32::Register low = LowRegisterFrom(in);
vixl32::Register high = HighRegisterFrom(in);
vixl32::SRegister out_s = LowSRegisterFrom(out);
@@ -4158,7 +4141,6 @@
}
case DataType::Type::kFloat32:
- // Processing a Dex `float-to-double' instruction.
__ Vcvt(F64, F32, DRegisterFrom(out), InputSRegisterAt(conversion, 0));
break;
@@ -4760,6 +4742,7 @@
switch (instruction->GetType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -5288,9 +5271,10 @@
new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
switch (compare->InputAt(0)->GetType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32:
case DataType::Type::kInt64: {
locations->SetInAt(0, Location::RequiresRegister());
@@ -5323,9 +5307,10 @@
vixl32::Condition less_cond = vixl32::Condition(kNone);
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32: {
// Emit move to `out` before the `Cmp`, as `Mov` might affect the status flags.
__ Mov(out, 0);
@@ -5513,18 +5498,16 @@
switch (field_type) {
case DataType::Type::kBool:
- case DataType::Type::kInt8: {
- GetAssembler()->StoreToOffset(kStoreByte, RegisterFrom(value), base, offset);
- break;
- }
-
+ case DataType::Type::kUint8:
+ case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
- case DataType::Type::kUint16: {
- GetAssembler()->StoreToOffset(kStoreHalfword, RegisterFrom(value), base, offset);
+ case DataType::Type::kInt32: {
+ StoreOperandType operand_type = GetStoreOperandType(field_type);
+ GetAssembler()->StoreToOffset(operand_type, RegisterFrom(value), base, offset);
break;
}
- case DataType::Type::kInt32:
case DataType::Type::kReference: {
if (kPoisonHeapReferences && needs_write_barrier) {
// Note that in the case where `value` is a null reference,
@@ -5764,24 +5747,15 @@
switch (field_type) {
case DataType::Type::kBool:
- GetAssembler()->LoadFromOffset(kLoadUnsignedByte, RegisterFrom(out), base, offset);
- break;
-
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- GetAssembler()->LoadFromOffset(kLoadSignedByte, RegisterFrom(out), base, offset);
- break;
-
- case DataType::Type::kInt16:
- GetAssembler()->LoadFromOffset(kLoadSignedHalfword, RegisterFrom(out), base, offset);
- break;
-
case DataType::Type::kUint16:
- GetAssembler()->LoadFromOffset(kLoadUnsignedHalfword, RegisterFrom(out), base, offset);
+ case DataType::Type::kInt16:
+ case DataType::Type::kInt32: {
+ LoadOperandType operand_type = GetLoadOperandType(field_type);
+ GetAssembler()->LoadFromOffset(operand_type, RegisterFrom(out), base, offset);
break;
-
- case DataType::Type::kInt32:
- GetAssembler()->LoadFromOffset(kLoadWord, RegisterFrom(out), base, offset);
- break;
+ }
case DataType::Type::kReference: {
// /* HeapReference<Object> */ out = *(base + offset)
@@ -5995,56 +5969,6 @@
codegen_->GenerateNullCheck(instruction);
}
-static LoadOperandType GetLoadOperandType(DataType::Type type) {
- switch (type) {
- case DataType::Type::kReference:
- return kLoadWord;
- case DataType::Type::kBool:
- return kLoadUnsignedByte;
- case DataType::Type::kInt8:
- return kLoadSignedByte;
- case DataType::Type::kUint16:
- return kLoadUnsignedHalfword;
- case DataType::Type::kInt16:
- return kLoadSignedHalfword;
- case DataType::Type::kInt32:
- return kLoadWord;
- case DataType::Type::kInt64:
- return kLoadWordPair;
- case DataType::Type::kFloat32:
- return kLoadSWord;
- case DataType::Type::kFloat64:
- return kLoadDWord;
- default:
- LOG(FATAL) << "Unreachable type " << type;
- UNREACHABLE();
- }
-}
-
-static StoreOperandType GetStoreOperandType(DataType::Type type) {
- switch (type) {
- case DataType::Type::kReference:
- return kStoreWord;
- case DataType::Type::kBool:
- case DataType::Type::kInt8:
- return kStoreByte;
- case DataType::Type::kUint16:
- case DataType::Type::kInt16:
- return kStoreHalfword;
- case DataType::Type::kInt32:
- return kStoreWord;
- case DataType::Type::kInt64:
- return kStoreWordPair;
- case DataType::Type::kFloat32:
- return kStoreSWord;
- case DataType::Type::kFloat64:
- return kStoreDWord;
- default:
- LOG(FATAL) << "Unreachable type " << type;
- UNREACHABLE();
- }
-}
-
void CodeGeneratorARMVIXL::LoadFromShiftedRegOffset(DataType::Type type,
Location out_loc,
vixl32::Register base,
@@ -6054,18 +5978,19 @@
MemOperand mem_address(base, reg_index, vixl32::LSL, shift_count);
switch (type) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
__ Ldrsb(cond, RegisterFrom(out_loc), mem_address);
break;
case DataType::Type::kBool:
__ Ldrb(cond, RegisterFrom(out_loc), mem_address);
break;
- case DataType::Type::kInt16:
- __ Ldrsh(cond, RegisterFrom(out_loc), mem_address);
- break;
case DataType::Type::kUint16:
__ Ldrh(cond, RegisterFrom(out_loc), mem_address);
break;
+ case DataType::Type::kInt16:
+ __ Ldrsh(cond, RegisterFrom(out_loc), mem_address);
+ break;
case DataType::Type::kReference:
case DataType::Type::kInt32:
__ Ldr(cond, RegisterFrom(out_loc), mem_address);
@@ -6089,12 +6014,13 @@
MemOperand mem_address(base, reg_index, vixl32::LSL, shift_count);
switch (type) {
- case DataType::Type::kInt8:
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
+ case DataType::Type::kInt8:
__ Strb(cond, RegisterFrom(loc), mem_address);
break;
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
__ Strh(cond, RegisterFrom(loc), mem_address);
break;
case DataType::Type::kReference:
@@ -6182,9 +6108,10 @@
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32: {
vixl32::Register length;
if (maybe_compressed_char_at) {
@@ -6434,9 +6361,10 @@
switch (value_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32: {
if (index.IsConstant()) {
int32_t const_index = Int32ConstantFrom(index);
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index a7c8557..70c8a5b 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -51,12 +51,13 @@
Location MipsReturnLocation(DataType::Type return_type) {
switch (return_type) {
+ case DataType::Type::kReference:
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kReference:
return Location::RegisterLocation(V0);
case DataType::Type::kInt64:
@@ -84,12 +85,13 @@
Location next_location;
switch (type) {
+ case DataType::Type::kReference:
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
- case DataType::Type::kInt32:
- case DataType::Type::kReference: {
+ case DataType::Type::kInt32: {
uint32_t gp_index = gp_index_++;
if (gp_index < calling_convention.GetNumberOfRegisters()) {
next_location = Location::RegisterLocation(calling_convention.GetRegisterAt(gp_index));
@@ -2592,7 +2594,8 @@
const bool maybe_compressed_char_at = mirror::kUseStringCompression &&
instruction->IsStringCharAt();
switch (type) {
- case DataType::Type::kBool: {
+ case DataType::Type::kBool:
+ case DataType::Type::kUint8: {
Register out = out_loc.AsRegister<Register>();
if (index.IsConstant()) {
size_t offset =
@@ -2618,19 +2621,6 @@
break;
}
- case DataType::Type::kInt16: {
- Register out = out_loc.AsRegister<Register>();
- if (index.IsConstant()) {
- size_t offset =
- (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset;
- __ LoadFromOffset(kLoadSignedHalfword, out, obj, offset, null_checker);
- } else {
- __ ShiftAndAdd(TMP, index.AsRegister<Register>(), obj, TIMES_2, TMP);
- __ LoadFromOffset(kLoadSignedHalfword, out, TMP, data_offset, null_checker);
- }
- break;
- }
-
case DataType::Type::kUint16: {
Register out = out_loc.AsRegister<Register>();
if (maybe_compressed_char_at) {
@@ -2683,6 +2673,19 @@
break;
}
+ case DataType::Type::kInt16: {
+ Register out = out_loc.AsRegister<Register>();
+ if (index.IsConstant()) {
+ size_t offset =
+ (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset;
+ __ LoadFromOffset(kLoadSignedHalfword, out, obj, offset, null_checker);
+ } else {
+ __ ShiftAndAdd(TMP, index.AsRegister<Register>(), obj, TIMES_2, TMP);
+ __ LoadFromOffset(kLoadSignedHalfword, out, TMP, data_offset, null_checker);
+ }
+ break;
+ }
+
case DataType::Type::kInt32: {
DCHECK_EQ(sizeof(mirror::HeapReference<mirror::Object>), sizeof(int32_t));
Register out = out_loc.AsRegister<Register>();
@@ -2880,6 +2883,7 @@
switch (value_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8: {
uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value();
if (index.IsConstant()) {
@@ -2897,8 +2901,8 @@
break;
}
- case DataType::Type::kInt16:
- case DataType::Type::kUint16: {
+ case DataType::Type::kUint16:
+ case DataType::Type::kInt16: {
uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value();
if (index.IsConstant()) {
data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2;
@@ -3390,9 +3394,10 @@
switch (in_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32:
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
@@ -3429,9 +3434,10 @@
// -1 if: left < right
switch (in_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32: {
Register lhs = locations->InAt(0).AsRegister<Register>();
Register rhs = locations->InAt(1).AsRegister<Register>();
@@ -3833,6 +3839,7 @@
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -6159,17 +6166,18 @@
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
load_type = kLoadUnsignedByte;
break;
case DataType::Type::kInt8:
load_type = kLoadSignedByte;
break;
- case DataType::Type::kInt16:
- load_type = kLoadSignedHalfword;
- break;
case DataType::Type::kUint16:
load_type = kLoadUnsignedHalfword;
break;
+ case DataType::Type::kInt16:
+ load_type = kLoadSignedHalfword;
+ break;
case DataType::Type::kInt32:
case DataType::Type::kFloat32:
case DataType::Type::kReference:
@@ -6312,11 +6320,12 @@
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
store_type = kStoreByte;
break;
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
store_type = kStoreHalfword;
break;
case DataType::Type::kInt32:
@@ -8601,7 +8610,8 @@
void LocationsBuilderMIPS::VisitTypeConversion(HTypeConversion* conversion) {
DataType::Type input_type = conversion->GetInputType();
DataType::Type result_type = conversion->GetResultType();
- DCHECK_NE(input_type, result_type);
+ DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type))
+ << input_type << " -> " << result_type;
bool isR6 = codegen_->GetInstructionSetFeatures().IsR6();
if ((input_type == DataType::Type::kReference) || (input_type == DataType::Type::kVoid) ||
@@ -8652,7 +8662,8 @@
bool has_sign_extension = codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2();
bool isR6 = codegen_->GetInstructionSetFeatures().IsR6();
- DCHECK_NE(input_type, result_type);
+ DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type))
+ << input_type << " -> " << result_type;
if (result_type == DataType::Type::kInt64 && DataType::IsIntegralType(input_type)) {
Register dst_high = locations->Out().AsRegisterPairHigh<Register>();
@@ -8670,8 +8681,8 @@
: locations->InAt(0).AsRegister<Register>();
switch (result_type) {
- case DataType::Type::kUint16:
- __ Andi(dst, src, 0xFFFF);
+ case DataType::Type::kUint8:
+ __ Andi(dst, src, 0xFF);
break;
case DataType::Type::kInt8:
if (has_sign_extension) {
@@ -8681,6 +8692,9 @@
__ Sra(dst, dst, 24);
}
break;
+ case DataType::Type::kUint16:
+ __ Andi(dst, src, 0xFFFF);
+ break;
case DataType::Type::kInt16:
if (has_sign_extension) {
__ Seh(dst, src);
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 7051cce..6877003 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -50,6 +50,7 @@
Location Mips64ReturnLocation(DataType::Type return_type) {
switch (return_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -2170,7 +2171,8 @@
const bool maybe_compressed_char_at = mirror::kUseStringCompression &&
instruction->IsStringCharAt();
switch (type) {
- case DataType::Type::kBool: {
+ case DataType::Type::kBool:
+ case DataType::Type::kUint8: {
GpuRegister out = out_loc.AsRegister<GpuRegister>();
if (index.IsConstant()) {
size_t offset =
@@ -2196,19 +2198,6 @@
break;
}
- case DataType::Type::kInt16: {
- GpuRegister out = out_loc.AsRegister<GpuRegister>();
- if (index.IsConstant()) {
- size_t offset =
- (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset;
- __ LoadFromOffset(kLoadSignedHalfword, out, obj, offset, null_checker);
- } else {
- __ Dlsa(TMP, index.AsRegister<GpuRegister>(), obj, TIMES_2);
- __ LoadFromOffset(kLoadSignedHalfword, out, TMP, data_offset, null_checker);
- }
- break;
- }
-
case DataType::Type::kUint16: {
GpuRegister out = out_loc.AsRegister<GpuRegister>();
if (maybe_compressed_char_at) {
@@ -2261,6 +2250,19 @@
break;
}
+ case DataType::Type::kInt16: {
+ GpuRegister out = out_loc.AsRegister<GpuRegister>();
+ if (index.IsConstant()) {
+ size_t offset =
+ (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset;
+ __ LoadFromOffset(kLoadSignedHalfword, out, obj, offset, null_checker);
+ } else {
+ __ Dlsa(TMP, index.AsRegister<GpuRegister>(), obj, TIMES_2);
+ __ LoadFromOffset(kLoadSignedHalfword, out, TMP, data_offset, null_checker);
+ }
+ break;
+ }
+
case DataType::Type::kInt32: {
DCHECK_EQ(sizeof(mirror::HeapReference<mirror::Object>), sizeof(int32_t));
GpuRegister out = out_loc.AsRegister<GpuRegister>();
@@ -2460,6 +2462,7 @@
switch (value_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8: {
uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value();
if (index.IsConstant()) {
@@ -2477,8 +2480,8 @@
break;
}
- case DataType::Type::kInt16:
- case DataType::Type::kUint16: {
+ case DataType::Type::kUint16:
+ case DataType::Type::kInt16: {
uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value();
if (index.IsConstant()) {
data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2;
@@ -2969,9 +2972,10 @@
switch (in_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32:
case DataType::Type::kInt64:
locations->SetInAt(0, Location::RequiresRegister());
@@ -3001,9 +3005,10 @@
// -1 if: left < right
switch (in_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32:
case DataType::Type::kInt64: {
GpuRegister lhs = locations->InAt(0).AsRegister<GpuRegister>();
@@ -4681,17 +4686,18 @@
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
load_type = kLoadUnsignedByte;
break;
case DataType::Type::kInt8:
load_type = kLoadSignedByte;
break;
- case DataType::Type::kInt16:
- load_type = kLoadSignedHalfword;
- break;
case DataType::Type::kUint16:
load_type = kLoadUnsignedHalfword;
break;
+ case DataType::Type::kInt16:
+ load_type = kLoadSignedHalfword;
+ break;
case DataType::Type::kInt32:
case DataType::Type::kFloat32:
load_type = kLoadWord;
@@ -4779,11 +4785,12 @@
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
store_type = kStoreByte;
break;
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
store_type = kStoreHalfword;
break;
case DataType::Type::kInt32:
@@ -6767,7 +6774,8 @@
void LocationsBuilderMIPS64::VisitTypeConversion(HTypeConversion* conversion) {
DataType::Type input_type = conversion->GetInputType();
DataType::Type result_type = conversion->GetResultType();
- DCHECK_NE(input_type, result_type);
+ DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type))
+ << input_type << " -> " << result_type;
if ((input_type == DataType::Type::kReference) || (input_type == DataType::Type::kVoid) ||
(result_type == DataType::Type::kReference) || (result_type == DataType::Type::kVoid)) {
@@ -6794,15 +6802,16 @@
DataType::Type result_type = conversion->GetResultType();
DataType::Type input_type = conversion->GetInputType();
- DCHECK_NE(input_type, result_type);
+ DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type))
+ << input_type << " -> " << result_type;
if (DataType::IsIntegralType(result_type) && DataType::IsIntegralType(input_type)) {
GpuRegister dst = locations->Out().AsRegister<GpuRegister>();
GpuRegister src = locations->InAt(0).AsRegister<GpuRegister>();
switch (result_type) {
- case DataType::Type::kUint16:
- __ Andi(dst, src, 0xFFFF);
+ case DataType::Type::kUint8:
+ __ Andi(dst, src, 0xFF);
break;
case DataType::Type::kInt8:
if (input_type == DataType::Type::kInt64) {
@@ -6815,6 +6824,9 @@
__ Seb(dst, src);
}
break;
+ case DataType::Type::kUint16:
+ __ Andi(dst, src, 0xFFFF);
+ break;
case DataType::Type::kInt16:
if (input_type == DataType::Type::kInt64) {
// Type conversion from long to types narrower than int is a result of code
diff --git a/compiler/optimizing/code_generator_vector_arm64.cc b/compiler/optimizing/code_generator_vector_arm64.cc
index 5d5623b..b2aec1e 100644
--- a/compiler/optimizing/code_generator_vector_arm64.cc
+++ b/compiler/optimizing/code_generator_vector_arm64.cc
@@ -42,6 +42,7 @@
HInstruction* input = instruction->InputAt(0);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -73,6 +74,7 @@
VRegister dst = VRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
if (src_loc.IsConstant()) {
@@ -132,6 +134,7 @@
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -185,6 +188,7 @@
instruction->IsVecNot() ? Location::kOutputOverlap
: Location::kNoOutputOverlap);
break;
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -268,6 +272,7 @@
VRegister src = VRegisterFrom(locations->InAt(0));
VRegister dst = VRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ Neg(dst.V16B(), src.V16B());
@@ -312,7 +317,6 @@
DCHECK_EQ(16u, instruction->GetVectorLength());
__ Abs(dst.V16B(), src.V16B());
break;
- case DataType::Type::kUint16:
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
__ Abs(dst.V8H(), src.V8H());
@@ -353,6 +357,7 @@
__ Movi(dst.V16B(), 1);
__ Eor(dst.V16B(), dst.V16B(), src.V16B());
break;
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -371,6 +376,7 @@
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -398,6 +404,7 @@
VRegister rhs = VRegisterFrom(locations->InAt(1));
VRegister dst = VRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ Add(dst.V16B(), lhs.V16B(), rhs.V16B());
@@ -439,30 +446,29 @@
VRegister rhs = VRegisterFrom(locations->InAt(1));
VRegister dst = VRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
+ DCHECK_EQ(16u, instruction->GetVectorLength());
+ instruction->IsRounded()
+ ? __ Urhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
+ : __ Uhadd(dst.V16B(), lhs.V16B(), rhs.V16B());
+ break;
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- instruction->IsRounded()
- ? __ Urhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
- : __ Uhadd(dst.V16B(), lhs.V16B(), rhs.V16B());
- } else {
- instruction->IsRounded()
- ? __ Srhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
- : __ Shadd(dst.V16B(), lhs.V16B(), rhs.V16B());
- }
+ instruction->IsRounded()
+ ? __ Srhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
+ : __ Shadd(dst.V16B(), lhs.V16B(), rhs.V16B());
break;
case DataType::Type::kUint16:
+ DCHECK_EQ(8u, instruction->GetVectorLength());
+ instruction->IsRounded()
+ ? __ Urhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
+ : __ Uhadd(dst.V8H(), lhs.V8H(), rhs.V8H());
+ break;
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- instruction->IsRounded()
- ? __ Urhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
- : __ Uhadd(dst.V8H(), lhs.V8H(), rhs.V8H());
- } else {
- instruction->IsRounded()
- ? __ Srhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
- : __ Shadd(dst.V8H(), lhs.V8H(), rhs.V8H());
- }
+ instruction->IsRounded()
+ ? __ Srhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
+ : __ Shadd(dst.V8H(), lhs.V8H(), rhs.V8H());
break;
default:
LOG(FATAL) << "Unsupported SIMD type";
@@ -480,6 +486,7 @@
VRegister rhs = VRegisterFrom(locations->InAt(1));
VRegister dst = VRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ Sub(dst.V16B(), lhs.V16B(), rhs.V16B());
@@ -521,6 +528,7 @@
VRegister rhs = VRegisterFrom(locations->InAt(1));
VRegister dst = VRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ Mul(dst.V16B(), lhs.V16B(), rhs.V16B());
@@ -582,22 +590,21 @@
VRegister rhs = VRegisterFrom(locations->InAt(1));
VRegister dst = VRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
+ DCHECK_EQ(16u, instruction->GetVectorLength());
+ __ Umin(dst.V16B(), lhs.V16B(), rhs.V16B());
+ break;
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ Umin(dst.V16B(), lhs.V16B(), rhs.V16B());
- } else {
- __ Smin(dst.V16B(), lhs.V16B(), rhs.V16B());
- }
+ __ Smin(dst.V16B(), lhs.V16B(), rhs.V16B());
break;
case DataType::Type::kUint16:
+ DCHECK_EQ(8u, instruction->GetVectorLength());
+ __ Umin(dst.V8H(), lhs.V8H(), rhs.V8H());
+ break;
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ Umin(dst.V8H(), lhs.V8H(), rhs.V8H());
- } else {
- __ Smin(dst.V8H(), lhs.V8H(), rhs.V8H());
- }
+ __ Smin(dst.V8H(), lhs.V8H(), rhs.V8H());
break;
case DataType::Type::kInt32:
DCHECK_EQ(4u, instruction->GetVectorLength());
@@ -633,22 +640,21 @@
VRegister rhs = VRegisterFrom(locations->InAt(1));
VRegister dst = VRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
+ DCHECK_EQ(16u, instruction->GetVectorLength());
+ __ Umax(dst.V16B(), lhs.V16B(), rhs.V16B());
+ break;
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ Umax(dst.V16B(), lhs.V16B(), rhs.V16B());
- } else {
- __ Smax(dst.V16B(), lhs.V16B(), rhs.V16B());
- }
+ __ Smax(dst.V16B(), lhs.V16B(), rhs.V16B());
break;
case DataType::Type::kUint16:
+ DCHECK_EQ(8u, instruction->GetVectorLength());
+ __ Umax(dst.V8H(), lhs.V8H(), rhs.V8H());
+ break;
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ Umax(dst.V8H(), lhs.V8H(), rhs.V8H());
- } else {
- __ Smax(dst.V8H(), lhs.V8H(), rhs.V8H());
- }
+ __ Smax(dst.V8H(), lhs.V8H(), rhs.V8H());
break;
case DataType::Type::kInt32:
DCHECK_EQ(4u, instruction->GetVectorLength());
@@ -675,6 +681,7 @@
}
void LocationsBuilderARM64::VisitVecAnd(HVecAnd* instruction) {
+ // TODO: Allow constants supported by BIC (vector, immediate).
CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
}
@@ -685,6 +692,7 @@
VRegister dst = VRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -705,6 +713,7 @@
}
void InstructionCodeGeneratorARM64::VisitVecAndNot(HVecAndNot* instruction) {
+ // TODO: Use BIC (vector, register).
LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
}
@@ -719,6 +728,7 @@
VRegister dst = VRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -745,6 +755,7 @@
VRegister dst = VRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -764,6 +775,7 @@
static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -789,6 +801,7 @@
VRegister dst = VRegisterFrom(locations->Out());
int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ Shl(dst.V16B(), lhs.V16B(), value);
@@ -822,6 +835,7 @@
VRegister dst = VRegisterFrom(locations->Out());
int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ Sshr(dst.V16B(), lhs.V16B(), value);
@@ -855,6 +869,7 @@
VRegister dst = VRegisterFrom(locations->Out());
int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ Ushr(dst.V16B(), lhs.V16B(), value);
@@ -888,6 +903,7 @@
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -926,6 +942,7 @@
// Set required elements.
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ Mov(dst.V16B(), 0, InputRegisterAt(instruction, 0));
@@ -953,6 +970,7 @@
static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) {
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -985,6 +1003,7 @@
DCHECK(locations->InAt(0).Equals(locations->Out()));
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
if (instruction->GetOpKind() == HInstruction::kAdd) {
@@ -1024,6 +1043,7 @@
HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
DCHECK_EQ(a->GetPackedType(), b->GetPackedType());
switch (a->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
switch (instruction->GetPackedType()) {
case DataType::Type::kInt64:
@@ -1069,10 +1089,10 @@
HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
DCHECK_EQ(a->GetPackedType(), b->GetPackedType());
switch (a->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, a->GetVectorLength());
switch (instruction->GetPackedType()) {
- case DataType::Type::kUint16:
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
__ Sabal(acc.V8H(), left.V8B(), right.V8B());
@@ -1202,6 +1222,7 @@
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -1300,6 +1321,7 @@
}
FALLTHROUGH_INTENDED;
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
@@ -1329,6 +1351,7 @@
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
diff --git a/compiler/optimizing/code_generator_vector_arm_vixl.cc b/compiler/optimizing/code_generator_vector_arm_vixl.cc
index 333d108..df75752 100644
--- a/compiler/optimizing/code_generator_vector_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_vector_arm_vixl.cc
@@ -36,6 +36,7 @@
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -54,6 +55,7 @@
vixl32::DRegister dst = DRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(8u, instruction->GetVectorLength());
__ Vdup(Untyped8, dst, InputRegisterAt(instruction, 0));
@@ -91,6 +93,7 @@
instruction->IsVecNot() ? Location::kOutputOverlap
: Location::kNoOutputOverlap);
break;
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -129,6 +132,7 @@
vixl32::DRegister src = DRegisterFrom(locations->InAt(0));
vixl32::DRegister dst = DRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(8u, instruction->GetVectorLength());
__ Vneg(DataTypeValue::S8, dst, src);
@@ -161,7 +165,6 @@
DCHECK_EQ(8u, instruction->GetVectorLength());
__ Vabs(DataTypeValue::S8, dst, src);
break;
- case DataType::Type::kUint16:
case DataType::Type::kInt16:
DCHECK_EQ(4u, instruction->GetVectorLength());
__ Vabs(DataTypeValue::S16, dst, src);
@@ -190,6 +193,7 @@
__ Vmov(I8, dst, 1);
__ Veor(dst, dst, src);
break;
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -207,6 +211,7 @@
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -231,6 +236,7 @@
vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
vixl32::DRegister dst = DRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(8u, instruction->GetVectorLength());
__ Vadd(I8, dst, lhs, rhs);
@@ -260,30 +266,29 @@
vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
vixl32::DRegister dst = DRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
+ DCHECK_EQ(8u, instruction->GetVectorLength());
+ instruction->IsRounded()
+ ? __ Vrhadd(DataTypeValue::U8, dst, lhs, rhs)
+ : __ Vhadd(DataTypeValue::U8, dst, lhs, rhs);
+ break;
case DataType::Type::kInt8:
DCHECK_EQ(8u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- instruction->IsRounded()
- ? __ Vrhadd(DataTypeValue::U8, dst, lhs, rhs)
- : __ Vhadd(DataTypeValue::U8, dst, lhs, rhs);
- } else {
- instruction->IsRounded()
- ? __ Vrhadd(DataTypeValue::S8, dst, lhs, rhs)
- : __ Vhadd(DataTypeValue::S8, dst, lhs, rhs);
- }
+ instruction->IsRounded()
+ ? __ Vrhadd(DataTypeValue::S8, dst, lhs, rhs)
+ : __ Vhadd(DataTypeValue::S8, dst, lhs, rhs);
break;
case DataType::Type::kUint16:
+ DCHECK_EQ(4u, instruction->GetVectorLength());
+ instruction->IsRounded()
+ ? __ Vrhadd(DataTypeValue::U16, dst, lhs, rhs)
+ : __ Vhadd(DataTypeValue::U16, dst, lhs, rhs);
+ break;
case DataType::Type::kInt16:
DCHECK_EQ(4u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- instruction->IsRounded()
- ? __ Vrhadd(DataTypeValue::U16, dst, lhs, rhs)
- : __ Vhadd(DataTypeValue::U16, dst, lhs, rhs);
- } else {
- instruction->IsRounded()
- ? __ Vrhadd(DataTypeValue::S16, dst, lhs, rhs)
- : __ Vhadd(DataTypeValue::S16, dst, lhs, rhs);
- }
+ instruction->IsRounded()
+ ? __ Vrhadd(DataTypeValue::S16, dst, lhs, rhs)
+ : __ Vhadd(DataTypeValue::S16, dst, lhs, rhs);
break;
default:
LOG(FATAL) << "Unsupported SIMD type";
@@ -301,6 +306,7 @@
vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
vixl32::DRegister dst = DRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(8u, instruction->GetVectorLength());
__ Vsub(I8, dst, lhs, rhs);
@@ -330,6 +336,7 @@
vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
vixl32::DRegister dst = DRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(8u, instruction->GetVectorLength());
__ Vmul(I8, dst, lhs, rhs);
@@ -367,22 +374,21 @@
vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
vixl32::DRegister dst = DRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
+ DCHECK_EQ(8u, instruction->GetVectorLength());
+ __ Vmin(DataTypeValue::U8, dst, lhs, rhs);
+ break;
case DataType::Type::kInt8:
DCHECK_EQ(8u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ Vmin(DataTypeValue::U8, dst, lhs, rhs);
- } else {
- __ Vmin(DataTypeValue::S8, dst, lhs, rhs);
- }
+ __ Vmin(DataTypeValue::S8, dst, lhs, rhs);
break;
case DataType::Type::kUint16:
+ DCHECK_EQ(4u, instruction->GetVectorLength());
+ __ Vmin(DataTypeValue::U16, dst, lhs, rhs);
+ break;
case DataType::Type::kInt16:
DCHECK_EQ(4u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ Vmin(DataTypeValue::U16, dst, lhs, rhs);
- } else {
- __ Vmin(DataTypeValue::S16, dst, lhs, rhs);
- }
+ __ Vmin(DataTypeValue::S16, dst, lhs, rhs);
break;
case DataType::Type::kInt32:
DCHECK_EQ(2u, instruction->GetVectorLength());
@@ -408,22 +414,21 @@
vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
vixl32::DRegister dst = DRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
+ DCHECK_EQ(8u, instruction->GetVectorLength());
+ __ Vmax(DataTypeValue::U8, dst, lhs, rhs);
+ break;
case DataType::Type::kInt8:
DCHECK_EQ(8u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ Vmax(DataTypeValue::U8, dst, lhs, rhs);
- } else {
- __ Vmax(DataTypeValue::S8, dst, lhs, rhs);
- }
+ __ Vmax(DataTypeValue::S8, dst, lhs, rhs);
break;
case DataType::Type::kUint16:
+ DCHECK_EQ(4u, instruction->GetVectorLength());
+ __ Vmax(DataTypeValue::U16, dst, lhs, rhs);
+ break;
case DataType::Type::kInt16:
DCHECK_EQ(4u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ Vmax(DataTypeValue::U16, dst, lhs, rhs);
- } else {
- __ Vmax(DataTypeValue::S16, dst, lhs, rhs);
- }
+ __ Vmax(DataTypeValue::S16, dst, lhs, rhs);
break;
case DataType::Type::kInt32:
DCHECK_EQ(2u, instruction->GetVectorLength());
@@ -440,6 +445,7 @@
}
void LocationsBuilderARMVIXL::VisitVecAnd(HVecAnd* instruction) {
+ // TODO: Allow constants supported by VAND (immediate).
CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
}
@@ -450,6 +456,7 @@
vixl32::DRegister dst = DRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -481,6 +488,7 @@
vixl32::DRegister dst = DRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -504,6 +512,7 @@
vixl32::DRegister dst = DRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -520,6 +529,7 @@
static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -544,6 +554,7 @@
vixl32::DRegister dst = DRegisterFrom(locations->Out());
int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(8u, instruction->GetVectorLength());
__ Vshl(I8, dst, lhs, value);
@@ -573,6 +584,7 @@
vixl32::DRegister dst = DRegisterFrom(locations->Out());
int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(8u, instruction->GetVectorLength());
__ Vshr(DataTypeValue::S8, dst, lhs, value);
@@ -602,6 +614,7 @@
vixl32::DRegister dst = DRegisterFrom(locations->Out());
int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(8u, instruction->GetVectorLength());
__ Vshr(DataTypeValue::U8, dst, lhs, value);
@@ -633,6 +646,7 @@
static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) {
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -678,6 +692,7 @@
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -764,6 +779,7 @@
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(8u, instruction->GetVectorLength());
if (IsWordAligned(instruction)) {
@@ -811,6 +827,7 @@
vixl32::Register scratch;
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(8u, instruction->GetVectorLength());
if (IsWordAligned(instruction)) {
diff --git a/compiler/optimizing/code_generator_vector_mips.cc b/compiler/optimizing/code_generator_vector_mips.cc
index c25f5ac..e8c5157 100644
--- a/compiler/optimizing/code_generator_vector_mips.cc
+++ b/compiler/optimizing/code_generator_vector_mips.cc
@@ -27,6 +27,7 @@
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -51,6 +52,7 @@
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ FillB(dst, locations->InAt(0).AsRegister<Register>());
@@ -106,6 +108,7 @@
instruction->IsVecNot() ? Location::kOutputOverlap
: Location::kNoOutputOverlap);
break;
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -160,6 +163,7 @@
VectorRegister src = VectorRegisterFrom(locations->InAt(0));
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ FillB(dst, ZERO);
@@ -211,7 +215,6 @@
__ FillB(dst, ZERO); // all zeroes
__ Add_aB(dst, dst, src); // dst = abs(0) + abs(src)
break;
- case DataType::Type::kUint16:
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
__ FillH(dst, ZERO); // all zeroes
@@ -259,6 +262,7 @@
__ LdiB(dst, 1);
__ XorV(dst, dst, src);
break;
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -281,6 +285,7 @@
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -308,6 +313,7 @@
VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ AddvB(dst, lhs, rhs);
@@ -349,30 +355,29 @@
VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
+ DCHECK_EQ(16u, instruction->GetVectorLength());
+ instruction->IsRounded()
+ ? __ Aver_uB(dst, lhs, rhs)
+ : __ Ave_uB(dst, lhs, rhs);
+ break;
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- instruction->IsRounded()
- ? __ Aver_uB(dst, lhs, rhs)
- : __ Ave_uB(dst, lhs, rhs);
- } else {
- instruction->IsRounded()
- ? __ Aver_sB(dst, lhs, rhs)
- : __ Ave_sB(dst, lhs, rhs);
- }
+ instruction->IsRounded()
+ ? __ Aver_sB(dst, lhs, rhs)
+ : __ Ave_sB(dst, lhs, rhs);
break;
case DataType::Type::kUint16:
+ DCHECK_EQ(8u, instruction->GetVectorLength());
+ instruction->IsRounded()
+ ? __ Aver_uH(dst, lhs, rhs)
+ : __ Ave_uH(dst, lhs, rhs);
+ break;
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- instruction->IsRounded()
- ? __ Aver_uH(dst, lhs, rhs)
- : __ Ave_uH(dst, lhs, rhs);
- } else {
- instruction->IsRounded()
- ? __ Aver_sH(dst, lhs, rhs)
- : __ Ave_sH(dst, lhs, rhs);
- }
+ instruction->IsRounded()
+ ? __ Aver_sH(dst, lhs, rhs)
+ : __ Ave_sH(dst, lhs, rhs);
break;
default:
LOG(FATAL) << "Unsupported SIMD type";
@@ -390,6 +395,7 @@
VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ SubvB(dst, lhs, rhs);
@@ -431,6 +437,7 @@
VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ MulvB(dst, lhs, rhs);
@@ -496,22 +503,21 @@
VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
+ DCHECK_EQ(16u, instruction->GetVectorLength());
+ __ Min_uB(dst, lhs, rhs);
+ break;
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ Min_uB(dst, lhs, rhs);
- } else {
- __ Min_sB(dst, lhs, rhs);
- }
+ __ Min_sB(dst, lhs, rhs);
break;
case DataType::Type::kUint16:
+ DCHECK_EQ(8u, instruction->GetVectorLength());
+ __ Min_uH(dst, lhs, rhs);
+ break;
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ Min_uH(dst, lhs, rhs);
- } else {
- __ Min_sH(dst, lhs, rhs);
- }
+ __ Min_sH(dst, lhs, rhs);
break;
case DataType::Type::kInt32:
DCHECK_EQ(4u, instruction->GetVectorLength());
@@ -557,22 +563,21 @@
VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
+ DCHECK_EQ(16u, instruction->GetVectorLength());
+ __ Max_uB(dst, lhs, rhs);
+ break;
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ Max_uB(dst, lhs, rhs);
- } else {
- __ Max_sB(dst, lhs, rhs);
- }
+ __ Max_sB(dst, lhs, rhs);
break;
case DataType::Type::kUint16:
+ DCHECK_EQ(8u, instruction->GetVectorLength());
+ __ Max_uH(dst, lhs, rhs);
+ break;
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ Max_uH(dst, lhs, rhs);
- } else {
- __ Max_sH(dst, lhs, rhs);
- }
+ __ Max_sH(dst, lhs, rhs);
break;
case DataType::Type::kInt32:
DCHECK_EQ(4u, instruction->GetVectorLength());
@@ -619,6 +624,7 @@
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -655,6 +661,7 @@
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -683,6 +690,7 @@
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -704,6 +712,7 @@
static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -729,6 +738,7 @@
VectorRegister dst = VectorRegisterFrom(locations->Out());
int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ SlliB(dst, lhs, value);
@@ -762,6 +772,7 @@
VectorRegister dst = VectorRegisterFrom(locations->Out());
int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ SraiB(dst, lhs, value);
@@ -795,6 +806,7 @@
VectorRegister dst = VectorRegisterFrom(locations->Out());
int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ SrliB(dst, lhs, value);
@@ -830,6 +842,7 @@
static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) {
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -856,6 +869,7 @@
VectorRegister left = VectorRegisterFrom(locations->InAt(1));
VectorRegister right = VectorRegisterFrom(locations->InAt(2));
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
if (instruction->GetOpKind() == HInstruction::kAdd) {
@@ -911,6 +925,7 @@
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -976,6 +991,7 @@
int32_t offset = VecAddress(locations, size, &base);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ LdB(reg, base, offset);
@@ -1018,6 +1034,7 @@
int32_t offset = VecAddress(locations, size, &base);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ StB(reg, base, offset);
diff --git a/compiler/optimizing/code_generator_vector_mips64.cc b/compiler/optimizing/code_generator_vector_mips64.cc
index f60f708..7d69773 100644
--- a/compiler/optimizing/code_generator_vector_mips64.cc
+++ b/compiler/optimizing/code_generator_vector_mips64.cc
@@ -32,6 +32,7 @@
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -56,6 +57,7 @@
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ FillB(dst, locations->InAt(0).AsRegister<GpuRegister>());
@@ -109,6 +111,7 @@
instruction->IsVecNot() ? Location::kOutputOverlap
: Location::kNoOutputOverlap);
break;
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -164,6 +167,7 @@
VectorRegister src = VectorRegisterFrom(locations->InAt(0));
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ FillB(dst, ZERO);
@@ -215,7 +219,6 @@
__ FillB(dst, ZERO); // all zeroes
__ Add_aB(dst, dst, src); // dst = abs(0) + abs(src)
break;
- case DataType::Type::kUint16:
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
__ FillH(dst, ZERO); // all zeroes
@@ -263,6 +266,7 @@
__ LdiB(dst, 1);
__ XorV(dst, dst, src);
break;
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -285,6 +289,7 @@
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -312,6 +317,7 @@
VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ AddvB(dst, lhs, rhs);
@@ -353,30 +359,29 @@
VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
+ DCHECK_EQ(16u, instruction->GetVectorLength());
+ instruction->IsRounded()
+ ? __ Aver_uB(dst, lhs, rhs)
+ : __ Ave_uB(dst, lhs, rhs);
+ break;
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- instruction->IsRounded()
- ? __ Aver_uB(dst, lhs, rhs)
- : __ Ave_uB(dst, lhs, rhs);
- } else {
- instruction->IsRounded()
- ? __ Aver_sB(dst, lhs, rhs)
- : __ Ave_sB(dst, lhs, rhs);
- }
+ instruction->IsRounded()
+ ? __ Aver_sB(dst, lhs, rhs)
+ : __ Ave_sB(dst, lhs, rhs);
break;
case DataType::Type::kUint16:
+ DCHECK_EQ(8u, instruction->GetVectorLength());
+ instruction->IsRounded()
+ ? __ Aver_uH(dst, lhs, rhs)
+ : __ Ave_uH(dst, lhs, rhs);
+ break;
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- instruction->IsRounded()
- ? __ Aver_uH(dst, lhs, rhs)
- : __ Ave_uH(dst, lhs, rhs);
- } else {
- instruction->IsRounded()
- ? __ Aver_sH(dst, lhs, rhs)
- : __ Ave_sH(dst, lhs, rhs);
- }
+ instruction->IsRounded()
+ ? __ Aver_sH(dst, lhs, rhs)
+ : __ Ave_sH(dst, lhs, rhs);
break;
default:
LOG(FATAL) << "Unsupported SIMD type";
@@ -394,6 +399,7 @@
VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ SubvB(dst, lhs, rhs);
@@ -435,6 +441,7 @@
VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ MulvB(dst, lhs, rhs);
@@ -500,22 +507,21 @@
VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
+ DCHECK_EQ(16u, instruction->GetVectorLength());
+ __ Min_uB(dst, lhs, rhs);
+ break;
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ Min_uB(dst, lhs, rhs);
- } else {
- __ Min_sB(dst, lhs, rhs);
- }
+ __ Min_sB(dst, lhs, rhs);
break;
case DataType::Type::kUint16:
+ DCHECK_EQ(8u, instruction->GetVectorLength());
+ __ Min_uH(dst, lhs, rhs);
+ break;
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ Min_uH(dst, lhs, rhs);
- } else {
- __ Min_sH(dst, lhs, rhs);
- }
+ __ Min_sH(dst, lhs, rhs);
break;
case DataType::Type::kInt32:
DCHECK_EQ(4u, instruction->GetVectorLength());
@@ -561,22 +567,21 @@
VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
+ DCHECK_EQ(16u, instruction->GetVectorLength());
+ __ Max_uB(dst, lhs, rhs);
+ break;
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ Max_uB(dst, lhs, rhs);
- } else {
- __ Max_sB(dst, lhs, rhs);
- }
+ __ Max_sB(dst, lhs, rhs);
break;
case DataType::Type::kUint16:
+ DCHECK_EQ(8u, instruction->GetVectorLength());
+ __ Max_uH(dst, lhs, rhs);
+ break;
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ Max_uH(dst, lhs, rhs);
- } else {
- __ Max_sH(dst, lhs, rhs);
- }
+ __ Max_sH(dst, lhs, rhs);
break;
case DataType::Type::kInt32:
DCHECK_EQ(4u, instruction->GetVectorLength());
@@ -623,6 +628,7 @@
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -659,6 +665,7 @@
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -687,6 +694,7 @@
VectorRegister dst = VectorRegisterFrom(locations->Out());
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -708,6 +716,7 @@
static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -733,6 +742,7 @@
VectorRegister dst = VectorRegisterFrom(locations->Out());
int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ SlliB(dst, lhs, value);
@@ -766,6 +776,7 @@
VectorRegister dst = VectorRegisterFrom(locations->Out());
int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ SraiB(dst, lhs, value);
@@ -799,6 +810,7 @@
VectorRegister dst = VectorRegisterFrom(locations->Out());
int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ SrliB(dst, lhs, value);
@@ -834,6 +846,7 @@
static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) {
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -860,6 +873,7 @@
VectorRegister left = VectorRegisterFrom(locations->InAt(1));
VectorRegister right = VectorRegisterFrom(locations->InAt(2));
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
if (instruction->GetOpKind() == HInstruction::kAdd) {
@@ -915,6 +929,7 @@
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -980,6 +995,7 @@
int32_t offset = VecAddress(locations, size, &base);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ LdB(reg, base, offset);
@@ -1022,6 +1038,7 @@
int32_t offset = VecAddress(locations, size, &base);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ StB(reg, base, offset);
diff --git a/compiler/optimizing/code_generator_vector_x86.cc b/compiler/optimizing/code_generator_vector_x86.cc
index 6515dbe..a2ef1b1 100644
--- a/compiler/optimizing/code_generator_vector_x86.cc
+++ b/compiler/optimizing/code_generator_vector_x86.cc
@@ -37,6 +37,7 @@
}
FALLTHROUGH_INTENDED;
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -70,6 +71,7 @@
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ movd(dst, locations->InAt(0).AsRegister<Register>());
@@ -122,6 +124,7 @@
locations->AddTemp(Location::RequiresFpuRegister());
FALLTHROUGH_INTENDED;
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -145,6 +148,7 @@
XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16: // TODO: up to here, and?
@@ -180,6 +184,7 @@
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -290,6 +295,7 @@
XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ pxor(dst, dst);
@@ -390,6 +396,7 @@
__ pxor(dst, src);
break;
}
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -421,6 +428,7 @@
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -448,6 +456,7 @@
XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ paddb(dst, src);
@@ -490,15 +499,13 @@
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
DCHECK(instruction->IsRounded());
- DCHECK(instruction->IsUnsigned());
switch (instruction->GetPackedType()) {
- case DataType::Type::kInt8:
+ case DataType::Type::kUint8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ pavgb(dst, src);
return;
case DataType::Type::kUint16:
- case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
__ pavgw(dst, src);
return;
@@ -518,6 +525,7 @@
XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ psubb(dst, src);
@@ -616,22 +624,21 @@
XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
+ DCHECK_EQ(16u, instruction->GetVectorLength());
+ __ pminub(dst, src);
+ break;
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ pminub(dst, src);
- } else {
- __ pminsb(dst, src);
- }
+ __ pminsb(dst, src);
break;
case DataType::Type::kUint16:
+ DCHECK_EQ(8u, instruction->GetVectorLength());
+ __ pminuw(dst, src);
+ break;
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ pminuw(dst, src);
- } else {
- __ pminsw(dst, src);
- }
+ __ pminsw(dst, src);
break;
case DataType::Type::kInt32:
DCHECK_EQ(4u, instruction->GetVectorLength());
@@ -668,22 +675,21 @@
XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
+ DCHECK_EQ(16u, instruction->GetVectorLength());
+ __ pmaxub(dst, src);
+ break;
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ pmaxub(dst, src);
- } else {
- __ pmaxsb(dst, src);
- }
+ __ pmaxsb(dst, src);
break;
case DataType::Type::kUint16:
+ DCHECK_EQ(8u, instruction->GetVectorLength());
+ __ pmaxuw(dst, src);
+ break;
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ pmaxuw(dst, src);
- } else {
- __ pmaxsw(dst, src);
- }
+ __ pmaxsw(dst, src);
break;
case DataType::Type::kInt32:
DCHECK_EQ(4u, instruction->GetVectorLength());
@@ -721,6 +727,7 @@
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -755,6 +762,7 @@
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -789,6 +797,7 @@
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -823,6 +832,7 @@
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -963,6 +973,7 @@
}
FALLTHROUGH_INTENDED;
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -1000,6 +1011,7 @@
// Set required elements.
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16: // TODO: up to here, and?
@@ -1036,6 +1048,7 @@
static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) {
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -1077,6 +1090,7 @@
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -1156,6 +1170,7 @@
}
FALLTHROUGH_INTENDED;
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
@@ -1190,6 +1205,7 @@
bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
diff --git a/compiler/optimizing/code_generator_vector_x86_64.cc b/compiler/optimizing/code_generator_vector_x86_64.cc
index 4241042..2270f6b 100644
--- a/compiler/optimizing/code_generator_vector_x86_64.cc
+++ b/compiler/optimizing/code_generator_vector_x86_64.cc
@@ -31,6 +31,7 @@
bool is_zero = IsZeroBitPattern(input);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -65,6 +66,7 @@
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ movd(dst, locations->InAt(0).AsRegister<CpuRegister>(), /*64-bit*/ false);
@@ -109,6 +111,7 @@
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -133,6 +136,7 @@
XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16: // TODO: up to here, and?
@@ -163,6 +167,7 @@
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -273,6 +278,7 @@
XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ pxor(dst, dst);
@@ -373,6 +379,7 @@
__ pxor(dst, src);
break;
}
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -404,6 +411,7 @@
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -431,6 +439,7 @@
XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ paddb(dst, src);
@@ -473,15 +482,13 @@
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
DCHECK(instruction->IsRounded());
- DCHECK(instruction->IsUnsigned());
switch (instruction->GetPackedType()) {
- case DataType::Type::kInt8:
+ case DataType::Type::kUint8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ pavgb(dst, src);
return;
case DataType::Type::kUint16:
- case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
__ pavgw(dst, src);
return;
@@ -501,6 +508,7 @@
XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
__ psubb(dst, src);
@@ -599,22 +607,21 @@
XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
+ DCHECK_EQ(16u, instruction->GetVectorLength());
+ __ pminub(dst, src);
+ break;
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ pminub(dst, src);
- } else {
- __ pminsb(dst, src);
- }
+ __ pminsb(dst, src);
break;
case DataType::Type::kUint16:
+ DCHECK_EQ(8u, instruction->GetVectorLength());
+ __ pminuw(dst, src);
+ break;
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ pminuw(dst, src);
- } else {
- __ pminsw(dst, src);
- }
+ __ pminsw(dst, src);
break;
case DataType::Type::kInt32:
DCHECK_EQ(4u, instruction->GetVectorLength());
@@ -651,22 +658,21 @@
XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
+ DCHECK_EQ(16u, instruction->GetVectorLength());
+ __ pmaxub(dst, src);
+ break;
case DataType::Type::kInt8:
DCHECK_EQ(16u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ pmaxub(dst, src);
- } else {
- __ pmaxsb(dst, src);
- }
+ __ pmaxsb(dst, src);
break;
case DataType::Type::kUint16:
+ DCHECK_EQ(8u, instruction->GetVectorLength());
+ __ pmaxuw(dst, src);
+ break;
case DataType::Type::kInt16:
DCHECK_EQ(8u, instruction->GetVectorLength());
- if (instruction->IsUnsigned()) {
- __ pmaxuw(dst, src);
- } else {
- __ pmaxsw(dst, src);
- }
+ __ pmaxsw(dst, src);
break;
case DataType::Type::kInt32:
DCHECK_EQ(4u, instruction->GetVectorLength());
@@ -704,6 +710,7 @@
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -738,6 +745,7 @@
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -772,6 +780,7 @@
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -806,6 +815,7 @@
XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -940,6 +950,7 @@
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -978,6 +989,7 @@
// Set required elements.
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16: // TODO: up to here, and?
@@ -1009,6 +1021,7 @@
static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) {
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -1050,6 +1063,7 @@
LocationSummary* locations = new (arena) LocationSummary(instruction);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -1129,6 +1143,7 @@
}
FALLTHROUGH_INTENDED;
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
@@ -1163,6 +1178,7 @@
bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16);
switch (instruction->GetPackedType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 70e270e..3515649 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1131,12 +1131,13 @@
Location InvokeDexCallingConventionVisitorX86::GetReturnLocation(DataType::Type type) const {
switch (type) {
+ case DataType::Type::kReference:
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kReference:
return Location::RegisterLocation(EAX);
case DataType::Type::kInt64:
@@ -1159,12 +1160,13 @@
Location InvokeDexCallingConventionVisitorX86::GetNextLocation(DataType::Type type) {
switch (type) {
+ case DataType::Type::kReference:
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
- case DataType::Type::kInt32:
- case DataType::Type::kReference: {
+ case DataType::Type::kInt32: {
uint32_t index = gp_index_++;
stack_index_++;
if (index < calling_convention.GetNumberOfRegisters()) {
@@ -2099,12 +2101,13 @@
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(ret, LocationSummary::kNoCall);
switch (ret->InputAt(0)->GetType()) {
+ case DataType::Type::kReference:
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kReference:
locations->SetInAt(0, Location::RegisterLocation(EAX));
break;
@@ -2127,12 +2130,13 @@
void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
if (kIsDebugBuild) {
switch (ret->InputAt(0)->GetType()) {
+ case DataType::Type::kReference:
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kReference:
DCHECK_EQ(ret->GetLocations()->InAt(0).AsRegister<Register>(), EAX);
break;
@@ -2408,7 +2412,8 @@
void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) {
DataType::Type result_type = conversion->GetResultType();
DataType::Type input_type = conversion->GetInputType();
- DCHECK_NE(result_type, input_type);
+ DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type))
+ << input_type << " -> " << result_type;
// The float-to-long and double-to-long type conversions rely on a
// call to the runtime.
@@ -2420,14 +2425,21 @@
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(conversion, call_kind);
- // The Java language does not allow treating boolean as an integral type but
- // our bit representation makes it safe.
-
switch (result_type) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
switch (input_type) {
+ case DataType::Type::kUint8:
+ case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
+ case DataType::Type::kInt32:
+ locations->SetInAt(0, Location::ByteRegisterOrConstant(ECX, conversion->InputAt(0)));
+ // Make the output overlap to please the register allocator. This greatly simplifies
+ // the validation of the linear scan implementation
+ locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
+ break;
case DataType::Type::kInt64: {
- // Type conversion from long to byte is a result of code transformations.
HInstruction* input = conversion->InputAt(0);
Location input_location = input->IsConstant()
? Location::ConstantLocation(input->AsConstant())
@@ -2438,17 +2450,6 @@
locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
break;
}
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
- case DataType::Type::kInt16:
- case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-byte' instruction.
- locations->SetInAt(0, Location::ByteRegisterOrConstant(ECX, conversion->InputAt(0)));
- // Make the output overlap to please the register allocator. This greatly simplifies
- // the validation of the linear scan implementation
- locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
- break;
default:
LOG(FATAL) << "Unexpected type conversion from " << input_type
@@ -2456,43 +2457,27 @@
}
break;
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
- switch (input_type) {
- case DataType::Type::kInt64:
- // Type conversion from long to short is a result of code transformations.
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
- case DataType::Type::kInt8:
- case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-short' instruction.
- locations->SetInAt(0, Location::Any());
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
- break;
-
- default:
- LOG(FATAL) << "Unexpected type conversion from " << input_type
- << " to " << result_type;
- }
+ DCHECK(DataType::IsIntegralType(input_type)) << input_type;
+ locations->SetInAt(0, Location::Any());
+ locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
break;
case DataType::Type::kInt32:
switch (input_type) {
case DataType::Type::kInt64:
- // Processing a Dex `long-to-int' instruction.
locations->SetInAt(0, Location::Any());
locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
break;
case DataType::Type::kFloat32:
- // Processing a Dex `float-to-int' instruction.
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetOut(Location::RequiresRegister());
locations->AddTemp(Location::RequiresFpuRegister());
break;
case DataType::Type::kFloat64:
- // Processing a Dex `double-to-int' instruction.
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetOut(Location::RequiresRegister());
locations->AddTemp(Location::RequiresFpuRegister());
@@ -2507,19 +2492,17 @@
case DataType::Type::kInt64:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-long' instruction.
locations->SetInAt(0, Location::RegisterLocation(EAX));
locations->SetOut(Location::RegisterPairLocation(EAX, EDX));
break;
case DataType::Type::kFloat32:
case DataType::Type::kFloat64: {
- // Processing a Dex `float-to-long' or 'double-to-long' instruction.
InvokeRuntimeCallingConvention calling_convention;
XmmRegister parameter = calling_convention.GetFpuRegisterAt(0);
locations->SetInAt(0, Location::FpuRegisterLocation(parameter));
@@ -2535,47 +2518,24 @@
}
break;
- case DataType::Type::kUint16:
- switch (input_type) {
- case DataType::Type::kInt64:
- // Type conversion from long to char is a result of code transformations.
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
- case DataType::Type::kInt8:
- case DataType::Type::kInt16:
- case DataType::Type::kInt32:
- // Processing a Dex `int-to-char' instruction.
- locations->SetInAt(0, Location::Any());
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
- break;
-
- default:
- LOG(FATAL) << "Unexpected type conversion from " << input_type
- << " to " << result_type;
- }
- break;
-
case DataType::Type::kFloat32:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-float' instruction.
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::RequiresFpuRegister());
break;
case DataType::Type::kInt64:
- // Processing a Dex `long-to-float' instruction.
locations->SetInAt(0, Location::Any());
locations->SetOut(Location::Any());
break;
case DataType::Type::kFloat64:
- // Processing a Dex `double-to-float' instruction.
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
break;
@@ -2589,24 +2549,21 @@
case DataType::Type::kFloat64:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-double' instruction.
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::RequiresFpuRegister());
break;
case DataType::Type::kInt64:
- // Processing a Dex `long-to-double' instruction.
locations->SetInAt(0, Location::Any());
locations->SetOut(Location::Any());
break;
case DataType::Type::kFloat32:
- // Processing a Dex `float-to-double' instruction.
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
break;
@@ -2629,12 +2586,54 @@
Location in = locations->InAt(0);
DataType::Type result_type = conversion->GetResultType();
DataType::Type input_type = conversion->GetInputType();
- DCHECK_NE(result_type, input_type);
+ DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type))
+ << input_type << " -> " << result_type;
switch (result_type) {
+ case DataType::Type::kUint8:
+ switch (input_type) {
+ case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
+ case DataType::Type::kInt32:
+ if (in.IsRegister()) {
+ __ movzxb(out.AsRegister<Register>(), in.AsRegister<ByteRegister>());
+ } else {
+ DCHECK(in.GetConstant()->IsIntConstant());
+ int32_t value = in.GetConstant()->AsIntConstant()->GetValue();
+ __ movl(out.AsRegister<Register>(), Immediate(static_cast<uint8_t>(value)));
+ }
+ break;
+ case DataType::Type::kInt64:
+ if (in.IsRegisterPair()) {
+ __ movzxb(out.AsRegister<Register>(), in.AsRegisterPairLow<ByteRegister>());
+ } else {
+ DCHECK(in.GetConstant()->IsLongConstant());
+ int64_t value = in.GetConstant()->AsLongConstant()->GetValue();
+ __ movl(out.AsRegister<Register>(), Immediate(static_cast<uint8_t>(value)));
+ }
+ break;
+
+ default:
+ LOG(FATAL) << "Unexpected type conversion from " << input_type
+ << " to " << result_type;
+ }
+ break;
+
case DataType::Type::kInt8:
switch (input_type) {
+ case DataType::Type::kUint8:
+ case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
+ case DataType::Type::kInt32:
+ if (in.IsRegister()) {
+ __ movsxb(out.AsRegister<Register>(), in.AsRegister<ByteRegister>());
+ } else {
+ DCHECK(in.GetConstant()->IsIntConstant());
+ int32_t value = in.GetConstant()->AsIntConstant()->GetValue();
+ __ movl(out.AsRegister<Register>(), Immediate(static_cast<int8_t>(value)));
+ }
+ break;
case DataType::Type::kInt64:
- // Type conversion from long to byte is a result of code transformations.
if (in.IsRegisterPair()) {
__ movsxb(out.AsRegister<Register>(), in.AsRegisterPairLow<ByteRegister>());
} else {
@@ -2643,18 +2642,37 @@
__ movl(out.AsRegister<Register>(), Immediate(static_cast<int8_t>(value)));
}
break;
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+
+ default:
+ LOG(FATAL) << "Unexpected type conversion from " << input_type
+ << " to " << result_type;
+ }
+ break;
+
+ case DataType::Type::kUint16:
+ switch (input_type) {
+ case DataType::Type::kInt8:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-byte' instruction.
if (in.IsRegister()) {
- __ movsxb(out.AsRegister<Register>(), in.AsRegister<ByteRegister>());
+ __ movzxw(out.AsRegister<Register>(), in.AsRegister<Register>());
+ } else if (in.IsStackSlot()) {
+ __ movzxw(out.AsRegister<Register>(), Address(ESP, in.GetStackIndex()));
} else {
DCHECK(in.GetConstant()->IsIntConstant());
int32_t value = in.GetConstant()->AsIntConstant()->GetValue();
- __ movl(out.AsRegister<Register>(), Immediate(static_cast<int8_t>(value)));
+ __ movl(out.AsRegister<Register>(), Immediate(static_cast<uint16_t>(value)));
+ }
+ break;
+ case DataType::Type::kInt64:
+ if (in.IsRegisterPair()) {
+ __ movzxw(out.AsRegister<Register>(), in.AsRegisterPairLow<Register>());
+ } else if (in.IsDoubleStackSlot()) {
+ __ movzxw(out.AsRegister<Register>(), Address(ESP, in.GetStackIndex()));
+ } else {
+ DCHECK(in.GetConstant()->IsLongConstant());
+ int64_t value = in.GetConstant()->AsLongConstant()->GetValue();
+ __ movl(out.AsRegister<Register>(), Immediate(static_cast<uint16_t>(value)));
}
break;
@@ -2666,24 +2684,8 @@
case DataType::Type::kInt16:
switch (input_type) {
- case DataType::Type::kInt64:
- // Type conversion from long to short is a result of code transformations.
- if (in.IsRegisterPair()) {
- __ movsxw(out.AsRegister<Register>(), in.AsRegisterPairLow<Register>());
- } else if (in.IsDoubleStackSlot()) {
- __ movsxw(out.AsRegister<Register>(), Address(ESP, in.GetStackIndex()));
- } else {
- DCHECK(in.GetConstant()->IsLongConstant());
- int64_t value = in.GetConstant()->AsLongConstant()->GetValue();
- __ movl(out.AsRegister<Register>(), Immediate(static_cast<int16_t>(value)));
- }
- break;
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
- case DataType::Type::kInt8:
- case DataType::Type::kInt32:
case DataType::Type::kUint16:
- // Processing a Dex `int-to-short' instruction.
+ case DataType::Type::kInt32:
if (in.IsRegister()) {
__ movsxw(out.AsRegister<Register>(), in.AsRegister<Register>());
} else if (in.IsStackSlot()) {
@@ -2694,6 +2696,17 @@
__ movl(out.AsRegister<Register>(), Immediate(static_cast<int16_t>(value)));
}
break;
+ case DataType::Type::kInt64:
+ if (in.IsRegisterPair()) {
+ __ movsxw(out.AsRegister<Register>(), in.AsRegisterPairLow<Register>());
+ } else if (in.IsDoubleStackSlot()) {
+ __ movsxw(out.AsRegister<Register>(), Address(ESP, in.GetStackIndex()));
+ } else {
+ DCHECK(in.GetConstant()->IsLongConstant());
+ int64_t value = in.GetConstant()->AsLongConstant()->GetValue();
+ __ movl(out.AsRegister<Register>(), Immediate(static_cast<int16_t>(value)));
+ }
+ break;
default:
LOG(FATAL) << "Unexpected type conversion from " << input_type
@@ -2704,7 +2717,6 @@
case DataType::Type::kInt32:
switch (input_type) {
case DataType::Type::kInt64:
- // Processing a Dex `long-to-int' instruction.
if (in.IsRegisterPair()) {
__ movl(out.AsRegister<Register>(), in.AsRegisterPairLow<Register>());
} else if (in.IsDoubleStackSlot()) {
@@ -2718,7 +2730,6 @@
break;
case DataType::Type::kFloat32: {
- // Processing a Dex `float-to-int' instruction.
XmmRegister input = in.AsFpuRegister<XmmRegister>();
Register output = out.AsRegister<Register>();
XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
@@ -2743,7 +2754,6 @@
}
case DataType::Type::kFloat64: {
- // Processing a Dex `double-to-int' instruction.
XmmRegister input = in.AsFpuRegister<XmmRegister>();
Register output = out.AsRegister<Register>();
XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
@@ -2776,12 +2786,11 @@
case DataType::Type::kInt64:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-long' instruction.
DCHECK_EQ(out.AsRegisterPairLow<Register>(), EAX);
DCHECK_EQ(out.AsRegisterPairHigh<Register>(), EDX);
DCHECK_EQ(in.AsRegister<Register>(), EAX);
@@ -2789,13 +2798,11 @@
break;
case DataType::Type::kFloat32:
- // Processing a Dex `float-to-long' instruction.
codegen_->InvokeRuntime(kQuickF2l, conversion, conversion->GetDexPc());
CheckEntrypointTypes<kQuickF2l, int64_t, float>();
break;
case DataType::Type::kFloat64:
- // Processing a Dex `double-to-long' instruction.
codegen_->InvokeRuntime(kQuickD2l, conversion, conversion->GetDexPc());
CheckEntrypointTypes<kQuickD2l, int64_t, double>();
break;
@@ -2806,57 +2813,18 @@
}
break;
- case DataType::Type::kUint16:
- switch (input_type) {
- case DataType::Type::kInt64:
- // Type conversion from long to short is a result of code transformations.
- if (in.IsRegisterPair()) {
- __ movzxw(out.AsRegister<Register>(), in.AsRegisterPairLow<Register>());
- } else if (in.IsDoubleStackSlot()) {
- __ movzxw(out.AsRegister<Register>(), Address(ESP, in.GetStackIndex()));
- } else {
- DCHECK(in.GetConstant()->IsLongConstant());
- int64_t value = in.GetConstant()->AsLongConstant()->GetValue();
- __ movl(out.AsRegister<Register>(), Immediate(static_cast<uint16_t>(value)));
- }
- break;
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
- case DataType::Type::kInt8:
- case DataType::Type::kInt16:
- case DataType::Type::kInt32:
- // Processing a Dex `Process a Dex `int-to-char'' instruction.
- if (in.IsRegister()) {
- __ movzxw(out.AsRegister<Register>(), in.AsRegister<Register>());
- } else if (in.IsStackSlot()) {
- __ movzxw(out.AsRegister<Register>(), Address(ESP, in.GetStackIndex()));
- } else {
- DCHECK(in.GetConstant()->IsIntConstant());
- int32_t value = in.GetConstant()->AsIntConstant()->GetValue();
- __ movl(out.AsRegister<Register>(), Immediate(static_cast<uint16_t>(value)));
- }
- break;
-
- default:
- LOG(FATAL) << "Unexpected type conversion from " << input_type
- << " to " << result_type;
- }
- break;
-
case DataType::Type::kFloat32:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-float' instruction.
__ cvtsi2ss(out.AsFpuRegister<XmmRegister>(), in.AsRegister<Register>());
break;
case DataType::Type::kInt64: {
- // Processing a Dex `long-to-float' instruction.
size_t adjustment = 0;
// Create stack space for the call to
@@ -2886,7 +2854,6 @@
}
case DataType::Type::kFloat64:
- // Processing a Dex `double-to-float' instruction.
__ cvtsd2ss(out.AsFpuRegister<XmmRegister>(), in.AsFpuRegister<XmmRegister>());
break;
@@ -2899,17 +2866,15 @@
case DataType::Type::kFloat64:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-double' instruction.
__ cvtsi2sd(out.AsFpuRegister<XmmRegister>(), in.AsRegister<Register>());
break;
case DataType::Type::kInt64: {
- // Processing a Dex `long-to-double' instruction.
size_t adjustment = 0;
// Create stack space for the call to
@@ -2939,7 +2904,6 @@
}
case DataType::Type::kFloat32:
- // Processing a Dex `float-to-double' instruction.
__ cvtss2sd(out.AsFpuRegister<XmmRegister>(), in.AsFpuRegister<XmmRegister>());
break;
@@ -3832,6 +3796,7 @@
LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction);
switch (instruction->GetType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -3860,6 +3825,7 @@
switch (instruction->GetType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -4349,9 +4315,10 @@
new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
switch (compare->InputAt(0)->GetType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32:
case DataType::Type::kInt64: {
locations->SetInAt(0, Location::RequiresRegister());
@@ -4388,9 +4355,10 @@
switch (compare->InputAt(0)->GetType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32: {
codegen_->GenerateIntCompare(left, right);
break;
@@ -4792,7 +4760,8 @@
uint32_t offset = field_info.GetFieldOffset().Uint32Value();
switch (field_type) {
- case DataType::Type::kBool: {
+ case DataType::Type::kBool:
+ case DataType::Type::kUint8: {
__ movzxb(out.AsRegister<Register>(), Address(base, offset));
break;
}
@@ -4802,13 +4771,13 @@
break;
}
- case DataType::Type::kInt16: {
- __ movsxw(out.AsRegister<Register>(), Address(base, offset));
+ case DataType::Type::kUint16: {
+ __ movzxw(out.AsRegister<Register>(), Address(base, offset));
break;
}
- case DataType::Type::kUint16: {
- __ movzxw(out.AsRegister<Register>(), Address(base, offset));
+ case DataType::Type::kInt16: {
+ __ movsxw(out.AsRegister<Register>(), Address(base, offset));
break;
}
@@ -4897,8 +4866,7 @@
locations->SetInAt(0, Location::RequiresRegister());
bool is_volatile = field_info.IsVolatile();
DataType::Type field_type = field_info.GetFieldType();
- bool is_byte_type = (field_type == DataType::Type::kBool)
- || (field_type == DataType::Type::kInt8);
+ bool is_byte_type = DataType::Size(field_type) == 1u;
// The register allocator does not support multiple
// inputs that die at entry with one in a specific register.
@@ -4957,13 +4925,14 @@
switch (field_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8: {
__ movb(Address(base, offset), value.AsRegister<ByteRegister>());
break;
}
- case DataType::Type::kInt16:
- case DataType::Type::kUint16: {
+ case DataType::Type::kUint16:
+ case DataType::Type::kInt16: {
if (value.IsConstant()) {
__ movw(Address(base, offset),
Immediate(CodeGenerator::GetInt16ValueOf(value.GetConstant())));
@@ -5242,7 +5211,8 @@
DataType::Type type = instruction->GetType();
switch (type) {
- case DataType::Type::kBool: {
+ case DataType::Type::kBool:
+ case DataType::Type::kUint8: {
Register out = out_loc.AsRegister<Register>();
__ movzxb(out, CodeGeneratorX86::ArrayAddress(obj, index, TIMES_1, data_offset));
break;
@@ -5254,12 +5224,6 @@
break;
}
- case DataType::Type::kInt16: {
- Register out = out_loc.AsRegister<Register>();
- __ movsxw(out, CodeGeneratorX86::ArrayAddress(obj, index, TIMES_2, data_offset));
- break;
- }
-
case DataType::Type::kUint16: {
Register out = out_loc.AsRegister<Register>();
if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
@@ -5284,6 +5248,12 @@
break;
}
+ case DataType::Type::kInt16: {
+ Register out = out_loc.AsRegister<Register>();
+ __ movsxw(out, CodeGeneratorX86::ArrayAddress(obj, index, TIMES_2, data_offset));
+ break;
+ }
+
case DataType::Type::kInt32: {
Register out = out_loc.AsRegister<Register>();
__ movl(out, CodeGeneratorX86::ArrayAddress(obj, index, TIMES_4, data_offset));
@@ -5368,8 +5338,7 @@
LocationSummary::kCallOnSlowPath :
LocationSummary::kNoCall);
- bool is_byte_type = (value_type == DataType::Type::kBool)
- || (value_type == DataType::Type::kInt8);
+ bool is_byte_type = DataType::Size(value_type) == 1u;
// We need the inputs to be different than the output in case of long operation.
// In case of a byte operation, the register allocator does not support multiple
// inputs that die at entry with one in a specific register.
@@ -5407,6 +5376,7 @@
switch (value_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8: {
uint32_t offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value();
Address address = CodeGeneratorX86::ArrayAddress(array, index, TIMES_1, offset);
@@ -5419,8 +5389,8 @@
break;
}
- case DataType::Type::kInt16:
- case DataType::Type::kUint16: {
+ case DataType::Type::kUint16:
+ case DataType::Type::kInt16: {
uint32_t offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value();
Address address = CodeGeneratorX86::ArrayAddress(array, index, TIMES_2, offset);
if (value.IsRegister()) {
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 42704e9..e8bfa66 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1521,6 +1521,7 @@
DataType::Type type = condition->InputAt(0)->GetType();
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -2036,9 +2037,10 @@
new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
switch (compare->InputAt(0)->GetType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32:
case DataType::Type::kInt64: {
locations->SetInAt(0, Location::RequiresRegister());
@@ -2070,9 +2072,10 @@
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32: {
codegen_->GenerateIntCompare(left, right);
break;
@@ -2207,12 +2210,13 @@
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(ret, LocationSummary::kNoCall);
switch (ret->InputAt(0)->GetType()) {
+ case DataType::Type::kReference:
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kReference:
case DataType::Type::kInt64:
locations->SetInAt(0, Location::RegisterLocation(RAX));
break;
@@ -2230,12 +2234,13 @@
void InstructionCodeGeneratorX86_64::VisitReturn(HReturn* ret) {
if (kIsDebugBuild) {
switch (ret->InputAt(0)->GetType()) {
+ case DataType::Type::kReference:
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kReference:
case DataType::Type::kInt64:
DCHECK_EQ(ret->GetLocations()->InAt(0).AsRegister<CpuRegister>().AsRegister(), RAX);
break;
@@ -2255,12 +2260,13 @@
Location InvokeDexCallingConventionVisitorX86_64::GetReturnLocation(DataType::Type type) const {
switch (type) {
+ case DataType::Type::kReference:
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kReference:
case DataType::Type::kInt64:
return Location::RegisterLocation(RAX);
@@ -2281,12 +2287,13 @@
Location InvokeDexCallingConventionVisitorX86_64::GetNextLocation(DataType::Type type) {
switch (type) {
+ case DataType::Type::kReference:
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
- case DataType::Type::kInt32:
- case DataType::Type::kReference: {
+ case DataType::Type::kInt32: {
uint32_t index = gp_index_++;
stack_index_++;
if (index < calling_convention.GetNumberOfRegisters()) {
@@ -2536,68 +2543,32 @@
new (GetGraph()->GetArena()) LocationSummary(conversion, LocationSummary::kNoCall);
DataType::Type result_type = conversion->GetResultType();
DataType::Type input_type = conversion->GetInputType();
- DCHECK_NE(result_type, input_type);
-
- // The Java language does not allow treating boolean as an integral type but
- // our bit representation makes it safe.
+ DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type))
+ << input_type << " -> " << result_type;
switch (result_type) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- switch (input_type) {
- case DataType::Type::kInt64:
- // Type conversion from long to byte is a result of code transformations.
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
- case DataType::Type::kInt16:
- case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-byte' instruction.
- locations->SetInAt(0, Location::Any());
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
- break;
-
- default:
- LOG(FATAL) << "Unexpected type conversion from " << input_type
- << " to " << result_type;
- }
- break;
-
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
- switch (input_type) {
- case DataType::Type::kInt64:
- // Type conversion from long to short is a result of code transformations.
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
- case DataType::Type::kInt8:
- case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-short' instruction.
- locations->SetInAt(0, Location::Any());
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
- break;
-
- default:
- LOG(FATAL) << "Unexpected type conversion from " << input_type
- << " to " << result_type;
- }
+ DCHECK(DataType::IsIntegralType(input_type)) << input_type;
+ locations->SetInAt(0, Location::Any());
+ locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
break;
case DataType::Type::kInt32:
switch (input_type) {
case DataType::Type::kInt64:
- // Processing a Dex `long-to-int' instruction.
locations->SetInAt(0, Location::Any());
locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
break;
case DataType::Type::kFloat32:
- // Processing a Dex `float-to-int' instruction.
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetOut(Location::RequiresRegister());
break;
case DataType::Type::kFloat64:
- // Processing a Dex `double-to-int' instruction.
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetOut(Location::RequiresRegister());
break;
@@ -2611,12 +2582,11 @@
case DataType::Type::kInt64:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-long' instruction.
// TODO: We would benefit from a (to-be-implemented)
// Location::RegisterOrStackSlot requirement for this input.
locations->SetInAt(0, Location::RequiresRegister());
@@ -2624,13 +2594,11 @@
break;
case DataType::Type::kFloat32:
- // Processing a Dex `float-to-long' instruction.
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetOut(Location::RequiresRegister());
break;
case DataType::Type::kFloat64:
- // Processing a Dex `double-to-long' instruction.
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetOut(Location::RequiresRegister());
break;
@@ -2641,47 +2609,24 @@
}
break;
- case DataType::Type::kUint16:
- switch (input_type) {
- case DataType::Type::kInt64:
- // Type conversion from long to char is a result of code transformations.
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
- case DataType::Type::kInt8:
- case DataType::Type::kInt16:
- case DataType::Type::kInt32:
- // Processing a Dex `int-to-char' instruction.
- locations->SetInAt(0, Location::Any());
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
- break;
-
- default:
- LOG(FATAL) << "Unexpected type conversion from " << input_type
- << " to " << result_type;
- }
- break;
-
case DataType::Type::kFloat32:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-float' instruction.
locations->SetInAt(0, Location::Any());
locations->SetOut(Location::RequiresFpuRegister());
break;
case DataType::Type::kInt64:
- // Processing a Dex `long-to-float' instruction.
locations->SetInAt(0, Location::Any());
locations->SetOut(Location::RequiresFpuRegister());
break;
case DataType::Type::kFloat64:
- // Processing a Dex `double-to-float' instruction.
locations->SetInAt(0, Location::Any());
locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
break;
@@ -2695,24 +2640,21 @@
case DataType::Type::kFloat64:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-double' instruction.
locations->SetInAt(0, Location::Any());
locations->SetOut(Location::RequiresFpuRegister());
break;
case DataType::Type::kInt64:
- // Processing a Dex `long-to-double' instruction.
locations->SetInAt(0, Location::Any());
locations->SetOut(Location::RequiresFpuRegister());
break;
case DataType::Type::kFloat32:
- // Processing a Dex `float-to-double' instruction.
locations->SetInAt(0, Location::Any());
locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
break;
@@ -2735,18 +2677,40 @@
Location in = locations->InAt(0);
DataType::Type result_type = conversion->GetResultType();
DataType::Type input_type = conversion->GetInputType();
- DCHECK_NE(result_type, input_type);
+ DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type))
+ << input_type << " -> " << result_type;
switch (result_type) {
- case DataType::Type::kInt8:
+ case DataType::Type::kUint8:
switch (input_type) {
- case DataType::Type::kInt64:
- // Type conversion from long to byte is a result of code transformations.
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
+ case DataType::Type::kInt64:
+ if (in.IsRegister()) {
+ __ movzxb(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>());
+ } else if (in.IsStackSlot() || in.IsDoubleStackSlot()) {
+ __ movzxb(out.AsRegister<CpuRegister>(),
+ Address(CpuRegister(RSP), in.GetStackIndex()));
+ } else {
+ __ movl(out.AsRegister<CpuRegister>(),
+ Immediate(static_cast<uint8_t>(Int64FromConstant(in.GetConstant()))));
+ }
+ break;
+
+ default:
+ LOG(FATAL) << "Unexpected type conversion from " << input_type
+ << " to " << result_type;
+ }
+ break;
+
+ case DataType::Type::kInt8:
+ switch (input_type) {
+ case DataType::Type::kUint8:
case DataType::Type::kUint16:
- // Processing a Dex `int-to-byte' instruction.
+ case DataType::Type::kInt16:
+ case DataType::Type::kInt32:
+ case DataType::Type::kInt64:
if (in.IsRegister()) {
__ movsxb(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>());
} else if (in.IsStackSlot() || in.IsDoubleStackSlot()) {
@@ -2764,16 +2728,34 @@
}
break;
+ case DataType::Type::kUint16:
+ switch (input_type) {
+ case DataType::Type::kInt8:
+ case DataType::Type::kInt16:
+ case DataType::Type::kInt32:
+ case DataType::Type::kInt64:
+ if (in.IsRegister()) {
+ __ movzxw(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>());
+ } else if (in.IsStackSlot() || in.IsDoubleStackSlot()) {
+ __ movzxw(out.AsRegister<CpuRegister>(),
+ Address(CpuRegister(RSP), in.GetStackIndex()));
+ } else {
+ __ movl(out.AsRegister<CpuRegister>(),
+ Immediate(static_cast<uint16_t>(Int64FromConstant(in.GetConstant()))));
+ }
+ break;
+
+ default:
+ LOG(FATAL) << "Unexpected type conversion from " << input_type
+ << " to " << result_type;
+ }
+ break;
+
case DataType::Type::kInt16:
switch (input_type) {
- case DataType::Type::kInt64:
- // Type conversion from long to short is a result of code transformations.
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
- case DataType::Type::kInt8:
- case DataType::Type::kInt32:
case DataType::Type::kUint16:
- // Processing a Dex `int-to-short' instruction.
+ case DataType::Type::kInt32:
+ case DataType::Type::kInt64:
if (in.IsRegister()) {
__ movsxw(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>());
} else if (in.IsStackSlot() || in.IsDoubleStackSlot()) {
@@ -2794,7 +2776,6 @@
case DataType::Type::kInt32:
switch (input_type) {
case DataType::Type::kInt64:
- // Processing a Dex `long-to-int' instruction.
if (in.IsRegister()) {
__ movl(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>());
} else if (in.IsDoubleStackSlot()) {
@@ -2809,7 +2790,6 @@
break;
case DataType::Type::kFloat32: {
- // Processing a Dex `float-to-int' instruction.
XmmRegister input = in.AsFpuRegister<XmmRegister>();
CpuRegister output = out.AsRegister<CpuRegister>();
NearLabel done, nan;
@@ -2831,7 +2811,6 @@
}
case DataType::Type::kFloat64: {
- // Processing a Dex `double-to-int' instruction.
XmmRegister input = in.AsFpuRegister<XmmRegister>();
CpuRegister output = out.AsRegister<CpuRegister>();
NearLabel done, nan;
@@ -2862,18 +2841,16 @@
switch (input_type) {
DCHECK(out.IsRegister());
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-long' instruction.
DCHECK(in.IsRegister());
__ movsxd(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>());
break;
case DataType::Type::kFloat32: {
- // Processing a Dex `float-to-long' instruction.
XmmRegister input = in.AsFpuRegister<XmmRegister>();
CpuRegister output = out.AsRegister<CpuRegister>();
NearLabel done, nan;
@@ -2895,7 +2872,6 @@
}
case DataType::Type::kFloat64: {
- // Processing a Dex `double-to-long' instruction.
XmmRegister input = in.AsFpuRegister<XmmRegister>();
CpuRegister output = out.AsRegister<CpuRegister>();
NearLabel done, nan;
@@ -2922,42 +2898,14 @@
}
break;
- case DataType::Type::kUint16:
- switch (input_type) {
- case DataType::Type::kInt64:
- // Type conversion from long to char is a result of code transformations.
- case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
- case DataType::Type::kInt8:
- case DataType::Type::kInt16:
- case DataType::Type::kInt32:
- // Processing a Dex `int-to-char' instruction.
- if (in.IsRegister()) {
- __ movzxw(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>());
- } else if (in.IsStackSlot() || in.IsDoubleStackSlot()) {
- __ movzxw(out.AsRegister<CpuRegister>(),
- Address(CpuRegister(RSP), in.GetStackIndex()));
- } else {
- __ movl(out.AsRegister<CpuRegister>(),
- Immediate(static_cast<uint16_t>(Int64FromConstant(in.GetConstant()))));
- }
- break;
-
- default:
- LOG(FATAL) << "Unexpected type conversion from " << input_type
- << " to " << result_type;
- }
- break;
-
case DataType::Type::kFloat32:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-float' instruction.
if (in.IsRegister()) {
__ cvtsi2ss(out.AsFpuRegister<XmmRegister>(), in.AsRegister<CpuRegister>(), false);
} else if (in.IsConstant()) {
@@ -2971,7 +2919,6 @@
break;
case DataType::Type::kInt64:
- // Processing a Dex `long-to-float' instruction.
if (in.IsRegister()) {
__ cvtsi2ss(out.AsFpuRegister<XmmRegister>(), in.AsRegister<CpuRegister>(), true);
} else if (in.IsConstant()) {
@@ -2985,7 +2932,6 @@
break;
case DataType::Type::kFloat64:
- // Processing a Dex `double-to-float' instruction.
if (in.IsFpuRegister()) {
__ cvtsd2ss(out.AsFpuRegister<XmmRegister>(), in.AsFpuRegister<XmmRegister>());
} else if (in.IsConstant()) {
@@ -3007,12 +2953,11 @@
case DataType::Type::kFloat64:
switch (input_type) {
case DataType::Type::kBool:
- // Boolean input is a result of code transformations.
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
case DataType::Type::kInt16:
case DataType::Type::kInt32:
- case DataType::Type::kUint16:
- // Processing a Dex `int-to-double' instruction.
if (in.IsRegister()) {
__ cvtsi2sd(out.AsFpuRegister<XmmRegister>(), in.AsRegister<CpuRegister>(), false);
} else if (in.IsConstant()) {
@@ -3026,7 +2971,6 @@
break;
case DataType::Type::kInt64:
- // Processing a Dex `long-to-double' instruction.
if (in.IsRegister()) {
__ cvtsi2sd(out.AsFpuRegister<XmmRegister>(), in.AsRegister<CpuRegister>(), true);
} else if (in.IsConstant()) {
@@ -3040,7 +2984,6 @@
break;
case DataType::Type::kFloat32:
- // Processing a Dex `float-to-double' instruction.
if (in.IsFpuRegister()) {
__ cvtss2sd(out.AsFpuRegister<XmmRegister>(), in.AsFpuRegister<XmmRegister>());
} else if (in.IsConstant()) {
@@ -3883,6 +3826,7 @@
switch (instruction->GetType()) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -4290,7 +4234,8 @@
uint32_t offset = field_info.GetFieldOffset().Uint32Value();
switch (field_type) {
- case DataType::Type::kBool: {
+ case DataType::Type::kBool:
+ case DataType::Type::kUint8: {
__ movzxb(out.AsRegister<CpuRegister>(), Address(base, offset));
break;
}
@@ -4300,13 +4245,13 @@
break;
}
- case DataType::Type::kInt16: {
- __ movsxw(out.AsRegister<CpuRegister>(), Address(base, offset));
+ case DataType::Type::kUint16: {
+ __ movzxw(out.AsRegister<CpuRegister>(), Address(base, offset));
break;
}
- case DataType::Type::kUint16: {
- __ movzxw(out.AsRegister<CpuRegister>(), Address(base, offset));
+ case DataType::Type::kInt16: {
+ __ movsxw(out.AsRegister<CpuRegister>(), Address(base, offset));
break;
}
@@ -4433,6 +4378,7 @@
switch (field_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8: {
if (value.IsConstant()) {
__ movb(Address(base, offset),
@@ -4443,8 +4389,8 @@
break;
}
- case DataType::Type::kInt16:
- case DataType::Type::kUint16: {
+ case DataType::Type::kUint16:
+ case DataType::Type::kInt16: {
if (value.IsConstant()) {
__ movw(Address(base, offset),
Immediate(CodeGenerator::GetInt16ValueOf(value.GetConstant())));
@@ -4714,7 +4660,8 @@
DataType::Type type = instruction->GetType();
switch (type) {
- case DataType::Type::kBool: {
+ case DataType::Type::kBool:
+ case DataType::Type::kUint8: {
CpuRegister out = out_loc.AsRegister<CpuRegister>();
__ movzxb(out, CodeGeneratorX86_64::ArrayAddress(obj, index, TIMES_1, data_offset));
break;
@@ -4726,12 +4673,6 @@
break;
}
- case DataType::Type::kInt16: {
- CpuRegister out = out_loc.AsRegister<CpuRegister>();
- __ movsxw(out, CodeGeneratorX86_64::ArrayAddress(obj, index, TIMES_2, data_offset));
- break;
- }
-
case DataType::Type::kUint16: {
CpuRegister out = out_loc.AsRegister<CpuRegister>();
if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
@@ -4754,6 +4695,12 @@
break;
}
+ case DataType::Type::kInt16: {
+ CpuRegister out = out_loc.AsRegister<CpuRegister>();
+ __ movsxw(out, CodeGeneratorX86_64::ArrayAddress(obj, index, TIMES_2, data_offset));
+ break;
+ }
+
case DataType::Type::kInt32: {
CpuRegister out = out_loc.AsRegister<CpuRegister>();
__ movl(out, CodeGeneratorX86_64::ArrayAddress(obj, index, TIMES_4, data_offset));
@@ -4865,6 +4812,7 @@
switch (value_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8: {
uint32_t offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value();
Address address = CodeGeneratorX86_64::ArrayAddress(array, index, TIMES_1, offset);
@@ -4877,8 +4825,8 @@
break;
}
- case DataType::Type::kInt16:
- case DataType::Type::kUint16: {
+ case DataType::Type::kUint16:
+ case DataType::Type::kInt16: {
uint32_t offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value();
Address address = CodeGeneratorX86_64::ArrayAddress(array, index, TIMES_2, offset);
if (value.IsRegister()) {
diff --git a/compiler/optimizing/data_type-inl.h b/compiler/optimizing/data_type-inl.h
index fbc0c12..e389bad 100644
--- a/compiler/optimizing/data_type-inl.h
+++ b/compiler/optimizing/data_type-inl.h
@@ -46,17 +46,19 @@
constexpr char DataType::TypeId(DataType::Type type) {
// Type id for visualizer.
+ // Types corresponding to Java types are given a lower-case version of their shorty character.
switch (type) {
- case DataType::Type::kBool: return 'z';
- case DataType::Type::kInt8: return 'b';
- case DataType::Type::kUint16: return 'c';
- case DataType::Type::kInt16: return 's';
- case DataType::Type::kInt32: return 'i';
- case DataType::Type::kInt64: return 'j';
- case DataType::Type::kFloat32: return 'f';
- case DataType::Type::kFloat64: return 'd';
- case DataType::Type::kReference: return 'l';
- case DataType::Type::kVoid: return 'v';
+ case DataType::Type::kBool: return 'z'; // Java boolean (Z).
+ case DataType::Type::kUint8: return 'a'; // The character before Java byte's 'b'.
+ case DataType::Type::kInt8: return 'b'; // Java byte (B).
+ case DataType::Type::kUint16: return 'c'; // Java char (C).
+ case DataType::Type::kInt16: return 's'; // Java short (S).
+ case DataType::Type::kInt32: return 'i'; // Java int (I).
+ case DataType::Type::kInt64: return 'j'; // Java long (J).
+ case DataType::Type::kFloat32: return 'f'; // Java float (F).
+ case DataType::Type::kFloat64: return 'd'; // Java double (D).
+ case DataType::Type::kReference: return 'l'; // Java reference (L).
+ case DataType::Type::kVoid: return 'v'; // Java void (V).
}
LOG(FATAL) << "Unreachable";
UNREACHABLE();
diff --git a/compiler/optimizing/data_type.cc b/compiler/optimizing/data_type.cc
index 6890617..3c99a76 100644
--- a/compiler/optimizing/data_type.cc
+++ b/compiler/optimizing/data_type.cc
@@ -21,6 +21,7 @@
static const char* kTypeNames[] = {
"Reference",
"Bool",
+ "Uint8",
"Int8",
"Uint16",
"Int16",
diff --git a/compiler/optimizing/data_type.h b/compiler/optimizing/data_type.h
index 08f9263..5a023ad 100644
--- a/compiler/optimizing/data_type.h
+++ b/compiler/optimizing/data_type.h
@@ -29,6 +29,7 @@
enum class Type : uint8_t {
kReference = 0,
kBool,
+ kUint8,
kInt8,
kUint16,
kInt16,
@@ -47,6 +48,7 @@
switch (type) {
case Type::kVoid:
case Type::kBool:
+ case Type::kUint8:
case Type::kInt8:
return 0;
case Type::kUint16:
@@ -71,6 +73,7 @@
case Type::kVoid:
return 0;
case Type::kBool:
+ case Type::kUint8:
case Type::kInt8:
return 1;
case Type::kUint16:
@@ -99,6 +102,7 @@
// our bit representation makes it safe.
switch (type) {
case Type::kBool:
+ case Type::kUint8:
case Type::kInt8:
case Type::kUint16:
case Type::kInt16:
@@ -118,10 +122,27 @@
return type == Type::kInt64 || type == Type::kFloat64;
}
+ static bool IsUnsignedType(Type type) {
+ return type == Type::kUint8 || type == Type::kUint16;
+ }
+
+ static Type ToSignedType(Type type) {
+ switch (type) {
+ case Type::kUint8:
+ return Type::kInt8;
+ case Type::kUint16:
+ return Type::kInt16;
+ default:
+ DCHECK(type != Type::kVoid && type != Type::kReference);
+ return type;
+ }
+ }
+
// Return the general kind of `type`, fusing integer-like types as Type::kInt.
static Type Kind(Type type) {
switch (type) {
case Type::kBool:
+ case Type::kUint8:
case Type::kInt8:
case Type::kInt16:
case Type::kUint16:
@@ -136,6 +157,8 @@
switch (type) {
case Type::kBool:
return std::numeric_limits<bool>::min();
+ case Type::kUint8:
+ return std::numeric_limits<uint8_t>::min();
case Type::kInt8:
return std::numeric_limits<int8_t>::min();
case Type::kUint16:
@@ -156,6 +179,8 @@
switch (type) {
case Type::kBool:
return std::numeric_limits<bool>::max();
+ case Type::kUint8:
+ return std::numeric_limits<uint8_t>::max();
case Type::kInt8:
return std::numeric_limits<int8_t>::max();
case Type::kUint16:
@@ -172,6 +197,8 @@
return 0;
}
+ static bool IsTypeConversionImplicit(Type input_type, Type result_type);
+
static const char* PrettyDescriptor(Type type);
private:
@@ -179,6 +206,25 @@
};
std::ostream& operator<<(std::ostream& os, DataType::Type data_type);
+// Defined outside DataType to have the operator<< available for DCHECK_NE().
+inline bool DataType::IsTypeConversionImplicit(Type input_type, Type result_type) {
+ DCHECK_NE(DataType::Type::kVoid, result_type);
+ DCHECK_NE(DataType::Type::kVoid, input_type);
+
+ // Invariant: We should never generate a conversion to a Boolean value.
+ DCHECK_NE(DataType::Type::kBool, result_type);
+
+ // Besides conversion to the same type, integral conversions to non-Int64 types
+ // are implicit if the result value range covers the input value range, i.e.
+ // widening conversions that do not need to trim the sign bits.
+ return result_type == input_type ||
+ (result_type != Type::kInt64 &&
+ IsIntegralType(input_type) &&
+ IsIntegralType(result_type) &&
+ MinValueOfIntegralType(input_type) >= MinValueOfIntegralType(result_type) &&
+ MaxValueOfIntegralType(input_type) <= MaxValueOfIntegralType(result_type));
+}
+
} // namespace art
#endif // ART_COMPILER_OPTIMIZING_DATA_TYPE_H_
diff --git a/compiler/optimizing/data_type_test.cc b/compiler/optimizing/data_type_test.cc
index 927291a..3ce683a 100644
--- a/compiler/optimizing/data_type_test.cc
+++ b/compiler/optimizing/data_type_test.cc
@@ -18,6 +18,8 @@
#include "data_type-inl.h"
+#include "base/array_ref.h"
+#include "base/macros.h"
#include "primitive.h"
namespace art {
@@ -57,4 +59,58 @@
#undef CHECK_NAME
}
+TEST(DataType, IsTypeConversionImplicit) {
+ static const DataType::Type kIntegralTypes[] = {
+ DataType::Type::kBool,
+ DataType::Type::kUint8,
+ DataType::Type::kInt8,
+ DataType::Type::kUint16,
+ DataType::Type::kInt16,
+ DataType::Type::kInt32,
+ DataType::Type::kInt64,
+ };
+ const ArrayRef<const DataType::Type> kIntegralInputTypes(kIntegralTypes);
+ // Note: kBool cannot be used as a result type.
+ DCHECK_EQ(kIntegralTypes[0], DataType::Type::kBool);
+ const ArrayRef<const DataType::Type> kIntegralResultTypes = kIntegralInputTypes.SubArray(1u);
+
+ static const bool kImplicitIntegralConversions[][arraysize(kIntegralTypes)] = {
+ // Bool Uint8 Int8 Uint16 Int16 Int32 Int64
+ { /* Bool N/A */ true, true, true, true, true, false },
+ { /* Uint8 N/A */ true, false, true, true, true, false },
+ { /* Int8 N/A */ false, true, false, true, true, false },
+ { /* Uint16 N/A */ false, false, true, false, true, false },
+ { /* Int16 N/A */ false, false, false, true, true, false },
+ { /* Int32 N/A */ false, false, false, false, true, false },
+ { /* Int64 N/A */ false, false, false, false, false, true },
+ };
+ static_assert(arraysize(kIntegralTypes) == arraysize(kImplicitIntegralConversions), "size check");
+
+ for (size_t input_index = 0; input_index != kIntegralInputTypes.size(); ++input_index) {
+ DataType::Type input_type = kIntegralInputTypes[input_index];
+ for (size_t result_index = 1u; result_index != kIntegralResultTypes.size(); ++result_index) {
+ DataType::Type result_type = kIntegralResultTypes[result_index];
+ EXPECT_EQ(kImplicitIntegralConversions[input_index][result_index],
+ DataType::IsTypeConversionImplicit(input_type, result_type))
+ << input_type << " " << result_type;
+ }
+ }
+ for (DataType::Type input_type : kIntegralInputTypes) {
+ EXPECT_FALSE(DataType::IsTypeConversionImplicit(input_type, DataType::Type::kFloat32));
+ EXPECT_FALSE(DataType::IsTypeConversionImplicit(input_type, DataType::Type::kFloat64));
+ }
+ for (DataType::Type result_type : kIntegralResultTypes) {
+ EXPECT_FALSE(DataType::IsTypeConversionImplicit(DataType::Type::kFloat32, result_type));
+ EXPECT_FALSE(DataType::IsTypeConversionImplicit(DataType::Type::kFloat64, result_type));
+ }
+ EXPECT_TRUE(
+ DataType::IsTypeConversionImplicit(DataType::Type::kFloat32, DataType::Type::kFloat32));
+ EXPECT_FALSE(
+ DataType::IsTypeConversionImplicit(DataType::Type::kFloat32, DataType::Type::kFloat64));
+ EXPECT_FALSE(
+ DataType::IsTypeConversionImplicit(DataType::Type::kFloat64, DataType::Type::kFloat32));
+ EXPECT_TRUE(
+ DataType::IsTypeConversionImplicit(DataType::Type::kFloat64, DataType::Type::kFloat64));
+}
+
} // namespace art
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 194f063..eccdccf 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -521,20 +521,28 @@
StartAttributeStream("kind") << deoptimize->GetKind();
}
+ void VisitVecOperation(HVecOperation* vec_operation) OVERRIDE {
+ StartAttributeStream("packed_type") << vec_operation->GetPackedType();
+ }
+
void VisitVecHalvingAdd(HVecHalvingAdd* hadd) OVERRIDE {
+ VisitVecBinaryOperation(hadd);
StartAttributeStream("unsigned") << std::boolalpha << hadd->IsUnsigned() << std::noboolalpha;
StartAttributeStream("rounded") << std::boolalpha << hadd->IsRounded() << std::noboolalpha;
}
void VisitVecMin(HVecMin* min) OVERRIDE {
+ VisitVecBinaryOperation(min);
StartAttributeStream("unsigned") << std::boolalpha << min->IsUnsigned() << std::noboolalpha;
}
void VisitVecMax(HVecMax* max) OVERRIDE {
+ VisitVecBinaryOperation(max);
StartAttributeStream("unsigned") << std::boolalpha << max->IsUnsigned() << std::noboolalpha;
}
void VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) OVERRIDE {
+ VisitVecOperation(instruction);
StartAttributeStream("kind") << instruction->GetOpKind();
}
diff --git a/compiler/optimizing/induction_var_analysis.cc b/compiler/optimizing/induction_var_analysis.cc
index fe286ab..eab17aa 100644
--- a/compiler/optimizing/induction_var_analysis.cc
+++ b/compiler/optimizing/induction_var_analysis.cc
@@ -59,14 +59,19 @@
static bool IsNarrowingIntegralConversion(DataType::Type from, DataType::Type to) {
switch (from) {
case DataType::Type::kInt64:
- return to == DataType::Type::kInt8 || to == DataType::Type::kInt16
- || to == DataType::Type::kUint16 || to == DataType::Type::kInt32;
+ return to == DataType::Type::kUint8 ||
+ to == DataType::Type::kInt8 ||
+ to == DataType::Type::kUint16 ||
+ to == DataType::Type::kInt16 ||
+ to == DataType::Type::kInt32;
case DataType::Type::kInt32:
- return to == DataType::Type::kInt8 || to == DataType::Type::kInt16
- || to == DataType::Type::kUint16;
+ return to == DataType::Type::kUint8 ||
+ to == DataType::Type::kInt8 ||
+ to == DataType::Type::kUint16 ||
+ to == DataType::Type::kInt16;
case DataType::Type::kUint16:
case DataType::Type::kInt16:
- return to == DataType::Type::kInt8;
+ return to == DataType::Type::kUint8 || to == DataType::Type::kInt8;
default:
return false;
}
@@ -77,10 +82,11 @@
*/
static DataType::Type ImplicitConversion(DataType::Type type) {
switch (type) {
- case DataType::Type::kInt16:
- case DataType::Type::kUint16:
- case DataType::Type::kInt8:
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
+ case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
return DataType::Type::kInt32;
default:
return type;
@@ -1142,9 +1148,10 @@
bool HInductionVarAnalysis::IsNarrowingLinear(InductionInfo* info) {
return info != nullptr &&
info->induction_class == kLinear &&
- (info->type == DataType::Type::kInt8 ||
- info->type == DataType::Type::kInt16 ||
+ (info->type == DataType::Type::kUint8 ||
+ info->type == DataType::Type::kInt8 ||
info->type == DataType::Type::kUint16 ||
+ info->type == DataType::Type::kInt16 ||
(info->type == DataType::Type::kInt32 && (info->op_a->type == DataType::Type::kInt64 ||
info->op_b->type == DataType::Type::kInt64)));
}
diff --git a/compiler/optimizing/induction_var_range.cc b/compiler/optimizing/induction_var_range.cc
index 92b584c..ab6fbae 100644
--- a/compiler/optimizing/induction_var_range.cc
+++ b/compiler/optimizing/induction_var_range.cc
@@ -159,9 +159,10 @@
/** Corrects a value for type to account for arithmetic wrap-around in lower precision. */
static InductionVarRange::Value CorrectForType(InductionVarRange::Value v, DataType::Type type) {
switch (type) {
- case DataType::Type::kInt16:
+ case DataType::Type::kUint8:
+ case DataType::Type::kInt8:
case DataType::Type::kUint16:
- case DataType::Type::kInt8: {
+ case DataType::Type::kInt16: {
// Constants within range only.
// TODO: maybe some room for improvement, like allowing widening conversions
int32_t min = DataType::MinValueOfIntegralType(type);
@@ -216,10 +217,11 @@
// bounds check elimination, will have truncated higher precision induction
// at their use point already).
switch (info->type) {
- case DataType::Type::kInt32:
- case DataType::Type::kInt16:
- case DataType::Type::kUint16:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
+ case DataType::Type::kInt32:
break;
default:
return false;
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index cf1cbd5..f739d7b 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -251,7 +251,8 @@
InstructionSet isa = codegen_->GetInstructionSet();
switch (isa) {
case kArm64:
- if (!(type == DataType::Type::kInt8 ||
+ if (!(type == DataType::Type::kUint8 ||
+ type == DataType::Type::kInt8 ||
type == DataType::Type::kUint16 ||
type == DataType::Type::kInt16 ||
type == DataType::Type::kInt32)) {
@@ -260,7 +261,8 @@
break;
case kMips:
case kMips64:
- if (!(type == DataType::Type::kInt8 ||
+ if (!(type == DataType::Type::kUint8 ||
+ type == DataType::Type::kInt8 ||
type == DataType::Type::kUint16 ||
type == DataType::Type::kInt16 ||
type == DataType::Type::kInt32 ||
@@ -876,10 +878,11 @@
}
DataType::Type type1 = a->GetType();
DataType::Type type2 = b->GetType();
- return (type1 == DataType::Type::kInt8 && type2 == DataType::Type::kInt8) ||
- (type1 == DataType::Type::kInt16 && type2 == DataType::Type::kInt16) ||
- (type1 == DataType::Type::kUint16 && type2 == DataType::Type::kUint16) ||
- (type1 == DataType::Type::kInt32 && type2 == DataType::Type::kInt32 &&
+ return (type1 == DataType::Type::kUint8 && type2 == DataType::Type::kUint8) ||
+ (type1 == DataType::Type::kInt8 && type2 == DataType::Type::kInt8) ||
+ (type1 == DataType::Type::kInt16 && type2 == DataType::Type::kInt16) ||
+ (type1 == DataType::Type::kUint16 && type2 == DataType::Type::kUint16) ||
+ (type1 == DataType::Type::kInt32 && type2 == DataType::Type::kInt32 &&
to_type == DataType::Type::kInt64);
}
@@ -1036,30 +1039,13 @@
}
}
-static bool IsTypeConversionImplicit(DataType::Type input_type, DataType::Type result_type) {
- // Invariant: We should never generate a conversion to a Boolean value.
- DCHECK_NE(DataType::Type::kBool, result_type);
-
- // Besides conversion to the same type, widening integral conversions are implicit,
- // excluding conversions to long and the byte->char conversion where we need to
- // clear the high 16 bits of the 32-bit sign-extended representation of byte.
- return result_type == input_type ||
- (result_type == DataType::Type::kInt32 && (input_type == DataType::Type::kBool ||
- input_type == DataType::Type::kInt8 ||
- input_type == DataType::Type::kInt16 ||
- input_type == DataType::Type::kUint16)) ||
- (result_type == DataType::Type::kUint16 && input_type == DataType::Type::kBool) ||
- (result_type == DataType::Type::kInt16 && (input_type == DataType::Type::kBool ||
- input_type == DataType::Type::kInt8)) ||
- (result_type == DataType::Type::kInt8 && input_type == DataType::Type::kBool);
-}
-
static bool IsTypeConversionLossless(DataType::Type input_type, DataType::Type result_type) {
// The conversion to a larger type is loss-less with the exception of two cases,
- // - conversion to Uint16, the only unsigned type, where we may lose some bits, and
+ // - conversion to the unsigned type Uint16, where we may lose some bits, and
// - conversion from float to long, the only FP to integral conversion with smaller FP type.
// For integral to FP conversions this holds because the FP mantissa is large enough.
- DCHECK_NE(input_type, result_type);
+ // Note: The size check excludes Uint8 as the result type.
+ DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type));
return DataType::Size(result_type) > DataType::Size(input_type) &&
result_type != DataType::Type::kUint16 &&
!(result_type == DataType::Type::kInt64 && input_type == DataType::Type::kFloat32);
@@ -1069,7 +1055,7 @@
HInstruction* input = instruction->GetInput();
DataType::Type input_type = input->GetType();
DataType::Type result_type = instruction->GetResultType();
- if (IsTypeConversionImplicit(input_type, result_type)) {
+ if (DataType::IsTypeConversionImplicit(input_type, result_type)) {
// Remove the implicit conversion; this includes conversion to the same type.
instruction->ReplaceWith(input);
instruction->GetBlock()->RemoveInstruction(instruction);
@@ -1098,7 +1084,7 @@
if (is_first_conversion_lossless || integral_conversions_with_non_widening_second) {
// If the merged conversion is implicit, do the simplification unconditionally.
- if (IsTypeConversionImplicit(original_type, result_type)) {
+ if (DataType::IsTypeConversionImplicit(original_type, result_type)) {
instruction->ReplaceWith(original_input);
instruction->GetBlock()->RemoveInstruction(instruction);
if (!input_conversion->HasUses()) {
@@ -1127,7 +1113,7 @@
if (trailing_ones >= kBitsPerByte * DataType::Size(result_type)) {
// The `HAnd` is useless, for example in `(byte) (x & 0xff)`, get rid of it.
HInstruction* original_input = input_and->GetLeastConstantLeft();
- if (IsTypeConversionImplicit(original_input->GetType(), result_type)) {
+ if (DataType::IsTypeConversionImplicit(original_input->GetType(), result_type)) {
instruction->ReplaceWith(original_input);
instruction->GetBlock()->RemoveInstruction(instruction);
RecordSimplification();
@@ -2167,8 +2153,12 @@
HBoundsCheck* bounds_check = new (arena) HBoundsCheck(
index, length, dex_pc, invoke->GetDexMethodIndex());
invoke->GetBlock()->InsertInstructionBefore(bounds_check, invoke);
- HArrayGet* array_get = new (arena) HArrayGet(
- str, bounds_check, DataType::Type::kUint16, dex_pc, /* is_string_char_at */ true);
+ HArrayGet* array_get = new (arena) HArrayGet(str,
+ bounds_check,
+ DataType::Type::kUint16,
+ SideEffects::None(), // Strings are immutable.
+ dex_pc,
+ /* is_string_char_at */ true);
invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, array_get);
bounds_check->CopyEnvironmentFrom(invoke->GetEnvironment());
GetGraph()->SetHasBoundsChecks(true);
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc
index bd14f2b..54c2d43 100644
--- a/compiler/optimizing/load_store_elimination.cc
+++ b/compiler/optimizing/load_store_elimination.cc
@@ -276,6 +276,7 @@
case DataType::Type::kReference:
return GetGraph()->GetNullConstant();
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index fec64e2..2090a12 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -28,6 +28,46 @@
namespace art {
+// TODO: Clean up the packed type detection so that we have the right type straight away
+// and do not need to go through this normalization.
+static inline void NormalizePackedType(/* inout */ DataType::Type* type,
+ /* inout */ bool* is_unsigned) {
+ switch (*type) {
+ case DataType::Type::kBool:
+ DCHECK(!*is_unsigned);
+ break;
+ case DataType::Type::kUint8:
+ case DataType::Type::kInt8:
+ if (*is_unsigned) {
+ *is_unsigned = false;
+ *type = DataType::Type::kUint8;
+ } else {
+ *type = DataType::Type::kInt8;
+ }
+ break;
+ case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
+ if (*is_unsigned) {
+ *is_unsigned = false;
+ *type = DataType::Type::kUint16;
+ } else {
+ *type = DataType::Type::kInt16;
+ }
+ break;
+ case DataType::Type::kInt32:
+ case DataType::Type::kInt64:
+ // We do not have kUint32 and kUint64 at the moment.
+ break;
+ case DataType::Type::kFloat32:
+ case DataType::Type::kFloat64:
+ DCHECK(!*is_unsigned);
+ break;
+ default:
+ LOG(FATAL) << "Unexpected type " << *type;
+ UNREACHABLE();
+ }
+}
+
// Enables vectorization (SIMDization) in the loop optimizer.
static constexpr bool kEnableVectorization = true;
@@ -87,6 +127,7 @@
int64_t value = 0;
if (IsInt64AndGet(instruction, /*out*/ &value)) {
switch (type) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
if (IsInt<8>(value)) {
*operand = instruction;
@@ -151,6 +192,7 @@
int64_t value = 0;
if (IsInt64AndGet(instruction, /*out*/ &value)) {
switch (type) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
if (IsUint<8>(value)) {
*operand = instruction;
@@ -170,9 +212,13 @@
}
// An implicit widening conversion of any unsigned expression zero-extends.
if (instruction->GetType() == type) {
- if (type == DataType::Type::kUint16) {
- *operand = instruction;
- return true;
+ switch (type) {
+ case DataType::Type::kUint8:
+ case DataType::Type::kUint16:
+ *operand = instruction;
+ return true;
+ default:
+ return false;
}
}
// A sign (or zero) extension followed by an explicit removal of just the
@@ -190,6 +236,7 @@
(IsInt64AndGet(b, /*out*/ &mask) && (IsSignExtensionAndGet(a, type, /*out*/ operand) ||
IsZeroExtensionAndGet(a, type, /*out*/ operand)))) {
switch ((*operand)->GetType()) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
return mask == std::numeric_limits<uint8_t>::max();
case DataType::Type::kUint16:
@@ -257,51 +304,10 @@
// Compute relative vector length based on type difference.
static size_t GetOtherVL(DataType::Type other_type, DataType::Type vector_type, size_t vl) {
- switch (other_type) {
- case DataType::Type::kBool:
- case DataType::Type::kInt8:
- switch (vector_type) {
- case DataType::Type::kBool:
- case DataType::Type::kInt8: return vl;
- default: break;
- }
- return vl;
- case DataType::Type::kUint16:
- case DataType::Type::kInt16:
- switch (vector_type) {
- case DataType::Type::kBool:
- case DataType::Type::kInt8: return vl >> 1;
- case DataType::Type::kUint16:
- case DataType::Type::kInt16: return vl;
- default: break;
- }
- break;
- case DataType::Type::kInt32:
- switch (vector_type) {
- case DataType::Type::kBool:
- case DataType::Type::kInt8: return vl >> 2;
- case DataType::Type::kUint16:
- case DataType::Type::kInt16: return vl >> 1;
- case DataType::Type::kInt32: return vl;
- default: break;
- }
- break;
- case DataType::Type::kInt64:
- switch (vector_type) {
- case DataType::Type::kBool:
- case DataType::Type::kInt8: return vl >> 3;
- case DataType::Type::kUint16:
- case DataType::Type::kInt16: return vl >> 2;
- case DataType::Type::kInt32: return vl >> 1;
- case DataType::Type::kInt64: return vl;
- default: break;
- }
- break;
- default:
- break;
- }
- LOG(FATAL) << "Unsupported idiom conversion";
- UNREACHABLE();
+ DCHECK(DataType::IsIntegralType(other_type));
+ DCHECK(DataType::IsIntegralType(vector_type));
+ DCHECK_GE(DataType::SizeShift(other_type), DataType::SizeShift(vector_type));
+ return vl >> (DataType::SizeShift(other_type) - DataType::SizeShift(vector_type));
}
// Detect up to two instructions a and b, and an acccumulated constant c.
@@ -1105,19 +1111,19 @@
return true;
} else if (instruction->IsArrayGet()) {
// Deal with vector restrictions.
- if (instruction->AsArrayGet()->IsStringCharAt() &&
- HasVectorRestrictions(restrictions, kNoStringCharAt)) {
+ bool is_string_char_at = instruction->AsArrayGet()->IsStringCharAt();
+ if (is_string_char_at && HasVectorRestrictions(restrictions, kNoStringCharAt)) {
return false;
}
// Accept a right-hand-side array base[index] for
- // (1) exact matching vector type,
+ // (1) matching vector type (exact match or signed/unsigned integral type of the same size),
// (2) loop-invariant base,
// (3) unit stride index,
// (4) vectorizable right-hand-side value.
HInstruction* base = instruction->InputAt(0);
HInstruction* index = instruction->InputAt(1);
HInstruction* offset = nullptr;
- if (type == instruction->GetType() &&
+ if (DataType::ToSignedType(type) == DataType::ToSignedType(instruction->GetType()) &&
node->loop_info->IsDefinedOutOfTheLoop(base) &&
induction_range_.IsUnitStride(instruction, index, graph_, &offset)) {
if (generate_code) {
@@ -1281,6 +1287,7 @@
}
if (VectorizeUse(node, r, generate_code, type, restrictions)) {
if (generate_code) {
+ NormalizePackedType(&type, &is_unsigned);
GenerateVecOp(instruction, vector_map_->Get(r), nullptr, type);
}
return true;
@@ -1340,6 +1347,7 @@
// ARM 32-bit always supports advanced SIMD (64-bit SIMD).
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
*restrictions |= kNoDiv | kNoReduction;
return TrySetVectorLength(8);
@@ -1359,6 +1367,7 @@
// ARMv8 AArch64 always supports advanced SIMD (128-bit SIMD).
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
*restrictions |= kNoDiv;
return TrySetVectorLength(16);
@@ -1387,6 +1396,7 @@
if (features->AsX86InstructionSetFeatures()->HasSSE4_1()) {
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
*restrictions |=
kNoMul | kNoDiv | kNoShift | kNoAbs | kNoSignedHAdd | kNoUnroundedHAdd | kNoSAD;
@@ -1416,6 +1426,7 @@
if (features->AsMipsInstructionSetFeatures()->HasMsa()) {
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
*restrictions |= kNoDiv | kNoReduction | kNoSAD;
return TrySetVectorLength(16);
@@ -1444,6 +1455,7 @@
if (features->AsMips64InstructionSetFeatures()->HasMsa()) {
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
*restrictions |= kNoDiv | kNoReduction | kNoSAD;
return TrySetVectorLength(16);
@@ -1540,11 +1552,16 @@
HInstruction* base = org->InputAt(0);
if (opb != nullptr) {
vector = new (global_allocator_) HVecStore(
- global_allocator_, base, opa, opb, type, vector_length_);
+ global_allocator_, base, opa, opb, type, org->GetSideEffects(), vector_length_);
} else {
bool is_string_char_at = org->AsArrayGet()->IsStringCharAt();
- vector = new (global_allocator_) HVecLoad(
- global_allocator_, base, opa, type, vector_length_, is_string_char_at);
+ vector = new (global_allocator_) HVecLoad(global_allocator_,
+ base,
+ opa,
+ type,
+ org->GetSideEffects(),
+ vector_length_,
+ is_string_char_at);
}
// Known dynamically enforced alignment?
if (vector_peeling_candidate_ != nullptr &&
@@ -1556,11 +1573,12 @@
// Scalar store or load.
DCHECK(vector_mode_ == kSequential);
if (opb != nullptr) {
- vector = new (global_allocator_) HArraySet(org->InputAt(0), opa, opb, type, kNoDexPc);
+ vector = new (global_allocator_) HArraySet(
+ org->InputAt(0), opa, opb, type, org->GetSideEffects(), kNoDexPc);
} else {
bool is_string_char_at = org->AsArrayGet()->IsStringCharAt();
vector = new (global_allocator_) HArrayGet(
- org->InputAt(0), opa, type, kNoDexPc, is_string_char_at);
+ org->InputAt(0), opa, type, org->GetSideEffects(), kNoDexPc, is_string_char_at);
}
}
vector_map_->Put(org, vector);
@@ -1737,6 +1755,7 @@
case Intrinsics::kMathMinLongLong:
case Intrinsics::kMathMinFloatFloat:
case Intrinsics::kMathMinDoubleDouble: {
+ NormalizePackedType(&type, &is_unsigned);
vector = new (global_allocator_)
HVecMin(global_allocator_, opa, opb, type, vector_length_, is_unsigned);
break;
@@ -1745,6 +1764,7 @@
case Intrinsics::kMathMaxLongLong:
case Intrinsics::kMathMaxFloatFloat:
case Intrinsics::kMathMaxDoubleDouble: {
+ NormalizePackedType(&type, &is_unsigned);
vector = new (global_allocator_)
HVecMax(global_allocator_, opa, opb, type, vector_length_, is_unsigned);
break;
@@ -1857,14 +1877,15 @@
VectorizeUse(node, s, generate_code, type, restrictions)) {
if (generate_code) {
if (vector_mode_ == kVector) {
+ NormalizePackedType(&type, &is_unsigned);
vector_map_->Put(instruction, new (global_allocator_) HVecHalvingAdd(
global_allocator_,
vector_map_->Get(r),
vector_map_->Get(s),
type,
vector_length_,
- is_unsigned,
- is_rounded));
+ is_rounded,
+ is_unsigned));
MaybeRecordStat(stats_, MethodCompilationStat::kLoopVectorizedIdiom);
} else {
GenerateVecOp(instruction, vector_map_->Get(r), vector_map_->Get(s), type);
@@ -1952,6 +1973,7 @@
VectorizeUse(node, r, generate_code, sub_type, restrictions) &&
VectorizeUse(node, s, generate_code, sub_type, restrictions)) {
if (generate_code) {
+ NormalizePackedType(&reduction_type, &is_unsigned);
if (vector_mode_ == kVector) {
vector_map_->Put(instruction, new (global_allocator_) HVecSADAccumulate(
global_allocator_,
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 41ea998..cae5054 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -590,6 +590,7 @@
case DataType::Type::kBool:
DCHECK(IsUint<1>(value));
FALLTHROUGH_INTENDED;
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index c49cee3..c75a512 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1760,14 +1760,26 @@
static constexpr uint64_t kAllReads =
((1ULL << (kLastBitForReads + 1 - kFieldReadOffset)) - 1) << kFieldReadOffset;
- // Translates type to bit flag.
+ // Translates type to bit flag. The type must correspond to a Java type.
static uint64_t TypeFlag(DataType::Type type, int offset) {
- CHECK_NE(type, DataType::Type::kVoid);
- const uint64_t one = 1;
- const int shift = static_cast<int>(type); // 0-based consecutive enum
+ int shift;
+ switch (type) {
+ case DataType::Type::kReference: shift = 0; break;
+ case DataType::Type::kBool: shift = 1; break;
+ case DataType::Type::kInt8: shift = 2; break;
+ case DataType::Type::kUint16: shift = 3; break;
+ case DataType::Type::kInt16: shift = 4; break;
+ case DataType::Type::kInt32: shift = 5; break;
+ case DataType::Type::kInt64: shift = 6; break;
+ case DataType::Type::kFloat32: shift = 7; break;
+ case DataType::Type::kFloat64: shift = 8; break;
+ default:
+ LOG(FATAL) << "Unexpected data type " << type;
+ UNREACHABLE();
+ }
DCHECK_LE(kFieldWriteOffset, shift);
DCHECK_LT(shift, kArrayWriteOffset);
- return one << (shift + offset);
+ return UINT64_C(1) << (shift + offset);
}
// Private constructor on direct flags value.
@@ -5382,9 +5394,21 @@
HArrayGet(HInstruction* array,
HInstruction* index,
DataType::Type type,
+ uint32_t dex_pc)
+ : HArrayGet(array,
+ index,
+ type,
+ SideEffects::ArrayReadOfType(type),
+ dex_pc,
+ /* is_string_char_at */ false) {}
+
+ HArrayGet(HInstruction* array,
+ HInstruction* index,
+ DataType::Type type,
+ SideEffects side_effects,
uint32_t dex_pc,
- bool is_string_char_at = false)
- : HExpression(type, SideEffects::ArrayReadOfType(type), dex_pc) {
+ bool is_string_char_at)
+ : HExpression(type, side_effects, dex_pc) {
SetPackedFlag<kFlagIsStringCharAt>(is_string_char_at);
SetRawInputAt(0, array);
SetRawInputAt(1, index);
@@ -5453,7 +5477,21 @@
HInstruction* value,
DataType::Type expected_component_type,
uint32_t dex_pc)
- : HTemplateInstruction(SideEffects::None(), dex_pc) {
+ : HArraySet(array,
+ index,
+ value,
+ expected_component_type,
+ // Make a best guess for side effects now, may be refined during SSA building.
+ ComputeSideEffects(GetComponentType(value->GetType(), expected_component_type)),
+ dex_pc) {}
+
+ HArraySet(HInstruction* array,
+ HInstruction* index,
+ HInstruction* value,
+ DataType::Type expected_component_type,
+ SideEffects side_effects,
+ uint32_t dex_pc)
+ : HTemplateInstruction(side_effects, dex_pc) {
SetPackedField<ExpectedComponentTypeField>(expected_component_type);
SetPackedFlag<kFlagNeedsTypeCheck>(value->GetType() == DataType::Type::kReference);
SetPackedFlag<kFlagValueCanBeNull>(true);
@@ -5461,8 +5499,6 @@
SetRawInputAt(0, array);
SetRawInputAt(1, index);
SetRawInputAt(2, value);
- // Make a best guess now, may be refined during SSA building.
- ComputeSideEffects();
}
bool NeedsEnvironment() const OVERRIDE {
@@ -5501,24 +5537,26 @@
HInstruction* GetValue() const { return InputAt(2); }
DataType::Type GetComponentType() const {
+ return GetComponentType(GetValue()->GetType(), GetRawExpectedComponentType());
+ }
+
+ static DataType::Type GetComponentType(DataType::Type value_type,
+ DataType::Type expected_component_type) {
// The Dex format does not type floating point index operations. Since the
- // `expected_component_type_` is set during building and can therefore not
+ // `expected_component_type` comes from SSA building and can therefore not
// be correct, we also check what is the value type. If it is a floating
// point type, we must use that type.
- DataType::Type value_type = GetValue()->GetType();
return ((value_type == DataType::Type::kFloat32) || (value_type == DataType::Type::kFloat64))
? value_type
- : GetRawExpectedComponentType();
+ : expected_component_type;
}
DataType::Type GetRawExpectedComponentType() const {
return GetPackedField<ExpectedComponentTypeField>();
}
- void ComputeSideEffects() {
- DataType::Type type = GetComponentType();
- SetSideEffects(SideEffects::ArrayWriteOfType(type).Union(
- SideEffectsForArchRuntimeCalls(type)));
+ static SideEffects ComputeSideEffects(DataType::Type type) {
+ return SideEffects::ArrayWriteOfType(type).Union(SideEffectsForArchRuntimeCalls(type));
}
static SideEffects SideEffectsForArchRuntimeCalls(DataType::Type value_type) {
diff --git a/compiler/optimizing/nodes_vector.h b/compiler/optimizing/nodes_vector.h
index 0aac260..d01f8c0 100644
--- a/compiler/optimizing/nodes_vector.h
+++ b/compiler/optimizing/nodes_vector.h
@@ -232,8 +232,10 @@
DataType::Type input_type = input->AsVecOperation()->GetPackedType();
switch (input_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
return type == DataType::Type::kBool ||
+ type == DataType::Type::kUint8 ||
type == DataType::Type::kInt8;
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -471,10 +473,14 @@
HInstruction* right,
DataType::Type packed_type,
size_t vector_length,
- bool is_unsigned,
bool is_rounded,
- uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
+ bool is_unsigned = false)
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, kNoDexPc) {
+ // The `is_unsigned` flag should be used exclusively with the Int32 or Int64.
+ // This flag is a temporary measure while we do not have the Uint32 and Uint64 data types.
+ DCHECK(!is_unsigned ||
+ packed_type == DataType::Type::kInt32 ||
+ packed_type == DataType::Type::kInt64) << packed_type;
DCHECK(HasConsistentPackedTypes(left, packed_type));
DCHECK(HasConsistentPackedTypes(right, packed_type));
SetPackedFlag<kFieldHAddIsUnsigned>(is_unsigned);
@@ -584,9 +590,13 @@
HInstruction* right,
DataType::Type packed_type,
size_t vector_length,
- bool is_unsigned,
- uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
+ bool is_unsigned = false)
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, kNoDexPc) {
+ // The `is_unsigned` flag should be used exclusively with the Int32 or Int64.
+ // This flag is a temporary measure while we do not have the Uint32 and Uint64 data types.
+ DCHECK(!is_unsigned ||
+ packed_type == DataType::Type::kInt32 ||
+ packed_type == DataType::Type::kInt64) << packed_type;
DCHECK(HasConsistentPackedTypes(left, packed_type));
DCHECK(HasConsistentPackedTypes(right, packed_type));
SetPackedFlag<kFieldMinOpIsUnsigned>(is_unsigned);
@@ -622,9 +632,13 @@
HInstruction* right,
DataType::Type packed_type,
size_t vector_length,
- bool is_unsigned,
- uint32_t dex_pc = kNoDexPc)
- : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
+ bool is_unsigned = false)
+ : HVecBinaryOperation(arena, left, right, packed_type, vector_length, kNoDexPc) {
+ // The `is_unsigned` flag should be used exclusively with the Int32 or Int64.
+ // This flag is a temporary measure while we do not have the Uint32 and Uint64 data types.
+ DCHECK(!is_unsigned ||
+ packed_type == DataType::Type::kInt32 ||
+ packed_type == DataType::Type::kInt64) << packed_type;
DCHECK(HasConsistentPackedTypes(left, packed_type));
DCHECK(HasConsistentPackedTypes(right, packed_type));
SetPackedFlag<kFieldMaxOpIsUnsigned>(is_unsigned);
@@ -933,12 +947,13 @@
HInstruction* base,
HInstruction* index,
DataType::Type packed_type,
+ SideEffects side_effects,
size_t vector_length,
bool is_string_char_at,
uint32_t dex_pc = kNoDexPc)
: HVecMemoryOperation(arena,
packed_type,
- SideEffects::ArrayReadOfType(packed_type),
+ side_effects,
/* number_of_inputs */ 2,
vector_length,
dex_pc) {
@@ -977,11 +992,12 @@
HInstruction* index,
HInstruction* value,
DataType::Type packed_type,
+ SideEffects side_effects,
size_t vector_length,
uint32_t dex_pc = kNoDexPc)
: HVecMemoryOperation(arena,
packed_type,
- SideEffects::ArrayWriteOfType(packed_type),
+ side_effects,
/* number_of_inputs */ 3,
vector_length,
dex_pc) {
diff --git a/compiler/optimizing/nodes_vector_test.cc b/compiler/optimizing/nodes_vector_test.cc
index 3acdb20..7dbfcda 100644
--- a/compiler/optimizing/nodes_vector_test.cc
+++ b/compiler/optimizing/nodes_vector_test.cc
@@ -47,6 +47,16 @@
0,
DataType::Type::kInt32);
entry_block_->AddInstruction(parameter_);
+ int8_parameter_ = new (&allocator_) HParameterValue(graph_->GetDexFile(),
+ dex::TypeIndex(1),
+ 0,
+ DataType::Type::kInt8);
+ entry_block_->AddInstruction(int8_parameter_);
+ int16_parameter_ = new (&allocator_) HParameterValue(graph_->GetDexFile(),
+ dex::TypeIndex(2),
+ 0,
+ DataType::Type::kInt16);
+ entry_block_->AddInstruction(int16_parameter_);
}
// General building fields.
@@ -58,6 +68,8 @@
HBasicBlock* exit_block_;
HInstruction* parameter_;
+ HInstruction* int8_parameter_;
+ HInstruction* int16_parameter_;
};
//
@@ -126,8 +138,14 @@
HVecReplicateScalar(&allocator_, parameter_, DataType::Type::kInt32, 2);
HVecOperation* v3 = new (&allocator_)
HVecReplicateScalar(&allocator_, parameter_, DataType::Type::kInt16, 4);
- HVecOperation* v4 = new (&allocator_)
- HVecStore(&allocator_, parameter_, parameter_, v0, DataType::Type::kInt32, 4);
+ HVecOperation* v4 = new (&allocator_) HVecStore(
+ &allocator_,
+ parameter_,
+ parameter_,
+ v0,
+ DataType::Type::kInt32,
+ SideEffects::ArrayWriteOfType(DataType::Type::kInt32),
+ 4);
EXPECT_TRUE(v0->Equals(v0));
EXPECT_TRUE(v1->Equals(v1));
@@ -175,12 +193,27 @@
}
TEST_F(NodesVectorTest, VectorAlignmentAndStringCharAtMatterOnLoad) {
- HVecLoad* v0 = new (&allocator_) HVecLoad(
- &allocator_, parameter_, parameter_, DataType::Type::kInt32, 4, /*is_string_char_at*/ false);
- HVecLoad* v1 = new (&allocator_) HVecLoad(
- &allocator_, parameter_, parameter_, DataType::Type::kInt32, 4, /*is_string_char_at*/ false);
- HVecLoad* v2 = new (&allocator_) HVecLoad(
- &allocator_, parameter_, parameter_, DataType::Type::kInt32, 4, /*is_string_char_at*/ true);
+ HVecLoad* v0 = new (&allocator_) HVecLoad(&allocator_,
+ parameter_,
+ parameter_,
+ DataType::Type::kInt32,
+ SideEffects::ArrayReadOfType(DataType::Type::kInt32),
+ 4,
+ /*is_string_char_at*/ false);
+ HVecLoad* v1 = new (&allocator_) HVecLoad(&allocator_,
+ parameter_,
+ parameter_,
+ DataType::Type::kInt32,
+ SideEffects::ArrayReadOfType(DataType::Type::kInt32),
+ 4,
+ /*is_string_char_at*/ false);
+ HVecLoad* v2 = new (&allocator_) HVecLoad(&allocator_,
+ parameter_,
+ parameter_,
+ DataType::Type::kInt32,
+ SideEffects::ArrayReadOfType(DataType::Type::kInt32),
+ 4,
+ /*is_string_char_at*/ true);
EXPECT_TRUE(v0->CanBeMoved());
EXPECT_TRUE(v1->CanBeMoved());
@@ -209,99 +242,155 @@
}
TEST_F(NodesVectorTest, VectorSignMattersOnMin) {
- HVecOperation* v0 = new (&allocator_)
+ HVecOperation* p0 = new (&allocator_)
HVecReplicateScalar(&allocator_, parameter_, DataType::Type::kInt32, 4);
+ HVecOperation* p1 = new (&allocator_)
+ HVecReplicateScalar(&allocator_, int8_parameter_, DataType::Type::kInt8, 4);
+ HVecOperation* p2 = new (&allocator_)
+ HVecReplicateScalar(&allocator_, int16_parameter_, DataType::Type::kInt16, 4);
- HVecMin* v1 = new (&allocator_)
- HVecMin(&allocator_, v0, v0, DataType::Type::kInt32, 4, /*is_unsigned*/ true);
- HVecMin* v2 = new (&allocator_)
- HVecMin(&allocator_, v0, v0, DataType::Type::kInt32, 4, /*is_unsigned*/ false);
- HVecMin* v3 = new (&allocator_)
- HVecMin(&allocator_, v0, v0, DataType::Type::kInt32, 2, /*is_unsigned*/ true);
+ HVecMin* v0 = new (&allocator_) HVecMin(
+ &allocator_, p0, p0, DataType::Type::kInt32, 4, /*is_unsigned*/ true);
+ HVecMin* v1 = new (&allocator_) HVecMin(
+ &allocator_, p0, p0, DataType::Type::kInt32, 4, /*is_unsigned*/ false);
+ HVecMin* v2 = new (&allocator_) HVecMin(
+ &allocator_, p0, p0, DataType::Type::kInt32, 2, /*is_unsigned*/ true);
+ HVecMin* v3 = new (&allocator_) HVecMin(&allocator_, p1, p1, DataType::Type::kUint8, 16);
+ HVecMin* v4 = new (&allocator_) HVecMin(&allocator_, p1, p1, DataType::Type::kInt8, 16);
+ HVecMin* v5 = new (&allocator_) HVecMin(&allocator_, p2, p2, DataType::Type::kUint16, 8);
+ HVecMin* v6 = new (&allocator_) HVecMin(&allocator_, p2, p2, DataType::Type::kInt16, 8);
+ HVecMin* min_insns[] = { v0, v1, v2, v3, v4, v5, v6 };
- EXPECT_FALSE(v0->CanBeMoved());
- EXPECT_TRUE(v1->CanBeMoved());
- EXPECT_TRUE(v2->CanBeMoved());
- EXPECT_TRUE(v3->CanBeMoved());
+ EXPECT_FALSE(p0->CanBeMoved());
+ EXPECT_FALSE(p1->CanBeMoved());
+ EXPECT_FALSE(p2->CanBeMoved());
- EXPECT_TRUE(v1->IsUnsigned());
- EXPECT_FALSE(v2->IsUnsigned());
- EXPECT_TRUE(v3->IsUnsigned());
+ for (HVecMin* min_insn : min_insns) {
+ EXPECT_TRUE(min_insn->CanBeMoved());
+ }
- EXPECT_TRUE(v1->Equals(v1));
- EXPECT_TRUE(v2->Equals(v2));
- EXPECT_TRUE(v3->Equals(v3));
+ // Deprecated; IsUnsigned() should be removed with the introduction of Uint32 and Uint64.
+ EXPECT_TRUE(v0->IsUnsigned());
+ EXPECT_FALSE(v1->IsUnsigned());
+ EXPECT_TRUE(v2->IsUnsigned());
- EXPECT_FALSE(v1->Equals(v2)); // different signs
- EXPECT_FALSE(v1->Equals(v3)); // different vector lengths
+ for (HVecMin* min_insn1 : min_insns) {
+ for (HVecMin* min_insn2 : min_insns) {
+ EXPECT_EQ(min_insn1 == min_insn2, min_insn1->Equals(min_insn2));
+ }
+ }
}
TEST_F(NodesVectorTest, VectorSignMattersOnMax) {
- HVecOperation* v0 = new (&allocator_)
+ HVecOperation* p0 = new (&allocator_)
HVecReplicateScalar(&allocator_, parameter_, DataType::Type::kInt32, 4);
+ HVecOperation* p1 = new (&allocator_)
+ HVecReplicateScalar(&allocator_, int8_parameter_, DataType::Type::kInt8, 4);
+ HVecOperation* p2 = new (&allocator_)
+ HVecReplicateScalar(&allocator_, int16_parameter_, DataType::Type::kInt16, 4);
- HVecMax* v1 = new (&allocator_)
- HVecMax(&allocator_, v0, v0, DataType::Type::kInt32, 4, /*is_unsigned*/ true);
- HVecMax* v2 = new (&allocator_)
- HVecMax(&allocator_, v0, v0, DataType::Type::kInt32, 4, /*is_unsigned*/ false);
- HVecMax* v3 = new (&allocator_)
- HVecMax(&allocator_, v0, v0, DataType::Type::kInt32, 2, /*is_unsigned*/ true);
+ HVecMax* v0 = new (&allocator_) HVecMax(
+ &allocator_, p0, p0, DataType::Type::kInt32, 4, /*is_unsigned*/ true);
+ HVecMax* v1 = new (&allocator_) HVecMax(
+ &allocator_, p0, p0, DataType::Type::kInt32, 4, /*is_unsigned*/ false);
+ HVecMax* v2 = new (&allocator_) HVecMax(
+ &allocator_, p0, p0, DataType::Type::kInt32, 2, /*is_unsigned*/ true);
+ HVecMax* v3 = new (&allocator_) HVecMax(&allocator_, p1, p1, DataType::Type::kUint8, 16);
+ HVecMax* v4 = new (&allocator_) HVecMax(&allocator_, p1, p1, DataType::Type::kInt8, 16);
+ HVecMax* v5 = new (&allocator_) HVecMax(&allocator_, p2, p2, DataType::Type::kUint16, 8);
+ HVecMax* v6 = new (&allocator_) HVecMax(&allocator_, p2, p2, DataType::Type::kInt16, 8);
+ HVecMax* max_insns[] = { v0, v1, v2, v3, v4, v5, v6 };
- EXPECT_FALSE(v0->CanBeMoved());
- EXPECT_TRUE(v1->CanBeMoved());
- EXPECT_TRUE(v2->CanBeMoved());
- EXPECT_TRUE(v3->CanBeMoved());
+ EXPECT_FALSE(p0->CanBeMoved());
+ EXPECT_FALSE(p1->CanBeMoved());
+ EXPECT_FALSE(p2->CanBeMoved());
- EXPECT_TRUE(v1->IsUnsigned());
- EXPECT_FALSE(v2->IsUnsigned());
- EXPECT_TRUE(v3->IsUnsigned());
+ for (HVecMax* max_insn : max_insns) {
+ EXPECT_TRUE(max_insn->CanBeMoved());
+ }
- EXPECT_TRUE(v1->Equals(v1));
- EXPECT_TRUE(v2->Equals(v2));
- EXPECT_TRUE(v3->Equals(v3));
+ // Deprecated; IsUnsigned() should be removed with the introduction of Uint32 and Uint64.
+ EXPECT_TRUE(v0->IsUnsigned());
+ EXPECT_FALSE(v1->IsUnsigned());
+ EXPECT_TRUE(v2->IsUnsigned());
- EXPECT_FALSE(v1->Equals(v2)); // different signs
- EXPECT_FALSE(v1->Equals(v3)); // different vector lengths
+ for (HVecMax* max_insn1 : max_insns) {
+ for (HVecMax* max_insn2 : max_insns) {
+ EXPECT_EQ(max_insn1 == max_insn2, max_insn1->Equals(max_insn2));
+ }
+ }
}
TEST_F(NodesVectorTest, VectorAttributesMatterOnHalvingAdd) {
- HVecOperation* v0 = new (&allocator_)
+ HVecOperation* p0 = new (&allocator_)
HVecReplicateScalar(&allocator_, parameter_, DataType::Type::kInt32, 4);
+ HVecOperation* p1 = new (&allocator_)
+ HVecReplicateScalar(&allocator_, int8_parameter_, DataType::Type::kInt8, 4);
+ HVecOperation* p2 = new (&allocator_)
+ HVecReplicateScalar(&allocator_, int16_parameter_, DataType::Type::kInt16, 4);
+ HVecHalvingAdd* v0 = new (&allocator_) HVecHalvingAdd(
+ &allocator_, p0, p0, DataType::Type::kInt32, 4, /*is_rounded*/ true, /*is_unsigned*/ true);
HVecHalvingAdd* v1 = new (&allocator_) HVecHalvingAdd(
- &allocator_, v0, v0, DataType::Type::kInt32, 4, /*is_unsigned*/ true, /*is_rounded*/ true);
+ &allocator_, p0, p0, DataType::Type::kInt32, 4, /*is_rounded*/ false, /*is_unsigned*/ true);
HVecHalvingAdd* v2 = new (&allocator_) HVecHalvingAdd(
- &allocator_, v0, v0, DataType::Type::kInt32, 4, /*is_unsigned*/ true, /*is_rounded*/ false);
+ &allocator_, p0, p0, DataType::Type::kInt32, 4, /*is_rounded*/ true, /*is_unsigned*/ false);
HVecHalvingAdd* v3 = new (&allocator_) HVecHalvingAdd(
- &allocator_, v0, v0, DataType::Type::kInt32, 4, /*is_unsigned*/ false, /*is_rounded*/ true);
+ &allocator_, p0, p0, DataType::Type::kInt32, 4, /*is_rounded*/ false, /*is_unsigned*/ false);
HVecHalvingAdd* v4 = new (&allocator_) HVecHalvingAdd(
- &allocator_, v0, v0, DataType::Type::kInt32, 4, /*is_unsigned*/ false, /*is_rounded*/ false);
+ &allocator_, p0, p0, DataType::Type::kInt32, 2, /*is_rounded*/ true, /*is_unsigned*/ true);
HVecHalvingAdd* v5 = new (&allocator_) HVecHalvingAdd(
- &allocator_, v0, v0, DataType::Type::kInt32, 2, /*is_unsigned*/ true, /*is_rounded*/ true);
+ &allocator_, p1, p1, DataType::Type::kUint8, 16, /*is_rounded*/ true);
+ HVecHalvingAdd* v6 = new (&allocator_) HVecHalvingAdd(
+ &allocator_, p1, p1, DataType::Type::kUint8, 16, /*is_rounded*/ false);
+ HVecHalvingAdd* v7 = new (&allocator_) HVecHalvingAdd(
+ &allocator_, p1, p1, DataType::Type::kInt8, 16, /*is_rounded*/ true);
+ HVecHalvingAdd* v8 = new (&allocator_) HVecHalvingAdd(
+ &allocator_, p1, p1, DataType::Type::kInt8, 16, /*is_rounded*/ false);
+ HVecHalvingAdd* v9 = new (&allocator_) HVecHalvingAdd(
+ &allocator_, p2, p2, DataType::Type::kUint16, 8, /*is_rounded*/ true);
+ HVecHalvingAdd* v10 = new (&allocator_) HVecHalvingAdd(
+ &allocator_, p2, p2, DataType::Type::kUint16, 8, /*is_rounded*/ false);
+ HVecHalvingAdd* v11 = new (&allocator_) HVecHalvingAdd(
+ &allocator_, p2, p2, DataType::Type::kInt16, 2, /*is_rounded*/ true);
+ HVecHalvingAdd* v12 = new (&allocator_) HVecHalvingAdd(
+ &allocator_, p2, p2, DataType::Type::kInt16, 2, /*is_rounded*/ false);
+ HVecHalvingAdd* hadd_insns[] = { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12 };
- EXPECT_FALSE(v0->CanBeMoved());
- EXPECT_TRUE(v1->CanBeMoved());
- EXPECT_TRUE(v2->CanBeMoved());
- EXPECT_TRUE(v3->CanBeMoved());
- EXPECT_TRUE(v4->CanBeMoved());
- EXPECT_TRUE(v5->CanBeMoved());
+ EXPECT_FALSE(p0->CanBeMoved());
+ EXPECT_FALSE(p1->CanBeMoved());
+ EXPECT_FALSE(p2->CanBeMoved());
- EXPECT_TRUE(v1->Equals(v1));
- EXPECT_TRUE(v2->Equals(v2));
- EXPECT_TRUE(v3->Equals(v3));
- EXPECT_TRUE(v4->Equals(v4));
- EXPECT_TRUE(v5->Equals(v5));
+ for (HVecHalvingAdd* hadd_insn : hadd_insns) {
+ EXPECT_TRUE(hadd_insn->CanBeMoved());
+ }
- EXPECT_TRUE(v1->IsUnsigned() && v1->IsRounded());
- EXPECT_TRUE(v2->IsUnsigned() && !v2->IsRounded());
- EXPECT_TRUE(!v3->IsUnsigned() && v3->IsRounded());
- EXPECT_TRUE(!v4->IsUnsigned() && !v4->IsRounded());
- EXPECT_TRUE(v5->IsUnsigned() && v5->IsRounded());
+ // Deprecated; IsUnsigned() should be removed with the introduction of Uint32 and Uint64.
+ EXPECT_TRUE(v0->IsUnsigned());
+ EXPECT_TRUE(v1->IsUnsigned());
+ EXPECT_TRUE(!v2->IsUnsigned());
+ EXPECT_TRUE(!v3->IsUnsigned());
+ EXPECT_TRUE(v4->IsUnsigned());
- EXPECT_FALSE(v1->Equals(v2)); // different attributes
- EXPECT_FALSE(v1->Equals(v3)); // different attributes
- EXPECT_FALSE(v1->Equals(v4)); // different attributes
- EXPECT_FALSE(v1->Equals(v5)); // different vector lengths
+ EXPECT_TRUE(v0->IsRounded());
+ EXPECT_TRUE(!v1->IsRounded());
+ EXPECT_TRUE(v2->IsRounded());
+ EXPECT_TRUE(!v3->IsRounded());
+ EXPECT_TRUE(v4->IsRounded());
+ EXPECT_TRUE(v5->IsRounded());
+ EXPECT_TRUE(!v6->IsRounded());
+ EXPECT_TRUE(v7->IsRounded());
+ EXPECT_TRUE(!v8->IsRounded());
+ EXPECT_TRUE(v9->IsRounded());
+ EXPECT_TRUE(!v10->IsRounded());
+ EXPECT_TRUE(v11->IsRounded());
+ EXPECT_TRUE(!v12->IsRounded());
+
+ for (HVecHalvingAdd* hadd_insn1 : hadd_insns) {
+ for (HVecHalvingAdd* hadd_insn2 : hadd_insns) {
+ EXPECT_EQ(hadd_insn1 == hadd_insn2, hadd_insn1->Equals(hadd_insn2));
+ }
+ }
}
TEST_F(NodesVectorTest, VectorOperationMattersOnMultiplyAccumulate) {
diff --git a/compiler/optimizing/register_allocation_resolver.cc b/compiler/optimizing/register_allocation_resolver.cc
index f0057c3..1786aa7 100644
--- a/compiler/optimizing/register_allocation_resolver.cc
+++ b/compiler/optimizing/register_allocation_resolver.cc
@@ -112,6 +112,7 @@
case DataType::Type::kReference:
case DataType::Type::kInt32:
case DataType::Type::kUint16:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kBool:
case DataType::Type::kInt16:
diff --git a/compiler/optimizing/register_allocator_graph_color.cc b/compiler/optimizing/register_allocator_graph_color.cc
index 4ff7315..33df607 100644
--- a/compiler/optimizing/register_allocator_graph_color.cc
+++ b/compiler/optimizing/register_allocator_graph_color.cc
@@ -1940,6 +1940,7 @@
case DataType::Type::kReference:
case DataType::Type::kInt32:
case DataType::Type::kUint16:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kBool:
case DataType::Type::kInt16:
diff --git a/compiler/optimizing/register_allocator_linear_scan.cc b/compiler/optimizing/register_allocator_linear_scan.cc
index 2012cd5..9803a7b 100644
--- a/compiler/optimizing/register_allocator_linear_scan.cc
+++ b/compiler/optimizing/register_allocator_linear_scan.cc
@@ -1116,6 +1116,7 @@
case DataType::Type::kReference:
case DataType::Type::kInt32:
case DataType::Type::kUint16:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kBool:
case DataType::Type::kInt16:
diff --git a/compiler/optimizing/scheduler_arm.cc b/compiler/optimizing/scheduler_arm.cc
index 110db47..b3c8f10 100644
--- a/compiler/optimizing/scheduler_arm.cc
+++ b/compiler/optimizing/scheduler_arm.cc
@@ -514,9 +514,10 @@
DataType::Type type = instr->InputAt(0)->GetType();
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32:
last_visited_internal_latency_ = 2 * kArmIntegerOpLatency;
break;
@@ -633,9 +634,10 @@
switch (type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32: {
if (maybe_compressed_char_at) {
last_visited_internal_latency_ += kArmMemoryLoadLatency;
@@ -733,9 +735,10 @@
switch (value_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32: {
if (index->IsConstant()) {
last_visited_latency_ = kArmMemoryStoreLatency;
@@ -916,9 +919,10 @@
switch (field_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
case DataType::Type::kInt32:
last_visited_latency_ = kArmMemoryLoadLatency;
break;
@@ -977,9 +981,10 @@
switch (field_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
- case DataType::Type::kInt16:
case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
if (is_volatile) {
last_visited_internal_latency_ = kArmMemoryBarrierLatency + kArmMemoryStoreLatency;
last_visited_latency_ = kArmMemoryBarrierLatency;
@@ -1047,6 +1052,7 @@
DataType::Type input_type = instr->GetInputType();
switch (result_type) {
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -1072,6 +1078,7 @@
case DataType::Type::kInt64:
switch (input_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -1095,6 +1102,7 @@
case DataType::Type::kFloat32:
switch (input_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
@@ -1118,6 +1126,7 @@
case DataType::Type::kFloat64:
switch (input_type) {
case DataType::Type::kBool:
+ case DataType::Type::kUint8:
case DataType::Type::kInt8:
case DataType::Type::kUint16:
case DataType::Type::kInt16:
diff --git a/compiler/optimizing/side_effects_test.cc b/compiler/optimizing/side_effects_test.cc
index ac5eb15..9731712 100644
--- a/compiler/optimizing/side_effects_test.cc
+++ b/compiler/optimizing/side_effects_test.cc
@@ -21,6 +21,19 @@
namespace art {
+// Only runtime types other than void are allowed.
+static const DataType::Type kTestTypes[] = {
+ DataType::Type::kReference,
+ DataType::Type::kBool,
+ DataType::Type::kInt8,
+ DataType::Type::kUint16,
+ DataType::Type::kInt16,
+ DataType::Type::kInt32,
+ DataType::Type::kInt64,
+ DataType::Type::kFloat32,
+ DataType::Type::kFloat64,
+};
+
/**
* Tests for the SideEffects class.
*/
@@ -91,9 +104,7 @@
TEST(SideEffectsTest, DependencesAndNoDependences) {
// Apply test to each individual data type.
- for (DataType::Type type = DataType::Type::kReference;
- type < DataType::Type::kVoid;
- type = static_cast<DataType::Type>(static_cast<uint8_t>(type) + 1u)) {
+ for (DataType::Type type : kTestTypes) {
// Same data type and access type: proper write/read dep.
testWriteAndReadDependence(
SideEffects::FieldWriteOfType(type, false),
@@ -169,9 +180,7 @@
TEST(SideEffectsTest, AllWritesAndReads) {
SideEffects s = SideEffects::None();
// Keep taking the union of different writes and reads.
- for (DataType::Type type = DataType::Type::kReference;
- type < DataType::Type::kVoid;
- type = static_cast<DataType::Type>(static_cast<uint8_t>(type) + 1u)) {
+ for (DataType::Type type : kTestTypes) {
s = s.Union(SideEffects::FieldWriteOfType(type, /* is_volatile */ false));
s = s.Union(SideEffects::ArrayWriteOfType(type));
s = s.Union(SideEffects::FieldReadOfType(type, /* is_volatile */ false));
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index 77b7a22..2356316 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -393,7 +393,7 @@
}
// Refine the side effects of this floating point aset. Note that we do this even if
// no replacement occurs, since the right-hand-side may have been corrected already.
- aset->ComputeSideEffects();
+ aset->SetSideEffects(HArraySet::ComputeSideEffects(aset->GetComponentType()));
} else {
// Array elements are integral and the value assigned to it initially
// was integral too. Nothing to do.