Skip to content

Commit f738f72

Browse files
minor changes
1 parent ab1bbc3 commit f738f72

File tree

1 file changed

+119
-18
lines changed

1 file changed

+119
-18
lines changed

src/passes/DeadStoreElimination.cpp

Lines changed: 119 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,25 @@ std::atomic<int> gcUnderstoodUsedStores(0);
8080
std::atomic<int> gcHaltedWithNoLoads(0);
8181
std::atomic<int> gcHaltedWithLoads(0);
8282

83+
enum class HaltReason {
84+
NoHalt,
85+
Call,
86+
Throw,
87+
Trap,
88+
BranchOut,
89+
Interaction,
90+
Exit,
91+
Unknown
92+
};
93+
94+
std::atomic<int> gcHaltCall(0);
95+
std::atomic<int> gcHaltThrow(0);
96+
std::atomic<int> gcHaltTrap(0);
97+
std::atomic<int> gcHaltBranchOut(0);
98+
std::atomic<int> gcHaltInteraction(0);
99+
std::atomic<int> gcHaltExit(0);
100+
std::atomic<int> gcHaltUnknown(0);
101+
83102
// A variation of LocalGraph that can also compare expressions to check for
84103
// their equivalence. Basic LocalGraph just looks at locals, while this class
85104
// goes further and looks at the structure of the expression, taking into
@@ -146,15 +165,27 @@ struct Logic {
146165
//
147166
// The default behavior here considers all calls to be barriers. Subclasses
148167
// can use whole-program information to do better.
149-
bool isBarrier(Expression* curr, const ShallowEffectAnalyzer& currEffects) {
168+
HaltReason isBarrier(Expression* curr,
169+
const ShallowEffectAnalyzer& currEffects) {
150170
// TODO: ignore throws of an exception that is definitely caught in this
151171
// function
152172
// TODO: if we add an "ignore after trap mode" (to assume nothing happens
153173
// after a trap) then we could stop assuming any trap can lead to
154174
// access of global data, likely greatly reducing the number of
155175
// barriers.
156-
return currEffects.calls || currEffects.throws() || currEffects.trap ||
157-
currEffects.branchesOut;
176+
if (currEffects.calls)
177+
return HaltReason::Call;
178+
if (currEffects.throws())
179+
return HaltReason::Throw;
180+
if (currEffects.trap && !currEffects.trapsNeverHappen)
181+
return HaltReason::Trap;
182+
if (currEffects.branchesOut)
183+
return HaltReason::BranchOut;
184+
185+
return HaltReason::NoHalt;
186+
// return currEffects.calls || currEffects.throws() || (currEffects.trap &&
187+
// !currEffects.trapsNeverHappen) ||
188+
// currEffects.branchesOut;
158189
};
159190

160191
// Returns whether an expression may interact with loads and stores in
@@ -431,6 +462,10 @@ struct GCLogic : public ComparingLogic {
431462
return mayAlias(load, store);
432463
}
433464

465+
std::cerr << "mayInteractWith\n";
466+
curr->dump();
467+
return false;
468+
434469
// This is not a load or a store that we recognize; check for generic heap
435470
// interactions.
436471
return currEffects.readsMutableStruct || currEffects.writesStruct;
@@ -474,6 +509,14 @@ struct DeadStoreCFG
474509
int localHaltedWithNoLoads = 0;
475510
int localHaltedWithLoads = 0;
476511

512+
int localHaltCall = 0;
513+
int localHaltThrow = 0;
514+
int localHaltTrap = 0;
515+
int localHaltBranchOut = 0;
516+
int localHaltInteraction = 0;
517+
int localHaltExit = 0;
518+
int localHaltUnknown = 0;
519+
477520
DeadStoreCFG(Module& wasm, Function* func, PassOptions& passOptions)
478521
: func(func), passOptions(passOptions), logic(func, passOptions, wasm) {
479522
this->setModule(&wasm);
@@ -491,13 +534,8 @@ struct DeadStoreCFG
491534
// Add all relevant things to the list of exprs for the current basic block.
492535
if (isStore(curr) || isLoad(curr)) {
493536
exprs.push_back(curr);
494-
} else if (logic.isBarrier(curr, currEffects)) {
495-
// Barriers can be very common, so as a minor optimization avoid having
496-
// consecutive ones; a single barrier will stop us.
497-
if (exprs.empty() || exprs.back() != barrier) {
498-
exprs.push_back(barrier);
499-
}
500-
} else if (logic.mayInteract(curr, currEffects)) {
537+
} else if (logic.isBarrier(curr, currEffects) != HaltReason::NoHalt ||
538+
logic.mayInteract(curr, currEffects)) {
501539
exprs.push_back(curr);
502540
}
503541
}
@@ -558,11 +596,37 @@ struct DeadStoreCFG
558596

559597
// When we find something we cannot optimize, stop flowing and mark the
560598
// store as unoptimizable.
561-
auto halt = [&]() {
599+
auto halt = [&](HaltReason reason) {
562600
work.clear();
563601
understoodStores.erase(store);
564602
if (definiteLoads == 0) {
565603
localHaltedWithNoLoads++;
604+
switch (reason) {
605+
case HaltReason::NoHalt:
606+
assert(false && "impossible");
607+
break;
608+
case HaltReason::Call:
609+
localHaltCall++;
610+
break;
611+
case HaltReason::Throw:
612+
localHaltThrow++;
613+
break;
614+
case HaltReason::Trap:
615+
localHaltTrap++;
616+
break;
617+
case HaltReason::BranchOut:
618+
localHaltBranchOut++;
619+
break;
620+
case HaltReason::Interaction:
621+
localHaltInteraction++;
622+
break;
623+
case HaltReason::Exit:
624+
localHaltExit++;
625+
break;
626+
case HaltReason::Unknown:
627+
localHaltUnknown++;
628+
break;
629+
}
566630
} else {
567631
localHaltedWithLoads++;
568632
}
@@ -574,14 +638,21 @@ struct DeadStoreCFG
574638
for (size_t i = from; i < block->contents.exprs.size(); i++) {
575639
auto* curr = block->contents.exprs[i];
576640

577-
if (curr == barrier) {
578-
halt();
579-
return;
580-
}
581-
582641
ShallowEffectAnalyzer currEffects(
583642
passOptions, *this->getModule(), curr);
584643

644+
if (auto reason = logic.isBarrier(curr, currEffects);
645+
reason != HaltReason::NoHalt) {
646+
halt(reason);
647+
return;
648+
// if (currEffects.calls) halt(HaltReason::Call);
649+
// else if (currEffects.throws()) halt(HaltReason::Throw);
650+
// else if (currEffects.trap && !currEffects.trapsNeverHappen)
651+
// halt(HaltReason::Trap); else if (currEffects.branchesOut)
652+
// halt(HaltReason::BranchOut); else halt(HaltReason::Unknown);
653+
// return;
654+
}
655+
585656
if (logic.isLoadFrom(curr, currEffects, store)) {
586657
// We found a definite load of this store, note it.
587658
definiteLoads++;
@@ -592,7 +663,7 @@ struct DeadStoreCFG
592663
return;
593664
} else if (logic.mayInteractWith(curr, currEffects, store)) {
594665
// Stop: we cannot fully analyze the uses of this store.
595-
halt();
666+
halt(HaltReason::Interaction);
596667
return;
597668
}
598669
}
@@ -605,7 +676,7 @@ struct DeadStoreCFG
605676
if (block == this->exit) {
606677
// Any value flowing out can be reached by global code outside the
607678
// function after we leave.
608-
halt();
679+
halt(HaltReason::Exit);
609680
}
610681
};
611682

@@ -665,6 +736,14 @@ struct DeadStoreCFG
665736
gcUnderstoodUsedStores += localUnderstoodUsedStores;
666737
gcHaltedWithNoLoads += localHaltedWithNoLoads;
667738
gcHaltedWithLoads += localHaltedWithLoads;
739+
740+
gcHaltCall += localHaltCall;
741+
gcHaltThrow += localHaltThrow;
742+
gcHaltTrap += localHaltTrap;
743+
gcHaltBranchOut += localHaltBranchOut;
744+
gcHaltInteraction += localHaltInteraction;
745+
gcHaltExit += localHaltExit;
746+
gcHaltUnknown += localHaltUnknown;
668747
}
669748

670749
if (replacer.replacements.empty()) {
@@ -718,6 +797,14 @@ struct LocalDeadStoreEliminationRunner : public Pass {
718797
gcHaltedWithNoLoads = 0;
719798
gcHaltedWithLoads = 0;
720799

800+
gcHaltCall = 0;
801+
gcHaltThrow = 0;
802+
gcHaltTrap = 0;
803+
gcHaltBranchOut = 0;
804+
gcHaltInteraction = 0;
805+
gcHaltExit = 0;
806+
gcHaltUnknown = 0;
807+
721808
// Run the actual DSE in parallel. We use a nested PassRunner to take
722809
// advantage of its built-in function parallelism logic.
723810
PassRunner passRunner(module, getPassOptions());
@@ -733,6 +820,20 @@ struct LocalDeadStoreEliminationRunner : public Pass {
733820
<< "\n";
734821
std::cerr << " Halted w/ NO loads (Likely Dead): "
735822
<< gcHaltedWithNoLoads.load() << "\n";
823+
if (gcHaltedWithNoLoads > 0) {
824+
std::cerr << " Reason: Call: " << gcHaltCall.load() << "\n";
825+
std::cerr << " Reason: Throw: " << gcHaltThrow.load() << "\n";
826+
std::cerr << " Reason: Trap: " << gcHaltTrap.load() << "\n";
827+
std::cerr << " Reason: BranchOut: " << gcHaltBranchOut.load()
828+
<< "\n";
829+
std::cerr << " Reason: Interaction: " << gcHaltInteraction.load()
830+
<< "\n";
831+
std::cerr << " Reason: Exit: " << gcHaltExit.load() << "\n";
832+
if (gcHaltUnknown > 0) {
833+
std::cerr << " Reason: Unknown: " << gcHaltUnknown.load()
834+
<< "\n";
835+
}
836+
}
736837
std::cerr << " Halted w/ loads (Partially Used): "
737838
<< gcHaltedWithLoads.load() << "\n";
738839
std::cerr << "=========================\n\n";

0 commit comments

Comments
 (0)