[Mlir-commits] [mlir] [mlir][MathToLLVM] Fix math.fpowi incorrectly being mapped to llvm.powi (PR #226089)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Thu Sep 24 02:35:21 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir

Author: Mattéo Rizza Murgier (matteo-rm)

<details>
<summary>Changes</summary>

`math.fpowi` allows vector exponents, while `llvm.intr.powi` only takes scalar exponents. This led to vector `math.fpowi` ops being lowered to invalid IR.

This PR adds support for constant splat exponents, and leaves other vector cases unconverted.

---
Full diff: https://github.com/llvm/llvm-project/pull/226089.diff


2 Files Affected:

- (modified) mlir/lib/Conversion/MathToLLVM/MathToLLVM.cpp (+54-2) 
- (modified) mlir/test/Conversion/MathToLLVM/math-to-llvm.mlir (+48) 


``````````diff
diff --git a/mlir/lib/Conversion/MathToLLVM/MathToLLVM.cpp b/mlir/lib/Conversion/MathToLLVM/MathToLLVM.cpp
index 29e1678bdd38a..ca7888a9aec76 100644
--- a/mlir/lib/Conversion/MathToLLVM/MathToLLVM.cpp
+++ b/mlir/lib/Conversion/MathToLLVM/MathToLLVM.cpp
@@ -15,6 +15,7 @@
 #include "mlir/Conversion/LLVMCommon/VectorPattern.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 #include "mlir/Dialect/Math/IR/Math.h"
+#include "mlir/IR/Matchers.h"
 #include "mlir/IR/TypeUtilities.h"
 #include "mlir/Pass/Pass.h"
 
@@ -95,8 +96,6 @@ using Log10OpLowering =
 using Log2OpLowering = ConvertFMFMathToLLVMPattern<math::Log2Op, LLVM::Log2Op>;
 using LogOpLowering = ConvertFMFMathToLLVMPattern<math::LogOp, LLVM::LogOp>;
 using PowFOpLowering = ConvertFMFMathToLLVMPattern<math::PowFOp, LLVM::PowOp>;
-using FPowIOpLowering =
-    ConvertFMFMathToLLVMPattern<math::FPowIOp, LLVM::PowIOp>;
 using RoundEvenOpLowering =
     ConvertFMFMathToLLVMPattern<math::RoundEvenOp, LLVM::RoundEvenOp>;
 using RoundOpLowering =
@@ -406,6 +405,59 @@ struct RsqrtOpLowering
   }
 };
 
+struct FPowIOpLowering
+    : public ConvertOpToLLVMPattern<math::FPowIOp,
+                                    /*FailOnUnsupportedFP=*/true> {
+  using ConvertOpToLLVMPattern<
+      math::FPowIOp, /*FailOnUnsupportedFP=*/true>::ConvertOpToLLVMPattern;
+
+  LogicalResult
+  matchAndRewrite(math::FPowIOp op, OpAdaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    const auto &typeConverter = *this->getTypeConverter();
+    auto llvmOperandType = typeConverter.convertType(op.getLhs().getType());
+    if (!llvmOperandType)
+      return failure();
+
+    auto loc = op.getLoc();
+    Value exponent = adaptor.getRhs();
+    if (isa<VectorType>(op.getRhs().getType())) {
+      SplatElementsAttr splatAttr;
+      if (!matchPattern(op.getRhs(), m_Constant(&splatAttr)))
+        return rewriter.notifyMatchFailure(op, "expected a splat exponent");
+
+      auto exponentType = typeConverter.convertType(
+          getElementTypeOrSelf(op.getRhs().getType()));
+      if (!exponentType)
+        return failure();
+      exponent = LLVM::ConstantOp::create(
+          rewriter, loc, exponentType,
+          rewriter.getIntegerAttr(exponentType,
+                                  splatAttr.getSplatValue<APInt>()));
+    }
+
+    ConvertFastMath<math::FPowIOp, LLVM::PowIOp> attrs(op);
+
+    if (!isa<LLVM::LLVMArrayType>(llvmOperandType)) {
+      rewriter.replaceOpWithNewOp<LLVM::PowIOp>(
+          op, TypeRange{llvmOperandType},
+          ValueRange{adaptor.getLhs(), exponent}, attrs.getProperties(),
+          attrs.getDiscardableAttrs());
+      return success();
+    }
+
+    return LLVM::detail::handleMultidimensionalVectors(
+        op.getOperation(), ValueRange{adaptor.getLhs()}, typeConverter,
+        [&](Type llvm1DVectorTy, ValueRange operands) {
+          return LLVM::PowIOp::create(rewriter, loc, TypeRange{llvm1DVectorTy},
+                                      ValueRange{operands[0], exponent},
+                                      attrs.getProperties(),
+                                      attrs.getDiscardableAttrs());
+        },
+        rewriter);
+  }
+};
+
 struct IsNaNOpLowering
     : public ConvertOpToLLVMPattern<math::IsNaNOp,
                                     /*FailOnUnsupportedFP=*/true> {
diff --git a/mlir/test/Conversion/MathToLLVM/math-to-llvm.mlir b/mlir/test/Conversion/MathToLLVM/math-to-llvm.mlir
index 3cb902a64f18b..3dd9d74ba7043 100644
--- a/mlir/test/Conversion/MathToLLVM/math-to-llvm.mlir
+++ b/mlir/test/Conversion/MathToLLVM/math-to-llvm.mlir
@@ -583,6 +583,54 @@ func.func @fpowi(%arg0 : f64, %arg1 : i32) {
   func.return
 }
 
+// -----
+
+// CHECK-LABEL: func @fpowi_splat_vector(
+// CHECK-SAME: vector<4xf32>
+func.func @fpowi_splat_vector(%arg0 : vector<4xf32>) {
+  // CHECK: %[[EXP:.*]] = llvm.mlir.constant(2 : i32) : i32
+  // CHECK: llvm.intr.powi(%arg0, %[[EXP]]) : (vector<4xf32>, i32) -> vector<4xf32>
+  %cst = arith.constant dense<2> : vector<4xi32>
+  %0 = math.fpowi %arg0, %cst : vector<4xf32>, vector<4xi32>
+  func.return
+}
+
+// -----
+
+// CHECK-LABEL: func @fpowi_splat_scalable_vector(
+// CHECK-SAME: vector<[4]xf32>
+func.func @fpowi_splat_scalable_vector(%arg0 : vector<[4]xf32>) {
+  // CHECK: %[[EXP:.*]] = llvm.mlir.constant(2 : i32) : i32
+  // CHECK: llvm.intr.powi(%arg0, %[[EXP]]) : (vector<[4]xf32>, i32) -> vector<[4]xf32>
+  %cst = arith.constant dense<2> : vector<[4]xi32>
+  %0 = math.fpowi %arg0, %cst : vector<[4]xf32>, vector<[4]xi32>
+  func.return
+}
+
+// -----
+
+// CHECK-LABEL: func @fpowi_multidim_vector(
+// CHECK-SAME: vector<4x4xf32>
+func.func @fpowi_multidim_vector(%arg0 : vector<4x4xf32>) {
+  // CHECK: %[[EXP:.*]] = llvm.mlir.constant(2 : i32) : i32
+  // CHECK: %[[EXTRACT:.*]] = llvm.extractvalue %{{.*}}[0] : !llvm.array<4 x vector<4xf32>>
+  // CHECK: %[[POWI:.*]] = llvm.intr.powi(%[[EXTRACT]], %[[EXP]]) : (vector<4xf32>, i32) -> vector<4xf32>
+  // CHECK: %[[INSERT:.*]] = llvm.insertvalue %[[POWI]], %{{.*}}[0] : !llvm.array<4 x vector<4xf32>>
+  %cst = arith.constant dense<2> : vector<4x4xi32>
+  %0 = math.fpowi %arg0, %cst : vector<4x4xf32>, vector<4x4xi32>
+  func.return
+}
+
+// -----
+
+// CHECK-LABEL: func @fpowi_non_splat_vector(
+// CHECK-SAME: vector<4xf32>
+func.func @fpowi_non_splat_vector(%arg0 : vector<4xf32>, %arg1 : vector<4xi32>) {
+  // CHECK: math.fpowi
+  // CHECK-NOT: llvm.intr.powi
+  %0 = math.fpowi %arg0, %arg1 : vector<4xf32>, vector<4xi32>
+  func.return
+}
 
 // -----
 

``````````

</details>


https://github.com/llvm/llvm-project/pull/226089


More information about the Mlir-commits mailing list