From 0e9676ea1ff0e02a76c2cbb7ff05bee0f5588a0d Mon Sep 17 00:00:00 2001 From: Ryan Macnak Date: Mon, 5 Jan 2026 16:31:30 -0800 Subject: [PATCH] [vm, compiler] Some shorter load immediate sequences for RISC-V. TEST=ci Change-Id: I34e72727b5560da88916f996f92b33ddc1ff6dff Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/468980 Reviewed-by: Alexander Markov Commit-Queue: Ryan Macnak --- .../vm/compiler/assembler/assembler_riscv.cc | 37 +++++++++++ .../assembler/assembler_riscv_test.cc | 64 +++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/runtime/vm/compiler/assembler/assembler_riscv.cc b/runtime/vm/compiler/assembler/assembler_riscv.cc index 1d9eccf78d3..e41aa68991d 100644 --- a/runtime/vm/compiler/assembler/assembler_riscv.cc +++ b/runtime/vm/compiler/assembler/assembler_riscv.cc @@ -4592,6 +4592,11 @@ void Assembler::LoadIsolateGroup(Register dst) { void Assembler::LoadImmediate(Register reg, intx_t imm) { #if XLEN > 32 if (!Utils::IsInt(32, imm)) { + if (Supports(RV_Zbs) && Utils::IsPowerOfTwo(imm)) { + bseti(reg, ZR, Utils::ShiftForPowerOfTwo(imm)); + return; + } + int shift = Utils::CountTrailingZeros64(imm); if (IsITypeImm(imm >> shift)) { li(reg, imm >> shift); @@ -4651,6 +4656,22 @@ void Assembler::LoadSImmediate(FRegister reg, float imms) { return; } } + uint32_t nimm = imm ^ 0x80000000; + for (intptr_t i = 0; i < 32; i++) { + if (kFlisConstants[i] == nimm) { + flis(reg, i); + fnegs(reg, reg); + return; + } + } + } + + int32_t immi = imms; + if (IsITypeImm(immi) && + imm == bit_cast(static_cast(immi))) { + li(TMP2, immi); + fcvtsw(reg, TMP2); // static_cast int32_t -> float + return; } ASSERT(constant_pool_allowed()); @@ -4676,6 +4697,22 @@ void Assembler::LoadDImmediate(FRegister reg, double immd) { return; } } + uint64_t nimm = imm ^ 0x8000000000000000; + for (intptr_t i = 0; i < 32; i++) { + if (kFlidConstants[i] == nimm) { + flid(reg, i); + fnegd(reg, reg); + return; + } + } + } + + int32_t immi = immd; + if (IsITypeImm(immi) && + imm == bit_cast(static_cast(immi))) { + li(TMP2, immi); + fcvtdw(reg, TMP2); // static_cast int32_t -> double + return; } ASSERT(constant_pool_allowed()); diff --git a/runtime/vm/compiler/assembler/assembler_riscv_test.cc b/runtime/vm/compiler/assembler/assembler_riscv_test.cc index 797d2822da1..1723d257ba7 100644 --- a/runtime/vm/compiler/assembler/assembler_riscv_test.cc +++ b/runtime/vm/compiler/assembler/assembler_riscv_test.cc @@ -9324,6 +9324,18 @@ ASSEMBLER_TEST_RUN(LoadImmediate_LiSlliAddi, test) { " 8082 ret\n"); EXPECT_EQ(static_cast(0xFF000000000000FF), Call(test->entry())); } + +ASSEMBLER_TEST_GENERATE(LoadImmediate_Bseti, assembler) { + __ SetExtensions(RV_GCB); + __ LoadImmediate(A0, static_cast(1) << 62); + __ ret(); +} +ASSEMBLER_TEST_RUN(LoadImmediate_Bseti, test) { + EXPECT_DISASSEMBLY( + "2be01513 bseti a0, zero, 0x3e\n" + " 8082 ret\n"); + EXPECT_EQ(static_cast(1) << 62, Call(test->entry())); +} #endif ASSEMBLER_TEST_GENERATE(BitwiseImmediates_GC, assembler) { @@ -9372,6 +9384,58 @@ ASSEMBLER_TEST_RUN(BitwiseImmediates_GCB, test) { " 8082 ret\n"); } +ASSEMBLER_TEST_GENERATE(LoadSImmediate_IntCast, assembler) { + __ SetExtensions(RV_GC); + __ LoadSImmediate(FA0, 10.0); + __ ret(); +} +ASSEMBLER_TEST_RUN(LoadSImmediate_IntCast, test) { + EXPECT_DISASSEMBLY( + " 4729 li tmp2, 10\n" + "d0070553 fcvt.s.w fa0, tmp2\n" + " 8082 ret\n"); + EXPECT_EQ(10.0f, CallF(test->entry(), 0.0f)); +} + +ASSEMBLER_TEST_GENERATE(LoadSImmediate_NegLi, assembler) { + __ SetExtensions(RV_GC | RV_Zfa); + __ LoadSImmediate(FA0, -2.0); + __ ret(); +} +ASSEMBLER_TEST_RUN(LoadSImmediate_NegLi, test) { + EXPECT_DISASSEMBLY( + "f01a0553 flis fa0, 2.000000\n" + "20a51553 fneg.s fa0, fa0\n" + " 8082 ret\n"); + EXPECT_EQ(-2.0f, CallF(test->entry(), 0.0f)); +} + +ASSEMBLER_TEST_GENERATE(LoadDImmediate_IntCast, assembler) { + __ SetExtensions(RV_GC); + __ LoadDImmediate(FA0, 10.0); + __ ret(); +} +ASSEMBLER_TEST_RUN(LoadDImmediate_IntCast, test) { + EXPECT_DISASSEMBLY( + " 4729 li tmp2, 10\n" + "d2070553 fcvt.d.w fa0, tmp2\n" + " 8082 ret\n"); + EXPECT_EQ(10.0, CallD(test->entry(), 0.0)); +} + +ASSEMBLER_TEST_GENERATE(LoadDImmediate_NegLi, assembler) { + __ SetExtensions(RV_GC | RV_Zfa); + __ LoadDImmediate(FA0, -2.0); + __ ret(); +} +ASSEMBLER_TEST_RUN(LoadDImmediate_NegLi, test) { + EXPECT_DISASSEMBLY( + "f21a0553 flid fa0, 2.000000\n" + "22a51553 fneg.d fa0, fa0\n" + " 8082 ret\n"); + EXPECT_EQ(-2.0, CallD(test->entry(), 0.0)); +} + ASSEMBLER_TEST_GENERATE(AddImmediateBranchOverflow, assembler) { __ SetExtensions(RV_GC); Label overflow;