@@ -63,11 +63,6 @@ pub fn RegisterManager(
63
63
return @alignCast (@fieldParentPtr ("register_manager" , self ));
64
64
}
65
65
66
- fn excludeRegister (reg : Register , register_class : RegisterBitSet ) bool {
67
- const index = indexOfRegIntoTracked (reg ) orelse return true ;
68
- return ! register_class .isSet (index );
69
- }
70
-
71
66
fn markRegIndexAllocated (self : * Self , tracked_index : TrackedIndex ) void {
72
67
self .allocated_registers .set (tracked_index );
73
68
}
@@ -239,28 +234,20 @@ pub fn RegisterManager(
239
234
) ? [count ]Register {
240
235
comptime assert (count > 0 and count <= tracked_registers .len );
241
236
242
- var free_and_not_locked_registers = self .free_registers ;
243
- free_and_not_locked_registers .setIntersection (register_class );
244
-
245
- var unlocked_registers = self .locked_registers ;
246
- unlocked_registers .toggleAll ();
247
-
248
- free_and_not_locked_registers .setIntersection (unlocked_registers );
249
-
250
- if (free_and_not_locked_registers .count () < count ) return null ;
237
+ var free_and_unlocked_registers = self .locked_registers ;
238
+ free_and_unlocked_registers .toggleAll ();
239
+ free_and_unlocked_registers .setIntersection (self .free_registers );
240
+ free_and_unlocked_registers .setIntersection (register_class );
251
241
252
242
var regs : [count ]Register = undefined ;
253
243
var i : usize = 0 ;
254
- for (tracked_registers ) | reg | {
255
- if (i >= count ) break ;
256
- if (excludeRegister (reg , register_class )) continue ;
257
- if (self .isRegLocked (reg )) continue ;
258
- if (! self .isRegFree (reg )) continue ;
259
-
260
- regs [i ] = reg ;
244
+ var it = free_and_unlocked_registers .iterator (.{});
245
+ while (it .next ()) | reg_index | {
246
+ regs [i ] = regAtTrackedIndex (@intCast (reg_index ));
261
247
i += 1 ;
248
+ if (i >= count ) break ;
262
249
}
263
- assert (i == count );
250
+ if (i < count ) return null ;
264
251
265
252
for (regs , insts ) | reg , inst | {
266
253
log .debug ("tryAllocReg {} for inst {?}" , .{ reg , inst });
@@ -295,46 +282,27 @@ pub fn RegisterManager(
295
282
) AllocateRegistersError ! [count ]Register {
296
283
comptime assert (count > 0 and count <= tracked_registers .len );
297
284
298
- var locked_registers = self .locked_registers ;
299
- locked_registers .setIntersection (register_class );
300
-
301
- if (count > register_class .count () - locked_registers .count ()) return error .OutOfRegisters ;
302
-
303
285
const result = self .tryAllocRegs (count , insts , register_class ) orelse blk : {
286
+ var unlocked_registers = self .locked_registers ;
287
+ unlocked_registers .toggleAll ();
288
+ unlocked_registers .setIntersection (register_class );
289
+
304
290
// We'll take over the first count registers. Spill
305
291
// the instructions that were previously there to a
306
292
// stack allocations.
307
293
var regs : [count ]Register = undefined ;
308
294
var i : usize = 0 ;
309
- for (tracked_registers ) | reg | {
310
- if (i >= count ) break ;
311
- if (excludeRegister (reg , register_class )) break ;
312
- if (self .isRegLocked (reg )) continue ;
313
-
314
- log .debug ("allocReg {} for inst {?}" , .{ reg , insts [i ] });
315
- regs [i ] = reg ;
316
- self .markRegAllocated (reg );
317
- const index = indexOfRegIntoTracked (reg ).? ; // indexOfReg() on a callee-preserved reg should never return null
318
- if (insts [i ]) | inst | {
319
- // Track the register
320
- if (self .isRegFree (reg )) {
321
- self .markRegUsed (reg );
322
- } else {
323
- const spilled_inst = self .registers [index ];
324
- try self .getFunction ().spillInstruction (reg , spilled_inst );
325
- }
326
- self .registers [index ] = inst ;
327
- } else {
328
- // Don't track the register
329
- if (! self .isRegFree (reg )) {
330
- const spilled_inst = self .registers [index ];
331
- try self .getFunction ().spillInstruction (reg , spilled_inst );
332
- self .freeReg (reg );
333
- }
334
- }
335
-
295
+ var it = unlocked_registers .iterator (.{});
296
+ while (it .next ()) | reg_index | {
297
+ const tracked_index : TrackedIndex = @intCast (reg_index );
298
+ if (! self .isRegIndexFree (tracked_index ) and
299
+ self .registers [tracked_index ].unwrap () == .target ) continue ;
300
+ try self .getRegIndex (tracked_index , insts [i ]);
301
+ regs [i ] = regAtTrackedIndex (tracked_index );
336
302
i += 1 ;
303
+ if (i >= count ) break ;
337
304
}
305
+ if (i < count ) return error .OutOfRegisters ;
338
306
339
307
break :blk regs ;
340
308
};
@@ -356,7 +324,7 @@ pub fn RegisterManager(
356
324
/// Spills the register if it is currently allocated. If a
357
325
/// corresponding instruction is passed, will also track this
358
326
/// register.
359
- fn getRegIndex (
327
+ pub fn getRegIndex (
360
328
self : * Self ,
361
329
tracked_index : TrackedIndex ,
362
330
inst : ? Air.Inst.Index ,
0 commit comments