|
22 | 22 | #include <ir/branch-hints.h> |
23 | 23 | #include <ir/drop.h> |
24 | 24 | #include <ir/effects.h> |
| 25 | +#include <ir/find_all.h> |
25 | 26 | #include <ir/intrinsics.h> |
26 | 27 | #include <ir/iteration.h> |
27 | 28 | #include <ir/literal-utils.h> |
@@ -473,10 +474,40 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> { |
473 | 474 | } else { |
474 | 475 | ExpressionManipulator::nop(curr->body); |
475 | 476 | } |
476 | | - if (curr->getResults() == Type::none && |
477 | | - !EffectAnalyzer(getPassOptions(), *getModule(), curr) |
478 | | - .hasUnremovableSideEffects()) { |
479 | | - ExpressionManipulator::nop(curr->body); |
| 477 | + if (curr->getResults() == Type::none) { |
| 478 | + EffectAnalyzer effects(getPassOptions(), *getModule(), curr); |
| 479 | + if (!effects.hasUnremovableSideEffects()) { |
| 480 | + // We can remove these contents. However, there is one situation we want |
| 481 | + // to handle here: in trapsNeverHappen mode, we can remove traps, but |
| 482 | + // we don't want to remove an actual Unreachable - replacing an |
| 483 | + // Unreachable with a Nop is valid, but does not propagate to callers in |
| 484 | + // other passes. |
| 485 | + // |
| 486 | + // To avoid that situation, after finding we can remove the code, we |
| 487 | + // also require that no Unreachable exists. Note that this is unoptimal: |
| 488 | + // there may be a complex bundle of code whose only effect is to |
| 489 | + // potentially trap, and it happens to contain an Unreachable inside |
| 490 | + // somewhere, then that would prevent us from nopping the entire thing. |
| 491 | + // But we leave untangling such code for other passes. |
| 492 | + // |
| 493 | + // This is also unoptimal as it is a heuristic: some toolchain might |
| 494 | + // emit 0 / 0 for a logical trap, rather than an Unreachable. We would |
| 495 | + // remove that 0 / 0 if we saw it, and the trap would not propagate. |
| 496 | + // (But other passes would handle it, if they saw it first.) |
| 497 | + if (effects.trap) { |
| 498 | + // The code is removable, so the trap is the only effect it has, and |
| 499 | + // we are considering removing it because TNH is enabled. |
| 500 | + assert(getPassOptions().trapsNeverHappen); |
| 501 | + if (!FindAll<Unreachable>(curr->body).list.empty()) { |
| 502 | + return; |
| 503 | + } |
| 504 | + } |
| 505 | + // Either trapsNeverHappen and there is no Unreachable (so we are only |
| 506 | + // removing implicit traps, which is fine), or traps may happen in terms |
| 507 | + // of the flag, but not in this actual code. Either way, we can remove |
| 508 | + // all of this. |
| 509 | + ExpressionManipulator::nop(curr->body); |
| 510 | + } |
480 | 511 | } |
481 | 512 | } |
482 | 513 | }; |
|
0 commit comments