mirror of
https://github.com/ziglang/zig.git
synced 2024-11-27 07:32:44 +00:00
stage2: Teach Liveness that safety checks do not modify memory
This change adds to Liveness a simple pattern match for the try-like `.condbr` blocks emitted by Sema's safety checks. This allows us to determine that these do not modify memory, which permits us to elide additional loads in the backend. As @Vexu points out in the main issue, this is probably not a complete solution on its own. We'll still want a way to reliably narrow the load/copy when performing several consecutive accesses, such as `foo.arr[x][y].z` Resolves https://github.com/ziglang/zig/issues/12215
This commit is contained in:
parent
d0eef26687
commit
25d3713b07
@ -501,6 +501,41 @@ pub fn categorizeOperand(
|
||||
return .complex;
|
||||
},
|
||||
.block => {
|
||||
const extra = air.extraData(Air.Block, air_datas[inst].ty_pl.payload);
|
||||
const body = air.extra[extra.end..][0..extra.data.body_len];
|
||||
|
||||
if (body.len == 1 and air_tags[body[0]] == .cond_br) {
|
||||
// Peephole optimization for "panic-like" conditionals, which have
|
||||
// one empty branch and another which calls a `noreturn` function.
|
||||
// This allows us to infer that safety checks do not modify memory,
|
||||
// as far as control flow successors are concerned.
|
||||
|
||||
const inst_data = air_datas[body[0]].pl_op;
|
||||
const cond_extra = air.extraData(Air.CondBr, inst_data.payload);
|
||||
if (inst_data.operand == operand_ref and operandDies(l, body[0], 0))
|
||||
return .tomb;
|
||||
|
||||
if (cond_extra.data.then_body_len != 1 or cond_extra.data.else_body_len != 1)
|
||||
return .complex;
|
||||
|
||||
var operand_live: bool = true;
|
||||
for (air.extra[cond_extra.end..][0..2]) |cond_inst| {
|
||||
if (l.categorizeOperand(air, cond_inst, operand) == .tomb)
|
||||
operand_live = false;
|
||||
|
||||
switch (air_tags[cond_inst]) {
|
||||
.br => { // Breaks immediately back to block
|
||||
const br = air_datas[cond_inst].br;
|
||||
if (br.block_inst != inst)
|
||||
return .complex;
|
||||
},
|
||||
.call => {}, // Calls a noreturn function
|
||||
else => return .complex,
|
||||
}
|
||||
}
|
||||
return if (operand_live) .none else .tomb;
|
||||
}
|
||||
|
||||
return .complex;
|
||||
},
|
||||
.@"try" => {
|
||||
|
Loading…
Reference in New Issue
Block a user