Skip to content

Commit 61d8751

Browse files
authored
[Flang][OpenMP] Fix for SWDEV-540203 and other character array issues (llvm#3574)
2 parents e94a8ae + 706ef7f commit 61d8751

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

flang/lib/Optimizer/CodeGen/CodeGenOpenMP.cpp

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,21 @@ struct MapInfoOpConversion
5959
: public OpenMPFIROpConversion<mlir::omp::MapInfoOp> {
6060
using OpenMPFIROpConversion::OpenMPFIROpConversion;
6161

62+
mlir::omp::MapBoundsOp
63+
createBoundsForCharString(mlir::ConversionPatternRewriter &rewriter,
64+
unsigned int len, mlir::Location loc) const {
65+
mlir::Type i64Ty = rewriter.getIntegerType(64);
66+
auto lBound = mlir::LLVM::ConstantOp::create(rewriter, loc, i64Ty, 0);
67+
auto uBoundAndExt =
68+
mlir::LLVM::ConstantOp::create(rewriter, loc, i64Ty, len - 1);
69+
auto stride = mlir::LLVM::ConstantOp::create(rewriter, loc, i64Ty, 1);
70+
auto baseLb = mlir::LLVM::ConstantOp::create(rewriter, loc, i64Ty, 1);
71+
auto mapBoundType = rewriter.getType<mlir::omp::MapBoundsType>();
72+
return mlir::omp::MapBoundsOp::create(rewriter, loc, mapBoundType, lBound,
73+
uBoundAndExt, uBoundAndExt, stride,
74+
/*strideInBytes*/ false, baseLb);
75+
}
76+
6277
llvm::LogicalResult
6378
matchAndRewrite(mlir::omp::MapInfoOp curOp, OpAdaptor adaptor,
6479
mlir::ConversionPatternRewriter &rewriter) const override {
@@ -68,13 +83,58 @@ struct MapInfoOpConversion
6883
return mlir::failure();
6984

7085
llvm::SmallVector<mlir::NamedAttribute> newAttrs;
71-
mlir::omp::MapInfoOp newOp;
86+
mlir::omp::MapBoundsOp mapBoundsOp;
7287
for (mlir::NamedAttribute attr : curOp->getAttrs()) {
7388
if (auto typeAttr = mlir::dyn_cast<mlir::TypeAttr>(attr.getValue())) {
7489
mlir::Type newAttr;
7590
if (fir::isTypeWithDescriptor(typeAttr.getValue())) {
7691
newAttr = lowerTy().convertBoxTypeAsStruct(
7792
mlir::cast<fir::BaseBoxType>(typeAttr.getValue()));
93+
} else if (fir::isa_char_string(fir::unwrapSequenceType(
94+
fir::unwrapPassByRefType(typeAttr.getValue()))) &&
95+
!characterWithDynamicLen(
96+
fir::unwrapPassByRefType(typeAttr.getValue()))) {
97+
// Characters with a LEN param are represented as char
98+
// arrays/strings, the initial lowering doesn't generate
99+
// bounds for these, however, we require them to map the
100+
// data appropriately in the later lowering stages. This
101+
// is to prevent the need for unecessary caveats
102+
// specific to Flang. We also strip the array from the
103+
// type so that all variations of strings are treated
104+
// identically and there's no caveats or specialisations
105+
// required in the later stages. As an example, Boxed
106+
// char strings will emit a single char array no matter
107+
// the number of dimensions caused by additional array
108+
// dimensions which needs specialised for, as it differs
109+
// from the non-box variation which will emit each array
110+
// wrapping the character array, e.g. given a type of
111+
// the same dimensions, if one is boxed, the types would
112+
// end up:
113+
//
114+
// array<i8 x 16>
115+
// vs
116+
// array<10 x array< 10 x array<i8 x 16>>>
117+
//
118+
// This means we have to treat one specially in the
119+
// lowering. So we try to "canonicalize" it here.
120+
// TODO: Handle dynamic LEN characters.
121+
if (auto ct = mlir::dyn_cast_or_null<fir::CharacterType>(
122+
fir::unwrapSequenceType(typeAttr.getValue()))) {
123+
newAttr = converter->convertType(
124+
fir::unwrapSequenceType(typeAttr.getValue()));
125+
if (auto type = mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(newAttr))
126+
newAttr = type.getElementType();
127+
// We do not generate for device, as MapBoundsOps are
128+
// unsupported, as they're currently unused.
129+
auto offloadMod =
130+
llvm::dyn_cast_or_null<mlir::omp::OffloadModuleInterface>(
131+
*curOp->getParentOfType<mlir::ModuleOp>());
132+
if (!offloadMod.getIsTargetDevice())
133+
mapBoundsOp = createBoundsForCharString(rewriter, ct.getLen(),
134+
curOp.getLoc());
135+
} else {
136+
newAttr = converter->convertType(typeAttr.getValue());
137+
}
78138
} else {
79139
newAttr = converter->convertType(typeAttr.getValue());
80140
}
@@ -84,8 +144,13 @@ struct MapInfoOpConversion
84144
}
85145
}
86146

87-
rewriter.replaceOpWithNewOp<mlir::omp::MapInfoOp>(
147+
auto newOp = rewriter.replaceOpWithNewOp<mlir::omp::MapInfoOp>(
88148
curOp, resTypes, adaptor.getOperands(), newAttrs);
149+
if (mapBoundsOp) {
150+
rewriter.startOpModification(newOp);
151+
newOp.getBoundsMutable().append(mlir::ValueRange{mapBoundsOp});
152+
rewriter.finalizeOpModification(newOp);
153+
}
89154

90155
return mlir::success();
91156
}

mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3553,6 +3553,8 @@ llvm::Value *getSizeInBytes(DataLayout &dl, const mlir::Type &type,
35533553
Operation *clauseOp, llvm::Value *basePointer,
35543554
llvm::Type *baseType, llvm::IRBuilderBase &builder,
35553555
LLVM::ModuleTranslation &moduleTranslation) {
3556+
// TODO: If the array is provably constant sized (e.g. from the type), work
3557+
// out constant size from the type and skip the calculation from the bounds.
35563558
if (auto memberClause =
35573559
mlir::dyn_cast_if_present<mlir::omp::MapInfoOp>(clauseOp)) {
35583560
// This calculates the size to transfer based on bounds and the underlying

0 commit comments

Comments
 (0)