Why some OpenMP ops only interoperate with llvm dialect?

I’m working with the omp dialect, and I’ve been exploring for a while how to perform a parallel reduction efficiently. At first I was trying to do the reduction by hand, but then I realized that there is a omp.reduction op which at first seemed very handy. However, by looking at the examples, I noticed that it only interoperates with the llvm dialect, e.g.:

%4 = llvm.alloca ...
...
omp.reduction %11, %4 : i32, !llvm.ptr<i32>

I’m working at the memref level, and the fact that the omp.reduction expects a llvm.ptr makes me question if there is something I’m overlooking or if there’s something I don’t fully understand. I also noticed this “unexpected low level” in the omp dialect with omp.threadprivate which always expects a llvm.ptr.

Is there a reason for this, or am I missing something? Is there an omp.reduction operation at the mlir level that can be lowered to the llvm dialect?

There is no such restriction. From the definition of the reduction operation, the arguments do not specify the LLVM types. Since llvm provides a ptr type, it is easy to write example with the llvm dialect hence you might have seen such examples.

def ReductionOp : OpenMP_Op<"reduction"> {
  let summary = "reduction construct";                   
  let description = [{
    Indicates the value that is produced by the current reduction-participating
    entity for a reduction requested in some ancestor. The reduction is
    identified by the accumulator, but the value of the accumulator may not be
    updated immediately.
  }];
      
  let arguments= (ins AnyType:$operand, OpenMP_PointerLikeType:$accumulator);
  let assemblyFormat = [{
    $operand `,` $accumulator attr-dict `:` type($operand) `,` type($accumulator)
  }];    
  let hasVerifier = 1;
} 
1 Like

Thanks for the fast response. My bad, I was having issues with omp.reduction and thought it was due to the op only working with llvm dialect but actually it was another problem unrelated to this.