astgen: add isAlwaysVoid and endsWithNoReturn checks to rvalue

Port two missing checks from upstream AstGen.zig rvalueInner to the C
rvalue function:

1. isAlwaysVoid (Zir.zig:1343-1608): When the result refers to an
   instruction that always produces void (e.g., dbg_stmt, store_node,
   export, memcpy, etc.), replace the result with void_value before
   proceeding. This prevents emitting unnecessary type coercions or
   stores on always-void instructions.

2. endsWithNoReturn (AstGen.zig:11068): When the current GenZir block
   ends with a noreturn instruction, return the result immediately
   without emitting any rvalue instructions. This avoids emitting dead
   ZIR instructions after noreturn.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 22:11:01 +00:00
parent 0b12e027a3
commit 811672be4b

View File

@@ -1906,9 +1906,72 @@ static uint32_t rlResultType(GenZir* gz, ResultLoc rl, uint32_t node) {
}
}
static bool endsWithNoReturn(GenZir* gz);
// Mirrors Zir.Inst.Tag.isAlwaysVoid (Zir.zig:1343-1608).
static bool isAlwaysVoid(ZirInstTag tag, ZirInstData data) {
switch (tag) {
case ZIR_INST_DBG_STMT:
case ZIR_INST_DBG_VAR_PTR:
case ZIR_INST_DBG_VAR_VAL:
case ZIR_INST_ENSURE_RESULT_USED:
case ZIR_INST_ENSURE_RESULT_NON_ERROR:
case ZIR_INST_ENSURE_ERR_UNION_PAYLOAD_VOID:
case ZIR_INST_SET_EVAL_BRANCH_QUOTA:
case ZIR_INST_ATOMIC_STORE:
case ZIR_INST_STORE_NODE:
case ZIR_INST_STORE_TO_INFERRED_PTR:
case ZIR_INST_VALIDATE_DEREF:
case ZIR_INST_VALIDATE_DESTRUCTURE:
case ZIR_INST_EXPORT:
case ZIR_INST_SET_RUNTIME_SAFETY:
case ZIR_INST_MEMCPY:
case ZIR_INST_MEMSET:
case ZIR_INST_MEMMOVE:
case ZIR_INST_CHECK_COMPTIME_CONTROL_FLOW:
case ZIR_INST_DEFER:
case ZIR_INST_DEFER_ERR_CODE:
case ZIR_INST_SAVE_ERR_RET_INDEX:
case ZIR_INST_RESTORE_ERR_RET_INDEX_UNCONDITIONAL:
case ZIR_INST_RESTORE_ERR_RET_INDEX_FN_ENTRY:
case ZIR_INST_VALIDATE_STRUCT_INIT_TY:
case ZIR_INST_VALIDATE_STRUCT_INIT_RESULT_TY:
case ZIR_INST_VALIDATE_PTR_STRUCT_INIT:
case ZIR_INST_VALIDATE_ARRAY_INIT_TY:
case ZIR_INST_VALIDATE_ARRAY_INIT_RESULT_TY:
case ZIR_INST_VALIDATE_PTR_ARRAY_INIT:
case ZIR_INST_VALIDATE_REF_TY:
case ZIR_INST_VALIDATE_CONST:
return true;
case ZIR_INST_EXTENDED:
switch (data.extended.opcode) {
case ZIR_EXT_BRANCH_HINT:
case ZIR_EXT_BREAKPOINT:
case ZIR_EXT_DISABLE_INSTRUMENTATION:
case ZIR_EXT_DISABLE_INTRINSICS:
return true;
default:
return false;
}
default:
return false;
}
}
// rvalue (AstGen.zig:11051-11224): apply result location wrapping.
static uint32_t rvalue(
GenZir* gz, ResultLoc rl, uint32_t result, uint32_t node) {
// isAlwaysVoid check (AstGen.zig:11058-11067).
if (result >= ZIR_REF_START_INDEX) {
uint32_t result_index = result - ZIR_REF_START_INDEX;
if (isAlwaysVoid(gz->astgen->inst_tags[result_index],
gz->astgen->inst_datas[result_index])) {
result = ZIR_REF_VOID_VALUE;
}
}
// endsWithNoReturn check (AstGen.zig:11068).
if (endsWithNoReturn(gz))
return result;
switch (rl.tag) {
case RL_NONE:
case RL_COERCED_TY: