[RFC] Adding more power operations into Math dialect


I would like to get some feedback on the following patches:

The intention is to have operations for representing Fortran exponentiation operator (**) in FIR/MLIR after Flang lowering. Currently Math dialect has PowFOp that has both base and power operands of floating-point-like types. Fortran exponentiation may take the following operand types (fp, fp), (fp, sint), (sint, sint), and the same for complex data types, but this is for future work.

The fp operands may be 16, 32, 64, 80, 128-bit wide. The sint operands may be 8, 16, 32, 64 and 128-bit wide.

I propose adding IPowSI and FPowSI operations to support representing the exponentiation. The reason for distinguishing IPowSI from the operations with the FP base is that it has no floating point related effects whatsoever. The reason for distinguishing the existing PowF and FPowSI is that their constant folding and conversions to LLVM dialect are somewhat different, but I do not reallty have a strong a point here.

@kiranchandramohan noted that having SI suffix does not make much sense unless we are going to have a UI version. So I think I am going to change SI to just I.

I have some questions about the FPowSI lowering to LLVM dialect in Login

  1. It turns out that llvm.powi.* intrinsic supports only i32 power operand (see verification in LegalizeDAG.cpp), even though the “corresponding” LLVM dialect PowIOp is defined quite loosely allowing any operand type. Which one is right?
  2. Does it make sense to lower Math’s FPowSI into LLVM’s PowIOp for the supported cases and use an alternative implementation (like here) otherwise?

Thank you,

The LLVM dialects goal is to closely model actuall LLVM, so when there’s a discrepancy between the two, it’s always the LLVM dialect that needs fixing. That said, according to the LLVM language reference llvm.powi.* as taking any integer type, and making the target decide whether it is legal or not, only guaranteeing that at least sizeof(int) is allowed. For that reason I think the LLVM dialect should probabaly keep it unrestricted.

Would this then call pow or powf in libc or would it have a an inline implementation such as the patch you posted?

For that reason I think the LLVM dialect should probabaly keep it unrestricted.

Okay, thank you for the clarification. Then it sounds like MathToLLVM convertor may only rely on llvm::PowIOp supporting only i32 power operand, unless there is a way to query the target for the supported power operand types during this conversion. I am not aware whether this is possible currently.

Would this then call pow or powf in libc or would it have a an inline implementation such as the patch you posted?

Representing power operation with integer power operand via libm is possible with extending the power operand bitwidth, e.g. POWER(base, power_i32) can be computed via double-precision libm’s pow((double)base, (double)power_i32). I am not in favor of such a conversion mainly due to performance reasons.

So I see two alternatives to this:

  1. Convert FPowSI to a call of the inlined implementation always, OR
  2. Convert FPowSI with i32 power operand to llvm::PowIOp (which then will be transformed into a call to LLVM’s compiler-rt/libgcc __powi* function), otherwise, convert it into a call of the inlined implementation.

I prefer the second one even though it is kind of a fragmented solution, but I expect better performance from the specialized handling of llvm.powi.* in LLVM backend.

I split D129809 into three patches, so here is the current set of patches ready for review:

Please help review.