Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add canonicalization passes for cir.complex.create #726

Open
Lancern opened this issue Jul 9, 2024 · 0 comments
Open

Add canonicalization passes for cir.complex.create #726

Lancern opened this issue Jul 9, 2024 · 0 comments
Assignees
Labels
enhancement New feature or request

Comments

@Lancern
Copy link
Collaborator

Lancern commented Jul 9, 2024

The LLVM IR generated for cir.complex.create is a bit ugly since it includes the insertvalue instruction, which typically is not generated in upstream CodeGen.
-- Originally posted in the comments of #723 .

Consider the following example:

void test(float a, float b) {
  float _Complex x = {a, b};
}

CIRGen emits code similar to the following:

%0 = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
%1 = cir.complex.create %a, %b : !cir.float -> !cir.complex<!cir.float>
cir.store %1, %0 : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>

Then LLVMIR lowering pass further emits code similar to the following:

%0 = alloca { float, float } align 4
%1 = insertvalue { float, float } undef, float %a, 0
%2 = insertvalue { float, float } %0, float %b, 1
store { float, float } %2, ptr %0

The insertvalue instruction is required to lower cir.complex.create because complex values are lowered to LLVM aggregate values, and thus we need to construct the aggregate value entirely in LLVM registers. But this is not the way the upstream CodeGen currently handles complex values. For the C code listed above, the upstream CodeGen would emit code like the following:

%0 = alloca { float, float } align 4
%0.realp = getelementptr inbounds { float, float }, ptr %0, i32 0, i32 0
%0.imagp = getelementptr inbounds { float, float }, ptr %0, i32 0, i32 1
store float %a, ptr %0.realp
store float %b, ptr %0.imagp

Basically the upstream CodeGen breaks the big store of aggregate values down to small stores of fields. To keep consistent LLVM IR codegen, we need further canonicalization passes to track the data flow of SSA values created by the cir.complex.create operation and breaks it into its real part and imaginary part. To give an example, after the canonicalization, the code generated by CIRGen above should be similar to:

%0 = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
%0.realp = cir.complex.real_ptr %0 : !cir.ptr<!cir.complex<!cir.float>> -> !cir.ptr<!cir.float>
%0.imagp = cir.complex.imag_ptr %0 : !cir.ptr<!cir.complex<!cir.float>> -> !cir.ptr<!cir.float>
cir.store %a, %0.realp : !cir.float, !cir.ptr<!cir.float>
cir.store %b, %0.imagp : !cir.float, !cir.ptr<!cir.float>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant