Skip to content

Commit 58a3d99

Browse files
committed
copy elision: if-err with scalar types
```zig export fn entry() void { var x: error!i32 = 1234; var y = if (x) |a| a else |e| 5678; } ``` ```llvm define void @entry() #2 !dbg !41 { Entry: %x = alloca { i16, i32 }, align 4 %y = alloca i32, align 4 %0 = bitcast { i16, i32 }* %x to i8*, !dbg !56 call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %0, i8* align 4 bitcast ({ i16, i32 }* @0 to i8*), i64 8, i1 false), !dbg !56 call void @llvm.dbg.declare(metadata { i16, i32 }* %x, metadata !45, metadata !DIExpression()), !dbg !57 %1 = getelementptr inbounds { i16, i32 }, { i16, i32 }* %x, i32 0, i32 0, !dbg !58 %2 = load i16, i16* %1, align 2, !dbg !58 %3 = icmp ne i16 %2, 0, !dbg !58 br i1 %3, label %IfErrElse, label %IfErrThen, !dbg !58 IfErrThen: ; preds = %Entry %4 = getelementptr inbounds { i16, i32 }, { i16, i32 }* %x, i32 0, i32 1, !dbg !58 call void @llvm.dbg.declare(metadata i32* %4, metadata !52, metadata !DIExpression()), !dbg !58 %5 = load i32, i32* %4, align 4, !dbg !59 store i32 %5, i32* %y, align 4, !dbg !59 br label %IfErrEnd, !dbg !58 IfErrElse: ; preds = %Entry %6 = load i16, i16* %1, align 2, !dbg !58 call void @llvm.dbg.declare(metadata i16* %1, metadata !54, metadata !DIExpression()), !dbg !58 store i32 5678, i32* %y, align 4, !dbg !61 br label %IfErrEnd, !dbg !58 IfErrEnd: ; preds = %IfErrElse, %IfErrThen call void @llvm.dbg.declare(metadata i32* %y, metadata !55, metadata !DIExpression()), !dbg !63 ret void, !dbg !64 } ```
1 parent 7d6c967 commit 58a3d99

File tree

1 file changed

+18
-35
lines changed

1 file changed

+18
-35
lines changed

src/ir.cpp

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10984,19 +10984,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1098410984
if (actual_type->id == ZigTypeIdComptimeFloat ||
1098510985
actual_type->id == ZigTypeIdComptimeInt)
1098610986
{
10987-
if ((err = ensure_complete_type(ira->codegen, wanted_type)))
10988-
return ira->codegen->invalid_instruction;
10989-
if (wanted_type->id == ZigTypeIdEnum) {
10990-
IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.enumeration.tag_int_type, value);
10991-
if (type_is_invalid(cast1->value.type))
10992-
return ira->codegen->invalid_instruction;
10993-
10994-
IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
10995-
if (type_is_invalid(cast2->value.type))
10996-
return ira->codegen->invalid_instruction;
10997-
10998-
return cast2;
10999-
} else if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
10987+
if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
1100010988
CastOp op;
1100110989
if ((actual_type->id == ZigTypeIdComptimeFloat &&
1100210990
wanted_type->id == ZigTypeIdFloat) ||
@@ -11211,7 +11199,7 @@ static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) {
1121111199
}
1121211200

1121311201
static IrInstruction *ir_implicit_cast_result(IrAnalyze *ira, IrInstruction *result_loc,
11214-
ZigType *needed_child_type)
11202+
ZigType *needed_child_type, bool allow_failure)
1121511203
{
1121611204
Error err;
1121711205
if (type_is_invalid(result_loc->value.type) || type_is_invalid(needed_child_type))
@@ -11278,14 +11266,18 @@ static IrInstruction *ir_implicit_cast_result(IrAnalyze *ira, IrInstruction *res
1127811266
needed_child_type->id == ZigTypeIdComptimeFloat)
1127911267
{
1128011268
IrInstruction *cast1 = ir_implicit_cast_result(ira, result_loc,
11281-
have_child_type->data.error_union.payload_type);
11269+
have_child_type->data.error_union.payload_type, allow_failure);
1128211270
if (type_is_invalid(cast1->value.type))
1128311271
return ira->codegen->invalid_instruction;
1128411272

11285-
return ir_implicit_cast_result(ira, cast1, needed_child_type);
11273+
return ir_implicit_cast_result(ira, cast1, needed_child_type, allow_failure);
1128611274
}
1128711275
}
1128811276

11277+
if (allow_failure) {
11278+
return result_loc;
11279+
}
11280+
1128911281
ErrorMsg *parent_msg = ir_add_error_node(ira, source_node,
1129011282
buf_sprintf("expected type '%s', found '%s'",
1129111283
buf_ptr(&have_child_type->name),
@@ -13377,7 +13369,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1337713369
}
1337813370

1337913371
static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
13380-
IrInstruction *uncasted_ptr, IrInstruction *value)
13372+
IrInstruction *uncasted_ptr, IrInstruction *uncasted_value)
1338113373
{
1338213374
if (uncasted_ptr->value.type->id != ZigTypeIdPointer) {
1338313375
ir_add_error(ira, uncasted_ptr,
@@ -13394,10 +13386,15 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
1339413386
return ira->codegen->invalid_instruction;
1339513387
}
1339613388

13397-
IrInstruction *ptr = ir_implicit_cast_result(ira, uncasted_ptr, value->value.type);
13389+
IrInstruction *ptr = ir_implicit_cast_result(ira, uncasted_ptr, uncasted_value->value.type, true);
1339813390
if (type_is_invalid(ptr->value.type))
1339913391
return ira->codegen->invalid_instruction;
1340013392

13393+
ZigType *child_type = ptr->value.type->data.pointer.child_type;
13394+
IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type);
13395+
if (type_is_invalid(value->value.type))
13396+
return ira->codegen->invalid_instruction;
13397+
1340113398
if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
1340213399
if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
1340313400
ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
@@ -13977,7 +13974,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1397713974
IrInstruction *result_loc = nullptr;
1397813975

1397913976
if (call_instruction->result_loc != nullptr) {
13980-
result_loc = ir_implicit_cast_result(ira, call_instruction->result_loc->child, return_type);
13977+
result_loc = ir_implicit_cast_result(ira, call_instruction->result_loc->child, return_type, false);
1398113978
if (type_is_invalid(result_loc->value.type))
1398213979
return ira->codegen->invalid_instruction;
1398313980
}
@@ -15434,21 +15431,7 @@ static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstruc
1543415431
static IrInstruction *ir_analyze_store_result(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
1543515432
IrInstruction *uncasted_result_loc)
1543615433
{
15437-
if (instr_is_comptime(value)) {
15438-
// No need for the ir_implicit_cast_result for comptime values.
15439-
return ir_analyze_store_ptr(ira, source_instr, uncasted_result_loc, value);
15440-
}
15441-
15442-
if (value->id == IrInstructionIdCall && handle_is_ptr(value->value.type)) {
15443-
// Elide this copy because it was the sret pointer in the function call.
15444-
return ir_const_void(ira, source_instr);
15445-
}
15446-
15447-
IrInstruction *result_loc = ir_implicit_cast_result(ira, uncasted_result_loc, value->value.type);
15448-
if (type_is_invalid(result_loc->value.type))
15449-
return ira->codegen->invalid_instruction;
15450-
15451-
return ir_analyze_store_ptr(ira, source_instr, result_loc, value);
15434+
zig_panic("TODO delete this instruction");
1545215435
}
1545315436

1545415437
static IrInstruction *ir_analyze_instruction_store_result(IrAnalyze *ira, IrInstructionStoreResult *instruction) {
@@ -21388,7 +21371,7 @@ static IrInstruction *ir_analyze_instruction_first_arg_result_loc(IrAnalyze *ira
2138821371
return ira->codegen->invalid_instruction;
2138921372

2139021373
IrInstruction *new_result_loc = ir_implicit_cast_result(ira, instruction->prev_result_loc->child,
21391-
dest_type);
21374+
dest_type, false);
2139221375
if (type_is_invalid(new_result_loc->value.type))
2139321376
return ira->codegen->invalid_instruction;
2139421377
return new_result_loc;

0 commit comments

Comments
 (0)