Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit 9b67391

Browse files
CSharperMantlejandem
authored andcommitted
Bug 1975752 - [riscv64] Refactor riscv64 FloatRegister representation to allow correct lowering. r=jandem,anba
Differential Revision: https://phabricator.services.mozilla.com/D256119
1 parent f8da7ca commit 9b67391

File tree

8 files changed

+96
-83
lines changed

8 files changed

+96
-83
lines changed

js/src/jit/JitFrames.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2539,12 +2539,7 @@ uintptr_t MachineState::read(Register reg) const {
25392539

25402540
template <typename T>
25412541
T MachineState::read(FloatRegister reg) const {
2542-
#if !defined(JS_CODEGEN_RISCV64)
25432542
MOZ_ASSERT(reg.size() == sizeof(T));
2544-
#else
2545-
// RISCV64 always store FloatRegister as 64bit.
2546-
MOZ_ASSERT(reg.size() == sizeof(double));
2547-
#endif
25482543

25492544
#if !defined(JS_CODEGEN_NONE) && !defined(JS_CODEGEN_WASM32)
25502545
if (state_.is<BailoutState>()) {

js/src/jit/LIR.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -609,18 +609,12 @@ class LDefinition {
609609
Type type() const { return (Type)((bits_ >> TYPE_SHIFT) & TYPE_MASK); }
610610

611611
static bool isFloatRegCompatible(Type type, FloatRegister reg) {
612-
#ifdef JS_CODEGEN_RISCV64
613-
if (type == FLOAT32 || type == DOUBLE) {
614-
return reg.isSingle() || reg.isDouble();
615-
}
616-
#else
617612
if (type == FLOAT32) {
618613
return reg.isSingle();
619614
}
620615
if (type == DOUBLE) {
621616
return reg.isDouble();
622617
}
623-
#endif
624618
MOZ_ASSERT(type == SIMD128);
625619
return reg.isSimd128();
626620
}

js/src/jit/riscv64/Architecture-riscv64.h

Lines changed: 64 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -270,16 +270,18 @@ class FloatRegisters {
270270
ft11 = f31
271271
};
272272

273-
enum Kind : uint8_t { Double, NumTypes, Single };
273+
enum Kind : uint8_t { Double, Single, NumTypes };
274+
275+
// (invalid << 7) | (kind << 5) | encoding
276+
using Code = uint8_t;
277+
using Encoding = FPRegisterID;
274278

275-
typedef FPRegisterID Code;
276-
typedef FPRegisterID Encoding;
277279
union RegisterContent {
278280
float s;
279281
double d;
280282
};
281283

282-
static const char* GetName(uint32_t code) {
284+
static const char* GetName(Code code) {
283285
static const char* const Names[] = {
284286
"ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
285287
"fs0", "fs2", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
@@ -289,37 +291,51 @@ class FloatRegisters {
289291
if (code >= Total) {
290292
return "invalid";
291293
}
292-
return Names[code];
294+
return Names[code & 0x1f];
293295
}
294296

295297
static Code FromName(const char* name);
296298

297-
typedef uint32_t SetType;
299+
using SetType = uint64_t;
298300

299-
static const Code Invalid = invalid_reg;
300-
static const uint32_t Total = 32;
301+
static const Code Invalid = Code(0b10000000);
301302
static const uint32_t TotalPhys = 32;
303+
static const uint32_t Total = TotalPhys * NumTypes;
302304
static const uint32_t Allocatable = 23;
303-
static const SetType AllPhysMask = 0xFFFFFFFF;
304-
static const SetType AllMask = 0xFFFFFFFF;
305-
static const SetType AllDoubleMask = AllMask;
306-
// Single values are stored as 64 bits values (NaN-boxed) when pushing them to
307-
// the stack, we do not require making distinctions between the 2 types, and
308-
// therefore the masks are overlapping.See The RISC-V Instruction Set Manual
309-
// for 14.2 NaN Boxing of Narrower Values.
310-
static const SetType AllSingleMask = AllMask;
305+
306+
static_assert(sizeof(SetType) * 8 >= Total,
307+
"SetType should be large enough to enumerate all registers.");
308+
309+
// Magic values which are used to duplicate a mask of physical register for
310+
// a specific type of register. A multiplication is used to copy and shift
311+
// the bits of the physical register mask.
312+
static const SetType SpreadSingle = SetType(1)
313+
<< (uint32_t(Kind::Single) * TotalPhys);
314+
static const SetType SpreadDouble = SetType(1)
315+
<< (uint32_t(Kind::Double) * TotalPhys);
316+
static const SetType Spread = SpreadSingle | SpreadDouble;
317+
318+
static const SetType AllPhysMask = ((SetType(1) << TotalPhys) - 1);
319+
static const SetType AllMask = AllPhysMask * Spread;
320+
static const SetType AllSingleMask = AllPhysMask * SpreadSingle;
321+
static const SetType AllDoubleMask = AllPhysMask * SpreadDouble;
322+
static const SetType NoneMask = SetType(0);
323+
311324
static const SetType NonVolatileMask =
312325
SetType((1 << FloatRegisters::fs0) | (1 << FloatRegisters::fs1) |
313326
(1 << FloatRegisters::fs2) | (1 << FloatRegisters::fs3) |
314327
(1 << FloatRegisters::fs4) | (1 << FloatRegisters::fs5) |
315328
(1 << FloatRegisters::fs6) | (1 << FloatRegisters::fs7) |
316329
(1 << FloatRegisters::fs8) | (1 << FloatRegisters::fs9) |
317-
(1 << FloatRegisters::fs10) | (1 << FloatRegisters::fs11));
330+
(1 << FloatRegisters::fs10) | (1 << FloatRegisters::fs11)) *
331+
Spread;
318332
static const SetType VolatileMask = AllMask & ~NonVolatileMask;
319333

320334
// fs11/ft10 is the scratch register.
321335
static const SetType NonAllocatableMask =
322-
SetType((1 << FloatRegisters::fs11) | (1 << FloatRegisters::ft10));
336+
((SetType(1) << FloatRegisters::fs11) |
337+
(SetType(1) << FloatRegisters::ft10)) *
338+
Spread;
323339

324340
static const SetType AllocatableMask = AllMask & ~NonAllocatableMask;
325341
};
@@ -329,29 +345,32 @@ class TypedRegisterSet;
329345

330346
struct FloatRegister {
331347
public:
332-
typedef FloatRegisters Codes;
333-
typedef Codes::Code Code;
334-
typedef Codes::Encoding Encoding;
335-
typedef Codes::SetType SetType;
348+
using Codes = FloatRegisters;
349+
using Code = Codes::Code;
350+
using Encoding = Codes::Encoding;
351+
using SetType = Codes::SetType;
336352

337353
static uint32_t SetSize(SetType x) {
338-
static_assert(sizeof(SetType) == 4, "SetType must be 32 bits");
354+
static_assert(sizeof(SetType) == 8, "SetType must be 64 bits");
355+
x |= x >> FloatRegisters::TotalPhys;
339356
x &= FloatRegisters::AllPhysMask;
340357
return mozilla::CountPopulation32(x);
341358
}
342359

343360
static uint32_t FirstBit(SetType x) {
344-
static_assert(sizeof(SetType) == 4, "SetType");
361+
static_assert(sizeof(SetType) == 8, "SetType must be 64 bits");
345362
return mozilla::CountTrailingZeroes64(x);
346363
}
347364
static uint32_t LastBit(SetType x) {
348-
static_assert(sizeof(SetType) == 4, "SetType");
349-
return 31 - mozilla::CountLeadingZeroes64(x);
365+
static_assert(sizeof(SetType) == 8, "SetType must be 64 bits");
366+
return 63 - mozilla::CountLeadingZeroes64(x);
350367
}
351368

352-
static FloatRegister FromCode(uint32_t i) {
353-
uint32_t code = i & 0x1f;
354-
return FloatRegister(Code(code));
369+
static FloatRegister FromCode(Code code) {
370+
MOZ_ASSERT(code < Codes::Total);
371+
const Encoding encoding = Encoding(code & 0x1f);
372+
const Kind kind = Kind((code >> 5) & 0x3);
373+
return FloatRegister(encoding, kind);
355374
}
356375
bool isSimd128() const { return false; }
357376
bool isInvalid() const { return invalid_; }
@@ -366,10 +385,11 @@ struct FloatRegister {
366385
FloatRegister asSimd128() const { MOZ_CRASH(); }
367386
constexpr Code code() const {
368387
MOZ_ASSERT(!invalid_);
369-
return encoding_;
388+
return Code((invalid_ << 7) | ((static_cast<uint8_t>(kind_) & 0x3) << 5) |
389+
(static_cast<uint8_t>(encoding_) & 0x1f));
370390
}
371-
Encoding encoding() const { return encoding_; }
372-
const char* name() const { return FloatRegisters::GetName(code()); }
391+
constexpr Encoding encoding() const { return encoding_; }
392+
const char* name() const { return FloatRegisters::GetName(encoding()); }
373393
bool volatile_() const {
374394
MOZ_ASSERT(!invalid_);
375395
return !!((SetType(1) << code()) & FloatRegisters::VolatileMask);
@@ -379,10 +399,12 @@ struct FloatRegister {
379399
bool aliases(FloatRegister other) const {
380400
return other.encoding_ == encoding_;
381401
}
382-
uint32_t numAliased() const { return 1; }
402+
uint32_t numAliased() const { return FloatRegisters::NumTypes; }
383403
FloatRegister aliased(uint32_t aliasIdx) const {
384-
MOZ_ASSERT(aliasIdx == 0);
385-
return *this;
404+
MOZ_ASSERT(!invalid_);
405+
MOZ_ASSERT(aliasIdx < numAliased());
406+
return FloatRegister(Encoding(encoding_),
407+
Kind((aliasIdx + kind_) % numAliased()));
386408
}
387409
// Ensure that two floating point registers' types are equivalent.
388410
bool equiv(FloatRegister other) const {
@@ -402,7 +424,9 @@ struct FloatRegister {
402424
MOZ_ASSERT(aliasIdx < numAliased());
403425
return aliased(aliasIdx);
404426
}
405-
SetType alignedOrDominatedAliasedSet() const { return SetType(1) << code(); }
427+
SetType alignedOrDominatedAliasedSet() const {
428+
return Codes::Spread << encoding_;
429+
}
406430
static constexpr RegTypeName DefaultType = RegTypeName::Float64;
407431

408432
template <RegTypeName Name = DefaultType>
@@ -427,7 +451,7 @@ struct FloatRegister {
427451
# error "Needs more careful logic if SIMD is enabled"
428452
#endif
429453

430-
return code() * sizeof(double);
454+
return encoding() * sizeof(double);
431455
}
432456
static Code FromName(const char* name);
433457

@@ -436,7 +460,7 @@ struct FloatRegister {
436460
static uint32_t GetPushSizeInBytes(const TypedRegisterSet<FloatRegister>& s);
437461

438462
private:
439-
typedef Codes::Kind Kind;
463+
using Kind = Codes::Kind;
440464
// These fields only hold valid values: an invalid register is always
441465
// represented as a valid encoding and kind with the invalid_ bit set.
442466
Encoding encoding_; // 32 encodings
@@ -461,16 +485,13 @@ struct FloatRegister {
461485

462486
bool isSingle() const {
463487
MOZ_ASSERT(!invalid_);
464-
// On riscv64 arch, float register and double register using the same
465-
// register file.
466-
return kind_ == FloatRegisters::Single || kind_ == FloatRegisters::Double;
488+
return kind_ == FloatRegisters::Single;
467489
}
490+
468491
bool isDouble() const {
469492
MOZ_ASSERT(!invalid_);
470493
return kind_ == FloatRegisters::Double;
471494
}
472-
473-
Encoding code() { return encoding_; }
474495
};
475496

476497
template <>

js/src/jit/riscv64/Assembler-riscv64.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ class UseScratchRegisterScope {
586586
class Operand {
587587
public:
588588
enum Tag { REG, FREG, MEM, IMM };
589-
Operand(FloatRegister freg) : tag(FREG), rm_(freg.code()) {}
589+
Operand(FloatRegister freg) : tag(FREG), rm_(freg.encoding()) {}
590590

591591
explicit Operand(Register base, Imm32 off)
592592
: tag(MEM), rm_(base.code()), offset_(off.value) {}
@@ -653,7 +653,7 @@ static inline bool GetIntArgReg(uint32_t usedIntArgs, Register* out) {
653653

654654
static inline bool GetFloatArgReg(uint32_t usedFloatArgs, FloatRegister* out) {
655655
if (usedFloatArgs < NumFloatArgRegs) {
656-
*out = FloatRegister::FromCode(fa0.code() + usedFloatArgs);
656+
*out = FloatRegister::FromCode(fa0.encoding() + usedFloatArgs);
657657
return true;
658658
}
659659
return false;

js/src/jit/riscv64/Register-riscv64.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,17 @@ static constexpr Register ReturnReg{Registers::a0};
8989
static constexpr Register ScratchRegister{Registers::s11};
9090
static constexpr Register64 ReturnReg64(ReturnReg);
9191

92-
static constexpr FloatRegister ReturnFloat32Reg{FloatRegisters::fa0};
92+
static constexpr FloatRegister ReturnFloat32Reg{FloatRegisters::fa0,
93+
FloatRegisters::Single};
9394
static constexpr FloatRegister ReturnDoubleReg{FloatRegisters::fa0};
9495
#ifdef ENABLE_WASM_SIMD
9596
static constexpr FloatRegister ReturnSimd128Reg{FloatRegisters::invalid_reg};
9697
static constexpr FloatRegister ScratchSimd128Reg{FloatRegisters::invalid_reg};
9798
#endif
9899
static constexpr FloatRegister InvalidFloatReg{};
99100

100-
static constexpr FloatRegister ScratchFloat32Reg{FloatRegisters::ft10};
101+
static constexpr FloatRegister ScratchFloat32Reg{FloatRegisters::ft10,
102+
FloatRegisters::Single};
101103
static constexpr FloatRegister ScratchDoubleReg{FloatRegisters::ft10};
102104
static constexpr FloatRegister ScratchDoubleReg2{FloatRegisters::fs11};
103105

0 commit comments

Comments
 (0)