diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index 7696f5f900c5e..cbe52bcddcb03 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -3755,25 +3755,41 @@ struct GlobalOpConversion : public fir::FIROpConversion { // initialization is on the full range. auto insertOnRangeOps = gr.front().getOps(); for (auto insertOp : insertOnRangeOps) { - if (insertOp.isFullRange()) { - auto seqTyAttr = convertType(insertOp.getType()); - auto *op = insertOp.getVal().getDefiningOp(); - auto constant = mlir::dyn_cast(op); - if (!constant) { - auto convertOp = mlir::dyn_cast(op); - if (!convertOp) - continue; - constant = mlir::cast( - convertOp.getValue().getDefiningOp()); - } - mlir::Type vecType = mlir::VectorType::get( - insertOp.getType().getShape(), constant.getType()); - auto denseAttr = mlir::DenseElementsAttr::get( - mlir::cast(vecType), constant.getValue()); - rewriter.setInsertionPointAfter(insertOp); - rewriter.replaceOpWithNewOp( - insertOp, seqTyAttr, denseAttr); + if (!insertOp.isFullRange()) + continue; + // 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()); + mlir::Value val = insertOp.getVal(); + // Logical constants reach the insertion through a `fir.convert`. + auto convertOp = val.getDefiningOp(); + if (convertOp) + val = convertOp.getValue(); + auto constant = val.getDefiningOp(); + if (!constant) + continue; + mlir::TypedAttr valueAttr = constant.getValue(); + if (valueAttr.getType() != elementType) { + // Looking through the `fir.convert` leaves the constant with the + // source type. Only an integer<->logical conversion is folded here: + // it normalizes any integer operand to a canonical 0/1, see + // ConvertOpConversion. Any other mismatching conversion is left to + // the regular lowering. + auto intAttr = mlir::dyn_cast(valueAttr); + auto intType = mlir::dyn_cast(elementType); + if (!intAttr || !intType || !convertOp || + (!mlir::isa(convertOp.getType()) && + !mlir::isa(convertOp.getValue().getType()))) + continue; + valueAttr = mlir::IntegerAttr::get( + intType, intAttr.getValue().isZero() ? 0 : 1); } + auto vecType = + mlir::VectorType::get(insertOp.getType().getShape(), elementType); + auto denseAttr = mlir::DenseElementsAttr::get(vecType, valueAttr); + rewriter.setInsertionPointAfter(insertOp); + rewriter.replaceOpWithNewOp( + insertOp, convertType(insertOp.getType()), denseAttr); } } diff --git a/flang/test/Fir/global-initialization.fir b/flang/test/Fir/global-initialization.fir index 98c842c4b7551..a683b46de2541 100644 --- a/flang/test/Fir/global-initialization.fir +++ b/flang/test/Fir/global-initialization.fir @@ -41,10 +41,25 @@ 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 : 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: } +// A logical conversion normalizes any integer operand to a canonical 0/1, not +// just an `i1` one, so the full-range fold must apply here as well. +fir.global internal @_QEmasklogicalkind : !fir.array<8x!fir.logical<8>> { + %c1_i32 = arith.constant 1 : i32 + %0 = fir.undefined !fir.array<8x!fir.logical<8>> + %1 = fir.convert %c1_i32 : (i32) -> !fir.logical<8> + %2 = fir.insert_on_range %0, %1 from (0) to (7) : (!fir.array<8x!fir.logical<8>>, !fir.logical<8>) -> !fir.array<8x!fir.logical<8>> + fir.has_value %2 : !fir.array<8x!fir.logical<8>> +} + +// CHECK: llvm.mlir.global internal @_QEmasklogicalkind() {addr_space = 0 : i32} : !llvm.array<8 x i64> { +// CHECK: [[VAL2:%.*]] = llvm.mlir.constant(dense<1> : vector<8xi64>) : !llvm.array<8 x i64> +// CHECK: llvm.return [[VAL2]] : !llvm.array<8 x i64> +// CHECK: } + fir.global internal @_QElookforme : !fir.type<_QTt{i:!fir.array<500xi32>,j:!fir.array<500xi32>}> { %c2_i32 = arith.constant 2 : i32 %c52_i32 = arith.constant 52 : i32