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