@mehdi_amini I’ve revised the statement to say we directly lower Clang AST to arith/scf/control flow/etc as opposed to directly lowering Clang AST, if that clarifies things?
Regarding your polyhedral comment, Polygeist supports far more than just the polyhedral parts of the program (aiming to lower all of the C/C++ code [which notably is incomplete in various places, such as virtual methods / destructors / ABI mismatch at the moment]). However, if something is capable of being represented by affine (i.e. polyhedral code) Polygeist will raise it to that, if not it will remain scf, as an example. To date the largest program we have tested is the PyTorch binary operator file, which as it also includes aten/libstdc++/others, results in ~850K lines of MLIR after optimization (here pytorchbin.mlir.txt - Google Drive if you’re curious, certainly would make a good compile-time test).
Some snippets of general non-polyhedral code and the corresponding Polygeist output:
int fib(int n) {
if (n <= 2) return 1;
return fib(n-1) + fib(n-2);
}
func @fib(%arg0: i32) -> i32 attributes {llvm.linkage = #llvm.linkage<external>} {
%c2_i32 = arith.constant 2 : i32
%c1_i32 = arith.constant 1 : i32
%c-1_i32 = arith.constant -1 : i32
%c-2_i32 = arith.constant -2 : i32
%0 = arith.cmpi sle, %arg0, %c2_i32 : i32
%1 = scf.if %0 -> (i32) {
scf.yield %c1_i32 : i32
} else {
%2 = arith.addi %arg0, %c-1_i32 : i32
%3 = call @fib(%2) : (i32) -> i32
%4 = arith.addi %arg0, %c-2_i32 : i32
%5 = call @fib(%4) : (i32) -> i32
%6 = arith.addi %3, %5 : i32
scf.yield %6 : i32
}
return %1 : i32
}
int gcd(int m, int n) {
while (n > 0) {
int r = m % n;
m = n;
n = r;
}
return m;
}
func @gcd(%arg0: i32, %arg1: i32) -> i32
%c0_i32 = arith.constant 0 : i32
%0:2 = scf.while (%arg2 = %arg1, %arg3 = %arg0) : (i32, i32) -> (i32, i32) {
%1 = arith.cmpi sgt, %arg2, %c0_i32 : i32
scf.condition(%1) %arg3, %arg2 : i32, i32
} do {
^bb0(%arg2: i32, %arg3: i32): // no predecessors
%1 = arith.remsi %arg2, %arg3 : i32
scf.yield %1, %arg3 : i32, i32
}
return %0#0 : i32
}
Structs (https://github.com/wsmoses/Polygeist/blob/main/tools/mlir-clang/Test/Verification/classrefmem.cpp)
Inheritance (https://github.com/wsmoses/Polygeist/blob/main/tools/mlir-clang/Test/Verification/virt.cpp)
Advanced OpenMP (Polygeist/omp2.c at 7c26e71fab863552e4a3890dd4cc5eda91fa5b3c · llvm/Polygeist · GitHub)
Templates (https://github.com/wsmoses/Polygeist/blob/main/tools/mlir-clang/Test/Verification/twotemplatevardecls.cpp)
Templated Classes (Polygeist/caff.cpp at 7c26e71fab863552e4a3890dd4cc5eda91fa5b3c · llvm/Polygeist · GitHub)
Lambda functions (https://github.com/wsmoses/Polygeist/blob/main/tools/mlir-clang/Test/Verification/capture.cpp)
@clattner There are certainly design choices we made to do this, which we hope being an incubator project will better allow us to discuss as a community. It is unclear if the decisions made were the best ones to make, but hopefully having an existing end-to-end flow as an incubator enables anyone who wants to explore a different design a relatively easy way to try their design out.
As one example, in C/C++ it is possible to return from any point in the program. However, structured control flow does not support an “immediate exist from all of the ancestor scope” operations (and for good reason), so we chose to create a variable that denotes whether a return has occurred and guard all statements with an scf.if that check thats flag. We also have similar flags to enable break/continue in loops. Relatedly this is why I have been sending numerous scf.if and similar canonicalization patches for you to review @medhi_amini @rriddle 
Here’s the “immediate” unoptimized and optimized IR output of an example for the return case:
void compute(int x) {
A();
if (x == 0) {
B();
return;
}
C();
}
func @compute(%arg0: i32) attributes {llvm.linkage = #llvm.linkage<external>} {
%0 = memref.alloca() : memref<1xi32>
%1 = memref.cast %0 : memref<1xi32> to memref<?xi32>
%c0 = arith.constant 0 : index
%2 = llvm.mlir.undef : i32
memref.store %2, %1[%c0] : memref<?xi32>
%c0_0 = arith.constant 0 : index
memref.store %arg0, %1[%c0_0] : memref<?xi32>
%true = arith.constant true
%3 = memref.alloca() : memref<i1>
%4 = memref.alloca() : memref<i1>
memref.store %true, %4[] : memref<i1>
memref.store %true, %3[] : memref<i1>
%5 = memref.load %3[] : memref<i1>
scf.if %5 {
scf.execute_region {
call @A() : () -> ()
scf.yield
}
}
%6 = memref.load %3[] : memref<i1>
scf.if %6 {
scf.execute_region {
%8 = memref.load %3[] : memref<i1>
scf.if %8 {
scf.execute_region {
%c0_1 = arith.constant 0 : index
%9 = memref.load %1[%c0_1] : memref<?xi32>
%c0_i32 = arith.constant 0 : i32
%10 = arith.cmpi eq, %9, %c0_i32 : i32
%11 = arith.extsi %10 : i1 to i32
%c0_i32_2 = arith.constant 0 : i32
%12 = arith.cmpi ne, %11, %c0_i32_2 : i32
scf.if %12 {
%13 = memref.load %3[] : memref<i1>
scf.if %13 {
scf.execute_region {
call @B() : () -> ()
scf.yield
}
}
%14 = memref.load %3[] : memref<i1>
scf.if %14 {
scf.execute_region {
%15 = memref.load %3[] : memref<i1>
scf.if %15 {
scf.execute_region {
%false = arith.constant false
memref.store %false, %3[] : memref<i1>
memref.store %false, %4[] : memref<i1>
scf.yield
}
}
scf.yield
}
}
}
scf.yield
}
}
scf.yield
}
}
%7 = memref.load %3[] : memref<i1>
scf.if %7 {
scf.execute_region {
call @C() : () -> ()
scf.yield
}
}
return
}
}
After optimization:
func @compute(%arg0: i32) attributes {llvm.linkage = #llvm.linkage<external>} {
%c0_i32 = arith.constant 0 : i32
call @A() : () -> ()
%0 = arith.cmpi eq, %arg0, %c0_i32 : i32
scf.if %0 {
call @B() : () -> ()
} else {
call @C() : () -> ()
}
return
}
@River707 I agree in trying to get this in a category with broader visibility, but I’m not exactly sure how/where to do so on discourse. I was seemingly only allowed to select one primary category (MLIR) and I saw there was a secondary tag I could add to clang (which I added), but that’s not the same as the clang category it seems. I also considered making this in the incubator category, but that also felt like it wouldn’t get appropriate visibility. Happy to move/add things and please forgive my relative lack of discourse skills.