Commit 998370fd authored by Lu Yahan's avatar Lu Yahan Committed by V8 LUCI CQ

[riscv64] Optimize-trampoline

In trampoline, we emit auipc+jalr first. But the offset between target and trampoline is less than int21, so we can use jal to replace auipc+jalr.
It can reduce number of execution instruction.

Change-Id: Idc37d80341030130c478209681cb54c63d1ddf27
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2939442
Auto-Submit: Yahan Lu <yahan@iscas.ac.cn>
Commit-Queue: Brice Dobry <brice.dobry@futurewei.com>
Reviewed-by: 's avatarBrice Dobry <brice.dobry@futurewei.com>
Cr-Commit-Position: refs/heads/master@{#75072}
parent 088e252d
......@@ -312,6 +312,8 @@ bool Assembler::IsJump(Instr instr) {
return Op == JAL || Op == JALR;
}
bool Assembler::IsNop(Instr instr) { return instr == kNopByte; }
bool Assembler::IsJal(Instr instr) { return (instr & kBaseOpcodeMask) == JAL; }
bool Assembler::IsJalr(Instr instr) {
......@@ -523,7 +525,8 @@ static inline Instr SetCBranchOffset(int32_t pos, int32_t target_pos,
return instr | (imm8 & kRvcBImm8Mask);
}
void Assembler::target_at_put(int pos, int target_pos, bool is_internal) {
void Assembler::target_at_put(int pos, int target_pos, bool is_internal,
bool trampoline) {
if (is_internal) {
uint64_t imm = reinterpret_cast<uint64_t>(buffer_start_) + target_pos;
*reinterpret_cast<uint64_t*>(buffer_start_ + pos) = imm;
......@@ -542,6 +545,7 @@ void Assembler::target_at_put(int pos, int target_pos, bool is_internal) {
instr_at_put(pos, instr);
} break;
case JAL: {
DCHECK(IsJal(instr));
instr = SetJalOffset(pos, target_pos, instr);
instr_at_put(pos, instr);
} break;
......@@ -556,19 +560,29 @@ void Assembler::target_at_put(int pos, int target_pos, bool is_internal) {
DCHECK(IsJalr(instr_I) || IsAddi(instr_I));
int64_t offset = target_pos - pos;
DCHECK(is_int32(offset));
if (is_int21(offset) && IsJalr(instr_I) && trampoline) {
DCHECK(is_int21(offset) && ((offset & 1) == 0));
Instr instr = JAL;
instr = SetJalOffset(pos, target_pos, instr);
DCHECK(IsJal(instr));
DCHECK(JumpOffset(instr) == offset);
instr_at_put(pos, instr);
instr_at_put(pos + 4, kNopByte);
} else {
DCHECK(is_int32(offset));
int32_t Hi20 = (((int32_t)offset + 0x800) >> 12);
int32_t Lo12 = (int32_t)offset << 20 >> 20;
int32_t Hi20 = (((int32_t)offset + 0x800) >> 12);
int32_t Lo12 = (int32_t)offset << 20 >> 20;
instr_auipc =
(instr_auipc & ~kImm31_12Mask) | ((Hi20 & kImm19_0Mask) << 12);
instr_at_put(pos, instr_auipc);
instr_auipc =
(instr_auipc & ~kImm31_12Mask) | ((Hi20 & kImm19_0Mask) << 12);
instr_at_put(pos, instr_auipc);
const int kImm31_20Mask = ((1 << 12) - 1) << 20;
const int kImm11_0Mask = ((1 << 12) - 1);
instr_I = (instr_I & ~kImm31_20Mask) | ((Lo12 & kImm11_0Mask) << 20);
instr_at_put(pos + 4, instr_I);
const int kImm31_20Mask = ((1 << 12) - 1) << 20;
const int kImm11_0Mask = ((1 << 12) - 1);
instr_I = (instr_I & ~kImm31_20Mask) | ((Lo12 & kImm11_0Mask) << 20);
instr_at_put(pos + 4, instr_I);
}
} break;
case RO_C_J: {
ShortInstr short_instr = SetCJalOffset(pos, target_pos, instr);
......@@ -643,7 +657,7 @@ void Assembler::bind_to(Label* L, int pos) {
}
CHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset);
DEBUG_PRINTF("\t\ttrampolining: %d\n", trampoline_pos);
target_at_put(fixup_pos, trampoline_pos, false);
target_at_put(fixup_pos, trampoline_pos, false, true);
fixup_pos = trampoline_pos;
}
target_at_put(fixup_pos, pos, false);
......@@ -655,7 +669,7 @@ void Assembler::bind_to(Label* L, int pos) {
}
CHECK((trampoline_pos - fixup_pos) <= kMaxJumpOffset);
DEBUG_PRINTF("\t\ttrampolining: %d\n", trampoline_pos);
target_at_put(fixup_pos, trampoline_pos, false);
target_at_put(fixup_pos, trampoline_pos, false, true);
fixup_pos = trampoline_pos;
}
target_at_put(fixup_pos, pos, false);
......@@ -733,6 +747,8 @@ int Assembler::BrachlongOffset(Instr auipc, Instr instr_I) {
DCHECK(reinterpret_cast<Instruction*>(&instr_I)->InstructionType() ==
InstructionBase::kIType);
DCHECK(IsAuipc(auipc));
DCHECK_EQ((auipc & kRdFieldMask) >> kRdShift,
(instr_I & kRs1FieldMask) >> kRs1Shift);
int32_t imm_auipc = AuipcOffset(auipc);
int32_t imm12 = (instr_I & kImm12Mask) >> 20;
int32_t offset = imm12 + imm_auipc;
......
......@@ -883,6 +883,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
// Check if an instruction is a branch of some kind.
static bool IsBranch(Instr instr);
static bool IsCBranch(Instr instr);
static bool IsNop(Instr instr);
static bool IsJump(Instr instr);
static bool IsJal(Instr instr);
static bool IsCJal(Instr instr);
......@@ -958,7 +959,8 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
int target_at(int pos, bool is_internal);
// Patch branch instruction at pos to branch to given branch target pos.
void target_at_put(int pos, int target_pos, bool is_internal);
void target_at_put(int pos, int target_pos, bool is_internal,
bool trampoline = false);
// Say if we need to relocate with this mode.
bool MustUseReg(RelocInfo::Mode rmode);
......
......@@ -261,6 +261,7 @@ const int kFcsrFrmMask = ((1 << kFcsrFrmBits) - 1) << kFcsrFrmShift;
const int kFcsrBits = kFcsrFlagsBits + kFcsrFrmBits;
const int kFcsrMask = kFcsrFlagsMask | kFcsrFrmMask;
const int kNopByte = 0x00000013;
// Original MIPS constants
// TODO(RISCV): to be cleaned up
const int kImm16Shift = 0;
......
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