Hi there,
I tried to call a simple 2D memref load-store MLIR function from C, while the result looks weird -
The MLIR code:
// File name: main.mlir
func @load_store_2d(%A : memref<?x?xf32>, %B : memref<?x?xf32>) {
%c0 = constant 0 : index
%c1 = constant 1 : index
%d0 = dim %A, %c0 : memref<?x?xf32>
%d1 = dim %A, %c1 : memref<?x?xf32>
affine.for %i = 0 to %d0 {
affine.for %j = 0 to %d1 {
%0 = affine.load %A[%i, %j] : memref<?x?xf32>
affine.store %0, %B[%i, %j] : memref<?x?xf32>
}
}
return
}
The C code:
// File name: main.c
#include <stdio.h>
struct TwoDMemrefF32 {
float *ptrToData;
float *alignedPtrToData;
long offset;
long shape[2];
long stride[2];
};
#define M 6
#define N 8
extern void _mlir_ciface_load_store_2d(struct TwoDMemrefF32 *,
struct TwoDMemrefF32 *);
int main(int argc, char *argv[]) {
int i, j;
float A[M][N], B[M][N];
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
A[i][j] = ((float)i + j) / (i + j + 1);
B[i][j] = (float)0;
printf("%8.6f ", A[i][j]);
}
printf("\n");
}
printf("\n");
struct TwoDMemrefF32 A_mem = {&A[0][0], &A[0][0], 0, {M, N}, {1, 1}};
struct TwoDMemrefF32 B_mem = {&B[0][0], &B[0][0], 0, {M, N}, {1, 1}};
_mlir_ciface_load_store_2d(&A_mem, &B_mem);
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++)
printf("%8.6f ", B[i][j]);
printf("\n");
}
return 0;
}
The script to compile and run:
#!/usr/bin/bash
# File name: run.sh
NAME="$1"
MAIN_FILE="${NAME}.c"
MAIN_LLVMIR_FILE="${NAME}.ll"
MLIR_FILE="${NAME}.mlir"
MLIR_LLVM_FILE="${NAME}_llvm.mlir"
MLIR_LLVMIR_FILE="${NAME}_mlir.ll"
MLIR_BC_FILE="${NAME}_mlir.bc"
RESULT_BC_FILE="result.bc"
RESULT_OBJ_FILE="result.o"
EXE=main
# NOTE: change this to your LLVM build bin directory.
LLVM_BINDIR="${PWD}/../../../../llvm/build/bin"
${LLVM_BINDIR}/mlir-opt \
--lower-affine \
--convert-scf-to-std \
--convert-std-to-llvm='emit-c-wrappers=1' \
"${MLIR_FILE}" \
-o "${MLIR_LLVM_FILE}"
${LLVM_BINDIR}/mlir-translate "${MLIR_LLVM_FILE}" --mlir-to-llvmir -o "${MLIR_LLVMIR_FILE}"
${LLVM_BINDIR}/llvm-as "${MLIR_LLVMIR_FILE}" -o "${MLIR_BC_FILE}"
${LLVM_BINDIR}/clang -emit-llvm "${MAIN_FILE}" -S -o "${MAIN_LLVMIR_FILE}"
${LLVM_BINDIR}/llvm-link "${MAIN_LLVMIR_FILE}" "${MLIR_LLVMIR_FILE}" -o "${RESULT_BC_FILE}"
${LLVM_BINDIR}/llc -filetype=obj "${RESULT_BC_FILE}"
${LLVM_BINDIR}/clang "${RESULT_OBJ_FILE}" -o "${EXE}"
"./${EXE}"
The result of compilation and running ./run.sh main
is -
warning: Linking two modules of different data layouts: 'main_mlir.ll' is '' whereas 'llvm-link' is 'e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128'
0.000000 0.500000 0.666667 0.750000 0.800000 0.833333 0.857143 0.875000
0.500000 0.666667 0.750000 0.800000 0.833333 0.857143 0.875000 0.888889
0.666667 0.750000 0.800000 0.833333 0.857143 0.875000 0.888889 0.900000
0.750000 0.800000 0.833333 0.857143 0.875000 0.888889 0.900000 0.909091
0.800000 0.833333 0.857143 0.875000 0.888889 0.900000 0.909091 0.916667
0.833333 0.857143 0.875000 0.888889 0.900000 0.909091 0.916667 0.923077
0.000000 0.500000 0.666667 0.750000 0.800000 0.833333 0.857143 0.875000
0.500000 0.666667 0.750000 0.800000 0.833333 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
The second block, which corresponds to the 2D memory that should load data from the first block, doesn’t exactly match its source.
I assume there might be some alignment issue, but I’m not entirely sure. Would anyone that has similar experience kindly point me why this may happen? Thanks in advance for any help
cc: @ftynse
Best regards
Ruizhe