| ... | @@ -1231,46 +1231,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1231,46 +1231,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 1231 | const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; | 1231 | const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; |
| 1232 | const liveness_condbr = self.liveness.getCondBr(inst); | 1232 | const liveness_condbr = self.liveness.getCondBr(inst); |
| 1233 | | 1233 | |
| 1234 | // Here we either emit a BPcc for branching on CCR content, | 1234 | // Here we emit a branch to the false section. |
| 1235 | // or emit a BPr to branch on register content. | 1235 | const reloc: Mir.Inst.Index = try self.condBr(condition); |
| 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 | }); | | |
| 1274 | | 1236 | |
| 1275 | // If the condition dies here in this condbr instruction, process | 1237 | // If the condition dies here in this condbr instruction, process |
| 1276 | // that death now instead of later as this has an effect on | 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,6 +2386,51 @@ fn brVoid(self: *Self, block: Air.Inst.Index) !void { |
| 2424 | block_data.relocs.appendAssumeCapacity(br_index); | 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 | /// Copies a value to a register without tracking the register. The register is not considered | 2434 | /// Copies a value to a register without tracking the register. The register is not considered |
| 2428 | /// allocated. A second call to `copyToTmpRegister` may return the same register. | 2435 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 2429 | /// This can have a side effect of spilling instructions to the stack to free up a register. | 2436 | /// This can have a side effect of spilling instructions to the stack to free up a register. |