Skip to content

Commit d3bc3a0

Browse files
committed
[flang][codegen] ensure descriptor lower bounds are LBOUND compliant
Follow-up of https://reviews.llvm.org/D121488 to ensure all descriptors created inline complies with LBOUND requirement that the lower bound is `1` when the related dimension extent is zero. Both fir.xrebox and fir.xembox codegen is updated to enforce this constraint. Also upstream the "normalized lower bound" attribute that was added in fir-dev since embox codegen was upstreamed, it is conflicting with this patch otherwise. Differential Revision: https://reviews.llvm.org/D122419
1 parent 7f1adba commit d3bc3a0

File tree

3 files changed

+50
-14
lines changed

3 files changed

+50
-14
lines changed

flang/include/flang/Optimizer/Dialect/FIROps.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ static constexpr llvm::StringRef getAdaptToByRefAttrName() {
4040
return "adapt.valuebyref";
4141
}
4242

43+
static constexpr llvm::StringRef getNormalizedLowerBoundAttrName() {
44+
return "normalized.lb";
45+
}
46+
4347
} // namespace fir
4448

4549
#define GET_OP_CLASSES

flang/lib/Optimizer/CodeGen/CodeGen.cpp

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,20 +1529,30 @@ struct XEmboxOpConversion : public EmboxCommonConversion<fir::cg::XEmboxOp> {
15291529
}
15301530
}
15311531
if (!skipNext) {
1532-
// store lower bound (normally 0)
1532+
if (hasSlice)
1533+
extent = computeTripletExtent(rewriter, loc, operands[sliceOffset],
1534+
operands[sliceOffset + 1],
1535+
operands[sliceOffset + 2], zero, i64Ty);
1536+
// store lower bound (normally 0) for BIND(C) interoperability.
15331537
mlir::Value lb = zero;
1534-
if (eleTy.isa<fir::PointerType>() || eleTy.isa<fir::HeapType>()) {
1538+
const bool isaPointerOrAllocatable =
1539+
eleTy.isa<fir::PointerType>() || eleTy.isa<fir::HeapType>();
1540+
// Lower bound is defaults to 1 for POINTER, ALLOCATABLE, and
1541+
// denormalized descriptors.
1542+
if (isaPointerOrAllocatable || !normalizedLowerBound(xbox)) {
15351543
lb = one;
1536-
if (hasShift)
1544+
// If there is a shifted origin and this is not a normalized
1545+
// descriptor then use the value from the shift op as the lower bound.
1546+
if (hasShift) {
15371547
lb = operands[shiftOffset];
1548+
auto extentIsEmpty = rewriter.create<mlir::LLVM::ICmpOp>(
1549+
loc, mlir::LLVM::ICmpPredicate::eq, extent, zero);
1550+
lb = rewriter.create<mlir::LLVM::SelectOp>(loc, extentIsEmpty, one,
1551+
lb);
1552+
}
15381553
}
15391554
dest = insertLowerBound(rewriter, loc, dest, descIdx, lb);
15401555

1541-
// store extent
1542-
if (hasSlice)
1543-
extent = computeTripletExtent(rewriter, loc, operands[sliceOffset],
1544-
operands[sliceOffset + 1],
1545-
operands[sliceOffset + 2], zero, i64Ty);
15461556
dest = insertExtent(rewriter, loc, dest, descIdx, extent);
15471557

15481558
// store step (scaled by shaped extent)
@@ -1597,6 +1607,13 @@ struct XEmboxOpConversion : public EmboxCommonConversion<fir::cg::XEmboxOp> {
15971607
rewriter.replaceOp(xbox, result);
15981608
return success();
15991609
}
1610+
1611+
/// Return true if `xbox` has a normalized lower bounds attribute. A box value
1612+
/// that is neither a POINTER nor an ALLOCATABLE should be normalized to a
1613+
/// zero origin lower bound for interoperability with BIND(C).
1614+
inline static bool normalizedLowerBound(fir::cg::XEmboxOp xbox) {
1615+
return xbox->hasAttr(fir::getNormalizedLowerBoundAttrName());
1616+
}
16001617
};
16011618

16021619
/// Create a new box given a box reference.
@@ -1662,12 +1679,21 @@ struct XReboxOpConversion : public EmboxCommonConversion<fir::cg::XReboxOp> {
16621679
mlir::ValueRange strides,
16631680
mlir::ConversionPatternRewriter &rewriter) const {
16641681
mlir::Location loc = rebox.getLoc();
1682+
mlir::Value zero =
1683+
genConstantIndex(loc, lowerTy().indexType(), rewriter, 0);
16651684
mlir::Value one = genConstantIndex(loc, lowerTy().indexType(), rewriter, 1);
16661685
for (auto iter : llvm::enumerate(llvm::zip(extents, strides))) {
1686+
mlir::Value extent = std::get<0>(iter.value());
16671687
unsigned dim = iter.index();
1668-
mlir::Value lb = lbounds.empty() ? one : lbounds[dim];
1688+
mlir::Value lb = one;
1689+
if (!lbounds.empty()) {
1690+
lb = lbounds[dim];
1691+
auto extentIsEmpty = rewriter.create<mlir::LLVM::ICmpOp>(
1692+
loc, mlir::LLVM::ICmpPredicate::eq, extent, zero);
1693+
lb = rewriter.create<mlir::LLVM::SelectOp>(loc, extentIsEmpty, one, lb);
1694+
};
16691695
dest = insertLowerBound(rewriter, loc, dest, dim, lb);
1670-
dest = insertExtent(rewriter, loc, dest, dim, std::get<0>(iter.value()));
1696+
dest = insertExtent(rewriter, loc, dest, dim, extent);
16711697
dest = insertStride(rewriter, loc, dest, dim, std::get<1>(iter.value()));
16721698
}
16731699
dest = insertBaseAddress(rewriter, loc, dest, base);

flang/test/Fir/convert-to-llvm.fir

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1738,12 +1738,14 @@ func @xembox0(%arg0: !fir.ref<!fir.array<?xi32>>) {
17381738
// CHECK: %[[ADJUSTED_OFFSET:.*]] = llvm.sub %[[C0]], %[[C0]] : i64
17391739
// CHECK: %[[DIM_OFFSET:.*]] = llvm.mul %[[ADJUSTED_OFFSET]], %[[ONE]] : i64
17401740
// CHECK: %[[PTR_OFFSET:.*]] = llvm.add %[[DIM_OFFSET]], %[[ZERO]] : i64
1741-
// CHECK: %[[BOX7:.*]] = llvm.insertvalue %[[ZERO]], %[[BOX6]][7 : i32, 0 : i32, 0 : i32] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
17421741
// CHECK: %[[EXTENT0:.*]] = llvm.sub %[[C0]], %[[C0]] : i64
17431742
// CHECK: %[[EXTENT1:.*]] = llvm.add %[[EXTENT0]], %[[C0]] : i64
17441743
// CHECK: %[[EXTENT2:.*]] = llvm.sdiv %[[EXTENT1]], %[[C0]] : i64
17451744
// CHECK: %[[EXTENT_CMP:.*]] = llvm.icmp "sgt" %[[EXTENT2]], %[[ZERO]] : i64
17461745
// CHECK: %[[EXTENT:.*]] = llvm.select %[[EXTENT_CMP]], %[[EXTENT2]], %[[ZERO]] : i1, i64
1746+
// CHECK: %[[EXTENT_CMP_2:.*]] = llvm.icmp "eq" %[[EXTENT]], %[[ZERO]] : i64
1747+
// CHECK: %[[LOWER:.*]] = llvm.select %[[EXTENT_CMP_2]], %[[ONE]], %[[C0]] : i1, i64
1748+
// CHECK: %[[BOX7:.*]] = llvm.insertvalue %[[LOWER]], %[[BOX6]][7 : i32, 0 : i32, 0 : i32] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
17471749
// CHECK: %[[BOX8:.*]] = llvm.insertvalue %[[EXTENT]], %[[BOX7]][7 : i32, 0 : i32, 1 : i32] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
17481750
// CHECK: %[[STRIDE:.*]] = llvm.mul %[[ELEM_LEN_I64]], %[[C0]] : i64
17491751
// CHECK: %[[BOX9:.*]] = llvm.insertvalue %[[STRIDE]], %[[BOX8]][7 : i32, 0 : i32, 2 : i32] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
@@ -1837,12 +1839,14 @@ func private @_QPxb(!fir.box<!fir.array<?x?xf64>>)
18371839
// CHECK: %[[ADJUSTED_OFFSET:.*]] = llvm.sub %[[C2]], %[[SH1]] : i64
18381840
// CHECK: %[[DIM_OFFSET:.*]] = llvm.mul %[[ADJUSTED_OFFSET]], %[[ONE]] : i64
18391841
// CHECK: %[[PTR_OFFSET:.*]] = llvm.add %[[DIM_OFFSET]], %[[ZERO]] : i64
1840-
// CHECK: %[[BOX7:.*]] = llvm.insertvalue %[[ZERO]], %[[BOX6]][7 : i32, 0 : i32, 0 : i32] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
18411842
// CHECK: %[[EXTENT0:.*]] = llvm.sub %[[ARG0]], %[[C2]] : i64
18421843
// CHECK: %[[EXTENT1:.*]] = llvm.add %[[EXTENT0]], %[[C1]] : i64
18431844
// CHECK: %[[EXTENT2:.*]] = llvm.sdiv %[[EXTENT1]], %[[C1]] : i64
18441845
// CHECK: %[[EXTENT_CMP:.*]] = llvm.icmp "sgt" %[[EXTENT2]], %[[ZERO]] : i64
18451846
// CHECK: %[[EXTENT:.*]] = llvm.select %[[EXTENT_CMP]], %[[EXTENT2]], %[[ZERO]] : i1, i64
1847+
// CHECK: %[[EXTENT_CMP_2:.*]] = llvm.icmp "eq" %[[EXTENT]], %[[ZERO]] : i64
1848+
// CHECK: %[[SH1B:.*]] = llvm.select %[[EXTENT_CMP_2]], %[[ONE]], %[[SH1]] : i1, i64
1849+
// CHECK: %[[BOX7:.*]] = llvm.insertvalue %[[SH1B]], %[[BOX6]][7 : i32, 0 : i32, 0 : i32] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
18461850
// CHECK: %[[BOX8:.*]] = llvm.insertvalue %[[EXTENT]], %[[BOX7]][7 : i32, 0 : i32, 1 : i32] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
18471851
// CHECK: %[[STRIDE:.*]] = llvm.mul %[[ELEM_LEN_I64]], %[[C1]] : i64
18481852
// CHECK: %[[BOX9:.*]] = llvm.insertvalue %[[STRIDE]], %[[BOX8]][7 : i32, 0 : i32, 2 : i32] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
@@ -1851,12 +1855,14 @@ func private @_QPxb(!fir.box<!fir.array<?x?xf64>>)
18511855
// CHECK: %[[ADJUSTED_OFFSET:.*]] = llvm.sub %[[C4]], %[[SH2]] : i64
18521856
// CHECK: %[[DIM_OFFSET:.*]] = llvm.mul %[[ADJUSTED_OFFSET]], %[[PREV_PTROFF]] : i64
18531857
// CHECK: %[[PTR_OFFSET0:.*]] = llvm.add %[[DIM_OFFSET]], %[[PTR_OFFSET]] : i64
1854-
// CHECK: %[[BOX10:.*]] = llvm.insertvalue %[[ZERO]], %[[BOX9]][7 : i32, 1 : i32, 0 : i32] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
18551858
// CHECK: %[[EXT_SUB:.*]] = llvm.sub %[[N]], %[[C4]] : i64
18561859
// CHECK: %[[EXT_ADD:.*]] = llvm.add %[[EXT_SUB]], %[[C1]] : i64
18571860
// CHECK: %[[EXT_SDIV:.*]] = llvm.sdiv %[[EXT_ADD]], %[[C1]] : i64
18581861
// CHECK: %[[EXT_ICMP:.*]] = llvm.icmp "sgt" %[[EXT_SDIV]], %[[ZERO]] : i64
18591862
// CHECK: %[[EXT_SELECT:.*]] = llvm.select %[[EXT_ICMP]], %[[EXT_SDIV]], %[[ZERO]] : i1, i64
1863+
// CHECK: %[[EXT_ICMP_2:.*]] = llvm.icmp "eq" %[[EXT_SELECT]], %[[ZERO]] : i64
1864+
// CHECK: %[[SH2B:.*]] = llvm.select %[[EXT_ICMP_2]], %[[ONE]], %[[SH2]] : i1, i64
1865+
// CHECK: %[[BOX10:.*]] = llvm.insertvalue %[[SH2B]], %[[BOX9]][7 : i32, 1 : i32, 0 : i32] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
18601866
// CHECK: %[[BOX11:.*]] = llvm.insertvalue %[[EXT_SELECT]], %[[BOX10]][7 : i32, 1 : i32, 1 : i32] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
18611867
// CHECK: %[[STRIDE_MUL:.*]] = llvm.mul %[[PREV_DIM]], %[[C1]] : i64
18621868
// CHECK: %[[BOX12:.*]] = llvm.insertvalue %[[STRIDE_MUL]], %[[BOX11]][7 : i32, 1 : i32, 2 : i32] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
@@ -1918,12 +1924,12 @@ func private @_QPtest_dt_callee(%arg0: !fir.box<!fir.array<?xi32>>)
19181924
// CHECK: %[[GEP_DTYPE_SIZE:.*]] = llvm.getelementptr %[[ELE_TYPE]][%[[C1_0]]] : (!llvm.ptr<struct<"_QFtest_dt_sliceTt", (i32, i32)>>, i64) -> !llvm.ptr<struct<"_QFtest_dt_sliceTt", (i32, i32)>>
19191925
// CHECK: %[[PTRTOINT_DTYPE_SIZE:.*]] = llvm.ptrtoint %[[GEP_DTYPE_SIZE]] : !llvm.ptr<struct<"_QFtest_dt_sliceTt", (i32, i32)>> to i64
19201926
// CHECK: %[[ADJUSTED_OFFSET:.*]] = llvm.sub %3, %30 : i64
1921-
// CHECK: %[[BOX7:.*]] = llvm.insertvalue %[[ZERO]], %[[BOX6]][7 : i32, 0 : i32, 0 : i32] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
19221927
// CHECK: %[[EXT_SUB:.*]] = llvm.sub %[[C10]], %[[C1]] : i64
19231928
// CHECK: %[[EXT_ADD:.*]] = llvm.add %[[EXT_SUB]], %[[C2]] : i64
19241929
// CHECK: %[[EXT_SDIV:.*]] = llvm.sdiv %[[EXT_ADD]], %[[C2]] : i64
19251930
// CHECK: %[[EXT_ICMP:.*]] = llvm.icmp "sgt" %[[EXT_SDIV]], %[[ZERO]] : i64
19261931
// CHECK: %[[EXT_SELECT:.*]] = llvm.select %[[EXT_ICMP]], %[[EXT_SDIV]], %[[ZERO]] : i1, i64
1932+
// CHECK: %[[BOX7:.*]] = llvm.insertvalue %[[ONE]], %[[BOX6]][7 : i32, 0 : i32, 0 : i32] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
19271933
// CHECK: %[[BOX8:.*]] = llvm.insertvalue %[[EXT_SELECT]], %[[BOX7]][7 : i32, 0 : i32, 1 : i32] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
19281934
// CHECK: %[[STRIDE_MUL:.*]] = llvm.mul %[[PTRTOINT_DTYPE_SIZE]], %[[C2]] : i64
19291935
// CHECK: %[[BOX9:.*]] = llvm.insertvalue %[[STRIDE_MUL]], %[[BOX8]][7 : i32, 0 : i32, 2 : i32] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>

0 commit comments

Comments
 (0)