summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/dex/mir_optimization.cc4
-rw-r--r--compiler/image_writer.cc131
-rw-r--r--compiler/optimizing/builder.cc10
-rw-r--r--compiler/optimizing/code_generator_arm.cc43
-rw-r--r--compiler/optimizing/code_generator_x86.cc64
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc68
-rw-r--r--compiler/utils/x86_64/assembler_x86_64.cc12
-rw-r--r--compiler/utils/x86_64/assembler_x86_64.h1
8 files changed, 212 insertions, 121 deletions
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 55f2abcd3f..3c6b61de89 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -795,10 +795,6 @@ bool MIRGraph::LayoutBlocks(BasicBlock* bb) {
break;
}
walker = prev;
-
- if (walker->visited) {
- break;
- }
}
return false;
}
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index ab5c6c77de..a45c2d1bab 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -480,34 +480,29 @@ class StringCollector {
};
// Compare strings based on length, used for sorting strings by length / reverse length.
-class StringLengthComparator {
+class LexicographicalStringComparator {
public:
- explicit StringLengthComparator(Handle<mirror::ObjectArray<mirror::String>> strings)
- : strings_(strings) {
+ bool operator()(const mirror::HeapReference<mirror::String>& lhs,
+ const mirror::HeapReference<mirror::String>& rhs) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::String* lhs_s = lhs.AsMirrorPtr();
+ mirror::String* rhs_s = rhs.AsMirrorPtr();
+ uint16_t* lhs_begin = lhs_s->GetCharArray()->GetData() + lhs_s->GetOffset();
+ uint16_t* rhs_begin = rhs_s->GetCharArray()->GetData() + rhs_s->GetOffset();
+ return std::lexicographical_compare(lhs_begin, lhs_begin + lhs_s->GetLength(),
+ rhs_begin, rhs_begin + rhs_s->GetLength());
}
- bool operator()(size_t a, size_t b) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return strings_->GetWithoutChecks(a)->GetLength() < strings_->GetWithoutChecks(b)->GetLength();
- }
-
- private:
- Handle<mirror::ObjectArray<mirror::String>> strings_;
};
-// Normal string < comparison through the chars_ array.
-class SubstringComparator {
- public:
- explicit SubstringComparator(const std::vector<uint16_t>* const chars) : chars_(chars) {
- }
- bool operator()(const std::pair<size_t, size_t>& a, const std::pair<size_t, size_t>& b) {
- return std::lexicographical_compare(chars_->begin() + a.first,
- chars_->begin() + a.first + a.second,
- chars_->begin() + b.first,
- chars_->begin() + b.first + b.second);
+static bool IsPrefix(mirror::String* pref, mirror::String* full)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (pref->GetLength() > full->GetLength()) {
+ return false;
}
-
- private:
- const std::vector<uint16_t>* const chars_;
-};
+ uint16_t* pref_begin = pref->GetCharArray()->GetData() + pref->GetOffset();
+ uint16_t* full_begin = full->GetCharArray()->GetData() + full->GetOffset();
+ return std::equal(pref_begin, pref_begin + pref->GetLength(), full_begin);
+}
void ImageWriter::ProcessStrings() {
size_t total_strings = 0;
@@ -529,67 +524,51 @@ void ImageWriter::ProcessStrings() {
// Some strings could have gotten freed if AllocStringArray caused a GC.
CHECK_LE(string_collector.GetIndex(), total_strings);
total_strings = string_collector.GetIndex();
- size_t total_length = 0;
- std::vector<size_t> reverse_sorted_strings;
- for (size_t i = 0; i < total_strings; ++i) {
- mirror::String* s = strings->GetWithoutChecks(i);
- // Look up the string in the array.
- total_length += s->GetLength();
- reverse_sorted_strings.push_back(i);
- }
- // Sort by reverse length.
- StringLengthComparator comparator(strings);
- std::sort(reverse_sorted_strings.rbegin(), reverse_sorted_strings.rend(), comparator);
- // Deduplicate prefixes and add strings to the char array.
- std::vector<uint16_t> combined_chars(total_length, 0U);
- size_t num_chars = 0;
+ auto* strings_begin = reinterpret_cast<mirror::HeapReference<mirror::String>*>(
+ strings->GetRawData(sizeof(mirror::HeapReference<mirror::String>), 0));
+ std::sort(strings_begin, strings_begin + total_strings, LexicographicalStringComparator());
// Characters of strings which are non equal prefix of another string (not the same string).
// We don't count the savings from equal strings since these would get interned later anyways.
size_t prefix_saved_chars = 0;
- std::set<std::pair<size_t, size_t>, SubstringComparator> existing_strings((
- SubstringComparator(&combined_chars)));
- for (size_t i = 0; i < total_strings; ++i) {
- mirror::String* s = strings->GetWithoutChecks(reverse_sorted_strings[i]);
- // Add the string to the end of the char array.
+ // Count characters needed for the strings.
+ size_t num_chars = 0u;
+ mirror::String* prev_s = nullptr;
+ for (size_t idx = 0; idx != total_strings; ++idx) {
+ mirror::String* s = strings->GetWithoutChecks(idx);
size_t length = s->GetLength();
- for (size_t j = 0; j < length; ++j) {
- combined_chars[num_chars++] = s->CharAt(j);
- }
- // Try to see if the string exists as a prefix of an existing string.
- size_t new_offset = 0;
- std::pair<size_t, size_t> new_string(num_chars - length, length);
- auto it = existing_strings.lower_bound(new_string);
- bool is_prefix = false;
- if (it != existing_strings.end()) {
- CHECK_LE(length, it->second);
- is_prefix = std::equal(combined_chars.begin() + new_string.first,
- combined_chars.begin() + new_string.first + new_string.second,
- combined_chars.begin() + it->first);
- }
- if (is_prefix) {
- // Shares a prefix, set the offset to where the new offset will be.
- new_offset = it->first;
- // Remove the added chars.
- num_chars -= length;
- if (it->second != length) {
- prefix_saved_chars += length;
+ num_chars += length;
+ if (prev_s != nullptr && IsPrefix(prev_s, s)) {
+ size_t prev_length = prev_s->GetLength();
+ num_chars -= prev_length;
+ if (prev_length != length) {
+ prefix_saved_chars += prev_length;
}
- } else {
- new_offset = new_string.first;
- existing_strings.insert(new_string);
}
- s->SetOffset(new_offset);
- }
- // Allocate and update the char arrays.
- auto* array = mirror::CharArray::Alloc(self, num_chars);
- for (size_t i = 0; i < num_chars; ++i) {
- array->SetWithoutChecks<false>(i, combined_chars[i]);
- }
- for (size_t i = 0; i < total_strings; ++i) {
- strings->GetWithoutChecks(i)->SetArray(array);
+ prev_s = s;
+ }
+ // Create character array, copy characters and point the strings there.
+ mirror::CharArray* array = mirror::CharArray::Alloc(self, num_chars);
+ uint16_t* array_data = array->GetData();
+ size_t pos = 0u;
+ prev_s = nullptr;
+ for (size_t idx = 0; idx != total_strings; ++idx) {
+ mirror::String* s = strings->GetWithoutChecks(idx);
+ uint16_t* s_data = s->GetCharArray()->GetData() + s->GetOffset();
+ int32_t s_length = s->GetLength();
+ int32_t prefix_length = 0u;
+ if (idx != 0u && IsPrefix(prev_s, s)) {
+ prefix_length = prev_s->GetLength();
+ }
+ memcpy(array_data + pos, s_data + prefix_length, (s_length - prefix_length) * sizeof(*s_data));
+ s->SetOffset(pos - prefix_length);
+ s->SetArray(array);
+ pos += s_length - prefix_length;
+ prev_s = s;
}
+ CHECK_EQ(pos, num_chars);
+
LOG(INFO) << "Total # image strings=" << total_strings << " combined length="
- << total_length << " prefix saved chars=" << prefix_saved_chars;
+ << num_chars << " prefix saved chars=" << prefix_saved_chars;
ComputeEagerResolvedStrings();
}
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 9561054b69..ca72f3f242 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -1306,6 +1306,16 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32
break;
}
+ case Instruction::DOUBLE_TO_INT: {
+ Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimInt, dex_pc);
+ break;
+ }
+
+ case Instruction::DOUBLE_TO_LONG: {
+ Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimLong, dex_pc);
+ break;
+ }
+
case Instruction::DOUBLE_TO_FLOAT: {
Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimFloat, dex_pc);
break;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 5076c85885..36af393e3b 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -44,7 +44,7 @@ static constexpr int kCurrentMethodStackOffset = 0;
static constexpr Register kRuntimeParameterCoreRegisters[] = { R0, R1, R2, R3 };
static constexpr size_t kRuntimeParameterCoreRegistersLength =
arraysize(kRuntimeParameterCoreRegisters);
-static constexpr SRegister kRuntimeParameterFpuRegisters[] = { S0 };
+static constexpr SRegister kRuntimeParameterFpuRegisters[] = { S0, S1 };
static constexpr size_t kRuntimeParameterFpuRegistersLength =
arraysize(kRuntimeParameterFpuRegisters);
@@ -1365,9 +1365,11 @@ void LocationsBuilderARM::VisitTypeConversion(HTypeConversion* conversion) {
Primitive::Type input_type = conversion->GetInputType();
DCHECK_NE(result_type, input_type);
- // Float-to-long conversions invoke the runtime.
+ // The float-to-long and double-to-long type conversions rely on a
+ // call to the runtime.
LocationSummary::CallKind call_kind =
- (input_type == Primitive::kPrimFloat && result_type == Primitive::kPrimLong)
+ ((input_type == Primitive::kPrimFloat || input_type == Primitive::kPrimDouble)
+ && result_type == Primitive::kPrimLong)
? LocationSummary::kCall
: LocationSummary::kNoCall;
LocationSummary* locations =
@@ -1422,8 +1424,10 @@ void LocationsBuilderARM::VisitTypeConversion(HTypeConversion* conversion) {
break;
case Primitive::kPrimDouble:
- LOG(FATAL) << "Type conversion from " << input_type
- << " to " << result_type << " not yet implemented";
+ // Processing a Dex `double-to-int' instruction.
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresFpuRegister());
break;
default:
@@ -1452,10 +1456,15 @@ void LocationsBuilderARM::VisitTypeConversion(HTypeConversion* conversion) {
break;
}
- case Primitive::kPrimDouble:
- LOG(FATAL) << "Type conversion from " << input_type << " to "
- << result_type << " not yet implemented";
+ case Primitive::kPrimDouble: {
+ // Processing a Dex `double-to-long' instruction.
+ InvokeRuntimeCallingConvention calling_convention;
+ locations->SetInAt(0, Location::FpuRegisterPairLocation(
+ calling_convention.GetFpuRegisterAt(0),
+ calling_convention.GetFpuRegisterAt(1)));
+ locations->SetOut(Location::RegisterPairLocation(R0, R1));
break;
+ }
default:
LOG(FATAL) << "Unexpected type conversion from " << input_type
@@ -1614,10 +1623,15 @@ void InstructionCodeGeneratorARM::VisitTypeConversion(HTypeConversion* conversio
break;
}
- case Primitive::kPrimDouble:
- LOG(FATAL) << "Type conversion from " << input_type
- << " to " << result_type << " not yet implemented";
+ case Primitive::kPrimDouble: {
+ // Processing a Dex `double-to-int' instruction.
+ SRegister temp_s = locations->GetTemp(0).AsFpuRegisterPairLow<SRegister>();
+ DRegister temp_d = FromLowSToD(temp_s);
+ __ vmovd(temp_d, FromLowSToD(in.AsFpuRegisterPairLow<SRegister>()));
+ __ vcvtid(temp_s, temp_d);
+ __ vmovrs(out.AsRegister<Register>(), temp_s);
break;
+ }
default:
LOG(FATAL) << "Unexpected type conversion from " << input_type
@@ -1643,15 +1657,16 @@ void InstructionCodeGeneratorARM::VisitTypeConversion(HTypeConversion* conversio
case Primitive::kPrimFloat:
// Processing a Dex `float-to-long' instruction.
- // This call does not actually record PC information.
codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pF2l),
conversion,
conversion->GetDexPc());
break;
case Primitive::kPrimDouble:
- LOG(FATAL) << "Type conversion from " << input_type << " to "
- << result_type << " not yet implemented";
+ // Processing a Dex `double-to-long' instruction.
+ codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pD2l),
+ conversion,
+ conversion->GetDexPc());
break;
default:
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 2aa121d04b..2fd712f7e2 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1330,9 +1330,11 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) {
Primitive::Type input_type = conversion->GetInputType();
DCHECK_NE(result_type, input_type);
- // Float-to-long conversions invoke the runtime.
+ // The float-to-long and double-to-long type conversions rely on a
+ // call to the runtime.
LocationSummary::CallKind call_kind =
- (input_type == Primitive::kPrimFloat && result_type == Primitive::kPrimLong)
+ ((input_type == Primitive::kPrimFloat || input_type == Primitive::kPrimDouble)
+ && result_type == Primitive::kPrimLong)
? LocationSummary::kCall
: LocationSummary::kNoCall;
LocationSummary* locations =
@@ -1387,8 +1389,10 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) {
break;
case Primitive::kPrimDouble:
- LOG(FATAL) << "Type conversion from " << input_type
- << " to " << result_type << " not yet implemented";
+ // Processing a Dex `double-to-int' instruction.
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresFpuRegister());
break;
default:
@@ -1411,15 +1415,27 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) {
case Primitive::kPrimFloat: {
// Processing a Dex `float-to-long' instruction.
InvokeRuntimeCallingConvention calling_convention;
- locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
+ // Note that on x86 floating-point parameters are passed
+ // through core registers (here, EAX).
+ locations->SetInAt(0, Location::RegisterLocation(
+ calling_convention.GetRegisterAt(0)));
// The runtime helper puts the result in EAX, EDX.
locations->SetOut(Location::RegisterPairLocation(EAX, EDX));
break;
}
- case Primitive::kPrimDouble:
- LOG(FATAL) << "Type conversion from " << input_type << " to "
- << result_type << " not yet implemented";
+ case Primitive::kPrimDouble: {
+ // Processing a Dex `double-to-long' instruction.
+ InvokeRuntimeCallingConvention calling_convention;
+ // Note that on x86 floating-point parameters are passed
+ // through core registers (here, EAX and ECX).
+ locations->SetInAt(0, Location::RegisterPairLocation(
+ calling_convention.GetRegisterAt(0),
+ calling_convention.GetRegisterAt(1)));
+ // The runtime helper puts the result in EAX, EDX.
+ locations->SetOut(Location::RegisterPairLocation(EAX, EDX));
+ break;
+ }
break;
default:
@@ -1607,10 +1623,30 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio
break;
}
- case Primitive::kPrimDouble:
- LOG(FATAL) << "Type conversion from " << input_type
- << " to " << result_type << " not yet implemented";
+ case Primitive::kPrimDouble: {
+ // Processing a Dex `double-to-int' instruction.
+ XmmRegister input = in.AsFpuRegister<XmmRegister>();
+ Register output = out.AsRegister<Register>();
+ XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
+ Label done, nan;
+
+ __ movl(output, Immediate(kPrimIntMax));
+ // temp = int-to-double(output)
+ __ cvtsi2sd(temp, output);
+ // if input >= temp goto done
+ __ comisd(input, temp);
+ __ j(kAboveEqual, &done);
+ // if input == NaN goto nan
+ __ j(kUnordered, &nan);
+ // output = double-to-int-truncate(input)
+ __ cvttsd2si(output, input);
+ __ jmp(&done);
+ __ Bind(&nan);
+ // output = 0
+ __ xorl(output, output);
+ __ Bind(&done);
break;
+ }
default:
LOG(FATAL) << "Unexpected type conversion from " << input_type
@@ -1634,13 +1670,13 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio
case Primitive::kPrimFloat:
// Processing a Dex `float-to-long' instruction.
__ fs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pF2l)));
- // This call does not actually record PC information.
codegen_->RecordPcInfo(conversion, conversion->GetDexPc());
break;
case Primitive::kPrimDouble:
- LOG(FATAL) << "Type conversion from " << input_type << " to "
- << result_type << " not yet implemented";
+ // Processing a Dex `double-to-long' instruction.
+ __ fs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pD2l)));
+ codegen_->RecordPcInfo(conversion, conversion->GetDexPc());
break;
default:
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 5761fb1bda..39a97661c9 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1370,8 +1370,10 @@ void LocationsBuilderX86_64::VisitTypeConversion(HTypeConversion* conversion) {
break;
case Primitive::kPrimDouble:
- LOG(FATAL) << "Type conversion from " << input_type
- << " to " << result_type << " not yet implemented";
+ // Processing a Dex `double-to-int' instruction.
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresFpuRegister());
break;
default:
@@ -1401,8 +1403,10 @@ void LocationsBuilderX86_64::VisitTypeConversion(HTypeConversion* conversion) {
break;
case Primitive::kPrimDouble:
- LOG(FATAL) << "Type conversion from " << input_type << " to "
- << result_type << " not yet implemented";
+ // Processing a Dex `double-to-long' instruction.
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresFpuRegister());
break;
default:
@@ -1589,10 +1593,30 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver
break;
}
- case Primitive::kPrimDouble:
- LOG(FATAL) << "Type conversion from " << input_type
- << " to " << result_type << " not yet implemented";
+ case Primitive::kPrimDouble: {
+ // Processing a Dex `double-to-int' instruction.
+ XmmRegister input = in.AsFpuRegister<XmmRegister>();
+ CpuRegister output = out.AsRegister<CpuRegister>();
+ XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
+ Label done, nan;
+
+ __ movl(output, Immediate(kPrimIntMax));
+ // temp = int-to-double(output)
+ __ cvtsi2sd(temp, output);
+ // if input >= temp goto done
+ __ comisd(input, temp);
+ __ j(kAboveEqual, &done);
+ // if input == NaN goto nan
+ __ j(kUnordered, &nan);
+ // output = double-to-int-truncate(input)
+ __ cvttsd2si(output, input);
+ __ jmp(&done);
+ __ Bind(&nan);
+ // output = 0
+ __ xorl(output, output);
+ __ Bind(&done);
break;
+ }
default:
LOG(FATAL) << "Unexpected type conversion from " << input_type
@@ -1620,14 +1644,14 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver
Label done, nan;
__ movq(output, Immediate(kPrimLongMax));
- // temp = int-to-float(output)
+ // temp = long-to-float(output)
__ cvtsi2ss(temp, output, true);
// if input >= temp goto done
__ comiss(input, temp);
__ j(kAboveEqual, &done);
// if input == NaN goto nan
__ j(kUnordered, &nan);
- // output = float-to-int-truncate(input)
+ // output = float-to-long-truncate(input)
__ cvttss2si(output, input, true);
__ jmp(&done);
__ Bind(&nan);
@@ -1637,10 +1661,30 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver
break;
}
- case Primitive::kPrimDouble:
- LOG(FATAL) << "Type conversion from " << input_type << " to "
- << result_type << " not yet implemented";
+ case Primitive::kPrimDouble: {
+ // Processing a Dex `double-to-long' instruction.
+ XmmRegister input = in.AsFpuRegister<XmmRegister>();
+ CpuRegister output = out.AsRegister<CpuRegister>();
+ XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
+ Label done, nan;
+
+ __ movq(output, Immediate(kPrimLongMax));
+ // temp = long-to-double(output)
+ __ cvtsi2sd(temp, output, true);
+ // if input >= temp goto done
+ __ comisd(input, temp);
+ __ j(kAboveEqual, &done);
+ // if input == NaN goto nan
+ __ j(kUnordered, &nan);
+ // output = double-to-long-truncate(input)
+ __ cvttsd2si(output, input, true);
+ __ jmp(&done);
+ __ Bind(&nan);
+ // output = 0
+ __ xorq(output, output);
+ __ Bind(&done);
break;
+ }
default:
LOG(FATAL) << "Unexpected type conversion from " << input_type
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index 3c21236a8a..2a6c58e128 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -683,9 +683,19 @@ void X86_64Assembler::cvttss2si(CpuRegister dst, XmmRegister src, bool is64bit)
void X86_64Assembler::cvttsd2si(CpuRegister dst, XmmRegister src) {
+ cvttsd2si(dst, src, false);
+}
+
+
+void X86_64Assembler::cvttsd2si(CpuRegister dst, XmmRegister src, bool is64bit) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xF2);
- EmitOptionalRex32(dst, src);
+ if (is64bit) {
+ // Emit a REX.W prefix if the operand size is 64 bits.
+ EmitRex64(dst, src);
+ } else {
+ EmitOptionalRex32(dst, src);
+ }
EmitUint8(0x0F);
EmitUint8(0x2C);
EmitXmmRegisterOperand(dst.LowBits(), src);
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index 4c2836665d..51d1de2c0f 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -342,6 +342,7 @@ class X86_64Assembler FINAL : public Assembler {
void cvttss2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
void cvttss2si(CpuRegister dst, XmmRegister src, bool is64bit);
void cvttsd2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
+ void cvttsd2si(CpuRegister dst, XmmRegister src, bool is64bit);
void cvtdq2pd(XmmRegister dst, XmmRegister src);