Fix issue where array comparison would emit the wrong basic block reference to phi when underlying comparison would emit a block.

This commit is contained in:
Christoffer Lerno
2023-07-06 20:29:00 +02:00
parent df9bc377dd
commit b74de0b1e4
4 changed files with 180 additions and 9 deletions

View File

@@ -131,8 +131,10 @@
- Add checks to prevent incorrect alignment on malloc.
- Updated clamp.
- Added `Clock` and `DateTime`.
- Added posix socket functions.
### Fixes
- Fix to bug when comparing nested arrays.
- Fix to bug when a macro is using rethrow.
- Fixes bug initializing a const struct with a const struct value.
- Fixes bug when `void` is passed to an "any"-vararg.

View File

@@ -3509,13 +3509,25 @@ static void llvm_emit_subarray_comp(GenContext *c, BEValue *be_value, BEValue *l
}
INLINE bool should_inline_array_comp(ArraySize len, Type *base_type_lowered)
{
switch (base_type_lowered->type_kind)
{
case TYPE_ARRAY:
return should_inline_array_comp(base_type_lowered->array.len * len, type_lowering(base_type_lowered->array.base));
case TYPE_SUBARRAY:
return len <= 4;
default:
return len <= 16;
}
}
static void llvm_emit_array_comp(GenContext *c, BEValue *be_value, BEValue *lhs, BEValue *rhs, BinaryOp binary_op)
{
bool want_match = binary_op == BINARYOP_EQ;
ArraySize len = lhs->type->array.len;
Type *array_base_type = type_lowering(lhs->type->array.base);
LLVMTypeRef array_type = llvm_get_type(c, lhs->type);
if (len <= 16)
if (should_inline_array_comp(len, array_base_type))
{
LLVMBasicBlockRef blocks[17];
LLVMValueRef value_block[17];
@@ -3525,7 +3537,7 @@ static void llvm_emit_array_comp(GenContext *c, BEValue *be_value, BEValue *lhs,
llvm_value_addr(c, rhs);
LLVMValueRef success = LLVMConstInt(c->bool_type, want_match ? 1 : 0, false);
LLVMValueRef failure = LLVMConstInt(c->bool_type, want_match ? 0 : 1, false);
blocks[0] = c->current_block;
for (unsigned i = 0; i < len; i++)
{
value_block[i] = failure;
@@ -3539,11 +3551,9 @@ static void llvm_emit_array_comp(GenContext *c, BEValue *be_value, BEValue *lhs,
llvm_value_set_address(&rhs_v, rhs_ptr, array_base_type, align_rhs);
BEValue comp;
llvm_emit_comp(c, &comp, &lhs_v, &rhs_v, BINARYOP_EQ);
blocks[i] = c->current_block;
LLVMBasicBlockRef block = ok_block;
if (i < len - 1)
{
block = blocks[i + 1] = llvm_basic_block_new(c, "next_check");
}
block = i < len - 1 ? llvm_basic_block_new(c, "next_check") : block;
llvm_emit_cond_br(c, &comp, block, exit_block);
llvm_emit_block(c, block);
}
@@ -3560,7 +3570,8 @@ static void llvm_emit_array_comp(GenContext *c, BEValue *be_value, BEValue *lhs,
LLVMBasicBlockRef exit = llvm_basic_block_new(c, "array_cmp_exit");
LLVMBasicBlockRef loop_begin = llvm_basic_block_new(c, "array_loop_start");
LLVMBasicBlockRef comparison = llvm_basic_block_new(c, "array_loop_comparison");
LLVMBasicBlockRef comparison_phi;
LLVMBasicBlockRef loop_begin_phi;
LLVMValueRef len_val = llvm_const_int(c, type_usz, len);
LLVMValueRef one = llvm_const_int(c, type_usz, 1);
BEValue index_var;
@@ -3581,12 +3592,14 @@ static void llvm_emit_array_comp(GenContext *c, BEValue *be_value, BEValue *lhs,
llvm_value_set_address(&rhs_v, rhs_ptr, array_base_type, align_rhs);
BEValue comp;
llvm_emit_comp(c, &comp, &lhs_v, &rhs_v, BINARYOP_EQ);
loop_begin_phi = c->current_block;
llvm_emit_cond_br(c, &comp, comparison, exit);
llvm_emit_block(c, comparison);
LLVMValueRef new_index = LLVMBuildAdd(c->builder, index, one, "inc");
llvm_store_raw(c, &index_var, new_index);
llvm_emit_int_comp_raw(c, &comp, type_usz, type_usz, new_index, len_val, BINARYOP_LT);
comparison_phi = c->current_block;
llvm_emit_cond_br(c, &comp, loop_begin, exit);
llvm_emit_block(c, exit);
LLVMValueRef phi = LLVMBuildPhi(c->builder, c->bool_type, "array_cmp_phi");
@@ -3594,7 +3607,7 @@ static void llvm_emit_array_comp(GenContext *c, BEValue *be_value, BEValue *lhs,
LLVMValueRef success = LLVMConstInt(c->bool_type, want_match ? 1 : 0, false);
LLVMValueRef failure = LLVMConstInt(c->bool_type, want_match ? 0 : 1, false);
LLVMValueRef logic_values[3] = { success, failure };
LLVMBasicBlockRef blocks[3] = { comparison, loop_begin };
LLVMBasicBlockRef blocks[3] = { comparison_phi, loop_begin_phi };
LLVMAddIncoming(phi, logic_values, blocks, 2);
llvm_value_set(be_value, phi, type_bool);
}

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.4.553"
#define COMPILER_VERSION "0.4.554"

View File

@@ -0,0 +1,156 @@
// #target: macos-x64
module test;
fn void main()
{
int[2][2] x;
int[2][2] y;
bool match = x == y;
int[2][2][8] z;
int[2][2][8] w;
match = z == w;
}
/* #expect: test.ll
define void @test.main() #0 {
entry:
%x = alloca [2 x [2 x i32]], align 16
%y = alloca [2 x [2 x i32]], align 16
%match = alloca i8, align 1
%z = alloca [8 x [2 x [2 x i32]]], align 16
%w = alloca [8 x [2 x [2 x i32]]], align 16
%cmp.idx = alloca i64, align 8
%0 = getelementptr inbounds [2 x [2 x i32]], ptr %x, i64 0, i64 0
%1 = getelementptr inbounds [2 x i32], ptr %0, i64 0, i64 0
store i32 0, ptr %1, align 4
%2 = getelementptr inbounds [2 x i32], ptr %0, i64 0, i64 1
store i32 0, ptr %2, align 4
%3 = getelementptr inbounds [2 x [2 x i32]], ptr %x, i64 0, i64 1
%4 = getelementptr inbounds [2 x i32], ptr %3, i64 0, i64 0
store i32 0, ptr %4, align 4
%5 = getelementptr inbounds [2 x i32], ptr %3, i64 0, i64 1
store i32 0, ptr %5, align 4
%6 = getelementptr inbounds [2 x [2 x i32]], ptr %y, i64 0, i64 0
%7 = getelementptr inbounds [2 x i32], ptr %6, i64 0, i64 0
store i32 0, ptr %7, align 4
%8 = getelementptr inbounds [2 x i32], ptr %6, i64 0, i64 1
store i32 0, ptr %8, align 4
%9 = getelementptr inbounds [2 x [2 x i32]], ptr %y, i64 0, i64 1
%10 = getelementptr inbounds [2 x i32], ptr %9, i64 0, i64 0
store i32 0, ptr %10, align 4
%11 = getelementptr inbounds [2 x i32], ptr %9, i64 0, i64 1
store i32 0, ptr %11, align 4
%12 = getelementptr inbounds [2 x [2 x i32]], ptr %x, i64 0, i64 0
%13 = getelementptr inbounds [2 x [2 x i32]], ptr %y, i64 0, i64 0
%14 = getelementptr inbounds [2 x i32], ptr %12, i64 0, i64 0
%15 = getelementptr inbounds [2 x i32], ptr %13, i64 0, i64 0
%16 = load i32, ptr %14, align 4
%17 = load i32, ptr %15, align 4
%eq = icmp eq i32 %16, %17
br i1 %eq, label %next_check, label %exit
next_check: ; preds = %entry
%18 = getelementptr inbounds [2 x i32], ptr %12, i64 0, i64 1
%19 = getelementptr inbounds [2 x i32], ptr %13, i64 0, i64 1
%20 = load i32, ptr %18, align 4
%21 = load i32, ptr %19, align 4
%eq1 = icmp eq i32 %20, %21
br i1 %eq1, label %match2, label %exit
match2: ; preds = %next_check
br label %exit
exit: ; preds = %match2, %next_check, %entry
%array_cmp_phi = phi i1 [ false, %entry ], [ false, %next_check ], [ true, %match2 ]
br i1 %array_cmp_phi, label %next_check3, label %exit11
next_check3: ; preds = %exit
%22 = getelementptr inbounds [2 x [2 x i32]], ptr %x, i64 0, i64 1
%23 = getelementptr inbounds [2 x [2 x i32]], ptr %y, i64 0, i64 1
%24 = getelementptr inbounds [2 x i32], ptr %22, i64 0, i64 0
%25 = getelementptr inbounds [2 x i32], ptr %23, i64 0, i64 0
%26 = load i32, ptr %24, align 4
%27 = load i32, ptr %25, align 4
%eq4 = icmp eq i32 %26, %27
br i1 %eq4, label %next_check5, label %exit8
next_check5: ; preds = %next_check3
%28 = getelementptr inbounds [2 x i32], ptr %22, i64 0, i64 1
%29 = getelementptr inbounds [2 x i32], ptr %23, i64 0, i64 1
%30 = load i32, ptr %28, align 4
%31 = load i32, ptr %29, align 4
%eq6 = icmp eq i32 %30, %31
br i1 %eq6, label %match7, label %exit8
match7: ; preds = %next_check5
br label %exit8
exit8: ; preds = %match7, %next_check5, %next_check3
%array_cmp_phi9 = phi i1 [ false, %next_check3 ], [ false, %next_check5 ], [ true, %match7 ]
br i1 %array_cmp_phi9, label %match10, label %exit11
match10: ; preds = %exit8
br label %exit11
exit11: ; preds = %match10, %exit8, %exit
%array_cmp_phi12 = phi i1 [ false, %exit ], [ false, %exit8 ], [ true, %match10 ]
%32 = zext i1 %array_cmp_phi12 to i8
store i8 %32, ptr %match, align 1
call void @llvm.memset.p0.i64(ptr align 16 %z, i8 0, i64 128, i1 false)
call void @llvm.memset.p0.i64(ptr align 16 %w, i8 0, i64 128, i1 false)
store i64 0, ptr %cmp.idx, align 8
br label %array_loop_start
array_loop_start: ; preds = %array_loop_comparison, %exit11
%33 = load i64, ptr %cmp.idx, align 8
%34 = getelementptr inbounds [8 x [2 x [2 x i32]]], ptr %z, i64 0, i64 %33
%35 = getelementptr inbounds [8 x [2 x [2 x i32]]], ptr %w, i64 0, i64 %33
%36 = getelementptr inbounds [2 x [2 x i32]], ptr %34, i64 0, i64 0
%37 = getelementptr inbounds [2 x [2 x i32]], ptr %35, i64 0, i64 0
%38 = getelementptr inbounds [2 x i32], ptr %36, i64 0, i64 0
%39 = getelementptr inbounds [2 x i32], ptr %37, i64 0, i64 0
%40 = load i32, ptr %38, align 4
%41 = load i32, ptr %39, align 4
%eq13 = icmp eq i32 %40, %41
br i1 %eq13, label %next_check14, label %exit17
next_check14: ; preds = %array_loop_start
%42 = getelementptr inbounds [2 x i32], ptr %36, i64 0, i64 1
%43 = getelementptr inbounds [2 x i32], ptr %37, i64 0, i64 1
%44 = load i32, ptr %42, align 4
%45 = load i32, ptr %43, align 4
%eq15 = icmp eq i32 %44, %45
br i1 %eq15, label %match16, label %exit17
match16: ; preds = %next_check14
br label %exit17
exit17: ; preds = %match16, %next_check14, %array_loop_start
%array_cmp_phi18 = phi i1 [ false, %array_loop_start ], [ false, %next_check14 ], [ true, %match16 ]
br i1 %array_cmp_phi18, label %next_check19, label %exit27
next_check19: ; preds = %exit17
%46 = getelementptr inbounds [2 x [2 x i32]], ptr %34, i64 0, i64 1
%47 = getelementptr inbounds [2 x [2 x i32]], ptr %35, i64 0, i64 1
%48 = getelementptr inbounds [2 x i32], ptr %46, i64 0, i64 0
%49 = getelementptr inbounds [2 x i32], ptr %47, i64 0, i64 0
%50 = load i32, ptr %48, align 4
%51 = load i32, ptr %49, align 4
%eq20 = icmp eq i32 %50, %51
br i1 %eq20, label %next_check21, label %exit24
next_check21: ; preds = %next_check19
%52 = getelementptr inbounds [2 x i32], ptr %46, i64 0, i64 1
%53 = getelementptr inbounds [2 x i32], ptr %47, i64 0, i64 1
%54 = load i32, ptr %52, align 4
%55 = load i32, ptr %53, align 4
%eq22 = icmp eq i32 %54, %55
br i1 %eq22, label %match23, label %exit24
match23: ; preds = %next_check21
br label %exit24
exit24: ; preds = %match23, %next_check21, %next_check19
%array_cmp_phi25 = phi i1 [ false, %next_check19 ], [ false, %next_check21 ], [ true, %match23 ]
br i1 %array_cmp_phi25, label %match26, label %exit27
match26: ; preds = %exit24
br label %exit27
exit27: ; preds = %match26, %exit24, %exit17
%array_cmp_phi28 = phi i1 [ false, %exit17 ], [ false, %exit24 ], [ true, %match26 ]
br i1 %array_cmp_phi28, label %array_loop_comparison, label %array_cmp_exit
array_loop_comparison: ; preds = %exit27
%inc = add i64 %33, 1
store i64 %inc, ptr %cmp.idx, align 8
%lt = icmp ult i64 %inc, 8
br i1 %lt, label %array_loop_start, label %array_cmp_exit
array_cmp_exit: ; preds = %array_loop_comparison, %exit27
%array_cmp_phi29 = phi i1 [ true, %array_loop_comparison ], [ false, %exit27 ]
%56 = zext i1 %array_cmp_phi29 to i8
store i8 %56, ptr %match, align 1
ret void
}