[flang-commits] [flang] [flang][CodeGen] Fix element type of folded insert_on_range initializers (PR #218587)

via flang-commits flang-commits at lists.llvm.org
Mon Aug 24 22:58:14 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-codegen

Author: Christian Ulmann (Dinistro)

<details>
<summary>Changes</summary>

`GlobalOpConversion` folds a full-range `fir.insert_on_range` into a dense constant. When the inserted value comes from a `fir.convert`, the fold reached through the conversion and built the dense attribute from the type of the *source* constant. For a `logical(4)` array initialized to `.true.` this produced

  llvm.mlir.constant(dense<true> : vector<32768xi1>) : !llvm.array<32768 x i32>

where the attribute element type `i1` disagrees with the result element type `i32`. Translation to LLVM IR ignores the attribute type and uses the result type, so the emitted global is still correct today, but the IR is malformed and any consumer that trusts the attribute type sees the wrong element width.

Build the dense attribute from the converted element type instead. A logical conversion normalizes its operand to a canonical 0/1 (see `ConvertOpConversion`), so apply the same normalization here; any other mismatching conversion is left to the regular lowering.

Note that this is a preparation to strengthen the verifiers of `llvm.mlir.constant`.

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


2 Files Affected:

- (modified) flang/lib/Optimizer/CodeGen/CodeGen.cpp (+25-5) 
- (modified) flang/test/Fir/global-initialization.fir (+1-1) 


``````````diff
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 7696f5f900c5e..7274fecc5e056 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -3757,19 +3757,39 @@ struct GlobalOpConversion : public fir::FIROpConversion<fir::GlobalOp> {
       for (auto insertOp : insertOnRangeOps) {
         if (insertOp.isFullRange()) {
           auto seqTyAttr = convertType(insertOp.getType());
+          // The dense attribute must use the converted element type of the
+          // array, not the type of whatever constant feeds the insertion.
+          mlir::Type elementType = convertType(insertOp.getType().getEleTy());
           auto *op = insertOp.getVal().getDefiningOp();
           auto constant = mlir::dyn_cast<mlir::arith::ConstantOp>(op);
+          fir::ConvertOp convertOp;
           if (!constant) {
-            auto convertOp = mlir::dyn_cast<fir::ConvertOp>(op);
+            convertOp = mlir::dyn_cast<fir::ConvertOp>(op);
             if (!convertOp)
               continue;
-            constant = mlir::cast<mlir::arith::ConstantOp>(
+            constant = mlir::dyn_cast<mlir::arith::ConstantOp>(
                 convertOp.getValue().getDefiningOp());
+            if (!constant)
+              continue;
+          }
+          mlir::TypedAttr valueAttr = constant.getValue();
+          if (valueAttr.getType() != elementType) {
+            // Reaching through a `fir.convert` leaves the constant with the
+            // source type. Only a logical conversion is folded here, and it
+            // normalizes the value to a canonical 0/1, see ConvertOpConversion.
+            auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(valueAttr);
+            auto intType = mlir::dyn_cast<mlir::IntegerType>(elementType);
+            if (!intAttr || !intType || !convertOp ||
+                (!mlir::isa<fir::LogicalType>(convertOp.getType()) &&
+                 !mlir::isa<fir::LogicalType>(convertOp.getValue().getType())))
+              continue;
+            valueAttr = mlir::IntegerAttr::get(
+                intType, intAttr.getValue().isZero() ? 0 : 1);
           }
-          mlir::Type vecType = mlir::VectorType::get(
-              insertOp.getType().getShape(), constant.getType());
+          mlir::Type vecType =
+              mlir::VectorType::get(insertOp.getType().getShape(), elementType);
           auto denseAttr = mlir::DenseElementsAttr::get(
-              mlir::cast<mlir::ShapedType>(vecType), constant.getValue());
+              mlir::cast<mlir::ShapedType>(vecType), valueAttr);
           rewriter.setInsertionPointAfter(insertOp);
           rewriter.replaceOpWithNewOp<mlir::arith::ConstantOp>(
               insertOp, seqTyAttr, denseAttr);
diff --git a/flang/test/Fir/global-initialization.fir b/flang/test/Fir/global-initialization.fir
index 98c842c4b7551..740429f320ee0 100644
--- a/flang/test/Fir/global-initialization.fir
+++ b/flang/test/Fir/global-initialization.fir
@@ -41,7 +41,7 @@ fir.global internal @_QEmasklogical : !fir.array<32768x!fir.logical<4>> {
 // CHECK:   [[VAL0:%.*]] = llvm.mlir.constant(true) : i1
 // CHECK:   [[VAL1:%.*]] = llvm.mlir.undef : !llvm.array<32768 x i32>
 // CHECK:   [[VAL2:%.*]] = llvm.mlir.constant(1 : i32) : i32
-// CHECK:   [[VAL3:%.*]] = llvm.mlir.constant(dense<true> : vector<32768xi1>) : !llvm.array<32768 x i32>
+// CHECK:   [[VAL3:%.*]] = llvm.mlir.constant(dense<1> : vector<32768xi32>) : !llvm.array<32768 x i32>
 // CHECK:   llvm.return [[VAL3]] : !llvm.array<32768 x i32>
 // CHECK: }
 

``````````

</details>


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


More information about the flang-commits mailing list