Skip to content

Commit fda68a8

Browse files
committed
[JSC] Air FixObviousSpills state should track aliased regs
https://bugs.webkit.org/show_bug.cgi?id=324695 rdar://187965961 Reviewed by Dan Hecht. State::clobber(Reg) is very frequently called as it is called once per def of regs in Air::Inst. 1. For regConst case, one reg can only have one const. So instead of having Vector of Reg and Const pair, we have std::array for const value with Reg-index. And we have ScalarRegisterSet for set constReg. 2. To quickly know whether we have RegSlot for a particular Reg, we maintain ScalarRegisterSet regSlotRegs bitset. * Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp: Canonical link: https://commits.webkit.org/321519@main
1 parent 9e7af10 commit fda68a8

1 file changed

Lines changed: 64 additions & 81 deletions

File tree

‎Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp‎

Lines changed: 64 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "AirInstInlines.h"
3535
#include "AirPhaseScope.h"
3636
#include "Options.h"
37+
#include "RegisterSet.h"
3738
#include <wtf/GraphOrdering.h>
3839
#include <wtf/IndexMap.h>
3940
#include <wtf/ListDump.h>
@@ -217,6 +218,8 @@ class FixObviousSpills {
217218
}
218219
return;
219220
}
221+
if (m_state.hasNoRegAlias())
222+
return;
220223
arg.forEachTmp(role, bank, width,
221224
[&](Tmp& tmp, Arg::Role refinedRole, Bank, Width) {
222225
if (isWhichDef(refinedRole) && tmp.isReg()) {
@@ -318,21 +321,21 @@ class FixObviousSpills {
318321
// since it's more deterministic.
319322
uint64_t myValue = inst.args()[0].value();
320323
Reg myDest = inst.args()[1].reg();
321-
for (const RegConst& regConst : m_state.regConst) {
322-
uint64_t otherValue = regConst.constant;
323-
324+
for (Reg reg : m_state.constRegs) {
325+
uint64_t otherValue = m_state.constants[reg.index()];
326+
324327
// Let's try add. That's the only thing that works on all platforms, since it's
325328
// the only cheap arithmetic op that x86 does in three operands. Long term, we
326329
// should add fancier materializations here for ARM if the BigImm is yuge.
327330
uint64_t delta = myValue - otherValue;
328-
331+
329332
if (Arg::isValidImmForm(delta)) {
330333
if (delta) {
331334
inst.kind = Add64;
332-
inst.setArgs(Arg::imm(delta), Tmp(regConst.reg), Tmp(myDest));
335+
inst.setArgs(Arg::imm(delta), Tmp(reg), Tmp(myDest));
333336
} else {
334337
inst.kind = Move;
335-
inst.setArgs(Tmp(regConst.reg), Tmp(myDest));
338+
inst.setArgs(Tmp(reg), Tmp(myDest));
336339
}
337340
return;
338341
}
@@ -438,35 +441,14 @@ class FixObviousSpills {
438441
{
439442
return arg.isStack() && arg.stackSlot()->isSpill();
440443
}
441-
444+
442445
struct RegConst {
443-
RegConst()
444-
{
445-
}
446-
447446
RegConst(Reg reg, int64_t constant)
448447
: reg(reg)
449448
, constant(constant)
450449
{
451450
}
452451

453-
explicit operator bool() const
454-
{
455-
return !!reg;
456-
}
457-
458-
friend bool NODELETE operator==(const RegConst&, const RegConst&) = default;
459-
460-
bool NODELETE operator<(const RegConst& other) const
461-
{
462-
return reg < other.reg || (reg == other.reg && constant < other.constant);
463-
}
464-
465-
void dump(PrintStream& out) const
466-
{
467-
out.print(reg, "->", constant);
468-
}
469-
470452
Reg reg;
471453
int64_t constant { 0 };
472454
};
@@ -556,20 +538,21 @@ class FixObviousSpills {
556538
};
557539

558540
struct State {
559-
bool NODELETE isEmpty() const { return regConst.isEmpty() && slotConst.isEmpty() && regSlot.isEmpty(); }
541+
bool NODELETE isEmpty() const { return constRegs.isEmpty() && slotConst.isEmpty() && regSlot.isEmpty(); }
560542

561543
bool NODELETE hasNoSlotAlias() const { return slotConst.isEmpty() && regSlot.isEmpty(); }
562544

545+
bool NODELETE hasNoRegAlias() const { return constRegs.isEmpty() && regSlot.isEmpty(); }
546+
563547
void addAlias(const RegConst& newAlias)
564548
{
565-
regConst.append(newAlias);
566-
#if ASSERT_ENABLED
567-
m_isSorted = false;
568-
#endif
549+
constRegs.add(newAlias.reg);
550+
constants[newAlias.reg.index()] = newAlias.constant;
569551
}
570552
void addAlias(const RegSlot& newAlias)
571553
{
572554
regSlot.append(newAlias);
555+
regSlotRegs.add(newAlias.reg);
573556
#if ASSERT_ENABLED
574557
m_isSorted = false;
575558
#endif
@@ -581,36 +564,27 @@ class FixObviousSpills {
581564
m_isSorted = false;
582565
#endif
583566
}
584-
585-
bool contains(const RegConst& alias)
567+
568+
bool contains(const RegConst& alias) const
586569
{
587-
return regConst.contains(alias);
570+
return constantForReg(alias.reg) == alias.constant;
588571
}
589572
bool contains(const RegSlot& alias)
590573
{
574+
if (!regSlotRegs.contains(alias.reg))
575+
return false;
591576
return regSlot.contains(alias);
592577
}
593578
bool contains(const SlotConst& alias)
594579
{
595580
return slotConst.contains(alias);
596581
}
597582

598-
const RegConst* NODELETE getRegConst(Reg reg) const
599-
{
600-
for (const RegConst& alias : regConst) {
601-
if (alias.reg == reg)
602-
return &alias;
603-
}
604-
return nullptr;
605-
}
606-
607-
const RegSlot* NODELETE getRegSlot(Reg reg) const
583+
std::optional<int64_t> NODELETE constantForReg(Reg reg) const
608584
{
609-
for (const RegSlot& alias : regSlot) {
610-
if (alias.reg == reg)
611-
return &alias;
612-
}
613-
return nullptr;
585+
if (!constRegs.contains(reg))
586+
return std::nullopt;
587+
return constants[reg.index()];
614588
}
615589

616590
const RegSlot* NODELETE getRegSlot(StackSlot* slot) const
@@ -622,15 +596,6 @@ class FixObviousSpills {
622596
return nullptr;
623597
}
624598

625-
const RegSlot* NODELETE getRegSlot(Reg reg, StackSlot* slot) const
626-
{
627-
for (const RegSlot& alias : regSlot) {
628-
if (alias.reg == reg && alias.slot == slot)
629-
return &alias;
630-
}
631-
return nullptr;
632-
}
633-
634599
const SlotConst* NODELETE getSlotConst(StackSlot* slot) const
635600
{
636601
for (const SlotConst& alias : slotConst) {
@@ -642,11 +607,8 @@ class FixObviousSpills {
642607

643608
std::optional<int64_t> NODELETE constantFor(const Arg& arg)
644609
{
645-
if (arg.isReg()) {
646-
if (const RegConst* alias = getRegConst(arg.reg()))
647-
return alias->constant;
648-
return std::nullopt;
649-
}
610+
if (arg.isReg())
611+
return constantForReg(arg.reg());
650612
if (arg.isStack()) {
651613
if (const SlotConst* alias = getSlotConst(arg.stackSlot()))
652614
return alias->constant;
@@ -655,16 +617,17 @@ class FixObviousSpills {
655617
return std::nullopt;
656618
}
657619

658-
void clobber(const Reg& reg)
620+
void clobber(Reg reg)
659621
{
660-
regConst.removeAllMatching(
661-
[&] (const RegConst& alias) -> bool {
662-
return alias.reg == reg;
663-
});
664-
regSlot.removeAllMatching(
622+
constRegs.remove(reg);
623+
if (!regSlotRegs.contains(reg))
624+
return;
625+
unsigned matchCount = regSlot.removeAllMatching(
665626
[&] (const RegSlot& alias) -> bool {
666627
return alias.reg == reg;
667628
});
629+
ASSERT_UNUSED(matchCount, matchCount);
630+
regSlotRegs.remove(reg);
668631
}
669632

670633
void clobber(StackSlot* slot)
@@ -673,17 +636,12 @@ class FixObviousSpills {
673636
[&] (const SlotConst& alias) -> bool {
674637
return alias.slot == slot;
675638
});
676-
regSlot.removeAllMatching(
677-
[&] (const RegSlot& alias) -> bool {
678-
return alias.slot == slot;
679-
});
639+
if (regSlot.removeAllMatching([&] (const RegSlot& alias) -> bool { return alias.slot == slot; }))
640+
rebuildRegSlotRegs();
680641
}
681642

682643
void sort()
683644
{
684-
std::ranges::sort(regConst, [](const auto& a, const auto& b) {
685-
return a < b;
686-
});
687645
std::ranges::sort(slotConst, [](const auto& a, const auto& b) {
688646
return a < b;
689647
});
@@ -721,7 +679,16 @@ class FixObviousSpills {
721679
ASSERT(other.m_isSorted);
722680
bool changed = false;
723681

724-
changed |= filterVectorAgainst(regConst, other.regConst, [](RegConst& a, const RegConst& b) { return a == b; });
682+
ScalarRegisterSet survivingConstRegs;
683+
for (Reg reg : constRegs) {
684+
if (other.constantForReg(reg) == constants[reg.index()])
685+
survivingConstRegs.add(reg);
686+
}
687+
if (survivingConstRegs != constRegs) {
688+
constRegs = survivingConstRegs;
689+
changed = true;
690+
}
691+
725692
changed |= filterVectorAgainst(slotConst, other.slotConst, [](SlotConst& a, const SlotConst& b) { return a == b; });
726693
changed |= filterVectorAgainst(regSlot, other.regSlot, [&](RegSlot& alias, const RegSlot& otherAlias) {
727694
if (alias.reg != otherAlias.reg || alias.slot != otherAlias.slot)
@@ -733,19 +700,35 @@ class FixObviousSpills {
733700
return true;
734701
});
735702

703+
if (changed)
704+
rebuildRegSlotRegs();
705+
736706
return changed;
737707
}
738708

709+
void rebuildRegSlotRegs()
710+
{
711+
regSlotRegs = { };
712+
for (const RegSlot& alias : regSlot)
713+
regSlotRegs.add(alias.reg);
714+
}
715+
739716
void dump(PrintStream& out) const
740717
{
718+
out.print("{regConst = [");
719+
CommaPrinter comma;
720+
for (Reg reg : constRegs)
721+
out.print(comma, reg, "->", constants[reg.index()]);
741722
out.print(
742-
"{regConst = [", listDump(regConst), "], slotConst = [", listDump(slotConst),
723+
"], slotConst = [", listDump(slotConst),
743724
"], regSlot = [", listDump(regSlot), "]}");
744725
}
745726

746-
Vector<RegConst> regConst;
727+
ScalarRegisterSet constRegs;
728+
std::array<int64_t, Reg::maxIndex() + 1> constants { };
747729
Vector<SlotConst> slotConst;
748730
Vector<RegSlot> regSlot;
731+
ScalarRegisterSet regSlotRegs;
749732
#if ASSERT_ENABLED
750733
bool m_isSorted { true };
751734
#endif

0 commit comments

Comments
 (0)