Skip to content

Commit

Permalink
Optimize temp variables in LLVM.
Browse files Browse the repository at this point in the history
  • Loading branch information
lerno committed Jan 6, 2025
1 parent ea2dce0 commit f801372
Show file tree
Hide file tree
Showing 25 changed files with 1,588 additions and 1,708 deletions.
1 change: 1 addition & 0 deletions src/compiler/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ Decl *decl_new_generated_var(Type *type, VarDeclKind kind, SourceSpan span)
decl->span = span;
decl->name = NULL;
decl->var.kind = kind;
decl->var.is_temp = true;
decl->type = type;
decl->alignment = type ? type_alloca_alignment(type) : 0;
ASSERT0(!type || !type_is_user_defined(type) || type->decl->resolve_status == RESOLVE_DONE);
Expand Down
1 change: 1 addition & 0 deletions src/compiler/compiler_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ typedef struct VarDecl_
bool no_alias : 1;
bool bit_is_expr : 1;
bool is_self : 1;
bool is_temp : 1;
union
{
Expr *init_expr;
Expand Down
11 changes: 11 additions & 0 deletions src/compiler/llvm_codegen_stmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ void llvm_emit_local_decl(GenContext *c, Decl *decl, BEValue *value)

// Create a local alloca
ASSERT0(!decl->backend_ref);
Type *type_low = type_lowering(decl->type);
if (decl->var.is_temp && !IS_OPTIONAL(decl) && !decl->var.is_addr && !decl->var.is_written && !type_is_user_defined(
type_low) && type_low->type_kind != TYPE_ARRAY)
{
assert(decl->var.init_expr);
llvm_emit_expr(c, value, decl->var.init_expr);
llvm_value_rvalue(c, value);
decl->backend_value = value->value;
decl->is_value = true;
return;
}
llvm_emit_local_var_alloca(c, decl);

// Create optional storage
Expand Down
194 changes: 95 additions & 99 deletions test/test_suite/any/variant_assign.c3t
Original file line number Diff line number Diff line change
Expand Up @@ -146,170 +146,166 @@ switch.exit: ; preds = %switch.default, %sw
define void @foo.test2(i64 %0, ptr %1) #0 {
entry:
%y = alloca %any, align 8
%.anon = alloca %any, align 8
%switch = alloca i64, align 8
%z = alloca ptr, align 8
%taddr = alloca i32, align 4
%z10 = alloca ptr, align 8
%z9 = alloca ptr, align 8
store i64 %0, ptr %y, align 8
%ptradd = getelementptr inbounds i8, ptr %y, i64 8
store ptr %1, ptr %ptradd, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %.anon, ptr align 8 %y, i32 16, i1 false)
%ptradd1 = getelementptr inbounds i8, ptr %y, i64 8
%2 = load i64, ptr %ptradd1, align 8
store i64 %2, ptr %switch, align 8
%2 = load %any, ptr %y, align 8
%3 = extractvalue %any %2, 1
store i64 %3, ptr %switch, align 8
br label %switch.entry

switch.entry: ; preds = %entry
%3 = load i64, ptr %switch, align 8
%4 = load i64, ptr %switch, align 8
br label %check_subtype

check_subtype: ; preds = %parent_type_block, %switch.entry
%4 = phi i64 [ %3, %switch.entry ], [ %typeid.parent, %parent_type_block ]
%eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %4
%5 = phi i64 [ %4, %switch.entry ], [ %typeid.parent, %parent_type_block ]
%eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %5
br i1 %eq, label %result_block, label %parent_type_block

parent_type_block: ; preds = %check_subtype
%5 = inttoptr i64 %4 to ptr
%ptradd2 = getelementptr inbounds i8, ptr %5, i64 8
%typeid.parent = load i64, ptr %ptradd2, align 8
%6 = icmp eq i64 %typeid.parent, 0
br i1 %6, label %result_block, label %check_subtype
%6 = inttoptr i64 %5 to ptr
%ptradd1 = getelementptr inbounds i8, ptr %6, i64 8
%typeid.parent = load i64, ptr %ptradd1, align 8
%7 = icmp eq i64 %typeid.parent, 0
br i1 %7, label %result_block, label %check_subtype

result_block: ; preds = %parent_type_block, %check_subtype
%7 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ]
br i1 %7, label %switch.case, label %next_if
%8 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ]
br i1 %8, label %switch.case, label %next_if

switch.case: ; preds = %result_block
%8 = load ptr, ptr %.anon, align 8
store ptr %8, ptr %z, align 8
%9 = extractvalue %any %2, 0
store ptr %9, ptr %z, align 8
store i32 12, ptr %taddr, align 4
%9 = insertvalue %any undef, ptr %taddr, 0
%10 = insertvalue %any %9, i64 ptrtoint (ptr @"$ct.int" to i64), 1
store %any %10, ptr %y, align 8
%11 = load ptr, ptr %z, align 8
%12 = load i32, ptr %11, align 4
call void (ptr, ...) @printf(ptr @.str.3, i32 %12)
%10 = insertvalue %any undef, ptr %taddr, 0
%11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.int" to i64), 1
store %any %11, ptr %y, align 8
%12 = load ptr, ptr %z, align 8
%13 = load i32, ptr %12, align 4
call void (ptr, ...) @printf(ptr @.str.3, i32 %13)
br label %switch.exit

next_if: ; preds = %result_block
br label %check_subtype3

check_subtype3: ; preds = %parent_type_block5, %next_if
%13 = phi i64 [ %3, %next_if ], [ %typeid.parent7, %parent_type_block5 ]
%eq4 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %13
br i1 %eq4, label %result_block8, label %parent_type_block5

parent_type_block5: ; preds = %check_subtype3
%14 = inttoptr i64 %13 to ptr
%ptradd6 = getelementptr inbounds i8, ptr %14, i64 8
%typeid.parent7 = load i64, ptr %ptradd6, align 8
%15 = icmp eq i64 %typeid.parent7, 0
br i1 %15, label %result_block8, label %check_subtype3

result_block8: ; preds = %parent_type_block5, %check_subtype3
%16 = phi i1 [ false, %parent_type_block5 ], [ true, %check_subtype3 ]
br i1 %16, label %switch.case9, label %next_if11

switch.case9: ; preds = %result_block8
%17 = load ptr, ptr %.anon, align 8
store ptr %17, ptr %z10, align 8
%18 = load ptr, ptr %z10, align 8
%19 = load double, ptr %18, align 8
call void (ptr, ...) @printf(ptr @.str.4, double %19)
br label %check_subtype2

check_subtype2: ; preds = %parent_type_block4, %next_if
%14 = phi i64 [ %4, %next_if ], [ %typeid.parent6, %parent_type_block4 ]
%eq3 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %14
br i1 %eq3, label %result_block7, label %parent_type_block4

parent_type_block4: ; preds = %check_subtype2
%15 = inttoptr i64 %14 to ptr
%ptradd5 = getelementptr inbounds i8, ptr %15, i64 8
%typeid.parent6 = load i64, ptr %ptradd5, align 8
%16 = icmp eq i64 %typeid.parent6, 0
br i1 %16, label %result_block7, label %check_subtype2

result_block7: ; preds = %parent_type_block4, %check_subtype2
%17 = phi i1 [ false, %parent_type_block4 ], [ true, %check_subtype2 ]
br i1 %17, label %switch.case8, label %next_if10

switch.case8: ; preds = %result_block7
%18 = extractvalue %any %2, 0
store ptr %18, ptr %z9, align 8
%19 = load ptr, ptr %z9, align 8
%20 = load double, ptr %19, align 8
call void (ptr, ...) @printf(ptr @.str.4, double %20)
br label %switch.exit

next_if11: ; preds = %result_block8
next_if10: ; preds = %result_block7
br label %switch.default

switch.default: ; preds = %next_if11
switch.default: ; preds = %next_if10
call void (ptr, ...) @printf(ptr @.str.5)
br label %switch.exit

switch.exit: ; preds = %switch.default, %switch.case9, %switch.case
switch.exit: ; preds = %switch.default, %switch.case8, %switch.case
ret void
}

; Function Attrs:
define void @foo.test3(i64 %0, ptr %1) #0 {
entry:
%y = alloca %any, align 8
%.anon = alloca %any, align 8
%switch = alloca i64, align 8
%z = alloca i32, align 4
%z10 = alloca double, align 8
%z9 = alloca double, align 8
store i64 %0, ptr %y, align 8
%ptradd = getelementptr inbounds i8, ptr %y, i64 8
store ptr %1, ptr %ptradd, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %.anon, ptr align 8 %y, i32 16, i1 false)
%ptradd1 = getelementptr inbounds i8, ptr %y, i64 8
%2 = load i64, ptr %ptradd1, align 8
store i64 %2, ptr %switch, align 8
%2 = load %any, ptr %y, align 8
%3 = extractvalue %any %2, 1
store i64 %3, ptr %switch, align 8
br label %switch.entry

switch.entry: ; preds = %entry
%3 = load i64, ptr %switch, align 8
%4 = load i64, ptr %switch, align 8
br label %check_subtype

check_subtype: ; preds = %parent_type_block, %switch.entry
%4 = phi i64 [ %3, %switch.entry ], [ %typeid.parent, %parent_type_block ]
%eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %4
%5 = phi i64 [ %4, %switch.entry ], [ %typeid.parent, %parent_type_block ]
%eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %5
br i1 %eq, label %result_block, label %parent_type_block

parent_type_block: ; preds = %check_subtype
%5 = inttoptr i64 %4 to ptr
%ptradd2 = getelementptr inbounds i8, ptr %5, i64 8
%typeid.parent = load i64, ptr %ptradd2, align 8
%6 = icmp eq i64 %typeid.parent, 0
br i1 %6, label %result_block, label %check_subtype
%6 = inttoptr i64 %5 to ptr
%ptradd1 = getelementptr inbounds i8, ptr %6, i64 8
%typeid.parent = load i64, ptr %ptradd1, align 8
%7 = icmp eq i64 %typeid.parent, 0
br i1 %7, label %result_block, label %check_subtype

result_block: ; preds = %parent_type_block, %check_subtype
%7 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ]
br i1 %7, label %switch.case, label %next_if
%8 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ]
br i1 %8, label %switch.case, label %next_if

switch.case: ; preds = %result_block
%8 = load ptr, ptr %.anon, align 8
%9 = load i32, ptr %8, align 4
store i32 %9, ptr %z, align 4
%10 = load i32, ptr %z, align 4
call void (ptr, ...) @printf(ptr @.str.6, i32 %10)
%9 = extractvalue %any %2, 0
%10 = load i32, ptr %9, align 4
store i32 %10, ptr %z, align 4
%11 = load i32, ptr %z, align 4
call void (ptr, ...) @printf(ptr @.str.6, i32 %11)
br label %switch.exit

next_if: ; preds = %result_block
br label %check_subtype3

check_subtype3: ; preds = %parent_type_block5, %next_if
%11 = phi i64 [ %3, %next_if ], [ %typeid.parent7, %parent_type_block5 ]
%eq4 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %11
br i1 %eq4, label %result_block8, label %parent_type_block5

parent_type_block5: ; preds = %check_subtype3
%12 = inttoptr i64 %11 to ptr
%ptradd6 = getelementptr inbounds i8, ptr %12, i64 8
%typeid.parent7 = load i64, ptr %ptradd6, align 8
%13 = icmp eq i64 %typeid.parent7, 0
br i1 %13, label %result_block8, label %check_subtype3

result_block8: ; preds = %parent_type_block5, %check_subtype3
%14 = phi i1 [ false, %parent_type_block5 ], [ true, %check_subtype3 ]
br i1 %14, label %switch.case9, label %next_if11

switch.case9: ; preds = %result_block8
%15 = load ptr, ptr %.anon, align 8
%16 = load double, ptr %15, align 8
store double %16, ptr %z10, align 8
%17 = load double, ptr %z10, align 8
call void (ptr, ...) @printf(ptr @.str.7, double %17)
br label %check_subtype2

check_subtype2: ; preds = %parent_type_block4, %next_if
%12 = phi i64 [ %4, %next_if ], [ %typeid.parent6, %parent_type_block4 ]
%eq3 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %12
br i1 %eq3, label %result_block7, label %parent_type_block4

parent_type_block4: ; preds = %check_subtype2
%13 = inttoptr i64 %12 to ptr
%ptradd5 = getelementptr inbounds i8, ptr %13, i64 8
%typeid.parent6 = load i64, ptr %ptradd5, align 8
%14 = icmp eq i64 %typeid.parent6, 0
br i1 %14, label %result_block7, label %check_subtype2

result_block7: ; preds = %parent_type_block4, %check_subtype2
%15 = phi i1 [ false, %parent_type_block4 ], [ true, %check_subtype2 ]
br i1 %15, label %switch.case8, label %next_if10

switch.case8: ; preds = %result_block7
%16 = extractvalue %any %2, 0
%17 = load double, ptr %16, align 8
store double %17, ptr %z9, align 8
%18 = load double, ptr %z9, align 8
call void (ptr, ...) @printf(ptr @.str.7, double %18)
br label %switch.exit

next_if11: ; preds = %result_block8
next_if10: ; preds = %result_block7
br label %switch.default

switch.default: ; preds = %next_if11
switch.default: ; preds = %next_if10
call void (ptr, ...) @printf(ptr @.str.8)
br label %switch.exit

switch.exit: ; preds = %switch.default, %switch.case9, %switch.case
switch.exit: ; preds = %switch.default, %switch.case8, %switch.case
ret void
}

Expand Down
25 changes: 11 additions & 14 deletions test/test_suite/any/variant_test.c3t
Original file line number Diff line number Diff line change
Expand Up @@ -192,35 +192,32 @@ define void @foo.test_all(ptr %0, i64 %1) #0 {
entry:
%y = alloca %"any[]", align 8
%.anon = alloca i64, align 8
%.anon2 = alloca i64, align 8
%element = alloca %any, align 8
store ptr %0, ptr %y, align 8
%ptradd = getelementptr inbounds i8, ptr %y, i64 8
store i64 %1, ptr %ptradd, align 8
%ptradd1 = getelementptr inbounds i8, ptr %y, i64 8
%2 = load i64, ptr %ptradd1, align 8
store i64 %2, ptr %.anon, align 8
store i64 0, ptr %.anon2, align 8
store i64 0, ptr %.anon, align 8
br label %loop.cond

loop.cond: ; preds = %loop.body, %entry
%3 = load i64, ptr %.anon2, align 8
%4 = load i64, ptr %.anon, align 8
%lt = icmp ult i64 %3, %4
%3 = load i64, ptr %.anon, align 8
%lt = icmp ult i64 %3, %2
br i1 %lt, label %loop.body, label %loop.exit

loop.body: ; preds = %loop.cond
%5 = load ptr, ptr %y, align 8
%6 = load i64, ptr %.anon2, align 8
%ptroffset = getelementptr inbounds [16 x i8], ptr %5, i64 %6
%4 = load ptr, ptr %y, align 8
%5 = load i64, ptr %.anon, align 8
%ptroffset = getelementptr inbounds [16 x i8], ptr %4, i64 %5
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %element, ptr align 8 %ptroffset, i32 16, i1 false)
%lo = load i64, ptr %element, align 8
%ptradd3 = getelementptr inbounds i8, ptr %element, i64 8
%hi = load ptr, ptr %ptradd3, align 8
%ptradd2 = getelementptr inbounds i8, ptr %element, i64 8
%hi = load ptr, ptr %ptradd2, align 8
call void @foo.test(i64 %lo, ptr %hi)
%7 = load i64, ptr %.anon2, align 8
%addnuw = add nuw i64 %7, 1
store i64 %addnuw, ptr %.anon2, align 8
%6 = load i64, ptr %.anon, align 8
%addnuw = add nuw i64 %6, 1
store i64 %addnuw, ptr %.anon, align 8
br label %loop.cond

loop.exit: ; preds = %loop.cond
Expand Down
Loading

0 comments on commit f801372

Please sign in to comment.