Skip to content

Commit 6c89c53

Browse files
schweitzpgijeanPerier
authored andcommitted
[flang] Fix bug in character casting. Add missing sext/trunc in code gen.
This patch is part of the upstreaming effort from fir-dev branch. It also ensures all descriptors created inline complies with LBOUND requirement that the lower bound is `1` when the related dimension extent is zero. This patch is part of the upstreaming effort from fir-dev branch. Reviewed By: jeanPerier, PeteSteinfeld Differential Revision: https://reviews.llvm.org/D128047 Co-authored-by: Eric Schweitz <[email protected]> Co-authored-by: Jean Perier <[email protected]>
1 parent 2a68364 commit 6c89c53

File tree

2 files changed

+84
-55
lines changed

2 files changed

+84
-55
lines changed

flang/lib/Optimizer/CodeGen/CodeGen.cpp

Lines changed: 65 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,10 +1168,11 @@ struct EmboxCommonConversion : public FIROpConversion<OP> {
11681168
auto typeCodeVal = this->genConstantOffset(loc, rewriter, typeCode);
11691169
if (width == 8)
11701170
return {len, typeCodeVal};
1171-
auto byteWidth = this->genConstantOffset(loc, rewriter, width / 8);
11721171
auto i64Ty = mlir::IntegerType::get(&this->lowerTy().getContext(), 64);
1172+
auto byteWidth = genConstantIndex(loc, i64Ty, rewriter, width / 8);
1173+
auto len64 = FIROpConversion<OP>::integerCast(loc, rewriter, i64Ty, len);
11731174
auto size =
1174-
rewriter.create<mlir::LLVM::MulOp>(loc, i64Ty, byteWidth, len);
1175+
rewriter.create<mlir::LLVM::MulOp>(loc, i64Ty, byteWidth, len64);
11751176
return {size, typeCodeVal};
11761177
};
11771178
auto getKindMap = [&]() -> fir::KindMapping & {
@@ -1382,10 +1383,11 @@ struct EmboxCommonConversion : public FIROpConversion<OP> {
13821383
base.getType().cast<mlir::LLVM::LLVMPointerType>().getElementType();
13831384
if (baseType.isa<mlir::LLVM::LLVMArrayType>()) {
13841385
auto idxTy = this->lowerTy().indexType();
1385-
mlir::Value zero = genConstantIndex(loc, idxTy, rewriter, 0);
1386-
gepOperands.push_back(zero);
1386+
gepOperands.push_back(genConstantIndex(loc, idxTy, rewriter, 0));
1387+
gepOperands.push_back(lowerBound);
1388+
} else {
1389+
gepOperands.push_back(lowerBound);
13871390
}
1388-
gepOperands.push_back(lowerBound);
13891391
return this->genGEP(loc, base.getType(), rewriter, base, gepOperands);
13901392
}
13911393

@@ -1468,50 +1470,58 @@ struct XEmboxOpConversion : public EmboxCommonConversion<fir::cg::XEmboxOp> {
14681470
mlir::Location loc = xbox.getLoc();
14691471
mlir::Value zero = genConstantIndex(loc, i64Ty, rewriter, 0);
14701472
mlir::Value one = genConstantIndex(loc, i64Ty, rewriter, 1);
1471-
mlir::Value prevDim = integerCast(loc, rewriter, i64Ty, eleSize);
14721473
mlir::Value prevPtrOff = one;
14731474
mlir::Type eleTy = boxTy.getEleTy();
14741475
const unsigned rank = xbox.getRank();
14751476
llvm::SmallVector<mlir::Value> gepArgs;
14761477
unsigned constRows = 0;
14771478
mlir::Value ptrOffset = zero;
1478-
if (auto memEleTy = fir::dyn_cast_ptrEleTy(xbox.memref().getType()))
1479-
if (auto seqTy = memEleTy.dyn_cast<fir::SequenceType>()) {
1480-
mlir::Type seqEleTy = seqTy.getEleTy();
1481-
// Adjust the element scaling factor if the element is a dependent type.
1482-
if (fir::hasDynamicSize(seqEleTy)) {
1483-
if (fir::isa_char(seqEleTy)) {
1484-
assert(xbox.lenParams().size() == 1);
1485-
prevPtrOff = integerCast(loc, rewriter, i64Ty,
1486-
operands[xbox.lenParamOffset()]);
1487-
} else if (seqEleTy.isa<fir::RecordType>()) {
1488-
TODO(loc, "generate call to calculate size of PDT");
1489-
} else {
1490-
return rewriter.notifyMatchFailure(xbox, "unexpected dynamic type");
1491-
}
1492-
} else {
1493-
constRows = seqTy.getConstantRows();
1494-
}
1479+
mlir::Type memEleTy = fir::dyn_cast_ptrEleTy(xbox.memref().getType());
1480+
assert(memEleTy.isa<fir::SequenceType>());
1481+
auto seqTy = memEleTy.cast<fir::SequenceType>();
1482+
mlir::Type seqEleTy = seqTy.getEleTy();
1483+
// Adjust the element scaling factor if the element is a dependent type.
1484+
if (fir::hasDynamicSize(seqEleTy)) {
1485+
if (auto charTy = seqEleTy.dyn_cast<fir::CharacterType>()) {
1486+
assert(xbox.lenParams().size() == 1);
1487+
mlir::LLVM::ConstantOp charSize = genConstantIndex(
1488+
loc, i64Ty, rewriter, lowerTy().characterBitsize(charTy) / 8);
1489+
mlir::Value castedLen =
1490+
integerCast(loc, rewriter, i64Ty, operands[xbox.lenParamOffset()]);
1491+
auto byteOffset =
1492+
rewriter.create<mlir::LLVM::MulOp>(loc, i64Ty, charSize, castedLen);
1493+
prevPtrOff = integerCast(loc, rewriter, i64Ty, byteOffset);
1494+
} else if (seqEleTy.isa<fir::RecordType>()) {
1495+
// prevPtrOff = ;
1496+
TODO(loc, "generate call to calculate size of PDT");
1497+
} else {
1498+
fir::emitFatalError(loc, "unexpected dynamic type");
14951499
}
1500+
} else {
1501+
constRows = seqTy.getConstantRows();
1502+
}
14961503

1497-
bool hasSubcomp = !xbox.subcomponent().empty();
1498-
if (!xbox.substr().empty())
1499-
TODO(loc, "codegen of fir.embox with substring");
1500-
1501-
mlir::Value stepExpr;
1504+
const auto hasSubcomp = !xbox.subcomponent().empty();
1505+
const bool hasSubstr = !xbox.substr().empty();
1506+
/// Compute initial element stride that will be use to compute the step in
1507+
/// each dimension.
1508+
mlir::Value prevDimByteStride = integerCast(loc, rewriter, i64Ty, eleSize);
15021509
if (hasSubcomp) {
15031510
// We have a subcomponent. The step value needs to be the number of
15041511
// bytes per element (which is a derived type).
1505-
mlir::Type ty0 = base.getType();
1506-
[[maybe_unused]] auto ptrTy = ty0.dyn_cast<mlir::LLVM::LLVMPointerType>();
1507-
assert(ptrTy && "expected pointer type");
1508-
mlir::Type memEleTy = fir::dyn_cast_ptrEleTy(xbox.memref().getType());
1509-
assert(memEleTy && "expected fir pointer type");
1510-
auto seqTy = memEleTy.dyn_cast<fir::SequenceType>();
1511-
assert(seqTy && "expected sequence type");
1512-
mlir::Type seqEleTy = seqTy.getEleTy();
15131512
auto eleTy = mlir::LLVM::LLVMPointerType::get(convertType(seqEleTy));
1514-
stepExpr = computeDerivedTypeSize(loc, eleTy, i64Ty, rewriter);
1513+
prevDimByteStride = computeDerivedTypeSize(loc, eleTy, i64Ty, rewriter);
1514+
} else if (hasSubstr) {
1515+
// We have a substring. The step value needs to be the number of bytes
1516+
// per CHARACTER element.
1517+
auto charTy = seqEleTy.cast<fir::CharacterType>();
1518+
if (fir::hasDynamicSize(charTy)) {
1519+
prevDimByteStride = prevPtrOff;
1520+
} else {
1521+
prevDimByteStride = genConstantIndex(
1522+
loc, i64Ty, rewriter,
1523+
charTy.getLen() * lowerTy().characterBitsize(charTy) / 8);
1524+
}
15151525
}
15161526

15171527
// Process the array subspace arguments (shape, shift, etc.), if any,
@@ -1544,36 +1554,36 @@ struct XEmboxOpConversion : public EmboxCommonConversion<fir::cg::XEmboxOp> {
15441554
}
15451555
}
15461556
if (!skipNext) {
1557+
// store extent
15471558
if (hasSlice)
15481559
extent = computeTripletExtent(rewriter, loc, operands[sliceOffset],
15491560
operands[sliceOffset + 1],
15501561
operands[sliceOffset + 2], zero, i64Ty);
1551-
// store lower bound (normally 0) for BIND(C) interoperability.
1562+
// Lower bound is normalized to 0 for BIND(C) interoperability.
15521563
mlir::Value lb = zero;
15531564
const bool isaPointerOrAllocatable =
15541565
eleTy.isa<fir::PointerType>() || eleTy.isa<fir::HeapType>();
15551566
// Lower bound is defaults to 1 for POINTER, ALLOCATABLE, and
15561567
// denormalized descriptors.
1557-
if (isaPointerOrAllocatable || !normalizedLowerBound(xbox)) {
1568+
if (isaPointerOrAllocatable || !normalizedLowerBound(xbox))
15581569
lb = one;
1559-
// If there is a shifted origin, and no fir.slice, and this is not
1560-
// a normalized descriptor then use the value from the shift op as
1561-
// the lower bound.
1562-
if (hasShift && !(hasSlice || hasSubcomp)) {
1563-
lb = operands[shiftOffset];
1564-
auto extentIsEmpty = rewriter.create<mlir::LLVM::ICmpOp>(
1565-
loc, mlir::LLVM::ICmpPredicate::eq, extent, zero);
1566-
lb = rewriter.create<mlir::LLVM::SelectOp>(loc, extentIsEmpty, one,
1567-
lb);
1568-
}
1570+
// If there is a shifted origin, and no fir.slice, and this is not
1571+
// a normalized descriptor then use the value from the shift op as
1572+
// the lower bound.
1573+
if (hasShift && !(hasSlice || hasSubcomp || hasSubstr) &&
1574+
(isaPointerOrAllocatable || !normalizedLowerBound(xbox))) {
1575+
lb = operands[shiftOffset];
1576+
auto extentIsEmpty = rewriter.create<mlir::LLVM::ICmpOp>(
1577+
loc, mlir::LLVM::ICmpPredicate::eq, extent, zero);
1578+
lb = rewriter.create<mlir::LLVM::SelectOp>(loc, extentIsEmpty, one,
1579+
lb);
15691580
}
15701581
dest = insertLowerBound(rewriter, loc, dest, descIdx, lb);
15711582

15721583
dest = insertExtent(rewriter, loc, dest, descIdx, extent);
15731584

15741585
// store step (scaled by shaped extent)
1575-
1576-
mlir::Value step = hasSubcomp ? stepExpr : prevDim;
1586+
mlir::Value step = prevDimByteStride;
15771587
if (hasSlice)
15781588
step = rewriter.create<mlir::LLVM::MulOp>(loc, i64Ty, step,
15791589
operands[sliceOffset + 2]);
@@ -1582,8 +1592,8 @@ struct XEmboxOpConversion : public EmboxCommonConversion<fir::cg::XEmboxOp> {
15821592
}
15831593

15841594
// compute the stride and offset for the next natural dimension
1585-
prevDim =
1586-
rewriter.create<mlir::LLVM::MulOp>(loc, i64Ty, prevDim, outerExtent);
1595+
prevDimByteStride = rewriter.create<mlir::LLVM::MulOp>(
1596+
loc, i64Ty, prevDimByteStride, outerExtent);
15871597
if (constRows == 0)
15881598
prevPtrOff = rewriter.create<mlir::LLVM::MulOp>(loc, i64Ty, prevPtrOff,
15891599
outerExtent);
@@ -1597,7 +1607,7 @@ struct XEmboxOpConversion : public EmboxCommonConversion<fir::cg::XEmboxOp> {
15971607
if (hasSlice)
15981608
sliceOffset += 3;
15991609
}
1600-
if (hasSlice || hasSubcomp || !xbox.substr().empty()) {
1610+
if (hasSlice || hasSubcomp || hasSubstr) {
16011611
llvm::SmallVector<mlir::Value> args = {ptrOffset};
16021612
args.append(gepArgs.rbegin(), gepArgs.rend());
16031613
if (hasSubcomp) {
@@ -1613,7 +1623,7 @@ struct XEmboxOpConversion : public EmboxCommonConversion<fir::cg::XEmboxOp> {
16131623
}
16141624
base =
16151625
rewriter.create<mlir::LLVM::GEPOp>(loc, base.getType(), base, args);
1616-
if (!xbox.substr().empty())
1626+
if (hasSubstr)
16171627
base = shiftSubstringBase(rewriter, loc, base,
16181628
operands[xbox.substrOffset()]);
16191629
}

flang/test/Fir/embox-write.fir

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: fir-opt %s | tco | FileCheck %s
2+
3+
// CHECK-LABEL: @set_all_n
4+
func.func @set_all_n(%n : index, %x : i32) {
5+
%aTmp = fir.alloca i32, %n
6+
%aMem = fir.convert %aTmp : (!fir.ref<i32>) -> !fir.ref<!fir.array<?xi32>>
7+
%c1 = arith.constant 1 : index
8+
%aDim = fir.shape %n : (index) -> !fir.shape<1>
9+
%a = fir.embox %aMem(%aDim) : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>>
10+
// CHECK-DAG: %[[IV:.*]] = phi i64
11+
// CHECK-DAG: %[[LCV:.*]] = phi i64
12+
// CHECK: icmp sgt i64 %[[LCV]], 0
13+
fir.do_loop %i = %c1 to %n step %c1 unordered {
14+
%1 = fir.coordinate_of %a, %i : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
15+
// CHECK: store i32 %{{.*}}, ptr %{{.*}}
16+
fir.store %x to %1 : !fir.ref<i32>
17+
}
18+
return
19+
}

0 commit comments

Comments
 (0)