| ... | ... | @@ -1231,46 +1231,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 1231 | 1231 | const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; |
| 1232 | 1232 | const liveness_condbr = self.liveness.getCondBr(inst); |
| 1233 | 1233 | |
| 1234 | | // Here we either emit a BPcc for branching on CCR content, |
| 1235 | | // or emit a BPr to branch on register content. |
| 1236 | | const reloc: Mir.Inst.Index = switch (condition) { |
| 1237 | | .condition_flags => |flags| try self.addInst(.{ |
| 1238 | | .tag = .bpcc, |
| 1239 | | .data = .{ |
| 1240 | | .branch_predict_int = .{ |
| 1241 | | .ccr = flags.ccr, |
| 1242 | | // Here we map to the opposite condition because the jump is to the false branch. |
| 1243 | | .cond = flags.cond.icond.negate(), |
| 1244 | | .inst = undefined, // Will be filled by performReloc |
| 1245 | | }, |
| 1246 | | }, |
| 1247 | | }), |
| 1248 | | else => blk: { |
| 1249 | | const reg = switch (condition) { |
| 1250 | | .register => |r| r, |
| 1251 | | else => try self.copyToTmpRegister(Type.bool, condition), |
| 1252 | | }; |
| 1253 | | |
| 1254 | | break :blk try self.addInst(.{ |
| 1255 | | .tag = .bpr, |
| 1256 | | .data = .{ |
| 1257 | | .branch_predict_reg = .{ |
| 1258 | | .cond = .eq_zero, |
| 1259 | | .rs1 = reg, |
| 1260 | | .inst = undefined, // populated later through performReloc |
| 1261 | | }, |
| 1262 | | }, |
| 1263 | | }); |
| 1264 | | }, |
| 1265 | | }; |
| 1266 | | |
| 1267 | | // Regardless of the branch type that's emitted, we need to reserve |
| 1268 | | // a space for the delay slot. |
| 1269 | | // TODO Find a way to fill this delay slot |
| 1270 | | _ = try self.addInst(.{ |
| 1271 | | .tag = .nop, |
| 1272 | | .data = .{ .nop = {} }, |
| 1273 | | }); |
| 1234 | // Here we emit a branch to the false section. |
| 1235 | const reloc: Mir.Inst.Index = try self.condBr(condition); |
| 1274 | 1236 | |
| 1275 | 1237 | // If the condition dies here in this condbr instruction, process |
| 1276 | 1238 | // that death now instead of later as this has an effect on |
| ... | ... | @@ -2424,6 +2386,51 @@ fn brVoid(self: *Self, block: Air.Inst.Index) !void { |
| 2424 | 2386 | block_data.relocs.appendAssumeCapacity(br_index); |
| 2425 | 2387 | } |
| 2426 | 2388 | |
| 2389 | fn condBr(self: *Self, condition: MCValue) !Mir.Inst.Index { |
| 2390 | // Here we either emit a BPcc for branching on CCR content, |
| 2391 | // or emit a BPr to branch on register content. |
| 2392 | const reloc: Mir.Inst.Index = switch (condition) { |
| 2393 | .condition_flags => |flags| try self.addInst(.{ |
| 2394 | .tag = .bpcc, |
| 2395 | .data = .{ |
| 2396 | .branch_predict_int = .{ |
| 2397 | .ccr = flags.ccr, |
| 2398 | // Here we map to the opposite condition because the jump is to the false branch. |
| 2399 | .cond = flags.cond.icond.negate(), |
| 2400 | .inst = undefined, // Will be filled by performReloc |
| 2401 | }, |
| 2402 | }, |
| 2403 | }), |
| 2404 | else => blk: { |
| 2405 | const reg = switch (condition) { |
| 2406 | .register => |r| r, |
| 2407 | else => try self.copyToTmpRegister(Type.bool, condition), |
| 2408 | }; |
| 2409 | |
| 2410 | break :blk try self.addInst(.{ |
| 2411 | .tag = .bpr, |
| 2412 | .data = .{ |
| 2413 | .branch_predict_reg = .{ |
| 2414 | .cond = .eq_zero, |
| 2415 | .rs1 = reg, |
| 2416 | .inst = undefined, // populated later through performReloc |
| 2417 | }, |
| 2418 | }, |
| 2419 | }); |
| 2420 | }, |
| 2421 | }; |
| 2422 | |
| 2423 | // Regardless of the branch type that's emitted, we need to reserve |
| 2424 | // a space for the delay slot. |
| 2425 | // TODO Find a way to fill this delay slot |
| 2426 | _ = try self.addInst(.{ |
| 2427 | .tag = .nop, |
| 2428 | .data = .{ .nop = {} }, |
| 2429 | }); |
| 2430 | |
| 2431 | return reloc; |
| 2432 | } |
| 2433 | |
| 2427 | 2434 | /// Copies a value to a register without tracking the register. The register is not considered |
| 2428 | 2435 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 2429 | 2436 | /// This can have a side effect of spilling instructions to the stack to free up a register. |