[flang-commits] [flang] [flang] Fix -debug crash from VScaleAttrPass (PR #180234)

via flang-commits flang-commits at lists.llvm.org
Fri Feb 6 09:12:29 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-fir-hlfir

Author: Philipp Rados (prados-oc)

<details>
<summary>Changes</summary>

This pass splits up the `vscaleRange` pass-option from the `VScaleAttrPass` into `vscaleMin` and `vscaleMax` respectively, since a `std::pair<>` cannot be used as a cli-option and crashes when running `flang -march=rv64gcv -O3 file.f90 -mmlir -debug`.

Since the options can now be set individually I added some error checking following the semantics described in the langref https://llvm.org/docs/LangRef.html#function-attributes.

I also added tests since there were none for only this pass before.

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


4 Files Affected:

- (modified) flang/include/flang/Optimizer/Transforms/Passes.td (+4-4) 
- (modified) flang/lib/Optimizer/Passes/Pipelines.cpp (+1-1) 
- (modified) flang/lib/Optimizer/Transforms/VScaleAttr.cpp (+21-5) 
- (added) flang/test/Transforms/vscale-attr.fir (+24) 


``````````diff
diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td
index c2d6526b558d2..0edcd31bb3aba 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.td
+++ b/flang/include/flang/Optimizer/Transforms/Passes.td
@@ -399,10 +399,10 @@ def VScaleAttr : Pass<"vscale-attr", "mlir::func::FuncOp"> {
      Set an attribute for the vscale range on functions, to allow scalable
      vector operations to be used on processors with variable vector length.
   }];
-  let options = [
-    Option<"vscaleRange", "vscale-range",
-           "std::pair<unsigned, unsigned>", /*default=*/"std::pair<unsigned, unsigned>{}",
-           "vector scale range">,
+  let options = [Option<"vscaleMin", "vscale-min", "unsigned", /*default=*/"1",
+                        "vector scale minimum value. Defaults to \"1\"">,
+                 Option<"vscaleMax", "vscale-max", "unsigned", /*default=*/"0",
+                        "vector scale maximum value. Defaults to \"0\"">,
   ];
 }
 
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
index 6812347a8d39b..ff87ff0975302 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -383,7 +383,7 @@ void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
   fir::addCompilerGeneratedNamesConversionPass(pm);
 
   if (config.VScaleMin != 0)
-    pm.addPass(fir::createVScaleAttr({{config.VScaleMin, config.VScaleMax}}));
+    pm.addPass(fir::createVScaleAttr({config.VScaleMin, config.VScaleMax}));
 
   // Add function attributes
   mlir::LLVM::framePointerKind::FramePointerKind framePointerKind;
diff --git a/flang/lib/Optimizer/Transforms/VScaleAttr.cpp b/flang/lib/Optimizer/Transforms/VScaleAttr.cpp
index 54a2456e77366..5c82b665f751a 100644
--- a/flang/lib/Optimizer/Transforms/VScaleAttr.cpp
+++ b/flang/lib/Optimizer/Transforms/VScaleAttr.cpp
@@ -33,9 +33,11 @@
 #include "mlir/Transforms/GreedyPatternRewriteDriver.h"
 #include "mlir/Transforms/RegionUtils.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 
 #include <algorithm>
+#include <mlir/IR/Diagnostics.h>
 
 namespace fir {
 #define GEN_PASS_DEF_VSCALEATTR
@@ -49,7 +51,8 @@ namespace {
 class VScaleAttrPass : public fir::impl::VScaleAttrBase<VScaleAttrPass> {
 public:
   VScaleAttrPass(const fir::VScaleAttrOptions &options) {
-    vscaleRange = options.vscaleRange;
+    vscaleMin = options.vscaleMin;
+    vscaleMax = options.vscaleMax;
   }
   VScaleAttrPass() {}
   void runOnOperation() override;
@@ -63,16 +66,29 @@ void VScaleAttrPass::runOnOperation() {
 
   LLVM_DEBUG(llvm::dbgs() << "Func-name:" << func.getSymName() << "\n");
 
+  if (!llvm::isPowerOf2_32(vscaleMin)) {
+    LLVM_DEBUG(
+        llvm::dbgs()
+        << "VScaleAttr: vscaleMin has to be a power-of-two greater than 0\n");
+    return;
+  }
+
+  if (vscaleMax != 0 &&
+      (!llvm::isPowerOf2_32(vscaleMax) || (vscaleMin > vscaleMax))) {
+    LLVM_DEBUG(llvm::dbgs() << "VScaleAttr: vscaleMax has to be a power-of-two "
+                               "greater-than-or-equal to min or 0 to signify "
+                               "an unbounded maximum\n");
+    return;
+  }
+
   auto context = &getContext();
 
   auto intTy = mlir::IntegerType::get(context, 32);
 
-  assert(vscaleRange.first && "VScaleRange minimum should be non-zero");
-
   func->setAttr("vscale_range",
                 mlir::LLVM::VScaleRangeAttr::get(
-                    context, mlir::IntegerAttr::get(intTy, vscaleRange.first),
-                    mlir::IntegerAttr::get(intTy, vscaleRange.second)));
+                    context, mlir::IntegerAttr::get(intTy, vscaleMin),
+                    mlir::IntegerAttr::get(intTy, vscaleMax)));
 
   LLVM_DEBUG(llvm::dbgs() << "=== End " DEBUG_TYPE " ===\n");
 }
diff --git a/flang/test/Transforms/vscale-attr.fir b/flang/test/Transforms/vscale-attr.fir
new file mode 100644
index 0000000000000..59d0a4809f6c9
--- /dev/null
+++ b/flang/test/Transforms/vscale-attr.fir
@@ -0,0 +1,24 @@
+// RUN: fir-opt --vscale-attr %s | FileCheck %s --check-prefix=CHECK-DEFAULT
+// RUN: fir-opt --vscale-attr="vscale-min=4" %s | FileCheck %s --check-prefix=CHECK-MIN
+// RUN: fir-opt --vscale-attr="vscale-max=16" %s | FileCheck %s --check-prefix=CHECK-MAX
+// RUN: fir-opt --vscale-attr="vscale-min=8 vscale-max=16" %s | FileCheck %s --check-prefix=CHECK-BOTH
+// RUN: fir-opt --vscale-attr="vscale-min=8 vscale-max=8" %s | FileCheck %s --check-prefix=CHECK-EQUAL
+// RUN: fir-opt --vscale-attr="vscale-min=0 vscale-max=4" -debug %s 2>&1 | FileCheck %s --check-prefix=VSCALE-MIN-0
+// RUN: fir-opt --vscale-attr="vscale-min=3 vscale-max=4" -debug %s 2>&1 | FileCheck %s --check-prefix=VSCALE-MIN-NO-PO2
+// RUN: fir-opt --vscale-attr="vscale-max=6" -debug %s 2>&1 | FileCheck %s --check-prefix=VSCALE-MAX-NO-PO2
+// RUN: fir-opt --vscale-attr="vscale-min=16 vscale-max=8" -debug %s 2>&1 | FileCheck %s --check-prefix=VSCALE-MIN-GREATER
+
+
+// CHECK-DEFAULT: attributes {vscale_range = #llvm.vscale_range<minRange = 1 : i32, maxRange = 0 : i32>}
+// CHECK-MIN: attributes {vscale_range = #llvm.vscale_range<minRange = 4 : i32, maxRange = 0 : i32>}
+// CHECK-MAX: attributes {vscale_range = #llvm.vscale_range<minRange = 1 : i32, maxRange = 16 : i32>}
+// CHECK-BOTH: attributes {vscale_range = #llvm.vscale_range<minRange = 8 : i32, maxRange = 16 : i32>}
+// CHECK-EQUAL: attributes {vscale_range = #llvm.vscale_range<minRange = 8 : i32, maxRange = 8 : i32>}
+
+// VSCALE-MIN-0:      VScaleAttr: vscaleMin has to be a power-of-two greater than 0
+// VSCALE-MIN-NO-PO2: VScaleAttr: vscaleMin has to be a power-of-two greater than 0
+// VSCALE-MAX-NO-PO2: VScaleAttr: vscaleMax has to be a power-of-two greater-than-or-equal to min or 0 to signify an unbounded maximum
+// VSCALE-MIN-GREATER: VScaleAttr: vscaleMax has to be a power-of-two greater-than-or-equal to min or 0 to signify an unbounded maximum
+func.func @_QPtest(%arg0: !fir.ref<i32> {fir.bindc_name = "x"}) {
+  return
+}
\ No newline at end of file

``````````

</details>


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


More information about the flang-commits mailing list