llvm / llvm/llvm-project

[Codegen] Codegen breaks IR

Open
#169,496 3 comments 0 reactions 0 assignees View on GitHub
llvm:codegen
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

I'm not sure whether it's a bug or expected behaviour, but I would expect some kind of assert if `IR` is invalid after `Codegen`.

*What happens*
Running `Codegen` on module leads to incorrect IR in module after `Codegen`.

IR dump before `Codegen`:
```
@"a" = dllexport global ptr inttoptr (i64 0 to ptr)
@"b" = dllexport global ptr inttoptr (i64 0 to ptr)
@"c" = dllexport global ptr inttoptr (i64 0 to ptr)

declare ptr @jit_string_builder_temp(ptr, ptr, ptr)

define dllexport <4 x float> @"main"(ptr %0, ptr %1, ptr %2) {
entry:
%args.i.i.i = alloca [1 x <4 x float>], align 16
%mks_local_sp_0x20.i.i = alloca { ptr, i32, i32, i32, i32 }, align 16
%variable_st.i = alloca { ptr, i32, i32, i32, i32 }, align 16
%args.i = alloca [1 x <4 x float>], align 16
call void @llvm.lifetime.start.p0(ptr nonnull %variable_st.i)
call void @llvm.lifetime.start.p0(ptr nonnull %args.i)
call void @llvm.lifetime.start.p0(ptr nonnull %mks_local_sp_0x20.i.i)
call void @llvm.memset.p0.i32(ptr noundef nonnull align 16 dereferenceable(24) %mks_local_sp_0x20.i.i, i8 0, i32 24, i1 false)
call void @llvm.lifetime.start.p0(ptr nonnull %args.i.i.i)
store ptr %mks_local_sp_0x20.i.i, ptr %args.i.i.i, align 16
%3 = load ptr, ptr @"a", align 8
%4 = load ptr, ptr @"b", align 8
%5 = call <4 x float> %3(ptr align 16 %0, ptr %4, ptr nonnull %args.i.i.i)
call void @llvm.lifetime.end.p0(ptr nonnull %args.i.i.i)
call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 16 dereferenceable(24) %variable_st.i, ptr noundef nonnull align 16 dereferenceable(24) %mks_local_sp_0x20.i.i, i32 24, i1 false)
call void @llvm.memset.p0.i32(ptr noundef nonnull align 16 dereferenceable(24) %mks_local_sp_0x20.i.i, i8 0, i32 24, i1 false)
call void @llvm.lifetime.end.p0(ptr nonnull %mks_local_sp_0x20.i.i)
store ptr %variable_st.i, ptr %args.i, align 16
%6 = load ptr, ptr @"c", align 8
%string_builder.i = call ptr @jit_string_builder_temp(ptr align 16 %0, ptr %6, ptr nonnull %args.i)
call void @llvm.lifetime.end.p0(ptr nonnull %variable_st.i)
call void @llvm.lifetime.end.p0(ptr nonnull %args.i)
ret <4 x float> undef
}
```
And calling IR dump after `Codegen` prints:
```

define dllexport <4 x float> @main(ptr %0, ptr %1, ptr %2) {
entry:
%variable_st.i = alloca { ptr, i32, i32, i32, i32 }, align 16
%args.i.i.i = alloca [1 x <4 x float>], align 16
%mks_local_sp_0x20.i.i = alloca { ptr, i32, i32, i32, i32 }, align 16
%args.i = alloca [1 x <4 x float>], align 16
call void @llvm.lifetime.start.p0(ptr nonnull %variable_st.i)
call void @llvm.lifetime.start.p0(ptr nonnull %mks_local_sp_0x20.i.i)
call void @llvm.lifetime.start.p0(ptr nonnull %mks_local_sp_0x20.i.i)
call void @llvm.memset.p0.i32(ptr noundef nonnull align 16 dereferenceable(24) %mks_local_sp_0x20.i.i, i8 0, i32 24, i1 false)
call void @llvm.lifetime.start.p0(ptr nonnull %variable_st.i)
store ptr %mks_local_sp_0x20.i.i, ptr %variable_st.i, align 16
%3 = load ptr, ptr @a, align 8
%4 = load ptr, ptr @b, align 8
%5 = call <4 x float> %3(ptr align 16 %0, ptr %4, ptr nonnull %variable_st.i)
call void @llvm.lifetime.end.p0(ptr nonnull %variable_st.i)
call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 16 dereferenceable(24) %variable_st.i, ptr noundef nonnull align 16 dereferenceable(24) %mks_local_sp_0x20.i.i, i32 24, i1 false)
call void @llvm.memset.p0.i32(ptr noundef nonnull align 16 dereferenceable(24) %mks_local_sp_0x20.i.i, i8 0, i32 24, i1 false)
call void @llvm.lifetime.end.p0(ptr nonnull %mks_local_sp_0x20.i.i)
store ptr %variable_st.i, ptr %mks_local_sp_0x20.i.i, align 16
%6 = load ptr, ptr @c, align 8
%string_builder.i = call ptr @jit_string_builder_temp(ptr align 16 %0, ptr %6, ptr nonnull %mks_local_sp_0x20.i.i)
call void @llvm.lifetime.end.p0(ptr nonnull %variable_st.i)
call void @llvm.lifetime.end.p0(ptr nonnull %mks_local_sp_0x20.i.i)
ret <4 x float> undef
}
```

As we can see `StackColoring` merged 2 variables, which lead to calling `lifetime.start` and `lifetime.end` twice, however we can't use variable after first `lifetime.end`. So, calling `Codegen` second time will lead to incorrect binary code.

Contributor guide

Open the contributing guide

Research direction

Start at the Codegen entry point and the StackColoring pass, then compare the supplied pre- and post-Codegen IR dumps. Determine whether repeated Codegen should be rejected or whether the invalid lifetime reuse must be prevented; done means the module remains valid across repeated Codegen or reports the invalid state clearly.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.