#include "code_generator_arm.h"
+#include "arch/arm/instruction_set_features_arm.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "gc/accounting/card_table.h"
#include "mirror/array-inl.h"
return kArmWordSize;
}
-CodeGeneratorARM::CodeGeneratorARM(HGraph* graph)
+CodeGeneratorARM::CodeGeneratorARM(HGraph* graph,
+ const ArmInstructionSetFeatures* isa_features)
: CodeGenerator(graph, kNumberOfCoreRegisters, kNumberOfSRegisters, kNumberOfRegisterPairs),
block_labels_(graph->GetArena(), 0),
location_builder_(graph, this),
instruction_visitor_(graph, this),
move_resolver_(graph->GetArena(), this),
- assembler_(true) {}
+ assembler_(true),
+ isa_features_(isa_features) {}
size_t CodeGeneratorARM::FrameEntrySpillSize() const {
return kNumberOfPushedRegistersAtEntry * kArmWordSize;
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
- bool is_volatile = field_info.IsVolatile();
+
Primitive::Type field_type = field_info.GetFieldType();
bool is_wide = field_type == Primitive::kPrimLong || field_type == Primitive::kPrimDouble;
-
+ bool generate_volatile = field_info.IsVolatile()
+ && is_wide
+ && !codegen_->GetInstructionSetFeatures()->HasAtomicLdrdAndStrd();
// Temporary registers for the write barrier.
// TODO: consider renaming StoreNeedsWriteBarrier to StoreNeedsGCMark.
if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1))) {
locations->AddTemp(Location::RequiresRegister());
locations->AddTemp(Location::RequiresRegister());
- } else if (is_volatile && is_wide) {
+ } else if (generate_volatile) {
// Arm encoding have some additional constraints for ldrexd/strexd:
// - registers need to be consecutive
// - the first register should be even but not R14.
Location value = locations->InAt(1);
bool is_volatile = field_info.IsVolatile();
+ bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures()->HasAtomicLdrdAndStrd();
Primitive::Type field_type = field_info.GetFieldType();
uint32_t offset = field_info.GetFieldOffset().Uint32Value();
}
case Primitive::kPrimLong: {
- if (is_volatile) {
- // TODO: We could use ldrd and strd that are atomic with Large Physical Address Extension
- // support. This info is stored in the compiler driver (HasAtomicLdrdAndStrd) and we should
- // pass it around to be able to optimize.
+ if (is_volatile && !atomic_ldrd_strd) {
GenerateWideAtomicStore(base, offset,
value.AsRegisterPairLow<Register>(),
value.AsRegisterPairHigh<Register>(),
case Primitive::kPrimDouble: {
DRegister value_reg = FromLowSToD(value.AsFpuRegisterPairLow<SRegister>());
- if (is_volatile) {
+ if (is_volatile && !atomic_ldrd_strd) {
Register value_reg_lo = locations->GetTemp(0).AsRegister<Register>();
Register value_reg_hi = locations->GetTemp(1).AsRegister<Register>();
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
- if (field_info.IsVolatile() && (field_info.GetFieldType() == Primitive::kPrimDouble)) {
+ bool generate_volatile = field_info.IsVolatile()
+ && (field_info.GetFieldType() == Primitive::kPrimDouble)
+ && !codegen_->GetInstructionSetFeatures()->HasAtomicLdrdAndStrd();
+ if (generate_volatile) {
// Arm encoding have some additional constraints for ldrexd/strexd:
// - registers need to be consecutive
// - the first register should be even but not R14.
Register base = locations->InAt(0).AsRegister<Register>();
Location out = locations->Out();
bool is_volatile = field_info.IsVolatile();
+ bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures()->HasAtomicLdrdAndStrd();
Primitive::Type field_type = field_info.GetFieldType();
uint32_t offset = field_info.GetFieldOffset().Uint32Value();
}
case Primitive::kPrimLong: {
- if (is_volatile) {
+ if (is_volatile && !atomic_ldrd_strd) {
GenerateWideAtomicLoad(base, offset,
out.AsRegisterPairLow<Register>(),
out.AsRegisterPairHigh<Register>());
case Primitive::kPrimDouble: {
DRegister out_reg = FromLowSToD(out.AsFpuRegisterPairLow<SRegister>());
- if (is_volatile) {
+ if (is_volatile && !atomic_ldrd_strd) {
Register lo = locations->GetTemp(0).AsRegister<Register>();
Register hi = locations->GetTemp(1).AsRegister<Register>();
GenerateWideAtomicLoad(base, offset, lo, hi);
#include <functional>
#include "arch/instruction_set.h"
+#include "arch/arm/instruction_set_features_arm.h"
#include "base/macros.h"
#include "builder.h"
#include "code_generator_arm.h"
Run(allocator, codegenX86, has_result, expected);
}
- arm::CodeGeneratorARM codegenARM(graph);
+ arm::CodeGeneratorARM codegenARM(graph, ArmInstructionSetFeatures::FromCppDefines());
codegenARM.CompileBaseline(&allocator, true);
if (kRuntimeISA == kArm || kRuntimeISA == kThumb2) {
Run(allocator, codegenARM, has_result, expected);
bool has_result,
Expected expected) {
if (kRuntimeISA == kArm || kRuntimeISA == kThumb2) {
- arm::CodeGeneratorARM codegenARM(graph);
+ arm::CodeGeneratorARM codegenARM(graph, ArmInstructionSetFeatures::FromCppDefines());
RunCodeOptimized(&codegenARM, graph, hook_before_codegen, has_result, expected);
} else if (kRuntimeISA == kArm64) {
arm64::CodeGeneratorARM64 codegenARM64(graph);
return nullptr;
}
- CodeGenerator* codegen = CodeGenerator::Create(&arena, graph, instruction_set);
+ CompilerDriver* compiler_driver = GetCompilerDriver();
+ CodeGenerator* codegen = CodeGenerator::Create(&arena, graph, instruction_set,
+ *compiler_driver->GetInstructionSetFeatures());
if (codegen == nullptr) {
CHECK(!shouldCompile) << "Could not find code generator for optimizing compiler";
compilation_stats_.RecordStat(MethodCompilationStat::kNotCompiledNoCodegen);
return nullptr;
}
RunOptimizations(
- graph, GetCompilerDriver(), &compilation_stats_, dex_compilation_unit, visualizer);
+ graph, compiler_driver, &compilation_stats_, dex_compilation_unit, visualizer);
PrepareForRegisterAllocation(graph).Run();
SsaLivenessAnalysis liveness(*graph, codegen);
compilation_stats_.RecordStat(MethodCompilationStat::kCompiledOptimized);
return CompiledMethod::SwapAllocCompiledMethodStackMap(
- GetCompilerDriver(),
+ compiler_driver,
instruction_set,
ArrayRef<const uint8_t>(allocator.GetMemory()),
codegen->GetFrameSize(),
std::vector<uint8_t> mapping_table;
DefaultSrcMap src_mapping_table;
- codegen->BuildMappingTable(&mapping_table,
- GetCompilerDriver()->GetCompilerOptions().GetIncludeDebugSymbols() ?
- &src_mapping_table : nullptr);
+ bool include_debug_symbol = compiler_driver->GetCompilerOptions().GetIncludeDebugSymbols();
+ codegen->BuildMappingTable(&mapping_table, include_debug_symbol ? &src_mapping_table : nullptr);
std::vector<uint8_t> vmap_table;
codegen->BuildVMapTable(&vmap_table);
std::vector<uint8_t> gc_map;
codegen->BuildNativeGCMap(&gc_map, dex_compilation_unit);
compilation_stats_.RecordStat(MethodCompilationStat::kCompiledBaseline);
- return CompiledMethod::SwapAllocCompiledMethod(GetCompilerDriver(),
+ return CompiledMethod::SwapAllocCompiledMethod(compiler_driver,
instruction_set,
ArrayRef<const uint8_t>(allocator.GetMemory()),
codegen->GetFrameSize(),