Commit 3573d3cb authored by balazs.kilvady's avatar balazs.kilvady Committed by Commit bot

MIPS: r6 compact branch optimization.

BUG=

Review URL: https://codereview.chromium.org/1396133002

Cr-Commit-Position: refs/heads/master@{#31761}
parent 05947816
......@@ -879,8 +879,6 @@ void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) {
Address patch_address =
andi_instruction_address - delta * Instruction::kInstrSize;
Instr instr_at_patch = Assembler::instr_at(patch_address);
Instr branch_instr =
Assembler::instr_at(patch_address + Instruction::kInstrSize);
// This is patching a conditional "jump if not smi/jump if smi" site.
// Enabling by changing from
// andi at, rx, 0
......@@ -900,13 +898,44 @@ void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) {
DCHECK(Assembler::IsAndImmediate(instr_at_patch));
patcher.masm()->andi(at, reg, 0);
}
Instr branch_instr =
Assembler::instr_at(patch_address + Instruction::kInstrSize);
DCHECK(Assembler::IsBranch(branch_instr));
if (Assembler::IsBeq(branch_instr)) {
patcher.ChangeBranchCondition(ne);
} else {
DCHECK(Assembler::IsBne(branch_instr));
patcher.ChangeBranchCondition(eq);
uint32_t opcode = Assembler::GetOpcodeField(branch_instr);
// Currently only the 'eq' and 'ne' cond values are supported and the simple
// branch instructions and their r6 variants (with opcode being the branch
// type). There are some special cases (see Assembler::IsBranch()) so
// extending this would be tricky.
DCHECK(opcode == BEQ || // BEQ
opcode == BNE || // BNE
opcode == POP10 || // BEQC
opcode == POP30 || // BNEC
opcode == POP66 || // BEQZC
opcode == POP76); // BNEZC
switch (opcode) {
case BEQ:
opcode = BNE; // change BEQ to BNE.
break;
case POP10:
opcode = POP30; // change BEQC to BNEC.
break;
case POP66:
opcode = POP76; // change BEQZC to BNEZC.
break;
case BNE:
opcode = BEQ; // change BNE to BEQ.
break;
case POP30:
opcode = POP10; // change BNEC to BEQC.
break;
case POP76:
opcode = POP66; // change BNEZC to BEQZC.
break;
default:
UNIMPLEMENTED();
}
patcher.ChangeBranchCondition(branch_instr, opcode);
}
} // namespace internal
} // namespace v8
......
......@@ -445,12 +445,24 @@ void Assembler::CheckTrampolinePoolQuick(int extra_instructions) {
}
void Assembler::emit(Instr x) {
void Assembler::emit(Instr x, CompactBranchType is_compact_branch) {
if (!is_buffer_growth_blocked()) {
CheckBuffer();
}
if (IsPrevInstrCompactBranch()) {
if (Instruction::IsForbiddenAfterBranchInstr(x)) {
// Nop instruction to preceed a CTI in forbidden slot:
Instr nop = SPECIAL | SLL;
*reinterpret_cast<Instr*>(pc_) = nop;
pc_ += kInstrSize;
}
ClearCompactBranchState();
}
*reinterpret_cast<Instr*>(pc_) = x;
pc_ += kInstrSize;
if (is_compact_branch == CompactBranchType::COMPACT_BRANCH) {
EmittedCompactBranchInstruction();
}
CheckTrampolinePoolQuick();
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -126,24 +126,28 @@ int FPURegisters::Number(const char* name) {
// -----------------------------------------------------------------------------
// Instructions.
bool Instruction::IsForbiddenInBranchDelay() const {
const int op = OpcodeFieldRaw();
switch (op) {
bool Instruction::IsForbiddenAfterBranchInstr(Instr instr) {
Opcode opcode = static_cast<Opcode>(instr & kOpcodeMask);
switch (opcode) {
case J:
case JAL:
case BEQ:
case BNE:
case BLEZ:
case BGTZ:
case BLEZ: // POP06 bgeuc/bleuc, blezalc, bgezalc
case BGTZ: // POP07 bltuc/bgtuc, bgtzalc, bltzalc
case BEQL:
case BNEL:
case BLEZL:
case BGTZL:
case BLEZL: // POP26 bgezc, blezc, bgec/blec
case BGTZL: // POP27 bgtzc, bltzc, bltc/bgtc
case BC:
case BALC:
case POP10: // beqzalc, bovc, beqc
case POP30: // bnezalc, bvnc, bnec
case POP66: // beqzc, jic
case POP76: // bnezc, jialc
return true;
case REGIMM:
switch (RtFieldRaw()) {
switch (instr & kRtFieldMask) {
case BLTZ:
case BGEZ:
case BLTZAL:
......@@ -154,7 +158,7 @@ bool Instruction::IsForbiddenInBranchDelay() const {
}
break;
case SPECIAL:
switch (FunctionFieldRaw()) {
switch (instr & kFunctionFieldMask) {
case JR:
case JALR:
return true;
......@@ -169,8 +173,7 @@ bool Instruction::IsForbiddenInBranchDelay() const {
bool Instruction::IsLinkingInstruction() const {
const int op = OpcodeFieldRaw();
switch (op) {
switch (OpcodeFieldRaw()) {
case JAL:
return true;
case POP76:
......
This diff is collapsed.
......@@ -1377,12 +1377,12 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
Format(instr, "blez 'rs, 'imm16u -> 'imm16p4s2");
} else if ((instr->RtValue() != instr->RsValue()) &&
(instr->RsValue() != 0) && (instr->RtValue() != 0)) {
Format(instr, "bgeuc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
Format(instr, "bgeuc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
} else if ((instr->RtValue() == instr->RsValue()) &&
(instr->RtValue() != 0)) {
Format(instr, "bgezalc 'rs, 'imm16u -> 'imm16p4s2");
Format(instr, "bgezalc 'rs, 'imm16u -> 'imm16p4s2");
} else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
Format(instr, "blezalc 'rt, 'imm16u -> 'imm16p4s2");
Format(instr, "blezalc 'rt, 'imm16u -> 'imm16p4s2");
} else {
UNREACHABLE();
}
......@@ -1419,7 +1419,7 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
Format(instr, "bltzc 'rt, 'imm16u -> 'imm16p4s2");
} else if ((instr->RtValue() != instr->RsValue()) &&
(instr->RsValue() != 0) && (instr->RtValue() != 0)) {
Format(instr, "bltc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
Format(instr, "bltc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
} else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
Format(instr, "bgtzc 'rt, 'imm16u -> 'imm16p4s2");
} else {
......@@ -1445,25 +1445,33 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
if (!IsMipsArchVariant(kMips32r6)) {
Format(instr, "addi 'rt, 'rs, 'imm16s");
} else {
// Check if BOVC or BEQC instruction.
if (instr->RsValue() >= instr->RtValue()) {
int rs_reg = instr->RsValue();
int rt_reg = instr->RtValue();
// Check if BOVC, BEQZALC or BEQC instruction.
if (rs_reg >= rt_reg) {
Format(instr, "bovc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
} else if (instr->RsValue() < instr->RtValue()) {
Format(instr, "beqc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
} else {
UNREACHABLE();
if (rs_reg == 0) {
Format(instr, "beqzalc 'rt, 'imm16s -> 'imm16p4s2");
} else {
Format(instr, "beqc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
}
}
}
break;
case DADDI:
if (IsMipsArchVariant(kMips32r6)) {
// Check if BNVC or BNEC instruction.
if (instr->RsValue() >= instr->RtValue()) {
int rs_reg = instr->RsValue();
int rt_reg = instr->RtValue();
// Check if BNVC, BNEZALC or BNEC instruction.
if (rs_reg >= rt_reg) {
Format(instr, "bnvc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
} else if (instr->RsValue() < instr->RtValue()) {
Format(instr, "bnec 'rs, 'rt, 'imm16s -> 'imm16p4s2");
} else {
UNREACHABLE();
if (rs_reg == 0) {
Format(instr, "bnezalc 'rt, 'imm16s -> 'imm16p4s2");
} else {
Format(instr, "bnec 'rs, 'rt, 'imm16s -> 'imm16p4s2");
}
}
}
break;
......
This diff is collapsed.
......@@ -164,9 +164,9 @@ class MacroAssembler: public Assembler {
Name(target, COND_ARGS, bd); \
}
#define DECLARE_BRANCH_PROTOTYPES(Name) \
#define DECLARE_BRANCH_PROTOTYPES(Name) \
DECLARE_NORELOC_PROTOTYPE(Name, Label*) \
DECLARE_NORELOC_PROTOTYPE(Name, int16_t)
DECLARE_NORELOC_PROTOTYPE(Name, int32_t)
DECLARE_BRANCH_PROTOTYPES(Branch)
DECLARE_BRANCH_PROTOTYPES(BranchAndLink)
......@@ -203,6 +203,8 @@ class MacroAssembler: public Assembler {
Ret(cond, rs, rt, bd);
}
bool IsNear(Label* L, Condition cond, int rs_reg);
void Branch(Label* L,
Condition cond,
Register rs,
......@@ -1632,14 +1634,30 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
int num_reg_arguments,
int num_double_arguments);
void BranchAndLinkShort(int16_t offset, BranchDelaySlot bdslot = PROTECT);
void BranchAndLinkShort(int16_t offset, Condition cond, Register rs,
const Operand& rt,
BranchDelaySlot bdslot = PROTECT);
inline Register GetRtAsRegisterHelper(const Operand& rt, Register scratch);
inline int32_t GetOffset(int32_t offset, Label* L, OffsetSize bits);
void BranchShortHelperR6(int32_t offset, Label* L);
void BranchShortHelper(int16_t offset, Label* L, BranchDelaySlot bdslot);
bool BranchShortHelperR6(int32_t offset, Label* L, Condition cond,
Register rs, const Operand& rt);
bool BranchShortHelper(int16_t offset, Label* L, Condition cond, Register rs,
const Operand& rt, BranchDelaySlot bdslot);
bool BranchShortCheck(int32_t offset, Label* L, Condition cond, Register rs,
const Operand& rt, BranchDelaySlot bdslot);
void BranchAndLinkShortHelperR6(int32_t offset, Label* L);
void BranchAndLinkShortHelper(int16_t offset, Label* L,
BranchDelaySlot bdslot);
void BranchAndLinkShort(int32_t offset, BranchDelaySlot bdslot = PROTECT);
void BranchAndLinkShort(Label* L, BranchDelaySlot bdslot = PROTECT);
void BranchAndLinkShort(Label* L, Condition cond, Register rs,
const Operand& rt,
BranchDelaySlot bdslot = PROTECT);
bool BranchAndLinkShortHelperR6(int32_t offset, Label* L, Condition cond,
Register rs, const Operand& rt);
bool BranchAndLinkShortHelper(int16_t offset, Label* L, Condition cond,
Register rs, const Operand& rt,
BranchDelaySlot bdslot);
bool BranchAndLinkShortCheck(int32_t offset, Label* L, Condition cond,
Register rs, const Operand& rt,
BranchDelaySlot bdslot);
void Jr(Label* L, BranchDelaySlot bdslot);
void Jalr(Label* L, BranchDelaySlot bdslot);
......@@ -1726,7 +1744,7 @@ class CodePatcher {
// Change the condition part of an instruction leaving the rest of the current
// instruction unchanged.
void ChangeBranchCondition(Condition cond);
void ChangeBranchCondition(Instr current_instr, uint32_t new_opcode);
private:
byte* address_; // The address of the code being patched.
......
This diff is collapsed.
......@@ -315,6 +315,7 @@ class Simulator {
void DecodeTypeRegisterLRsType();
Instruction* currentInstr_;
inline Instruction* get_instr() const { return currentInstr_; }
inline void set_instr(Instruction* instr) { currentInstr_ = instr; }
......@@ -346,6 +347,18 @@ class Simulator {
// Used for breakpoints and traps.
void SoftwareInterrupt(Instruction* instr);
// Compact branch guard.
void CheckForbiddenSlot(int32_t current_pc) {
Instruction* instr_aftter_compact_branch =
reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
if (instr_aftter_compact_branch->IsForbiddenInBranchDelay()) {
V8_Fatal(__FILE__, __LINE__,
"Error: Unexpected instruction 0x%08x immediately after a "
"compact branch instruction.",
*reinterpret_cast<uint32_t*>(instr_aftter_compact_branch));
}
}
// Stop helper functions.
bool IsWatchpoint(uint32_t code);
void PrintWatchpoint(uint32_t code);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment