llvm / llvm/Polygeist

affine.for can't be convert to affine.parallel if scf is raised through polygeist-opt

Open
#314 0 comments 0 reactions 0 assignees View on GitHub

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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.