|
20 | 20 | #include "llvm/CodeGen/MachineFunctionPass.h" |
21 | 21 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
22 | 22 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
| 23 | +#include <iterator> |
23 | 24 | using namespace llvm; |
24 | 25 |
|
25 | 26 | #define DEBUG_TYPE "wasm-peephole" |
@@ -109,6 +110,53 @@ static bool maybeRewriteToFallthrough(MachineInstr &MI, MachineBasicBlock &MBB, |
109 | 110 | return true; |
110 | 111 | } |
111 | 112 |
|
| 113 | +static bool eraseDeadCodeAroundUnreachable(MachineInstr &UnreachbleMI, |
| 114 | + MachineBasicBlock &MBB) { |
| 115 | + SmallVector<MachineInstr *, 16> ToDelete; |
| 116 | + |
| 117 | + // Because wasm unreachable is stack polymorphic and unconditionally ends |
| 118 | + // control, all instructions after it can be removed until the end of this |
| 119 | + // block. We remove the common case of double unreachable. |
| 120 | + auto ForwardsIterator = UnreachbleMI.getIterator(); |
| 121 | + for (ForwardsIterator++; !ForwardsIterator.isEnd(); ForwardsIterator++) { |
| 122 | + MachineInstr &MI = *ForwardsIterator; |
| 123 | + if (MI.getOpcode() == WebAssembly::UNREACHABLE) { |
| 124 | + ToDelete.push_back(&MI); |
| 125 | + } else { |
| 126 | + break; |
| 127 | + } |
| 128 | + } |
| 129 | + |
| 130 | + // For the same reasons as above, previous instructions that only affect |
| 131 | + // local function state can be removed (e.g. local.set, drop, various reads). |
| 132 | + // We remove the common case of "drop unreachable". |
| 133 | + auto BackwardsIterator = UnreachbleMI.getReverseIterator(); |
| 134 | + for (BackwardsIterator++; !BackwardsIterator.isEnd(); BackwardsIterator++) { |
| 135 | + MachineInstr &MI = *BackwardsIterator; |
| 136 | + switch (MI.getOpcode()) { |
| 137 | + case WebAssembly::DROP_I32: |
| 138 | + case WebAssembly::DROP_I64: |
| 139 | + case WebAssembly::DROP_F32: |
| 140 | + case WebAssembly::DROP_F64: |
| 141 | + case WebAssembly::DROP_EXTERNREF: |
| 142 | + case WebAssembly::DROP_FUNCREF: |
| 143 | + case WebAssembly::DROP_V128: |
| 144 | + ToDelete.push_back(&MI); |
| 145 | + continue; |
| 146 | + default: |
| 147 | + goto exit_loop; |
| 148 | + } |
| 149 | + } |
| 150 | +exit_loop:; |
| 151 | + |
| 152 | + bool Changed = false; |
| 153 | + for (MachineInstr *MI : ToDelete) { |
| 154 | + MI->eraseFromParent(); |
| 155 | + Changed = true; |
| 156 | + } |
| 157 | + return Changed; |
| 158 | +} |
| 159 | + |
112 | 160 | bool WebAssemblyPeephole::runOnMachineFunction(MachineFunction &MF) { |
113 | 161 | LLVM_DEBUG({ |
114 | 162 | dbgs() << "********** Peephole **********\n" |
@@ -159,6 +207,9 @@ bool WebAssemblyPeephole::runOnMachineFunction(MachineFunction &MF) { |
159 | 207 | case WebAssembly::RETURN: |
160 | 208 | Changed |= maybeRewriteToFallthrough(MI, MBB, MF, MFI, MRI, TII); |
161 | 209 | break; |
| 210 | + case WebAssembly::UNREACHABLE: |
| 211 | + Changed |= eraseDeadCodeAroundUnreachable(MI, MBB); |
| 212 | + break; |
162 | 213 | } |
163 | 214 |
|
164 | 215 | return Changed; |
|
0 commit comments