Don't touch x18 on ARM64 - it is globally reserved on iOS.

Move SP on ARM64 to x19.

Use a mask instead of a range for determining the globally blocked registers.

R=regis@google.com

Review URL: https://codereview.chromium.org/1417433002 .
This commit is contained in:
Ryan Macnak 2015-10-19 14:17:07 -07:00
parent caedcce440
commit 91bc8005fe
13 changed files with 139 additions and 125 deletions

View file

@ -26,8 +26,6 @@ namespace dart {
enum Register {
kNoRegister = -1,
kFirstFreeCpuRegister = 0,
R0 = 0,
R1 = 1,
R2 = 2,
@ -36,21 +34,23 @@ enum Register {
R5 = 5,
R6 = 6,
R7 = 7,
R8 = 8,
R9 = 9,
R10 = 10,
R11 = 11,
R12 = 12,
R13 = 13,
R14 = 14,
kLastFreeCpuRegister = 14,
R15 = 15,
R8 = 8, // THR
R9 = 9, // PP
R10 = 10, // CTX
R11 = 11, // FP
R12 = 12, // IP aka TMP
R13 = 13, // SP
R14 = 14, // LR
R15 = 15, // PC
kNumberOfCpuRegisters = 16,
kNoRegister = -1, // Signals an illegal register.
// Aliases.
FP = R11,
IP = R12,
SP = R13,
LR = R14,
PC = R15,
kNumberOfCpuRegisters = 16,
};
@ -269,12 +269,16 @@ const QRegister kAbiFirstPreservedFpuReg = Q4;
const QRegister kAbiLastPreservedFpuReg = Q7;
const int kAbiPreservedFpuRegCount = 4;
const RegList kReservedCpuRegisters =
(1 << SPREG) |
(1 << FPREG) |
(1 << TMP) |
(1 << PP) |
(1 << THR) |
(1 << PC);
// CPU registers available to Dart allocator.
const RegList kDartAvailableCpuRegs =
(1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) |
(1 << R4) | (1 << R5) | (1 << R6) | (1 << R7) |
(1 << R8) | (1 << R14);
kAllCpuRegistersList & ~kReservedCpuRegisters;
// Registers available to Dart that are not preserved by runtime calls.
const RegList kDartVolatileCpuRegs =
kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs;

View file

@ -10,7 +10,6 @@
namespace dart {
enum Register {
kFirstFreeCpuRegister = 0,
R0 = 0,
R1 = 1,
R2 = 2,
@ -29,16 +28,15 @@ enum Register {
R15 = 15,
R16 = 16, // IP0 aka TMP
R17 = 17, // IP1 aka TMP2
R18 = 18, // SP in Dart code.
R19 = 19,
R20 = 20,
R18 = 18, // "platform register" on iOS.
R19 = 19, // SP in Dart code.
R20 = 20, // THR
R21 = 21,
R22 = 22,
R23 = 23,
R24 = 24,
R25 = 25,
R26 = 26,
kLastFreeCpuRegister = 26,
R27 = 27, // PP
R28 = 28, // CTX
R29 = 29, // FP
@ -55,11 +53,12 @@ enum Register {
// Aliases.
IP0 = R16,
IP1 = R17,
SP = R18,
SP = R19,
FP = R29,
LR = R30,
};
enum VRegister {
V0 = 0,
V1 = 1,
@ -113,12 +112,13 @@ const Register CTX = R28; // Location of current context at method entry.
const Register PP = R27; // Caches object pool pointer in generated code.
const Register CODE_REG = R24;
const Register FPREG = FP; // Frame pointer register.
const Register SPREG = R18; // Stack pointer register.
const Register SPREG = R19; // Stack pointer register.
const Register LRREG = LR; // Link register.
const Register ICREG = R5; // IC data register.
const Register ARGS_DESC_REG = R4; // Arguments descriptor register.
const Register THR = R20; // Caches current thread in generated code.
// Exception object is passed in this register to the catch handlers when an
// exception is thrown.
const Register kExceptionObjectReg = R0;
@ -143,25 +143,31 @@ const RegList kAbiArgumentCpuRegs =
(1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) |
(1 << R4) | (1 << R5) | (1 << R6) | (1 << R7);
const RegList kAbiPreservedCpuRegs =
(1 << R19) | (1 << R20) | (1 << R21) | (1 << R22) |
(1 << R23) | (1 << R24) | (1 << R25) | (1 << R26) |
(1 << R27) | (1 << R28);
const Register kAbiFirstPreservedCpuReg = R19;
(1 << R20) | (1 << R21) | (1 << R22) | (1 << R23) |
(1 << R24) | (1 << R25) | (1 << R26) | (1 << R27) |
(1 << R28);
const Register kAbiFirstPreservedCpuReg = R20;
const Register kAbiLastPreservedCpuReg = R28;
const int kAbiPreservedCpuRegCount = 10;
const int kAbiPreservedCpuRegCount = 9;
const VRegister kAbiFirstPreservedFpuReg = V8;
const VRegister kAbiLastPreservedFpuReg = V15;
const int kAbiPreservedFpuRegCount = 8;
const intptr_t kReservedCpuRegisters =
(1 << SPREG) | // Dart SP
(1 << FPREG) |
(1 << TMP) |
(1 << TMP2) |
(1 << PP) |
(1 << THR) |
(1 << LR) |
(1 << R31) | // C++ SP
(1 << CTX) |
(1 << R18); // iOS platform register.
// TODO(rmacnak): Only reserve on Mac & iOS.
// CPU registers available to Dart allocator.
const RegList kDartAvailableCpuRegs =
(1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) |
(1 << R4) | (1 << R5) | (1 << R6) | (1 << R7) |
(1 << R8) | (1 << R9) | (1 << R10) | (1 << R11) |
(1 << R12) | (1 << R13) | (1 << R14) | (1 << R15) |
(1 << R19) | (1 << R20) | (1 << R21) | (1 << R22) |
(1 << R23) | (1 << R24) | (1 << R25) | (1 << R26);
kAllCpuRegistersList & ~kReservedCpuRegisters;
// Registers available to Dart that are not preserved by runtime calls.
const RegList kDartVolatileCpuRegs =
kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs;

View file

@ -10,7 +10,6 @@
namespace dart {
enum Register {
kFirstFreeCpuRegister = 0,
EAX = 0,
ECX = 1,
EDX = 2,
@ -19,9 +18,8 @@ enum Register {
EBP = 5,
ESI = 6,
EDI = 7,
kLastFreeCpuRegister = 7,
kNumberOfCpuRegisters = 8,
kNoRegister = -1 // Signals an illegal register.
kNoRegister = -1, // Signals an illegal register.
};
@ -71,6 +69,7 @@ const Register ICREG = ECX; // IC data register.
const Register ARGS_DESC_REG = EDX; // Arguments descriptor register.
const Register THR = ESI; // Caches current thread in generated code.
// Exception object is passed in this register to the catch handlers when an
// exception is thrown.
const Register kExceptionObjectReg = EAX;
@ -80,6 +79,18 @@ const Register kExceptionObjectReg = EAX;
const Register kStackTraceObjectReg = EDX;
typedef uint32_t RegList;
const RegList kAllCpuRegistersList = 0xFF;
const intptr_t kReservedCpuRegisters =
(1 << SPREG) |
(1 << FPREG) |
(1 << THR);
// CPU registers available to Dart allocator.
const RegList kDartAvailableCpuRegs =
kAllCpuRegistersList & ~kReservedCpuRegisters;
enum ScaleFactor {
TIMES_1 = 0,
TIMES_2 = 1,

View file

@ -11,8 +11,7 @@ namespace dart {
enum Register {
R0 = 0,
R1 = 1,
kFirstFreeCpuRegister = 2,
R1 = 1, // AT aka TMP
R2 = 2,
R3 = 3,
R4 = 4,
@ -30,23 +29,23 @@ enum Register {
R16 = 16,
R17 = 17,
R18 = 18,
R19 = 19,
R19 = 19, // THR
R20 = 20,
R21 = 21,
kLastFreeCpuRegister = 21,
R22 = 22,
R23 = 23,
R22 = 22, // CTX
R23 = 23, // PP
R24 = 24,
R25 = 25,
R26 = 26,
R27 = 27,
R28 = 28,
R29 = 29,
R30 = 30,
R31 = 31,
R29 = 29, // SP
R30 = 30, // FP
R31 = 31, // RA
kNumberOfCpuRegisters = 32,
IMM = 32, // Positive value is easier to encode than kNoRegister in bitfield.
kNoRegister = -1,
kNoRegister = -1, // Signals an illegal register.
// Register aliases.
ZR = R0,
@ -188,6 +187,7 @@ const Register ICREG = S5; // IC data register.
const Register ARGS_DESC_REG = S4;
const Register THR = S3; // Caches current thread in generated code.
// The code that generates a comparison can be far away from the code that
// generates the branch that uses the result of that comparison. In this case,
// CMPRES1 and CMPRES2 are used for the results of the comparison. We need two
@ -207,7 +207,6 @@ const Register kStackTraceObjectReg = V1;
typedef uint32_t RegList;
const RegList kAllCpuRegistersList = 0xFFFFFFFF;
const RegList kAbiArgumentCpuRegs =
(1 << A0) | (1 << A1) | (1 << A2) | (1 << A3);
const RegList kAbiPreservedCpuRegs =
@ -221,13 +220,24 @@ const FRegister kAbiLastPreservedFpuReg =
static_cast<FRegister>(kNumberOfFRegisters - 1);
const int kAbiPreservedFpuRegCount = 12;
const RegList kReservedCpuRegisters =
(1 << SPREG) |
(1 << FPREG) |
(1 << TMP) |
(1 << PP) |
(1 << THR) |
(1 << CTX) |
(1 << ZR) |
(1 << CMPRES1) |
(1 << CMPRES2) |
(1 << K0) |
(1 << K1) |
(1 << GP) |
(1 << RA);
// CPU registers available to Dart allocator.
const RegList kDartAvailableCpuRegs =
(1 << R2) | (1 << R3) | (1 << R4) | (1 << R5) |
(1 << R6) | (1 << R7) | (1 << R8) | (1 << R9) |
(1 << R10) | (1 << R11) | (1 << R12) | (1 << R13) |
(1 << R14) | (1 << R15) | (1 << R16) | (1 << R17) |
(1 << R18) | (1 << R19) | (1 << R20) | (1 << R21);
kAllCpuRegistersList & ~kReservedCpuRegisters;
// Registers available to Dart that are not preserved by runtime calls.
const RegList kDartVolatileCpuRegs =
kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs;
const int kDartVolatileCpuRegCount = 14;

View file

@ -8,7 +8,6 @@
namespace dart {
enum Register {
kFirstFreeCpuRegister = 0,
RAX = 0,
RCX = 1,
RDX = 2,
@ -25,9 +24,8 @@ enum Register {
R13 = 13,
R14 = 14,
R15 = 15,
kLastFreeCpuRegister = 15,
kNumberOfCpuRegisters = 16,
kNoRegister = -1 // Signals an illegal register.
kNoRegister = -1, // Signals an illegal register.
};
@ -96,6 +94,7 @@ const Register ARGS_DESC_REG = R10; // Arguments descriptor register.
const Register CODE_REG = R12;
const Register THR = R14; // Caches current thread in generated code.
// Exception object is passed in this register to the catch handlers when an
// exception is thrown.
const Register kExceptionObjectReg = RAX;
@ -105,6 +104,20 @@ const Register kExceptionObjectReg = RAX;
const Register kStackTraceObjectReg = RDX;
typedef uint32_t RegList;
const RegList kAllCpuRegistersList = 0xFFFF;
const RegList kReservedCpuRegisters =
(1 << SPREG) |
(1 << FPREG) |
(1 << TMP) |
(1 << PP) |
(1 << THR);
// CPU registers available to Dart allocator.
const RegList kDartAvailableCpuRegs =
kAllCpuRegistersList & ~kReservedCpuRegisters;
enum ScaleFactor {
TIMES_1 = 0,
TIMES_2 = 1,

View file

@ -83,12 +83,12 @@ void ARM64Decoder::Print(const char* str) {
// These register names are defined in a way to match the native disassembler
// formatting, except for register aliases ctx (r9) and pp (r10).
// formatting, except for register aliases ctx (r9), pp (r10) and sp (r19).
// See for example the command "objdump -d <binary file>".
static const char* reg_names[kNumberOfCpuRegisters] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"ip0", "ip1", "sp", "r19", "r20", "r21", "r22", "r23",
"ip0", "ip1", "r18", "sp", "r20", "r21", "r22", "r23",
"r24", "r25", "r26", "pp", "ctx", "fp", "lr", "r31",
};

View file

@ -101,24 +101,11 @@ FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph,
// All registers are marked as "not blocked" (array initialized to false).
// Mark the unavailable ones as "blocked" (true).
for (intptr_t i = 0; i < kFirstFreeCpuRegister; i++) {
blocked_cpu_registers_[i] = true;
for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
if ((kDartAvailableCpuRegs & (1 << i)) == 0) {
blocked_cpu_registers_[i] = true;
}
}
for (intptr_t i = kLastFreeCpuRegister + 1; i < kNumberOfCpuRegisters; i++) {
blocked_cpu_registers_[i] = true;
}
if (TMP != kNoRegister) {
blocked_cpu_registers_[TMP] = true;
}
if (TMP2 != kNoRegister) {
blocked_cpu_registers_[TMP2] = true;
}
if (PP != kNoRegister) {
blocked_cpu_registers_[PP] = true;
}
blocked_cpu_registers_[SPREG] = true;
blocked_cpu_registers_[FPREG] = true;
blocked_cpu_registers_[THR] = true;
// FpuTMP is used as scratch by optimized code and parallel move resolver.
blocked_fpu_registers_[FpuTMP] = true;

View file

@ -1260,16 +1260,6 @@ static uword RegMaskBit(Register reg) {
}
// Mask of globally reserved registers. Some other registers are only reserved
// in particular code (e.g., ARGS_DESC_REG in intrinsics).
static const uword kReservedCpuRegisters = RegMaskBit(SPREG)
| RegMaskBit(FPREG)
| RegMaskBit(TMP)
| RegMaskBit(TMP2)
| RegMaskBit(PP)
| RegMaskBit(THR);
void FlowGraphCompiler::AllocateRegistersLocally(Instruction* instr) {
ASSERT(!is_optimizing());
@ -1279,16 +1269,10 @@ void FlowGraphCompiler::AllocateRegistersLocally(Instruction* instr) {
bool blocked_registers[kNumberOfCpuRegisters];
// Mark all available registers free.
// Block all registers globally reserved by the assembler, etc and mark
// the rest as free.
for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
blocked_registers[i] = false;
}
// Block all registers globally reserved by the assembler, etc.
for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
if ((kReservedCpuRegisters & (1 << i)) != 0) {
blocked_registers[i] = true;
}
blocked_registers[i] = (kDartAvailableCpuRegs & (1 << i)) == 0;
}
// Mark all fixed input, temp and output registers as used.
@ -1316,14 +1300,6 @@ void FlowGraphCompiler::AllocateRegistersLocally(Instruction* instr) {
blocked_registers[locs->out(0).reg()] = true;
}
// Block all non-free registers.
for (intptr_t i = 0; i < kFirstFreeCpuRegister; i++) {
blocked_registers[i] = true;
}
for (intptr_t i = kLastFreeCpuRegister + 1; i < kNumberOfCpuRegisters; i++) {
blocked_registers[i] = true;
}
// Allocate all unallocated input locations.
const bool should_pop = !instr->IsPushArgument() && !instr->IsPushTemp();
for (intptr_t i = locs->input_count() - 1; i >= 0; i--) {
@ -1582,8 +1558,8 @@ ParallelMoveResolver::ScratchRegisterScope::ScratchRegisterScope(
reg_ = static_cast<Register>(
resolver_->AllocateScratchRegister(Location::kRegister,
blocked_mask,
kFirstFreeCpuRegister,
kLastFreeCpuRegister,
0,
kNumberOfCpuRegisters - 1,
&spilled_));
if (spilled_) {

View file

@ -900,6 +900,7 @@ void Simulator::set_register(
Instr* instr, Register reg, int64_t value, R31Type r31t) {
// Register is in range.
ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
ASSERT(instr == NULL || reg != R18); // R18 is globally reserved on iOS.
if ((reg != R31) || (r31t != R31IsZR)) {
registers_[reg] = value;
// If we're setting CSP, make sure it is 16-byte aligned. In truth, CSP
@ -1650,24 +1651,24 @@ void Simulator::DoRedirectedCall(Instr* instr) {
// Zap caller-saved registers, since the actual runtime call could have
// used them.
set_register(instr, R2, icount_);
set_register(instr, R3, icount_);
set_register(instr, R4, icount_);
set_register(instr, R5, icount_);
set_register(instr, R6, icount_);
set_register(instr, R7, icount_);
set_register(instr, R8, icount_);
set_register(instr, R9, icount_);
set_register(instr, R10, icount_);
set_register(instr, R11, icount_);
set_register(instr, R12, icount_);
set_register(instr, R13, icount_);
set_register(instr, R14, icount_);
set_register(instr, R15, icount_);
set_register(instr, IP0, icount_);
set_register(instr, IP1, icount_);
set_register(instr, R18, icount_);
set_register(instr, LR, icount_);
set_register(NULL, R2, icount_);
set_register(NULL, R3, icount_);
set_register(NULL, R4, icount_);
set_register(NULL, R5, icount_);
set_register(NULL, R6, icount_);
set_register(NULL, R7, icount_);
set_register(NULL, R8, icount_);
set_register(NULL, R9, icount_);
set_register(NULL, R10, icount_);
set_register(NULL, R11, icount_);
set_register(NULL, R12, icount_);
set_register(NULL, R13, icount_);
set_register(NULL, R14, icount_);
set_register(NULL, R15, icount_);
set_register(NULL, IP0, icount_);
set_register(NULL, IP1, icount_);
set_register(NULL, R18, icount_);
set_register(NULL, LR, icount_);
// TODO(zra): Zap caller-saved fpu registers.

View file

@ -44,6 +44,8 @@ static const int kCallerSpSlotFromFp = 2;
// Entry and exit frame layout.
static const int kExitLinkSlotFromEntryFp = -27;
COMPILE_ASSERT(kAbiPreservedCpuRegCount == 7);
COMPILE_ASSERT(kAbiPreservedFpuRegCount == 4);
} // namespace dart

View file

@ -44,7 +44,9 @@ static const int kCallerSpSlotFromFp = 2;
static const int kSavedAboveReturnAddress = 3; // Saved above return address.
// Entry and exit frame layout.
static const int kExitLinkSlotFromEntryFp = -22;
static const int kExitLinkSlotFromEntryFp = -21;
COMPILE_ASSERT(kAbiPreservedCpuRegCount == 9);
COMPILE_ASSERT(kAbiPreservedFpuRegCount == 8);
} // namespace dart

View file

@ -42,6 +42,8 @@ static const int kCallerSpSlotFromFp = 2;
// Entry and exit frame layout.
static const int kExitLinkSlotFromEntryFp = -24;
COMPILE_ASSERT(kAbiPreservedCpuRegCount == 8);
COMPILE_ASSERT(kAbiPreservedFpuRegCount == 12);
} // namespace dart

View file

@ -829,7 +829,7 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
__ LoadFromOffset(R6, THR, Thread::top_exit_frame_info_offset());
__ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
// kExitLinkSlotFromEntryFp must be kept in sync with the code below.
ASSERT(kExitLinkSlotFromEntryFp == -22);
ASSERT(kExitLinkSlotFromEntryFp == -21);
__ Push(R6);
// Load arguments descriptor array into R4, which is passed to Dart code.