Skip to content

Commit 028f60b

Browse files
authored
[fir] Lower full global initialization with dense attribute
1 parent 04ebc8f commit 028f60b

File tree

7 files changed

+172
-0
lines changed

7 files changed

+172
-0
lines changed

flang/include/flang/Optimizer/Dialect/FIRTypes.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,9 @@ def fir_SequenceType : FIR_Type<"Sequence", "array"> {
456456

457457
// The value `-1` represents an unknown extent for a dimension
458458
static constexpr Extent getUnknownExtent() { return -1; }
459+
460+
// Get the number of elements.
461+
std::size_t getNumElements() const;
459462
}];
460463
}
461464

flang/lib/Optimizer/CodeGen/CodeGen.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2425,10 +2425,49 @@ struct GlobalOpConversion : public FIROpConversion<fir::GlobalOp> {
24252425
loc, tyAttr, isConst, linkage, global.sym_name(), initAttr);
24262426
auto &gr = g.getInitializerRegion();
24272427
rewriter.inlineRegionBefore(global.region(), gr, gr.end());
2428+
if (!gr.empty()) {
2429+
// Replace insert_on_range with a constant dense attribute if the
2430+
// initialization is on the full range.
2431+
auto insertOnRangeOps = gr.front().getOps<fir::InsertOnRangeOp>();
2432+
for (auto insertOp : insertOnRangeOps) {
2433+
if (isFullRange(insertOp.coor(), insertOp.getType())) {
2434+
auto seqTyAttr = convertType(insertOp.getType());
2435+
auto op = insertOp.val().getDefiningOp();
2436+
auto constant = mlir::dyn_cast<mlir::ConstantOp>(op);
2437+
if (!constant) {
2438+
auto convertOp = mlir::dyn_cast<fir::ConvertOp>(op);
2439+
if (!convertOp)
2440+
continue;
2441+
constant =
2442+
cast<mlir::ConstantOp>(convertOp.value().getDefiningOp());
2443+
}
2444+
mlir::Type vecType = mlir::VectorType::get(
2445+
insertOp.getType().getShape(), constant.getType());
2446+
auto denseAttr = mlir::DenseElementsAttr::get(
2447+
vecType.cast<ShapedType>(), constant.getValue());
2448+
rewriter.setInsertionPointAfter(insertOp);
2449+
rewriter.replaceOpWithNewOp<mlir::ConstantOp>(insertOp, seqTyAttr,
2450+
denseAttr);
2451+
}
2452+
}
2453+
}
24282454
rewriter.eraseOp(global);
24292455
return success();
24302456
}
24312457

2458+
bool isFullRange(mlir::ArrayAttr indexes, fir::SequenceType seqTy) const {
2459+
auto extents = seqTy.getShape();
2460+
if (indexes.size() / 2 != extents.size())
2461+
return false;
2462+
for (unsigned i = 0; i < indexes.size(); i+= 2) {
2463+
if (indexes[i].cast<IntegerAttr>().getInt() != 0)
2464+
return false;
2465+
if (indexes[i+1].cast<IntegerAttr>().getInt() != extents[i/2] - 1)
2466+
return false;
2467+
}
2468+
return true;
2469+
}
2470+
24322471
mlir::LLVM::Linkage convertLinkage(Optional<StringRef> optLinkage) const {
24332472
if (optLinkage.hasValue()) {
24342473
auto name = optLinkage.getValue();

flang/lib/Optimizer/Dialect/FIROps.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,8 @@ void fir::InsertOnRangeOp::build(mlir::OpBuilder &builder,
995995

996996
/// Range bounds must be nonnegative, and the range must not be empty.
997997
static mlir::LogicalResult verify(fir::InsertOnRangeOp op) {
998+
if (op.coor().size() < 2 || op.coor().size() % 2 != 0)
999+
return op.emitOpError("has uneven number of values in ranges");
9981000
bool rangeIsKnownToBeNonempty = false;
9991001
for (auto i = op.coor().end(), b = op.coor().begin(); i != b;) {
10001002
int64_t ub = (*--i).cast<IntegerAttr>().getInt();

flang/lib/Optimizer/Dialect/FIRType.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,20 @@ bool fir::SequenceType::hasConstantInterior() const {
806806
return true;
807807
}
808808

809+
size_t fir::SequenceType::getNumElements() const {
810+
if (hasUnknownShape())
811+
return getUnknownExtent();
812+
813+
size_t numElements = 1;
814+
for (auto extent : getShape()) {
815+
if (extent != getUnknownExtent())
816+
numElements = numElements * extent;
817+
else
818+
return getUnknownExtent();
819+
}
820+
return numElements;
821+
}
822+
809823
mlir::LogicalResult fir::SequenceType::verify(
810824
llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
811825
llvm::ArrayRef<int64_t> shape, mlir::Type eleTy,
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// RUN: tco --fir-to-llvm-ir %s | FileCheck %s
2+
3+
fir.global internal @_QEmask : !fir.array<32xi32> {
4+
%c0_i32 = constant 1 : i32
5+
%0 = fir.undefined !fir.array<32xi32>
6+
%2 = fir.insert_on_range %0, %c0_i32, [0 : index, 31 : index] : (!fir.array<32xi32>, i32) -> !fir.array<32xi32>
7+
fir.has_value %2 : !fir.array<32xi32>
8+
}
9+
10+
// CHECK: llvm.mlir.global internal @_QEmask() : !llvm.array<32 x i32> {
11+
// CHECK: [[VAL0:%.*]] = llvm.mlir.constant(1 : i32) : i32
12+
// CHECK: [[VAL1:%.*]] = llvm.mlir.undef : !llvm.array<32 x i32>
13+
// CHECK: [[VAL2:%.*]] = llvm.mlir.constant(dense<1> : vector<32xi32>) : !llvm.array<32 x i32>
14+
// CHECK: llvm.return [[VAL2]] : !llvm.array<32 x i32>
15+
// CHECK: }
16+
17+
fir.global internal @_QEmultiarray : !fir.array<32x32xi32> {
18+
%c0_i32 = constant 1 : i32
19+
%0 = fir.undefined !fir.array<32x32xi32>
20+
%2 = fir.insert_on_range %0, %c0_i32, [0 : index, 31 : index, 0 : index, 31 : index] : (!fir.array<32x32xi32>, i32) -> !fir.array<32x32xi32>
21+
fir.has_value %2 : !fir.array<32x32xi32>
22+
}
23+
24+
// CHECK: llvm.mlir.global internal @_QEmultiarray() : !llvm.array<32 x array<32 x i32>> {
25+
// CHECK: [[VAL0:%.*]] = llvm.mlir.constant(1 : i32) : i32
26+
// CHECK: [[VAL1:%.*]] = llvm.mlir.undef : !llvm.array<32 x array<32 x i32>>
27+
// CHECK: [[VAL2:%.*]] = llvm.mlir.constant(dense<1> : vector<32x32xi32>) : !llvm.array<32 x array<32 x i32>>
28+
// CHECK: llvm.return [[VAL2]] : !llvm.array<32 x array<32 x i32>>
29+
// CHECK: }
30+
31+
fir.global internal @_QEmasklogical : !fir.array<32768x!fir.logical<4>> {
32+
%true = constant true
33+
%0 = fir.undefined !fir.array<32768x!fir.logical<4>>
34+
%1 = fir.convert %true : (i1) -> !fir.logical<4>
35+
%2 = fir.insert_on_range %0, %1, [0 : index, 32767 : index] : (!fir.array<32768x!fir.logical<4>>, !fir.logical<4>) -> !fir.array<32768x!fir.logical<4>>
36+
fir.has_value %2 : !fir.array<32768x!fir.logical<4>>
37+
}
38+
39+
// CHECK: llvm.mlir.global internal @_QEmasklogical() : !llvm.array<32768 x i32> {
40+
// CHECK: [[VAL0:%.*]] = llvm.mlir.constant(true) : i1
41+
// CHECK: [[VAL1:%.*]] = llvm.mlir.undef : !llvm.array<32768 x i32>
42+
// CHECK: [[VAL2:%.*]] = llvm.sext [[VAL0]] : i1 to i32
43+
// CHECK: [[VAL3:%.*]] = llvm.mlir.constant(dense<true> : vector<32768xi1>) : !llvm.array<32768 x i32>
44+
// CHECK: llvm.return [[VAL3]] : !llvm.array<32768 x i32>
45+
// CHECK: }
46+
47+
fir.global internal @_QElookforme : !fir.type<_QTt{i:!fir.array<500xi32>,j:!fir.array<500xi32>}> {
48+
%c2_i32 = constant 2 : i32
49+
%c52_i32 = constant 52 : i32
50+
%0 = fir.undefined !fir.type<_QTt{i:!fir.array<500xi32>,j:!fir.array<500xi32>}>
51+
%1 = fir.undefined !fir.array<500xi32>
52+
%2 = fir.insert_on_range %1, %c2_i32, [0 : index, 499 : index] : (!fir.array<500xi32>, i32) -> !fir.array<500xi32>
53+
%3 = fir.insert_value %0, %2, ["i", !fir.type<_QTt{i:!fir.array<500xi32>,j:!fir.array<500xi32>}>] :(!fir.type<_QTt{i:!fir.array<500xi32>,j:!fir.array<500xi32>}>, !fir.array<500xi32>) -> !fir.type<_QTt{i:!fir.array<500xi32>,j:!fir.array<500xi32>}>
54+
%4 = fir.insert_on_range %1, %c52_i32, [0 : index, 499 : index] : (!fir.array<500xi32>, i32) -> !fir.array<500xi32>
55+
%5 = fir.insert_value %3, %4, ["j", !fir.type<_QTt{i:!fir.array<500xi32>,j:!fir.array<500xi32>}>] : (!fir.type<_QTt{i:!fir.array<500xi32>,j:!fir.array<500xi32>}>, !fir.array<500xi32>) -> !fir.type<_QTt{i:!fir.array<500xi32>,j:!fir.array<500xi32>}>
56+
fir.has_value %5 : !fir.type<_QTt{i:!fir.array<500xi32>,j:!fir.array<500xi32>}>
57+
}
58+
59+
// CHECK: llvm.mlir.global internal @_QElookforme() : !llvm.struct<"_QTt", (array<500 x i32>, array<500 x i32>)> {
60+
// CHECK: [[CST0:%.*]] = llvm.mlir.constant(2 : i32) : i32
61+
// CHECK: [[CST1:%.*]] = llvm.mlir.constant(52 : i32) : i32
62+
// CHECK: [[STRUCT:%.*]] = llvm.mlir.undef : !llvm.struct<"_QTt", (array<500 x i32>, array<500 x i32>)>
63+
// CHECK: [[ARR1:%.*]] = llvm.mlir.undef : !llvm.array<500 x i32>
64+
// CHECK: [[DENSE1:%.*]] = llvm.mlir.constant(dense<2> : vector<500xi32>) : !llvm.array<500 x i32>
65+
// CHECK: [[STRUCT1:%.*]] = llvm.insertvalue [[DENSE1]], [[STRUCT]][0 : i32] : !llvm.struct<"_QTt", (array<500 x i32>, array<500 x i32>)>
66+
// CHECK: [[DENSE2:%.*]] = llvm.mlir.constant(dense<52> : vector<500xi32>) : !llvm.array<500 x i32>
67+
// CHECK: [[STRUCT2:%.*]] = llvm.insertvalue [[DENSE2]], [[STRUCT1]][1 : i32] : !llvm.struct<"_QTt", (array<500 x i32>, array<500 x i32>)>
68+
// CHECK: llvm.return [[STRUCT2]] : !llvm.struct<"_QTt", (array<500 x i32>, array<500 x i32>)>
69+
// CHECK: }

flang/test/Fir/global.fir

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,28 @@ fir.global @str1 : !fir.char<1,6> {
3232
%1 = fir.string_lit "Hello!"(6) : !fir.char<1,6>
3333
fir.has_value %1 : !fir.char<1,6>
3434
}
35+
36+
// CHECK: @_QEmask = internal global [32 x i32] [i32 1, i32 1
37+
fir.global internal @_QEmask : !fir.array<32xi32> {
38+
%c0_i32 = constant 1 : i32
39+
%0 = fir.undefined !fir.array<32xi32>
40+
%2 = fir.insert_on_range %0, %c0_i32, [0 : index, 31 : index] : (!fir.array<32xi32>, i32) -> !fir.array<32xi32>
41+
fir.has_value %2 : !fir.array<32xi32>
42+
}
43+
44+
// CHECK: @_QEmultiarray = internal global [32 x [32 x i32]]
45+
fir.global internal @_QEmultiarray : !fir.array<32x32xi32> {
46+
%c0_i32 = constant 1 : i32
47+
%0 = fir.undefined !fir.array<32x32xi32>
48+
%2 = fir.insert_on_range %0, %c0_i32, [0 : index, 31 : index, 0 : index, 31 : index] : (!fir.array<32x32xi32>, i32) -> !fir.array<32x32xi32>
49+
fir.has_value %2 : !fir.array<32x32xi32>
50+
}
51+
52+
// CHECK: @_QEmasklogical = internal global [32768 x i32] [i32 -1, i32 -1,
53+
fir.global internal @_QEmasklogical : !fir.array<32768x!fir.logical<4>> {
54+
%true = constant true
55+
%0 = fir.undefined !fir.array<32768x!fir.logical<4>>
56+
%1 = fir.convert %true : (i1) -> !fir.logical<4>
57+
%2 = fir.insert_on_range %0, %1, [0 : index, 32767 : index] : (!fir.array<32768x!fir.logical<4>>, !fir.logical<4>) -> !fir.array<32768x!fir.logical<4>>
58+
fir.has_value %2 : !fir.array<32768x!fir.logical<4>>
59+
}

flang/test/Fir/invalid.fir

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,3 +498,23 @@ func @ugly_char_convert() {
498498
fir.char_convert %2 for %2 to %3 : !fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>, !fir.ref<!fir.array<?x!fir.char<2,?>>>
499499
return
500500
}
501+
502+
// -----
503+
504+
fir.global internal @_QEmultiarray : !fir.array<32x32xi32> {
505+
%c0_i32 = constant 1 : i32
506+
%0 = fir.undefined !fir.array<32x32xi32>
507+
// expected-error@+1 {{'fir.insert_on_range' op has uneven number of values in ranges}}
508+
%2 = fir.insert_on_range %0, %c0_i32, [0 : index, 31 : index, 0 : index] : (!fir.array<32x32xi32>, i32) -> !fir.array<32x32xi32>
509+
fir.has_value %2 : !fir.array<32x32xi32>
510+
}
511+
512+
// -----
513+
514+
fir.global internal @_QEmultiarray : !fir.array<32x32xi32> {
515+
%c0_i32 = constant 1 : i32
516+
%0 = fir.undefined !fir.array<32x32xi32>
517+
// expected-error@+1 {{'fir.insert_on_range' op has uneven number of values in ranges}}
518+
%2 = fir.insert_on_range %0, %c0_i32, [0 : index] : (!fir.array<32x32xi32>, i32) -> !fir.array<32x32xi32>
519+
fir.has_value %2 : !fir.array<32x32xi32>
520+
}

0 commit comments

Comments
 (0)