| ... | @@ -144,6 +144,91 @@ fn analyzeInst( | ... | @@ -144,6 +144,91 @@ fn analyzeInst( |
| 144 | // instruction, and the deaths flag for the CondBr instruction will indicate whether the | 144 | // instruction, and the deaths flag for the CondBr instruction will indicate whether the |
| 145 | // condition's lifetime ends immediately before entering any branch. | 145 | // condition's lifetime ends immediately before entering any branch. |
| 146 | }, | 146 | }, |
| | 147 | .switchbr => { |
| | 148 | const inst = base.castTag(.switchbr).?; |
| | 149 | |
| | 150 | const Table = std.AutoHashMap(*ir.Inst, void); |
| | 151 | const case_tables = try table.allocator.alloc(Table, inst.cases.len + 1); // +1 for else |
| | 152 | defer table.allocator.free(case_tables); |
| | 153 | |
| | 154 | std.mem.set(Table, case_tables, Table.init(table.allocator)); |
| | 155 | defer for (case_tables) |*ct| ct.deinit(); |
| | 156 | |
| | 157 | for (inst.cases) |case, i| { |
| | 158 | try analyzeWithTable(arena, table, &case_tables[i], case.body); |
| | 159 | |
| | 160 | // Reset the table back to its state from before the case. |
| | 161 | var it = case_tables[i].iterator(); |
| | 162 | while (it.next()) |entry| { |
| | 163 | table.removeAssertDiscard(entry.key); |
| | 164 | } |
| | 165 | } |
| | 166 | { // else |
| | 167 | try analyzeWithTable(arena, table, &case_tables[case_tables.len - 1], inst.else_body); |
| | 168 | |
| | 169 | // Reset the table back to its state from before the case. |
| | 170 | var it = case_tables[case_tables.len - 1].iterator(); |
| | 171 | while (it.next()) |entry| { |
| | 172 | table.removeAssertDiscard(entry.key); |
| | 173 | } |
| | 174 | } |
| | 175 | |
| | 176 | const List = std.ArrayList(*ir.Inst); |
| | 177 | const case_deaths = try table.allocator.alloc(List, case_tables.len); // +1 for else |
| | 178 | defer table.allocator.free(case_deaths); |
| | 179 | |
| | 180 | std.mem.set(List, case_deaths, List.init(table.allocator)); |
| | 181 | defer for (case_deaths) |*cd| cd.deinit(); |
| | 182 | |
| | 183 | var total_deaths: u32 = 0; |
| | 184 | for (case_tables) |*ct, i| { |
| | 185 | total_deaths += ct.count(); |
| | 186 | var it = ct.iterator(); |
| | 187 | while (it.next()) |entry| { |
| | 188 | const case_death = entry.key; |
| | 189 | for (case_tables) |*ct_inner, j| { |
| | 190 | if (i == j) continue; |
| | 191 | if (!ct_inner.contains(case_death)) { |
| | 192 | try case_deaths[i].append(case_death); |
| | 193 | } |
| | 194 | } |
| | 195 | // undo resetting the table |
| | 196 | _ = try table.put(case_death, {}); |
| | 197 | } |
| | 198 | } |
| | 199 | |
| | 200 | // Now we have to correctly populate new_set. |
| | 201 | if (new_set) |ns| { |
| | 202 | try ns.ensureCapacity(@intCast(u32, ns.count() + total_deaths)); |
| | 203 | for (case_tables) |*ct| { |
| | 204 | var it = ct.iterator(); |
| | 205 | while (it.next()) |entry| { |
| | 206 | _ = ns.putAssumeCapacity(entry.key, {}); |
| | 207 | } |
| | 208 | } |
| | 209 | } |
| | 210 | |
| | 211 | total_deaths = 0; |
| | 212 | for (case_deaths[0 .. case_deaths.len - 1]) |*ct, i| { |
| | 213 | inst.cases[i].index = total_deaths; |
| | 214 | const len = std.math.cast(@TypeOf(inst.else_deaths), ct.items.len) catch return error.OutOfMemory; |
| | 215 | inst.cases[i].deaths = len; |
| | 216 | total_deaths += len; |
| | 217 | } |
| | 218 | { // else |
| | 219 | const else_deaths = std.math.cast(@TypeOf(inst.else_deaths), case_deaths[case_deaths.len - 1].items.len) catch return error.OutOfMemory; |
| | 220 | inst.else_index = total_deaths; |
| | 221 | inst.else_deaths = else_deaths; |
| | 222 | total_deaths += else_deaths; |
| | 223 | } |
| | 224 | |
| | 225 | const allocated_slice = try arena.alloc(*ir.Inst, total_deaths); |
| | 226 | inst.deaths = allocated_slice.ptr; |
| | 227 | for (case_deaths[0 .. case_deaths.len - 1]) |*cd, i| { |
| | 228 | std.mem.copy(*ir.Inst, inst.caseDeaths(i), cd.items); |
| | 229 | } |
| | 230 | std.mem.copy(*ir.Inst, inst.elseDeaths(), case_deaths[case_deaths.len - 1].items); |
| | 231 | }, |
| 147 | else => {}, | 232 | else => {}, |
| 148 | } | 233 | } |
| 149 | | 234 | |