[vm, compiler] Use bit-manipulation extensions when targeting Android or Fuchsia RISC-V.
Use Zbb instructions when available for ClampedUint8List stores. Use Zba instructions when available for IntConverter zero extensions. Fix LslImmediate(kUnsignedFourBytes) when Zba is enabled. TEST=locally switch to RV64GCB Change-Id: If9fc0ac3fd2c5248785322f949e2003024e5152a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/385640 Reviewed-by: Alexander Aprelev <aam@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
committed by
Commit Queue
parent
36da75d075
commit
e25601e129
@@ -2406,9 +2406,7 @@ void MicroAssembler::EmitJType(intptr_t imm, Register rd, Opcode opcode) {
|
||||
|
||||
Assembler::Assembler(ObjectPoolBuilder* object_pool_builder,
|
||||
intptr_t far_branch_level)
|
||||
: MicroAssembler(object_pool_builder,
|
||||
far_branch_level,
|
||||
FLAG_use_compressed_instructions ? RV_GC : RV_G),
|
||||
: MicroAssembler(object_pool_builder, far_branch_level, RV_baseline),
|
||||
constant_pool_allowed_(false) {
|
||||
generate_invoke_write_barrier_wrapper_ = [&](Register reg) {
|
||||
// Note this does not destroy RA.
|
||||
@@ -2572,7 +2570,7 @@ void Assembler::ExtendValue(Register rd, Register rn, OperandSize sz) {
|
||||
return mv(rd, rn);
|
||||
case kUnsignedFourBytes:
|
||||
if (Supports(RV_Zba)) {
|
||||
return adduw(rd, rn, ZR);
|
||||
return zextw(rd, rn);
|
||||
}
|
||||
slli(rd, rn, XLEN - 32);
|
||||
return srli(rd, rn, XLEN - 32);
|
||||
@@ -3311,13 +3309,12 @@ void Assembler::LslImmediate(Register rd,
|
||||
return slliw(rd, rn, shift);
|
||||
}
|
||||
if (sz == kUnsignedFourBytes) {
|
||||
if (Supports(RV_Zba)) {
|
||||
return slliuw(rd, rn, shift);
|
||||
} else {
|
||||
// Clear upper bits in addition to the shift.
|
||||
slli(rd, rn, shift + (XLEN / 2));
|
||||
return srli(rd, rn, XLEN / 2);
|
||||
}
|
||||
// Not slliuw even when available. That zero extends the input, not the
|
||||
// output.
|
||||
|
||||
// Clear upper bits in addition to the shift.
|
||||
slli(rd, rn, shift + (XLEN / 2));
|
||||
return srli(rd, rn, XLEN / 2);
|
||||
}
|
||||
#endif
|
||||
slli(rd, rn, shift);
|
||||
|
||||
@@ -69,6 +69,7 @@ class MicroAssembler : public AssemblerBase {
|
||||
#if defined(TESTING)
|
||||
void SetExtensions(ExtensionSet extensions) { extensions_ = extensions; }
|
||||
#endif
|
||||
ExtensionSet extensions() const { return extensions_; }
|
||||
bool Supports(Extension extension) const {
|
||||
return extensions_.Includes(extension);
|
||||
}
|
||||
@@ -562,6 +563,8 @@ class MicroAssembler : public AssemblerBase {
|
||||
void sh3adduw(Register rd, Register rs1, Register rs2);
|
||||
void slliuw(Register rd, Register rs1, intx_t imm);
|
||||
|
||||
void zextw(Register rd, Register rs) { adduw(rd, rs, ZR); }
|
||||
|
||||
// ==== Zbb: Basic bit-manipulation ====
|
||||
void andn(Register rd, Register rs1, Register rs2);
|
||||
void orn(Register rd, Register rs1, Register rs2);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -196,6 +196,12 @@ class Disassembler : public AllStatic {
|
||||
|
||||
static void DisassembleStub(const char* name, const Code& code);
|
||||
|
||||
#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
|
||||
static void SetExtensions(ExtensionSet extensions) {
|
||||
extensions_ = extensions;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
static void DisassembleCodeHelper(const char* function_fullname,
|
||||
const char* function_info,
|
||||
@@ -204,6 +210,10 @@ class Disassembler : public AllStatic {
|
||||
|
||||
static constexpr int kHexadecimalBufferSize = 32;
|
||||
static constexpr int kUserReadableBufferSize = 256;
|
||||
|
||||
#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
|
||||
static ExtensionSet extensions_;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace dart
|
||||
|
||||
@@ -993,7 +993,11 @@ void RISCVDisassembler::DisassembleOP32_ADDUW(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
#if XLEN >= 64
|
||||
case F3_0:
|
||||
Print("add.uw 'rd, 'rs1, 'rs2", instr, RV_Zba);
|
||||
if (instr.rs2() == ZR) {
|
||||
Print("zext.w 'rd, 'rs1", instr, RV_Zba);
|
||||
} else {
|
||||
Print("add.uw 'rd, 'rs1, 'rs2", instr, RV_Zba);
|
||||
}
|
||||
break;
|
||||
case ZEXT:
|
||||
Print("zext.h 'rd, 'rs1", instr, RV_Zbb);
|
||||
@@ -1592,8 +1596,6 @@ void RISCVDisassembler::UnknownInstruction(CInstr instr) {
|
||||
void RISCVDisassembler::Print(const char* format,
|
||||
Instr instr,
|
||||
ExtensionSet ex) {
|
||||
// Printf(" %08x ", instr.encoding());
|
||||
|
||||
while (format[0] != '\0') {
|
||||
if (format[0] == '\'') {
|
||||
format = PrintOption(format + 1, instr);
|
||||
@@ -1603,14 +1605,14 @@ void RISCVDisassembler::Print(const char* format,
|
||||
}
|
||||
}
|
||||
|
||||
// Printf("\n");
|
||||
if (!Supports(ex)) {
|
||||
Printf(" ;; from unsupported extension");
|
||||
}
|
||||
}
|
||||
|
||||
void RISCVDisassembler::Print(const char* format,
|
||||
CInstr instr,
|
||||
ExtensionSet ex) {
|
||||
// Printf(" %04x ", instr.encoding());
|
||||
|
||||
while (format[0] != '\0') {
|
||||
if (format[0] == '\'') {
|
||||
format = PrintOption(format + 1, instr);
|
||||
@@ -1620,7 +1622,9 @@ void RISCVDisassembler::Print(const char* format,
|
||||
}
|
||||
}
|
||||
|
||||
// Printf("\n");
|
||||
if (!Supports(ex)) {
|
||||
Printf(" ;; from unsupported extension");
|
||||
}
|
||||
}
|
||||
|
||||
#define STRING_STARTS_WITH(string, compare_string) \
|
||||
@@ -1816,6 +1820,8 @@ const char* RISCVDisassembler::PrintOption(const char* format, CInstr instr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ExtensionSet Disassembler::extensions_ = RV_baseline;
|
||||
|
||||
void Disassembler::DecodeInstruction(char* hex_buffer,
|
||||
intptr_t hex_size,
|
||||
char* human_buffer,
|
||||
@@ -1824,8 +1830,7 @@ void Disassembler::DecodeInstruction(char* hex_buffer,
|
||||
const Code& code,
|
||||
Object** object,
|
||||
uword pc) {
|
||||
RISCVDisassembler decoder(human_buffer, human_size,
|
||||
FLAG_use_compressed_instructions ? RV_GC : RV_G);
|
||||
RISCVDisassembler decoder(human_buffer, human_size, extensions_);
|
||||
int instr_size = decoder.Disassemble(pc);
|
||||
if (instr_size == 2) {
|
||||
Utils::SNPrint(hex_buffer, hex_size, " %04x",
|
||||
|
||||
@@ -2392,23 +2392,29 @@ void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
} else {
|
||||
const Register value = locs()->in(2).reg();
|
||||
if (__ Supports(RV_Zbb)) {
|
||||
__ li(TMP, 255);
|
||||
__ min(TMP, TMP, value);
|
||||
__ max(TMP, TMP, ZR);
|
||||
__ sb(TMP, element_address);
|
||||
} else {
|
||||
compiler::Label store_zero, store_ff, done;
|
||||
__ blt(value, ZR, &store_zero, compiler::Assembler::kNearJump);
|
||||
|
||||
compiler::Label store_zero, store_ff, done;
|
||||
__ blt(value, ZR, &store_zero, compiler::Assembler::kNearJump);
|
||||
__ li(TMP, 0xFF);
|
||||
__ bgt(value, TMP, &store_ff, compiler::Assembler::kNearJump);
|
||||
|
||||
__ li(TMP, 0xFF);
|
||||
__ bgt(value, TMP, &store_ff, compiler::Assembler::kNearJump);
|
||||
__ sb(value, element_address);
|
||||
__ j(&done, compiler::Assembler::kNearJump);
|
||||
|
||||
__ sb(value, element_address);
|
||||
__ j(&done, compiler::Assembler::kNearJump);
|
||||
__ Bind(&store_zero);
|
||||
__ mv(TMP, ZR);
|
||||
|
||||
__ Bind(&store_zero);
|
||||
__ mv(TMP, ZR);
|
||||
__ Bind(&store_ff);
|
||||
__ sb(TMP, element_address);
|
||||
|
||||
__ Bind(&store_ff);
|
||||
__ sb(TMP, element_address);
|
||||
|
||||
__ Bind(&done);
|
||||
__ Bind(&done);
|
||||
}
|
||||
}
|
||||
} else if (RepresentationUtils::IsUnboxedInteger(rep)) {
|
||||
if (rep == kUnboxedUint8 || rep == kUnboxedInt8) {
|
||||
@@ -6993,15 +6999,12 @@ void IntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
} else if (from() == kUnboxedInt64) {
|
||||
if (to() == kUnboxedInt32) {
|
||||
if (is_truncating() || out != value) {
|
||||
__ sextw(out, value); // Signed extension 64->32.
|
||||
__ ExtendValue(out, value, compiler::kFourBytes);
|
||||
}
|
||||
} else {
|
||||
ASSERT(to() == kUnboxedUint32);
|
||||
if (is_truncating() || out != value) {
|
||||
// Unsigned extension 64->32.
|
||||
// TODO(riscv): Might be a shorter way to do this.
|
||||
__ slli(out, value, 32);
|
||||
__ srli(out, out, 32);
|
||||
__ ExtendValue(out, value, compiler::kUnsignedFourBytes);
|
||||
}
|
||||
}
|
||||
if (CanDeoptimize()) {
|
||||
@@ -7011,12 +7014,10 @@ void IntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
} else if (to() == kUnboxedInt64) {
|
||||
if (from() == kUnboxedUint32) {
|
||||
// TODO(riscv): Might be a shorter way to do this.
|
||||
__ slli(out, value, 32);
|
||||
__ srli(out, out, 32);
|
||||
__ ExtendValue(out, value, compiler::kUnsignedFourBytes);
|
||||
} else {
|
||||
ASSERT(from() == kUnboxedInt32);
|
||||
__ sextw(out, value); // Signed extension 32->64.
|
||||
__ ExtendValue(out, value, compiler::kFourBytes);
|
||||
}
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
|
||||
@@ -10,13 +10,6 @@
|
||||
|
||||
namespace dart {
|
||||
|
||||
#if !defined(FFI_UNIT_TESTS)
|
||||
DEFINE_FLAG(bool,
|
||||
use_compressed_instructions,
|
||||
true,
|
||||
"Use instructions from the C extension");
|
||||
#endif
|
||||
|
||||
const char* const cpu_reg_names[kNumberOfCpuRegisters] = {
|
||||
"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "fp", "thr", "a0",
|
||||
"a1", "a2", "tmp", "tmp2", "pp", "a6", "a7", "s2", "s3", "s4", "s5",
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
|
||||
namespace dart {
|
||||
|
||||
DECLARE_FLAG(bool, use_compressed_instructions);
|
||||
|
||||
#if defined(TARGET_ARCH_RISCV32)
|
||||
typedef uint32_t uintx_t;
|
||||
typedef int32_t intx_t;
|
||||
@@ -1603,6 +1601,12 @@ static constexpr ExtensionSet RV_GCB = RV_GC | RV_B;
|
||||
static constexpr Extension RV_Zbc(9); // Carry-less multiplication
|
||||
static constexpr Extension RV_Zalasr(10); // Load-acquire, store-release
|
||||
|
||||
#if defined(DART_TARGET_OS_FUCHSIA) || defined(DART_TARGET_OS_ANDROID)
|
||||
static constexpr ExtensionSet RV_baseline = RV_GCB;
|
||||
#else
|
||||
static constexpr ExtensionSet RV_baseline = RV_GC;
|
||||
#endif
|
||||
|
||||
#undef R
|
||||
|
||||
inline Register ConcreteRegister(Register r) {
|
||||
|
||||
@@ -726,13 +726,16 @@ void AssemblerTest::Assemble() {
|
||||
// Disassemble relative since code addresses are not stable from run to run.
|
||||
SetFlagScope<bool> sfs(&FLAG_disassemble_relative, true);
|
||||
uword start = code_.PayloadStart();
|
||||
uword end = start + assembler_->CodeSize();
|
||||
#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
|
||||
Disassembler::SetExtensions(assembler_->extensions());
|
||||
#endif
|
||||
if (FLAG_disassemble) {
|
||||
OS::PrintErr("Code for test '%s' {\n", name_);
|
||||
Disassembler::Disassemble(start, start + assembler_->CodeSize());
|
||||
Disassembler::Disassemble(start, end);
|
||||
OS::PrintErr("}\n");
|
||||
}
|
||||
Disassembler::Disassemble(start, start + assembler_->CodeSize(), disassembly_,
|
||||
DISASSEMBLY_SIZE);
|
||||
Disassembler::Disassemble(start, end, disassembly_, DISASSEMBLY_SIZE);
|
||||
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
|
||||
// Blank out absolute addressing constants on ia32, since they are not stable
|
||||
// from run to run.
|
||||
|
||||
Reference in New Issue
Block a user