[flang-commits] [flang] [Flang][HLFIR] Lower PACK(array, .TRUE.) to hlfir.reshape (PR #220860)

via flang-commits flang-commits at lists.llvm.org
Mon Sep 7 06:54:28 PDT 2026


================
@@ -3068,6 +3069,71 @@ class DotProductConversion
   }
 };
 
+static std::optional<bool> getLogicalConstant(mlir::Value value) {
+  if (auto convertOp = value.getDefiningOp<fir::ConvertOp>())
+    value = convertOp.getValue();
+  if (auto cst = fir::getIntIfConstant(value))
+    return *cst != 0;
+  return std::nullopt;
+}
+
+class PackAsReshapeConversion : public mlir::OpRewritePattern<hlfir::PackOp> {
+public:
+  using mlir::OpRewritePattern<hlfir::PackOp>::OpRewritePattern;
+
+  llvm::LogicalResult
+  matchAndRewrite(hlfir::PackOp pack,
+                  mlir::PatternRewriter &rewriter) const override {
+    if (pack.getVector())
+      return rewriter.notifyMatchFailure(pack, "PACK with VECTOR");
+    hlfir::Entity mask{pack.getMask()};
+    if (mask.getRank() != 0)
+      return rewriter.notifyMatchFailure(pack, "non-scalar mask");
+    if (!getLogicalConstant(pack.getMask()).value_or(false))
+      return rewriter.notifyMatchFailure(pack, "mask is not .TRUE.");
+    hlfir::Entity array{pack.getArray()};
+    if (!fir::isa_trivial(array.getFortranElementType()) ||
+        array.isPolymorphic())
+      return rewriter.notifyMatchFailure(pack, "unsupported array type");
+
+    mlir::Location loc = pack.getLoc();
+    fir::FirOpBuilder builder{rewriter, pack.getOperation()};
+    builder.setIntegerOverflowFlags(mlir::arith::IntegerOverflowFlags::nuw);
+
+    llvm::SmallVector<mlir::Value, Fortran::common::maxRank> arrayExtents =
+        hlfir::genExtentsVector(loc, builder, array);
+    mlir::Type indexType = builder.getIndexType();
+    mlir::Value totalSize = builder.createIntegerConstant(loc, indexType, 1);
+    for (mlir::Value extent : arrayExtents)
+      totalSize = mlir::arith::MulIOp::create(
+          builder, loc, totalSize,
+          builder.createConvert(loc, indexType, extent));
+
+    mlir::Value one = builder.createIntegerConstant(loc, indexType, 1);
+    mlir::Value unitShape = fir::ShapeOp::create(builder, loc, one);
+    mlir::Type shapeExprType =
+        hlfir::ExprType::get(builder.getContext(), {1}, indexType,
----------------
jeanPerier wrote:

Do you know if there are precedents in using `hlfir.expr<..index>`?

If not, I am not sure we would allow it because the idea under hlfir.expr is that it is for objects that relates to Fortran types (for instance, for integers, I think we should be able to retrieve a KIND parameter from it).

Mapping index to a type code may lead to weird situations where we complain in the runtime about mismatching type code between index that were lowered to I64 and the related type code and index for which the type code is different (In the end, I think type codes should map to the same codes when the C type maps to the same types, but this is not the case right now and is a more complex change).

I am not vastly opposed to it if there are precedent, but I would otherwise advise building a sized hlfir.expr (maybe using getIntPtrType() to select the sized integer for it, or a new getSubscriptIntegerType to match the SubscriptInteger type used in Semantics for shape and extents)/


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


More information about the flang-commits mailing list