affine.for can't be convert to affine.parallel if scf is raised through polygeist-opt
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 624
- Forks
- 170
- PR merge metrics
- No merged PRs in 30d
Description
for the following case, if it raise to affine through cgeist, matmul can be parallized by polygeist-opt(affine-parallize), but DSPF_sp_mat_trans_cplx can't be parallize, if it raise to affine through polygeist, then both funcions(DSPF_sp_mat_trans_cplx and mamtul) can't be parallized
cgeist test.c -S | polygeist-opt --raise-scf-to-affine --affine-parallelize
result: DSPF_sp_mat_trans_cplx and matmul can't be parallized through --affine-parallelize
cgeist test.c -S --raise-scf-to-affine | polygeist-opt --affine-parallelize
result: matmul can be parallized through --affine-parallelize but DSPF_sp_mat_trans_cplx still can't be
example code:
```
void DSPF_sp_mat_trans_cplx( float* x, int rows, int cols, float * r)
{
int i, j;
for (i = 0; i < cols; i++)
for (j = 0; j < rows; j++)
{
r[(i * rows + j) * 2] = x[(i + cols * j) * 2];
r[(i * rows + j) * 2 + 1] = x[(i + cols * j) * 2 + 1];
}
}
#define N 200
#define M 300
#define K 400
#define DATA_TYPE float
void matmul(DATA_TYPE A[N][K], DATA_TYPE B[K][M], DATA_TYPE C[N][M], int N_L, int M_L, int K_L) {
int i, j, k;
for (int i = 0; i < N_L; i++) {
for (int j = 0; j < M_L; j++) {
for (int k = 0; k < K_L; k++) {
C[i][j] += A[i][k] * B[k][j];
}
}
}
}
int main() {
float a[N][K];
float b[K][M];
float c[N][M];
matmul(a, b, c, N, M, K);
DSPF_sp_mat_trans_cplx(a, N, M, b);
return 0;
}
```
cgeist test.c -S | polygeist-opt --raise-scf-to-affine --affine-parallelize result:
```
func.func @matmul(%arg0: memref, %arg1: memref, %arg2: memref, %arg3: i32, %arg4: i32, %arg5: i32) attributes {llvm.linkage = #llvm.linkage} {
%0 = arith.index_cast %arg3 : i32 to index
%1 = arith.index_cast %arg4 : i32 to index
%2 = arith.index_cast %arg5 : i32 to index
affine.for %arg6 = 0 to %0 {
affine.for %arg7 = 0 to %1 {
affine.for %arg8 = 0 to %2 {
%3 = memref.load %arg0[%arg6, %arg8] : memref
%4 = memref.load %arg1[%arg8, %arg7] : memref
%5 = arith.mulf %3, %4 : f32
%6 = memref.load %arg2[%arg6, %arg7] : memref
%7 = arith.addf %6, %5 : f32
memref.store %7, %arg2[%arg6, %arg7] : memref
}
}
}
return
}
func.func @DSPF_sp_mat_trans_cplx(%arg0: memref, %arg1: i32, %arg2: i32, %arg3: memref) attributes {llvm.linkage = #llvm.linkage} {
%c1_i32 = arith.constant 1 : i32
%c2_i32 = arith.constant 2 : i32
%0 = arith.index_cast %arg2 : i32 to index
%1 = arith.index_cast %arg1 : i32 to index
affine.for %arg4 = 0 to %0 {
%2 = arith.index_cast %arg4 : index to i32
%3 = arith.muli %2, %arg1 : i32
affine.for %arg5 = 0 to %1 {
%4 = arith.index_cast %arg5 : index to i32
%5 = arith.addi %3, %4 : i32
%6 = arith.muli %5, %c2_i32 : i32
%7 = arith.index_cast %6 : i32 to index
%8 = arith.muli %arg2, %4 : i32
%9 = arith.addi %2, %8 : i32
%10 = arith.muli %9, %c2_i32 : i32
%11 = arith.index_cast %10 : i32 to index
%12 = memref.load %arg0[%11] : memref
memref.store %12, %arg3[%7] : memref
%13 = arith.addi %6, %c1_i32 : i32
%14 = arith.index_cast %13 : i32 to index
%15 = arith.addi %10, %c1_i32 : i32
%16 = arith.index_cast %15 : i32 to index
%17 = memref.load %arg0[%16] : memref
memref.store %17, %arg3[%14] : memref
}
}
return
}
```
cgeist test.c -S --raise-scf-to-affine | polygeist-opt --affine-parallelize result:
```
func.func @matmul(%arg0: memref, %arg1: memref, %arg2: memref, %arg3: i32, %arg4: i32, %arg5: i32) attributes {llvm.linkage = #llvm.linkage} {
%0 = arith.index_cast %arg3 : i32 to index
%1 = arith.index_cast %arg4 : i32 to index
%2 = arith.index_cast %arg5 : i32 to index
affine.parallel (%arg6) = (0) to (symbol(%0)) {
affine.parallel (%arg7) = (0) to (symbol(%1)) {
affine.for %arg8 = 0 to %2 {
%3 = affine.load %arg0[%arg6, %arg8] : memref
%4 = affine.load %arg1[%arg8, %arg7] : memref
%5 = arith.mulf %3, %4 : f32
%6 = affine.load %arg2[%arg6, %arg7] : memref
%7 = arith.addf %6, %5 : f32
affine.store %7, %arg2[%arg6, %arg7] : memref
}
}
}
return
}
func.func @DSPF_sp_mat_trans_cplx(%arg0: memref, %arg1: i32, %arg2: i32, %arg3: memref) attributes {llvm.linkage = #llvm.linkage} {
%0 = arith.index_cast %arg2 : i32 to index
%1 = arith.index_cast %arg1 : i32 to index
affine.for %arg4 = 0 to %0 {
affine.for %arg5 = 0 to %1 {
%2 = affine.load %arg0[%arg4 * 2 + (%arg5 * symbol(%0)) * 2] : memref
affine.store %2, %arg3[%arg5 * 2 + (%arg4 * symbol(%1)) * 2] : memref
%3 = affine.load %arg0[%arg4 * 2 + (%arg5 * symbol(%0)) * 2 + 1] : memref
affine.store %3, %arg3[%arg5 * 2 + (%arg4 * symbol(%1)) * 2 + 1] : memref
}
}
return
}
}
```
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the test.c reproducer and run the two cgeist/polygeist-opt command sequences using --raise-scf-to-affine and --affine-parallelize. Compare the generated affine loops for DSPF_sp_mat_trans_cplx and matmul, then trace the raise-to-affine and affine-parallelize entry points. Done means the transpose function is parallelized consistently without regressing matmul.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, cpp
- Domain
- compilers, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100